mesh
mesh copied to clipboard
Reordering of fields on schema is not preserved
Gentics Mesh Version, operating system, or hardware.
- v1.3.2
Operating System
- Linux
JVM
- Oracle JDK 1.8.0_100
Problem
Create an schema add multiple fields to it. (save) Re-edit the schema, reorder the fields using the UI drag bars. (save) Re-enter the schema: the fields are out of order. Try to create a node using the schema: the fields are not in order.
Reproducer
Try reordering the following schema: { "name": "b2g_app_config", "container": true, "autoPurge": false, "description": "Main node configuring a white-label", "displayField": "title", "segmentField": null, "urlFields": [ "id" ], "fields": [ { "name": "home_upcoming", "type": "list", "label": "Home Upcoming", "required": true, "listType": "micronode" }, { "name": "id", "type": "string", "label": "URL Slug", "required": true }, { "name": "league_upcoming", "type": "list", "label": "League Upcoming", "required": true, "listType": "micronode" }, { "name": "menu_pages", "type": "list", "label": "Additional Pages", "required": false, "listType": "micronode" }, { "name": "pages_upcoming", "type": "list", "label": "Pages Upcoming", "required": false, "listType": "micronode" }, { "name": "sport_upcoming", "type": "list", "label": "Sport Upcoming", "required": true, "listType": "micronode" }, { "name": "title", "type": "string", "label": "Title", "required": true }, { "name": "top_sports", "type": "list", "label": "Top Sports", "required": true, "listType": "micronode" } ] }
Expected behaviour and actual behaviour
The reordering is preserved. Actual behaviour: the reordering is not preserved.
I have a similar problem when I add new schemas via the API. The order of fields in the schema is not preserved.
The main problem with this is not how it looks on the JSON but what happens when one tries to use the schema to create a new node instance. The fields appear is some irrational order for the person adding the data that make little or no sense. The field use for display-name in the middle, the field used for the slug in some random location, optional fields at the top, required fields intermingled.
It makes very difficult for people to make sense of what they are editing.
We create schemas and microschemas for different types of learning articles with 5 to 10 schema-fields. So we have different articles with different schemas and the fields of the articles are rendered in the order of the schema, because the schema defines structure of the article. Currently before updating a schema the user has to correct the order as it was before. Therefore we need to document the order of every schema.
It is obvious that the bug is in the HTML-Editor for the schema. After saving the schema and refreshing it the editor sorts the field alphabetical. As seen in the following screenshot.
The issue seems to be related to a sorting function, that is called when opening the schema.
Reproduction steps:
I created a schema with 4 fields
- 1Date
- 2A_Field
- 3Name
- 4Test
After that I opened the schema again and reordered the fields -> 4Test, 3Name, 2A_Field, 1Date
Like this
Then I clicked save and went back to the list and selected my schema and opened it and this is where the fields get sorted by name
schema-detail.component.ts (110)
this.subscription = this.schema$.subscribe(schema => {
this.schemaJson$.next(schema ? JSON.stringify(stripSchemaFields(schema), undefined, 4) : `{}`);
});
this calls the stripSchemaFields method
schema-detail.component.ts (254)
function stripSchemaFields(schema: SchemaResponse): any {
schema.fields.sort((a: any, b: any) => a.name.localeCompare(b.name));
return updateFields.reduce((obj, key) => ({ ...obj, [key]: schema[key] || null }), {});
}
which sorts the fields by field.name -> changing the "saved" field order
Here is a gif stepping through the stack trace highlighting where the field order is modified.
Proposed solution:
removing the line which sorts the schema works for this specific scenario
function stripSchemaFields(schema: SchemaResponse): any {
//schema.fields.sort((a: any, b: any) => a.name.localeCompare(b.name));
return updateFields.reduce((obj, key) => ({ ...obj, [key]: schema[key] || null }), {});
}
but as this is called on multiple occasions it might have side-effects / is needed for other scenarios
Update:
After investigating a bit further, I noticed that this sorting is causing an additional issue with the change detection:
Situation
When rearranging the fields without changing any other content and then leaving the screen, the compare method should detect changes inside the schema and display a popup if the user wants to save / discard the changes
Problem
The comparison logic uses the same method and is therefore sorting the fields in both the original and modified schema
get schemaHasChanged(): boolean {
try {
const a = stripSchemaFields(JSON.parse(this.schemaJsonOriginal)); //original schema gets sorted
const b = stripSchemaFields(JSON.parse(this.schemaJson)); //current schema gets sorted
return !simpleDeepEquals(a, b);
} catch (error) {
return false;
}
}
which results in "no changes" as both schema fields are identically sorted and even though I made changes to the order of fields I dont get a popup when leaving the screen