@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
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { DataTable } from "simple-datatables";
|
|
2
|
+
import type { ImageDB } from "./database.js";
|
|
3
|
+
/** A single license under which an image is available. */
|
|
4
|
+
export interface License {
|
|
5
|
+
url: string;
|
|
6
|
+
title: string;
|
|
7
|
+
start?: string | false;
|
|
8
|
+
}
|
|
9
|
+
/** Copyright and licensing information for an image. */
|
|
10
|
+
export interface Copyright {
|
|
11
|
+
holder?: string | false;
|
|
12
|
+
year?: number | false;
|
|
13
|
+
freeToRead: boolean;
|
|
14
|
+
licenses: License[];
|
|
15
|
+
}
|
|
16
|
+
/** A category used to group images. */
|
|
17
|
+
export interface ImageCategory {
|
|
18
|
+
id: number;
|
|
19
|
+
category_title: string;
|
|
20
|
+
}
|
|
21
|
+
/** A single image as stored in the client-side image database. */
|
|
22
|
+
export interface Image {
|
|
23
|
+
id: number;
|
|
24
|
+
title: string;
|
|
25
|
+
file_type: string;
|
|
26
|
+
image: string;
|
|
27
|
+
thumbnail?: string;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
added: number;
|
|
31
|
+
cats: number[];
|
|
32
|
+
copyright: Copyright;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
/** End-to-end encryption context passed to dialogs that handle images. */
|
|
36
|
+
export interface E2EEContext {
|
|
37
|
+
encrypted: boolean;
|
|
38
|
+
key: CryptoKey;
|
|
39
|
+
}
|
|
40
|
+
/** Subset of the main Fidus Writer app object used by image-manager code. */
|
|
41
|
+
export interface ImageManagerApp {
|
|
42
|
+
imageDB: ImageDB;
|
|
43
|
+
isOffline: () => boolean;
|
|
44
|
+
settings: {
|
|
45
|
+
APPS: string[];
|
|
46
|
+
MEDIA_MAX_SIZE?: number;
|
|
47
|
+
[key: string]: unknown;
|
|
48
|
+
};
|
|
49
|
+
name: string;
|
|
50
|
+
[key: string]: unknown;
|
|
51
|
+
}
|
|
52
|
+
/** Page object passed to image dialogs. */
|
|
53
|
+
export interface ImageManagerPage {
|
|
54
|
+
app: ImageManagerApp;
|
|
55
|
+
e2ee?: E2EEContext;
|
|
56
|
+
menu?: unknown;
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
}
|
|
59
|
+
/** Plugin instance created by the overview's plugin activation. */
|
|
60
|
+
export interface ImageOverviewPlugin {
|
|
61
|
+
init?: () => Promise<unknown> | unknown;
|
|
62
|
+
[key: string]: unknown;
|
|
63
|
+
}
|
|
64
|
+
/** Constructor for an image-overview plugin. */
|
|
65
|
+
export interface ImageOverviewPluginConstructor {
|
|
66
|
+
new (overview: unknown): ImageOverviewPlugin;
|
|
67
|
+
}
|
|
68
|
+
/** Row displayed in the image overview data table. */
|
|
69
|
+
export type ImageTableRow = [
|
|
70
|
+
id: number,
|
|
71
|
+
selected: boolean,
|
|
72
|
+
file: string,
|
|
73
|
+
size: string,
|
|
74
|
+
added: string,
|
|
75
|
+
actions: string
|
|
76
|
+
];
|
|
77
|
+
/** An image selection item coming from either the document or user DB. */
|
|
78
|
+
export interface ImageSelectionItem {
|
|
79
|
+
image: Image;
|
|
80
|
+
db: "document" | "user";
|
|
81
|
+
}
|
|
82
|
+
/** Response body from `POST /api/usermedia/images/`. */
|
|
83
|
+
export interface ImagesResponse {
|
|
84
|
+
imageCategories: ImageCategory[];
|
|
85
|
+
images: Image[];
|
|
86
|
+
}
|
|
87
|
+
/** Response body from `POST /api/usermedia/save/`. */
|
|
88
|
+
export interface SaveImageResponse {
|
|
89
|
+
errormsg: Record<string, string> & {
|
|
90
|
+
error?: string;
|
|
91
|
+
};
|
|
92
|
+
values: Image;
|
|
93
|
+
}
|
|
94
|
+
/** Request body for `POST /api/usermedia/save/`. */
|
|
95
|
+
export interface SaveImageRequest {
|
|
96
|
+
id?: number;
|
|
97
|
+
title: string;
|
|
98
|
+
copyright: Copyright | string;
|
|
99
|
+
cats: (string | number)[];
|
|
100
|
+
image?: File | Blob;
|
|
101
|
+
original_file_type?: string;
|
|
102
|
+
[key: string]: unknown;
|
|
103
|
+
}
|
|
104
|
+
/** Request body for `POST /api/usermedia/save_category/`. */
|
|
105
|
+
export interface SaveCategoriesRequest {
|
|
106
|
+
ids: (string | number)[];
|
|
107
|
+
titles: string[];
|
|
108
|
+
}
|
|
109
|
+
/** Response body from `POST /api/usermedia/save_category/`. */
|
|
110
|
+
export interface SaveCategoriesResponse {
|
|
111
|
+
entries: ImageCategory[];
|
|
112
|
+
}
|
|
113
|
+
/** Request body for `POST /api/usermedia/delete/`. */
|
|
114
|
+
export interface DeleteImagesRequest {
|
|
115
|
+
ids: (string | number)[];
|
|
116
|
+
}
|
|
117
|
+
export type { DataTable };
|
|
118
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,85 +1,101 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
"name": "@fiduswriter/image-manager",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Fidus Writer image/media manager",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "ssh://git@codeberg.org/fiduswriter/fiduswriter-image-manager-js.git"
|
|
8
|
+
},
|
|
9
|
+
"license": "AGPL-3.0",
|
|
10
|
+
"author": "Johannes Wilm",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
8
18
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"main": "./dist/index.js",
|
|
13
|
-
"types": "./dist/index.d.ts",
|
|
14
|
-
"exports": {
|
|
15
|
-
".": {
|
|
16
|
-
"types": "./dist/index.d.ts",
|
|
17
|
-
"default": "./dist/index.js"
|
|
18
|
-
},
|
|
19
|
-
"./*": {
|
|
20
|
-
"types": "./dist/*.d.ts",
|
|
21
|
-
"default": "./dist/*.js"
|
|
22
|
-
},
|
|
23
|
-
"./copyright_dialog": {
|
|
24
|
-
"types": "./dist/copyright_dialog/index.d.ts",
|
|
25
|
-
"default": "./dist/copyright_dialog/index.js"
|
|
26
|
-
},
|
|
27
|
-
"./copyright_dialog/*": {
|
|
28
|
-
"types": "./dist/copyright_dialog/*.d.ts",
|
|
29
|
-
"default": "./dist/copyright_dialog/*.js"
|
|
30
|
-
},
|
|
31
|
-
"./edit_dialog": {
|
|
32
|
-
"types": "./dist/edit_dialog/index.d.ts",
|
|
33
|
-
"default": "./dist/edit_dialog/index.js"
|
|
34
|
-
},
|
|
35
|
-
"./edit_dialog/*": {
|
|
36
|
-
"types": "./dist/edit_dialog/*.d.ts",
|
|
37
|
-
"default": "./dist/edit_dialog/*.js"
|
|
38
|
-
},
|
|
39
|
-
"./overview": {
|
|
40
|
-
"types": "./dist/overview/index.d.ts",
|
|
41
|
-
"default": "./dist/overview/index.js"
|
|
42
|
-
},
|
|
43
|
-
"./overview/*": {
|
|
44
|
-
"types": "./dist/overview/*.d.ts",
|
|
45
|
-
"default": "./dist/overview/*.js"
|
|
46
|
-
},
|
|
47
|
-
"./selection_dialog": {
|
|
48
|
-
"types": "./dist/selection_dialog/index.d.ts",
|
|
49
|
-
"default": "./dist/selection_dialog/index.js"
|
|
50
|
-
},
|
|
51
|
-
"./selection_dialog/*": {
|
|
52
|
-
"types": "./dist/selection_dialog/*.d.ts",
|
|
53
|
-
"default": "./dist/selection_dialog/*.js"
|
|
54
|
-
}
|
|
19
|
+
"./*": {
|
|
20
|
+
"types": "./dist/*.d.ts",
|
|
21
|
+
"default": "./dist/*.js"
|
|
55
22
|
},
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
23
|
+
"./copyright_dialog": {
|
|
24
|
+
"types": "./dist/copyright_dialog/index.d.ts",
|
|
25
|
+
"default": "./dist/copyright_dialog/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./copyright_dialog/*": {
|
|
28
|
+
"types": "./dist/copyright_dialog/*.d.ts",
|
|
29
|
+
"default": "./dist/copyright_dialog/*.js"
|
|
30
|
+
},
|
|
31
|
+
"./edit_dialog": {
|
|
32
|
+
"types": "./dist/edit_dialog/index.d.ts",
|
|
33
|
+
"default": "./dist/edit_dialog/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./edit_dialog/*": {
|
|
36
|
+
"types": "./dist/edit_dialog/*.d.ts",
|
|
37
|
+
"default": "./dist/edit_dialog/*.js"
|
|
71
38
|
},
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"fwtoolkit": "^0.1.9"
|
|
39
|
+
"./overview": {
|
|
40
|
+
"types": "./dist/overview/index.d.ts",
|
|
41
|
+
"default": "./dist/overview/index.js"
|
|
76
42
|
},
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
43
|
+
"./overview/*": {
|
|
44
|
+
"types": "./dist/overview/*.d.ts",
|
|
45
|
+
"default": "./dist/overview/*.js"
|
|
46
|
+
},
|
|
47
|
+
"./selection_dialog": {
|
|
48
|
+
"types": "./dist/selection_dialog/index.d.ts",
|
|
49
|
+
"default": "./dist/selection_dialog/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./selection_dialog/*": {
|
|
52
|
+
"types": "./dist/selection_dialog/*.d.ts",
|
|
53
|
+
"default": "./dist/selection_dialog/*.js"
|
|
84
54
|
}
|
|
55
|
+
},
|
|
56
|
+
"files": [
|
|
57
|
+
"dist/",
|
|
58
|
+
"src/",
|
|
59
|
+
"README.md",
|
|
60
|
+
"LICENSE"
|
|
61
|
+
],
|
|
62
|
+
"scripts": {
|
|
63
|
+
"build": "tsc",
|
|
64
|
+
"prepare": "npm run build",
|
|
65
|
+
"prepublishOnly": "npm run build",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"lint": "eslint src",
|
|
68
|
+
"lint:fix": "eslint src --fix",
|
|
69
|
+
"format": "prettier --write .",
|
|
70
|
+
"format:check": "prettier --check .",
|
|
71
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.js"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@fiduswriter/common": "^0.1.4",
|
|
75
|
+
"bibliojson": "^4.0.3",
|
|
76
|
+
"cropperjs": "^1.6.2",
|
|
77
|
+
"fast-deep-equal": "^3.1.3",
|
|
78
|
+
"fwtoolkit": "^0.1.9"
|
|
79
|
+
},
|
|
80
|
+
"devDependencies": {
|
|
81
|
+
"@eslint/js": "^10.0.1",
|
|
82
|
+
"@types/jest": "^30.0.0",
|
|
83
|
+
"eslint": "^10.6.0",
|
|
84
|
+
"globals": "^15.15.0",
|
|
85
|
+
"happy-dom": "^20.10.6",
|
|
86
|
+
"jest": "^30.4.2",
|
|
87
|
+
"prettier": "^3.5.3",
|
|
88
|
+
"ts-jest": "^29.4.11",
|
|
89
|
+
"ts-jest-resolver": "^2.0.1",
|
|
90
|
+
"typescript": "^6.0.3",
|
|
91
|
+
"typescript-eslint": "^8.62.0"
|
|
92
|
+
},
|
|
93
|
+
"lint-staged": {
|
|
94
|
+
"*.{ts,js,mjs,css,md,json,html}": [
|
|
95
|
+
"prettier --write"
|
|
96
|
+
],
|
|
97
|
+
"*.{ts,js,mjs}": [
|
|
98
|
+
"eslint --fix"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
85
101
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {edtfParse} from "bibliojson"
|
|
2
2
|
import deepEqual from "fast-deep-equal"
|
|
3
3
|
import {Dialog, InputList, TypeSwitch, escapeText} from "fwtoolkit"
|
|
4
|
+
import type {InputListItemRenderResult} from "fwtoolkit"
|
|
5
|
+
|
|
4
6
|
import {
|
|
5
7
|
copyrightTemplate,
|
|
6
8
|
licenseInputTemplate,
|
|
7
9
|
licenseSelectTemplate
|
|
8
10
|
} from "./templates.js"
|
|
11
|
+
import type {Copyright, License} from "../types.js"
|
|
9
12
|
|
|
10
13
|
export const LICENSE_URLS = [
|
|
11
14
|
["CC BY 4.0", "https://creativecommons.org/licenses/by/4.0/"],
|
|
@@ -15,42 +18,58 @@ export const LICENSE_URLS = [
|
|
|
15
18
|
["CC BY-NC-SA 4.0", "https://creativecommons.org/licenses/by-nc-sa/4.0/"],
|
|
16
19
|
["CC BY-NC-ND 4.0", "https://creativecommons.org/licenses/by-nc-nd/4.0/"],
|
|
17
20
|
["CC0", "https://creativecommons.org/publicdomain/zero/1.0/"]
|
|
18
|
-
]
|
|
21
|
+
] as [string, string][]
|
|
19
22
|
|
|
20
|
-
function getLicenseTitle(url) {
|
|
23
|
+
function getLicenseTitle(url: string): string {
|
|
21
24
|
const license = LICENSE_URLS.find(license => license[1] === url)
|
|
22
25
|
return license ? license[0] : ""
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
export class CopyrightDialog {
|
|
26
|
-
|
|
29
|
+
copyright: Copyright
|
|
30
|
+
|
|
31
|
+
origCopyright: Copyright
|
|
32
|
+
|
|
33
|
+
dialog: Dialog | false = false
|
|
34
|
+
|
|
35
|
+
licensesList!: InputList<License>
|
|
36
|
+
|
|
37
|
+
constructor(copyright: Copyright) {
|
|
27
38
|
this.copyright = copyright
|
|
28
39
|
this.origCopyright = copyright
|
|
29
40
|
this.dialog = false
|
|
30
41
|
}
|
|
31
42
|
|
|
32
|
-
getCurrentValue() {
|
|
33
|
-
this.
|
|
34
|
-
|
|
43
|
+
getCurrentValue(): void {
|
|
44
|
+
if (!this.dialog) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
const dialogEl = this.dialog.dialogEl
|
|
48
|
+
this.copyright = {} as Copyright
|
|
49
|
+
const holder = (
|
|
50
|
+
dialogEl.querySelector(".holder") as HTMLInputElement
|
|
51
|
+
).value
|
|
35
52
|
this.copyright.holder = holder.length ? holder : false
|
|
36
|
-
const year =
|
|
53
|
+
const year = (
|
|
54
|
+
dialogEl.querySelector(".year") as HTMLInputElement
|
|
55
|
+
).value
|
|
37
56
|
this.copyright.year = year.length
|
|
38
57
|
? Math.max(0, Math.min(Number.parseInt(year) || 0, 2100))
|
|
39
58
|
: false
|
|
40
|
-
this.copyright.freeToRead =
|
|
59
|
+
this.copyright.freeToRead = dialogEl.querySelector(
|
|
41
60
|
".free-to-read:checked"
|
|
42
61
|
)
|
|
43
62
|
? true
|
|
44
63
|
: false
|
|
45
64
|
const licenseStartDates = Array.from(
|
|
46
|
-
|
|
47
|
-
).map(el => el.value)
|
|
65
|
+
dialogEl.querySelectorAll(".license-start")
|
|
66
|
+
).map(el => (el as HTMLInputElement).value)
|
|
48
67
|
this.copyright.licenses = this.licensesList.values
|
|
49
68
|
.map((license, index) => {
|
|
50
69
|
if (!license.url.length) {
|
|
51
70
|
return false
|
|
52
71
|
}
|
|
53
|
-
const returnValue = {
|
|
72
|
+
const returnValue: License = {
|
|
54
73
|
url: license.url,
|
|
55
74
|
title: license.title
|
|
56
75
|
}
|
|
@@ -67,17 +86,17 @@ export class CopyrightDialog {
|
|
|
67
86
|
}
|
|
68
87
|
return returnValue
|
|
69
88
|
})
|
|
70
|
-
.filter(license => license)
|
|
89
|
+
.filter((license): license is License => license !== false)
|
|
71
90
|
}
|
|
72
91
|
|
|
73
|
-
init() {
|
|
92
|
+
init(): Promise<Copyright | false> {
|
|
74
93
|
return new Promise(resolve => {
|
|
75
94
|
const buttons = []
|
|
76
95
|
buttons.push({
|
|
77
96
|
text: gettext("Change"),
|
|
78
97
|
classes: "fw-dark",
|
|
79
98
|
click: () => {
|
|
80
|
-
|
|
99
|
+
dialog.close()
|
|
81
100
|
this.getCurrentValue()
|
|
82
101
|
if (deepEqual(this.copyright, this.origCopyright)) {
|
|
83
102
|
// No change.
|
|
@@ -88,10 +107,10 @@ export class CopyrightDialog {
|
|
|
88
107
|
})
|
|
89
108
|
|
|
90
109
|
buttons.push({
|
|
91
|
-
type: "cancel"
|
|
110
|
+
type: "cancel" as const
|
|
92
111
|
})
|
|
93
112
|
|
|
94
|
-
|
|
113
|
+
const dialog = new Dialog({
|
|
95
114
|
width: 940,
|
|
96
115
|
height: 300,
|
|
97
116
|
id: "configure-copyright",
|
|
@@ -99,28 +118,35 @@ export class CopyrightDialog {
|
|
|
99
118
|
body: copyrightTemplate(this.copyright),
|
|
100
119
|
buttons
|
|
101
120
|
})
|
|
121
|
+
this.dialog = dialog
|
|
102
122
|
|
|
103
|
-
|
|
123
|
+
dialog.open()
|
|
104
124
|
this.bind()
|
|
105
125
|
})
|
|
106
126
|
}
|
|
107
127
|
|
|
108
|
-
bind() {
|
|
109
|
-
this.
|
|
110
|
-
|
|
128
|
+
bind(): void {
|
|
129
|
+
if (!this.dialog) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
const dialogEl = this.dialog.dialogEl
|
|
133
|
+
this.licensesList = new InputList<License>({
|
|
134
|
+
dom: dialogEl.querySelector(
|
|
135
|
+
".copyright-licenses-list"
|
|
136
|
+
) as HTMLElement,
|
|
111
137
|
initialValues: this.copyright.licenses || [],
|
|
112
138
|
emptyValue: {url: "", title: "", start: false},
|
|
113
|
-
renderItem: license => ({
|
|
139
|
+
renderItem: (license): InputListItemRenderResult<License> => ({
|
|
114
140
|
html: `<div class="copyright-license-switch"></div>
|
|
115
141
|
<div class="field-part field-part-small">
|
|
116
142
|
<input type="text" class="license-start" value="${license.start ? escapeText(license.start) : ""}" placeholder="${gettext("Start date")}">
|
|
117
143
|
</div>`,
|
|
118
144
|
bind: el => {
|
|
119
|
-
const licenseContainer = el.closest("tr")
|
|
145
|
+
const licenseContainer = el.closest("tr") as HTMLElement
|
|
120
146
|
const startInput =
|
|
121
147
|
licenseContainer.querySelector(".license-start")
|
|
122
|
-
if (license.start) {
|
|
123
|
-
startInput.value = license.start
|
|
148
|
+
if (license.start && startInput) {
|
|
149
|
+
;(startInput as HTMLInputElement).value = license.start
|
|
124
150
|
}
|
|
125
151
|
|
|
126
152
|
const mode =
|
|
@@ -131,12 +157,13 @@ export class CopyrightDialog {
|
|
|
131
157
|
? 1
|
|
132
158
|
: 2
|
|
133
159
|
new TypeSwitch({
|
|
134
|
-
dom: el.querySelector(
|
|
160
|
+
dom: el.querySelector(
|
|
161
|
+
".copyright-license-switch"
|
|
162
|
+
) as HTMLElement,
|
|
135
163
|
label1: gettext("From list"),
|
|
136
164
|
label2: gettext("Custom"),
|
|
137
|
-
initialMode: mode,
|
|
138
|
-
render1: () =>
|
|
139
|
-
licenseSelectTemplate({url: license.url}),
|
|
165
|
+
initialMode: mode as 1 | 2,
|
|
166
|
+
render1: () => licenseSelectTemplate({url: license.url}),
|
|
140
167
|
render2: () =>
|
|
141
168
|
licenseInputTemplate({
|
|
142
169
|
url: license.url,
|
|
@@ -148,7 +175,7 @@ export class CopyrightDialog {
|
|
|
148
175
|
".fw-type-switch-input-inner input, .fw-type-switch-input-inner select"
|
|
149
176
|
)
|
|
150
177
|
if (focusable) {
|
|
151
|
-
focusable.focus()
|
|
178
|
+
;(focusable as HTMLElement).focus()
|
|
152
179
|
}
|
|
153
180
|
}
|
|
154
181
|
})
|
|
@@ -157,22 +184,27 @@ export class CopyrightDialog {
|
|
|
157
184
|
getValue: el => {
|
|
158
185
|
const licenseInput = el.querySelector(
|
|
159
186
|
".fw-type-switch-input-inner"
|
|
160
|
-
)
|
|
187
|
+
) as HTMLElement
|
|
161
188
|
const selectEl = licenseInput.querySelector("select.license")
|
|
162
|
-
let url, title
|
|
189
|
+
let url: string, title: string
|
|
163
190
|
if (selectEl) {
|
|
164
|
-
url = selectEl.value
|
|
191
|
+
url = (selectEl as HTMLSelectElement).value
|
|
165
192
|
title = getLicenseTitle(url)
|
|
166
193
|
} else {
|
|
167
|
-
url = licenseInput.querySelector("input.license").value
|
|
168
|
-
title = licenseInput.querySelector(
|
|
194
|
+
url = (licenseInput.querySelector("input.license") as HTMLInputElement).value
|
|
195
|
+
title = (licenseInput.querySelector(
|
|
169
196
|
"input.license-title"
|
|
170
|
-
).value
|
|
197
|
+
) as HTMLInputElement).value
|
|
171
198
|
}
|
|
172
199
|
const start =
|
|
173
|
-
el.closest("tr").querySelector(
|
|
174
|
-
|
|
175
|
-
|
|
200
|
+
(el.closest("tr") as HTMLElement).querySelector(
|
|
201
|
+
".license-start"
|
|
202
|
+
)
|
|
203
|
+
return {
|
|
204
|
+
url,
|
|
205
|
+
title,
|
|
206
|
+
start: start ? (start as HTMLInputElement).value || false : false
|
|
207
|
+
}
|
|
176
208
|
}
|
|
177
209
|
})
|
|
178
210
|
}
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import {escapeText} from "fwtoolkit"
|
|
2
|
+
|
|
2
3
|
import {LICENSE_URLS} from "./index.js"
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
interface LicenseSelectTemplateData {
|
|
6
|
+
url: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface LicenseInputTemplateData {
|
|
10
|
+
url: string
|
|
11
|
+
title: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface CopyrightTemplateData {
|
|
15
|
+
holder?: string | false
|
|
16
|
+
year?: number | false
|
|
17
|
+
freeToRead: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const licenseSelectTemplate = ({url}: LicenseSelectTemplateData) =>
|
|
5
21
|
`<select class="license">
|
|
6
22
|
<option value=""></option>
|
|
7
23
|
${LICENSE_URLS.map(
|
|
@@ -11,7 +27,7 @@ export const licenseSelectTemplate = ({url}) =>
|
|
|
11
27
|
</select>
|
|
12
28
|
<div class="fw-select-arrow fa fa-caret-down"></div>`
|
|
13
29
|
|
|
14
|
-
export const licenseInputTemplate = ({url, title}) =>
|
|
30
|
+
export const licenseInputTemplate = ({url, title}: LicenseInputTemplateData) =>
|
|
15
31
|
`<div class="field-part field-part-huge">
|
|
16
32
|
<input type='text' class='license' value="${escapeText(url)}" placeholder="${gettext("License URL")}">
|
|
17
33
|
</div>
|
|
@@ -19,7 +35,7 @@ export const licenseInputTemplate = ({url, title}) =>
|
|
|
19
35
|
<input type='text' class='license-title' value="${escapeText(title)}" placeholder="${gettext("License Title")}">
|
|
20
36
|
</div>`
|
|
21
37
|
|
|
22
|
-
export const copyrightTemplate = ({holder, year, freeToRead}) =>
|
|
38
|
+
export const copyrightTemplate = ({holder, year, freeToRead}: CopyrightTemplateData) =>
|
|
23
39
|
`<table class="fw-dialog-table">
|
|
24
40
|
<tbody>
|
|
25
41
|
<tr>
|
package/src/database.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {activateWait, addAlert, deactivateWait, gettext, postJson} from "fwtoolkit"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Image,
|
|
5
|
+
ImageCategory,
|
|
6
|
+
ImageManagerApp,
|
|
7
|
+
ImagesResponse,
|
|
8
|
+
SaveImageRequest,
|
|
9
|
+
SaveImageResponse
|
|
10
|
+
} from "./types.js"
|
|
11
|
+
|
|
12
|
+
/* A class that holds information about images uploaded by the user. */
|
|
13
|
+
|
|
14
|
+
export class ImageDB {
|
|
15
|
+
app: ImageManagerApp
|
|
16
|
+
|
|
17
|
+
db: Record<number, Image>
|
|
18
|
+
|
|
19
|
+
cats: ImageCategory[]
|
|
20
|
+
|
|
21
|
+
constructor(app: ImageManagerApp) {
|
|
22
|
+
this.app = app
|
|
23
|
+
this.db = {}
|
|
24
|
+
this.cats = []
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getDB(): Promise<void> {
|
|
28
|
+
this.db = {}
|
|
29
|
+
this.cats = []
|
|
30
|
+
|
|
31
|
+
activateWait()
|
|
32
|
+
|
|
33
|
+
return postJson("/api/usermedia/images/").then(({json}) => {
|
|
34
|
+
const response = json as ImagesResponse
|
|
35
|
+
this.cats = response.imageCategories
|
|
36
|
+
response.images.forEach(image => {
|
|
37
|
+
this.db[image.id] = image
|
|
38
|
+
})
|
|
39
|
+
deactivateWait()
|
|
40
|
+
return
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
saveImage(imageData: SaveImageRequest): Promise<number> {
|
|
45
|
+
activateWait()
|
|
46
|
+
const {image, ...jsonData} = imageData
|
|
47
|
+
|
|
48
|
+
return postJson(
|
|
49
|
+
"/api/usermedia/save/",
|
|
50
|
+
jsonData,
|
|
51
|
+
image ? {image} : {}
|
|
52
|
+
)
|
|
53
|
+
.then(({json}) => {
|
|
54
|
+
const response = json as SaveImageResponse
|
|
55
|
+
deactivateWait()
|
|
56
|
+
if (Object.keys(response.errormsg).length) {
|
|
57
|
+
return Promise.reject(new Error(response.errormsg.error))
|
|
58
|
+
} else {
|
|
59
|
+
this.db[response.values.id] = response.values
|
|
60
|
+
return response.values.id
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
.catch(error => {
|
|
64
|
+
const networkError = error as {
|
|
65
|
+
status?: number
|
|
66
|
+
message?: string
|
|
67
|
+
statusText?: string
|
|
68
|
+
}
|
|
69
|
+
if (networkError.status === 413) {
|
|
70
|
+
addAlert(
|
|
71
|
+
"error",
|
|
72
|
+
`${gettext("Image is larger than the maximum permitted size")}${this.app.settings?.MEDIA_MAX_SIZE ? `: ${Number.parseInt(String(this.app.settings.MEDIA_MAX_SIZE / 1000000))}MB` : "."}`
|
|
73
|
+
)
|
|
74
|
+
} else if (networkError.message) {
|
|
75
|
+
addAlert("error", gettext(networkError.message))
|
|
76
|
+
} else {
|
|
77
|
+
addAlert("error", gettext(networkError.statusText || ""))
|
|
78
|
+
}
|
|
79
|
+
deactivateWait()
|
|
80
|
+
throw error
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
}
|