@things-factory/figure-library 10.1.218 → 10.1.222
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/dist-client/bootstrap.d.ts +5 -3
- package/dist-client/bootstrap.js +6 -3
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/editors/ox-property-editor-figure-status.d.ts +41 -0
- package/dist-client/editors/ox-property-editor-figure-status.js +290 -0
- package/dist-client/editors/ox-property-editor-figure-status.js.map +1 -0
- package/dist-client/figure-palette-group.d.ts +9 -4
- package/dist-client/figure-palette-group.js +2 -1
- package/dist-client/figure-palette-group.js.map +1 -1
- package/dist-client/figure-palette.js +2 -1
- package/dist-client/figure-palette.js.map +1 -1
- package/dist-client/item-types/item-types-rows.d.ts +8 -0
- package/dist-client/item-types/item-types-rows.js +11 -0
- package/dist-client/item-types/item-types-rows.js.map +1 -1
- package/dist-client/item-types/ox-item-types-input.d.ts +5 -1
- package/dist-client/item-types/ox-item-types-input.js +144 -112
- package/dist-client/item-types/ox-item-types-input.js.map +1 -1
- package/dist-client/pages/figure-library-page.js +0 -1
- package/dist-client/pages/figure-library-page.js.map +1 -1
- package/dist-client/status-looks/ox-figure-status-looks.d.ts +58 -0
- package/dist-client/status-looks/ox-figure-status-looks.js +489 -0
- package/dist-client/status-looks/ox-figure-status-looks.js.map +1 -0
- package/dist-client/status-looks/status-looks.d.ts +99 -0
- package/dist-client/status-looks/status-looks.js +134 -0
- package/dist-client/status-looks/status-looks.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/figure-releases-popup.d.ts +1 -4
- package/dist-client/viewparts/figure-releases-popup.js +3 -21
- package/dist-client/viewparts/figure-releases-popup.js.map +1 -1
- package/dist-server/service/figure-library-release/figure-library-release.d.ts +3 -1
- package/dist-server/service/figure-library-release/figure-library-release.js +11 -1
- package/dist-server/service/figure-library-release/figure-library-release.js.map +1 -1
- package/dist-server/service/figure-library-resolver.d.ts +0 -1
- package/dist-server/service/figure-library-resolver.js +0 -15
- package/dist-server/service/figure-library-resolver.js.map +1 -1
- package/dist-server/service/figure-library-types.js +1 -1
- package/dist-server/service/figure-library-types.js.map +1 -1
- package/dist-server/service/figure-type-map/figure-type-map-entry.d.ts +0 -1
- package/dist-server/service/figure-type-map/figure-type-map-entry.js +1 -12
- package/dist-server/service/figure-type-map/figure-type-map-entry.js.map +1 -1
- package/dist-server/service/library/derived.d.ts +6 -2
- package/dist-server/service/library/derived.js +4 -2
- package/dist-server/service/library/derived.js.map +1 -1
- package/dist-server/service/library/figures.d.ts +2 -2
- package/dist-server/service/library/figures.js +2 -2
- package/dist-server/service/library/figures.js.map +1 -1
- package/dist-server/service/library/type-map.d.ts +0 -5
- package/dist-server/service/library/type-map.js +0 -14
- package/dist-server/service/library/type-map.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/translations/en.json +49 -5
- package/translations/es.json +49 -5
- package/translations/ja.json +49 -5
- package/translations/ko.json +49 -5
- package/translations/ms.json +49 -5
- package/translations/zh.json +49 -5
|
@@ -8,16 +8,19 @@ import { __decorate, __metadata } from "tslib";
|
|
|
8
8
|
*
|
|
9
9
|
* The words are the module's translations; an app whose items are called otherwise (fmsim: carriers) says them its own way.
|
|
10
10
|
*/
|
|
11
|
+
import '@material/web/button/filled-button.js';
|
|
12
|
+
import '@material/web/button/text-button.js';
|
|
11
13
|
import '@material/web/icon/icon.js';
|
|
14
|
+
import '@operato/popup/ox-popup-actions.js';
|
|
12
15
|
import gql from 'graphql-tag';
|
|
13
16
|
import { css, html, LitElement, nothing } from 'lit';
|
|
14
17
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
15
18
|
import { client } from '@operato/graphql';
|
|
16
19
|
import { i18next } from '@operato/i18n';
|
|
17
20
|
import { closePopup } from '@operato/popup';
|
|
18
|
-
import {
|
|
21
|
+
import { CommonPopupStyles, FormFieldStyles, PopupBodyStyles } from '@operato/styles';
|
|
19
22
|
import { getPathInfo } from '@operato/utils';
|
|
20
|
-
import { emptyRow, rowIssues } from './item-types-rows.js';
|
|
23
|
+
import { emptyRow, figureChoiceLabels, rowIssues } from './item-types-rows.js';
|
|
21
24
|
/* The names the domain draws as items, with the name and thumbnail of the release each draws with. */
|
|
22
25
|
const ITEM_FIGURES = gql `
|
|
23
26
|
query ($filters: [Filter!], $pagination: Pagination) {
|
|
@@ -35,6 +38,11 @@ const ITEM_FIGURES = gql `
|
|
|
35
38
|
/** As many item figures as one domain is expected to have; the picker lists them all. */
|
|
36
39
|
const ITEM_FIGURE_LIMIT = 500;
|
|
37
40
|
const t = (key, options) => i18next.t(`figure-library.item-types.${key}`, options);
|
|
41
|
+
/*
|
|
42
|
+
* The house popup (operato-application design/ui/page-standard.md 7 · 8): CommonPopupStyles' card, only the body
|
|
43
|
+
* scrolls (PopupBodyStyles), native fields at the table height (FormFieldStyles small), each row's problems right under
|
|
44
|
+
* it, the row's own button at its end, and cancel · confirm in ox-popup-actions.
|
|
45
|
+
*/
|
|
38
46
|
let OxItemTypesInput = class OxItemTypesInput extends LitElement {
|
|
39
47
|
constructor() {
|
|
40
48
|
super(...arguments);
|
|
@@ -42,112 +50,114 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
|
|
|
42
50
|
this.rows = [];
|
|
43
51
|
/** The domain's item figures; null until they are read, empty when the library cannot be read or marks none. */
|
|
44
52
|
this.figures = null;
|
|
45
|
-
/** Thumbnails that could not be drawn:
|
|
53
|
+
/** Thumbnails that could not be drawn: the empty mark in their place, not a broken image. */
|
|
46
54
|
this.unreadThumbnails = new Set();
|
|
47
55
|
}
|
|
48
56
|
static { this.styles = [
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
CommonPopupStyles,
|
|
58
|
+
PopupBodyStyles,
|
|
59
|
+
FormFieldStyles,
|
|
51
60
|
css `
|
|
52
61
|
:host {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
height: var(--overlay-center-large-height, 70%);
|
|
58
|
-
}
|
|
59
|
-
[body] {
|
|
60
|
-
flex: 1;
|
|
61
|
-
overflow: auto;
|
|
62
|
-
padding: var(--spacing-medium, 8px);
|
|
62
|
+
width: 100%;
|
|
63
|
+
height: 100%;
|
|
64
|
+
max-height: none;
|
|
65
|
+
--popup-min-width: 0;
|
|
63
66
|
}
|
|
64
67
|
table {
|
|
65
68
|
width: 100%;
|
|
66
69
|
border-collapse: collapse;
|
|
67
|
-
font-size: var(--ui-t-body, 13px);
|
|
68
70
|
}
|
|
69
71
|
th {
|
|
72
|
+
position: sticky;
|
|
73
|
+
top: 0;
|
|
74
|
+
z-index: 1;
|
|
75
|
+
background: var(--ui-bg, #ffffff);
|
|
70
76
|
text-align: left;
|
|
71
|
-
font-weight:
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
font-weight: normal;
|
|
78
|
+
font-size: var(--popup-font-size-small);
|
|
79
|
+
color: var(--ui-muted, #57676f);
|
|
80
|
+
padding: 0 var(--spacing-small, 4px) var(--spacing-small, 4px);
|
|
74
81
|
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
75
82
|
white-space: nowrap;
|
|
76
83
|
}
|
|
77
84
|
td {
|
|
78
|
-
padding:
|
|
85
|
+
padding: var(--spacing-small, 4px);
|
|
79
86
|
vertical-align: middle;
|
|
80
87
|
}
|
|
88
|
+
tr[type] td {
|
|
89
|
+
border-top: 1px solid var(--ui-line-soft, #eef1f3);
|
|
90
|
+
}
|
|
91
|
+
tr[issues] td {
|
|
92
|
+
padding-top: 0;
|
|
93
|
+
}
|
|
94
|
+
/*
|
|
95
|
+
Widths by what they hold (page-standard 7): a code is an identifier such as FORMATION_TRAY, wider than a
|
|
96
|
+
quantity; a type's name is a few words; the figure takes the rest.
|
|
97
|
+
*/
|
|
98
|
+
th[code],
|
|
99
|
+
td[code] {
|
|
100
|
+
width: 160px;
|
|
101
|
+
}
|
|
102
|
+
th[name],
|
|
103
|
+
td[name] {
|
|
104
|
+
width: 200px;
|
|
105
|
+
}
|
|
81
106
|
input,
|
|
82
107
|
select {
|
|
83
108
|
width: 100%;
|
|
84
|
-
box-sizing: border-box;
|
|
85
|
-
font: inherit;
|
|
86
|
-
padding: 3px 6px;
|
|
87
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
88
|
-
border-radius: 4px;
|
|
89
|
-
background: var(--md-sys-color-surface);
|
|
90
|
-
color: var(--md-sys-color-on-surface);
|
|
91
109
|
}
|
|
92
|
-
td[
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
gap: 6px;
|
|
96
|
-
min-width: 220px;
|
|
110
|
+
td[thumb] {
|
|
111
|
+
width: 32px;
|
|
112
|
+
padding-right: 0;
|
|
97
113
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
[thumb] img,
|
|
115
|
+
[thumb] [no-thumb] {
|
|
116
|
+
display: grid;
|
|
117
|
+
place-items: center;
|
|
118
|
+
box-sizing: border-box;
|
|
119
|
+
width: 32px;
|
|
120
|
+
height: 32px;
|
|
103
121
|
object-fit: contain;
|
|
104
|
-
border-radius: 4px;
|
|
105
|
-
background: var(--md-sys-color-surface-container);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
font-size: var(--ui-t-small, 11.5px);
|
|
109
|
-
min-width: 160px;
|
|
110
|
-
}
|
|
111
|
-
[issue] {
|
|
112
|
-
color: var(--md-sys-color-error);
|
|
113
|
-
}
|
|
114
|
-
[warning],
|
|
115
|
-
[empty] {
|
|
116
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
122
|
+
border-radius: var(--md-sys-shape-corner-small, 4px);
|
|
123
|
+
background: var(--md-sys-color-surface-container, #eef1f3);
|
|
124
|
+
color: var(--ui-muted, #57676f);
|
|
125
|
+
--md-icon-size: 16px;
|
|
117
126
|
}
|
|
118
|
-
[
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
td[end] {
|
|
128
|
+
width: 1%;
|
|
129
|
+
text-align: right;
|
|
121
130
|
}
|
|
122
|
-
/*
|
|
123
|
-
button[
|
|
124
|
-
button[add] {
|
|
131
|
+
/* A row's own button: quiet, an icon with its name in the tooltip (page-standard 8). */
|
|
132
|
+
button[quiet] {
|
|
125
133
|
display: inline-flex;
|
|
126
134
|
align-items: center;
|
|
127
|
-
gap: 4px;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
gap: var(--spacing-small, 4px);
|
|
136
|
+
height: var(--form-element-height-small, 26px);
|
|
137
|
+
padding: 0 var(--spacing-small, 4px);
|
|
138
|
+
border: 0;
|
|
139
|
+
border-radius: var(--md-sys-shape-corner-small, 4px);
|
|
140
|
+
background: transparent;
|
|
141
|
+
color: var(--ui-muted, #57676f);
|
|
133
142
|
font: inherit;
|
|
143
|
+
font-weight: 600;
|
|
134
144
|
cursor: pointer;
|
|
135
|
-
--md-icon-size:
|
|
145
|
+
--md-icon-size: 16px;
|
|
136
146
|
}
|
|
137
|
-
button[
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
background-color: var(--button-background-focus-color);
|
|
141
|
-
color: var(--md-sys-color-primary-container);
|
|
147
|
+
button[quiet]:hover {
|
|
148
|
+
background: var(--ui-line-soft, #eef1f3);
|
|
149
|
+
color: var(--ui-ink, #17242c);
|
|
142
150
|
}
|
|
143
|
-
button[add] {
|
|
144
|
-
|
|
151
|
+
button[quiet][add] md-icon {
|
|
152
|
+
color: var(--md-sys-color-primary);
|
|
145
153
|
}
|
|
146
|
-
[
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
[issue] {
|
|
155
|
+
color: var(--ui-crit, var(--md-sys-color-error));
|
|
156
|
+
font-size: var(--popup-font-size-small);
|
|
157
|
+
}
|
|
158
|
+
[warning] {
|
|
159
|
+
color: var(--ui-muted, #57676f);
|
|
160
|
+
font-size: var(--popup-font-size-small);
|
|
151
161
|
}
|
|
152
162
|
`
|
|
153
163
|
]; }
|
|
@@ -158,29 +168,32 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
|
|
|
158
168
|
render() {
|
|
159
169
|
const issues = rowIssues(this.rows);
|
|
160
170
|
return html `
|
|
161
|
-
<div body>
|
|
162
|
-
${this.figures?.length === 0 ? html `<
|
|
171
|
+
<div class="body">
|
|
172
|
+
${this.figures?.length === 0 ? html `<div class="note">${t('no-item-figures')}</div>` : nothing}
|
|
163
173
|
<table>
|
|
164
174
|
<thead>
|
|
165
175
|
<tr>
|
|
166
|
-
<th>${t('code')}</th>
|
|
167
|
-
<th>${t('name')}</th>
|
|
168
|
-
<th>${t('figure')}</th>
|
|
169
176
|
<th></th>
|
|
177
|
+
<th code>${t('code')}</th>
|
|
178
|
+
<th name>${t('name')}</th>
|
|
179
|
+
<th>${t('figure')}</th>
|
|
170
180
|
<th></th>
|
|
171
181
|
</tr>
|
|
172
182
|
</thead>
|
|
173
183
|
<tbody>
|
|
174
184
|
${this.rows.map((row, i) => this.renderRow(row, i, issues.get(i) ?? []))}
|
|
185
|
+
<tr>
|
|
186
|
+
<td></td>
|
|
187
|
+
<td colspan="4"><button quiet add @click=${this.onAdd}><md-icon>add</md-icon>${t('add')}</button></td>
|
|
188
|
+
</tr>
|
|
175
189
|
</tbody>
|
|
176
190
|
</table>
|
|
177
|
-
|
|
178
|
-
</div>
|
|
179
|
-
<div class="footer">
|
|
180
|
-
<div summary>${issues.size ? t('fix-rows', { count: issues.size }) : nothing}</div>
|
|
181
|
-
<button @click=${this.onCancel} danger><md-icon>cancel</md-icon>${i18next.t('button.cancel')}</button>
|
|
182
|
-
<button @click=${this.onConfirm} ?disabled=${issues.size > 0} done><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>
|
|
191
|
+
${issues.size ? html `<div class="failure">${t('fix-rows', { count: issues.size })}</div>` : nothing}
|
|
183
192
|
</div>
|
|
193
|
+
<ox-popup-actions>
|
|
194
|
+
<md-text-button slot="cancel" @click=${this.onCancel}>${i18next.t('button.cancel')}</md-text-button>
|
|
195
|
+
<md-filled-button slot="confirm" ?disabled=${issues.size > 0} @click=${this.onConfirm}>${i18next.t('button.confirm')}</md-filled-button>
|
|
196
|
+
</ox-popup-actions>
|
|
184
197
|
`;
|
|
185
198
|
}
|
|
186
199
|
renderRow(row, i, issues) {
|
|
@@ -188,25 +201,47 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
|
|
|
188
201
|
const chosen = figures.find(f => f.name === row.figure);
|
|
189
202
|
/* A figure written before that the library no longer marks as an item: kept as written, and told. */
|
|
190
203
|
const unmarked = !!row.figure && this.figures !== null && !chosen;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
? html `<img src=${
|
|
197
|
-
: html `<span no-thumb
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
const thumbnail = chosen?.thumbnail && !this.unreadThumbnails.has(chosen.thumbnail) ? chosen.thumbnail : '';
|
|
205
|
+
return html `
|
|
206
|
+
<tr type>
|
|
207
|
+
<td thumb>
|
|
208
|
+
${thumbnail
|
|
209
|
+
? html `<img src=${thumbnail} alt="" @error=${() => (this.unreadThumbnails = new Set([...this.unreadThumbnails, thumbnail]))} />`
|
|
210
|
+
: html `<span no-thumb title=${row.figure ? t('no-thumbnail') : t('figure-none')}>
|
|
211
|
+
<md-icon>${row.figure ? 'image_not_supported' : 'inventory_2'}</md-icon>
|
|
212
|
+
</span>`}
|
|
213
|
+
</td>
|
|
214
|
+
<td code><input small .value=${row.code} data-row=${i} data-key="code" @input=${this.onInput} /></td>
|
|
215
|
+
<td name><input small .value=${row.name} data-row=${i} data-key="name" @input=${this.onInput} /></td>
|
|
216
|
+
<td>
|
|
217
|
+
<select small data-row=${i} data-key="figure" title=${row.figure} @change=${this.onInput}>
|
|
218
|
+
<option value="" ?selected=${!row.figure}>${t('figure-none')}</option>
|
|
219
|
+
${unmarked ? html `<option value=${row.figure} selected>${row.figure}</option>` : nothing}
|
|
220
|
+
${figures.map(f => html `<option value=${f.name} ?selected=${f.name === row.figure}>${f.label}</option>`)}
|
|
221
|
+
</select>
|
|
222
|
+
</td>
|
|
223
|
+
<td end>
|
|
224
|
+
<button quiet remove title=${t('remove')} aria-label=${t('remove')} data-row=${i} @click=${this.onRemove}><md-icon>delete</md-icon></button>
|
|
225
|
+
</td>
|
|
226
|
+
</tr>
|
|
227
|
+
${issues.length || unmarked
|
|
228
|
+
? html `<tr issues>
|
|
229
|
+
<td></td>
|
|
230
|
+
<td colspan="4">
|
|
231
|
+
${issues.map(issue => html `<div issue>${this.issueText(issue)}</div>`)}
|
|
232
|
+
${unmarked ? html `<div warning>${t('figure-not-item')}</div>` : nothing}
|
|
233
|
+
</td>
|
|
234
|
+
</tr>`
|
|
235
|
+
: nothing}
|
|
236
|
+
`;
|
|
237
|
+
}
|
|
238
|
+
/* A code that does not hold is invalid to the browser too: the shared field style outlines it once it is typed in (:user-invalid). */
|
|
239
|
+
updated() {
|
|
240
|
+
const issues = rowIssues(this.rows);
|
|
241
|
+
this.renderRoot.querySelectorAll('input[data-key="code"]').forEach(input => {
|
|
242
|
+
const row = issues.get(Number(input.dataset.row));
|
|
243
|
+
input.setCustomValidity(row?.length ? this.issueText(row[0]) : '');
|
|
244
|
+
});
|
|
210
245
|
}
|
|
211
246
|
issueText(issue) {
|
|
212
247
|
if (issue.code === 'item-type-duplicate')
|
|
@@ -244,15 +279,12 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
|
|
|
244
279
|
fetchPolicy: 'network-only'
|
|
245
280
|
});
|
|
246
281
|
const { contextPath } = getPathInfo(location.pathname);
|
|
247
|
-
|
|
282
|
+
const items = data?.figureLibraryFigures?.items ?? [];
|
|
283
|
+
const labels = figureChoiceLabels(items.map((item) => ({ name: item.name, display: item.release?.name })));
|
|
284
|
+
this.figures = items
|
|
248
285
|
.map((item) => {
|
|
249
286
|
const hash = item.release?.dependencies?.find((d) => d.role === 'thumbnail')?.hash;
|
|
250
|
-
|
|
251
|
-
return {
|
|
252
|
-
name: item.name,
|
|
253
|
-
label: display && display !== item.name ? `${display} — ${item.name}` : item.name,
|
|
254
|
-
thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : ''
|
|
255
|
-
};
|
|
287
|
+
return { name: item.name, label: labels.get(item.name), thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : '' };
|
|
256
288
|
})
|
|
257
289
|
.sort((a, b) => a.label.localeCompare(b.label));
|
|
258
290
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-item-types-input.js","sourceRoot":"","sources":["../../client/item-types/ox-item-types-input.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,OAAO,4BAA4B,CAAA;AAEnC,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG5C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAA;AAE5E,sGAAsG;AACtG,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;CAYvB,CAAA;AAED,yFAAyF;AACzF,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAQ7B,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAA;AAG7G,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,UAAU;IAAzC;;QA4GL,gHAAgH;QACrF,SAAI,GAAkB,EAAE,CAAA;QAGnD,gHAAgH;QAC/F,YAAO,GAAwB,IAAI,CAAA;QACpD,2FAA2F;QAC1E,qBAAgB,GAAG,IAAI,GAAG,EAAU,CAAA;IAqHvD,CAAC;aAvOQ,WAAM,GAAG;QACd,kBAAkB;QAClB,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqGF;KACF,AAzGY,CAyGZ;IAWD,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QACzB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,OAAO,IAAI,CAAA;;UAEL,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,YAAY,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;;;oBAIvE,CAAC,CAAC,MAAM,CAAC;oBACT,CAAC,CAAC,MAAM,CAAC;oBACT,CAAC,CAAC,QAAQ,CAAC;;;;;;cAMjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;;;6BAGvD,IAAI,CAAC,KAAK,0BAA0B,CAAC,CAAC,KAAK,CAAC;;;uBAGlD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO;yBAC3D,IAAI,CAAC,QAAQ,oCAAoC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;yBAC3E,IAAI,CAAC,SAAS,cAAc,MAAM,CAAC,IAAI,GAAG,CAAC,gCAAgC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;;KAE1H,CAAA;IACH,CAAC;IAEO,SAAS,CAAC,GAAgB,EAAE,CAAS,EAAE,MAAuB;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,CAAA;QACvD,qGAAqG;QACrG,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,MAAM,CAAA;QACjE,OAAO,IAAI,CAAA;0BACW,GAAG,CAAC,IAAI,aAAa,CAAC,2BAA2B,IAAI,CAAC,OAAO;0BAC7D,GAAG,CAAC,IAAI,aAAa,CAAC,2BAA2B,IAAI,CAAC,OAAO;;UAE7E,MAAM,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;YACjE,CAAC,CAAC,IAAI,CAAA,YAAY,MAAM,CAAC,SAAS,kBAAkB,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK;YAC9I,CAAC,CAAC,IAAI,CAAA,wBAAwB;2BACb,CAAC,8BAA8B,IAAI,CAAC,OAAO;uCAC/B,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,CAAC;YAC1D,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,iBAAiB,GAAG,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,OAAO;YACtF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,WAAW,CAAC;;;;UAIxG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;UACpE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;iCAE9C,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,IAAI,CAAC,QAAQ;UACxE,CAAA;IACR,CAAC;IAEO,SAAS,CAAC,KAAoB;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB;YAAE,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpH,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3D,CAAC;IAEO,OAAO,CAAC,CAAQ;QACtB,MAAM,KAAK,GAAG,CAAC,CAAC,MAA8C,CAAA;QAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAwB,CAAA;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACnF,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IACxC,CAAC;IAEO,QAAQ,CAAC,CAAQ;QACvB,MAAM,CAAC,GAAG,MAAM,CAAE,CAAC,CAAC,aAA6B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC9D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,CAAC;IAEO,QAAQ;QACd,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAEO,SAAS;QACf,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI;YAAE,OAAM;QACrC,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAED,4GAA4G;IACpG,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAClC,KAAK,EAAE,YAAY;gBACnB,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE;gBAC1H,WAAW,EAAE,cAAc;aAC5B,CAAC,CAAA;YACF,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACtD,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,IAAI,EAAE,CAAC;iBACrD,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;gBACjB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,IAAI,CAAA;gBACvF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAA;gBAClC,OAAO;oBACL,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,KAAK,EAAE,OAAO,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI;oBACjF,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;iBACpE,CAAA;YACH,CAAC,CAAC;iBACD,IAAI,CAAC,CAAC,CAAa,EAAE,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACnB,CAAC;IACH,CAAC;;AA1H0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;8CAAyB;AACvB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yDAAgD;AAG1D;IAAhB,KAAK,EAAE;;iDAA4C;AAEnC;IAAhB,KAAK,EAAE;;0DAA6C;AAnH1C,gBAAgB;IAD5B,aAAa,CAAC,qBAAqB,CAAC;GACxB,gBAAgB,CAwO5B","sourcesContent":["/*\n * The item type table of a domain (ADR-0155), edited in a popup from a theme of type item-types (fmsim: carrier-types):\n * one row per type -- code, name, the figure it is drawn by. A type has no size; an item is drawn at the size of the\n * place it sits in (amendment 1). The figure is chosen from the names the domain's library marks as items (amendment\n * 1 E · F), shown with their thumbnails. What does not hold is said on its row by things-scene's rule and the table is\n * not confirmed until it holds; a figure written before that is no longer marked is told on its row and does not stop it.\n *\n * The words are the module's translations; an app whose items are called otherwise (fmsim: carriers) says them its own way.\n */\nimport '@material/web/icon/icon.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'\nimport { getPathInfo } from '@operato/utils'\nimport type { ItemTypeIssue } from '@hatiolab/things-scene'\n\nimport { emptyRow, rowIssues, type ItemTypeRow } from './item-types-rows.js'\n\n/* The names the domain draws as items, with the name and thumbnail of the release each draws with. */\nconst ITEM_FIGURES = gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n figureLibraryFigures(filters: $filters, pagination: $pagination) {\n items {\n name\n release {\n name\n dependencies\n }\n }\n }\n }\n`\n\n/** As many item figures as one domain is expected to have; the picker lists them all. */\nconst ITEM_FIGURE_LIMIT = 500\n\ninterface ItemFigure {\n name: string\n label: string\n thumbnail: string\n}\n\nconst t = (key: string, options?: Record<string, unknown>) => i18next.t(`figure-library.item-types.${key}`, options)\n\n@customElement('ox-item-types-input')\nexport class OxItemTypesInput extends LitElement {\n static styles = [\n CommonHeaderStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n background-color: var(--md-sys-color-surface);\n width: var(--overlay-center-large-width, 80%);\n height: var(--overlay-center-large-height, 70%);\n }\n [body] {\n flex: 1;\n overflow: auto;\n padding: var(--spacing-medium, 8px);\n }\n table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--ui-t-body, 13px);\n }\n th {\n text-align: left;\n font-weight: 600;\n color: var(--md-sys-color-on-surface-variant);\n padding: 4px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n white-space: nowrap;\n }\n td {\n padding: 2px 4px;\n vertical-align: middle;\n }\n input,\n select {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n padding: 3px 6px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 4px;\n background: var(--md-sys-color-surface);\n color: var(--md-sys-color-on-surface);\n }\n td[figure] {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 220px;\n }\n td[figure] img,\n td[figure] [no-thumb] {\n flex: none;\n width: 28px;\n height: 28px;\n object-fit: contain;\n border-radius: 4px;\n background: var(--md-sys-color-surface-container);\n }\n td[note] {\n font-size: var(--ui-t-small, 11.5px);\n min-width: 160px;\n }\n [issue] {\n color: var(--md-sys-color-error);\n }\n [warning],\n [empty] {\n color: var(--md-sys-color-on-surface-variant);\n }\n [empty] {\n margin: 0 0 var(--spacing-medium, 8px);\n font-size: var(--ui-t-small, 11.5px);\n }\n /* The row buttons as the value map editor draws its own (ox-input-value-map). */\n button[remove],\n button[add] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n border: var(--button-border);\n border-radius: var(--ox-input-radius, 4px);\n background-color: var(--button-background-color);\n padding: 2px 8px;\n color: var(--button-color);\n font: inherit;\n cursor: pointer;\n --md-icon-size: var(--fontsize-default, 14px);\n }\n button[remove]:hover,\n button[add]:hover {\n border: var(--button-activ-border);\n background-color: var(--button-background-focus-color);\n color: var(--md-sys-color-primary-container);\n }\n button[add] {\n margin-top: 6px;\n }\n [summary] {\n flex: 1;\n display: flex;\n align-items: center;\n color: var(--md-sys-color-error);\n }\n `\n ]\n\n /** The rows as typed; the popup's own copy (see the note in ox-popup-value-map-input on re-rendered popups). */\n @property({ type: Array }) rows: ItemTypeRow[] = []\n @property({ type: Object }) confirmCallback?: (rows: ItemTypeRow[]) => void\n\n /** The domain's item figures; null until they are read, empty when the library cannot be read or marks none. */\n @state() private figures: ItemFigure[] | null = null\n /** Thumbnails that could not be drawn: an empty box in their place, not a broken image. */\n @state() private unreadThumbnails = new Set<string>()\n\n connectedCallback() {\n super.connectedCallback()\n this.fetchFigures()\n }\n\n render() {\n const issues = rowIssues(this.rows)\n return html`\n <div body>\n ${this.figures?.length === 0 ? html`<p empty>${t('no-item-figures')}</p>` : nothing}\n <table>\n <thead>\n <tr>\n <th>${t('code')}</th>\n <th>${t('name')}</th>\n <th>${t('figure')}</th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n ${this.rows.map((row, i) => this.renderRow(row, i, issues.get(i) ?? []))}\n </tbody>\n </table>\n <button add @click=${this.onAdd}><md-icon>add</md-icon>${t('add')}</button>\n </div>\n <div class=\"footer\">\n <div summary>${issues.size ? t('fix-rows', { count: issues.size }) : nothing}</div>\n <button @click=${this.onCancel} danger><md-icon>cancel</md-icon>${i18next.t('button.cancel')}</button>\n <button @click=${this.onConfirm} ?disabled=${issues.size > 0} done><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>\n </div>\n `\n }\n\n private renderRow(row: ItemTypeRow, i: number, issues: ItemTypeIssue[]) {\n const figures = this.figures ?? []\n const chosen = figures.find(f => f.name === row.figure)\n /* A figure written before that the library no longer marks as an item: kept as written, and told. */\n const unmarked = !!row.figure && this.figures !== null && !chosen\n return html`<tr>\n <td><input .value=${row.code} data-row=${i} data-key=\"code\" @input=${this.onInput} /></td>\n <td><input .value=${row.name} data-row=${i} data-key=\"name\" @input=${this.onInput} /></td>\n <td figure>\n ${chosen?.thumbnail && !this.unreadThumbnails.has(chosen.thumbnail)\n ? html`<img src=${chosen.thumbnail} alt=\"\" @error=${() => (this.unreadThumbnails = new Set([...this.unreadThumbnails, chosen.thumbnail]))} />`\n : html`<span no-thumb></span>`}\n <select data-row=${i} data-key=\"figure\" @change=${this.onInput}>\n <option value=\"\" ?selected=${!row.figure}>${t('figure-none')}</option>\n ${unmarked ? html`<option value=${row.figure} selected>${row.figure}</option>` : nothing}\n ${figures.map(f => html`<option value=${f.name} ?selected=${f.name === row.figure}>${f.label}</option>`)}\n </select>\n </td>\n <td note>\n ${issues.map(issue => html`<div issue>${this.issueText(issue)}</div>`)}\n ${unmarked ? html`<div warning>${t('figure-not-item')}</div>` : nothing}\n </td>\n <td><button remove title=${t('remove')} data-row=${i} @click=${this.onRemove}><md-icon>delete</md-icon></button></td>\n </tr>`\n }\n\n private issueText(issue: ItemTypeIssue): string {\n if (issue.code === 'item-type-duplicate') return t('issue.duplicate', { rows: issue.at.map(n => n + 1).join(', ') })\n return t(`issue.${issue.code.replace('item-type-', '')}`)\n }\n\n private onInput(e: Event) {\n const input = e.target as HTMLInputElement | HTMLSelectElement\n const i = Number(input.dataset.row)\n const key = input.dataset.key as keyof ItemTypeRow\n this.rows = this.rows.map((r, n) => (n === i ? { ...r, [key]: input.value } : r))\n }\n\n private onAdd() {\n this.rows = [...this.rows, emptyRow()]\n }\n\n private onRemove(e: Event) {\n const i = Number((e.currentTarget as HTMLElement).dataset.row)\n this.rows = this.rows.filter((_, n) => n !== i)\n }\n\n private onCancel() {\n closePopup(this)\n }\n\n private onConfirm() {\n if (rowIssues(this.rows).size) return\n this.confirmCallback?.(this.rows)\n closePopup(this)\n }\n\n /** The names the domain's library marks as items, by display name. None when the library cannot be read. */\n private async fetchFigures() {\n try {\n const { data } = await client.query({\n query: ITEM_FIGURES,\n variables: { filters: [{ name: 'item', operator: 'eq', value: true }], pagination: { page: 1, limit: ITEM_FIGURE_LIMIT } },\n fetchPolicy: 'network-only'\n })\n const { contextPath } = getPathInfo(location.pathname)\n this.figures = (data?.figureLibraryFigures?.items ?? [])\n .map((item: any) => {\n const hash = item.release?.dependencies?.find((d: any) => d.role === 'thumbnail')?.hash\n const display = item.release?.name\n return {\n name: item.name,\n label: display && display !== item.name ? `${display} — ${item.name}` : item.name,\n thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : ''\n }\n })\n .sort((a: ItemFigure, b: ItemFigure) => a.label.localeCompare(b.label))\n } catch {\n this.figures = []\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-item-types-input.js","sourceRoot":"","sources":["../../client/item-types/ox-item-types-input.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The item type table of a domain (ADR-0155), edited in a popup from a theme of type item-types (fmsim: carrier-types):\n * one row per type -- code, name, the figure it is drawn by. A type has no size; an item is drawn at the size of the\n * place it sits in (amendment 1). The figure is chosen from the names the domain's library marks as items (amendment\n * 1 E · F), shown with their thumbnails. What does not hold is said on its row by things-scene's rule and the table is\n * not confirmed until it holds; a figure written before that is no longer marked is told on its row and does not stop it.\n *\n * The words are the module's translations; an app whose items are called otherwise (fmsim: carriers) says them its own way.\n */\nimport '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/icon/icon.js'\nimport '@operato/popup/ox-popup-actions.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport { CommonPopupStyles, FormFieldStyles, PopupBodyStyles } from '@operato/styles'\nimport { getPathInfo } from '@operato/utils'\nimport type { ItemTypeIssue } from '@hatiolab/things-scene'\n\nimport { emptyRow, figureChoiceLabels, rowIssues, type ItemTypeRow } from './item-types-rows.js'\n\n/* The names the domain draws as items, with the name and thumbnail of the release each draws with. */\nconst ITEM_FIGURES = gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n figureLibraryFigures(filters: $filters, pagination: $pagination) {\n items {\n name\n release {\n name\n dependencies\n }\n }\n }\n }\n`\n\n/** As many item figures as one domain is expected to have; the picker lists them all. */\nconst ITEM_FIGURE_LIMIT = 500\n\ninterface ItemFigure {\n name: string\n label: string\n thumbnail: string\n}\n\nconst t = (key: string, options?: Record<string, unknown>) => i18next.t(`figure-library.item-types.${key}`, options)\n\n/*\n * The house popup (operato-application design/ui/page-standard.md 7 · 8): CommonPopupStyles' card, only the body\n * scrolls (PopupBodyStyles), native fields at the table height (FormFieldStyles small), each row's problems right under\n * it, the row's own button at its end, and cancel · confirm in ox-popup-actions.\n */\n@customElement('ox-item-types-input')\nexport class OxItemTypesInput extends LitElement {\n static styles = [\n CommonPopupStyles,\n PopupBodyStyles,\n FormFieldStyles,\n css`\n :host {\n width: 100%;\n height: 100%;\n max-height: none;\n --popup-min-width: 0;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n }\n th {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--ui-bg, #ffffff);\n text-align: left;\n font-weight: normal;\n font-size: var(--popup-font-size-small);\n color: var(--ui-muted, #57676f);\n padding: 0 var(--spacing-small, 4px) var(--spacing-small, 4px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n white-space: nowrap;\n }\n td {\n padding: var(--spacing-small, 4px);\n vertical-align: middle;\n }\n tr[type] td {\n border-top: 1px solid var(--ui-line-soft, #eef1f3);\n }\n tr[issues] td {\n padding-top: 0;\n }\n /*\n Widths by what they hold (page-standard 7): a code is an identifier such as FORMATION_TRAY, wider than a\n quantity; a type's name is a few words; the figure takes the rest.\n */\n th[code],\n td[code] {\n width: 160px;\n }\n th[name],\n td[name] {\n width: 200px;\n }\n input,\n select {\n width: 100%;\n }\n td[thumb] {\n width: 32px;\n padding-right: 0;\n }\n [thumb] img,\n [thumb] [no-thumb] {\n display: grid;\n place-items: center;\n box-sizing: border-box;\n width: 32px;\n height: 32px;\n object-fit: contain;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: var(--md-sys-color-surface-container, #eef1f3);\n color: var(--ui-muted, #57676f);\n --md-icon-size: 16px;\n }\n td[end] {\n width: 1%;\n text-align: right;\n }\n /* A row's own button: quiet, an icon with its name in the tooltip (page-standard 8). */\n button[quiet] {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n height: var(--form-element-height-small, 26px);\n padding: 0 var(--spacing-small, 4px);\n border: 0;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: transparent;\n color: var(--ui-muted, #57676f);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n --md-icon-size: 16px;\n }\n button[quiet]:hover {\n background: var(--ui-line-soft, #eef1f3);\n color: var(--ui-ink, #17242c);\n }\n button[quiet][add] md-icon {\n color: var(--md-sys-color-primary);\n }\n [issue] {\n color: var(--ui-crit, var(--md-sys-color-error));\n font-size: var(--popup-font-size-small);\n }\n [warning] {\n color: var(--ui-muted, #57676f);\n font-size: var(--popup-font-size-small);\n }\n `\n ]\n\n /** The rows as typed; the popup's own copy (see the note in ox-popup-value-map-input on re-rendered popups). */\n @property({ type: Array }) rows: ItemTypeRow[] = []\n @property({ type: Object }) confirmCallback?: (rows: ItemTypeRow[]) => void\n\n /** The domain's item figures; null until they are read, empty when the library cannot be read or marks none. */\n @state() private figures: ItemFigure[] | null = null\n /** Thumbnails that could not be drawn: the empty mark in their place, not a broken image. */\n @state() private unreadThumbnails = new Set<string>()\n\n connectedCallback() {\n super.connectedCallback()\n this.fetchFigures()\n }\n\n render() {\n const issues = rowIssues(this.rows)\n return html`\n <div class=\"body\">\n ${this.figures?.length === 0 ? html`<div class=\"note\">${t('no-item-figures')}</div>` : nothing}\n <table>\n <thead>\n <tr>\n <th></th>\n <th code>${t('code')}</th>\n <th name>${t('name')}</th>\n <th>${t('figure')}</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n ${this.rows.map((row, i) => this.renderRow(row, i, issues.get(i) ?? []))}\n <tr>\n <td></td>\n <td colspan=\"4\"><button quiet add @click=${this.onAdd}><md-icon>add</md-icon>${t('add')}</button></td>\n </tr>\n </tbody>\n </table>\n ${issues.size ? html`<div class=\"failure\">${t('fix-rows', { count: issues.size })}</div>` : nothing}\n </div>\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${this.onCancel}>${i18next.t('button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" ?disabled=${issues.size > 0} @click=${this.onConfirm}>${i18next.t('button.confirm')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n private renderRow(row: ItemTypeRow, i: number, issues: ItemTypeIssue[]) {\n const figures = this.figures ?? []\n const chosen = figures.find(f => f.name === row.figure)\n /* A figure written before that the library no longer marks as an item: kept as written, and told. */\n const unmarked = !!row.figure && this.figures !== null && !chosen\n const thumbnail = chosen?.thumbnail && !this.unreadThumbnails.has(chosen.thumbnail) ? chosen.thumbnail : ''\n return html`\n <tr type>\n <td thumb>\n ${thumbnail\n ? html`<img src=${thumbnail} alt=\"\" @error=${() => (this.unreadThumbnails = new Set([...this.unreadThumbnails, thumbnail]))} />`\n : html`<span no-thumb title=${row.figure ? t('no-thumbnail') : t('figure-none')}>\n <md-icon>${row.figure ? 'image_not_supported' : 'inventory_2'}</md-icon>\n </span>`}\n </td>\n <td code><input small .value=${row.code} data-row=${i} data-key=\"code\" @input=${this.onInput} /></td>\n <td name><input small .value=${row.name} data-row=${i} data-key=\"name\" @input=${this.onInput} /></td>\n <td>\n <select small data-row=${i} data-key=\"figure\" title=${row.figure} @change=${this.onInput}>\n <option value=\"\" ?selected=${!row.figure}>${t('figure-none')}</option>\n ${unmarked ? html`<option value=${row.figure} selected>${row.figure}</option>` : nothing}\n ${figures.map(f => html`<option value=${f.name} ?selected=${f.name === row.figure}>${f.label}</option>`)}\n </select>\n </td>\n <td end>\n <button quiet remove title=${t('remove')} aria-label=${t('remove')} data-row=${i} @click=${this.onRemove}><md-icon>delete</md-icon></button>\n </td>\n </tr>\n ${issues.length || unmarked\n ? html`<tr issues>\n <td></td>\n <td colspan=\"4\">\n ${issues.map(issue => html`<div issue>${this.issueText(issue)}</div>`)}\n ${unmarked ? html`<div warning>${t('figure-not-item')}</div>` : nothing}\n </td>\n </tr>`\n : nothing}\n `\n }\n\n /* A code that does not hold is invalid to the browser too: the shared field style outlines it once it is typed in (:user-invalid). */\n updated() {\n const issues = rowIssues(this.rows)\n this.renderRoot.querySelectorAll<HTMLInputElement>('input[data-key=\"code\"]').forEach(input => {\n const row = issues.get(Number(input.dataset.row))\n input.setCustomValidity(row?.length ? this.issueText(row[0]) : '')\n })\n }\n\n private issueText(issue: ItemTypeIssue): string {\n if (issue.code === 'item-type-duplicate') return t('issue.duplicate', { rows: issue.at.map(n => n + 1).join(', ') })\n return t(`issue.${issue.code.replace('item-type-', '')}`)\n }\n\n private onInput(e: Event) {\n const input = e.target as HTMLInputElement | HTMLSelectElement\n const i = Number(input.dataset.row)\n const key = input.dataset.key as keyof ItemTypeRow\n this.rows = this.rows.map((r, n) => (n === i ? { ...r, [key]: input.value } : r))\n }\n\n private onAdd() {\n this.rows = [...this.rows, emptyRow()]\n }\n\n private onRemove(e: Event) {\n const i = Number((e.currentTarget as HTMLElement).dataset.row)\n this.rows = this.rows.filter((_, n) => n !== i)\n }\n\n private onCancel() {\n closePopup(this)\n }\n\n private onConfirm() {\n if (rowIssues(this.rows).size) return\n this.confirmCallback?.(this.rows)\n closePopup(this)\n }\n\n /** The names the domain's library marks as items, by display name. None when the library cannot be read. */\n private async fetchFigures() {\n try {\n const { data } = await client.query({\n query: ITEM_FIGURES,\n variables: { filters: [{ name: 'item', operator: 'eq', value: true }], pagination: { page: 1, limit: ITEM_FIGURE_LIMIT } },\n fetchPolicy: 'network-only'\n })\n const { contextPath } = getPathInfo(location.pathname)\n const items = data?.figureLibraryFigures?.items ?? []\n const labels = figureChoiceLabels(items.map((item: any) => ({ name: item.name, display: item.release?.name })))\n this.figures = items\n .map((item: any) => {\n const hash = item.release?.dependencies?.find((d: any) => d.role === 'thumbnail')?.hash\n return { name: item.name, label: labels.get(item.name)!, thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : '' }\n })\n .sort((a: ItemFigure, b: ItemFigure) => a.label.localeCompare(b.label))\n } catch {\n this.figures = []\n }\n }\n}\n"]}
|
|
@@ -263,7 +263,6 @@ let FigureLibraryPage = class FigureLibraryPage extends localize(i18next)(PageVi
|
|
|
263
263
|
.name=${record.name}
|
|
264
264
|
.drawing=${record.release?.id ?? ''}
|
|
265
265
|
.archived=${!!record.archivedAt}
|
|
266
|
-
.item=${!!record.item}
|
|
267
266
|
@saved=${() => this.grist.fetch()}
|
|
268
267
|
></figure-releases-popup>`, {
|
|
269
268
|
backdrop: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-library-page.js","sourceRoot":"","sources":["../../client/pages/figure-library-page.ts"],"names":[],"mappings":";AAAA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,sCAAsC,CAAA;AAC7C,OAAO,gEAAgE,CAAA;AACvE,OAAO,uCAAuC,CAAA;AAC9C,OAAO,uCAAuC,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAE5D,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAW,MAAM,KAAK,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE/D,OAAO,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAClI,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C;;;;;;;;;GASG;AAEH,MAAM,OAAO,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BlB,CAAA;AAED,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;CASjB,CAAA;AAED,0FAA0F;AAC1F,MAAM,IAAI,GAAG,GAAG,CAAA;AAGT,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;IAA3D;;QAmIG,iBAAY,GAAG,KAAK,EAAE,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAe,EAAE,EAAE;YACnF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAClC,KAAK,EAAE,OAAO;gBACd,SAAS,EAAE;oBACT,yEAAyE;oBACzE,OAAO,EAAE,OAAO;yBACb,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;yBAC7H,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;oBAC9H,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;iBAC5B;gBACD,WAAW,EAAE,cAAc;aAC5B,CAAC,CAAA;YACF,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,EAAE,CAAA;QACpG,CAAC,CAAA;IAgFH,CAAC;aA/NQ,WAAM,GAAG;QACd,qBAAqB;QACrB,eAAe;QACf,iBAAiB;QACjB,kBAAkB;QAClB,0GAA0G;QAC1G,iBAAiB;QACjB,GAAG,CAAA;;;;KAIF;KACF,AAZY,CAYZ;IAKD,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC;YACxC,MAAM,EAAE;gBACN,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;gBACpD,OAAO,EAAE,CAAC,MAAc,EAAE,EAAE;oBAC1B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;gBAChC,CAAC;gBACD,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE;aACpC;SACF,CAAA;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA;wDACyC,IAAI,CAAC,WAAW,kBAAkB,IAAI,CAAC,YAAY;;;;;;2BAMhF,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE;wCACV,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;;KAE5E,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,SAAS,EAAE,CAAA;IACxB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,SAAS;QACrB,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAA;QACxD,IAAI,CAAC,WAAW,GAAG;YACjB,IAAI,EAAE;gBACJ,SAAS,EAAE,WAAW;gBACtB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;gBACzB,OAAO,EAAE,EAAE;aACZ;YACD,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;iBAChH;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI;qBAC9E;iBACF;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;iBACxF;gBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;gBAC7F;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;oBAClD,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE;iBAChD;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,YAAY;oBAClB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC;oBACpD,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE;iBAClD;gBACD,6GAA6G;gBAC7G;oBACE,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;oBACnD,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;iBAC3B;gBACD,qGAAqG;gBACrG;oBACE,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;oBAClD,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;oBAC3B,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;iBAC3B;aACF;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE,KAAK;gBACjB,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE;oBACR,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;iBACjF;aACF;YACD,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE;SACpC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;IACtC,CAAC;IAiBD,iEAAiE;IACzD,KAAK,CAAC,MAAM;QAClB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAA;QACnF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,mBAAmB,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAA;QACzF,OAAO;YACL,UAAU,EAAE;gBACV,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxE,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1G;YACD,YAAY,EAAE;gBACZ,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,qBAAqB,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrI,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,mCAAmC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACxG;SACF,CAAA;IACH,CAAC;IAED,wFAAwF;IAChF,WAAW,CAAC,MAAW;QAC7B,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,IAAI,CAAA;QAC9G,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACtD,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QAC3C,OAAO,IAAI,CAAA;YACH,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;YACxD,CAAC,MAAM,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,CAAC,EAAE,IAAI,IAAI,EAAE;cAC7C,KAAK;aACN,IAAI;;+CAE8B,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC;qBACvE,CAAA;IACnB,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,MAAW;QAC1B,IAAI,MAAM,EAAE,UAAU;YAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,OAAO,CAAC,CAAA;QACnF,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,CAAA;QAC/B,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwC,CAAC,EAAE,MAAM,CAAC,CAAA;QAClF,IAAI,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC,aAAa;YAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,EAAE,MAAM,CAAC,CAAA;QAC1G,IAAI,OAAO,CAAC,UAAU;YAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,EAAE,OAAO,CAAC,CAAA;QACrF,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IACtB,CAAC;IAED,sIAAsI;IAC9H,MAAM,CAAC,MAAW;QACxB,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,MAAM,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAA;QAC7G,OAAO,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IACnF,CAAC;IAEO,YAAY,CAAC,MAAW;QAC9B,SAAS,CACP,IAAI,CAAA;gBACM,MAAM,CAAC,IAAI;mBACR,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE;oBACvB,CAAC,CAAC,MAAM,CAAC,UAAU;gBACvB,CAAC,CAAC,MAAM,CAAC,IAAI;iBACZ,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;gCACT,EAC1B;YACE,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,kCAAkC,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;SACnI,CACF,CAAA;IACH,CAAC;IAEO,UAAU;QAChB,SAAS,CACP,IAAI,CAAA;oBACU,KAAK,IAAI,EAAE;YACrB,MAAM,IAAI,CAAC,SAAS,EAAE,CAAA;YACtB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC;gCACuB,EAC1B,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,CACpG,CAAA;IACH,CAAC;;AAhNgB;IAAhB,KAAK,EAAE;;sDAAyB;AACN;IAA1B,KAAK,CAAC,UAAU,CAAC;8BAAiB,SAAS;gDAAA;AAhBjC,iBAAiB;IAD7B,aAAa,CAAC,qBAAqB,CAAC;GACxB,iBAAiB,CAgO7B","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-card-thumb.js'\nimport '@things-factory/figure-viewer/dist-client/figure-thumb-mark.js'\nimport '../viewparts/figure-releases-popup.js'\nimport '../viewparts/figure-package-import.js'\nimport { versionText } from '../viewparts/figure-version.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { openPopup } from '@operato/popup'\nimport { PageView } from '@operato/shell'\nimport { CardCatalogStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { getPathInfo } from '@operato/utils'\n\n/*\n * The board server's figures (ADR-0114, amended 2026-10-12), as a card catalogue with the board catalog's card: the\n * thumbnail, the name, and one line - the full name and the version it draws with. The one thing to know before opening\n * a card is its corner marker: cannot be read here, not drawing the latest, or deprecated. Clicking a card opens its\n * releases side by side to compare them and choose the one it draws with.\n *\n * The library is expected to grow to many figures, so the list pages from the server and the filters (category,\n * capability) are drop-down lists in the filter bar beside the name search. Upload, the screen's one primary action, is\n * the FAB; it opens a popup whose drop box takes the package and says what it came to.\n */\n\nconst FIGURES = gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: figureLibraryFigures(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n name\n archivedAt\n item\n latestVersion\n releaseCount\n release {\n id\n name\n version\n category\n capabilities\n formatSupported\n deprecated\n dependencies\n }\n latest {\n id\n name\n version\n formatSupported\n dependencies\n }\n }\n total\n }\n }\n`\n\nconst FACETS = gql`\n query {\n figureLibraryFacets {\n categories\n uncategorized\n capabilities\n incapable\n }\n }\n`\n\n/** The filter value for a figure with no category, or one that declares no capability. */\nconst NONE = '-'\n\n@customElement('figure-library-page')\nexport class FigureLibraryPage extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n /* The card, its picture cell and the upload FAB: every card catalog's (ADR-0117 amendment 2026-10-13). */\n CardCatalogStyles,\n css`\n ox-filters-form {\n flex: 1;\n }\n `\n ]\n\n @state() private gristConfig: any\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('figure-library.title'),\n search: {\n placeholder: i18next.t('figure-library.text.search'),\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n }\n }\n }\n\n render() {\n return html`\n <ox-grist class=\"page-fill\" mode=\"CARD\" .config=${this.gristConfig} .fetchHandler=${this.fetchHandler}>\n <div slot=\"headroom\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n </div>\n </ox-grist>\n\n <button fab @click=${() => this.openImport()}>\n <md-icon>upload_file</md-icon>${i18next.t('figure-library.button.upload')}\n </button>\n `\n }\n\n async pageInitialized() {\n await this.configure()\n }\n\n /*\n * The filter options are read once here (and again after an import), never per render: an async options function\n * runs on every render of the filter bar and replaces the open list's options under the pointer.\n */\n private async configure() {\n const { categories, capabilities } = await this.facets()\n this.gristConfig = {\n list: {\n thumbnail: 'thumbnail',\n fields: ['title', 'meta'],\n details: []\n },\n columns: [\n {\n type: 'image',\n name: 'thumbnail',\n record: { editable: false, renderEmpty: true, renderer: (_value, _column, record) => this.thumbnailOf(record) }\n },\n {\n type: 'string',\n name: 'title',\n record: {\n editable: false,\n renderer: (_value, _column, record) => (record.release ?? record.latest).name\n }\n },\n {\n type: 'string',\n name: 'meta',\n record: { editable: false, renderer: (_value, _column, record) => this.metaOf(record) }\n },\n { type: 'string', name: 'name', hidden: true, record: { editable: false }, filter: 'search' },\n {\n type: 'select',\n name: 'category',\n header: i18next.t('figure-library.label.category'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq', options: categories }\n },\n {\n type: 'select',\n name: 'capability',\n header: i18next.t('figure-library.label.capability'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq', options: capabilities }\n },\n /* Only the names this domain draws as items (ADR-0155 개정 1 E): what an item type table picks a look from. */\n {\n type: 'boolean',\n name: 'item',\n header: i18next.t('figure-library.label.item-only'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq' }\n },\n /* Archived figures are left out unless this box is checked (ADR-0114 결정 18, 화면; user 2026-10-22). */\n {\n type: 'boolean',\n name: 'archived',\n header: i18next.t('figure-library.label.archived'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq' }\n }\n ],\n rows: {\n selectable: false,\n appendable: false,\n handlers: {\n click: (_columns, _data, _column, record) => record && this.openReleases(record)\n }\n },\n pagination: { pages: [24, 48, 96] }\n }\n }\n\n async pageUpdated() {\n if (this.active) this.grist?.fetch()\n }\n\n private fetchHandler = async ({ page = 1, limit = 24, filters = [] }: FetchOption) => {\n const response = await client.query({\n query: FIGURES,\n variables: {\n /* The name search arrives as %text%; the server matches parts itself. */\n filters: filters\n .filter(filter => filter.value !== undefined && filter.value !== '' && !(Array.isArray(filter.value) && !filter.value.length))\n .map(filter => ({ ...filter, value: typeof filter.value === 'string' ? filter.value.replace(/^%|%$/g, '') : filter.value })),\n pagination: { page, limit }\n },\n fetchPolicy: 'network-only'\n })\n return { total: response.data.responses.total || 0, records: response.data.responses.items || [] }\n }\n\n /** The filter options, from what the figures that draw carry. */\n private async facets() {\n const response = await client.query({ query: FACETS, fetchPolicy: 'network-only' })\n const facets = response.data?.figureLibraryFacets ?? { categories: [], capabilities: [] }\n return {\n categories: [\n ...facets.categories.map((value: string) => ({ display: value, value })),\n ...(facets.uncategorized ? [{ display: i18next.t('figure-library.text.no-category'), value: NONE }] : [])\n ],\n capabilities: [\n ...facets.capabilities.map((value: string) => ({ display: i18next.t(`figure.label.role-${value}`, { defaultValue: value }), value })),\n ...(facets.incapable ? [{ display: i18next.t('figure-library.text.no-capability'), value: NONE }] : [])\n ]\n }\n }\n\n /** The picture cell every catalog card draws, with the one marker this figure needs. */\n private thumbnailOf(record: any) {\n const hash = (record?.release ?? record?.latest)?.dependencies?.find((d: any) => d.role === 'thumbnail')?.hash\n const { contextPath } = getPathInfo(location.pathname)\n const [badge, tone] = this.markerOf(record)\n return html`<ox-card-thumb\n src=${hash ? `${contextPath}/figure-library-file/${hash}` : ''}\n alt=${(record?.release ?? record?.latest)?.name ?? ''}\n badge=${badge}\n tone=${tone}\n >\n <figure-thumb-mark slot=\"empty\" .label=${i18next.t('figure-library.text.no-thumbnail')}></figure-thumb-mark>\n </ox-card-thumb>`\n }\n\n /**\n * The one thing a card says before it is opened, the gravest first: it is archived, nothing here can draw it, it does\n * not draw its latest release, or the release it draws is deprecated. A figure drawing its latest says nothing.\n */\n private markerOf(record: any): [string, 'plain' | 'warn' | 'crit'] {\n if (record?.archivedAt) return [i18next.t('figure-library.text.archived'), 'plain']\n const release = record?.release\n if (!release) return [i18next.t('figure-library.text.format-unsupported'), 'crit']\n if (release.version !== record.latestVersion) return [i18next.t('figure-library.text.not-latest'), 'warn']\n if (release.deprecated) return [i18next.t('figure-library.text.deprecated'), 'plain']\n return ['', 'plain']\n }\n\n /** The line under the name: the full name and the version it draws with, as a board card's 「v1 · 3일 전」, and whether it is an item. */\n private metaOf(record: any): string {\n const line = record?.release ? `${record.name} · ${versionText(record.release.version)}` : record?.name ?? ''\n return record?.item ? `${line} · ${i18next.t('figure-library.text.item')}` : line\n }\n\n private openReleases(record: any) {\n openPopup(\n html`<figure-releases-popup\n .name=${record.name}\n .drawing=${record.release?.id ?? ''}\n .archived=${!!record.archivedAt}\n .item=${!!record.item}\n @saved=${() => this.grist.fetch()}\n ></figure-releases-popup>`,\n {\n backdrop: true,\n size: 'large',\n title: i18next.t('figure-library.title.releases-of', { name: (record.release ?? record.latest).name, count: record.releaseCount })\n }\n )\n }\n\n private openImport() {\n openPopup(\n html`<figure-package-import\n @imported=${async () => {\n await this.configure()\n this.grist.fetch()\n }}\n ></figure-package-import>`,\n { backdrop: true, size: 'small', closable: true, title: i18next.t('figure-library.button.upload') }\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-library-page.js","sourceRoot":"","sources":["../../client/pages/figure-library-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/data-grist/ox-card-thumb.js'\nimport '@things-factory/figure-viewer/dist-client/figure-thumb-mark.js'\nimport '../viewparts/figure-releases-popup.js'\nimport '../viewparts/figure-package-import.js'\nimport { versionText } from '../viewparts/figure-version.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { openPopup } from '@operato/popup'\nimport { PageView } from '@operato/shell'\nimport { CardCatalogStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { getPathInfo } from '@operato/utils'\n\n/*\n * The board server's figures (ADR-0114, amended 2026-10-12), as a card catalogue with the board catalog's card: the\n * thumbnail, the name, and one line - the full name and the version it draws with. The one thing to know before opening\n * a card is its corner marker: cannot be read here, not drawing the latest, or deprecated. Clicking a card opens its\n * releases side by side to compare them and choose the one it draws with.\n *\n * The library is expected to grow to many figures, so the list pages from the server and the filters (category,\n * capability) are drop-down lists in the filter bar beside the name search. Upload, the screen's one primary action, is\n * the FAB; it opens a popup whose drop box takes the package and says what it came to.\n */\n\nconst FIGURES = gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: figureLibraryFigures(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n name\n archivedAt\n item\n latestVersion\n releaseCount\n release {\n id\n name\n version\n category\n capabilities\n formatSupported\n deprecated\n dependencies\n }\n latest {\n id\n name\n version\n formatSupported\n dependencies\n }\n }\n total\n }\n }\n`\n\nconst FACETS = gql`\n query {\n figureLibraryFacets {\n categories\n uncategorized\n capabilities\n incapable\n }\n }\n`\n\n/** The filter value for a figure with no category, or one that declares no capability. */\nconst NONE = '-'\n\n@customElement('figure-library-page')\nexport class FigureLibraryPage extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n /* The card, its picture cell and the upload FAB: every card catalog's (ADR-0117 amendment 2026-10-13). */\n CardCatalogStyles,\n css`\n ox-filters-form {\n flex: 1;\n }\n `\n ]\n\n @state() private gristConfig: any\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('figure-library.title'),\n search: {\n placeholder: i18next.t('figure-library.text.search'),\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n }\n }\n }\n\n render() {\n return html`\n <ox-grist class=\"page-fill\" mode=\"CARD\" .config=${this.gristConfig} .fetchHandler=${this.fetchHandler}>\n <div slot=\"headroom\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n </div>\n </ox-grist>\n\n <button fab @click=${() => this.openImport()}>\n <md-icon>upload_file</md-icon>${i18next.t('figure-library.button.upload')}\n </button>\n `\n }\n\n async pageInitialized() {\n await this.configure()\n }\n\n /*\n * The filter options are read once here (and again after an import), never per render: an async options function\n * runs on every render of the filter bar and replaces the open list's options under the pointer.\n */\n private async configure() {\n const { categories, capabilities } = await this.facets()\n this.gristConfig = {\n list: {\n thumbnail: 'thumbnail',\n fields: ['title', 'meta'],\n details: []\n },\n columns: [\n {\n type: 'image',\n name: 'thumbnail',\n record: { editable: false, renderEmpty: true, renderer: (_value, _column, record) => this.thumbnailOf(record) }\n },\n {\n type: 'string',\n name: 'title',\n record: {\n editable: false,\n renderer: (_value, _column, record) => (record.release ?? record.latest).name\n }\n },\n {\n type: 'string',\n name: 'meta',\n record: { editable: false, renderer: (_value, _column, record) => this.metaOf(record) }\n },\n { type: 'string', name: 'name', hidden: true, record: { editable: false }, filter: 'search' },\n {\n type: 'select',\n name: 'category',\n header: i18next.t('figure-library.label.category'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq', options: categories }\n },\n {\n type: 'select',\n name: 'capability',\n header: i18next.t('figure-library.label.capability'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq', options: capabilities }\n },\n /* Only the names this domain draws as items (ADR-0155 개정 1 E): what an item type table picks a look from. */\n {\n type: 'boolean',\n name: 'item',\n header: i18next.t('figure-library.label.item-only'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq' }\n },\n /* Archived figures are left out unless this box is checked (ADR-0114 결정 18, 화면; user 2026-10-22). */\n {\n type: 'boolean',\n name: 'archived',\n header: i18next.t('figure-library.label.archived'),\n hidden: true,\n record: { editable: false },\n filter: { operator: 'eq' }\n }\n ],\n rows: {\n selectable: false,\n appendable: false,\n handlers: {\n click: (_columns, _data, _column, record) => record && this.openReleases(record)\n }\n },\n pagination: { pages: [24, 48, 96] }\n }\n }\n\n async pageUpdated() {\n if (this.active) this.grist?.fetch()\n }\n\n private fetchHandler = async ({ page = 1, limit = 24, filters = [] }: FetchOption) => {\n const response = await client.query({\n query: FIGURES,\n variables: {\n /* The name search arrives as %text%; the server matches parts itself. */\n filters: filters\n .filter(filter => filter.value !== undefined && filter.value !== '' && !(Array.isArray(filter.value) && !filter.value.length))\n .map(filter => ({ ...filter, value: typeof filter.value === 'string' ? filter.value.replace(/^%|%$/g, '') : filter.value })),\n pagination: { page, limit }\n },\n fetchPolicy: 'network-only'\n })\n return { total: response.data.responses.total || 0, records: response.data.responses.items || [] }\n }\n\n /** The filter options, from what the figures that draw carry. */\n private async facets() {\n const response = await client.query({ query: FACETS, fetchPolicy: 'network-only' })\n const facets = response.data?.figureLibraryFacets ?? { categories: [], capabilities: [] }\n return {\n categories: [\n ...facets.categories.map((value: string) => ({ display: value, value })),\n ...(facets.uncategorized ? [{ display: i18next.t('figure-library.text.no-category'), value: NONE }] : [])\n ],\n capabilities: [\n ...facets.capabilities.map((value: string) => ({ display: i18next.t(`figure.label.role-${value}`, { defaultValue: value }), value })),\n ...(facets.incapable ? [{ display: i18next.t('figure-library.text.no-capability'), value: NONE }] : [])\n ]\n }\n }\n\n /** The picture cell every catalog card draws, with the one marker this figure needs. */\n private thumbnailOf(record: any) {\n const hash = (record?.release ?? record?.latest)?.dependencies?.find((d: any) => d.role === 'thumbnail')?.hash\n const { contextPath } = getPathInfo(location.pathname)\n const [badge, tone] = this.markerOf(record)\n return html`<ox-card-thumb\n src=${hash ? `${contextPath}/figure-library-file/${hash}` : ''}\n alt=${(record?.release ?? record?.latest)?.name ?? ''}\n badge=${badge}\n tone=${tone}\n >\n <figure-thumb-mark slot=\"empty\" .label=${i18next.t('figure-library.text.no-thumbnail')}></figure-thumb-mark>\n </ox-card-thumb>`\n }\n\n /**\n * The one thing a card says before it is opened, the gravest first: it is archived, nothing here can draw it, it does\n * not draw its latest release, or the release it draws is deprecated. A figure drawing its latest says nothing.\n */\n private markerOf(record: any): [string, 'plain' | 'warn' | 'crit'] {\n if (record?.archivedAt) return [i18next.t('figure-library.text.archived'), 'plain']\n const release = record?.release\n if (!release) return [i18next.t('figure-library.text.format-unsupported'), 'crit']\n if (release.version !== record.latestVersion) return [i18next.t('figure-library.text.not-latest'), 'warn']\n if (release.deprecated) return [i18next.t('figure-library.text.deprecated'), 'plain']\n return ['', 'plain']\n }\n\n /** The line under the name: the full name and the version it draws with, as a board card's 「v1 · 3일 전」, and whether it is an item. */\n private metaOf(record: any): string {\n const line = record?.release ? `${record.name} · ${versionText(record.release.version)}` : record?.name ?? ''\n return record?.item ? `${line} · ${i18next.t('figure-library.text.item')}` : line\n }\n\n private openReleases(record: any) {\n openPopup(\n html`<figure-releases-popup\n .name=${record.name}\n .drawing=${record.release?.id ?? ''}\n .archived=${!!record.archivedAt}\n @saved=${() => this.grist.fetch()}\n ></figure-releases-popup>`,\n {\n backdrop: true,\n size: 'large',\n title: i18next.t('figure-library.title.releases-of', { name: (record.release ?? record.latest).name, count: record.releaseCount })\n }\n )\n }\n\n private openImport() {\n openPopup(\n html`<figure-package-import\n @imported=${async () => {\n await this.configure()\n this.grist.fetch()\n }}\n ></figure-package-import>`,\n { backdrop: true, size: 'small', closable: true, title: i18next.t('figure-library.button.upload') }\n )\n }\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { type LookInput, type StatusIssue, type StatusLooks } from './status-looks.js';
|
|
3
|
+
/**
|
|
4
|
+
* A status template's looks, one card per code (ADR-0051 2.3): its colour, its effect, a value for each state input a
|
|
5
|
+
* figure's port offers -- with the input's name, unit and range -- and the clip of the port's motion group. The code the
|
|
6
|
+
* data gives now is marked; a part the figure did not take is said under the card, by the field that gave it. Every
|
|
7
|
+
* change sends `looks-change` with the whole looks; the host writes them where the template lives.
|
|
8
|
+
*
|
|
9
|
+
* A value outside its input's range is not taken from the field (as the property panel's number maps); a value written
|
|
10
|
+
* elsewhere that the figure refused shows with the reason, to be fixed here. Values for inputs not shown -- another
|
|
11
|
+
* figure's, in a table shared by many -- are kept as they are.
|
|
12
|
+
*
|
|
13
|
+
* Shared by the board's 「상태 표현」 section and fmsim's legend editor, which shows colour and values only.
|
|
14
|
+
*/
|
|
15
|
+
export declare class OxFigureStatusLooks extends LitElement {
|
|
16
|
+
static styles: import("lit").CSSResult;
|
|
17
|
+
looks: StatusLooks;
|
|
18
|
+
/** The state inputs shown, one field each: the figure's offered inputs, or those a legend gives values to. */
|
|
19
|
+
inputs: LookInput[];
|
|
20
|
+
/** Inputs that can be added as a field (a legend's editor: the inputs the carrier figures offer). */
|
|
21
|
+
addable: LookInput[];
|
|
22
|
+
/**
|
|
23
|
+
* Whether every input a look gives a value to has a field, offered or not: a legend, which no one figure reads. A
|
|
24
|
+
* figure's own section leaves the values of inputs it does not offer to the figures that do.
|
|
25
|
+
*/
|
|
26
|
+
showGiven: boolean;
|
|
27
|
+
/** The clips a look may choose; none, no clip field. */
|
|
28
|
+
clips: string[];
|
|
29
|
+
effects: boolean;
|
|
30
|
+
/** Whether a look may give no colour (a board's template); a legend's entry always has one. */
|
|
31
|
+
colorOptional: boolean;
|
|
32
|
+
/** The colour a new code starts with (a legend's entry has one from the start). */
|
|
33
|
+
defaultColor?: string;
|
|
34
|
+
/** The rows the data gives now, with the ports that read them. */
|
|
35
|
+
now: Record<string, string[]>;
|
|
36
|
+
/** What the figure did not take, by row. */
|
|
37
|
+
issues: Map<string, StatusIssue[]>;
|
|
38
|
+
disabled: boolean;
|
|
39
|
+
private added;
|
|
40
|
+
private newCode;
|
|
41
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
42
|
+
/** The inputs shown: those given, those added here, and, with `showGiven`, any a look gives a value to. */
|
|
43
|
+
private shownInputs;
|
|
44
|
+
private renderCard;
|
|
45
|
+
private addCode;
|
|
46
|
+
/** A number in range is taken; an empty field takes the value away (the next source gives it); anything else is not taken. */
|
|
47
|
+
private changeValue;
|
|
48
|
+
private change;
|
|
49
|
+
}
|
|
50
|
+
/** An input as the choice and the tooltip say it: its name, unit and range, and the port that offers it. */
|
|
51
|
+
export declare function describeInput(input: LookInput): string;
|
|
52
|
+
/** Why a part was not taken, in the person's words, with the value refused. */
|
|
53
|
+
export declare function issueSentence(issue: StatusIssue, inputs?: readonly LookInput[]): string;
|
|
54
|
+
declare global {
|
|
55
|
+
interface HTMLElementTagNameMap {
|
|
56
|
+
'ox-figure-status-looks': OxFigureStatusLooks;
|
|
57
|
+
}
|
|
58
|
+
}
|