@fiduswriter/image-manager 0.1.4 → 0.1.6
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/README.md +53 -3
- package/dist/copyright_dialog/index.d.ts +10 -13
- package/dist/copyright_dialog/index.d.ts.map +1 -1
- package/dist/copyright_dialog/index.js +32 -14
- package/dist/copyright_dialog/index.js.map +1 -1
- package/dist/copyright_dialog/templates.d.ts +16 -12
- package/dist/copyright_dialog/templates.d.ts.map +1 -1
- package/dist/copyright_dialog/templates.js.map +1 -1
- package/dist/database.d.ts +7 -6
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +17 -11
- package/dist/database.js.map +1 -1
- package/dist/edit_dialog/index.d.ts +22 -19
- package/dist/edit_dialog/index.d.ts.map +1 -1
- package/dist/edit_dialog/index.js +65 -33
- package/dist/edit_dialog/index.js.map +1 -1
- package/dist/edit_dialog/model.d.ts +2 -19
- package/dist/edit_dialog/model.d.ts.map +1 -1
- package/dist/edit_dialog/model.js +51 -31
- package/dist/edit_dialog/model.js.map +1 -1
- package/dist/edit_dialog/templates.d.ts +7 -4
- package/dist/edit_dialog/templates.d.ts.map +1 -1
- package/dist/edit_dialog/templates.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/overview/categories.d.ts +7 -5
- package/dist/overview/categories.d.ts.map +1 -1
- package/dist/overview/categories.js +18 -13
- package/dist/overview/categories.js.map +1 -1
- package/dist/overview/index.d.ts +31 -27
- package/dist/overview/index.d.ts.map +1 -1
- package/dist/overview/index.js +64 -33
- package/dist/overview/index.js.map +1 -1
- package/dist/overview/menu.d.ts +4 -47
- package/dist/overview/menu.d.ts.map +1 -1
- package/dist/overview/menu.js +13 -8
- package/dist/overview/menu.js.map +1 -1
- package/dist/overview/templates.d.ts +7 -3
- package/dist/overview/templates.d.ts.map +1 -1
- package/dist/overview/templates.js.map +1 -1
- package/dist/selection_dialog/index.d.ts +17 -15
- package/dist/selection_dialog/index.d.ts.map +1 -1
- package/dist/selection_dialog/index.js +18 -8
- package/dist/selection_dialog/index.js.map +1 -1
- package/dist/types.d.ts +118 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +94 -78
- package/src/copyright_dialog/{index.js → index.ts} +70 -38
- package/src/copyright_dialog/{templates.js → templates.ts} +19 -3
- package/src/database.ts +83 -0
- package/src/edit_dialog/{index.js → index.ts} +110 -45
- package/src/edit_dialog/{model.js → model.ts} +95 -46
- package/src/edit_dialog/{templates.js → templates.ts} +13 -2
- package/src/global.d.ts +37 -0
- package/src/overview/{categories.js → categories.ts} +34 -21
- package/src/overview/{index.js → index.ts} +157 -75
- package/src/overview/menu.ts +85 -0
- package/src/overview/{templates.js → templates.ts} +16 -2
- package/src/selection_dialog/{index.js → index.ts} +85 -49
- package/src/types.ts +133 -0
- package/src/database.js +0 -57
- package/src/overview/menu.js +0 -75
- /package/src/{index.js → index.ts} +0 -0
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import {escapeText} from "fwtoolkit"
|
|
2
2
|
|
|
3
|
+
import type {ImageCategory} from "../types.js"
|
|
4
|
+
|
|
5
|
+
interface CategoryFormsTemplateData {
|
|
6
|
+
categories: ImageCategory[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface EditcategoriesTemplateData {
|
|
10
|
+
categories: ImageCategory[]
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
/** A template for the image category edit form. */
|
|
4
|
-
const usermediaCategoryformsTemplate = ({
|
|
14
|
+
const usermediaCategoryformsTemplate = ({
|
|
15
|
+
categories
|
|
16
|
+
}: CategoryFormsTemplateData) =>
|
|
5
17
|
`${categories
|
|
6
18
|
.map(
|
|
7
19
|
cat =>
|
|
@@ -22,7 +34,9 @@ const usermediaCategoryformsTemplate = ({categories}) =>
|
|
|
22
34
|
</tr>`
|
|
23
35
|
|
|
24
36
|
/** A template to edit image categories. */
|
|
25
|
-
export const usermediaEditcategoriesTemplate = ({
|
|
37
|
+
export const usermediaEditcategoriesTemplate = ({
|
|
38
|
+
categories
|
|
39
|
+
}: EditcategoriesTemplateData) =>
|
|
26
40
|
`<table id="editCategoryList" class="fw-dialog-table">
|
|
27
41
|
<tbody>
|
|
28
42
|
${usermediaCategoryformsTemplate({categories})}
|
|
@@ -1,80 +1,113 @@
|
|
|
1
1
|
import {Dialog, SelectionDataTable, cancelPromise, escapeText, gettext} from "fwtoolkit"
|
|
2
|
+
import type {DialogButtonSpec} from "fwtoolkit/basic"
|
|
3
|
+
import type {DataTable} from "simple-datatables"
|
|
4
|
+
|
|
5
|
+
import type {ImageDB} from "../database.js"
|
|
6
|
+
import type {
|
|
7
|
+
ImageManagerPage,
|
|
8
|
+
ImageSelectionItem
|
|
9
|
+
} from "../types.js"
|
|
2
10
|
|
|
3
11
|
export class ImageSelectionDialog {
|
|
4
|
-
|
|
12
|
+
imageDB: ImageDB
|
|
13
|
+
|
|
14
|
+
userImageDB: ImageDB
|
|
15
|
+
|
|
16
|
+
page: ImageManagerPage
|
|
17
|
+
|
|
18
|
+
imgId: number | false
|
|
19
|
+
|
|
20
|
+
imgDb: "document" | "user" = "document"
|
|
21
|
+
|
|
22
|
+
images: ImageSelectionItem[] = []
|
|
23
|
+
|
|
24
|
+
imageDialog!: Dialog
|
|
25
|
+
|
|
26
|
+
selectionTable!: SelectionDataTable
|
|
27
|
+
|
|
28
|
+
table: DataTable | null = null
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
imageDB: ImageDB,
|
|
32
|
+
userImageDB: ImageDB,
|
|
33
|
+
imgId: number | false,
|
|
34
|
+
page: ImageManagerPage
|
|
35
|
+
) {
|
|
5
36
|
this.imageDB = imageDB
|
|
6
37
|
this.userImageDB = userImageDB
|
|
7
38
|
this.page = page
|
|
8
39
|
this.imgId = imgId // a preselected image
|
|
9
|
-
|
|
40
|
+
// the preselection image will always come from the document
|
|
10
41
|
this.images = [] // images from both databases
|
|
11
42
|
}
|
|
12
43
|
|
|
13
|
-
isE2EE() {
|
|
44
|
+
isE2EE(): boolean {
|
|
14
45
|
return this.page.e2ee?.encrypted === true
|
|
15
46
|
}
|
|
16
47
|
|
|
17
|
-
init() {
|
|
48
|
+
init(): Promise<unknown> {
|
|
18
49
|
console.log(
|
|
19
50
|
"DEBUG selection init: docImages=",
|
|
20
51
|
Object.keys(this.imageDB.db).length,
|
|
21
52
|
"userImages=",
|
|
22
53
|
Object.keys(this.userImageDB.db).length
|
|
23
54
|
)
|
|
24
|
-
this.images = Object.values(this.imageDB.db).map(image => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
})
|
|
55
|
+
this.images = Object.values(this.imageDB.db).map(image => ({
|
|
56
|
+
image,
|
|
57
|
+
db: "document" as const
|
|
58
|
+
}))
|
|
30
59
|
Object.values(this.userImageDB.db).forEach(image => {
|
|
31
60
|
if (this.imageDB.db[image.id]) {
|
|
32
61
|
return
|
|
33
62
|
}
|
|
34
63
|
this.images.push({
|
|
35
64
|
image,
|
|
36
|
-
db: "user"
|
|
65
|
+
db: "user" as const
|
|
37
66
|
})
|
|
38
67
|
})
|
|
39
68
|
console.log("DEBUG selection images=", this.images.length)
|
|
40
|
-
const buttons = []
|
|
69
|
+
const buttons: DialogButtonSpec[] = []
|
|
41
70
|
const p = new Promise(resolve => {
|
|
42
71
|
if (!this.page.app.isOffline()) {
|
|
43
72
|
buttons.push({
|
|
44
73
|
text: gettext("Add new image"),
|
|
45
74
|
icon: "plus-circle",
|
|
46
75
|
click: () => {
|
|
47
|
-
import("../edit_dialog/index.js").then(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
import("../edit_dialog/index.js").then(
|
|
77
|
+
({ImageEditDialog}) => {
|
|
78
|
+
const targetDB = this.isE2EE()
|
|
79
|
+
? this.imageDB
|
|
80
|
+
: this.userImageDB
|
|
81
|
+
const imageUpload = new ImageEditDialog(
|
|
82
|
+
targetDB,
|
|
83
|
+
false,
|
|
84
|
+
this.page
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
resolve(
|
|
88
|
+
imageUpload.init().then(imageId => {
|
|
89
|
+
console.log(
|
|
90
|
+
"DEBUG upload resolved imageId=",
|
|
91
|
+
imageId
|
|
92
|
+
)
|
|
93
|
+
this.imgId = imageId || false
|
|
94
|
+
// For E2EE docs the image goes straight
|
|
95
|
+
// into the document DB, not the user's.
|
|
96
|
+
this.imgDb = this.isE2EE()
|
|
97
|
+
? "document"
|
|
98
|
+
: "user"
|
|
99
|
+
console.log(
|
|
100
|
+
"DEBUG closing selection dialog"
|
|
101
|
+
)
|
|
102
|
+
this.imageDialog.close()
|
|
103
|
+
console.log(
|
|
104
|
+
"DEBUG reinit selection dialog"
|
|
105
|
+
)
|
|
106
|
+
return this.init()
|
|
107
|
+
})
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
)
|
|
78
111
|
}
|
|
79
112
|
})
|
|
80
113
|
}
|
|
@@ -89,7 +122,7 @@ export class ImageSelectionDialog {
|
|
|
89
122
|
})
|
|
90
123
|
|
|
91
124
|
buttons.push({
|
|
92
|
-
type: "cancel",
|
|
125
|
+
type: "cancel" as const,
|
|
93
126
|
click: () => {
|
|
94
127
|
this.imageDialog.close()
|
|
95
128
|
resolve(cancelPromise())
|
|
@@ -109,14 +142,17 @@ export class ImageSelectionDialog {
|
|
|
109
142
|
return p
|
|
110
143
|
}
|
|
111
144
|
|
|
112
|
-
initTable() {
|
|
145
|
+
initTable(): void {
|
|
113
146
|
/* Initialize the overview table */
|
|
114
147
|
const tableEl = document.createElement("table")
|
|
115
148
|
tableEl.classList.add("fw-data-table")
|
|
116
149
|
tableEl.classList.add("fw-small")
|
|
117
150
|
const host = this.imageDialog.dialogEl.querySelector(
|
|
118
151
|
"div.image-selection-table"
|
|
119
|
-
)
|
|
152
|
+
) as HTMLElement | null
|
|
153
|
+
if (!host) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
120
156
|
host.innerHTML = ""
|
|
121
157
|
host.appendChild(tableEl)
|
|
122
158
|
|
|
@@ -154,17 +190,17 @@ export class ImageSelectionDialog {
|
|
|
154
190
|
if (selected.length) {
|
|
155
191
|
const [db, id] = String(selected[0]).split("-")
|
|
156
192
|
this.imgId = Number.parseInt(id)
|
|
157
|
-
this.imgDb = db
|
|
193
|
+
this.imgDb = db as "document" | "user"
|
|
158
194
|
} else {
|
|
159
195
|
this.imgId = false
|
|
160
196
|
}
|
|
161
197
|
}
|
|
162
198
|
})
|
|
163
199
|
this.selectionTable.init()
|
|
164
|
-
this.table = this.selectionTable.table
|
|
200
|
+
this.table = this.selectionTable.table!
|
|
165
201
|
}
|
|
166
202
|
|
|
167
|
-
createTableRow(image) {
|
|
203
|
+
createTableRow(image: ImageSelectionItem): [string, string, string] {
|
|
168
204
|
return [
|
|
169
205
|
`${image.db}-${image.image.id}`,
|
|
170
206
|
image.image.thumbnail === undefined
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type {DataTable} from "simple-datatables"
|
|
2
|
+
import type {ImageDB} from "./database.js"
|
|
3
|
+
|
|
4
|
+
/** A single license under which an image is available. */
|
|
5
|
+
export interface License {
|
|
6
|
+
url: string
|
|
7
|
+
title: string
|
|
8
|
+
start?: string | false
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Copyright and licensing information for an image. */
|
|
12
|
+
export interface Copyright {
|
|
13
|
+
holder?: string | false
|
|
14
|
+
year?: number | false
|
|
15
|
+
freeToRead: boolean
|
|
16
|
+
licenses: License[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** A category used to group images. */
|
|
20
|
+
export interface ImageCategory {
|
|
21
|
+
id: number
|
|
22
|
+
category_title: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A single image as stored in the client-side image database. */
|
|
26
|
+
export interface Image {
|
|
27
|
+
id: number
|
|
28
|
+
title: string
|
|
29
|
+
file_type: string
|
|
30
|
+
image: string
|
|
31
|
+
thumbnail?: string
|
|
32
|
+
width: number
|
|
33
|
+
height: number
|
|
34
|
+
added: number
|
|
35
|
+
cats: number[]
|
|
36
|
+
copyright: Copyright
|
|
37
|
+
[key: string]: unknown
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** End-to-end encryption context passed to dialogs that handle images. */
|
|
41
|
+
export interface E2EEContext {
|
|
42
|
+
encrypted: boolean
|
|
43
|
+
key: CryptoKey
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Subset of the main Fidus Writer app object used by image-manager code. */
|
|
47
|
+
export interface ImageManagerApp {
|
|
48
|
+
imageDB: ImageDB
|
|
49
|
+
isOffline: () => boolean
|
|
50
|
+
settings: {
|
|
51
|
+
APPS: string[]
|
|
52
|
+
MEDIA_MAX_SIZE?: number
|
|
53
|
+
[key: string]: unknown
|
|
54
|
+
}
|
|
55
|
+
name: string
|
|
56
|
+
[key: string]: unknown
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Page object passed to image dialogs. */
|
|
60
|
+
export interface ImageManagerPage {
|
|
61
|
+
app: ImageManagerApp
|
|
62
|
+
e2ee?: E2EEContext
|
|
63
|
+
menu?: unknown
|
|
64
|
+
[key: string]: unknown
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Plugin instance created by the overview's plugin activation. */
|
|
68
|
+
export interface ImageOverviewPlugin {
|
|
69
|
+
init?: () => Promise<unknown> | unknown
|
|
70
|
+
[key: string]: unknown
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Constructor for an image-overview plugin. */
|
|
74
|
+
export interface ImageOverviewPluginConstructor {
|
|
75
|
+
new (overview: unknown): ImageOverviewPlugin
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Row displayed in the image overview data table. */
|
|
79
|
+
export type ImageTableRow = [
|
|
80
|
+
id: number,
|
|
81
|
+
selected: boolean,
|
|
82
|
+
file: string,
|
|
83
|
+
size: string,
|
|
84
|
+
added: string,
|
|
85
|
+
actions: string
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
/** An image selection item coming from either the document or user DB. */
|
|
89
|
+
export interface ImageSelectionItem {
|
|
90
|
+
image: Image
|
|
91
|
+
db: "document" | "user"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Response body from `POST /api/usermedia/images/`. */
|
|
95
|
+
export interface ImagesResponse {
|
|
96
|
+
imageCategories: ImageCategory[]
|
|
97
|
+
images: Image[]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Response body from `POST /api/usermedia/save/`. */
|
|
101
|
+
export interface SaveImageResponse {
|
|
102
|
+
errormsg: Record<string, string> & {error?: string}
|
|
103
|
+
values: Image
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Request body for `POST /api/usermedia/save/`. */
|
|
107
|
+
export interface SaveImageRequest {
|
|
108
|
+
id?: number
|
|
109
|
+
title: string
|
|
110
|
+
copyright: Copyright | string
|
|
111
|
+
cats: (string | number)[]
|
|
112
|
+
image?: File | Blob
|
|
113
|
+
original_file_type?: string
|
|
114
|
+
[key: string]: unknown
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Request body for `POST /api/usermedia/save_category/`. */
|
|
118
|
+
export interface SaveCategoriesRequest {
|
|
119
|
+
ids: (string | number)[]
|
|
120
|
+
titles: string[]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Response body from `POST /api/usermedia/save_category/`. */
|
|
124
|
+
export interface SaveCategoriesResponse {
|
|
125
|
+
entries: ImageCategory[]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Request body for `POST /api/usermedia/delete/`. */
|
|
129
|
+
export interface DeleteImagesRequest {
|
|
130
|
+
ids: (string | number)[]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export type {DataTable}
|
package/src/database.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {activateWait, addAlert, deactivateWait, gettext, postJson} from "fwtoolkit"
|
|
2
|
-
|
|
3
|
-
/* A class that holds information about images uploaded by the user. */
|
|
4
|
-
|
|
5
|
-
export class ImageDB {
|
|
6
|
-
constructor(app) {
|
|
7
|
-
this.app = app
|
|
8
|
-
this.db = {}
|
|
9
|
-
this.cats = []
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
getDB() {
|
|
13
|
-
this.db = {}
|
|
14
|
-
this.cats = []
|
|
15
|
-
|
|
16
|
-
activateWait()
|
|
17
|
-
|
|
18
|
-
return postJson("/api/usermedia/images/").then(({json}) => {
|
|
19
|
-
this.cats = json.imageCategories
|
|
20
|
-
json.images.forEach(image => {
|
|
21
|
-
this.db[image.id] = image
|
|
22
|
-
})
|
|
23
|
-
deactivateWait()
|
|
24
|
-
return
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
saveImage(imageData) {
|
|
29
|
-
activateWait()
|
|
30
|
-
const {image, ...jsonData} = imageData
|
|
31
|
-
|
|
32
|
-
return postJson("/api/usermedia/save/", jsonData, image ? {image} : {})
|
|
33
|
-
.then(({json}) => {
|
|
34
|
-
deactivateWait()
|
|
35
|
-
if (Object.keys(json.errormsg).length) {
|
|
36
|
-
return Promise.reject(new Error(json.errormsg.error))
|
|
37
|
-
} else {
|
|
38
|
-
this.db[json.values.id] = json.values
|
|
39
|
-
return json.values.id
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
.catch(error => {
|
|
43
|
-
if (error.status === 413) {
|
|
44
|
-
addAlert(
|
|
45
|
-
"error",
|
|
46
|
-
`${gettext("Image is larger than the maximum permitted size")}${this.app.settings?.MEDIA_MAX_SIZE ? `: ${Number.parseInt(this.app.settings.MEDIA_MAX_SIZE / 1000000)}MB` : "."}`
|
|
47
|
-
)
|
|
48
|
-
} else if (error.message) {
|
|
49
|
-
addAlert("error", gettext(error.message))
|
|
50
|
-
} else {
|
|
51
|
-
addAlert("error", gettext(error.statusText))
|
|
52
|
-
}
|
|
53
|
-
deactivateWait()
|
|
54
|
-
throw error
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
}
|
package/src/overview/menu.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {gettext} from "fwtoolkit"
|
|
2
|
-
|
|
3
|
-
export const bulkMenuModel = () => ({
|
|
4
|
-
content: [
|
|
5
|
-
{
|
|
6
|
-
title: gettext("Delete selected"),
|
|
7
|
-
tooltip: gettext("Delete selected images."),
|
|
8
|
-
action: overview => {
|
|
9
|
-
const ids = overview.getSelected()
|
|
10
|
-
if (ids.length) {
|
|
11
|
-
overview.deleteImageDialog(ids)
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
disabled: overview =>
|
|
15
|
-
!overview.getSelected().length || overview.app.isOffline()
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
export const menuModel = () => ({
|
|
21
|
-
content: [
|
|
22
|
-
{
|
|
23
|
-
type: "dropdown",
|
|
24
|
-
id: "cat_selector",
|
|
25
|
-
keys: "Alt-c",
|
|
26
|
-
content: [
|
|
27
|
-
{
|
|
28
|
-
title: gettext("All categories"),
|
|
29
|
-
action: _overview => {
|
|
30
|
-
const trs = document.querySelectorAll(
|
|
31
|
-
"#imagelist > tbody > tr"
|
|
32
|
-
)
|
|
33
|
-
trs.forEach(tr => (tr.style.display = ""))
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
order: 1
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: "text",
|
|
41
|
-
title: gettext("Edit categories"),
|
|
42
|
-
keys: "Alt-e",
|
|
43
|
-
action: overview => overview.mod.categories.editCategoryDialog(),
|
|
44
|
-
order: 2,
|
|
45
|
-
disabled: overview => overview.app.isOffline()
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
type: "text",
|
|
49
|
-
title: gettext("Upload new image"),
|
|
50
|
-
keys: "Alt-u",
|
|
51
|
-
action: overview => {
|
|
52
|
-
import("../edit_dialog/index.js").then(({ImageEditDialog}) => {
|
|
53
|
-
const imageUpload = new ImageEditDialog(
|
|
54
|
-
overview.app.imageDB,
|
|
55
|
-
false,
|
|
56
|
-
overview
|
|
57
|
-
)
|
|
58
|
-
imageUpload.init().then(imageId => {
|
|
59
|
-
overview.updateTable([imageId])
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
},
|
|
63
|
-
order: 3,
|
|
64
|
-
disabled: overview => overview.app.isOffline()
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
type: "search",
|
|
68
|
-
icon: "search",
|
|
69
|
-
title: gettext("Search images"),
|
|
70
|
-
keys: "Alt-s",
|
|
71
|
-
input: (overview, text) => overview.table.search(text),
|
|
72
|
-
order: 4
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
})
|
|
File without changes
|