@things-factory/board-ui 10.0.0-beta.6 → 10.0.0-beta.64
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/apptools/favorite-tool.js +5 -5
- package/dist-client/apptools/favorite-tool.js.map +1 -1
- package/dist-client/board-list/board-tile-list.d.ts +6 -1
- package/dist-client/board-list/board-tile-list.js +291 -44
- package/dist-client/board-list/board-tile-list.js.map +1 -1
- package/dist-client/board-list/group-bar.js +3 -3
- package/dist-client/board-list/group-bar.js.map +1 -1
- package/dist-client/board-list/play-group-bar.d.ts +0 -1
- package/dist-client/board-list/play-group-bar.js +3 -6
- package/dist-client/board-list/play-group-bar.js.map +1 -1
- package/dist-client/board-provider.js +20 -8
- package/dist-client/board-provider.js.map +1 -1
- package/dist-client/data-grist/board-editor.js +4 -4
- package/dist-client/data-grist/board-editor.js.map +1 -1
- package/dist-client/data-grist/board-renderer.js +4 -4
- package/dist-client/data-grist/board-renderer.js.map +1 -1
- package/dist-client/graphql/board-template.js +1 -1
- package/dist-client/graphql/board-template.js.map +1 -1
- package/dist-client/graphql/board.d.ts +1 -0
- package/dist-client/graphql/board.js +28 -2
- package/dist-client/graphql/board.js.map +1 -1
- package/dist-client/graphql/group.js +1 -1
- package/dist-client/graphql/group.js.map +1 -1
- package/dist-client/graphql/play-group.js +3 -3
- package/dist-client/graphql/play-group.js.map +1 -1
- package/dist-client/pages/attachment-list-page.d.ts +16 -0
- package/dist-client/pages/attachment-list-page.js +63 -2
- package/dist-client/pages/attachment-list-page.js.map +1 -1
- package/dist-client/pages/board-list-page.d.ts +23 -3
- package/dist-client/pages/board-list-page.js +165 -77
- package/dist-client/pages/board-list-page.js.map +1 -1
- package/dist-client/pages/board-modeller-page.d.ts +122 -0
- package/dist-client/pages/board-modeller-page.js +705 -54
- package/dist-client/pages/board-modeller-page.js.map +1 -1
- package/dist-client/pages/board-player-by-name-page.js.map +1 -1
- package/dist-client/pages/board-player-page.js +14 -26
- package/dist-client/pages/board-player-page.js.map +1 -1
- package/dist-client/pages/board-viewer-by-name-page.d.ts +8 -1
- package/dist-client/pages/board-viewer-by-name-page.js +9 -1
- package/dist-client/pages/board-viewer-by-name-page.js.map +1 -1
- package/dist-client/pages/board-viewer-page.d.ts +2 -1
- package/dist-client/pages/board-viewer-page.js +52 -48
- package/dist-client/pages/board-viewer-page.js.map +1 -1
- package/dist-client/pages/play-list-page.d.ts +0 -1
- package/dist-client/pages/play-list-page.js +26 -33
- package/dist-client/pages/play-list-page.js.map +1 -1
- package/dist-client/pages/printable-board-viewer-page.js +2 -2
- package/dist-client/pages/printable-board-viewer-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js.map +1 -1
- package/dist-client/setting-let/board-view-setting-let.js +1 -1
- package/dist-client/setting-let/board-view-setting-let.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/notify-helper.d.ts +7 -0
- package/dist-client/utils/notify-helper.js +28 -0
- package/dist-client/utils/notify-helper.js.map +1 -0
- package/dist-client/utils/query-utils.d.ts +1 -0
- package/dist-client/utils/query-utils.js +20 -0
- package/dist-client/utils/query-utils.js.map +1 -0
- package/dist-client/viewparts/board-basic-info.js +9 -13
- package/dist-client/viewparts/board-basic-info.js.map +1 -1
- package/dist-client/viewparts/board-template-info.d.ts +0 -1
- package/dist-client/viewparts/board-template-info.js +5 -13
- package/dist-client/viewparts/board-template-info.js.map +1 -1
- package/dist-client/viewparts/board-versions.js +1 -1
- package/dist-client/viewparts/board-versions.js.map +1 -1
- package/dist-client/viewparts/group-info-basic.js +2 -2
- package/dist-client/viewparts/group-info-basic.js.map +1 -1
- package/dist-client/viewparts/group-info-import.js +2 -2
- package/dist-client/viewparts/group-info-import.js.map +1 -1
- package/dist-client/viewparts/link-builder.js +1 -1
- package/dist-client/viewparts/link-builder.js.map +1 -1
- package/dist-client/viewparts/play-group-info-basic.js +2 -2
- package/dist-client/viewparts/play-group-info-basic.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/translations/en.json +3 -29
- package/translations/ja.json +3 -29
- package/translations/ko.json +3 -29
- package/translations/ms.json +3 -29
- package/translations/zh.json +3 -29
|
@@ -5,8 +5,10 @@ import { customElement, query } from 'lit/decorators.js';
|
|
|
5
5
|
import gql from 'graphql-tag';
|
|
6
6
|
import { i18next, localize } from '@operato/i18n';
|
|
7
7
|
import { PageView } from '@operato/shell';
|
|
8
|
+
import { CommonButtonStyles } from '@operato/styles';
|
|
8
9
|
import { OxAttachmentList } from '@operato/attachment/ox-attachment-list.js';
|
|
9
10
|
import { client } from '@operato/graphql';
|
|
11
|
+
import { notify } from '@operato/layout';
|
|
10
12
|
async function fetchDataFromURL(fileURL) {
|
|
11
13
|
try {
|
|
12
14
|
const response = await fetch(fileURL);
|
|
@@ -57,7 +59,14 @@ let AttachmentListPage = class AttachmentListPage extends localize(i18next)(Page
|
|
|
57
59
|
},
|
|
58
60
|
importable: {
|
|
59
61
|
handler: this.importHandler.bind(this)
|
|
60
|
-
}
|
|
62
|
+
},
|
|
63
|
+
actions: [
|
|
64
|
+
{
|
|
65
|
+
title: i18next.t('button.backfill thumbnails'),
|
|
66
|
+
action: this.backfillThumbnails.bind(this),
|
|
67
|
+
...CommonButtonStyles.save
|
|
68
|
+
}
|
|
69
|
+
]
|
|
61
70
|
};
|
|
62
71
|
}
|
|
63
72
|
render() {
|
|
@@ -91,11 +100,63 @@ let AttachmentListPage = class AttachmentListPage extends localize(i18next)(Page
|
|
|
91
100
|
});
|
|
92
101
|
}
|
|
93
102
|
catch (err) {
|
|
94
|
-
console.
|
|
103
|
+
console.warn('Failed to process attachment:', name, err);
|
|
95
104
|
}
|
|
96
105
|
}
|
|
97
106
|
return data;
|
|
98
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* 썸네일이 없는 기존 첨부파일들에 대해 서버에서 일괄 썸네일 생성.
|
|
110
|
+
* 한 배치당 20 개씩, remaining 이 0 이 될 때까지 반복 호출.
|
|
111
|
+
*/
|
|
112
|
+
async backfillThumbnails() {
|
|
113
|
+
const BATCH = 20;
|
|
114
|
+
let total = { attempted: 0, succeeded: 0, failed: 0 };
|
|
115
|
+
let remaining = Number.POSITIVE_INFINITY;
|
|
116
|
+
notify({ message: i18next.t('text.backfilling thumbnails') });
|
|
117
|
+
while (remaining > 0) {
|
|
118
|
+
try {
|
|
119
|
+
const { data } = await client.mutate({
|
|
120
|
+
mutation: gql `
|
|
121
|
+
mutation BackfillAttachmentThumbnails($limit: Int) {
|
|
122
|
+
backfillAttachmentThumbnails(limit: $limit) {
|
|
123
|
+
attempted
|
|
124
|
+
succeeded
|
|
125
|
+
failed
|
|
126
|
+
remaining
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
`,
|
|
130
|
+
variables: { limit: BATCH }
|
|
131
|
+
});
|
|
132
|
+
const r = data?.backfillAttachmentThumbnails;
|
|
133
|
+
if (!r)
|
|
134
|
+
break;
|
|
135
|
+
total.attempted += r.attempted;
|
|
136
|
+
total.succeeded += r.succeeded;
|
|
137
|
+
total.failed += r.failed;
|
|
138
|
+
remaining = r.remaining;
|
|
139
|
+
if (r.attempted === 0)
|
|
140
|
+
break; // 더 이상 처리할 게 없음
|
|
141
|
+
// 한 배치에서 아무것도 성공하지 못했다면 무한 루프 방지를 위해 중단.
|
|
142
|
+
// 동일 후보들이 계속 실패하는 상황이므로 서버 측 원인 해결이 선행되어야 함.
|
|
143
|
+
if (r.succeeded === 0)
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
console.error('backfill error:', err);
|
|
148
|
+
notify({ level: 'error', message: String(err) });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
notify({
|
|
153
|
+
message: i18next.t('text.thumbnail backfill done', {
|
|
154
|
+
succeeded: total.succeeded,
|
|
155
|
+
failed: total.failed
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
this.grist.fetch();
|
|
159
|
+
}
|
|
99
160
|
async importHandler(data, file) {
|
|
100
161
|
await client.mutate({
|
|
101
162
|
mutation: gql `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment-list-page.js","sourceRoot":"","sources":["../../client/pages/attachment-list-page.ts"],"names":[],"mappings":";AAAA,OAAO,2CAA2C,CAAA;AAElD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,GAAG,MAAM,aAAa,CAAA;AAE7B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAA;AAC5E,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"attachment-list-page.js","sourceRoot":"","sources":["../../client/pages/attachment-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/attachment/ox-attachment-list.js'\n\nimport { css, html } from 'lit'\nimport { customElement, query } from 'lit/decorators.js'\nimport gql from 'graphql-tag'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { PageView } from '@operato/shell'\nimport { CommonButtonStyles } from '@operato/styles'\nimport { OxAttachmentList } from '@operato/attachment/ox-attachment-list.js'\nimport { client } from '@operato/graphql'\nimport { notify } from '@operato/layout'\n\nasync function fetchDataFromURL(fileURL: string) {\n try {\n const response = await fetch(fileURL)\n\n if (!response.ok) {\n throw new Error('Network response was not ok')\n }\n\n const blob = await response.blob() // 파일 데이터를 Blob으로 변환\n\n if (blob.size === 0) {\n throw new Error('Content is empty') // Content가 비어 있으면 예외\n }\n\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n\n reader.onload = (event: any) => {\n const dataURL = event.target.result\n resolve(dataURL)\n }\n\n reader.onerror = (event: any) => {\n reject(event.error)\n }\n\n reader.readAsDataURL(blob) // Blob을 Data URL로 읽기\n })\n } catch (error) {\n throw error\n }\n}\n\n@customElement('attachment-list-page')\nexport class AttachmentListPage extends localize(i18next)(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n }\n `\n ]\n\n @query('ox-attachment-list') attachmentList!: OxAttachmentList\n\n get context() {\n return {\n title: i18next.t('title.attachment list'),\n search: {\n handler: search => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n board_topmenu: true,\n exportable: {\n name: i18next.t('title.attachment list'),\n data: this.exportHandler.bind(this)\n },\n importable: {\n handler: this.importHandler.bind(this)\n },\n actions: [\n {\n title: i18next.t('button.backfill thumbnails'),\n action: this.backfillThumbnails.bind(this),\n ...CommonButtonStyles.save\n }\n ]\n }\n }\n\n render() {\n return html` <ox-attachment-list .creatable=${true} without-search></ox-attachment-list> `\n }\n\n get grist() {\n return this.attachmentList.grist\n }\n\n languageUpdated(i18next) {\n this.attachmentList.requestUpdate()\n }\n\n async pageInitialized() {\n await this.updateComplete\n\n this.attachmentList.refreshAttachments()\n }\n\n async exportHandler() {\n const records = this.grist.data.records\n const data = {} as any\n\n for (const record of records) {\n const { id, name, mimetype, encoding, category, fullpath } = record\n\n try {\n const dataURL = await fetchDataFromURL(fullpath)\n\n id &&\n (data[id!] = {\n id,\n name,\n mimetype,\n encoding,\n category,\n contents: dataURL\n })\n } catch (err) {\n console.warn('Failed to process attachment:', name, err)\n }\n }\n\n return data\n }\n\n /**\n * 썸네일이 없는 기존 첨부파일들에 대해 서버에서 일괄 썸네일 생성.\n * 한 배치당 20 개씩, remaining 이 0 이 될 때까지 반복 호출.\n */\n async backfillThumbnails() {\n const BATCH = 20\n let total = { attempted: 0, succeeded: 0, failed: 0 }\n let remaining = Number.POSITIVE_INFINITY\n\n notify({ message: i18next.t('text.backfilling thumbnails') })\n\n while (remaining > 0) {\n try {\n const { data } = await client.mutate({\n mutation: gql`\n mutation BackfillAttachmentThumbnails($limit: Int) {\n backfillAttachmentThumbnails(limit: $limit) {\n attempted\n succeeded\n failed\n remaining\n }\n }\n `,\n variables: { limit: BATCH }\n })\n const r = data?.backfillAttachmentThumbnails\n if (!r) break\n total.attempted += r.attempted\n total.succeeded += r.succeeded\n total.failed += r.failed\n remaining = r.remaining\n\n if (r.attempted === 0) break // 더 이상 처리할 게 없음\n // 한 배치에서 아무것도 성공하지 못했다면 무한 루프 방지를 위해 중단.\n // 동일 후보들이 계속 실패하는 상황이므로 서버 측 원인 해결이 선행되어야 함.\n if (r.succeeded === 0) break\n } catch (err) {\n console.error('backfill error:', err)\n notify({ level: 'error', message: String(err) })\n return\n }\n }\n\n notify({\n message: i18next.t('text.thumbnail backfill done', {\n succeeded: total.succeeded,\n failed: total.failed\n })\n })\n this.grist.fetch()\n }\n\n async importHandler(data, file) {\n await client.mutate({\n mutation: gql`\n mutation importAttachments($file: Upload!) {\n importAttachments(file: $file) {\n id\n name\n description\n path\n }\n }\n `,\n variables: {\n file\n },\n context: { hasUpload: true }\n })\n\n this.grist.fetch()\n }\n}\n"]}
|
|
@@ -16,6 +16,8 @@ export declare class BoardListPage extends BoardListPageBase {
|
|
|
16
16
|
private _page;
|
|
17
17
|
private _total;
|
|
18
18
|
private page?;
|
|
19
|
+
private _lastFetchTime?;
|
|
20
|
+
private _updatedBoardIds;
|
|
19
21
|
get context(): {
|
|
20
22
|
title: {
|
|
21
23
|
icon: string;
|
|
@@ -36,15 +38,30 @@ export declare class BoardListPage extends BoardListPageBase {
|
|
|
36
38
|
page?: number | undefined;
|
|
37
39
|
limit?: any;
|
|
38
40
|
}): Promise<any>;
|
|
41
|
+
/**
|
|
42
|
+
* favor/mywork 같이 "search text + pagination"만 받는 간단한 리스트 조회 공용 헬퍼.
|
|
43
|
+
* 그룹/타입 필터 등 복합 조건을 쓰는 일반 목록(getBoards)과 구분해 중복 제거.
|
|
44
|
+
*/
|
|
45
|
+
private _fetchSimpleBoardList;
|
|
39
46
|
getFavoriteBoards({ page, limit }?: {
|
|
40
47
|
page?: number | undefined;
|
|
41
48
|
limit?: any;
|
|
42
|
-
}): Promise<any>;
|
|
49
|
+
}): Promise<any[]>;
|
|
43
50
|
getMyBoards({ page, limit }?: {
|
|
44
51
|
page?: number | undefined;
|
|
45
52
|
limit?: any;
|
|
46
|
-
}): Promise<any>;
|
|
53
|
+
}): Promise<any[]>;
|
|
47
54
|
refreshBoards(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* 컨텐츠가 스크롤 영역을 채우지 못하면 다음 페이지를 자동 로드한다.
|
|
57
|
+
*/
|
|
58
|
+
private _filling;
|
|
59
|
+
private fillViewport;
|
|
60
|
+
/**
|
|
61
|
+
* 기존 목록을 유지하면서 변경된 보드만 갱신한다.
|
|
62
|
+
* 스크롤 위치가 보존된다.
|
|
63
|
+
*/
|
|
64
|
+
incrementalRefresh(): Promise<void>;
|
|
48
65
|
appendBoards(): Promise<void>;
|
|
49
66
|
scrollAction(): Promise<void>;
|
|
50
67
|
pageInitialized(): Promise<void>;
|
|
@@ -64,6 +81,10 @@ export declare class BoardListPage extends BoardListPageBase {
|
|
|
64
81
|
files: any;
|
|
65
82
|
overwrite: any;
|
|
66
83
|
}): Promise<void>;
|
|
84
|
+
onReorderBoards({ boardIds, movedId }: {
|
|
85
|
+
boardIds: any;
|
|
86
|
+
movedId: any;
|
|
87
|
+
}): Promise<void>;
|
|
67
88
|
onCreateBoard(board: any): Promise<void>;
|
|
68
89
|
onCloneBoard({ id, name, description, targetSubdomain, targetGroupId }: {
|
|
69
90
|
id: any;
|
|
@@ -94,6 +115,5 @@ export declare class BoardListPage extends BoardListPageBase {
|
|
|
94
115
|
visibility: any;
|
|
95
116
|
}): Promise<void>;
|
|
96
117
|
refreshFavorites(): Promise<void>;
|
|
97
|
-
_notify(level: 'info' | 'error' | 'warn', message: any, ex?: any): void;
|
|
98
118
|
}
|
|
99
119
|
export {};
|
|
@@ -15,7 +15,8 @@ import { ScrollbarStyles } from '@operato/styles';
|
|
|
15
15
|
import InfiniteScrollable from '@operato/utils/mixins/infinite-scrollable.js';
|
|
16
16
|
import { UPDATE_FAVORITES } from '@things-factory/fav-base/client/index.js';
|
|
17
17
|
import { swipe } from '@things-factory/utils/src/index.js';
|
|
18
|
-
import {
|
|
18
|
+
import { notify } from '../utils/notify-helper.js';
|
|
19
|
+
import { cloneBoard, releaseBoard, revertBoardVersion, createBoard, createGroup, deleteBoard, deleteGroup, fetchBoardList, fetchBoardsUpdatedSince, fetchFavoriteBoardList, fetchMyBoardList, fetchGroupList, updateBoard, updateGroup, importBoards } from '../graphql';
|
|
19
20
|
const BoardListPageBase = localize(i18next)(InfiniteScrollable(PageView));
|
|
20
21
|
let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
21
22
|
static { this.styles = [
|
|
@@ -42,8 +43,8 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
42
43
|
`
|
|
43
44
|
]; }
|
|
44
45
|
get context() {
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
const groupId = this.groupId;
|
|
47
|
+
const group = this.groups && this.groups.find(group => group.id === groupId);
|
|
47
48
|
return {
|
|
48
49
|
title: {
|
|
49
50
|
icon: 'dashboard',
|
|
@@ -59,6 +60,15 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
59
60
|
handler: search => {
|
|
60
61
|
this.searchText = search;
|
|
61
62
|
this.refreshBoards();
|
|
63
|
+
// URL에 검색어 반영 → 페이지 복귀 시 유지
|
|
64
|
+
const url = new URL(window.location.href);
|
|
65
|
+
if (search) {
|
|
66
|
+
url.searchParams.set('search', search);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
url.searchParams.delete('search');
|
|
70
|
+
}
|
|
71
|
+
history.replaceState(null, '', url.href);
|
|
62
72
|
},
|
|
63
73
|
value: this.searchText || ''
|
|
64
74
|
},
|
|
@@ -74,6 +84,11 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
74
84
|
this.searchText = '';
|
|
75
85
|
this._page = 1;
|
|
76
86
|
this._total = 0; /* required for infinite-scrolling */
|
|
87
|
+
this._updatedBoardIds = [];
|
|
88
|
+
/**
|
|
89
|
+
* 컨텐츠가 스크롤 영역을 채우지 못하면 다음 페이지를 자동 로드한다.
|
|
90
|
+
*/
|
|
91
|
+
this._filling = false;
|
|
77
92
|
this._infiniteScrollOptions.limit = 50;
|
|
78
93
|
}
|
|
79
94
|
render() {
|
|
@@ -92,6 +107,7 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
92
107
|
.favorites=${this.favorites}
|
|
93
108
|
.groups=${this.groups}
|
|
94
109
|
.group=${this.groupId}
|
|
110
|
+
.updatedIds=${this._updatedBoardIds}
|
|
95
111
|
search-text=${this.searchText}
|
|
96
112
|
@info-board=${e => this.onInfoBoard(e.detail)}
|
|
97
113
|
@scroll=${e => {
|
|
@@ -100,7 +116,9 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
100
116
|
}}
|
|
101
117
|
@create-board=${e => this.onCreateBoard(e.detail)}
|
|
102
118
|
@refresh-favorites=${e => this.refreshFavorites()}
|
|
119
|
+
@reordered=${e => this.onReorderBoards(e.detail)}
|
|
103
120
|
creatable
|
|
121
|
+
reorderable
|
|
104
122
|
></board-tile-list>
|
|
105
123
|
`;
|
|
106
124
|
}
|
|
@@ -149,9 +167,13 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
149
167
|
value: 'main'
|
|
150
168
|
});
|
|
151
169
|
}
|
|
152
|
-
|
|
170
|
+
const listParam = {
|
|
153
171
|
filters,
|
|
154
172
|
sortings: [
|
|
173
|
+
{
|
|
174
|
+
name: 'sortOrder',
|
|
175
|
+
desc: false
|
|
176
|
+
},
|
|
155
177
|
{
|
|
156
178
|
name: 'name',
|
|
157
179
|
desc: false
|
|
@@ -164,7 +186,11 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
164
186
|
};
|
|
165
187
|
return (await fetchBoardList(listParam)).boards;
|
|
166
188
|
}
|
|
167
|
-
|
|
189
|
+
/**
|
|
190
|
+
* favor/mywork 같이 "search text + pagination"만 받는 간단한 리스트 조회 공용 헬퍼.
|
|
191
|
+
* 그룹/타입 필터 등 복합 조건을 쓰는 일반 목록(getBoards)과 구분해 중복 제거.
|
|
192
|
+
*/
|
|
193
|
+
async _fetchSimpleBoardList(fetcher, resultKey, { page, limit }) {
|
|
168
194
|
const filters = [];
|
|
169
195
|
if (this.searchText) {
|
|
170
196
|
filters.push({
|
|
@@ -173,55 +199,88 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
173
199
|
value: '%' + this.searchText + '%'
|
|
174
200
|
});
|
|
175
201
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
return (await fetchFavoriteBoardList(listParam)).favoriteBoards;
|
|
202
|
+
const result = await fetcher({ filters, pagination: { page, limit } });
|
|
203
|
+
return result[resultKey];
|
|
204
|
+
}
|
|
205
|
+
async getFavoriteBoards({ page = 1, limit = this._infiniteScrollOptions.limit } = {}) {
|
|
206
|
+
return this._fetchSimpleBoardList(fetchFavoriteBoardList, 'favoriteBoards', { page, limit });
|
|
184
207
|
}
|
|
185
208
|
async getMyBoards({ page = 1, limit = this._infiniteScrollOptions.limit } = {}) {
|
|
186
|
-
|
|
187
|
-
if (this.searchText) {
|
|
188
|
-
filters.push({
|
|
189
|
-
name: 'name',
|
|
190
|
-
operator: 'search',
|
|
191
|
-
value: '%' + this.searchText + '%'
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
var listParam = {
|
|
195
|
-
filters,
|
|
196
|
-
pagination: {
|
|
197
|
-
page,
|
|
198
|
-
limit
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
return (await fetchMyBoardList(listParam)).boardsCreatedByMe;
|
|
209
|
+
return this._fetchSimpleBoardList(fetchMyBoardList, 'boardsCreatedByMe', { page, limit });
|
|
202
210
|
}
|
|
203
211
|
async refreshBoards() {
|
|
204
212
|
if (!this.groups) {
|
|
205
213
|
await this.refresh();
|
|
206
214
|
return;
|
|
207
215
|
}
|
|
208
|
-
|
|
216
|
+
const { items: boards, total } = await this.getBoards();
|
|
209
217
|
this.boards = boards;
|
|
210
218
|
this._page = 1;
|
|
211
219
|
this._total = total;
|
|
220
|
+
this._lastFetchTime = new Date();
|
|
212
221
|
this.updateContext();
|
|
213
222
|
this.scrollTargetEl.style.transition = '';
|
|
214
223
|
this.scrollTargetEl.style.transform = `translate3d(0, 0, 0)`;
|
|
224
|
+
this.fillViewport();
|
|
225
|
+
}
|
|
226
|
+
async fillViewport() {
|
|
227
|
+
if (this._filling)
|
|
228
|
+
return;
|
|
229
|
+
this._filling = true;
|
|
230
|
+
try {
|
|
231
|
+
const el = this.scrollTargetEl;
|
|
232
|
+
if (!el)
|
|
233
|
+
return;
|
|
234
|
+
const { limit } = this._infiniteScrollOptions;
|
|
235
|
+
while (this._page < this._total / limit && el.scrollHeight <= el.clientHeight) {
|
|
236
|
+
await this.appendBoards();
|
|
237
|
+
await this.updateComplete;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
this._filling = false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* 기존 목록을 유지하면서 변경된 보드만 갱신한다.
|
|
246
|
+
* 스크롤 위치가 보존된다.
|
|
247
|
+
*/
|
|
248
|
+
async incrementalRefresh() {
|
|
249
|
+
if (!this._lastFetchTime || this.boards.length === 0) {
|
|
250
|
+
return this.refreshBoards();
|
|
251
|
+
}
|
|
252
|
+
const updatedBoards = await fetchBoardsUpdatedSince(this._lastFetchTime);
|
|
253
|
+
if (updatedBoards && updatedBoards.length > 0) {
|
|
254
|
+
const updatedMap = new Map(updatedBoards.map((b) => [b.id, b]));
|
|
255
|
+
const changedIds = [];
|
|
256
|
+
this.boards = this.boards
|
|
257
|
+
.map(board => {
|
|
258
|
+
const updated = updatedMap.get(board.id);
|
|
259
|
+
if (!updated)
|
|
260
|
+
return board;
|
|
261
|
+
// 삭제되었거나 현재 그룹에서 벗어난 경우 제거
|
|
262
|
+
if (updated.deletedAt || (this.groupId && updated.group?.id !== this.groupId))
|
|
263
|
+
return null;
|
|
264
|
+
changedIds.push(updated.id);
|
|
265
|
+
return updated;
|
|
266
|
+
})
|
|
267
|
+
.filter(Boolean);
|
|
268
|
+
this._updatedBoardIds = changedIds;
|
|
269
|
+
}
|
|
270
|
+
this._lastFetchTime = new Date();
|
|
215
271
|
}
|
|
216
272
|
async appendBoards() {
|
|
217
273
|
if (!this.groups) {
|
|
218
274
|
await this.refresh();
|
|
219
275
|
return;
|
|
220
276
|
}
|
|
221
|
-
|
|
222
|
-
|
|
277
|
+
const { items: appendedBoards, total } = await this.getBoards({ page: this._page + 1 });
|
|
278
|
+
const existingIds = new Set(this.boards.map(b => b.id));
|
|
279
|
+
const newBoards = appendedBoards.filter(b => !existingIds.has(b.id));
|
|
280
|
+
this.boards = [...this.boards, ...newBoards];
|
|
223
281
|
this._page = this._page + 1;
|
|
224
282
|
this._total = total;
|
|
283
|
+
this._lastFetchTime = new Date();
|
|
225
284
|
}
|
|
226
285
|
async scrollAction() {
|
|
227
286
|
return this.appendBoards();
|
|
@@ -231,11 +290,23 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
231
290
|
}
|
|
232
291
|
async pageUpdated(changes, lifecycle) {
|
|
233
292
|
if (this.active) {
|
|
293
|
+
const prevGroupId = this.groupId;
|
|
294
|
+
const prevSearchText = this.searchText;
|
|
234
295
|
this.page = lifecycle.page;
|
|
235
296
|
this.groupId = lifecycle.resourceId;
|
|
236
297
|
this.searchText = lifecycle.params?.search || '';
|
|
237
298
|
await this.updateComplete;
|
|
238
|
-
|
|
299
|
+
// 검색어가 변경되었으면 전체 갱신
|
|
300
|
+
// 같은 그룹으로 복귀하고 기존 데이터가 있으면 변경분만 갱신 (스크롤 유지)
|
|
301
|
+
if (prevSearchText !== this.searchText) {
|
|
302
|
+
this.refreshBoards();
|
|
303
|
+
}
|
|
304
|
+
else if (prevGroupId === this.groupId && this.boards.length > 0 && this._lastFetchTime) {
|
|
305
|
+
this.incrementalRefresh();
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
this.refreshBoards();
|
|
309
|
+
}
|
|
239
310
|
}
|
|
240
311
|
}
|
|
241
312
|
connectedCallback() {
|
|
@@ -264,8 +335,8 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
264
335
|
container: list,
|
|
265
336
|
animates: {
|
|
266
337
|
dragging: async (d, opts) => {
|
|
267
|
-
|
|
268
|
-
|
|
338
|
+
const groups = [{ id: '' }, { id: 'favor' }, ...this.groups];
|
|
339
|
+
const currentIndex = groups.findIndex(group => group.id == this.groupId);
|
|
269
340
|
if ((d > 0 && currentIndex <= 0) || (d < 0 && currentIndex >= groups.length - 1)) {
|
|
270
341
|
/* TODO blocked gesture */
|
|
271
342
|
return false;
|
|
@@ -280,8 +351,8 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
280
351
|
});
|
|
281
352
|
},
|
|
282
353
|
swiping: async (d, opts) => {
|
|
283
|
-
|
|
284
|
-
|
|
354
|
+
const groups = [{ id: '' }, { id: 'favor' }, ...this.groups];
|
|
355
|
+
const currentIndex = groups.findIndex(group => group.id == this.groupId);
|
|
285
356
|
if ((d > 0 && currentIndex <= 0) || (d < 0 && currentIndex >= groups.length - 1)) {
|
|
286
357
|
list.style.transition = '';
|
|
287
358
|
list.style.transform = `translate3d(0, 0, 0)`;
|
|
@@ -329,43 +400,65 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
329
400
|
async onCreateGroup(group) {
|
|
330
401
|
try {
|
|
331
402
|
const data = await createGroup(group);
|
|
332
|
-
data &&
|
|
403
|
+
data && notify('info', i18next.t('text.group created', { group: group.name }));
|
|
333
404
|
}
|
|
334
405
|
catch (ex) {
|
|
335
|
-
|
|
406
|
+
notify('error', ex, ex);
|
|
336
407
|
}
|
|
337
408
|
this.refresh();
|
|
338
409
|
}
|
|
339
410
|
async onUpdateGroup(group) {
|
|
340
411
|
try {
|
|
341
412
|
const data = await updateGroup(group);
|
|
342
|
-
data &&
|
|
413
|
+
data && notify('info', i18next.t('text.group updated', { group: group.name }));
|
|
343
414
|
}
|
|
344
415
|
catch (ex) {
|
|
345
|
-
|
|
416
|
+
notify('error', ex, ex);
|
|
346
417
|
}
|
|
347
418
|
this.refresh();
|
|
348
419
|
}
|
|
349
420
|
async onDeleteGroup(group) {
|
|
350
421
|
try {
|
|
351
422
|
const data = await deleteGroup(group.id);
|
|
352
|
-
data &&
|
|
423
|
+
data && notify('info', i18next.t('text.group deleted', { group: group.name }));
|
|
353
424
|
}
|
|
354
425
|
catch (ex) {
|
|
355
|
-
|
|
426
|
+
notify('error', ex, ex);
|
|
356
427
|
}
|
|
357
428
|
this.refresh();
|
|
358
429
|
}
|
|
359
430
|
async onImportBoards({ group, files, overwrite }) {
|
|
360
431
|
try {
|
|
361
432
|
const data = await importBoards({ groupId: group.id, files, overwrite });
|
|
362
|
-
data &&
|
|
433
|
+
data && notify('info', i18next.t('text.boards imported', { count: files.length, group: group.name }));
|
|
363
434
|
}
|
|
364
435
|
catch (ex) {
|
|
365
|
-
|
|
436
|
+
notify('error', ex, ex);
|
|
366
437
|
}
|
|
367
438
|
this.refresh();
|
|
368
439
|
}
|
|
440
|
+
async onReorderBoards({ boardIds, movedId }) {
|
|
441
|
+
if (!movedId)
|
|
442
|
+
return;
|
|
443
|
+
const newIndex = boardIds.indexOf(movedId);
|
|
444
|
+
const prevId = newIndex > 0 ? boardIds[newIndex - 1] : undefined;
|
|
445
|
+
const nextId = newIndex < boardIds.length - 1 ? boardIds[newIndex + 1] : undefined;
|
|
446
|
+
this.boards = boardIds.map(id => this.boards.find(b => b.id === id)).filter(Boolean);
|
|
447
|
+
try {
|
|
448
|
+
await client.mutate({
|
|
449
|
+
mutation: gql `
|
|
450
|
+
mutation ($id: String!, $prevId: String, $nextId: String) {
|
|
451
|
+
reorderBoard(id: $id, prevId: $prevId, nextId: $nextId)
|
|
452
|
+
}
|
|
453
|
+
`,
|
|
454
|
+
variables: { id: movedId, prevId, nextId }
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
catch (ex) {
|
|
458
|
+
notify('error', ex, ex);
|
|
459
|
+
this.refreshBoards();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
369
462
|
async onCreateBoard(board) {
|
|
370
463
|
try {
|
|
371
464
|
if (!board.model) {
|
|
@@ -375,10 +468,10 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
375
468
|
};
|
|
376
469
|
}
|
|
377
470
|
const data = await createBoard(board);
|
|
378
|
-
data &&
|
|
471
|
+
data && notify('info', i18next.t('text.board created', { board: board.name }));
|
|
379
472
|
}
|
|
380
473
|
catch (ex) {
|
|
381
|
-
|
|
474
|
+
notify('error', ex, ex);
|
|
382
475
|
}
|
|
383
476
|
this.refreshBoards();
|
|
384
477
|
}
|
|
@@ -391,52 +484,52 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
391
484
|
targetSubdomain,
|
|
392
485
|
targetGroupId
|
|
393
486
|
});
|
|
394
|
-
data &&
|
|
487
|
+
data && notify('info', i18next.t('text.board cloned', { board: name }));
|
|
395
488
|
}
|
|
396
489
|
catch (ex) {
|
|
397
|
-
|
|
490
|
+
notify('error', ex, ex);
|
|
398
491
|
}
|
|
399
|
-
this.
|
|
492
|
+
this.incrementalRefresh();
|
|
400
493
|
}
|
|
401
494
|
async onReleaseBoard(board) {
|
|
402
495
|
try {
|
|
403
496
|
const data = await releaseBoard(board);
|
|
404
|
-
data &&
|
|
497
|
+
data && notify('info', i18next.t('text.board released', { board: board.name }));
|
|
405
498
|
}
|
|
406
499
|
catch (ex) {
|
|
407
|
-
|
|
500
|
+
notify('error', ex, ex);
|
|
408
501
|
}
|
|
409
|
-
this.
|
|
502
|
+
this.incrementalRefresh();
|
|
410
503
|
}
|
|
411
504
|
async onRevertBoardVersion({ id, version }) {
|
|
412
505
|
try {
|
|
413
506
|
const board = await revertBoardVersion(id, version);
|
|
414
|
-
board &&
|
|
507
|
+
board && notify('info', i18next.t('text.board reverted', { board: board.name, version }));
|
|
415
508
|
}
|
|
416
509
|
catch (ex) {
|
|
417
|
-
|
|
510
|
+
notify('error', ex, ex);
|
|
418
511
|
}
|
|
419
|
-
this.
|
|
512
|
+
this.incrementalRefresh();
|
|
420
513
|
}
|
|
421
514
|
async onUpdateBoard(board) {
|
|
422
515
|
try {
|
|
423
516
|
const data = await updateBoard(board);
|
|
424
|
-
data &&
|
|
517
|
+
data && notify('info', i18next.t('text.board updated', { board: board.name }));
|
|
425
518
|
}
|
|
426
519
|
catch (ex) {
|
|
427
|
-
|
|
520
|
+
notify('error', ex, ex);
|
|
428
521
|
}
|
|
429
|
-
this.
|
|
522
|
+
this.incrementalRefresh();
|
|
430
523
|
}
|
|
431
524
|
async onDeleteBoard(board) {
|
|
432
525
|
try {
|
|
433
526
|
const data = await deleteBoard(board.id);
|
|
434
|
-
data &&
|
|
527
|
+
data && notify('info', i18next.t('text.board deleted', { board: board.name }));
|
|
435
528
|
}
|
|
436
529
|
catch (ex) {
|
|
437
|
-
|
|
530
|
+
notify('error', ex, ex);
|
|
438
531
|
}
|
|
439
|
-
this.
|
|
532
|
+
this.incrementalRefresh();
|
|
440
533
|
}
|
|
441
534
|
async onJoinPlayGroup({ board, playGroup }) {
|
|
442
535
|
try {
|
|
@@ -454,10 +547,10 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
454
547
|
}
|
|
455
548
|
});
|
|
456
549
|
data &&
|
|
457
|
-
|
|
550
|
+
notify('info', i18next.t('text.joined into play-group', { board: board.name, playGroup: playGroup.name }));
|
|
458
551
|
}
|
|
459
552
|
catch (ex) {
|
|
460
|
-
|
|
553
|
+
notify('error', ex, ex);
|
|
461
554
|
}
|
|
462
555
|
}
|
|
463
556
|
async onLeavePlayGroup({ board, playGroup }) {
|
|
@@ -476,10 +569,10 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
476
569
|
}
|
|
477
570
|
});
|
|
478
571
|
data &&
|
|
479
|
-
|
|
572
|
+
notify('info', i18next.t('text.leaved from play-group', { board: board.name, playGroup: playGroup.name }));
|
|
480
573
|
}
|
|
481
574
|
catch (ex) {
|
|
482
|
-
|
|
575
|
+
notify('error', ex, ex);
|
|
483
576
|
}
|
|
484
577
|
}
|
|
485
578
|
async onRegisterTemplate({ id, name, description, visibility }) {
|
|
@@ -500,12 +593,12 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
500
593
|
}
|
|
501
594
|
});
|
|
502
595
|
data &&
|
|
503
|
-
|
|
596
|
+
notify('info', i18next.t('text.info_x_successfully', { x: i18next.t('text.register-template') }), {
|
|
504
597
|
name
|
|
505
598
|
});
|
|
506
599
|
}
|
|
507
600
|
catch (ex) {
|
|
508
|
-
|
|
601
|
+
notify('error', ex, ex);
|
|
509
602
|
}
|
|
510
603
|
}
|
|
511
604
|
async refreshFavorites() {
|
|
@@ -525,15 +618,6 @@ let BoardListPage = class BoardListPage extends BoardListPageBase {
|
|
|
525
618
|
favorites: data.myFavorites.map(favorite => favorite.routing)
|
|
526
619
|
});
|
|
527
620
|
}
|
|
528
|
-
_notify(level, message, ex) {
|
|
529
|
-
document.dispatchEvent(new CustomEvent('notify', {
|
|
530
|
-
detail: {
|
|
531
|
-
level,
|
|
532
|
-
message,
|
|
533
|
-
ex
|
|
534
|
-
}
|
|
535
|
-
}));
|
|
536
|
-
}
|
|
537
621
|
};
|
|
538
622
|
__decorate([
|
|
539
623
|
property({ type: String }),
|
|
@@ -563,6 +647,10 @@ __decorate([
|
|
|
563
647
|
query('board-tile-list'),
|
|
564
648
|
__metadata("design:type", HTMLElement)
|
|
565
649
|
], BoardListPage.prototype, "scrollTargetEl", void 0);
|
|
650
|
+
__decorate([
|
|
651
|
+
state(),
|
|
652
|
+
__metadata("design:type", Array)
|
|
653
|
+
], BoardListPage.prototype, "_updatedBoardIds", void 0);
|
|
566
654
|
BoardListPage = __decorate([
|
|
567
655
|
customElement('board-list-page'),
|
|
568
656
|
__metadata("design:paramtypes", [])
|