@things-factory/lite-menu 10.1.5 → 10.1.6

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.
@@ -1,2 +1,3 @@
1
+ export * from './menu-type-registry.js';
1
2
  export * from './actions/lite-menu';
2
3
  export * from './lite-menu-setting-let';
@@ -1,3 +1,5 @@
1
+ /* 메뉴 타입 registry — 보드처럼 자기 타입을 내는 쪽이 등록한다(§menu-type-registry). */
2
+ export * from './menu-type-registry.js';
1
3
  export * from './actions/lite-menu';
2
4
  export * from './lite-menu-setting-let';
3
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA","sourcesContent":["export * from './actions/lite-menu'\nexport * from './lite-menu-setting-let'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA","sourcesContent":["/* 메뉴 타입 registry — 보드처럼 자기 타입을 내는 쪽이 등록한다(§menu-type-registry). */\nexport * from './menu-type-registry.js'\nexport * from './actions/lite-menu'\nexport * from './lite-menu-setting-let'\n"]}
@@ -0,0 +1,22 @@
1
+ export interface MenuTypeSpec {
2
+ /** 저장되는 값. 행에 남으므로 나중에 바꾸면 이미 앉은 메뉴가 타입을 잃는다. */
3
+ name: string;
4
+ /**
5
+ * 값 칸의 grist 타입. 안 주면 값이 그냥 글자다.
6
+ *
7
+ * 이 이름의 renderer 가 등록돼 있지 않으면 이 타입은 **목록에 안 나오고** 값 칸도 글자로 떨어진다.
8
+ */
9
+ requiresRenderer?: string;
10
+ }
11
+ /** 메뉴 타입을 등록한다. 같은 이름을 두 번 주면 뒤엣것이 이긴다(재로드). */
12
+ export declare function registerMenuType(spec: MenuTypeSpec): void;
13
+ /**
14
+ * 고를 수 있는 타입들 — 설정 화면의 `select` 목록.
15
+ *
16
+ * 맨 앞의 빈 값은 「아직 안 고름」이고 타입이 아니므로 여기서 내지 않는다. 화면이 붙인다.
17
+ */
18
+ export declare function menuTypeNames(): string[];
19
+ /** 이 타입의 값 칸은 어떤 grist 타입인가. 등록 안 된 것·모르는 것은 글자다. */
20
+ export declare function gristTypeOf(name: string | undefined | null): string;
21
+ /** 시험용 — 등록을 비운다. 제품 코드에서 부르지 말 것. */
22
+ export declare function clearMenuTypes(): void;
@@ -0,0 +1,93 @@
1
+ /*
2
+ * 메뉴가 가리킬 수 있는 것 — **있는 것만 보여 준다.**
3
+ *
4
+ * ── 왜 만들었나 (2026-09-10) ────────────────────────────────────────────────
5
+ * 이 패키지가 `@things-factory/board-ui` 를 **선언만** 하고 있었다. 소스에서 부르는 자리는 0 건이고,
6
+ * 선언의 이유는 부작용이었다: 메뉴 설정 화면이 grist 컬럼 타입 `'board'` 를 쓰고, 그 renderer·editor
7
+ * 를 `board-ui/client/bootstrap.ts` 가 등록한다.
8
+ *
9
+ * 그래서 **아무도 import 하지 않는 의존**이 됐고, 그것이 사슬을 끌고 왔다 — 보드와 아무 상관 없는
10
+ * 앱에 `board-ui` 와 그 아래(`board-ai`·`barcode-base`·`print-base`)가 실렸고, 번역 키가
11
+ * 부딪혔다(figure 에서 `button.release` 가 「배포」로 떴다).
12
+ *
13
+ * ── 처음 안이 틀렸다: 「보드를 가진 쪽이 등록한다」 ─────────────────────────
14
+ * `board-ui` 의 bootstrap 에서 `registerMenuType('board')` 를 부르게 했다. 그러면 **board-ui 가
15
+ * lite-menu 를 의존해야 하고**, 재 보니 board-ui 는 있고 lite-menu 는 없는 앱이 넷이었다
16
+ * (`operato-board` · `operato-fleet` · `dashboard` · `worklist`). 그 넷에 lite-menu 모듈이 딸려
17
+ * 들어간다 — 서버 엔티티까지. 의존 하나를 없애려다 넷에 모듈을 하나 심는 것이었다.
18
+ *
19
+ * ── 그래서 선언하지 않고 **물어본다** ──────────────────────────────────────
20
+ * 타입 목록은 이 패키지가 갖는다(이미 `reducers/lite-menu.ts` 가 `type === 'board'` 를 알고 있다 —
21
+ * 런타임 메뉴 이동이 그것으로 갈린다). 달라진 것은 **쓸 수 있는지를 실제 상태에서 읽는 것**이다.
22
+ *
23
+ * `requiresRenderer` 가 붙은 타입은 그 renderer 가 grist 에 **등록되어 있을 때만** 보인다.
24
+ *
25
+ * 등록은 `board-ui` 가 자기 bootstrap 에서 이미 한다(`registerRenderer('board', BoardRenderer)`).
26
+ * 그러니 두 곳에서 선언할 것이 없고, 어느 쪽도 상대를 의존하지 않는다.
27
+ *
28
+ * 이 모양이 나은 이유가 하나 더 있다. 「선언했으니 있다」가 아니라 「있으니 보인다」이므로,
29
+ * board-ui 가 실렸는데 registerRenderer 를 빼먹은 날에도 목록이 거짓말하지 않는다.
30
+ *
31
+ * ── ⚠ 두 자리를 함께 먹여야 한다 ──────────────────────────────────────────
32
+ * 처음에 목록만 고치려 했는데, 값 칸 타입도 따로 하드코딩돼 있었다. 한쪽만 고치면 보드 없는 앱에서
33
+ * `board` 를 고를 수는 있고 값 칸은 조용히 글자 편집기가 된다 — 배치만 바뀐 같은 결함이다. 그래서
34
+ * `menuTypeNames()`(목록)와 `gristTypeOf()`(값 칸) 둘 다 여기서 나온다.
35
+ */
36
+ import { getRenderers } from '@operato/data-grist';
37
+ const types = new Map();
38
+ /** 이 renderer 가 grist 에 등록돼 있나. 물어보는 쪽이 판단한다. */
39
+ function rendererAvailable(name) {
40
+ if (!name)
41
+ return true;
42
+ try {
43
+ return !!getRenderers()?.[name];
44
+ }
45
+ catch {
46
+ /*
47
+ * 물을 수 없으면 **없는 것으로 본다.** 반대로 기울면 목록에 뜨고 값 칸이 조용히 망가진다 —
48
+ * 이 파일이 없애려는 바로 그 증상이다.
49
+ */
50
+ return false;
51
+ }
52
+ }
53
+ /** 메뉴 타입을 등록한다. 같은 이름을 두 번 주면 뒤엣것이 이긴다(재로드). */
54
+ export function registerMenuType(spec) {
55
+ if (!spec?.name) {
56
+ throw new Error('[lite-menu] registerMenuType: name is required — it is the value stored on the menu row.');
57
+ }
58
+ types.set(spec.name, spec);
59
+ }
60
+ /**
61
+ * 고를 수 있는 타입들 — 설정 화면의 `select` 목록.
62
+ *
63
+ * 맨 앞의 빈 값은 「아직 안 고름」이고 타입이 아니므로 여기서 내지 않는다. 화면이 붙인다.
64
+ */
65
+ export function menuTypeNames() {
66
+ return [...types.values()].filter(t => rendererAvailable(t.requiresRenderer)).map(t => t.name);
67
+ }
68
+ /** 이 타입의 값 칸은 어떤 grist 타입인가. 등록 안 된 것·모르는 것은 글자다. */
69
+ export function gristTypeOf(name) {
70
+ if (!name)
71
+ return 'string';
72
+ const spec = types.get(name);
73
+ if (!spec?.requiresRenderer)
74
+ return 'string';
75
+ return rendererAvailable(spec.requiresRenderer) ? spec.requiresRenderer : 'string';
76
+ }
77
+ /** 시험용 — 등록을 비운다. 제품 코드에서 부르지 말 것. */
78
+ export function clearMenuTypes() {
79
+ types.clear();
80
+ }
81
+ /*
82
+ * 메뉴가 가리킬 수 있는 것들.
83
+ *
84
+ * group 하위 메뉴를 담는 자리 — 값이 없다
85
+ * page 화면 이름을 가리킨다 — 값은 글자다
86
+ * board 보드를 가리킨다 — 보드 renderer 가 있는 앱에서만 보인다
87
+ * interactive-board 같은 보드를 조작 가능한 모드로
88
+ */
89
+ registerMenuType({ name: 'group' });
90
+ registerMenuType({ name: 'page' });
91
+ registerMenuType({ name: 'board', requiresRenderer: 'board' });
92
+ registerMenuType({ name: 'interactive-board', requiresRenderer: 'board' });
93
+ //# sourceMappingURL=menu-type-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-type-registry.js","sourceRoot":"","sources":["../client/menu-type-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAalD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAA;AAE7C,iDAAiD;AACjD,SAAS,iBAAiB,CAAC,IAAwB;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IACtB,IAAI,CAAC;QACH,OAAO,CAAC,CAAE,YAAY,EAAU,EAAE,CAAC,IAAI,CAAC,CAAA;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP;;;WAGG;QACH,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,gBAAgB,CAAC,IAAkB;IACjD,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,0FAA0F,CAAC,CAAA;IAC7G,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AAChG,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,WAAW,CAAC,IAA+B;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAA;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC5B,IAAI,CAAC,IAAI,EAAE,gBAAgB;QAAE,OAAO,QAAQ,CAAA;IAC5C,OAAO,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAA;AACpF,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,cAAc;IAC5B,KAAK,CAAC,KAAK,EAAE,CAAA;AACf,CAAC;AAED;;;;;;;GAOG;AACH,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;AACnC,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;AAClC,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAA;AAC9D,gBAAgB,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAA","sourcesContent":["/*\n * 메뉴가 가리킬 수 있는 것 — **있는 것만 보여 준다.**\n *\n * ── 왜 만들었나 (2026-09-10) ────────────────────────────────────────────────\n * 이 패키지가 `@things-factory/board-ui` 를 **선언만** 하고 있었다. 소스에서 부르는 자리는 0 건이고,\n * 선언의 이유는 부작용이었다: 메뉴 설정 화면이 grist 컬럼 타입 `'board'` 를 쓰고, 그 renderer·editor\n * 를 `board-ui/client/bootstrap.ts` 가 등록한다.\n *\n * 그래서 **아무도 import 하지 않는 의존**이 됐고, 그것이 사슬을 끌고 왔다 — 보드와 아무 상관 없는\n * 앱에 `board-ui` 와 그 아래(`board-ai`·`barcode-base`·`print-base`)가 실렸고, 번역 키가\n * 부딪혔다(figure 에서 `button.release` 가 「배포」로 떴다).\n *\n * ── 처음 안이 틀렸다: 「보드를 가진 쪽이 등록한다」 ─────────────────────────\n * `board-ui` 의 bootstrap 에서 `registerMenuType('board')` 를 부르게 했다. 그러면 **board-ui 가\n * lite-menu 를 의존해야 하고**, 재 보니 board-ui 는 있고 lite-menu 는 없는 앱이 넷이었다\n * (`operato-board` · `operato-fleet` · `dashboard` · `worklist`). 그 넷에 lite-menu 모듈이 딸려\n * 들어간다 — 서버 엔티티까지. 의존 하나를 없애려다 넷에 모듈을 하나 심는 것이었다.\n *\n * ── 그래서 선언하지 않고 **물어본다** ──────────────────────────────────────\n * 타입 목록은 이 패키지가 갖는다(이미 `reducers/lite-menu.ts` 가 `type === 'board'` 를 알고 있다 —\n * 런타임 메뉴 이동이 그것으로 갈린다). 달라진 것은 **쓸 수 있는지를 실제 상태에서 읽는 것**이다.\n *\n * `requiresRenderer` 가 붙은 타입은 그 renderer 가 grist 에 **등록되어 있을 때만** 보인다.\n *\n * 등록은 `board-ui` 가 자기 bootstrap 에서 이미 한다(`registerRenderer('board', BoardRenderer)`).\n * 그러니 두 곳에서 선언할 것이 없고, 어느 쪽도 상대를 의존하지 않는다.\n *\n * 이 모양이 나은 이유가 하나 더 있다. 「선언했으니 있다」가 아니라 「있으니 보인다」이므로,\n * board-ui 가 실렸는데 registerRenderer 를 빼먹은 날에도 목록이 거짓말하지 않는다.\n *\n * ── ⚠ 두 자리를 함께 먹여야 한다 ──────────────────────────────────────────\n * 처음에 목록만 고치려 했는데, 값 칸 타입도 따로 하드코딩돼 있었다. 한쪽만 고치면 보드 없는 앱에서\n * `board` 를 고를 수는 있고 값 칸은 조용히 글자 편집기가 된다 — 배치만 바뀐 같은 결함이다. 그래서\n * `menuTypeNames()`(목록)와 `gristTypeOf()`(값 칸) 둘 다 여기서 나온다.\n */\nimport { getRenderers } from '@operato/data-grist'\n\nexport interface MenuTypeSpec {\n /** 저장되는 값. 행에 남으므로 나중에 바꾸면 이미 앉은 메뉴가 타입을 잃는다. */\n name: string\n /**\n * 값 칸의 grist 타입. 안 주면 값이 그냥 글자다.\n *\n * 이 이름의 renderer 가 등록돼 있지 않으면 이 타입은 **목록에 안 나오고** 값 칸도 글자로 떨어진다.\n */\n requiresRenderer?: string\n}\n\nconst types = new Map<string, MenuTypeSpec>()\n\n/** 이 renderer 가 grist 에 등록돼 있나. 물어보는 쪽이 판단한다. */\nfunction rendererAvailable(name: string | undefined): boolean {\n if (!name) return true\n try {\n return !!(getRenderers() as any)?.[name]\n } catch {\n /*\n * 물을 수 없으면 **없는 것으로 본다.** 반대로 기울면 목록에 뜨고 값 칸이 조용히 망가진다 —\n * 이 파일이 없애려는 바로 그 증상이다.\n */\n return false\n }\n}\n\n/** 메뉴 타입을 등록한다. 같은 이름을 두 번 주면 뒤엣것이 이긴다(재로드). */\nexport function registerMenuType(spec: MenuTypeSpec): void {\n if (!spec?.name) {\n throw new Error('[lite-menu] registerMenuType: name is required — it is the value stored on the menu row.')\n }\n types.set(spec.name, spec)\n}\n\n/**\n * 고를 수 있는 타입들 — 설정 화면의 `select` 목록.\n *\n * 맨 앞의 빈 값은 「아직 안 고름」이고 타입이 아니므로 여기서 내지 않는다. 화면이 붙인다.\n */\nexport function menuTypeNames(): string[] {\n return [...types.values()].filter(t => rendererAvailable(t.requiresRenderer)).map(t => t.name)\n}\n\n/** 이 타입의 값 칸은 어떤 grist 타입인가. 등록 안 된 것·모르는 것은 글자다. */\nexport function gristTypeOf(name: string | undefined | null): string {\n if (!name) return 'string'\n const spec = types.get(name)\n if (!spec?.requiresRenderer) return 'string'\n return rendererAvailable(spec.requiresRenderer) ? spec.requiresRenderer : 'string'\n}\n\n/** 시험용 — 등록을 비운다. 제품 코드에서 부르지 말 것. */\nexport function clearMenuTypes(): void {\n types.clear()\n}\n\n/*\n * 메뉴가 가리킬 수 있는 것들.\n *\n * group 하위 메뉴를 담는 자리 — 값이 없다\n * page 화면 이름을 가리킨다 — 값은 글자다\n * board 보드를 가리킨다 — 보드 renderer 가 있는 앱에서만 보인다\n * interactive-board 같은 보드를 조작 가능한 모드로\n */\nregisterMenuType({ name: 'group' })\nregisterMenuType({ name: 'page' })\nregisterMenuType({ name: 'board', requiresRenderer: 'board' })\nregisterMenuType({ name: 'interactive-board', requiresRenderer: 'board' })\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ /*
2
+ * 무엇을 지키는가: **쓸 수 없는 메뉴 타입이 목록에 뜨지 않는 것.**
3
+ *
4
+ * 전에는 `lite-menu` 가 `['', 'group', 'page', 'board', 'interactive-board']` 를 하드코딩하고, 그
5
+ * 값 칸의 renderer 를 얻으려고 `board-ui` 를 **선언만** 하고 있었다(소스에서 부르는 자리 0 건).
6
+ *
7
+ * 그 상태의 증상은 「안 된다」가 아니라 **「되는 것처럼 보인다」**였다. 목록에 `board` 가 떠서 고를
8
+ * 수 있고, renderer 가 등록돼 있지 않으면 값 칸이 조용히 글자 편집기가 된다. 오류는 없다.
9
+ *
10
+ * 그래서 판정을 **선언이 아니라 실제 등록 상태**에서 읽는다. 이 시험들이 그것을 고정한다.
11
+ */
12
+ const mockRenderers = {};
13
+ jest.mock('@operato/data-grist', () => ({ getRenderers: () => mockRenderers }));
14
+ import { registerMenuType, menuTypeNames, gristTypeOf, clearMenuTypes } from './menu-type-registry';
15
+ /** 모듈 로드 때 등록되는 네 가지를 되살린다. */
16
+ function withDeclaredTypes() {
17
+ clearMenuTypes();
18
+ registerMenuType({ name: 'group' });
19
+ registerMenuType({ name: 'page' });
20
+ registerMenuType({ name: 'board', requiresRenderer: 'board' });
21
+ registerMenuType({ name: 'interactive-board', requiresRenderer: 'board' });
22
+ }
23
+ beforeEach(() => {
24
+ for (const k of Object.keys(mockRenderers))
25
+ delete mockRenderers[k];
26
+ withDeclaredTypes();
27
+ });
28
+ describe('보드 renderer 가 없는 앱 (board-ui 를 안 싣는 앱)', () => {
29
+ it('★ 보드 타입이 목록에 안 나온다 — 고를 수 없으니 조용히 망가질 자리가 없다', () => {
30
+ expect(menuTypeNames()).toEqual(['group', 'page']);
31
+ });
32
+ it('★ 값 칸도 글자다 — 없는 renderer 를 가리키지 않는다', () => {
33
+ expect(gristTypeOf('board')).toBe('string');
34
+ expect(gristTypeOf('interactive-board')).toBe('string');
35
+ });
36
+ });
37
+ describe('보드 renderer 가 있는 앱', () => {
38
+ beforeEach(() => {
39
+ mockRenderers['board'] = () => { };
40
+ });
41
+ it('보드 타입이 목록에 나온다 — 순서는 등록 순서다', () => {
42
+ expect(menuTypeNames()).toEqual(['group', 'page', 'board', 'interactive-board']);
43
+ });
44
+ it('값 칸이 보드 편집기를 가리킨다', () => {
45
+ expect(gristTypeOf('board')).toBe('board');
46
+ expect(gristTypeOf('interactive-board')).toBe('board');
47
+ });
48
+ });
49
+ describe('renderer 를 요구하지 않는 타입', () => {
50
+ it('group·page 는 renderer 와 무관하게 늘 있고, 값 칸은 글자다', () => {
51
+ expect(menuTypeNames()).toContain('group');
52
+ expect(gristTypeOf('group')).toBe('string');
53
+ expect(gristTypeOf('page')).toBe('string');
54
+ });
55
+ });
56
+ describe('가장자리', () => {
57
+ it('타입을 안 고른 행(빈 값·undefined·null)은 글자다', () => {
58
+ for (const v of ['', undefined, null])
59
+ expect(gristTypeOf(v)).toBe('string');
60
+ });
61
+ it('모르는 타입도 글자다 — 지어내지 않는다', () => {
62
+ expect(gristTypeOf('nonesuch')).toBe('string');
63
+ });
64
+ it('이름 없이 등록하면 던진다 — 그 값이 행에 저장되는 것이다', () => {
65
+ expect(() => registerMenuType({ name: '' })).toThrow(/name is required/);
66
+ expect(() => registerMenuType(undefined)).toThrow(/name is required/);
67
+ });
68
+ it('같은 이름을 두 번 주면 뒤엣것이 이기고 목록은 안 늘어난다 — 재로드가 목록을 부풀리지 않는다', () => {
69
+ mockRenderers['board'] = () => { };
70
+ const before = menuTypeNames().length;
71
+ registerMenuType({ name: 'board', requiresRenderer: 'board' });
72
+ expect(menuTypeNames().length).toBe(before);
73
+ });
74
+ });
75
+ //# sourceMappingURL=menu-type-registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-type-registry.test.js","sourceRoot":"","sources":["../client/menu-type-registry.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 무엇을 지키는가: **쓸 수 없는 메뉴 타입이 목록에 뜨지 않는 것.**\n *\n * 전에는 `lite-menu` 가 `['', 'group', 'page', 'board', 'interactive-board']` 를 하드코딩하고, 그\n * 값 칸의 renderer 를 얻으려고 `board-ui` 를 **선언만** 하고 있었다(소스에서 부르는 자리 0 건).\n *\n * 그 상태의 증상은 「안 된다」가 아니라 **「되는 것처럼 보인다」**였다. 목록에 `board` 가 떠서 고를\n * 수 있고, renderer 가 등록돼 있지 않으면 값 칸이 조용히 글자 편집기가 된다. 오류는 없다.\n *\n * 그래서 판정을 **선언이 아니라 실제 등록 상태**에서 읽는다. 이 시험들이 그것을 고정한다.\n */\nconst mockRenderers: Record<string, any> = {}\njest.mock('@operato/data-grist', () => ({ getRenderers: () => mockRenderers }))\n\nimport { registerMenuType, menuTypeNames, gristTypeOf, clearMenuTypes } from './menu-type-registry'\n\n/** 모듈 로드 때 등록되는 네 가지를 되살린다. */\nfunction withDeclaredTypes() {\n clearMenuTypes()\n registerMenuType({ name: 'group' })\n registerMenuType({ name: 'page' })\n registerMenuType({ name: 'board', requiresRenderer: 'board' })\n registerMenuType({ name: 'interactive-board', requiresRenderer: 'board' })\n}\n\nbeforeEach(() => {\n for (const k of Object.keys(mockRenderers)) delete mockRenderers[k]\n withDeclaredTypes()\n})\n\ndescribe('보드 renderer 가 없는 앱 (board-ui 를 안 싣는 앱)', () => {\n it('★ 보드 타입이 목록에 안 나온다 — 고를 수 없으니 조용히 망가질 자리가 없다', () => {\n expect(menuTypeNames()).toEqual(['group', 'page'])\n })\n\n it('★ 값 칸도 글자다 — 없는 renderer 를 가리키지 않는다', () => {\n expect(gristTypeOf('board')).toBe('string')\n expect(gristTypeOf('interactive-board')).toBe('string')\n })\n})\n\ndescribe('보드 renderer 가 있는 앱', () => {\n beforeEach(() => {\n mockRenderers['board'] = () => {}\n })\n\n it('보드 타입이 목록에 나온다 — 순서는 등록 순서다', () => {\n expect(menuTypeNames()).toEqual(['group', 'page', 'board', 'interactive-board'])\n })\n\n it('값 칸이 보드 편집기를 가리킨다', () => {\n expect(gristTypeOf('board')).toBe('board')\n expect(gristTypeOf('interactive-board')).toBe('board')\n })\n})\n\ndescribe('renderer 를 요구하지 않는 타입', () => {\n it('group·page 는 renderer 와 무관하게 늘 있고, 값 칸은 글자다', () => {\n expect(menuTypeNames()).toContain('group')\n expect(gristTypeOf('group')).toBe('string')\n expect(gristTypeOf('page')).toBe('string')\n })\n})\n\ndescribe('가장자리', () => {\n it('타입을 안 고른 행(빈 값·undefined·null)은 글자다', () => {\n for (const v of ['', undefined, null]) expect(gristTypeOf(v as any)).toBe('string')\n })\n\n it('모르는 타입도 글자다 — 지어내지 않는다', () => {\n expect(gristTypeOf('nonesuch')).toBe('string')\n })\n\n it('이름 없이 등록하면 던진다 — 그 값이 행에 저장되는 것이다', () => {\n expect(() => registerMenuType({ name: '' })).toThrow(/name is required/)\n expect(() => registerMenuType(undefined as any)).toThrow(/name is required/)\n })\n\n it('같은 이름을 두 번 주면 뒤엣것이 이기고 목록은 안 늘어난다 — 재로드가 목록을 부풀리지 않는다', () => {\n mockRenderers['board'] = () => {}\n const before = menuTypeNames().length\n registerMenuType({ name: 'board', requiresRenderer: 'board' })\n expect(menuTypeNames().length).toBe(before)\n })\n})\n"]}
@@ -17,6 +17,7 @@ import { isMobileDevice } from '@operato/utils';
17
17
  import { getLanguages } from '@things-factory/auth-base/dist-client';
