@operato/app 10.26.0 → 10.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ### [10.27.1](https://github.com/hatiolab/operato/compare/v10.27.0...v10.27.1) (2026-09-24)
7
+
8
+ **Note:** Version bump only for package @operato/app
9
+
10
+
11
+
12
+
13
+
14
+ ## [10.27.0](https://github.com/hatiolab/operato/compare/v10.26.0...v10.27.0) (2026-09-24)
15
+
16
+
17
+ ### :rocket: New Features
18
+
19
+ * **layout, app:** entity360Name - one markup for a name that opens its 360 ([f18711e](https://github.com/hatiolab/operato/commit/f18711e34d98f3bdc7d847cc39a8df3044888066))
20
+
21
+
22
+
6
23
  ## [10.26.0](https://github.com/hatiolab/operato/compare/v10.25.0...v10.26.0) (2026-09-24)
7
24
 
8
25
  **Note:** Version bump only for package @operato/app
@@ -1,5 +1,5 @@
1
1
  import { html } from 'lit-html';
2
- import { entity360KindOf, openEntity360For } from '@operato/layout';
2
+ import { entity360KindOf, entity360Name } from '@operato/layout';
3
3
  export const OxGristRendererResourceObject = (value, column, record, rowIndex, field) => {
4
4
  if (!value) {
5
5
  return '';
@@ -25,24 +25,12 @@ export const OxGristRendererResourceObject = (value, column, record, rowIndex, f
25
25
  * the cache off - returns exactly what it always did. dssp and fmsim render through here, and the
26
26
  * architect's condition is that their screens do not change by a byte; a test compares both paths.
27
27
  *
28
- * The link is the body colour with an underline (ADR-0071's link rule) and does not let the click
29
- * reach the row, which would start editing or select it.
28
+ * The link is `entity360Name` - the same markup as every other place a name is drawn. It does not
29
+ * let the click reach the row, which would start editing or select it.
30
30
  */
31
31
  if (!entity360KindOf(value)) {
32
32
  return html `<span>${name || ''}${description || ''}</span> `;
33
33
  }
34
- return html `<span
35
- ><a
36
- href="#"
37
- data-entity360
38
- style="color: inherit; text-decoration: underline; cursor: pointer"
39
- @click=${(event) => {
40
- event.preventDefault();
41
- event.stopPropagation();
42
- openEntity360For(value);
43
- }}
44
- >${name || ''}</a
45
- >${description || ''}</span
46
- > `;
34
+ return html `<span>${entity360Name(value, name || '')}${description || ''}</span> `;
47
35
  };
48
36
  //# sourceMappingURL=ox-grist-renderer-resource-object.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ox-grist-renderer-resource-object.js","sourceRoot":"","sources":["../../../src/grist-editor/ox-grist-renderer-resource-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAG/B,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEnE,MAAM,CAAC,MAAM,6BAA6B,GAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IACrG,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,gBAAgB,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;IAC1F,IAAI,IAAI,EAAE,WAAW,CAAA;IAErB,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACpC,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,OAAO,gBAAgB,KAAK,UAAU,EAAE,CAAC;QAC3C,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,IAAI,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAA;IACzE,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAA,SAAS,IAAI,IAAI,EAAE,GAAG,WAAW,IAAI,EAAE,UAAU,CAAA;IAC9D,CAAC;IAED,OAAO,IAAI,CAAA;;;;;iBAKI,CAAC,KAAY,EAAE,EAAE;QACxB,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,KAAK,CAAC,eAAe,EAAE,CAAA;QACvB,gBAAgB,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;WACE,IAAI,IAAI,EAAE;SACZ,WAAW,IAAI,EAAE;OACnB,CAAA;AACP,CAAC,CAAA","sourcesContent":["import { html } from 'lit-html'\n\nimport { FieldRenderer } from '@operato/data-grist'\nimport { entity360KindOf, openEntity360For } from '@operato/layout'\n\nexport const OxGristRendererResourceObject: FieldRenderer = (value, column, record, rowIndex, field) => {\n if (!value) {\n return ''\n }\n\n var { nameField = 'name', descriptionField = 'description' } = column.record.options || {}\n var name, description\n\n if (typeof nameField === 'function') {\n name = nameField(value)\n } else {\n name = value[nameField]\n }\n\n if (typeof descriptionField === 'function') {\n description = descriptionField(value)\n } else {\n description = value[descriptionField] && `(${value[descriptionField]})`\n }\n\n /*\n * A value whose kind opens a 360 is a link to it (ADR-0067 decision 1, the person 360 ruling).\n *\n * Everything else - a type nobody registered, or a value without __typename because its call turned\n * the cache off - returns exactly what it always did. dssp and fmsim render through here, and the\n * architect's condition is that their screens do not change by a byte; a test compares both paths.\n *\n * The link is the body colour with an underline (ADR-0071's link rule) and does not let the click\n * reach the row, which would start editing or select it.\n */\n if (!entity360KindOf(value)) {\n return html`<span>${name || ''}${description || ''}</span> `\n }\n\n return html`<span\n ><a\n href=\"#\"\n data-entity360\n style=\"color: inherit; text-decoration: underline; cursor: pointer\"\n @click=${(event: Event) => {\n event.preventDefault()\n event.stopPropagation()\n openEntity360For(value)\n }}\n >${name || ''}</a\n >${description || ''}</span\n > `\n}\n"]}
1
+ {"version":3,"file":"ox-grist-renderer-resource-object.js","sourceRoot":"","sources":["../../../src/grist-editor/ox-grist-renderer-resource-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAG/B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEhE,MAAM,CAAC,MAAM,6BAA6B,GAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IACrG,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,gBAAgB,GAAG,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;IAC1F,IAAI,IAAI,EAAE,WAAW,CAAA;IAErB,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACpC,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,OAAO,gBAAgB,KAAK,UAAU,EAAE,CAAC;QAC3C,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,KAAK,CAAC,gBAAgB,CAAC,IAAI,IAAI,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAA;IACzE,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAA,SAAS,IAAI,IAAI,EAAE,GAAG,WAAW,IAAI,EAAE,UAAU,CAAA;IAC9D,CAAC;IAED,OAAO,IAAI,CAAA,SAAS,aAAa,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,GAAG,WAAW,IAAI,EAAE,UAAU,CAAA;AACpF,CAAC,CAAA","sourcesContent":["import { html } from 'lit-html'\n\nimport { FieldRenderer } from '@operato/data-grist'\nimport { entity360KindOf, entity360Name } from '@operato/layout'\n\nexport const OxGristRendererResourceObject: FieldRenderer = (value, column, record, rowIndex, field) => {\n if (!value) {\n return ''\n }\n\n var { nameField = 'name', descriptionField = 'description' } = column.record.options || {}\n var name, description\n\n if (typeof nameField === 'function') {\n name = nameField(value)\n } else {\n name = value[nameField]\n }\n\n if (typeof descriptionField === 'function') {\n description = descriptionField(value)\n } else {\n description = value[descriptionField] && `(${value[descriptionField]})`\n }\n\n /*\n * A value whose kind opens a 360 is a link to it (ADR-0067 decision 1, the person 360 ruling).\n *\n * Everything else - a type nobody registered, or a value without __typename because its call turned\n * the cache off - returns exactly what it always did. dssp and fmsim render through here, and the\n * architect's condition is that their screens do not change by a byte; a test compares both paths.\n *\n * The link is `entity360Name` - the same markup as every other place a name is drawn. It does not\n * let the click reach the row, which would start editing or select it.\n */\n if (!entity360KindOf(value)) {\n return html`<span>${name || ''}${description || ''}</span> `\n }\n\n return html`<span>${entity360Name(value, name || '')}${description || ''}</span> `\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { expect } from '@open-wc/testing';
2
- import { html } from 'lit-html';
2
+ import { html, render as draw } from 'lit-html';
3
3
  import { registerEntity360Kind } from '@operato/layout';
4
4
  import { OxGristRendererResourceObject } from '../src/grist-editor/ox-grist-renderer-resource-object.js';
5
5
  /**
@@ -58,9 +58,19 @@ describe('resource-object cell and the entity 360', () => {
58
58
  expect(same(render(value, col), original(value, col))).to.equal(true);
59
59
  });
60
60
  it('★ a registered type renders the name as a link to its 360', () => {
61
- const result = render({ __typename: 'CellTestUser', id: '9', name: 'Park' });
62
- expect(result.strings.join('')).to.contain('data-entity360');
63
- expect(result.values).to.include('Park');
61
+ const into = document.createElement('div');
62
+ draw(render({ __typename: 'CellTestUser', id: '9', name: 'Park', description: 'QA' }), into);
63
+ const link = into.querySelector('a[data-entity360]');
64
+ expect(link.textContent).to.equal('Park');
65
+ expect(into.textContent.trim()).to.equal('Park(QA)');
66
+ });
67
+ it('★ a click on the link does not reach the row', () => {
68
+ const into = document.createElement('div');
69
+ let reached = false;
70
+ into.addEventListener('click', () => (reached = true));
71
+ draw(render({ __typename: 'CellTestUser', id: '9', name: 'Park' }), into);
72
+ into.querySelector('a[data-entity360]').click();
73
+ expect(reached).to.equal(false);
64
74
  });
65
75
  });
66
76
  //# sourceMappingURL=resource-object-renderer-360.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-object-renderer-360.test.js","sourceRoot":"","sources":["../../test/resource-object-renderer-360.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing'\nimport { html } from 'lit-html'\n\nimport { registerEntity360Kind } from '@operato/layout'\nimport { OxGristRendererResourceObject } from '../src/grist-editor/ox-grist-renderer-resource-object.js'\n\n/**\n * The resource-object cell links a value to its 360 only when its kind is registered - and otherwise\n * returns exactly what it always did (architect ruling on the person 360: dssp and fmsim render\n * through this cell, and their screens must not change by a byte).\n *\n * `original` is the renderer as it stood before, kept verbatim here as the reference.\n */\nfunction original(value: any, column: any) {\n if (!value) {\n return ''\n }\n\n var { nameField = 'name', descriptionField = 'description' } = column.record.options || {}\n var name, description\n\n if (typeof nameField === 'function') {\n name = nameField(value)\n } else {\n name = value[nameField]\n }\n\n if (typeof descriptionField === 'function') {\n description = descriptionField(value)\n } else {\n description = value[descriptionField] && `(${value[descriptionField]})`\n }\n\n return html`<span>${name || ''}${description || ''}</span> `\n}\n\nconst column = (options?: any) => ({ record: { options } }) as any\nconst render = (value: any, col = column()) => (OxGristRendererResourceObject as any)(value, col, {}, 0, {})\n\n/** A template's identity: the same static strings and the same values. */\nconst same = (a: any, b: any) => {\n if (typeof a === 'string' || typeof b === 'string') return a === b\n return a.strings === b.strings || (a.strings.join('\\u0000') === b.strings.join('\\u0000') && JSON.stringify(a.values) === JSON.stringify(b.values))\n}\n\ndescribe('resource-object cell and the entity 360', () => {\n before(() => {\n registerEntity360Kind({ kind: 'cell-test-person', typenames: ['CellTestUser'], title: s => s.value.name })\n })\n\n const unchanged = [\n ['an unregistered type', { __typename: 'SomethingElse', id: '1', name: 'Kim', description: 'QA' }],\n ['a value without __typename', { id: '1', name: 'Kim', description: 'QA' }],\n ['a value with a name only', { __typename: 'Nobody', id: '2', name: 'Lee' }],\n ['no value at all', null]\n ] as const\n\n for (const [what, value] of unchanged) {\n it(`★ ${what} renders exactly as before`, () => {\n expect(same(render(value), original(value, column()))).to.equal(true)\n })\n }\n\n it('★ and with custom name and description fields, still exactly as before', () => {\n const col = column({ nameField: 'title', descriptionField: (v: any) => `[${v.code}]` })\n const value = { __typename: 'Other', title: 'T', code: 'C' }\n expect(same(render(value, col), original(value, col))).to.equal(true)\n })\n\n it('★ a registered type renders the name as a link to its 360', () => {\n const result = render({ __typename: 'CellTestUser', id: '9', name: 'Park' })\n expect(result.strings.join('')).to.contain('data-entity360')\n expect(result.values).to.include('Park')\n })\n})\n"]}
1
+ {"version":3,"file":"resource-object-renderer-360.test.js","sourceRoot":"","sources":["../../test/resource-object-renderer-360.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing'\nimport { html, render as draw } from 'lit-html'\n\nimport { registerEntity360Kind } from '@operato/layout'\nimport { OxGristRendererResourceObject } from '../src/grist-editor/ox-grist-renderer-resource-object.js'\n\n/**\n * The resource-object cell links a value to its 360 only when its kind is registered - and otherwise\n * returns exactly what it always did (architect ruling on the person 360: dssp and fmsim render\n * through this cell, and their screens must not change by a byte).\n *\n * `original` is the renderer as it stood before, kept verbatim here as the reference.\n */\nfunction original(value: any, column: any) {\n if (!value) {\n return ''\n }\n\n var { nameField = 'name', descriptionField = 'description' } = column.record.options || {}\n var name, description\n\n if (typeof nameField === 'function') {\n name = nameField(value)\n } else {\n name = value[nameField]\n }\n\n if (typeof descriptionField === 'function') {\n description = descriptionField(value)\n } else {\n description = value[descriptionField] && `(${value[descriptionField]})`\n }\n\n return html`<span>${name || ''}${description || ''}</span> `\n}\n\nconst column = (options?: any) => ({ record: { options } }) as any\nconst render = (value: any, col = column()) => (OxGristRendererResourceObject as any)(value, col, {}, 0, {})\n\n/** A template's identity: the same static strings and the same values. */\nconst same = (a: any, b: any) => {\n if (typeof a === 'string' || typeof b === 'string') return a === b\n return a.strings === b.strings || (a.strings.join('\\u0000') === b.strings.join('\\u0000') && JSON.stringify(a.values) === JSON.stringify(b.values))\n}\n\ndescribe('resource-object cell and the entity 360', () => {\n before(() => {\n registerEntity360Kind({ kind: 'cell-test-person', typenames: ['CellTestUser'], title: s => s.value.name })\n })\n\n const unchanged = [\n ['an unregistered type', { __typename: 'SomethingElse', id: '1', name: 'Kim', description: 'QA' }],\n ['a value without __typename', { id: '1', name: 'Kim', description: 'QA' }],\n ['a value with a name only', { __typename: 'Nobody', id: '2', name: 'Lee' }],\n ['no value at all', null]\n ] as const\n\n for (const [what, value] of unchanged) {\n it(`★ ${what} renders exactly as before`, () => {\n expect(same(render(value), original(value, column()))).to.equal(true)\n })\n }\n\n it('★ and with custom name and description fields, still exactly as before', () => {\n const col = column({ nameField: 'title', descriptionField: (v: any) => `[${v.code}]` })\n const value = { __typename: 'Other', title: 'T', code: 'C' }\n expect(same(render(value, col), original(value, col))).to.equal(true)\n })\n\n it('★ a registered type renders the name as a link to its 360', () => {\n const into = document.createElement('div')\n draw(render({ __typename: 'CellTestUser', id: '9', name: 'Park', description: 'QA' }), into)\n const link = into.querySelector('a[data-entity360]')!\n expect(link.textContent).to.equal('Park')\n expect(into.textContent!.trim()).to.equal('Park(QA)')\n })\n\n it('★ a click on the link does not reach the row', () => {\n const into = document.createElement('div')\n let reached = false\n into.addEventListener('click', () => (reached = true))\n draw(render({ __typename: 'CellTestUser', id: '9', name: 'Park' }), into)\n ;(into.querySelector('a[data-entity360]') as HTMLElement).click()\n expect(reached).to.equal(false)\n })\n})\n"]}