Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foreign key ux mode annotation support #986

Merged
merged 7 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/user-docs/annotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ Supported display _option_ syntax:
- `"column_order": false`: Sorting by this foreign key psuedo-column should not be offered.
- `"show_foreign_key_link": true`: Override the inherited behavior of foreign key display and add a link to the referred row.
- `"show_foreign_key_link": false`: Override the inherited behavior of foreign key display by not adding any the extra.
- `"selector_ux_mode"`: The display mode for the recordedit input field when this foreign key relationship is part of the visible columns. Supported values are `"facet-search-popup"` and `"simple-search-dropdown"`, with `"facet-search-popup"` being the default. Currently only supported in `entry` contexts.

Supported _columnorder_key_ syntax:

Expand Down Expand Up @@ -587,6 +588,7 @@ Supported JSON _option_ payload patterns:
- The provided _pathsuffix_ MUST provide the appropriate projection-list to form a valid `/attribute/` API URI.
- The _pathsuffix_ MAY join additional tables to the path and MAY project from these tables as well as the table bound to the `S` table alias.
- The _pathsuffix_ SHOULD reset the path context to `$S` if it has joined other tables.
- `"selector_ux_mode"`: The display mode for the recordedit input field when this table is part of a foreignkey relationship as the `outbound` table. Supported values are `"facet-search-popup"` and `"simple-search-dropdown"`, with `"facet-search-popup"` being the default. Currently only supported in `entry` contexts.

It is not meaningful to use `page_markdown_pattern`, `row_markdown_pattern`, and `module` in for the same _context_. If they co-exist, the application will prefer `module` over `page_markdown_pattern` and `page_markdown_pattern` over `row_markdown_pattern`.

