@operato/attachment 10.20.0 → 10.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/ox-attachment-list.d.ts +3 -38
- package/dist/src/ox-attachment-list.js +37 -13
- package/dist/src/ox-attachment-list.js.map +1 -1
- package/dist/src/ox-attachment-tile.d.ts +14 -0
- package/dist/src/ox-attachment-tile.js +194 -0
- package/dist/src/ox-attachment-tile.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [10.23.0](https://github.com/hatiolab/operato/compare/v10.22.0...v10.23.0) (2026-09-24)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :rocket: New Features
|
|
10
|
+
|
|
11
|
+
* **attachment:** quiet cards for the attachment list; outlined card gutters ([97081d1](https://github.com/hatiolab/operato/commit/97081d17e37d99ae231317938329ccb52b4bfae6))
|
|
12
|
+
* **attachment:** tiles for files that are not pictures; one-line card titles ([371cafc](https://github.com/hatiolab/operato/commit/371cafc2b9745a2b15b7870f843767aff5646632))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### :bug: Bug Fix
|
|
16
|
+
|
|
17
|
+
* **attachment:** card actions as five quiet icons, so the row fits any card width ([1eb0665](https://github.com/hatiolab/operato/commit/1eb066581aa215957d98a1a8e7851af650c159ca))
|
|
18
|
+
* **attachment:** draw the tile for files with no server thumbnail; tooltips on card fields ([4a0ee28](https://github.com/hatiolab/operato/commit/4a0ee28396564f098aca8f0b365be65921d24e07))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## [10.22.0](https://github.com/hatiolab/operato/compare/v10.21.0...v10.22.0) (2026-09-24)
|
|
23
|
+
|
|
24
|
+
**Note:** Version bump only for package @operato/attachment
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
6
30
|
## [10.20.0](https://github.com/hatiolab/operato/compare/v10.19.1...v10.20.0) (2026-09-21)
|
|
7
31
|
|
|
8
32
|
**Note:** Version bump only for package @operato/attachment
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAA","sourcesContent":["export * from './ox-attachment-list.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA","sourcesContent":["export * from './ox-attachment-list.js'\nexport * from './ox-attachment-tile.js'\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import '@operato/data-grist';
|
|
2
|
+
import './ox-attachment-tile.js';
|
|
2
3
|
import '@operato/input/ox-input-file.js';
|
|
3
4
|
import { LitElement } from 'lit';
|
|
4
5
|
import { ColumnConfig, DataGrist, FetchOption, FieldRenderer, FilterValue, GristData, GristRecord, SortersConfig } from '@operato/data-grist';
|
|
@@ -26,7 +27,6 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
26
27
|
icon?: undefined;
|
|
27
28
|
title?: undefined;
|
|
28
29
|
handlers?: undefined;
|
|
29
|
-
iconOnly?: undefined;
|
|
30
30
|
danger?: undefined;
|
|
31
31
|
name?: undefined;
|
|
32
32
|
hidden?: undefined;
|
|
@@ -34,7 +34,6 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
34
34
|
width?: undefined;
|
|
35
35
|
filter?: undefined;
|
|
36
36
|
sortable?: undefined;
|
|
37
|
-
label?: undefined;
|
|
38
37
|
record?: undefined;
|
|
39
38
|
} | {
|
|
40
39
|
type: string;
|
|
@@ -44,7 +43,6 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
44
43
|
handlers: {
|
|
45
44
|
click: (columns: ColumnConfig[], data: GristData, column: ColumnConfig, record: GristRecord, rowIndex: number, target: HTMLElement) => void;
|
|
46
45
|
};
|
|
47
|
-
iconOnly?: undefined;
|
|
48
46
|
danger?: undefined;
|
|
49
47
|
name?: undefined;
|
|
50
48
|
hidden?: undefined;
|
|
@@ -52,31 +50,11 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
52
50
|
width?: undefined;
|
|
53
51
|
filter?: undefined;
|
|
54
52
|
sortable?: undefined;
|
|
55
|
-
label?: undefined;
|
|
56
53
|
record?: undefined;
|
|
57
54
|
} | {
|
|
58
55
|
type: string;
|
|
59
56
|
gutterName: string;
|
|
60
57
|
icon: string;
|
|
61
|
-
iconOnly: boolean;
|
|
62
|
-
title: string;
|
|
63
|
-
handlers: {
|
|
64
|
-
click: (columns: ColumnConfig[], data: GristData, column: ColumnConfig, record: GristRecord, rowIndex: number, target: HTMLElement) => void;
|
|
65
|
-
};
|
|
66
|
-
danger?: undefined;
|
|
67
|
-
name?: undefined;
|
|
68
|
-
hidden?: undefined;
|
|
69
|
-
header?: undefined;
|
|
70
|
-
width?: undefined;
|
|
71
|
-
filter?: undefined;
|
|
72
|
-
sortable?: undefined;
|
|
73
|
-
label?: undefined;
|
|
74
|
-
record?: undefined;
|
|
75
|
-
} | {
|
|
76
|
-
type: string;
|
|
77
|
-
gutterName: string;
|
|
78
|
-
icon: string;
|
|
79
|
-
iconOnly: boolean;
|
|
80
58
|
danger: boolean;
|
|
81
59
|
title: string;
|
|
82
60
|
handlers: {
|
|
@@ -88,7 +66,6 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
88
66
|
width?: undefined;
|
|
89
67
|
filter?: undefined;
|
|
90
68
|
sortable?: undefined;
|
|
91
|
-
label?: undefined;
|
|
92
69
|
record?: undefined;
|
|
93
70
|
} | {
|
|
94
71
|
type: string;
|
|
@@ -98,13 +75,11 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
98
75
|
icon?: undefined;
|
|
99
76
|
title?: undefined;
|
|
100
77
|
handlers?: undefined;
|
|
101
|
-
iconOnly?: undefined;
|
|
102
78
|
danger?: undefined;
|
|
103
79
|
header?: undefined;
|
|
104
80
|
width?: undefined;
|
|
105
81
|
filter?: undefined;
|
|
106
82
|
sortable?: undefined;
|
|
107
|
-
label?: undefined;
|
|
108
83
|
record?: undefined;
|
|
109
84
|
} | {
|
|
110
85
|
type: string;
|
|
@@ -117,10 +92,8 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
117
92
|
icon?: undefined;
|
|
118
93
|
title?: undefined;
|
|
119
94
|
handlers?: undefined;
|
|
120
|
-
iconOnly?: undefined;
|
|
121
95
|
danger?: undefined;
|
|
122
96
|
hidden?: undefined;
|
|
123
|
-
label?: undefined;
|
|
124
97
|
record?: undefined;
|
|
125
98
|
} | {
|
|
126
99
|
type: string;
|
|
@@ -132,11 +105,9 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
132
105
|
icon?: undefined;
|
|
133
106
|
title?: undefined;
|
|
134
107
|
handlers?: undefined;
|
|
135
|
-
iconOnly?: undefined;
|
|
136
108
|
danger?: undefined;
|
|
137
109
|
hidden?: undefined;
|
|
138
110
|
sortable?: undefined;
|
|
139
|
-
label?: undefined;
|
|
140
111
|
record?: undefined;
|
|
141
112
|
} | {
|
|
142
113
|
type: string;
|
|
@@ -153,19 +124,17 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
153
124
|
icon?: undefined;
|
|
154
125
|
title?: undefined;
|
|
155
126
|
handlers?: undefined;
|
|
156
|
-
iconOnly?: undefined;
|
|
157
127
|
danger?: undefined;
|
|
158
128
|
width?: undefined;
|
|
159
129
|
sortable?: undefined;
|
|
160
|
-
label?: undefined;
|
|
161
130
|
record?: undefined;
|
|
162
131
|
} | {
|
|
163
132
|
type: string;
|
|
164
133
|
name: string;
|
|
165
134
|
header: string;
|
|
166
|
-
label: boolean;
|
|
167
135
|
record: {
|
|
168
136
|
editable: boolean;
|
|
137
|
+
renderEmpty?: undefined;
|
|
169
138
|
renderer?: undefined;
|
|
170
139
|
};
|
|
171
140
|
filter: string;
|
|
@@ -174,7 +143,6 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
174
143
|
icon?: undefined;
|
|
175
144
|
title?: undefined;
|
|
176
145
|
handlers?: undefined;
|
|
177
|
-
iconOnly?: undefined;
|
|
178
146
|
danger?: undefined;
|
|
179
147
|
hidden?: undefined;
|
|
180
148
|
sortable?: undefined;
|
|
@@ -184,6 +152,7 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
184
152
|
hidden: boolean;
|
|
185
153
|
record: {
|
|
186
154
|
editable: boolean;
|
|
155
|
+
renderEmpty: boolean;
|
|
187
156
|
renderer: FieldRenderer;
|
|
188
157
|
};
|
|
189
158
|
handlers: {
|
|
@@ -193,12 +162,10 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
193
162
|
gutterName?: undefined;
|
|
194
163
|
icon?: undefined;
|
|
195
164
|
title?: undefined;
|
|
196
|
-
iconOnly?: undefined;
|
|
197
165
|
danger?: undefined;
|
|
198
166
|
header?: undefined;
|
|
199
167
|
filter?: undefined;
|
|
200
168
|
sortable?: undefined;
|
|
201
|
-
label?: undefined;
|
|
202
169
|
} | {
|
|
203
170
|
type: string;
|
|
204
171
|
name: string;
|
|
@@ -209,11 +176,9 @@ export declare class OxAttachmentList extends LitElement {
|
|
|
209
176
|
icon?: undefined;
|
|
210
177
|
title?: undefined;
|
|
211
178
|
handlers?: undefined;
|
|
212
|
-
iconOnly?: undefined;
|
|
213
179
|
danger?: undefined;
|
|
214
180
|
hidden?: undefined;
|
|
215
181
|
filter?: undefined;
|
|
216
|
-
label?: undefined;
|
|
217
182
|
record?: undefined;
|
|
218
183
|
})[];
|
|
219
184
|
rows: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import '@operato/data-grist';
|
|
3
|
+
import './ox-attachment-tile.js';
|
|
3
4
|
import '@operato/input/ox-input-file.js';
|
|
4
5
|
import gql from 'graphql-tag';
|
|
5
6
|
import { css, html, LitElement } from 'lit';
|
|
@@ -161,7 +162,6 @@ let OxAttachmentList = class OxAttachmentList extends LitElement {
|
|
|
161
162
|
type: 'gutter',
|
|
162
163
|
gutterName: 'button',
|
|
163
164
|
icon: 'save_alt',
|
|
164
|
-
iconOnly: false,
|
|
165
165
|
title: i18next.t('button.download'),
|
|
166
166
|
handlers: {
|
|
167
167
|
click: (columns, data, column, record, rowIndex, target) => {
|
|
@@ -178,7 +178,6 @@ let OxAttachmentList = class OxAttachmentList extends LitElement {
|
|
|
178
178
|
type: 'gutter',
|
|
179
179
|
gutterName: 'button',
|
|
180
180
|
icon: 'delete',
|
|
181
|
-
iconOnly: false,
|
|
182
181
|
danger: true,
|
|
183
182
|
title: i18next.t('button.delete'),
|
|
184
183
|
handlers: {
|
|
@@ -224,7 +223,6 @@ let OxAttachmentList = class OxAttachmentList extends LitElement {
|
|
|
224
223
|
type: 'hashtags',
|
|
225
224
|
name: 'tags',
|
|
226
225
|
header: i18next.t('field.hashtags'),
|
|
227
|
-
label: true,
|
|
228
226
|
record: {
|
|
229
227
|
editable: false
|
|
230
228
|
},
|
|
@@ -237,26 +235,25 @@ let OxAttachmentList = class OxAttachmentList extends LitElement {
|
|
|
237
235
|
hidden: true,
|
|
238
236
|
record: {
|
|
239
237
|
editable: false,
|
|
238
|
+
/* A file with no server thumbnail still gets the slot: the renderer draws a tile for it. */
|
|
239
|
+
renderEmpty: true,
|
|
240
240
|
renderer: function (value, column, record, rowIndex, owner) {
|
|
241
241
|
// 1순위: 서버가 생성한 썸네일 (data URI 또는 외부 URL)
|
|
242
242
|
// 이미지/GLTF 등 서버 측에서 썸네일이 있는 타입
|
|
243
243
|
if (record.thumbnail) {
|
|
244
244
|
return html ` <img src=${record.thumbnail} style="max-width: 100%; max-height: 100%;" /> `;
|
|
245
245
|
}
|
|
246
|
-
// 2순위:
|
|
247
|
-
if (record.category == 'video') {
|
|
248
|
-
return html ` <video src=${record.fullpath} style="width: 100%; height: 100%;" controls></video> `;
|
|
249
|
-
}
|
|
250
|
-
// 3순위: 썸네일 없는 이미지는 원본으로 폴백 (기존 attachment 호환)
|
|
246
|
+
// 2순위: 썸네일 없는 이미지는 원본으로 폴백 (기존 attachment 호환)
|
|
251
247
|
if (record.category == 'image') {
|
|
252
248
|
return html ` <img src=${record.fullpath} style="max-width: 100%; max-height: 100%;" /> `;
|
|
253
249
|
}
|
|
254
|
-
//
|
|
250
|
+
// 3순위: 그림이 아닌 파일 - 첫 프레임 · 첫 줄 · 종류 글리프 (ox-attachment-tile)
|
|
255
251
|
return html `
|
|
256
|
-
<
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
252
|
+
<ox-attachment-tile
|
|
253
|
+
.path=${record.path || record.name || ''}
|
|
254
|
+
.mimetype=${record.mimetype || ''}
|
|
255
|
+
.src=${record.fullpath || ''}
|
|
256
|
+
></ox-attachment-tile>
|
|
260
257
|
`;
|
|
261
258
|
}
|
|
262
259
|
},
|
|
@@ -408,6 +405,33 @@ OxAttachmentList.styles = [
|
|
|
408
405
|
|
|
409
406
|
--grid-record-emphasized-background-color: red;
|
|
410
407
|
--grid-record-emphasized-color: yellow;
|
|
408
|
+
|
|
409
|
+
/*
|
|
410
|
+
* The card: the file's picture on a plate across the top, then its name, when it changed,
|
|
411
|
+
* its tags if any, and the actions. One hairline, one radius, the same surfaces the
|
|
412
|
+
* product's other cards use; nothing coloured but the picture and the delete plate.
|
|
413
|
+
*/
|
|
414
|
+
--data-card-min-width: 240px;
|
|
415
|
+
--data-card-record-card-background-color: var(--board-card-surface, var(--md-sys-color-surface-container-lowest));
|
|
416
|
+
--data-card-record-card-background-color-hover: var(--board-card-surface, var(--md-sys-color-surface-container-lowest));
|
|
417
|
+
--data-card-record-card-border: 1px solid var(--md-sys-color-outline-variant);
|
|
418
|
+
--data-card-record-card-border-hover: 1px solid var(--md-sys-color-outline);
|
|
419
|
+
--data-card-record-card-boxshadow-hover: 0 2px 10px rgba(0, 0, 0, 0.08);
|
|
420
|
+
--data-card-record-card-border-radius: 12px;
|
|
421
|
+
--data-card-record-card-padding: 0;
|
|
422
|
+
--data-card-thumbnail-height: 150px;
|
|
423
|
+
--data-card-thumbnail-padding: 12px;
|
|
424
|
+
--data-card-thumbnail-background: var(--board-card-plate, var(--md-sys-color-surface-container));
|
|
425
|
+
--data-card-thumbnail-radius: 11px 11px 0 0;
|
|
426
|
+
--data-card-item-margin: 12px 16px 0;
|
|
427
|
+
--data-card-item-name-font: 600 0.86rem/1.3 var(--theme-font, Roboto, sans-serif);
|
|
428
|
+
--data-card-item-name-lines: 1;
|
|
429
|
+
--ox-attachment-tile-fade: var(--board-card-plate, var(--md-sys-color-surface-container));
|
|
430
|
+
--data-card-item-name-color: var(--md-sys-color-on-surface);
|
|
431
|
+
--data-card-item-etc-font: 0.74rem/1.3 var(--theme-font, Roboto, sans-serif);
|
|
432
|
+
--data-card-item-etc-color: var(--md-sys-color-on-surface-variant);
|
|
433
|
+
--data-card-detail-border-top: none;
|
|
434
|
+
--data-card-gutters-margin: 8px 12px 12px;
|
|
411
435
|
}
|
|
412
436
|
|
|
413
437
|
.header .filters {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-attachment-list.js","sourceRoot":"","sources":["../../src/ox-attachment-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport '@operato/input/ox-input-file.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { openPopup, PopupHandle } from '@operato/popup'\n\nimport {\n ColumnConfig,\n DataGrist,\n FetchOption,\n FieldRenderer,\n FilterValue,\n GristData,\n GristRecord,\n PaginationConfig,\n SortersConfig\n} from '@operato/data-grist'\nimport { buildArgs, client } from '@operato/graphql'\nimport { ScrollbarStyles, CommonGristStyles, CommonHeaderStyles } from '@operato/styles'\nimport { i18next } from '@operato/i18n'\nimport { copyToClipboard, sleep } from '@operato/utils'\n\nconst FETCH_ATTACHMENT_LIST_GQL = (listParam: any) => {\n return gql`\n {\n attachments(${buildArgs(listParam)}) {\n items {\n id\n name\n description\n mimetype\n encoding\n category\n fullpath\n path\n thumbnail\n tags\n createdAt\n updatedAt\n }\n total\n }\n }\n`\n}\n\nconst DELETE_ATTACHMENT_GQL = gql`\n mutation DeleteAttachment($id: String!) {\n deleteAttachment(id: $id)\n }\n`\n\nconst CREATE_ATTACHMENTS_GQL = gql`\n mutation ($attachments: [NewAttachment!]!) {\n createAttachments(attachments: $attachments) {\n id\n name\n description\n mimetype\n encoding\n category\n path\n tags\n createdAt\n updatedAt\n }\n }\n`\n\nconst UPDATE_ATTACHMENT_GQL = gql`\n mutation UpdateAttachment($patch: AttachmentPatch!, $id: String!) {\n updateAttachment(patch: $patch, id: $id) {\n id\n name\n description\n mimetype\n encoding\n category\n path\n tags\n createdAt\n updatedAt\n }\n }\n`\n\n@customElement('ox-attachment-list')\nexport class OxAttachmentList extends LitElement {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n\n width: 100%;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n ox-grist {\n flex: 1;\n overflow-y: auto;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n .header .filters {\n flex-direction: column;\n align-items: stretch;\n }\n `\n ]\n\n @property({ type: String }) category: string = ''\n @property({ type: Boolean }) creatable: boolean = false\n @property({ type: Boolean, attribute: 'without-search' }) withoutSearch: boolean = false\n\n @query('ox-grist') grist!: DataGrist\n @query('ox-input-file') fileUploader!: any\n\n render() {\n return html`\n <ox-grist .config=${this.gristConfig} .mode=${'CARD'} auto-fetch .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-input-file\n accept=\"*/*\"\n multiple=\"true\"\n hide-filelist\n @change=${this.onCreateAttachment.bind(this)}\n ></ox-input-file>\n\n <ox-filters-form autofocus .withoutSearch=${this.withoutSearch}></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {\n const { items: records, total } = await this.getAttachments({ page, limit, filters, sortings })\n\n return {\n total,\n records\n }\n }\n\n get gristConfig() {\n return {\n list: {\n thumbnail: 'thumbnail',\n fields: ['name'],\n details: ['tags', 'updatedAt']\n },\n columns: [\n {\n type: 'gutter',\n gutterName: 'dirty'\n },\n {\n type: 'gutter',\n gutterName: 'sequence'\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'tag',\n title: i18next.t('field.hashtags'),\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n this.popupHashtagEditor(record)\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'open_in_new',\n title: i18next.t('button.open-in-new'),\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n window.open(record.fullpath, '_blank')\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'link',\n title: i18next.t('button.copy-url'),\n handlers: {\n click: async (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): Promise<void> => {\n var { protocol, hostname, port } = location\n await copyToClipboard(`${protocol}//${hostname}:${port}${record.fullpath}`)\n\n target.setAttribute('data-tooltip', 'url copied!')\n\n const rect = target.getBoundingClientRect()\n target.style.setProperty('--tooltip-top', `${rect.top}px`)\n target.style.setProperty('--tooltip-left', `${rect.left}px`)\n\n await sleep(2000)\n target.removeAttribute('data-tooltip')\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'save_alt',\n iconOnly: false,\n title: i18next.t('button.download'),\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n const element = document.createElement('a')\n element.setAttribute('href', record.fullpath)\n element.setAttribute('download', record.name!)\n document.body.appendChild(element)\n element.click()\n element.remove()\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'delete',\n iconOnly: false,\n danger: true,\n title: i18next.t('button.delete'),\n handlers: {\n click: async (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): Promise<void> => {\n await this.deleteAttachment(record.id!)\n this.refreshAttachments()\n }\n }\n },\n {\n type: 'string',\n name: 'id',\n hidden: true\n },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n width: 200,\n filter: 'search',\n sortable: true\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n width: 200,\n filter: 'search'\n },\n {\n type: 'select-buttons',\n name: 'category',\n header: i18next.t('field.category'),\n hidden: true,\n filter: {\n operator: 'in',\n options: ['audio', 'video', 'image', 'text', 'application'],\n value: this.category,\n label: ''\n }\n },\n {\n type: 'hashtags',\n name: 'tags',\n header: i18next.t('field.hashtags'),\n label: true,\n record: {\n editable: false\n },\n filter: 'search',\n width: 200\n },\n {\n type: 'image',\n name: 'thumbnail',\n hidden: true,\n record: {\n editable: false,\n renderer: function (value, column, record, rowIndex, owner) {\n // 1순위: 서버가 생성한 썸네일 (data URI 또는 외부 URL)\n // 이미지/GLTF 등 서버 측에서 썸네일이 있는 타입\n if (record.thumbnail) {\n return html` <img src=${record.thumbnail} style=\"max-width: 100%; max-height: 100%;\" /> `\n }\n // 2순위: 비디오는 원본 컨트롤 재생\n if (record.category == 'video') {\n return html` <video src=${record.fullpath} style=\"width: 100%; height: 100%;\" controls></video> `\n }\n // 3순위: 썸네일 없는 이미지는 원본으로 폴백 (기존 attachment 호환)\n if (record.category == 'image') {\n return html` <img src=${record.fullpath} style=\"max-width: 100%; max-height: 100%;\" /> `\n }\n // 4순위: 일반 파일 아이콘 + 확장자\n return html`\n <div style=\"width: 100%; height: 100%;\" etc>\n <md-icon style=\"--md-icon-size: 24px;\">insert_drive_file</md-icon>\n <span>${record.path.substr(record.path.lastIndexOf('.'))}</span>\n </div>\n `\n } as FieldRenderer\n },\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n this.onClickSelect(record)\n }\n },\n width: 120\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated-at'),\n sortable: true,\n width: 180\n },\n {\n type: 'datetime',\n name: 'createdAt',\n header: i18next.t('field.created-at'),\n sortable: true,\n width: 180\n }\n ],\n rows: {\n appendable: false,\n selectable: {\n multiple: true\n },\n classifier: function (\n record: GristRecord,\n rowIndex: number\n ): { emphasized?: boolean | string | string[]; [key: string]: any } | void {}\n },\n sorters: [\n {\n name: 'name',\n desc: false\n }\n ],\n pagination: {\n pages: [20, 30, 50, 100, 200]\n }\n }\n }\n\n async firstUpdated() {\n this.refreshAttachments()\n }\n\n onClickSelect(attachment: any) {\n this.dispatchEvent(\n new CustomEvent('attachment-selected', {\n composed: true,\n bubbles: true,\n detail: {\n attachment\n }\n })\n )\n }\n\n async onCreateAttachment(e: CustomEvent) {\n const files = e.detail\n\n await this.createAttachments(files)\n this.refreshAttachments()\n }\n\n async onDeleteAttachment(id: string) {\n await this.deleteAttachment(id)\n\n this.refreshAttachments()\n }\n\n async refreshAttachments() {\n this.grist.fetch()\n }\n\n async getAttachments({\n page = 1,\n limit = 30,\n filters = [],\n sortings = []\n }: { page?: number; limit?: number; filters?: FilterValue[]; sortings?: SortersConfig } = {}) {\n var pagination: PaginationConfig = {\n limit,\n page\n }\n\n var params = {\n filters,\n sortings,\n pagination\n }\n\n var attachmentListResponse = await client.query({\n query: FETCH_ATTACHMENT_LIST_GQL(params)\n })\n\n return attachmentListResponse?.data?.attachments || {}\n }\n\n async createAttachments(files: File[]) {\n /*\n ref. https://github.com/jaydenseric/graphql-multipart-request-spec#client\n */\n\n const response = await client.mutate({\n mutation: CREATE_ATTACHMENTS_GQL,\n variables: {\n attachments: files.map(file => {\n return { file }\n })\n },\n context: {\n hasUpload: true\n }\n })\n }\n\n async updateAttachment(patch: any) {\n const response = await client.mutate({\n mutation: UPDATE_ATTACHMENT_GQL,\n variables: patch\n })\n }\n\n async deleteAttachment(id: string) {\n const response = await client.mutate({\n mutation: DELETE_ATTACHMENT_GQL,\n variables: {\n id\n }\n })\n\n return response.data\n }\n\n popupHashtagEditor(record: GristRecord) {\n const hashtags = Array.isArray(record.tags) ? [...record.tags] : []\n\n const confirmCallback = async (newval: any) => {\n await this.updateAttachment({\n id: record.id,\n patch: { tags: newval }\n })\n\n this.refreshAttachments()\n }\n\n openPopup(\n html`\n <ox-popup-hashtags-input .value=${hashtags} .confirmCallback=${confirmCallback}></ox-popup-hashtags-input>\n `,\n {\n backdrop: true,\n title: i18next.t('title.edit hashtags')\n }\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-attachment-list.js","sourceRoot":"","sources":["../../src/ox-attachment-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\nimport './ox-attachment-tile.js'\nimport '@operato/input/ox-input-file.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { openPopup, PopupHandle } from '@operato/popup'\n\nimport {\n ColumnConfig,\n DataGrist,\n FetchOption,\n FieldRenderer,\n FilterValue,\n GristData,\n GristRecord,\n PaginationConfig,\n SortersConfig\n} from '@operato/data-grist'\nimport { buildArgs, client } from '@operato/graphql'\nimport { ScrollbarStyles, CommonGristStyles, CommonHeaderStyles } from '@operato/styles'\nimport { i18next } from '@operato/i18n'\nimport { copyToClipboard, sleep } from '@operato/utils'\n\nconst FETCH_ATTACHMENT_LIST_GQL = (listParam: any) => {\n return gql`\n {\n attachments(${buildArgs(listParam)}) {\n items {\n id\n name\n description\n mimetype\n encoding\n category\n fullpath\n path\n thumbnail\n tags\n createdAt\n updatedAt\n }\n total\n }\n }\n`\n}\n\nconst DELETE_ATTACHMENT_GQL = gql`\n mutation DeleteAttachment($id: String!) {\n deleteAttachment(id: $id)\n }\n`\n\nconst CREATE_ATTACHMENTS_GQL = gql`\n mutation ($attachments: [NewAttachment!]!) {\n createAttachments(attachments: $attachments) {\n id\n name\n description\n mimetype\n encoding\n category\n path\n tags\n createdAt\n updatedAt\n }\n }\n`\n\nconst UPDATE_ATTACHMENT_GQL = gql`\n mutation UpdateAttachment($patch: AttachmentPatch!, $id: String!) {\n updateAttachment(patch: $patch, id: $id) {\n id\n name\n description\n mimetype\n encoding\n category\n path\n tags\n createdAt\n updatedAt\n }\n }\n`\n\n@customElement('ox-attachment-list')\nexport class OxAttachmentList extends LitElement {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n\n width: 100%;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n\n ox-grist {\n flex: 1;\n overflow-y: auto;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n\n /*\n * The card: the file's picture on a plate across the top, then its name, when it changed,\n * its tags if any, and the actions. One hairline, one radius, the same surfaces the\n * product's other cards use; nothing coloured but the picture and the delete plate.\n */\n --data-card-min-width: 240px;\n --data-card-record-card-background-color: var(--board-card-surface, var(--md-sys-color-surface-container-lowest));\n --data-card-record-card-background-color-hover: var(--board-card-surface, var(--md-sys-color-surface-container-lowest));\n --data-card-record-card-border: 1px solid var(--md-sys-color-outline-variant);\n --data-card-record-card-border-hover: 1px solid var(--md-sys-color-outline);\n --data-card-record-card-boxshadow-hover: 0 2px 10px rgba(0, 0, 0, 0.08);\n --data-card-record-card-border-radius: 12px;\n --data-card-record-card-padding: 0;\n --data-card-thumbnail-height: 150px;\n --data-card-thumbnail-padding: 12px;\n --data-card-thumbnail-background: var(--board-card-plate, var(--md-sys-color-surface-container));\n --data-card-thumbnail-radius: 11px 11px 0 0;\n --data-card-item-margin: 12px 16px 0;\n --data-card-item-name-font: 600 0.86rem/1.3 var(--theme-font, Roboto, sans-serif);\n --data-card-item-name-lines: 1;\n --ox-attachment-tile-fade: var(--board-card-plate, var(--md-sys-color-surface-container));\n --data-card-item-name-color: var(--md-sys-color-on-surface);\n --data-card-item-etc-font: 0.74rem/1.3 var(--theme-font, Roboto, sans-serif);\n --data-card-item-etc-color: var(--md-sys-color-on-surface-variant);\n --data-card-detail-border-top: none;\n --data-card-gutters-margin: 8px 12px 12px;\n }\n\n .header .filters {\n flex-direction: column;\n align-items: stretch;\n }\n `\n ]\n\n @property({ type: String }) category: string = ''\n @property({ type: Boolean }) creatable: boolean = false\n @property({ type: Boolean, attribute: 'without-search' }) withoutSearch: boolean = false\n\n @query('ox-grist') grist!: DataGrist\n @query('ox-input-file') fileUploader!: any\n\n render() {\n return html`\n <ox-grist .config=${this.gristConfig} .mode=${'CARD'} auto-fetch .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-input-file\n accept=\"*/*\"\n multiple=\"true\"\n hide-filelist\n @change=${this.onCreateAttachment.bind(this)}\n ></ox-input-file>\n\n <ox-filters-form autofocus .withoutSearch=${this.withoutSearch}></ox-filters-form>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {\n const { items: records, total } = await this.getAttachments({ page, limit, filters, sortings })\n\n return {\n total,\n records\n }\n }\n\n get gristConfig() {\n return {\n list: {\n thumbnail: 'thumbnail',\n fields: ['name'],\n details: ['tags', 'updatedAt']\n },\n columns: [\n {\n type: 'gutter',\n gutterName: 'dirty'\n },\n {\n type: 'gutter',\n gutterName: 'sequence'\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'tag',\n title: i18next.t('field.hashtags'),\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n this.popupHashtagEditor(record)\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'open_in_new',\n title: i18next.t('button.open-in-new'),\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n window.open(record.fullpath, '_blank')\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'link',\n title: i18next.t('button.copy-url'),\n handlers: {\n click: async (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): Promise<void> => {\n var { protocol, hostname, port } = location\n await copyToClipboard(`${protocol}//${hostname}:${port}${record.fullpath}`)\n\n target.setAttribute('data-tooltip', 'url copied!')\n\n const rect = target.getBoundingClientRect()\n target.style.setProperty('--tooltip-top', `${rect.top}px`)\n target.style.setProperty('--tooltip-left', `${rect.left}px`)\n\n await sleep(2000)\n target.removeAttribute('data-tooltip')\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'save_alt',\n title: i18next.t('button.download'),\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n const element = document.createElement('a')\n element.setAttribute('href', record.fullpath)\n element.setAttribute('download', record.name!)\n document.body.appendChild(element)\n element.click()\n element.remove()\n }\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'delete',\n danger: true,\n title: i18next.t('button.delete'),\n handlers: {\n click: async (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): Promise<void> => {\n await this.deleteAttachment(record.id!)\n this.refreshAttachments()\n }\n }\n },\n {\n type: 'string',\n name: 'id',\n hidden: true\n },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n width: 200,\n filter: 'search',\n sortable: true\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n width: 200,\n filter: 'search'\n },\n {\n type: 'select-buttons',\n name: 'category',\n header: i18next.t('field.category'),\n hidden: true,\n filter: {\n operator: 'in',\n options: ['audio', 'video', 'image', 'text', 'application'],\n value: this.category,\n label: ''\n }\n },\n {\n type: 'hashtags',\n name: 'tags',\n header: i18next.t('field.hashtags'),\n record: {\n editable: false\n },\n filter: 'search',\n width: 200\n },\n {\n type: 'image',\n name: 'thumbnail',\n hidden: true,\n record: {\n editable: false,\n /* A file with no server thumbnail still gets the slot: the renderer draws a tile for it. */\n renderEmpty: true,\n renderer: function (value, column, record, rowIndex, owner) {\n // 1순위: 서버가 생성한 썸네일 (data URI 또는 외부 URL)\n // 이미지/GLTF 등 서버 측에서 썸네일이 있는 타입\n if (record.thumbnail) {\n return html` <img src=${record.thumbnail} style=\"max-width: 100%; max-height: 100%;\" /> `\n }\n // 2순위: 썸네일 없는 이미지는 원본으로 폴백 (기존 attachment 호환)\n if (record.category == 'image') {\n return html` <img src=${record.fullpath} style=\"max-width: 100%; max-height: 100%;\" /> `\n }\n // 3순위: 그림이 아닌 파일 - 첫 프레임 · 첫 줄 · 종류 글리프 (ox-attachment-tile)\n return html`\n <ox-attachment-tile\n .path=${record.path || record.name || ''}\n .mimetype=${record.mimetype || ''}\n .src=${record.fullpath || ''}\n ></ox-attachment-tile>\n `\n } as FieldRenderer\n },\n handlers: {\n click: (\n columns: ColumnConfig[],\n data: GristData,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n target: HTMLElement\n ): void => {\n this.onClickSelect(record)\n }\n },\n width: 120\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated-at'),\n sortable: true,\n width: 180\n },\n {\n type: 'datetime',\n name: 'createdAt',\n header: i18next.t('field.created-at'),\n sortable: true,\n width: 180\n }\n ],\n rows: {\n appendable: false,\n selectable: {\n multiple: true\n },\n classifier: function (\n record: GristRecord,\n rowIndex: number\n ): { emphasized?: boolean | string | string[]; [key: string]: any } | void {}\n },\n sorters: [\n {\n name: 'name',\n desc: false\n }\n ],\n pagination: {\n pages: [20, 30, 50, 100, 200]\n }\n }\n }\n\n async firstUpdated() {\n this.refreshAttachments()\n }\n\n onClickSelect(attachment: any) {\n this.dispatchEvent(\n new CustomEvent('attachment-selected', {\n composed: true,\n bubbles: true,\n detail: {\n attachment\n }\n })\n )\n }\n\n async onCreateAttachment(e: CustomEvent) {\n const files = e.detail\n\n await this.createAttachments(files)\n this.refreshAttachments()\n }\n\n async onDeleteAttachment(id: string) {\n await this.deleteAttachment(id)\n\n this.refreshAttachments()\n }\n\n async refreshAttachments() {\n this.grist.fetch()\n }\n\n async getAttachments({\n page = 1,\n limit = 30,\n filters = [],\n sortings = []\n }: { page?: number; limit?: number; filters?: FilterValue[]; sortings?: SortersConfig } = {}) {\n var pagination: PaginationConfig = {\n limit,\n page\n }\n\n var params = {\n filters,\n sortings,\n pagination\n }\n\n var attachmentListResponse = await client.query({\n query: FETCH_ATTACHMENT_LIST_GQL(params)\n })\n\n return attachmentListResponse?.data?.attachments || {}\n }\n\n async createAttachments(files: File[]) {\n /*\n ref. https://github.com/jaydenseric/graphql-multipart-request-spec#client\n */\n\n const response = await client.mutate({\n mutation: CREATE_ATTACHMENTS_GQL,\n variables: {\n attachments: files.map(file => {\n return { file }\n })\n },\n context: {\n hasUpload: true\n }\n })\n }\n\n async updateAttachment(patch: any) {\n const response = await client.mutate({\n mutation: UPDATE_ATTACHMENT_GQL,\n variables: patch\n })\n }\n\n async deleteAttachment(id: string) {\n const response = await client.mutate({\n mutation: DELETE_ATTACHMENT_GQL,\n variables: {\n id\n }\n })\n\n return response.data\n }\n\n popupHashtagEditor(record: GristRecord) {\n const hashtags = Array.isArray(record.tags) ? [...record.tags] : []\n\n const confirmCallback = async (newval: any) => {\n await this.updateAttachment({\n id: record.id,\n patch: { tags: newval }\n })\n\n this.refreshAttachments()\n }\n\n openPopup(\n html`\n <ox-popup-hashtags-input .value=${hashtags} .confirmCallback=${confirmCallback}></ox-popup-hashtags-input>\n `,\n {\n backdrop: true,\n title: i18next.t('title.edit hashtags')\n }\n )\n }\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import '@material/web/icon/icon.js';
|
|
2
|
+
import { LitElement } from 'lit';
|
|
3
|
+
export declare function fileFamilyIcon(mimetype?: string, path?: string): string;
|
|
4
|
+
export declare class OxAttachmentTile extends LitElement {
|
|
5
|
+
static styles: import("lit").CSSResult[];
|
|
6
|
+
path: string;
|
|
7
|
+
mimetype: string;
|
|
8
|
+
src: string;
|
|
9
|
+
private _snippet?;
|
|
10
|
+
private _snippetFor?;
|
|
11
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
12
|
+
updated(): void;
|
|
13
|
+
private _loadSnippet;
|
|
14
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import '@material/web/icon/icon.js';
|
|
3
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
4
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
5
|
+
/*
|
|
6
|
+
* What stands in for a picture when the file is not one.
|
|
7
|
+
*
|
|
8
|
+
* The server thumbnails images and glTF models. Everything else used to get the same grey
|
|
9
|
+
* "insert_drive_file" glyph, so a list of audio, text and zip files was a wall of identical
|
|
10
|
+
* tiles. This tile draws what it can from the file itself, cheaply:
|
|
11
|
+
*
|
|
12
|
+
* - video: the file's own first frame (the browser decodes just the metadata and one frame)
|
|
13
|
+
* - text (txt, csv, json, md, code): the first few lines, fetched with a byte range
|
|
14
|
+
* - everything else: a glyph for the file's family, with its extension
|
|
15
|
+
*
|
|
16
|
+
* A glyph tile is never blank - the family and the extension are the two things a person
|
|
17
|
+
* scans a file list for.
|
|
18
|
+
*/
|
|
19
|
+
const TEXT_PREVIEW_BYTES = 600;
|
|
20
|
+
const FAMILIES = [
|
|
21
|
+
{ test: mime => mime === 'application/pdf', icon: 'picture_as_pdf' },
|
|
22
|
+
{ test: mime => mime.startsWith('audio/'), icon: 'audio_file' },
|
|
23
|
+
{ test: mime => mime.startsWith('video/'), icon: 'video_file' },
|
|
24
|
+
{ test: mime => mime.startsWith('model/'), icon: 'view_in_ar' },
|
|
25
|
+
{ test: mime => mime.startsWith('font/'), icon: 'font_download' },
|
|
26
|
+
{
|
|
27
|
+
test: (mime, ext) => /zip|compressed|tar|gzip|rar|7z/.test(mime) || ['zip', 'tar', 'gz', 'rar', '7z'].includes(ext),
|
|
28
|
+
icon: 'folder_zip'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
test: (mime, ext) => /spreadsheet|excel|csv/.test(mime) || ['xls', 'xlsx', 'csv', 'numbers'].includes(ext),
|
|
32
|
+
icon: 'table_chart'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
test: (mime, ext) => /presentation|powerpoint/.test(mime) || ['ppt', 'pptx', 'key'].includes(ext),
|
|
36
|
+
icon: 'slideshow'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
test: (mime, ext) => /msword|wordprocessing|rtf/.test(mime) || ['doc', 'docx', 'pages'].includes(ext),
|
|
40
|
+
icon: 'description'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
test: (mime, ext) => /json|xml|javascript|typescript|yaml|x-sh/.test(mime) ||
|
|
44
|
+
['js', 'ts', 'json', 'xml', 'yaml', 'yml', 'sh', 'py', 'java', 'css', 'html'].includes(ext),
|
|
45
|
+
icon: 'code'
|
|
46
|
+
},
|
|
47
|
+
{ test: mime => mime.startsWith('text/'), icon: 'article' }
|
|
48
|
+
];
|
|
49
|
+
function extensionOf(path = '') {
|
|
50
|
+
const dot = path.lastIndexOf('.');
|
|
51
|
+
return dot >= 0 ? path.slice(dot + 1).toLowerCase() : '';
|
|
52
|
+
}
|
|
53
|
+
export function fileFamilyIcon(mimetype = '', path = '') {
|
|
54
|
+
var _a;
|
|
55
|
+
const ext = extensionOf(path);
|
|
56
|
+
return ((_a = FAMILIES.find(family => family.test(mimetype, ext))) === null || _a === void 0 ? void 0 : _a.icon) || 'draft';
|
|
57
|
+
}
|
|
58
|
+
function isTextLike(mimetype = '', ext) {
|
|
59
|
+
return (mimetype.startsWith('text/') ||
|
|
60
|
+
/json|xml|javascript|yaml|x-sh/.test(mimetype) ||
|
|
61
|
+
['txt', 'md', 'csv', 'json', 'xml', 'yaml', 'yml', 'log', 'js', 'ts', 'py', 'sh', 'css', 'html', 'sql'].includes(ext));
|
|
62
|
+
}
|
|
63
|
+
let OxAttachmentTile = class OxAttachmentTile extends LitElement {
|
|
64
|
+
constructor() {
|
|
65
|
+
super(...arguments);
|
|
66
|
+
this.path = '';
|
|
67
|
+
this.mimetype = '';
|
|
68
|
+
this.src = '';
|
|
69
|
+
}
|
|
70
|
+
render() {
|
|
71
|
+
const ext = extensionOf(this.path);
|
|
72
|
+
const mime = this.mimetype || '';
|
|
73
|
+
if (mime.startsWith('video/') && this.src) {
|
|
74
|
+
return html `<video src="${this.src}#t=0.5" preload="metadata" muted playsinline></video>`;
|
|
75
|
+
}
|
|
76
|
+
if (this._snippet) {
|
|
77
|
+
return html `<pre text>${this._snippet}</pre>`;
|
|
78
|
+
}
|
|
79
|
+
return html `
|
|
80
|
+
<div glyph>
|
|
81
|
+
<md-icon>${fileFamilyIcon(mime, this.path)}</md-icon>
|
|
82
|
+
${ext ? html `<span ext>${ext}</span>` : nothing}
|
|
83
|
+
</div>
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
updated() {
|
|
87
|
+
const ext = extensionOf(this.path);
|
|
88
|
+
if (this.src && isTextLike(this.mimetype, ext) && this._snippetFor !== this.src) {
|
|
89
|
+
this._snippetFor = this.src;
|
|
90
|
+
this._loadSnippet(this.src);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async _loadSnippet(src) {
|
|
94
|
+
try {
|
|
95
|
+
const response = await fetch(src, { headers: { Range: `bytes=0-${TEXT_PREVIEW_BYTES - 1}` } });
|
|
96
|
+
if (!response.ok)
|
|
97
|
+
return;
|
|
98
|
+
const text = (await response.text()).slice(0, TEXT_PREVIEW_BYTES);
|
|
99
|
+
/* A file that starts with binary or is empty gets the glyph instead. */
|
|
100
|
+
if (!text.trim() || /[\u0000-\u0008\u000e-\u001f]/.test(text))
|
|
101
|
+
return;
|
|
102
|
+
if (this._snippetFor === src)
|
|
103
|
+
this._snippet = text;
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
/* the glyph stays */
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
OxAttachmentTile.styles = [
|
|
111
|
+
css `
|
|
112
|
+
:host {
|
|
113
|
+
display: flex;
|
|
114
|
+
width: 100%;
|
|
115
|
+
height: 100%;
|
|
116
|
+
min-height: 0;
|
|
117
|
+
box-sizing: border-box;
|
|
118
|
+
overflow: hidden;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[glyph] {
|
|
122
|
+
flex: 1;
|
|
123
|
+
display: flex;
|
|
124
|
+
flex-direction: column;
|
|
125
|
+
align-items: center;
|
|
126
|
+
justify-content: center;
|
|
127
|
+
gap: 6px;
|
|
128
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
[glyph] md-icon {
|
|
132
|
+
--md-icon-size: 40px;
|
|
133
|
+
font-variation-settings: 'wght' 300;
|
|
134
|
+
color: var(--md-sys-color-outline);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
[ext] {
|
|
138
|
+
padding: 0 8px;
|
|
139
|
+
border-radius: 999px;
|
|
140
|
+
font-size: 0.66rem;
|
|
141
|
+
font-weight: 600;
|
|
142
|
+
letter-spacing: 0.06em;
|
|
143
|
+
line-height: 18px;
|
|
144
|
+
text-transform: uppercase;
|
|
145
|
+
color: var(--md-sys-color-on-secondary-container);
|
|
146
|
+
background: var(--md-sys-color-secondary-container);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
video {
|
|
150
|
+
width: 100%;
|
|
151
|
+
height: 100%;
|
|
152
|
+
object-fit: contain;
|
|
153
|
+
pointer-events: none;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* The first lines of a text file, as they are, in a small monospace; the fade says "more". */
|
|
157
|
+
[text] {
|
|
158
|
+
position: relative;
|
|
159
|
+
flex: 1;
|
|
160
|
+
margin: 0;
|
|
161
|
+
padding: 10px 12px;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
font: 0.66rem/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
164
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
165
|
+
white-space: pre-wrap;
|
|
166
|
+
word-break: break-all;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
[text]::after {
|
|
170
|
+
content: '';
|
|
171
|
+
position: absolute;
|
|
172
|
+
inset: auto 0 0 0;
|
|
173
|
+
height: 40%;
|
|
174
|
+
background: linear-gradient(to bottom, transparent, var(--ox-attachment-tile-fade, var(--md-sys-color-surface-container)));
|
|
175
|
+
}
|
|
176
|
+
`
|
|
177
|
+
];
|
|
178
|
+
__decorate([
|
|
179
|
+
property({ type: String })
|
|
180
|
+
], OxAttachmentTile.prototype, "path", void 0);
|
|
181
|
+
__decorate([
|
|
182
|
+
property({ type: String })
|
|
183
|
+
], OxAttachmentTile.prototype, "mimetype", void 0);
|
|
184
|
+
__decorate([
|
|
185
|
+
property({ type: String })
|
|
186
|
+
], OxAttachmentTile.prototype, "src", void 0);
|
|
187
|
+
__decorate([
|
|
188
|
+
state()
|
|
189
|
+
], OxAttachmentTile.prototype, "_snippet", void 0);
|
|
190
|
+
OxAttachmentTile = __decorate([
|
|
191
|
+
customElement('ox-attachment-tile')
|
|
192
|
+
], OxAttachmentTile);
|
|
193
|
+
export { OxAttachmentTile };
|
|
194
|
+
//# sourceMappingURL=ox-attachment-tile.js.map
|