18
18
  import { p13n } from '@operato/p13n';
19
19
  import { fetchAddonMenus } from '../actions/lite-menu';
20
+ import { menuTypeNames, gristTypeOf } from '../menu-type-registry.js';
20
21
  const applicationName = document.querySelector('meta[name="application-name"]')?.content;
21
22
  let AddonMenuSetting = class AddonMenuSetting extends p13n(localize(i18next)(PageView)) {
22
23
  constructor() {
@@ -331,10 +332,10 @@ let AddonMenuSetting = class AddonMenuSetting extends p13n(localize(i18next)(Pag
331
332
  header: i18next.t('field.type'),
332
333
  record: {
333
334
  editable: true,
334
- options: ['', 'group', 'page', 'board', 'interactive-board']
335
+ options: ['', ...menuTypeNames()]
335
336
  },
336
337
  filter: {
337
- options: ['', 'group', 'page', 'board', 'interactive-board'],
338
+ options: ['', ...menuTypeNames()],
338
339
  multiple: false,
339
340
  operator: 'eq'
340
341
  },
@@ -346,13 +347,16 @@ let AddonMenuSetting = class AddonMenuSetting extends p13n(localize(i18next)(Pag
346
347
  header: i18next.t('field.value'),
347
348
  record: {
348
349
  editable: true,
350
+ /*
351
+ * 값 칸의 편집기·표시기는 **메뉴 타입이 정한다.** 타입 이름을 여기 적어 두면 보드 없는
352
+ * 앱에서도 `board` 를 고를 수 있게 되고, 그 renderer 가 등록돼 있지 않아 값 칸이 조용히
353
+ * 글자 편집기로 떨어진다(§`menu-type-registry`).
354
+ */
349
355
  editor: function (value, column, record, rowIndex, field) {
350
- var type = record.type !== 'board' && record.type !== 'interactive-board' ? 'string' : 'board';
351
- return getEditor(type)(value, column, record, rowIndex, field);
356
+ return getEditor(gristTypeOf(record.type))(value, column, record, rowIndex, field);
352
357
  },
353
358
  renderer: function (value, column, record, rowIndex, field) {
354
- var type = record.type !== 'board' && record.type !== 'interactive-board' ? 'string' : 'board';
355
- return getRenderer(type)(value, column, record, rowIndex, field);
359
+ return getRenderer(gristTypeOf(record.type))(value, column, record, rowIndex, field);
356
360
  }
357
361
  },
358
362
  width: 140
@@ -1 +1 @@
1
- {"version":3,"file":"addon-menu-setting.js","sourceRoot":"","sources":["../../client/pages/addon-menu-setting.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/data-grist/ox-sorters-control.js'\nimport '@operato/data-grist/ox-record-creator.js'\nimport '@operato/popup/ox-popup.js'\nimport '@operato/context/ox-context-page-toolbar.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { DataGrist, FetchOption, getEditor, getRenderer } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView, MenuController } from '@operato/shell'\nimport { CommonGristStyles, ScrollbarStyles, CommonHeaderStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { getLanguages } from '@things-factory/auth-base/dist-client'\nimport { p13n } from '@operato/p13n'\n\nimport { fetchAddonMenus } from '../actions/lite-menu'\n\nconst applicationName = (document.querySelector('meta[name=\"application-name\"]') as HTMLMetaElement)?.content\n\n@customElement('addon-menu-setting')\nclass AddonMenuSetting extends p13n(localize(i18next)(PageView)) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n overflow-x: hidden;\n flex-direction: column;\n\n width: 100%;\n }\n\n .header {\n grid-template-areas: 'filters actions';\n }\n\n ox-grist {\n overflow-y: auto;\n flex: 1;\n }\n `\n ]\n\n @state() config: any\n @state() mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'\n\n private _menuCtrl = new MenuController(this)\n\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('text.addon-menu management'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [\n {\n title: i18next.t('button.refresh'),\n action: () => {\n this.onReload()\n },\n icon: 'refresh'\n },\n {\n title: i18next.t('button.delete'),\n action: () => {\n this.onDelete()\n },\n icon: 'delete',\n emphasis: {\n danger: true\n }\n },\n {\n title: i18next.t('button.save'),\n action: () => {\n this.onCommit()\n },\n icon: 'save'\n }\n ],\n exportable: {\n accept: ['json'],\n name: 'lite-menu-list',\n data: () => {\n return this.grist.data\n }\n },\n toolbar: false\n }\n }\n\n render() {\n return html`\n <ox-grist\n .mode=${this.mode}\n .config=${this.config}\n .fetchHandler=${this.fetchHandler}\n .personalConfigProvider=${this.getPagePreferenceProvider('ox-grist')!}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n </div>\n <ox-context-page-toolbar class=\"actions\" .context=${this.context}> </ox-context-page-toolbar>\n </div>\n\n <ox-grist-personalizer slot=\"setting\"></ox-grist-personalizer>\n </ox-grist>\n `\n }\n\n async onCommit() {\n var grist = this.grist\n\n var modifiedList = grist.dirtyRecords.filter(record => record['__dirty__'] == 'M')\n var addedList = grist.dirtyRecords.filter(record => record['__dirty__'] == '+')\n\n await Promise.all(\n modifiedList.map(async record => {\n var id = record.__origin__.id\n var patch = {\n name: record.name,\n description: record.description,\n appName: record.appName,\n parent: record.parent,\n rank: record.rank,\n active: record.active,\n role: record.role,\n labels: record.labels,\n type: record.type,\n value: record.value,\n icon: record.icon,\n help: record.help\n }\n\n if (record.type == 'group') {\n patch = {\n ...patch,\n parent: ''\n }\n }\n\n return await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: LiteMenuPatch!) {\n updateLiteMenu(id: $id, patch: $patch) {\n id\n name\n }\n }\n `,\n variables: {\n id,\n patch: patch\n }\n })\n })\n )\n\n await Promise.all(\n addedList.map(async record => {\n var liteMenu = {\n name: record.name,\n description: record.description,\n appName: record.appName,\n parent: record.parent,\n rank: record.rank,\n active: record.active,\n role: record.role,\n type: record.type,\n value: record.value,\n icon: record.icon,\n help: record.help\n }\n\n return await client.mutate({\n mutation: gql`\n mutation ($liteMenu: NewLiteMenu!) {\n createLiteMenu(liteMenu: $liteMenu) {\n id\n name\n }\n }\n `,\n variables: {\n liteMenu\n }\n })\n })\n )\n\n grist.fetch()\n fetchAddonMenus() /* update menu-system */\n }\n\n onReload() {\n this.grist.fetch()\n }\n\n async onDelete() {\n var grist = this.grist\n\n var deletedList = grist.selected\n\n await Promise.all(\n deletedList.map(async record => {\n var id = record.id\n\n return await client.mutate({\n mutation: gql`\n mutation ($id: String!) {\n deleteLiteMenu(id: $id)\n }\n `,\n variables: {\n id\n }\n })\n })\n )\n\n grist.fetch()\n fetchAddonMenus() /* update menu-system */\n }\n\n async pageInitialized(lifecycle) {\n this.config = {\n list: {\n thumbnail: 'value',\n fields: ['name', 'description'],\n details: ['type', 'parent', 'rank', 'updatedAt']\n },\n columns: [\n {\n type: 'gutter',\n gutterName: 'dirty',\n fixed: true\n },\n {\n type: 'gutter',\n gutterName: 'sequence',\n fixed: true\n },\n {\n type: 'gutter',\n gutterName: 'row-selector',\n multiple: true,\n fixed: true\n },\n {\n type: 'string',\n name: 'id',\n hidden: true\n },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n fixed: true,\n record: {\n editable: true\n },\n filter: 'search',\n sortable: true,\n width: 120\n },\n {\n type: 'i18n-label',\n name: 'labels',\n record: {\n align: 'left',\n editable: true,\n renderer: (value, column, record, rowIndex, field) =>\n html`<span>${value && typeof value == 'object' ? value[i18next.language] : record['name']}</span>`,\n options: {\n objectified: true,\n languages: await getLanguages(),\n displayColumn: 'label'\n }\n },\n header: i18next.t('field.i18n-label'),\n sortable: true,\n filter: 'search',\n width: 120\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: {\n align: 'left',\n editable: true\n },\n filter: 'search',\n width: 200\n },\n {\n type: 'select',\n name: 'appName',\n header: i18next.t('field.app-name'),\n label: true,\n record: {\n align: 'left',\n editable: true,\n options: ['', applicationName]\n },\n filter: {\n options: ['', applicationName],\n multiple: false,\n operator: 'eq'\n },\n width: 200\n },\n {\n type: 'select',\n name: 'parent',\n label: true,\n header: i18next.t('field.parent-menu'),\n record: {\n editable: true,\n options: () => {\n const menus = this._menuCtrl.menus.filter(menu => menu.type !== 'group')\n return ['', ...menus.map(menu => menu.name)]\n }\n },\n sortable: true,\n width: 120\n },\n {\n type: 'number',\n name: 'rank',\n label: true,\n header: i18next.t('field.rank'),\n record: {\n align: 'right',\n editable: true\n },\n sortable: true,\n width: 60\n },\n {\n type: 'select',\n name: 'type',\n label: true,\n header: i18next.t('field.type'),\n record: {\n editable: true,\n options: ['', 'group', 'page', 'board', 'interactive-board']\n },\n filter: {\n options: ['', 'group', 'page', 'board', 'interactive-board'],\n multiple: false,\n operator: 'eq'\n },\n width: 80\n },\n {\n type: 'string',\n name: 'value',\n header: i18next.t('field.value'),\n record: {\n editable: true,\n editor: function (value, column, record, rowIndex, field) {\n var type = record.type !== 'board' && record.type !== 'interactive-board' ? 'string' : 'board'\n return getEditor(type)(value, column, record, rowIndex, field)\n },\n renderer: function (value, column, record, rowIndex, field) {\n var type = record.type !== 'board' && record.type !== 'interactive-board' ? 'string' : 'board'\n return getRenderer(type)(value, column, record, rowIndex, field)\n }\n },\n width: 140\n },\n {\n type: 'string',\n name: 'icon',\n header: i18next.t('field.icon'),\n record: {\n editable: true\n },\n sortable: false,\n width: 120\n },\n {\n type: 'boolean',\n name: 'active',\n label: true,\n header: i18next.t('field.active'),\n record: {\n editable: true\n },\n filter: true,\n sortable: true,\n width: 60\n },\n {\n type: 'string',\n name: 'help',\n label: true,\n header: i18next.t('field.help'),\n record: {\n editable: true\n },\n width: 200\n },\n {\n type: 'resource-object',\n name: 'role',\n label: true,\n header: i18next.t('field.required role'),\n record: {\n editable: true,\n options: {\n title: i18next.t('title.lookup role'),\n queryName: 'roles'\n }\n },\n width: 200\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated_at'),\n width: 180\n },\n {\n type: 'datetime',\n name: 'createdAt',\n header: i18next.t('field.created_at'),\n width: 180\n }\n ],\n rows: {\n selectable: {\n multiple: true\n },\n handlers: {\n click: 'select-row-toggle'\n }\n },\n sorters: [\n {\n name: 'parent',\n desc: false\n },\n {\n name: 'rank',\n desc: false\n }\n ],\n pagination: {\n pages: [20, 30, 50, 100, 200]\n }\n }\n }\n\n async pageUpdated(changes, lifecycle) {\n if (this.active) {\n await this.updateComplete\n\n this.grist.fetch()\n }\n }\n\n async fetchHandler({ filters = [], page, limit, sortings = [] }: FetchOption) {\n const response = (\n await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: liteMenus(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n label\n description\n help\n appName\n parent\n rank\n type\n value\n board {\n id\n name\n description\n thumbnail\n }\n icon\n active\n role {\n id\n name\n description\n }\n labels\n createdAt\n updatedAt\n creator {\n id\n name\n }\n updater {\n id\n name\n }\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n ...filters,\n {\n name: 'appName',\n operator: 'in',\n value: ['', applicationName]\n }\n ],\n pagination: { page, limit },\n sortings\n }\n })\n ).data.responses\n\n return {\n records: response.items,\n total: response.total\n }\n }\n\n liteMenuCreationCallback(liteMenu) {\n console.warn('not implemented yet.')\n }\n}\n"]}
1
+ {"version":3,"file":"addon-menu-setting.js","sourceRoot":"","sources":["../../client/pages/addon-menu-setting.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/data-grist/ox-sorters-control.js'\nimport '@operato/data-grist/ox-record-creator.js'\nimport '@operato/popup/ox-popup.js'\nimport '@operato/context/ox-context-page-toolbar.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { DataGrist, FetchOption, getEditor, getRenderer } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView, MenuController } from '@operato/shell'\nimport { CommonGristStyles, ScrollbarStyles, CommonHeaderStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { getLanguages } from '@things-factory/auth-base/dist-client'\nimport { p13n } from '@operato/p13n'\n\nimport { fetchAddonMenus } from '../actions/lite-menu'\nimport { menuTypeNames, gristTypeOf } from '../menu-type-registry.js'\n\nconst applicationName = (document.querySelector('meta[name=\"application-name\"]') as HTMLMetaElement)?.content\n\n@customElement('addon-menu-setting')\nclass AddonMenuSetting extends p13n(localize(i18next)(PageView)) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n overflow-x: hidden;\n flex-direction: column;\n\n width: 100%;\n }\n\n .header {\n grid-template-areas: 'filters actions';\n }\n\n ox-grist {\n overflow-y: auto;\n flex: 1;\n }\n `\n ]\n\n @state() config: any\n @state() mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'\n\n private _menuCtrl = new MenuController(this)\n\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('text.addon-menu management'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [\n {\n title: i18next.t('button.refresh'),\n action: () => {\n this.onReload()\n },\n icon: 'refresh'\n },\n {\n title: i18next.t('button.delete'),\n action: () => {\n this.onDelete()\n },\n icon: 'delete',\n emphasis: {\n danger: true\n }\n },\n {\n title: i18next.t('button.save'),\n action: () => {\n this.onCommit()\n },\n icon: 'save'\n }\n ],\n exportable: {\n accept: ['json'],\n name: 'lite-menu-list',\n data: () => {\n return this.grist.data\n }\n },\n toolbar: false\n }\n }\n\n render() {\n return html`\n <ox-grist\n .mode=${this.mode}\n .config=${this.config}\n .fetchHandler=${this.fetchHandler}\n .personalConfigProvider=${this.getPagePreferenceProvider('ox-grist')!}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n </div>\n <ox-context-page-toolbar class=\"actions\" .context=${this.context}> </ox-context-page-toolbar>\n </div>\n\n <ox-grist-personalizer slot=\"setting\"></ox-grist-personalizer>\n </ox-grist>\n `\n }\n\n async onCommit() {\n var grist = this.grist\n\n var modifiedList = grist.dirtyRecords.filter(record => record['__dirty__'] == 'M')\n var addedList = grist.dirtyRecords.filter(record => record['__dirty__'] == '+')\n\n await Promise.all(\n modifiedList.map(async record => {\n var id = record.__origin__.id\n var patch = {\n name: record.name,\n description: record.description,\n appName: record.appName,\n parent: record.parent,\n rank: record.rank,\n active: record.active,\n role: record.role,\n labels: record.labels,\n type: record.type,\n value: record.value,\n icon: record.icon,\n help: record.help\n }\n\n if (record.type == 'group') {\n patch = {\n ...patch,\n parent: ''\n }\n }\n\n return await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: LiteMenuPatch!) {\n updateLiteMenu(id: $id, patch: $patch) {\n id\n name\n }\n }\n `,\n variables: {\n id,\n patch: patch\n }\n })\n })\n )\n\n await Promise.all(\n addedList.map(async record => {\n var liteMenu = {\n name: record.name,\n description: record.description,\n appName: record.appName,\n parent: record.parent,\n rank: record.rank,\n active: record.active,\n role: record.role,\n type: record.type,\n value: record.value,\n icon: record.icon,\n help: record.help\n }\n\n return await client.mutate({\n mutation: gql`\n mutation ($liteMenu: NewLiteMenu!) {\n createLiteMenu(liteMenu: $liteMenu) {\n id\n name\n }\n }\n `,\n variables: {\n liteMenu\n }\n })\n })\n )\n\n grist.fetch()\n fetchAddonMenus() /* update menu-system */\n }\n\n onReload() {\n this.grist.fetch()\n }\n\n async onDelete() {\n var grist = this.grist\n\n var deletedList = grist.selected\n\n await Promise.all(\n deletedList.map(async record => {\n var id = record.id\n\n return await client.mutate({\n mutation: gql`\n mutation ($id: String!) {\n deleteLiteMenu(id: $id)\n }\n `,\n variables: {\n id\n }\n })\n })\n )\n\n grist.fetch()\n fetchAddonMenus() /* update menu-system */\n }\n\n async pageInitialized(lifecycle) {\n this.config = {\n list: {\n thumbnail: 'value',\n fields: ['name', 'description'],\n details: ['type', 'parent', 'rank', 'updatedAt']\n },\n columns: [\n {\n type: 'gutter',\n gutterName: 'dirty',\n fixed: true\n },\n {\n type: 'gutter',\n gutterName: 'sequence',\n fixed: true\n },\n {\n type: 'gutter',\n gutterName: 'row-selector',\n multiple: true,\n fixed: true\n },\n {\n type: 'string',\n name: 'id',\n hidden: true\n },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n fixed: true,\n record: {\n editable: true\n },\n filter: 'search',\n sortable: true,\n width: 120\n },\n {\n type: 'i18n-label',\n name: 'labels',\n record: {\n align: 'left',\n editable: true,\n renderer: (value, column, record, rowIndex, field) =>\n html`<span>${value && typeof value == 'object' ? value[i18next.language] : record['name']}</span>`,\n options: {\n objectified: true,\n languages: await getLanguages(),\n displayColumn: 'label'\n }\n },\n header: i18next.t('field.i18n-label'),\n sortable: true,\n filter: 'search',\n width: 120\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: {\n align: 'left',\n editable: true\n },\n filter: 'search',\n width: 200\n },\n {\n type: 'select',\n name: 'appName',\n header: i18next.t('field.app-name'),\n label: true,\n record: {\n align: 'left',\n editable: true,\n options: ['', applicationName]\n },\n filter: {\n options: ['', applicationName],\n multiple: false,\n operator: 'eq'\n },\n width: 200\n },\n {\n type: 'select',\n name: 'parent',\n label: true,\n header: i18next.t('field.parent-menu'),\n record: {\n editable: true,\n options: () => {\n const menus = this._menuCtrl.menus.filter(menu => menu.type !== 'group')\n return ['', ...menus.map(menu => menu.name)]\n }\n },\n sortable: true,\n width: 120\n },\n {\n type: 'number',\n name: 'rank',\n label: true,\n header: i18next.t('field.rank'),\n record: {\n align: 'right',\n editable: true\n },\n sortable: true,\n width: 60\n },\n {\n type: 'select',\n name: 'type',\n label: true,\n header: i18next.t('field.type'),\n record: {\n editable: true,\n options: ['', ...menuTypeNames()]\n },\n filter: {\n options: ['', ...menuTypeNames()],\n multiple: false,\n operator: 'eq'\n },\n width: 80\n },\n {\n type: 'string',\n name: 'value',\n header: i18next.t('field.value'),\n record: {\n editable: true,\n /*\n * 값 칸의 편집기·표시기는 **메뉴 타입이 정한다.** 타입 이름을 여기 적어 두면 보드 없는\n * 앱에서도 `board` 를 고를 수 있게 되고, 그 renderer 가 등록돼 있지 않아 값 칸이 조용히\n * 글자 편집기로 떨어진다(§`menu-type-registry`).\n */\n editor: function (value, column, record, rowIndex, field) {\n return getEditor(gristTypeOf(record.type))(value, column, record, rowIndex, field)\n },\n renderer: function (value, column, record, rowIndex, field) {\n return getRenderer(gristTypeOf(record.type))(value, column, record, rowIndex, field)\n }\n },\n width: 140\n },\n {\n type: 'string',\n name: 'icon',\n header: i18next.t('field.icon'),\n record: {\n editable: true\n },\n sortable: false,\n width: 120\n },\n {\n type: 'boolean',\n name: 'active',\n label: true,\n header: i18next.t('field.active'),\n record: {\n editable: true\n },\n filter: true,\n sortable: true,\n width: 60\n },\n {\n type: 'string',\n name: 'help',\n label: true,\n header: i18next.t('field.help'),\n record: {\n editable: true\n },\n width: 200\n },\n {\n type: 'resource-object',\n name: 'role',\n label: true,\n header: i18next.t('field.required role'),\n record: {\n editable: true,\n options: {\n title: i18next.t('title.lookup role'),\n queryName: 'roles'\n }\n },\n width: 200\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated_at'),\n width: 180\n },\n {\n type: 'datetime',\n name: 'createdAt',\n header: i18next.t('field.created_at'),\n width: 180\n }\n ],\n rows: {\n selectable: {\n multiple: true\n },\n handlers: {\n click: 'select-row-toggle'\n }\n },\n sorters: [\n {\n name: 'parent',\n desc: false\n },\n {\n name: 'rank',\n desc: false\n }\n ],\n pagination: {\n pages: [20, 30, 50, 100, 200]\n }\n }\n }\n\n async pageUpdated(changes, lifecycle) {\n if (this.active) {\n await this.updateComplete\n\n this.grist.fetch()\n }\n }\n\n async fetchHandler({ filters = [], page, limit, sortings = [] }: FetchOption) {\n const response = (\n await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: liteMenus(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n label\n description\n help\n appName\n parent\n rank\n type\n value\n board {\n id\n name\n description\n thumbnail\n }\n icon\n active\n role {\n id\n name\n description\n }\n labels\n createdAt\n updatedAt\n creator {\n id\n name\n }\n updater {\n id\n name\n }\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n ...filters,\n {\n name: 'appName',\n operator: 'in',\n value: ['', applicationName]\n }\n ],\n pagination: { page, limit },\n sortings\n }\n })\n ).data.responses\n\n return {\n records: response.items,\n total: response.total\n }\n }\n\n liteMenuCreationCallback(liteMenu) {\n console.warn('not implemented yet.')\n }\n}\n"]}