@fiduswriter/image-manager 0.1.12 → 0.1.14
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/copyright_dialog/index.d.ts.map +1 -1
- package/dist/copyright_dialog/index.js +19 -20
- package/dist/copyright_dialog/index.js.map +1 -1
- package/dist/copyright_dialog/templates.d.ts +2 -2
- package/dist/copyright_dialog/templates.d.ts.map +1 -1
- package/dist/copyright_dialog/templates.js +3 -3
- package/dist/copyright_dialog/templates.js.map +1 -1
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +7 -8
- package/dist/database.js.map +1 -1
- package/dist/edit_dialog/index.d.ts.map +1 -1
- package/dist/edit_dialog/index.js +25 -23
- package/dist/edit_dialog/index.js.map +1 -1
- package/dist/edit_dialog/model.d.ts.map +1 -1
- package/dist/edit_dialog/model.js +14 -18
- package/dist/edit_dialog/model.js.map +1 -1
- package/dist/edit_dialog/templates.d.ts.map +1 -1
- package/dist/edit_dialog/templates.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/overview/categories.d.ts.map +1 -1
- package/dist/overview/categories.js +17 -20
- package/dist/overview/categories.js.map +1 -1
- package/dist/overview/index.d.ts.map +1 -1
- package/dist/overview/index.js +7 -2
- package/dist/overview/index.js.map +1 -1
- package/dist/overview/menu.d.ts.map +1 -1
- package/dist/overview/menu.js +13 -15
- package/dist/overview/menu.js.map +1 -1
- package/dist/selection_dialog/index.d.ts.map +1 -1
- package/dist/selection_dialog/index.js +22 -26
- package/dist/selection_dialog/index.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/copyright_dialog/index.ts +177 -186
- package/src/copyright_dialog/templates.ts +26 -19
- package/src/database.ts +61 -68
- package/src/edit_dialog/index.ts +261 -251
- package/src/edit_dialog/model.ts +220 -220
- package/src/edit_dialog/templates.ts +22 -22
- package/src/index.ts +5 -4
- package/src/overview/categories.ts +106 -116
- package/src/overview/index.ts +6 -2
- package/src/overview/menu.ts +77 -77
- package/src/selection_dialog/index.ts +197 -207
- package/src/types.ts +79 -65
package/src/edit_dialog/index.ts
CHANGED
|
@@ -1,287 +1,297 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
CheckableList,
|
|
3
|
+
ContentMenu,
|
|
4
|
+
Dialog,
|
|
5
|
+
addAlert,
|
|
6
|
+
gettext,
|
|
7
|
+
} from "fwtoolkit";
|
|
8
|
+
import type { CheckableListOptions } from "fwtoolkit";
|
|
9
|
+
import type { ContentMenuInit } from "fwtoolkit/content_menu";
|
|
10
|
+
import { E2EEEncryptor } from "fwtoolkit/e2ee/encryptor";
|
|
5
11
|
|
|
6
|
-
import {imageEditModel} from "./model.js"
|
|
7
|
-
import {imageEditTemplate} from "./templates.js"
|
|
8
|
-
import type {ImageDB} from "../database.js"
|
|
12
|
+
import { imageEditModel } from "./model.js";
|
|
13
|
+
import { imageEditTemplate } from "./templates.js";
|
|
14
|
+
import type { ImageDB } from "../database.js";
|
|
9
15
|
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from "../types.js"
|
|
16
|
+
Copyright,
|
|
17
|
+
Image,
|
|
18
|
+
ImageCategory,
|
|
19
|
+
ImageManagerPage,
|
|
20
|
+
SaveImageRequest,
|
|
21
|
+
} from "../types.js";
|
|
16
22
|
|
|
17
23
|
export class ImageEditDialog {
|
|
18
|
-
|
|
24
|
+
imageDB: ImageDB;
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
page: ImageManagerPage;
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
imageId: number | false;
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
dialog: Dialog | false = false;
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
copyright: Copyright;
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
menu: ContentMenuInit;
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
catsList: CheckableList | { value: (string | number)[] } = { value: [] };
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
mediaPreviewerDiv?: HTMLElement;
|
|
33
39
|
|
|
34
|
-
|
|
40
|
+
mediaPreviewer?: HTMLElement;
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
rotation = 0;
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
cropped = false;
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
mediaInput?: File;
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this.showOffline()
|
|
63
|
-
return Promise.resolve()
|
|
64
|
-
}
|
|
65
|
-
const returnPromise = new Promise<number | void>(resolve => {
|
|
66
|
-
let dialog: Dialog
|
|
67
|
-
dialog = new Dialog({
|
|
68
|
-
title: this.imageId
|
|
69
|
-
? gettext("Update Image Information")
|
|
70
|
-
: gettext("Upload Image"),
|
|
71
|
-
id: "editimage",
|
|
72
|
-
classes: "fw-media-uploader",
|
|
73
|
-
body: imageEditTemplate({
|
|
74
|
-
image: this.imageId ? this.imageDB.db[this.imageId] : false,
|
|
75
|
-
cats: this.imageDB.cats
|
|
76
|
-
}),
|
|
77
|
-
buttons: [
|
|
78
|
-
{
|
|
79
|
-
text: this.imageId
|
|
80
|
-
? gettext("Update")
|
|
81
|
-
: gettext("Upload"),
|
|
82
|
-
click: () => resolve(this.saveImage()),
|
|
83
|
-
classes: "fw-dark"
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
type: "cancel",
|
|
87
|
-
classes: "fw-orange",
|
|
88
|
-
click: () => dialog.close()
|
|
89
|
-
}
|
|
90
|
-
]
|
|
91
|
-
})
|
|
92
|
-
this.dialog = dialog
|
|
93
|
-
dialog.open()
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
const image: Image | false = this.imageId
|
|
97
|
-
? this.imageDB.db[this.imageId]
|
|
98
|
-
: false
|
|
99
|
-
const catsEl = document.getElementById("image-edit-categories")
|
|
100
|
-
if (catsEl) {
|
|
101
|
-
const checkableOptions: CheckableListOptions = {
|
|
102
|
-
dom: catsEl,
|
|
103
|
-
options: this.imageDB.cats.map((cat: ImageCategory) => ({
|
|
104
|
-
id: cat.id,
|
|
105
|
-
label: cat.category_title
|
|
106
|
-
})),
|
|
107
|
-
initialValue: image ? image.cats : [],
|
|
108
|
-
multiple: true
|
|
109
|
-
}
|
|
110
|
-
this.catsList = new CheckableList(checkableOptions)
|
|
111
|
-
} else {
|
|
112
|
-
this.catsList = {value: []}
|
|
113
|
-
}
|
|
48
|
+
constructor(
|
|
49
|
+
imageDB: ImageDB,
|
|
50
|
+
imageId: number | false = false,
|
|
51
|
+
page: ImageManagerPage,
|
|
52
|
+
) {
|
|
53
|
+
this.imageDB = imageDB;
|
|
54
|
+
this.page = page;
|
|
55
|
+
this.imageId = imageId;
|
|
56
|
+
this.copyright = this.imageId
|
|
57
|
+
? this.imageDB.db[this.imageId].copyright
|
|
58
|
+
: {
|
|
59
|
+
holder: false,
|
|
60
|
+
year: false,
|
|
61
|
+
freeToRead: true,
|
|
62
|
+
licenses: [],
|
|
63
|
+
};
|
|
64
|
+
this.menu =
|
|
65
|
+
(this.page.menu as { imageEditModel?: ContentMenuInit } | undefined)
|
|
66
|
+
?.imageEditModel || imageEditModel();
|
|
67
|
+
}
|
|
114
68
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
69
|
+
//open a dialog for uploading an image
|
|
70
|
+
init(): Promise<number | void> {
|
|
71
|
+
if (this.page.app.isOffline()) {
|
|
72
|
+
this.showOffline();
|
|
73
|
+
return Promise.resolve();
|
|
74
|
+
}
|
|
75
|
+
const returnPromise = new Promise<number | void>((resolve) => {
|
|
76
|
+
let dialog: Dialog;
|
|
77
|
+
dialog = new Dialog({
|
|
78
|
+
title: this.imageId
|
|
79
|
+
? gettext("Update Image Information")
|
|
80
|
+
: gettext("Upload Image"),
|
|
81
|
+
id: "editimage",
|
|
82
|
+
classes: "fw-media-uploader",
|
|
83
|
+
body: imageEditTemplate({
|
|
84
|
+
image: this.imageId ? this.imageDB.db[this.imageId] : false,
|
|
85
|
+
cats: this.imageDB.cats,
|
|
86
|
+
}),
|
|
87
|
+
buttons: [
|
|
88
|
+
{
|
|
89
|
+
text: this.imageId ? gettext("Update") : gettext("Upload"),
|
|
90
|
+
click: () => resolve(this.saveImage()),
|
|
91
|
+
classes: "fw-dark",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: "cancel",
|
|
95
|
+
classes: "fw-orange",
|
|
96
|
+
click: () => dialog.close(),
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
this.dialog = dialog;
|
|
101
|
+
dialog.open();
|
|
102
|
+
});
|
|
124
103
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
104
|
+
const image: Image | false = this.imageId
|
|
105
|
+
? this.imageDB.db[this.imageId]
|
|
106
|
+
: false;
|
|
107
|
+
const catsEl = document.getElementById("image-edit-categories");
|
|
108
|
+
if (catsEl) {
|
|
109
|
+
const checkableOptions: CheckableListOptions = {
|
|
110
|
+
dom: catsEl,
|
|
111
|
+
options: this.imageDB.cats.map((cat: ImageCategory) => ({
|
|
112
|
+
id: cat.id,
|
|
113
|
+
label: cat.category_title,
|
|
114
|
+
})),
|
|
115
|
+
initialValue: image ? image.cats : [],
|
|
116
|
+
multiple: true,
|
|
117
|
+
};
|
|
118
|
+
this.catsList = new CheckableList(checkableOptions);
|
|
119
|
+
} else {
|
|
120
|
+
this.catsList = { value: [] };
|
|
121
|
+
}
|
|
134
122
|
|
|
135
|
-
|
|
123
|
+
if (!this.imageId) {
|
|
124
|
+
this.bindMediaUploadEvents();
|
|
136
125
|
}
|
|
137
126
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
mediaInputSelector = document.querySelector(
|
|
144
|
-
"#editimage .fw-media-file-input"
|
|
145
|
-
) as HTMLInputElement | null
|
|
146
|
-
this.mediaPreviewerDiv = document.querySelector(
|
|
147
|
-
"#editimage .figure-preview > div"
|
|
148
|
-
) as HTMLElement | null || undefined
|
|
149
|
-
this.rotation = 0
|
|
150
|
-
this.cropped = false
|
|
127
|
+
const figureEditMenu = document.querySelector(".figure-edit-menu");
|
|
128
|
+
if (figureEditMenu) {
|
|
129
|
+
figureEditMenu.addEventListener("click", (event) => {
|
|
130
|
+
event.preventDefault();
|
|
131
|
+
event.stopImmediatePropagation();
|
|
151
132
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
133
|
+
const contentMenu = new ContentMenu({
|
|
134
|
+
menu: this.menu,
|
|
135
|
+
width: 220,
|
|
136
|
+
page: this,
|
|
137
|
+
menuPos: {
|
|
138
|
+
X: (event as MouseEvent).pageX - 50,
|
|
139
|
+
Y: (event as MouseEvent).pageY + 50,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
contentMenu.open();
|
|
143
|
+
});
|
|
144
|
+
}
|
|
155
145
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
})
|
|
146
|
+
return returnPromise;
|
|
147
|
+
}
|
|
159
148
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
149
|
+
//add image upload events
|
|
150
|
+
bindMediaUploadEvents(): void {
|
|
151
|
+
const selectButton = document.querySelector(
|
|
152
|
+
"#editimage .fw-media-select-button",
|
|
153
|
+
) as HTMLButtonElement | null,
|
|
154
|
+
mediaInputSelector = document.querySelector(
|
|
155
|
+
"#editimage .fw-media-file-input",
|
|
156
|
+
) as HTMLInputElement | null;
|
|
157
|
+
this.mediaPreviewerDiv =
|
|
158
|
+
(document.querySelector(
|
|
159
|
+
"#editimage .figure-preview > div",
|
|
160
|
+
) as HTMLElement | null) || undefined;
|
|
161
|
+
this.rotation = 0;
|
|
162
|
+
this.cropped = false;
|
|
164
163
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const fr = new window.FileReader()
|
|
168
|
-
fr.onload = () => {
|
|
169
|
-
this.mediaPreviewerDiv!.innerHTML = `<div class="img" style="background-image: url(${fr.result});" />`
|
|
170
|
-
this.mediaPreviewer =
|
|
171
|
-
this.mediaPreviewerDiv!.querySelector(".img") || undefined
|
|
172
|
-
this.mediaPreviewerDiv!.classList.remove("crop-mode")
|
|
173
|
-
dialog.centerDialog()
|
|
174
|
-
}
|
|
175
|
-
fr.readAsDataURL(this.mediaInput)
|
|
176
|
-
})
|
|
164
|
+
if (!selectButton || !mediaInputSelector || !this.mediaPreviewerDiv) {
|
|
165
|
+
return;
|
|
177
166
|
}
|
|
178
167
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
} else {
|
|
187
|
-
const fieldEl = document.getElementById(`id_${eKey}`)
|
|
188
|
-
if (fieldEl) {
|
|
189
|
-
fieldEl.insertAdjacentHTML("afterend", eMsg)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
})
|
|
168
|
+
selectButton.addEventListener("click", () => {
|
|
169
|
+
mediaInputSelector.click();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const dialog = this.dialog;
|
|
173
|
+
if (!dialog) {
|
|
174
|
+
return;
|
|
193
175
|
}
|
|
194
176
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
} else if (this.mediaPreviewer && this.mediaInput) {
|
|
209
|
-
const mediaPreviewer = this.mediaPreviewer as HTMLElement & {
|
|
210
|
-
currentStyle?: CSSStyleDeclaration
|
|
211
|
-
}
|
|
212
|
-
const mediaPreviewerStyle =
|
|
213
|
-
mediaPreviewer.currentStyle ||
|
|
214
|
-
window.getComputedStyle(
|
|
215
|
-
mediaPreviewer,
|
|
216
|
-
false as unknown as string | null
|
|
217
|
-
)
|
|
218
|
-
const base64data = mediaPreviewerStyle.backgroundImage
|
|
219
|
-
.slice(4, -1)
|
|
220
|
-
.replace(/"/g, "")
|
|
221
|
-
const bstr = atob(base64data.split(",")[1])
|
|
222
|
-
let n = bstr.length
|
|
223
|
-
const u8arr = new Uint8Array(n)
|
|
224
|
-
while (n--) {
|
|
225
|
-
u8arr[n] = bstr.charCodeAt(n)
|
|
226
|
-
}
|
|
227
|
-
imageData.image = new File([u8arr], this.mediaInput.name, {
|
|
228
|
-
type: this.mediaInput.type
|
|
229
|
-
})
|
|
230
|
-
}
|
|
177
|
+
mediaInputSelector.addEventListener("change", () => {
|
|
178
|
+
this.mediaInput = mediaInputSelector.files![0];
|
|
179
|
+
const fr = new window.FileReader();
|
|
180
|
+
fr.onload = () => {
|
|
181
|
+
this.mediaPreviewerDiv!.innerHTML = `<div class="img" style="background-image: url(${fr.result});" />`;
|
|
182
|
+
this.mediaPreviewer =
|
|
183
|
+
this.mediaPreviewerDiv!.querySelector(".img") || undefined;
|
|
184
|
+
this.mediaPreviewerDiv!.classList.remove("crop-mode");
|
|
185
|
+
dialog.centerDialog();
|
|
186
|
+
};
|
|
187
|
+
fr.readAsDataURL(this.mediaInput);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
231
190
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
this.page.e2ee!.key
|
|
244
|
-
)
|
|
191
|
+
displayCreateImageError(errors: Record<string, string>): void {
|
|
192
|
+
Object.keys(errors).forEach((eKey) => {
|
|
193
|
+
const eMsg = `<div class="fw-warning">${errors[eKey]}</div>`;
|
|
194
|
+
if ("error" == eKey) {
|
|
195
|
+
document
|
|
196
|
+
.getElementById("editimage")!
|
|
197
|
+
.insertAdjacentHTML("afterbegin", eMsg);
|
|
198
|
+
} else {
|
|
199
|
+
const fieldEl = document.getElementById(`id_${eKey}`);
|
|
200
|
+
if (fieldEl) {
|
|
201
|
+
fieldEl.insertAdjacentHTML("afterend", eMsg);
|
|
245
202
|
}
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
246
206
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
207
|
+
async saveImage(): Promise<number | void> {
|
|
208
|
+
const titleInput = document.querySelector(
|
|
209
|
+
"#editimage .fw-media-title",
|
|
210
|
+
) as HTMLInputElement | null;
|
|
211
|
+
const imageData: SaveImageRequest = {
|
|
212
|
+
title: titleInput ? titleInput.value : "",
|
|
213
|
+
copyright: this.copyright,
|
|
214
|
+
cats: this.catsList.value,
|
|
215
|
+
};
|
|
216
|
+
if (this.imageId) {
|
|
217
|
+
imageData.id = this.imageId;
|
|
218
|
+
} else if (!this.rotation && !this.cropped && this.mediaInput) {
|
|
219
|
+
imageData.image = this.mediaInput;
|
|
220
|
+
} else if (this.mediaPreviewer && this.mediaInput) {
|
|
221
|
+
const mediaPreviewer = this.mediaPreviewer as HTMLElement & {
|
|
222
|
+
currentStyle?: CSSStyleDeclaration;
|
|
223
|
+
};
|
|
224
|
+
const mediaPreviewerStyle =
|
|
225
|
+
mediaPreviewer.currentStyle ||
|
|
226
|
+
window.getComputedStyle(
|
|
227
|
+
mediaPreviewer,
|
|
228
|
+
false as unknown as string | null,
|
|
229
|
+
);
|
|
230
|
+
const base64data = mediaPreviewerStyle.backgroundImage
|
|
231
|
+
.slice(4, -1)
|
|
232
|
+
.replace(/"/g, "");
|
|
233
|
+
const bstr = atob(base64data.split(",")[1]);
|
|
234
|
+
let n = bstr.length;
|
|
235
|
+
const u8arr = new Uint8Array(n);
|
|
236
|
+
while (n--) {
|
|
237
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
238
|
+
}
|
|
239
|
+
imageData.image = new File([u8arr], this.mediaInput.name, {
|
|
240
|
+
type: this.mediaInput.type,
|
|
241
|
+
});
|
|
277
242
|
}
|
|
278
243
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
244
|
+
// For E2EE documents, encrypt the image and copyright before uploading
|
|
245
|
+
const isE2EE = this.page.e2ee?.encrypted === true;
|
|
246
|
+
if (isE2EE && imageData.image) {
|
|
247
|
+
imageData.image = await E2EEEncryptor.encryptImage(
|
|
248
|
+
imageData.image as File | Blob,
|
|
249
|
+
this.page.e2ee!.key,
|
|
250
|
+
);
|
|
251
|
+
imageData.original_file_type = this.mediaInput?.type || "image/png";
|
|
252
|
+
// Encrypt copyright metadata so the server cannot read it
|
|
253
|
+
imageData.copyright = await E2EEEncryptor.encryptObject(
|
|
254
|
+
imageData.copyright,
|
|
255
|
+
this.page.e2ee!.key,
|
|
256
|
+
);
|
|
286
257
|
}
|
|
258
|
+
|
|
259
|
+
// Remove old warning messages
|
|
260
|
+
document
|
|
261
|
+
.querySelectorAll("#editimage .fw-warning")
|
|
262
|
+
.forEach((el) => el.parentElement!.removeChild(el));
|
|
263
|
+
return new Promise<number | void>((resolve) => {
|
|
264
|
+
const dialog = this.dialog;
|
|
265
|
+
this.imageDB.saveImage(imageData).then(
|
|
266
|
+
(imageId) => {
|
|
267
|
+
if (dialog) {
|
|
268
|
+
dialog.close();
|
|
269
|
+
}
|
|
270
|
+
addAlert("success", gettext("The image has been updated."));
|
|
271
|
+
this.imageId = imageId;
|
|
272
|
+
resolve(imageId);
|
|
273
|
+
},
|
|
274
|
+
(errors) => {
|
|
275
|
+
if (this.page.app.isOffline()) {
|
|
276
|
+
this.showOffline();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
this.displayCreateImageError(errors as Record<string, string>);
|
|
280
|
+
addAlert(
|
|
281
|
+
"error",
|
|
282
|
+
gettext("Some errors were found. Please examine the form."),
|
|
283
|
+
);
|
|
284
|
+
},
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
showOffline(): void {
|
|
290
|
+
addAlert(
|
|
291
|
+
"info",
|
|
292
|
+
gettext(
|
|
293
|
+
"You are currently offline. Please try again after going online.",
|
|
294
|
+
),
|
|
295
|
+
);
|
|
296
|
+
}
|
|
287
297
|
}
|