@things-factory/board-ui 10.1.178 → 10.1.181
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/graphql/attachment.d.ts +3 -1
- package/dist-client/graphql/attachment.js +4 -5
- package/dist-client/graphql/attachment.js.map +1 -1
- package/dist-client/pages/board-create-wizard-page.d.ts +2 -2
- package/dist-client/pages/board-create-wizard-page.js +22 -53
- package/dist-client/pages/board-create-wizard-page.js.map +1 -1
- package/dist-client/pages/board-list-page.d.ts +3 -28
- package/dist-client/pages/board-list-page.js +27 -129
- package/dist-client/pages/board-list-page.js.map +1 -1
- package/dist-client/pages/board-modeller-page.d.ts +5 -1
- package/dist-client/pages/board-modeller-page.js +15 -15
- package/dist-client/pages/board-modeller-page.js.map +1 -1
- package/dist-client/pages/board-viewer-page.d.ts +1 -0
- package/dist-client/pages/board-viewer-page.js +25 -5
- package/dist-client/pages/board-viewer-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -19
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type UploadProgress } from '@operato/graphql';
|
|
1
2
|
export interface AttachmentResult {
|
|
2
3
|
id: string;
|
|
3
4
|
name: string;
|
|
@@ -12,8 +13,9 @@ export interface AttachmentResult {
|
|
|
12
13
|
* file 은 Browser File 객체. 결과로 새 Attachment id / 메타데이터 반환.
|
|
13
14
|
*
|
|
14
15
|
* board-import wizard 가 사용 — 이후 importBoardAsync(attachmentId=result.id) 로 변환 시작.
|
|
16
|
+
* progress 를 주면 올라간 정도(0‒1)를 알려 준다 — 선택기가 그것을 보인다.
|
|
15
17
|
*/
|
|
16
|
-
export declare function createAttachmentForImport(file: File): Promise<AttachmentResult>;
|
|
18
|
+
export declare function createAttachmentForImport(file: File, progress?: UploadProgress): Promise<AttachmentResult>;
|
|
17
19
|
/**
|
|
18
20
|
* 기존 attachment 목록 조회 — wizard upload 스텝의 "기존 파일 선택" 탭에서 사용.
|
|
19
21
|
* 도메인 스코프 내 attachment 만 반환되는 건 attachment-base resolver 가 보장.
|
|
@@ -6,14 +6,15 @@
|
|
|
6
6
|
* → attachmentId 획득 → importBoardAsync 로 전달하는 짧은 흐름만 필요.
|
|
7
7
|
*/
|
|
8
8
|
import gql from 'graphql-tag';
|
|
9
|
-
import { client } from '@operato/graphql';
|
|
9
|
+
import { client, uploadContext } from '@operato/graphql';
|
|
10
10
|
/**
|
|
11
11
|
* 단일 파일을 Attachment 로 등록 — graphql-upload (Apollo client multipart) 사용.
|
|
12
12
|
* file 은 Browser File 객체. 결과로 새 Attachment id / 메타데이터 반환.
|
|
13
13
|
*
|
|
14
14
|
* board-import wizard 가 사용 — 이후 importBoardAsync(attachmentId=result.id) 로 변환 시작.
|
|
15
|
+
* progress 를 주면 올라간 정도(0‒1)를 알려 준다 — 선택기가 그것을 보인다.
|
|
15
16
|
*/
|
|
16
|
-
export async function createAttachmentForImport(file) {
|
|
17
|
+
export async function createAttachmentForImport(file, progress) {
|
|
17
18
|
const response = await client.mutate({
|
|
18
19
|
mutation: gql `
|
|
19
20
|
mutation CreateAttachmentForImport($attachment: NewAttachment!) {
|
|
@@ -36,9 +37,7 @@ export async function createAttachmentForImport(file) {
|
|
|
36
37
|
}
|
|
37
38
|
},
|
|
38
39
|
// multipart 업로드는 Apollo upload-link 가 처리. fetchPolicy 강제 무관.
|
|
39
|
-
context: {
|
|
40
|
-
hasUpload: true
|
|
41
|
-
}
|
|
40
|
+
context: progress ? uploadContext(progress) : { hasUpload: true }
|
|
42
41
|
});
|
|
43
42
|
return response.data.createAttachment;
|
|
44
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../client/graphql/attachment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,GAAG,MAAM,aAAa,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../client/graphql/attachment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,GAAG,MAAM,aAAa,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAuB,MAAM,kBAAkB,CAAA;AAY7E;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,IAAU,EAAE,QAAyB;IACnF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;QACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;;;;;;KAWZ;QACD,SAAS,EAAE;YACT,UAAU,EAAE;gBACV,IAAI;gBACJ,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,cAAc;gBACvB,WAAW,EAAE,4BAA4B;aAC1C;SACF;QACD,6DAA6D;QAC7D,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE;KAClE,CAAC,CAAA;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAA;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,OAK/C;IACC,MAAM,OAAO,GAA6D,EAAE,CAAA;IAC5E,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;IAClF,CAAC;IACD,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,cAAc,GAAG,EAAE,CAAC,CAAA;IAC7F,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;KAeT;QACD,SAAS,EAAE;YACT,OAAO;YACP,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE;YACnE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SAC9C;QACD,WAAW,EAAE,UAAU;KACxB,CAAC,CAAA;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAA;AAClC,CAAC","sourcesContent":["/**\n * Attachment GraphQL operations — board-import wizard 가 도면 파일 업로드 시 사용.\n *\n * 백엔드: @things-factory/attachment-base 의 createAttachment mutation.\n * 별도 ox-attachment-list 의 흐름과 독립 — wizard 는 단순 file input → createAttachment\n * → attachmentId 획득 → importBoardAsync 로 전달하는 짧은 흐름만 필요.\n */\nimport gql from 'graphql-tag'\n\nimport { client, uploadContext, type UploadProgress } from '@operato/graphql'\n\nexport interface AttachmentResult {\n id: string\n name: string\n mimetype?: string\n size?: number\n path?: string\n category?: string\n createdAt?: string\n}\n\n/**\n * 단일 파일을 Attachment 로 등록 — graphql-upload (Apollo client multipart) 사용.\n * file 은 Browser File 객체. 결과로 새 Attachment id / 메타데이터 반환.\n *\n * board-import wizard 가 사용 — 이후 importBoardAsync(attachmentId=result.id) 로 변환 시작.\n * progress 를 주면 올라간 정도(0‒1)를 알려 준다 — 선택기가 그것을 보인다.\n */\nexport async function createAttachmentForImport(file: File, progress?: UploadProgress): Promise<AttachmentResult> {\n const response = await client.mutate({\n mutation: gql`\n mutation CreateAttachmentForImport($attachment: NewAttachment!) {\n createAttachment(attachment: $attachment) {\n id\n name\n mimetype\n size\n path\n category\n }\n }\n `,\n variables: {\n attachment: {\n file,\n category: 'import',\n refType: 'board-import',\n description: 'board-import wizard upload'\n }\n },\n // multipart 업로드는 Apollo upload-link 가 처리. fetchPolicy 강제 무관.\n context: progress ? uploadContext(progress) : { hasUpload: true }\n })\n return response.data.createAttachment\n}\n\n/**\n * 기존 attachment 목록 조회 — wizard upload 스텝의 \"기존 파일 선택\" 탭에서 사용.\n * 도메인 스코프 내 attachment 만 반환되는 건 attachment-base resolver 가 보장.\n *\n * @param search 파일명 부분 일치 (선택)\n * @param mimetypePrefix 'image' | 'application' 등 — wizard 는 이미지/dxf 만 보여주려고 사용\n * @param page / limit 페이지네이션 (기본 1, 50)\n */\nexport async function fetchAttachmentsForImport(options: {\n search?: string\n mimetypePrefix?: string\n page?: number\n limit?: number\n}): Promise<{ items: AttachmentResult[]; total: number }> {\n const filters: Array<{ name: string; operator: string; value: string }> = []\n if (options.search) {\n filters.push({ name: 'name', operator: 'i_like', value: `%${options.search}%` })\n }\n if (options.mimetypePrefix) {\n filters.push({ name: 'mimetype', operator: 'i_like', value: `${options.mimetypePrefix}%` })\n }\n const response = await client.query({\n query: gql`\n query AttachmentsForImport($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n attachments(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n mimetype\n size\n path\n category\n createdAt\n }\n total\n }\n }\n `,\n variables: {\n filters,\n pagination: { page: options.page ?? 1, limit: options.limit ?? 50 },\n sortings: [{ name: 'createdAt', desc: true }]\n },\n fetchPolicy: 'no-cache'\n })\n return response.data.attachments\n}\n"]}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* 기존 파일 (existing) — 이미 업로드된 Attachment 에서 보드 생성.
|
|
8
8
|
*/
|
|
9
9
|
import '@material/web/icon/icon.js';
|
|
10
|
+
import '@operato/input/ox-input-file.js';
|
|
10
11
|
import { type PropertyValues } from 'lit';
|
|
11
12
|
import { PageView } from '@operato/shell';
|
|
12
13
|
import '@operato/board/ox-board-preview.js';
|
|
@@ -21,6 +22,7 @@ export declare class BoardCreateWizardPage extends BoardCreateWizardPage_base {
|
|
|
21
22
|
private _session?;
|
|
22
23
|
/** 현재 업로드 진행 중 — UI lock + spinner. */
|
|
23
24
|
private _uploading;
|
|
25
|
+
private _uploadProgress?;
|
|
24
26
|
/** 업로드 에러 메시지 — UI 표시 + 사용자가 다시 시도 가능. */
|
|
25
27
|
private _uploadError?;
|
|
26
28
|
/** upload 스텝 안의 모드 — 새 파일 업로드 vs 기존 attachment 선택. */
|
|
@@ -97,8 +99,6 @@ export declare class BoardCreateWizardPage extends BoardCreateWizardPage_base {
|
|
|
97
99
|
*/
|
|
98
100
|
private _refreshBrowse;
|
|
99
101
|
private _selectExisting;
|
|
100
|
-
private _onFileChange;
|
|
101
|
-
private _onDrop;
|
|
102
102
|
private _uploadFile;
|
|
103
103
|
private _resetUpload;
|
|
104
104
|
private _proceedToImport;
|
|
@@ -8,6 +8,7 @@ import { __decorate, __metadata } from "tslib";
|
|
|
8
8
|
* 기존 파일 (existing) — 이미 업로드된 Attachment 에서 보드 생성.
|
|
9
9
|
*/
|
|
10
10
|
import '@material/web/icon/icon.js';
|
|
11
|
+
import '@operato/input/ox-input-file.js';
|
|
11
12
|
import { css, html } from 'lit';
|
|
12
13
|
import { customElement, state } from 'lit/decorators.js';
|
|
13
14
|
import { i18next, localize } from '@operato/i18n';
|
|
@@ -186,25 +187,12 @@ let BoardCreateWizardPage = class BoardCreateWizardPage extends localize(i18next
|
|
|
186
187
|
transition: border-color 0.15s, background 0.15s;
|
|
187
188
|
}
|
|
188
189
|
.drop-zone:hover,
|
|
189
|
-
.drop-zone.
|
|
190
|
+
.drop-zone.candrop {
|
|
190
191
|
border-color: var(--md-sys-color-primary, #2a64d8);
|
|
191
192
|
background: var(--md-sys-color-primary-container, #eaf2ff);
|
|
192
193
|
}
|
|
193
|
-
.drop-zone
|
|
194
|
-
|
|
195
|
-
--md-icon-size: 36px;
|
|
196
|
-
opacity: 0.5;
|
|
197
|
-
}
|
|
198
|
-
.drop-zone .title {
|
|
199
|
-
font-size: 15px;
|
|
200
|
-
font-weight: 500;
|
|
201
|
-
}
|
|
202
|
-
.drop-zone .hint {
|
|
203
|
-
font-size: 12px;
|
|
204
|
-
color: var(--md-sys-color-on-secondary-container, #777);
|
|
205
|
-
}
|
|
206
|
-
input[type='file'] {
|
|
207
|
-
display: none;
|
|
194
|
+
.drop-zone {
|
|
195
|
+
--file-uploader-icon-size: 36px;
|
|
208
196
|
}
|
|
209
197
|
|
|
210
198
|
.uploaded {
|
|
@@ -1128,28 +1116,15 @@ let BoardCreateWizardPage = class BoardCreateWizardPage extends localize(i18next
|
|
|
1128
1116
|
}
|
|
1129
1117
|
_renderNewUpload() {
|
|
1130
1118
|
return html `
|
|
1131
|
-
<
|
|
1119
|
+
<ox-input-file
|
|
1132
1120
|
class="drop-zone"
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
}}
|
|
1141
|
-
@drop=${this._onDrop}
|
|
1142
|
-
>
|
|
1143
|
-
<md-icon class="icon">upload</md-icon>
|
|
1144
|
-
<div class="title">${this._uploading ? i18next.t('text.uploading') || 'Uploading...' : i18next.t('text.drop or click to upload') || 'Drop a drawing here or click to browse'}</div>
|
|
1145
|
-
<div class="hint">${ACCEPT}</div>
|
|
1146
|
-
<input
|
|
1147
|
-
type="file"
|
|
1148
|
-
accept=${ACCEPT}
|
|
1149
|
-
?disabled=${this._uploading}
|
|
1150
|
-
@change=${this._onFileChange}
|
|
1151
|
-
/>
|
|
1152
|
-
</label>
|
|
1121
|
+
accept=${ACCEPT}
|
|
1122
|
+
hide-filelist
|
|
1123
|
+
.description=${i18next.t('text.drop or click to upload') || 'Drop a drawing here or click to browse'}
|
|
1124
|
+
.progress=${this._uploadProgress}
|
|
1125
|
+
?disabled=${this._uploading && this._uploadProgress === undefined}
|
|
1126
|
+
@change=${(e) => this._uploadFile(e.detail?.[0])}
|
|
1127
|
+
></ox-input-file>
|
|
1153
1128
|
`;
|
|
1154
1129
|
}
|
|
1155
1130
|
_renderBrowseExisting() {
|
|
@@ -1359,26 +1334,14 @@ let BoardCreateWizardPage = class BoardCreateWizardPage extends localize(i18next
|
|
|
1359
1334
|
this._attachment = item;
|
|
1360
1335
|
this._uploadError = undefined;
|
|
1361
1336
|
}
|
|
1362
|
-
|
|
1363
|
-
const input = e.target;
|
|
1364
|
-
const file = input.files?.[0];
|
|
1365
|
-
if (file)
|
|
1366
|
-
await this._uploadFile(file);
|
|
1367
|
-
// value 초기화 — 같은 파일 재선택 가능
|
|
1368
|
-
input.value = '';
|
|
1369
|
-
}
|
|
1370
|
-
async _onDrop(e) {
|
|
1371
|
-
e.preventDefault();
|
|
1372
|
-
e.currentTarget.classList.remove('dragover');
|
|
1373
|
-
const file = e.dataTransfer?.files?.[0];
|
|
1374
|
-
if (file)
|
|
1375
|
-
await this._uploadFile(file);
|
|
1376
|
-
}
|
|
1337
|
+
/* The picker (ox-input-file) has refused what the server would refuse; what it hands over goes up. */
|
|
1377
1338
|
async _uploadFile(file) {
|
|
1339
|
+
if (!file || this._uploading)
|
|
1340
|
+
return;
|
|
1378
1341
|
this._uploading = true;
|
|
1379
1342
|
this._uploadError = undefined;
|
|
1380
1343
|
try {
|
|
1381
|
-
const result = await createAttachmentForImport(file);
|
|
1344
|
+
const result = await createAttachmentForImport(file, fraction => (this._uploadProgress = fraction));
|
|
1382
1345
|
this._attachment = result;
|
|
1383
1346
|
}
|
|
1384
1347
|
catch (err) {
|
|
@@ -1388,6 +1351,8 @@ let BoardCreateWizardPage = class BoardCreateWizardPage extends localize(i18next
|
|
|
1388
1351
|
}
|
|
1389
1352
|
finally {
|
|
1390
1353
|
this._uploading = false;
|
|
1354
|
+
this._uploadProgress = undefined;
|
|
1355
|
+
this.renderRoot.querySelector('ox-input-file')?.reset();
|
|
1391
1356
|
}
|
|
1392
1357
|
}
|
|
1393
1358
|
_resetUpload() {
|
|
@@ -2061,6 +2026,10 @@ __decorate([
|
|
|
2061
2026
|
state(),
|
|
2062
2027
|
__metadata("design:type", Object)
|
|
2063
2028
|
], BoardCreateWizardPage.prototype, "_uploading", void 0);
|
|
2029
|
+
__decorate([
|
|
2030
|
+
state(),
|
|
2031
|
+
__metadata("design:type", Number)
|
|
2032
|
+
], BoardCreateWizardPage.prototype, "_uploadProgress", void 0);
|
|
2064
2033
|
__decorate([
|
|
2065
2034
|
state(),
|
|
2066
2035
|
__metadata("design:type", String)
|