Expand Down Expand Up @@ -1290,6 +1292,7 @@ The following attributes can be used to manipulate the presentation settings of
- `ulist` for unordered bullet list.
- `csv` for comma-seperated values.
- `raw` for space-seperated values.
- `"selector_ux_mode"`: The display mode for the recordedit input field when this column directive is a foreign key relationship. Supported values are `"facet-search-popup"` and `"simple-search-dropdown"`, with `"facet-search-popup"` being the default. Currently only supported in `entry` contexts.
- `array_display`: This property is _deprecated_. It is the same as `array_ux_mode` that is defined above under `display` property.
- `array_options`: Applicaple only to read-only non-filter context of `visible-columns` annotation. This property is meant to be an object of properties that control the display of `array` or `array_d` aggregate column. These options will only affect the display (and templating environment) and have no effect on the generated ERMrest query. The available options are:
- `order`: An alternative sort method to apply when a client wants to semantically sort by key values. It follows the same syntax as `column_order`. In scalar array aggregate, you cannot sort based on other columns values, you can only sort based on the scalar value of the column.
Expand Down
13 changes: 10 additions & 3 deletions docs/user-docs/column-directive.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ In this category, you use the [`source`](#source) property to define the data so
"wait_for": <wait_for list>,
"show_foreign_key_link": <boolean>,
"show_key_link": <boolean>,
"array_ux_mode": <csv|ulist|olist|raw>
"array_ux_mode": <csv|ulist|olist|raw>,
"selector_ux_mode": <facet-search-popup|simple-search-dropdown>
},
"array_options": {
"order": <change the default order>,
Expand Down Expand Up @@ -95,7 +96,8 @@ In this category, the [`sourcekey`](#sourcekey) proprety is used to refer to one
"wait_for": <wait_for list>,
"show_foreign_key_link": <boolean>,
"show_key_link": <boolean>,
"array_ux_mode": <csv|ulist|olist|raw>
"array_ux_mode": <csv|ulist|olist|raw>,
"selector_ux_mode": <facet-search-popup|simple-search-dropdown>
},
"array_options":{
"order": <change the default order>,
Expand Down Expand Up @@ -379,7 +381,8 @@ By using this attribute you can customize the presented value to the users. The
"wait_for": <wait_for list>,
"show_foreign_key_link": <boolean>,
"show_key_link": <boolean>
"array_ux_mode": <csv|ulist|olist|raw>
"array_ux_mode": <csv|ulist|olist|raw>,
"selector_ux_mode": <facet-search-popup|simple-search-dropdown>
}
}
```
Expand All @@ -396,6 +399,10 @@ Used to signal Chaise that this column directive's `markdown_pattern` relies on

While generating a default presentation for all outbound foreign key paths, ERMrestJS will display a link to the referred row. Using this attribute you can modify this behavior. If this attribute is missing, we are going to use the inherited behavior from the [foreign key](annotation.md#tag-2016-foreign-key) annotation defined on the last foreign key in the path. If that one is missing too, [display annotation](annotation.md#tag-2015-display) will be applied.

##### selector_ux_mode

While generating a default presentation in `entry` mode for single outbound foreign key paths, Chaise will show a modal popup dialog for selecting rows. Using this attribute, you can modify this behavior. If this attribute is missing, we are going to use the inherited behavior from the [foreign key](annotation.md#tag-2016-foreign-key) annotation defined on the foreign key relationship. If that one is missing too, [table display](annotation.md#tag-2016-table-display) annotation will be applied. Supported values are `"facet-search-popup"` and `"simple-search-dropdown"`, with `"facet-search-popup"` being the default.

##### show_key_link

While generating a default presentation for key column directives (self link), ERMrestJS will add a link to the referred row. Using this attribute you can modify this behavior. If this attribute is missing, we are going to use the inherited behavior from the [key display](annotation.md#tag-2017-key-display) annotation. If that one is missing too, [display annotation](annotation.md#tag-2015-display) will be applied.
Expand Down
4 changes: 4 additions & 0 deletions js/column.js
Original file line number Diff line number Diff line change
Expand Up @@ -2108,6 +2108,10 @@ Object.defineProperty(ForeignKeyPseudoColumn.prototype, "display", {
sourceDisplay.sourceMarkdownPattern = displ.markdown_pattern;
sourceDisplay.sourceTemplateEngine = displ.template_engine;
}

if (module._foreignKeyInputModes.indexOf(displ.selector_ux_mode) !== -1) {
sourceDisplay.inputDisplayMode = displ.selector_ux_mode;
}
}

if (this.sourceObject && typeof this.sourceObject.hide_column_header === "boolean") {
Expand Down
29 changes: 28 additions & 1 deletion js/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -4332,7 +4332,7 @@

getDisplay: function(context) {
if (!(context in this._display)) {
var self = this, annotation = -1, columnOrder = [], showFKLink = true;
var self = this, annotation = -1, columnOrder = [], showFKLink = true, inputDisplayMode = module._foreignKeyInputModes[0], toTableAnnotation = -1;
// NOTE: commenting out contextualized functionality since it isn't being supported just yet
// var fromComment = null, fromCommentDisplay = "tooltip", toComment = null, toCommentDisplay = "tooltip";
if (this.annotations.contains(module._annotations.FOREIGN_KEY)) {
Expand All @@ -4358,6 +4358,32 @@
}
}

/**
* inputDisplayMode is set based on the following rules:
* 1. defined on display property in visible-columns
* 2. foreign key annotation
* 3. table-display annotation when defined on the leaf table of the fkey relationship
* 4. default value of 'popup'
*
* supported _foreignKeyInputModes are ['facet-search-popup', 'simple-search-dropdown']
*/

// NOTE: this property is only used when the table is used as the leaf for a foreign key
// using index 0 ensures we only support this on single outbound foreign key relationships when table-display is on the leaf table
var fromCol = this.colset.columns[0];
var toCol = this.mapping.get(fromCol);
if (toCol.table.annotations.contains(module._annotations.TABLE_DISPLAY)) {
toTableAnnotation = module._getRecursiveAnnotationValue(context, toCol.table.annotations.get(module._annotations.TABLE_DISPLAY).content);

if (toTableAnnotation.selector_ux_mode && module._foreignKeyInputModes.indexOf(toTableAnnotation.selector_ux_mode) !== -1) {
inputDisplayMode = toTableAnnotation.selector_ux_mode;
}
}

if (annotation.selector_ux_mode && module._foreignKeyInputModes.indexOf(annotation.selector_ux_mode) !== -1) {
inputDisplayMode = annotation.selector_ux_mode;
}

// fromComment = _processModelComment(annotation.from_comment);
// toComment = _processModelComment(annotation.to_comment);
// fromCommentDisplay = (annotation.from_comment && typeof annotation.from_comment_display === "string") ? annotation.from_comment_display : "tooltip";
Expand All @@ -4367,6 +4393,7 @@
"columnOrder": columnOrder,
// "fromComment": fromComment,
// "fromCommentDisplay": fromCommentDisplay,
"inputDisplayMode": inputDisplayMode,
"showForeignKeyLink": showFKLink,
// "toComment": toComment,
// "toCommentDisplay": toCommentDisplay
Expand Down
2 changes: 2 additions & 0 deletions js/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@
"json"
];

module._foreignKeyInputModes = ['facet-search-popup', 'simple-search-dropdown'];

module._facetUXModes = Object.freeze({
CHOICE: "choices",
RANGE: "ranges",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
136 changes: 132 additions & 4 deletions test/specs/column/conf/pseudo_column_schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,16 @@
"schema_name": "pseudo_column_schema",
"table_name": "outbound_1",
"column_name": "id"
}]
}],
"annotations": {
"tag:isrd.isi.edu,2016:foreign-key": {
"display": {
"entry/edit": {
"selector_ux_mode": "facet-search-popup"
}
}
}
}
}, {
"names": [["pseudo_column_schema", "main_fk2"]],
"foreign_key_columns": [{
Expand All @@ -45,6 +54,39 @@
"table_name": "outbound_2",
"column_name": "id"
}]
}, {
"names": [["pseudo_column_schema", "main_fk3"]],
"foreign_key_columns": [{
"schema_name": "pseudo_column_schema",
"table_name": "main",
"column_name": "fk3"
}],
"referenced_columns": [{
"schema_name": "pseudo_column_schema",
"table_name": "outbound_3",
"column_name": "id"
}],
"annotations": {
"tag:isrd.isi.edu,2016:foreign-key": {
"display": {
"entry/edit": {
"selector_ux_mode": "simple-search-dropdown"
}
}
}
}
}, {
"names": [["pseudo_column_schema", "main_fk4"]],
"foreign_key_columns": [{
"schema_name": "pseudo_column_schema",
"table_name": "main",
"column_name": "fk4"
}],
"referenced_columns": [{
"schema_name": "pseudo_column_schema",
"table_name": "outbound_4",
"column_name": "id"
}]
}
],
"column_definitions": [
Expand Down Expand Up @@ -90,6 +132,18 @@
"typename": "text"
}
},
{
"name": "fk3",
"type": {
"typename": "text"
}
},
{
"name": "fk4",
"type": {
"typename": "text"
}
},
{
"name": "asset",
"type": {
Expand Down Expand Up @@ -272,7 +326,33 @@
"aggregate": "array"
}
],
"entry": "detailed",
"entry/create": "detailed",
"entry/edit": [
"main_table_id_col",
{
"source": [{"outbound": ["pseudo_column_schema", "main_fk2"]}, "id"],
"markdown_name": "main fk2 dropdown",
"comment": "main fk2 cm dropdown display"
},
{
"source": [{"outbound": ["pseudo_column_schema", "main_fk1"]}, "id"],
"markdown_name": "main fk dropdown",
"comment": "main fk cm dropdown display"
},
{
"source": [{"outbound": ["pseudo_column_schema", "main_fk3"]}, "id"],
"markdown_name": "main fk3 popup",
"comment": "main fk3 cm override popup display",
"display": {
"selector_ux_mode": "facet-search-popup"
}
},
{
"source": [{"outbound": ["pseudo_column_schema", "main_fk4"]}, "id"],
"markdown_name": "main fk4 popup",
"comment": "main fk4 cm default popup display"
}
],
"compact/select": [
"col",
"main_table_id_col",
Expand Down Expand Up @@ -548,7 +628,10 @@
"tag:isrd.isi.edu,2016:table-display": {
"*" : {
"row_order": [{"column":"col", "descending":false}]
}
},
"entry/edit": {
"selector_ux_mode": "simple-search-dropdown"
}
}
}
},
Expand Down Expand Up @@ -1004,7 +1087,52 @@
"name": "fk",
"type": {"typename": "text"}
}
]
],
"annotations": {
"tag:isrd.isi.edu,2016:table-display": {
"entry/edit": {
"selector_ux_mode": "simple-search-dropdown"
}
}
}
},
"outbound_3": {
"kind": "table",
"table_name": "outbound_3",
"schema_name": "pseudo_column_schema",
"keys": [{"unique_columns": ["id"]}],
"foreign_keys": [],
"column_definitions": [
{
"name": "id",
"nullok": false,
"type": {"typename": "text"}
},
{
"name": "col",
"type": {"typename": "text"}
}
],
"annotations": {}
},
"outbound_4": {
"kind": "table",
"table_name": "outbound_4",
"schema_name": "pseudo_column_schema",
"keys": [{"unique_columns": ["id"]}],
"foreign_keys": [],
"column_definitions": [
{
"name": "id",
"nullok": false,
"type": {"typename": "text"}
},
{
"name": "col",
"type": {"typename": "text"}
}
],
"annotations": {}
},
"outbound_2_outbound_2": {
"comment": "outbound_2_outbound_2 comment",
Expand Down
30 changes: 29 additions & 1 deletion test/specs/column/tests/03.pseudo_column.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ exports.execute = function (options) {
mainRef = response;
mainRefDetailed = response.contextualize.detailed;
detailedCols = mainRefDetailed.columns;
mainRefEntry = response.contextualize.entry;
mainRefEntry = response.contextualize.entryCreate;
mainRefEntryEdit = response.contextualize.entryEdit;
mainRefCompactEntry = response.contextualize.compactEntry;
return options.ermRest.resolve(invalidEntityUri, {cid: "test"});
}).then(function (response) {
Expand Down Expand Up @@ -746,6 +747,33 @@ exports.execute = function (options) {
});

// the rest of tests are in 02.referenced_column.js
});

describe(".inputDisplayMode", function () {
var entryCols;
beforeAll(function () {
entryCols = mainRefEntryEdit.columns;
});

it('should return the `selector_ux_mode` defined on the table-display annotation', function () {
// table-display on outbound_2 says 'simple-search-dropdown' that overrides default ('facet-search-popup')
expect(entryCols[1].display.inputDisplayMode).toBe('simple-search-dropdown', "missmatch for index=2");
});

it('should return the `selector_ux_mode` defined on the foreign-key annotation', function () {
// foreign-key on ["pseudo_column_schema", "main_fk1"] says 'facet-search-popup' that overrides table-display 'simple-search-dropdown'
expect(entryCols[2].display.inputDisplayMode).toBe('facet-search-popup', "missmatch for index=2");
});

it ("should return the `selector_ux_mode` defined on the source and ignore the foreign-key", function () {
// source says 'facet-search-popup'that overrides foreign-key on ["pseudo_column_schema", "main_fk3"] 'simple-search-dropdown'
expect(entryCols[3].display.inputDisplayMode).toBe('facet-search-popup', "missmatch for index=1");
});

it ("should return the default value when no `selector_ux_mode` is defined", function () {
// foreign-key ["pseudo_column_schema", "main_fk4"] uses default value
expect(entryCols[4].display.inputDisplayMode).toBe('facet-search-popup', "missmatch for index=1");
});
})

describe(".table, ", function () {
Expand Down