@fiduswriter/editor 0.1.49 → 0.1.50
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/clipboard/copy/serializers.js.map +1 -1
- package/dist/collab/doc.js.map +1 -1
- package/dist/collab/merge/index.d.ts.map +1 -1
- package/dist/collab/merge/index.js +1 -1
- package/dist/collab/merge/index.js.map +1 -1
- package/dist/comments/editors/comment.d.ts.map +1 -1
- package/dist/comments/editors/comment.js +1 -1
- package/dist/comments/editors/comment.js.map +1 -1
- package/dist/comments/editors/notify.d.ts +2 -1
- package/dist/comments/editors/notify.d.ts.map +1 -1
- package/dist/comments/editors/notify.js +2 -3
- package/dist/comments/editors/notify.js.map +1 -1
- package/dist/comments/interactions.js +2 -2
- package/dist/comments/interactions.js.map +1 -1
- package/dist/contacts/add_dialog.d.ts +3 -1
- package/dist/contacts/add_dialog.d.ts.map +1 -1
- package/dist/contacts/add_dialog.js +11 -8
- package/dist/contacts/add_dialog.js.map +1 -1
- package/dist/databases/images.d.ts.map +1 -1
- package/dist/databases/images.js +8 -5
- package/dist/databases/images.js.map +1 -1
- package/dist/dialogs/citation.js +1 -1
- package/dist/dialogs/citation.js.map +1 -1
- package/dist/document_template/exporter.d.ts +8 -2
- package/dist/document_template/exporter.d.ts.map +1 -1
- package/dist/document_template/exporter.js +4 -8
- package/dist/document_template/exporter.js.map +1 -1
- package/dist/document_template/index.d.ts.map +1 -1
- package/dist/document_template/index.js +1 -1
- package/dist/document_template/index.js.map +1 -1
- package/dist/documents/access_rights/index.d.ts +9 -2
- package/dist/documents/access_rights/index.d.ts.map +1 -1
- package/dist/documents/access_rights/index.js +25 -12
- package/dist/documents/access_rights/index.js.map +1 -1
- package/dist/e2ee/passphrase_urls.d.ts +14 -0
- package/dist/e2ee/passphrase_urls.d.ts.map +1 -0
- package/dist/e2ee/passphrase_urls.js +27 -0
- package/dist/e2ee/passphrase_urls.js.map +1 -0
- package/dist/exporter/native/copy.d.ts +2 -1
- package/dist/exporter/native/copy.d.ts.map +1 -1
- package/dist/exporter/native/copy.js +11 -10
- package/dist/exporter/native/copy.js.map +1 -1
- package/dist/exporter/native/file.d.ts +8 -1
- package/dist/exporter/native/file.d.ts.map +1 -1
- package/dist/exporter/native/file.js +2 -2
- package/dist/exporter/native/file.js.map +1 -1
- package/dist/exporter/native/revision.js +4 -3
- package/dist/exporter/native/revision.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -15
- package/dist/index.js.map +1 -1
- package/dist/menus/headerbar/model.d.ts.map +1 -1
- package/dist/menus/headerbar/model.js +10 -8
- package/dist/menus/headerbar/model.js.map +1 -1
- package/dist/no_collab_save/index.d.ts +1 -1
- package/dist/no_collab_save/index.d.ts.map +1 -1
- package/dist/no_collab_save/index.js +13 -12
- package/dist/no_collab_save/index.js.map +1 -1
- package/dist/state_plugins/inline_reference/dropup.js.map +1 -1
- package/dist/state_plugins/settings.js.map +1 -1
- package/dist/types.d.ts +128 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -6
- package/src/clipboard/copy/serializers.ts +1 -1
- package/src/collab/doc.ts +1 -1
- package/src/collab/merge/index.ts +1 -0
- package/src/comments/editors/comment.ts +6 -1
- package/src/comments/editors/notify.ts +3 -2
- package/src/comments/interactions.ts +2 -2
- package/src/contacts/add_dialog.ts +15 -8
- package/src/databases/images.ts +21 -18
- package/src/dialogs/citation.ts +3 -3
- package/src/document_template/exporter.ts +10 -8
- package/src/document_template/index.ts +3 -2
- package/src/documents/access_rights/index.ts +44 -23
- package/src/exporter/native/copy.ts +18 -10
- package/src/exporter/native/file.ts +9 -1
- package/src/exporter/native/revision.ts +16 -16
- package/src/index.ts +46 -34
- package/src/menus/headerbar/model.ts +17 -9
- package/src/no_collab_save/index.ts +20 -22
- package/src/state_plugins/inline_reference/dropup.ts +2 -2
- package/src/state_plugins/settings.ts +1 -1
- package/src/types.ts +92 -2
|
@@ -43,7 +43,7 @@ class ClipboardDOMSerializer {
|
|
|
43
43
|
settings.citationstyle,
|
|
44
44
|
bibliographyHeader,
|
|
45
45
|
(this.editor.mod.db as any).bibDB,
|
|
46
|
-
|
|
46
|
+
this.editor.app.csl,
|
|
47
47
|
true // synchronous. Should work as the editor has used the same style previously.
|
|
48
48
|
)
|
|
49
49
|
const fm = citRenderer.fm as any
|
package/src/collab/doc.ts
CHANGED
|
@@ -1439,7 +1439,7 @@ export class ModCollabDoc {
|
|
|
1439
1439
|
rid: data["rid"],
|
|
1440
1440
|
footnoterender: data["footnoterender"],
|
|
1441
1441
|
reject_request_id: data["reject_request_id"],
|
|
1442
|
-
...decryptedPayload
|
|
1442
|
+
...(decryptedPayload as Record<string, unknown>)
|
|
1443
1443
|
}
|
|
1444
1444
|
|
|
1445
1445
|
// Process the decrypted diff normally
|
|
@@ -297,7 +297,12 @@ export class CommentEditor {
|
|
|
297
297
|
const comment = this.view.state.doc,
|
|
298
298
|
docId = this.mod.editor.docInfo.id as number
|
|
299
299
|
newUserTags.forEach(userId =>
|
|
300
|
-
notifyMentionedUser(
|
|
300
|
+
notifyMentionedUser(
|
|
301
|
+
this.mod.editor.app.apiConnectors.document,
|
|
302
|
+
docId,
|
|
303
|
+
userId,
|
|
304
|
+
comment
|
|
305
|
+
)
|
|
301
306
|
)
|
|
302
307
|
}
|
|
303
308
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {post} from "fwtoolkit"
|
|
2
1
|
import {serializeCommentNode} from "./schema.js"
|
|
3
2
|
import type {Node} from "prosemirror-model"
|
|
3
|
+
import type {EditorDocumentApi} from "../../types.js"
|
|
4
4
|
|
|
5
5
|
export const notifyMentionedUser = (
|
|
6
|
+
documentApi: EditorDocumentApi,
|
|
6
7
|
docId: number,
|
|
7
8
|
userId: number,
|
|
8
9
|
comment: Node
|
|
9
10
|
) => {
|
|
10
11
|
const {html, text} = serializeCommentNode(comment)
|
|
11
|
-
return
|
|
12
|
+
return documentApi.commentNotify({
|
|
12
13
|
doc_id: docId,
|
|
13
14
|
collaborator_id: userId,
|
|
14
15
|
comment_html: html,
|
|
@@ -3,7 +3,7 @@ import {TextSelection} from "prosemirror-state"
|
|
|
3
3
|
import {GapCursor} from "prosemirror-gapcursor"
|
|
4
4
|
import type {EditorView} from "prosemirror-view"
|
|
5
5
|
|
|
6
|
-
import {findTarget
|
|
6
|
+
import {findTarget} from "fwtoolkit"
|
|
7
7
|
import {READ_ONLY_ROLES} from "../index.js"
|
|
8
8
|
import type {Editor} from "../types.js"
|
|
9
9
|
import {
|
|
@@ -389,7 +389,7 @@ export class ModCommentInteractions {
|
|
|
389
389
|
const comment = this.mod.store.findComment(id)
|
|
390
390
|
const {html, text} = serializeComment(comment.comment)
|
|
391
391
|
|
|
392
|
-
|
|
392
|
+
this.mod.editor.app.apiConnectors.document.commentNotify({
|
|
393
393
|
doc_id: this.mod.editor.docInfo.id,
|
|
394
394
|
collaborator_id: user,
|
|
395
395
|
comment_html: html,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {Dialog, cancelPromise, escapeText
|
|
1
|
+
import {Dialog, cancelPromise, escapeText} from "fwtoolkit"
|
|
2
2
|
import {addContactTemplate} from "./templates.js"
|
|
3
|
+
import type {EditorContactsApi} from "../types.js"
|
|
3
4
|
|
|
4
5
|
interface ContactResponse {
|
|
5
6
|
contact?: unknown
|
|
@@ -9,9 +10,14 @@ interface ContactResponse {
|
|
|
9
10
|
//dialog for adding a user to contacts
|
|
10
11
|
export class AddContactDialog {
|
|
11
12
|
settings: Record<string, unknown>
|
|
13
|
+
contactsApi: EditorContactsApi
|
|
12
14
|
|
|
13
|
-
constructor(
|
|
15
|
+
constructor(
|
|
16
|
+
settings: Record<string, unknown>,
|
|
17
|
+
contactsApi: EditorContactsApi
|
|
18
|
+
) {
|
|
14
19
|
this.settings = settings
|
|
20
|
+
this.contactsApi = contactsApi
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
init(): Promise<unknown[]> {
|
|
@@ -91,24 +97,25 @@ export class AddContactDialog {
|
|
|
91
97
|
return cancelPromise()
|
|
92
98
|
}
|
|
93
99
|
|
|
94
|
-
const {json, status} =
|
|
100
|
+
const {json, status} = await this.contactsApi.add({
|
|
95
101
|
user_string: userString
|
|
96
|
-
})
|
|
102
|
+
})
|
|
103
|
+
const data = json as ContactResponse
|
|
97
104
|
if (status == 201) {
|
|
98
105
|
//user added to the contacts
|
|
99
|
-
return
|
|
106
|
+
return data.contact
|
|
100
107
|
} else {
|
|
101
108
|
//user not found
|
|
102
109
|
let responseHtml
|
|
103
|
-
if (
|
|
110
|
+
if (data.error === 1) {
|
|
104
111
|
responseHtml = gettext(
|
|
105
112
|
"You cannot add yourself to your contacts!"
|
|
106
113
|
)
|
|
107
|
-
} else if (
|
|
114
|
+
} else if (data.error === 2) {
|
|
108
115
|
responseHtml = gettext(
|
|
109
116
|
"This person is already in your contacts!"
|
|
110
117
|
)
|
|
111
|
-
} else if (
|
|
118
|
+
} else if (data.error === 3) {
|
|
112
119
|
responseHtml = gettext("Invalid email!")
|
|
113
120
|
}
|
|
114
121
|
document
|
package/src/databases/images.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
For E2EE documents, images are encrypted client-side and uploaded directly
|
|
10
10
|
via a dedicated endpoint to an EncryptedDocumentImage model.
|
|
11
11
|
*/
|
|
12
|
-
import {addAlert, get
|
|
12
|
+
import {addAlert, get} from "fwtoolkit"
|
|
13
13
|
|
|
14
14
|
import type {Editor} from "../types.js"
|
|
15
15
|
|
|
@@ -60,7 +60,7 @@ export class ModImageDB {
|
|
|
60
60
|
// Set a timeout so that the update can be combines with other updates
|
|
61
61
|
// if they happen more or less simultaneously.
|
|
62
62
|
window.setTimeout(
|
|
63
|
-
() =>
|
|
63
|
+
() => this.mod.editor.mod.collab!.doc.sendToCollaborators(),
|
|
64
64
|
100
|
|
65
65
|
)
|
|
66
66
|
}
|
|
@@ -79,7 +79,9 @@ export class ModImageDB {
|
|
|
79
79
|
const isE2EE = this.mod.editor.e2ee?.encrypted === true
|
|
80
80
|
if (!isE2EE) {
|
|
81
81
|
// Non-E2EE documents must use the user's imageDB
|
|
82
|
-
return
|
|
82
|
+
return this.mod.editor.app.imageDB.saveImage(
|
|
83
|
+
imageData as unknown as Record<string, unknown>
|
|
84
|
+
)
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
// E2EE path: upload encrypted image directly to the document
|
|
@@ -103,7 +105,8 @@ export class ModImageDB {
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
return
|
|
108
|
+
return this.mod.editor.app.apiConnectors.document
|
|
109
|
+
.saveE2EEImage(jsonData, files)
|
|
107
110
|
.then(({json}: {json: any}) => {
|
|
108
111
|
const dbEntry: ImageEntry = {
|
|
109
112
|
id: json.id,
|
|
@@ -122,7 +125,7 @@ export class ModImageDB {
|
|
|
122
125
|
this.setImage(json.id, dbEntry)
|
|
123
126
|
return json.id
|
|
124
127
|
})
|
|
125
|
-
.catch(error => {
|
|
128
|
+
.catch((error: unknown) => {
|
|
126
129
|
addAlert("error", gettext("Could not save encrypted image"))
|
|
127
130
|
throw error
|
|
128
131
|
})
|
|
@@ -160,12 +163,14 @@ export class ModImageDB {
|
|
|
160
163
|
}
|
|
161
164
|
|
|
162
165
|
deleteE2EEImageFromServer(id: number): void {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
this.mod.editor.app.apiConnectors.document
|
|
167
|
+
.deleteE2EEImage({
|
|
168
|
+
doc_id: this.mod.editor.docInfo.id as number,
|
|
169
|
+
image_id: id
|
|
170
|
+
})
|
|
171
|
+
.catch(() => {
|
|
172
|
+
// Silently ignore — orphaned image records are acceptable
|
|
173
|
+
})
|
|
169
174
|
}
|
|
170
175
|
|
|
171
176
|
deleteLocalImage(id: number): void {
|
|
@@ -186,10 +191,10 @@ export class ModImageDB {
|
|
|
186
191
|
// document's unique key and are not reusable across documents.
|
|
187
192
|
return
|
|
188
193
|
}
|
|
189
|
-
const appImageDB =
|
|
194
|
+
const appImageDB = this.mod.editor.app.imageDB
|
|
190
195
|
if (Object.keys(appImageDB.db).includes(String(id))) {
|
|
191
196
|
// Just directly reset the image as we already have the image present in user Image DB
|
|
192
|
-
this.setImage(id, appImageDB.db[id])
|
|
197
|
+
this.setImage(id, appImageDB.db[id] as unknown as ImageEntry)
|
|
193
198
|
} else {
|
|
194
199
|
// If image is not present in both the userImage DB and docDB we can safely assume that we have to upload again.
|
|
195
200
|
this.reUploadImage(
|
|
@@ -256,15 +261,13 @@ export class ModImageDB {
|
|
|
256
261
|
cats: [],
|
|
257
262
|
copyright: copyright
|
|
258
263
|
}
|
|
259
|
-
|
|
264
|
+
this.mod.editor.app.imageDB.saveImage(x).then(
|
|
260
265
|
(newId: number) => {
|
|
261
266
|
const imageData = JSON.parse(
|
|
262
267
|
JSON.stringify(
|
|
263
|
-
|
|
264
|
-
newId
|
|
265
|
-
]
|
|
268
|
+
this.mod.editor.app.imageDB.db[newId]
|
|
266
269
|
)
|
|
267
|
-
)
|
|
270
|
+
) as unknown as ImageEntry
|
|
268
271
|
this.setImage(newId, imageData)
|
|
269
272
|
this.mod.editor.view.state.doc.descendants(
|
|
270
273
|
(node, pos) => {
|
package/src/dialogs/citation.ts
CHANGED
|
@@ -160,8 +160,8 @@ export class CitationDialog {
|
|
|
160
160
|
)
|
|
161
161
|
)
|
|
162
162
|
})
|
|
163
|
-
Object.keys(
|
|
164
|
-
const bib =
|
|
163
|
+
Object.keys(this.editor.app.bibDB!.db).forEach(id => {
|
|
164
|
+
const bib = this.editor.app.bibDB!.db[id]
|
|
165
165
|
if (!(this.editor.mod.db as any).bibDB.hasReference(bib)) {
|
|
166
166
|
data.push(this.createTableRow(bib, Number.parseInt(id), "user"))
|
|
167
167
|
}
|
|
@@ -457,7 +457,7 @@ export class CitationDialog {
|
|
|
457
457
|
if (db === "user") {
|
|
458
458
|
// entry is from user's bibDB. We need to import it into the
|
|
459
459
|
// document's bibDB.
|
|
460
|
-
const bib =
|
|
460
|
+
const bib = this.editor.app.bibDB!.db[String(id)]
|
|
461
461
|
id = (this.editor.mod.db as any).bibDB.addReference(bib, id)
|
|
462
462
|
}
|
|
463
463
|
const returnObj: CitationReference = {
|
|
@@ -2,7 +2,6 @@ import download from "downloadjs"
|
|
|
2
2
|
|
|
3
3
|
import {createSlug} from "@fiduswriter/document/exporter/tools/file"
|
|
4
4
|
import {ZipFileCreator} from "fwtoolkit/file/zip"
|
|
5
|
-
import {postJson} from "fwtoolkit"
|
|
6
5
|
|
|
7
6
|
interface HttpFile {
|
|
8
7
|
filename: string
|
|
@@ -33,7 +32,10 @@ interface TemplateResponse {
|
|
|
33
32
|
|
|
34
33
|
export class DocumentTemplateExporter {
|
|
35
34
|
id: number | string
|
|
36
|
-
|
|
35
|
+
getTemplateForDoc: (
|
|
36
|
+
id: number | string,
|
|
37
|
+
token: string | false
|
|
38
|
+
) => Promise<{json: unknown; status: number}>
|
|
37
39
|
download: boolean
|
|
38
40
|
token: string | false
|
|
39
41
|
zipFileName: string | false
|
|
@@ -43,12 +45,15 @@ export class DocumentTemplateExporter {
|
|
|
43
45
|
|
|
44
46
|
constructor(
|
|
45
47
|
id: number | string,
|
|
46
|
-
|
|
48
|
+
getTemplateForDoc: (
|
|
49
|
+
id: number | string,
|
|
50
|
+
token: string | false
|
|
51
|
+
) => Promise<{json: unknown; status: number}>,
|
|
47
52
|
download = true,
|
|
48
53
|
token: string | false = false
|
|
49
54
|
) {
|
|
50
55
|
this.id = id
|
|
51
|
-
this.
|
|
56
|
+
this.getTemplateForDoc = getTemplateForDoc
|
|
52
57
|
this.download = download
|
|
53
58
|
this.token = token
|
|
54
59
|
|
|
@@ -59,10 +64,7 @@ export class DocumentTemplateExporter {
|
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
init(): Promise<void> {
|
|
62
|
-
|
|
63
|
-
? {id: this.id, token: this.token}
|
|
64
|
-
: {id: this.id}
|
|
65
|
-
return postJson(this.getUrl, params).then(({json}) => {
|
|
67
|
+
return this.getTemplateForDoc(this.id, this.token).then(({json}) => {
|
|
66
68
|
const data = json as TemplateResponse
|
|
67
69
|
this.docVersion = data.doc_version
|
|
68
70
|
this.zipFileName = `${createSlug(data.title)}.fidustemplate`
|
|
@@ -224,7 +224,8 @@ export class ModDocumentTemplate {
|
|
|
224
224
|
"select"
|
|
225
225
|
) as HTMLSelectElement
|
|
226
226
|
).value as any,
|
|
227
|
-
e2eeOptions
|
|
227
|
+
e2eeOptions,
|
|
228
|
+
editor.app.apiConnectors.documentImport
|
|
228
229
|
)
|
|
229
230
|
copier
|
|
230
231
|
.init()
|
|
@@ -232,7 +233,7 @@ export class ModDocumentTemplate {
|
|
|
232
233
|
const url = targetE2EE
|
|
233
234
|
? `/document/${docInfo.id}/?e2ee=1`
|
|
234
235
|
: `/document/${docInfo.id}/`
|
|
235
|
-
|
|
236
|
+
editor.app.goTo(url)
|
|
236
237
|
})
|
|
237
238
|
.catch(() => false)
|
|
238
239
|
selectTemplateDialog.close()
|
|
@@ -6,13 +6,12 @@ import {
|
|
|
6
6
|
enableDatePicker,
|
|
7
7
|
ensureCSS,
|
|
8
8
|
findTarget,
|
|
9
|
-
post,
|
|
10
|
-
postJson,
|
|
11
9
|
setCheckableLabel
|
|
12
10
|
} from "fwtoolkit"
|
|
13
11
|
import type {ContentMenuInit} from "fwtoolkit/content_menu"
|
|
14
12
|
|
|
15
13
|
import {AddContactDialog} from "../../contacts/add_dialog.js"
|
|
14
|
+
import type {EditorContactsApi, EditorDocumentApi} from "../../types.js"
|
|
16
15
|
import {
|
|
17
16
|
collaboratorsTemplate,
|
|
18
17
|
contactsTemplate,
|
|
@@ -66,6 +65,8 @@ interface AccessRightsTabOptions {
|
|
|
66
65
|
onShareSuccess?: (accessRights: AccessRight[]) => void
|
|
67
66
|
settings: Record<string, unknown>
|
|
68
67
|
container?: HTMLElement | null
|
|
68
|
+
documentApi: EditorDocumentApi
|
|
69
|
+
contactsApi: EditorContactsApi
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
interface AccessRightMenuItem {
|
|
@@ -146,6 +147,8 @@ export class AccessRightsTab {
|
|
|
146
147
|
container: HTMLElement | null
|
|
147
148
|
accessRights: AccessRight[]
|
|
148
149
|
dialogTabs!: DialogTabs
|
|
150
|
+
documentApi: EditorDocumentApi
|
|
151
|
+
contactsApi: EditorContactsApi
|
|
149
152
|
|
|
150
153
|
constructor({
|
|
151
154
|
documentIds,
|
|
@@ -155,7 +158,9 @@ export class AccessRightsTab {
|
|
|
155
158
|
documentPassword = "",
|
|
156
159
|
onShareSuccess,
|
|
157
160
|
settings,
|
|
158
|
-
container = null
|
|
161
|
+
container = null,
|
|
162
|
+
documentApi,
|
|
163
|
+
contactsApi
|
|
159
164
|
}: AccessRightsTabOptions) {
|
|
160
165
|
this.documentIds = documentIds
|
|
161
166
|
this.contacts = contacts
|
|
@@ -168,12 +173,15 @@ export class AccessRightsTab {
|
|
|
168
173
|
this.settings = settings
|
|
169
174
|
this.container = container || null
|
|
170
175
|
this.accessRights = []
|
|
176
|
+
this.documentApi = documentApi
|
|
177
|
+
this.contactsApi = contactsApi
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
load(): Promise<void> {
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
|
|
181
|
+
return this.documentApi
|
|
182
|
+
.getAccessRights({
|
|
183
|
+
document_ids: this.documentIds
|
|
184
|
+
})
|
|
177
185
|
.catch(error => {
|
|
178
186
|
addAlert("error", gettext("Cannot load document access data."))
|
|
179
187
|
throw error
|
|
@@ -521,9 +529,8 @@ export class AccessRightsTab {
|
|
|
521
529
|
return
|
|
522
530
|
}
|
|
523
531
|
listEl.innerHTML = `<p class="fw-ar-loading">${gettext("Loading…")}</p>`
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
})
|
|
532
|
+
this.documentApi
|
|
533
|
+
.listShareTokens(this.singleDocumentId as number)
|
|
527
534
|
.then(({json}: {json: unknown}) => {
|
|
528
535
|
const data = json as {tokens: ShareToken[]}
|
|
529
536
|
listEl.innerHTML = shareTokenListTemplate({
|
|
@@ -564,12 +571,13 @@ export class AccessRightsTab {
|
|
|
564
571
|
"#share-token-note"
|
|
565
572
|
) as HTMLInputElement
|
|
566
573
|
).value.trim()
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
574
|
+
this.documentApi
|
|
575
|
+
.createShareToken({
|
|
576
|
+
document_id: this.singleDocumentId,
|
|
577
|
+
rights,
|
|
578
|
+
expires_at: expiresRaw || "",
|
|
579
|
+
note
|
|
580
|
+
} as Record<string, unknown>)
|
|
573
581
|
.then(({json}: {json: unknown}) => {
|
|
574
582
|
const data = json as ShareToken
|
|
575
583
|
let shareUrl = data.share_url
|
|
@@ -624,7 +632,8 @@ export class AccessRightsTab {
|
|
|
624
632
|
}
|
|
625
633
|
|
|
626
634
|
revokeShareToken(tokenId: number, rowEl: HTMLElement): void {
|
|
627
|
-
|
|
635
|
+
this.documentApi
|
|
636
|
+
.revokeShareToken(tokenId)
|
|
628
637
|
.then(({json}: {json: unknown}) => {
|
|
629
638
|
const data = json as {success: boolean}
|
|
630
639
|
if (data.success) {
|
|
@@ -648,10 +657,11 @@ export class AccessRightsTab {
|
|
|
648
657
|
|
|
649
658
|
submit(): Promise<void> {
|
|
650
659
|
const accessRights = collectAccessRights(this.container!)
|
|
651
|
-
return
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
660
|
+
return this.documentApi
|
|
661
|
+
.saveAccessRights({
|
|
662
|
+
document_ids: this.documentIds,
|
|
663
|
+
access_rights: accessRights
|
|
664
|
+
})
|
|
655
665
|
.then(() => {
|
|
656
666
|
addAlert("success", gettext("Access rights have been saved"))
|
|
657
667
|
if (this.onShareSuccess) {
|
|
@@ -676,6 +686,8 @@ export class DocumentAccessRightsDialog {
|
|
|
676
686
|
documentPassword: string
|
|
677
687
|
onShareSuccess?: (accessRights: AccessRight[]) => void
|
|
678
688
|
settings: Record<string, unknown>
|
|
689
|
+
contactsApi: EditorContactsApi
|
|
690
|
+
documentApi: EditorDocumentApi
|
|
679
691
|
tab!: AccessRightsTab
|
|
680
692
|
dialog!: Dialog
|
|
681
693
|
|
|
@@ -686,7 +698,9 @@ export class DocumentAccessRightsDialog {
|
|
|
686
698
|
e2ee: boolean,
|
|
687
699
|
documentPassword = "",
|
|
688
700
|
onShareSuccess?: (accessRights: AccessRight[]) => void,
|
|
689
|
-
settings: Record<string, unknown> = {}
|
|
701
|
+
settings: Record<string, unknown> = {},
|
|
702
|
+
contactsApi?: EditorContactsApi,
|
|
703
|
+
documentApi?: EditorDocumentApi
|
|
690
704
|
) {
|
|
691
705
|
this.documentIds = documentIds
|
|
692
706
|
this.contacts = contacts
|
|
@@ -695,6 +709,8 @@ export class DocumentAccessRightsDialog {
|
|
|
695
709
|
this.documentPassword = documentPassword
|
|
696
710
|
this.onShareSuccess = onShareSuccess
|
|
697
711
|
this.settings = settings
|
|
712
|
+
this.contactsApi = contactsApi as EditorContactsApi
|
|
713
|
+
this.documentApi = documentApi as EditorDocumentApi
|
|
698
714
|
}
|
|
699
715
|
|
|
700
716
|
init(): void {
|
|
@@ -705,7 +721,9 @@ export class DocumentAccessRightsDialog {
|
|
|
705
721
|
e2ee: this.e2ee,
|
|
706
722
|
documentPassword: this.documentPassword,
|
|
707
723
|
onShareSuccess: this.onShareSuccess,
|
|
708
|
-
settings: this.settings
|
|
724
|
+
settings: this.settings,
|
|
725
|
+
documentApi: this.documentApi,
|
|
726
|
+
contactsApi: this.contactsApi
|
|
709
727
|
})
|
|
710
728
|
this.tab.load().then(() => this.createDialog())
|
|
711
729
|
}
|
|
@@ -722,7 +740,10 @@ export class DocumentAccessRightsDialog {
|
|
|
722
740
|
: gettext("Add contact"),
|
|
723
741
|
classes: "fw-light fw-add-button",
|
|
724
742
|
click: () => {
|
|
725
|
-
const dialog = new AddContactDialog(
|
|
743
|
+
const dialog = new AddContactDialog(
|
|
744
|
+
this.settings,
|
|
745
|
+
this.contactsApi
|
|
746
|
+
)
|
|
726
747
|
dialog.init().then(contactsData => {
|
|
727
748
|
;(contactsData as Contact[]).forEach(contactData => {
|
|
728
749
|
if (contactData.id) {
|
|
@@ -9,9 +9,10 @@ import type {
|
|
|
9
9
|
} from "@fiduswriter/document"
|
|
10
10
|
import {SaveCopy as GenericSaveCopy} from "@fiduswriter/document/exporter/native"
|
|
11
11
|
import {NativeImporter} from "@fiduswriter/document/importer/native"
|
|
12
|
-
import {addAlert, addProgress, gettext,
|
|
12
|
+
import {addAlert, addProgress, gettext, shortFileTitle} from "fwtoolkit"
|
|
13
13
|
import {E2EEEncryptor} from "fwtoolkit/e2ee/encryptor"
|
|
14
14
|
import {E2EEKeyManager} from "fwtoolkit/e2ee/key-manager"
|
|
15
|
+
import type {EditorDocumentImportApi} from "../../types.js"
|
|
15
16
|
|
|
16
17
|
type ProgressCallback = (message: string, percentage?: number | null) => void
|
|
17
18
|
|
|
@@ -115,7 +116,8 @@ async function maybeDecryptImage(
|
|
|
115
116
|
|
|
116
117
|
function createNativeImporterBackend(
|
|
117
118
|
_user: User,
|
|
118
|
-
_e2eeOptions: E2EEOptions | null
|
|
119
|
+
_e2eeOptions: E2EEOptions | null,
|
|
120
|
+
documentImportApi: EditorDocumentImportApi
|
|
119
121
|
): NativeImporterBackend {
|
|
120
122
|
return {
|
|
121
123
|
createDoc: (template, importId, path, e2ee, files) => {
|
|
@@ -140,7 +142,8 @@ function createNativeImporterBackend(
|
|
|
140
142
|
jsonData.e2ee_iterations = e2ee.iterations
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
|
-
return
|
|
145
|
+
return documentImportApi
|
|
146
|
+
.createDoc(jsonData, files)
|
|
144
147
|
.then(({json}) => {
|
|
145
148
|
const data = json as Record<string, unknown>
|
|
146
149
|
return {
|
|
@@ -157,9 +160,6 @@ function createNativeImporterBackend(
|
|
|
157
160
|
},
|
|
158
161
|
saveImages: async (images, docId, e2ee) => {
|
|
159
162
|
const isE2EE = e2ee?.enabled
|
|
160
|
-
const endpoint = isE2EE
|
|
161
|
-
? "/api/document/e2ee_image/"
|
|
162
|
-
: "/api/document/import/image/"
|
|
163
163
|
const imageTranslationTable: Record<number | string, number> = {}
|
|
164
164
|
await Promise.all(
|
|
165
165
|
Object.values(images.db).map(async imageEntry => {
|
|
@@ -184,7 +184,9 @@ function createNativeImporterBackend(
|
|
|
184
184
|
filename: entry.image.split("/").pop() as string
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
-
const {json} =
|
|
187
|
+
const {json} = isE2EE
|
|
188
|
+
? await documentImportApi.saveE2EEImage(jsonData, files)
|
|
189
|
+
: await documentImportApi.saveImage(jsonData, files)
|
|
188
190
|
const response = json as Record<string, unknown>
|
|
189
191
|
imageTranslationTable[entry.id] = response.id as number
|
|
190
192
|
})
|
|
@@ -210,7 +212,8 @@ function createNativeImporterBackend(
|
|
|
210
212
|
e2ee.key
|
|
211
213
|
)
|
|
212
214
|
}
|
|
213
|
-
return
|
|
215
|
+
return documentImportApi
|
|
216
|
+
.saveDocument(saveData)
|
|
214
217
|
.then(({json}) => {
|
|
215
218
|
const data = json as Record<string, unknown>
|
|
216
219
|
return {
|
|
@@ -243,7 +246,8 @@ export class SaveCopy extends GenericSaveCopy {
|
|
|
243
246
|
imageDB: ImageDB,
|
|
244
247
|
newUser: User,
|
|
245
248
|
importId: string | number | null = null,
|
|
246
|
-
e2eeOptions: E2EEOptions | null = null
|
|
249
|
+
e2eeOptions: E2EEOptions | null = null,
|
|
250
|
+
documentImportApi?: EditorDocumentImportApi
|
|
247
251
|
) {
|
|
248
252
|
const title = shortFileTitle(doc.title as string, (doc.path as string) || "")
|
|
249
253
|
const task = addProgress(
|
|
@@ -282,7 +286,11 @@ export class SaveCopy extends GenericSaveCopy {
|
|
|
282
286
|
content: Blob | ArrayBuffer | string
|
|
283
287
|
}>,
|
|
284
288
|
opts.user,
|
|
285
|
-
createNativeImporterBackend(
|
|
289
|
+
createNativeImporterBackend(
|
|
290
|
+
opts.user,
|
|
291
|
+
opts.e2eeOptions ?? null,
|
|
292
|
+
documentImportApi as EditorDocumentImportApi
|
|
293
|
+
),
|
|
286
294
|
{
|
|
287
295
|
importId: opts.importId,
|
|
288
296
|
requestedPath: opts.requestedPath,
|
|
@@ -2,9 +2,17 @@ import type {BibDB, ExportDoc, ImageDB} from "@fiduswriter/document"
|
|
|
2
2
|
import {ExportFidusFile as GenericExportFidusFile} from "@fiduswriter/document/exporter/native"
|
|
3
3
|
import {addProgress, gettext, shortFileTitle} from "fwtoolkit"
|
|
4
4
|
import {DocumentTemplateExporter} from "../../document_template/exporter.js"
|
|
5
|
+
import type {EditorDocumentApi} from "../../types.js"
|
|
6
|
+
|
|
7
|
+
interface ExportFidusFileApp {
|
|
8
|
+
apiConnectors: {
|
|
9
|
+
document: Pick<EditorDocumentApi, "getTemplateForDoc">
|
|
10
|
+
}
|
|
11
|
+
}
|
|
5
12
|
|
|
6
13
|
export class ExportFidusFile extends GenericExportFidusFile {
|
|
7
14
|
constructor(
|
|
15
|
+
app: ExportFidusFileApp,
|
|
8
16
|
doc: ExportDoc,
|
|
9
17
|
bibDB: BibDB,
|
|
10
18
|
imageDB: ImageDB,
|
|
@@ -22,7 +30,7 @@ export class ExportFidusFile extends GenericExportFidusFile {
|
|
|
22
30
|
const getTemplateFiles = (docId: number | string, token: string | boolean) => {
|
|
23
31
|
const templateExporter = new DocumentTemplateExporter(
|
|
24
32
|
docId,
|
|
25
|
-
|
|
33
|
+
app.apiConnectors.document.getTemplateForDoc,
|
|
26
34
|
false,
|
|
27
35
|
token as string | false
|
|
28
36
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {BibDB, ExportDoc, ImageDB, UploadRevision} from "@fiduswriter/document"
|
|
2
2
|
import {SaveRevision as GenericSaveRevision} from "@fiduswriter/document/exporter/native"
|
|
3
3
|
import {createSlug} from "@fiduswriter/document/exporter/tools/file"
|
|
4
|
-
import {addAlert, addProgress, gettext,
|
|
4
|
+
import {addAlert, addProgress, gettext, shortFileTitle} from "fwtoolkit"
|
|
5
5
|
import type {EditorApp} from "../../types.js"
|
|
6
6
|
import {DocumentTemplateExporter} from "../../document_template/exporter.js"
|
|
7
7
|
|
|
@@ -40,7 +40,7 @@ export class SaveRevision extends GenericSaveRevision {
|
|
|
40
40
|
const getTemplateFiles = (docId: number | string, token: string | boolean) => {
|
|
41
41
|
const templateExporter = new DocumentTemplateExporter(
|
|
42
42
|
docId,
|
|
43
|
-
|
|
43
|
+
app.apiConnectors.document.getTemplateForDoc,
|
|
44
44
|
false,
|
|
45
45
|
token as string | false
|
|
46
46
|
)
|
|
@@ -51,21 +51,21 @@ export class SaveRevision extends GenericSaveRevision {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const uploadRevision: UploadRevision = (blob, doc) => {
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
return app.apiConnectors.document
|
|
55
|
+
.uploadRevision(
|
|
56
|
+
{
|
|
57
|
+
note,
|
|
58
|
+
document_id: doc.id as number
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
file: {
|
|
62
|
+
file: blob,
|
|
63
|
+
filename: `${createSlug(
|
|
64
|
+
shortFileTitle(doc.title as string, doc.path as string)
|
|
65
|
+
)}.fidus`
|
|
66
|
+
}
|
|
66
67
|
}
|
|
67
|
-
|
|
68
|
-
)
|
|
68
|
+
)
|
|
69
69
|
.then(
|
|
70
70
|
() => {},
|
|
71
71
|
() => {
|