Skip to content

Commit

Permalink
Foreign key ux mode annotation support (#986)
Browse files Browse the repository at this point in the history
* functionality for foreign key inputDisplayMode in entry context
* update annotation document
* change options to facet-search-popup and simple-search-dropdown
  • Loading branch information
jrchudy authored Aug 31, 2023
1 parent 4b4a14d commit c658318
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 9 deletions.
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

0 comments on commit c658318

Please sign in to comment.