@fiduswriter/editor 0.1.75 → 0.1.77
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 +3 -3
- package/dist/document_template/exporter.d.ts.map +1 -1
- package/dist/document_template/exporter.js +2 -2
- package/dist/document_template/exporter.js.map +1 -1
- package/dist/document_template/index.js +3 -3
- package/dist/document_template/index.js.map +1 -1
- package/dist/documents/access_rights/index.d.ts +5 -2
- package/dist/documents/access_rights/index.d.ts.map +1 -1
- package/dist/documents/access_rights/index.js +20 -10
- package/dist/documents/access_rights/index.js.map +1 -1
- package/dist/documents/access_rights/request_access_dialog.d.ts +23 -0
- package/dist/documents/access_rights/request_access_dialog.d.ts.map +1 -0
- package/dist/documents/access_rights/request_access_dialog.js +102 -0
- package/dist/documents/access_rights/request_access_dialog.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -30
- package/dist/index.js.map +1 -1
- package/dist/menus/headerbar/model.d.ts +2 -2
- package/dist/menus/headerbar/model.d.ts.map +1 -1
- package/dist/menus/headerbar/model.js +37 -32
- package/dist/menus/headerbar/model.js.map +1 -1
- package/package.json +7 -7
- package/src/document_template/exporter.ts +6 -2
- package/src/document_template/index.ts +3 -3
- package/src/documents/access_rights/index.ts +39 -26
- package/src/documents/access_rights/request_access_dialog.ts +151 -0
- package/src/index.ts +57 -35
- package/src/menus/headerbar/model.ts +44 -51
|
@@ -67,6 +67,7 @@ interface AccessRightsTabOptions {
|
|
|
67
67
|
container?: HTMLElement | null
|
|
68
68
|
documentApi: EditorDocumentApi
|
|
69
69
|
contactsApi: EditorContactsApi
|
|
70
|
+
isOwner?: boolean
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
interface AccessRightMenuItem {
|
|
@@ -149,6 +150,7 @@ export class AccessRightsTab {
|
|
|
149
150
|
dialogTabs!: DialogTabs
|
|
150
151
|
documentApi: EditorDocumentApi
|
|
151
152
|
contactsApi: EditorContactsApi
|
|
153
|
+
isOwner: boolean
|
|
152
154
|
|
|
153
155
|
constructor({
|
|
154
156
|
documentIds,
|
|
@@ -160,7 +162,8 @@ export class AccessRightsTab {
|
|
|
160
162
|
settings,
|
|
161
163
|
container = null,
|
|
162
164
|
documentApi,
|
|
163
|
-
contactsApi
|
|
165
|
+
contactsApi,
|
|
166
|
+
isOwner = false
|
|
164
167
|
}: AccessRightsTabOptions) {
|
|
165
168
|
this.documentIds = documentIds
|
|
166
169
|
this.contacts = contacts
|
|
@@ -172,6 +175,7 @@ export class AccessRightsTab {
|
|
|
172
175
|
this.onShareSuccess = onShareSuccess
|
|
173
176
|
this.settings = settings
|
|
174
177
|
this.container = container || null
|
|
178
|
+
this.isOwner = isOwner
|
|
175
179
|
this.accessRights = []
|
|
176
180
|
this.documentApi = documentApi
|
|
177
181
|
this.contactsApi = contactsApi
|
|
@@ -205,31 +209,36 @@ export class AccessRightsTab {
|
|
|
205
209
|
</div>`
|
|
206
210
|
: ""
|
|
207
211
|
|
|
208
|
-
|
|
209
|
-
[
|
|
210
|
-
{
|
|
211
|
-
id: "people",
|
|
212
|
-
title: gettext("People"),
|
|
213
|
-
template: () =>
|
|
214
|
-
peopleTabTemplate({
|
|
215
|
-
contacts: this.contacts,
|
|
216
|
-
collaborators
|
|
217
|
-
})
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
id: "sharelink",
|
|
221
|
-
title: gettext("Share link"),
|
|
222
|
-
template: () => shareLinkTabTemplate()
|
|
223
|
-
}
|
|
224
|
-
],
|
|
212
|
+
const tabs = [
|
|
225
213
|
{
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
214
|
+
id: "people",
|
|
215
|
+
title: gettext("People"),
|
|
216
|
+
template: () =>
|
|
217
|
+
peopleTabTemplate({
|
|
218
|
+
contacts: this.contacts,
|
|
219
|
+
collaborators
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
if (this.isOwner) {
|
|
224
|
+
tabs.push({
|
|
225
|
+
id: "sharelink",
|
|
226
|
+
title: gettext("Share link"),
|
|
227
|
+
template: () => shareLinkTabTemplate()
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.dialogTabs = new DialogTabs(tabs, {
|
|
232
|
+
onShow: index => {
|
|
233
|
+
if (
|
|
234
|
+
this.isOwner &&
|
|
235
|
+
index === 1 &&
|
|
236
|
+
this.singleDocumentId
|
|
237
|
+
) {
|
|
238
|
+
this.loadShareTokens()
|
|
230
239
|
}
|
|
231
240
|
}
|
|
232
|
-
)
|
|
241
|
+
})
|
|
233
242
|
|
|
234
243
|
const html = e2eeWarningBanner + this.dialogTabs.render()
|
|
235
244
|
|
|
@@ -686,6 +695,7 @@ export class DocumentAccessRightsDialog {
|
|
|
686
695
|
documentPassword: string
|
|
687
696
|
onShareSuccess?: (accessRights: AccessRight[]) => void
|
|
688
697
|
settings: Record<string, unknown>
|
|
698
|
+
isOwner: boolean
|
|
689
699
|
contactsApi: EditorContactsApi
|
|
690
700
|
documentApi: EditorDocumentApi
|
|
691
701
|
tab!: AccessRightsTab
|
|
@@ -699,6 +709,7 @@ export class DocumentAccessRightsDialog {
|
|
|
699
709
|
documentPassword = "",
|
|
700
710
|
onShareSuccess?: (accessRights: AccessRight[]) => void,
|
|
701
711
|
settings: Record<string, unknown> = {},
|
|
712
|
+
isOwner = false,
|
|
702
713
|
contactsApi?: EditorContactsApi,
|
|
703
714
|
documentApi?: EditorDocumentApi
|
|
704
715
|
) {
|
|
@@ -709,6 +720,7 @@ export class DocumentAccessRightsDialog {
|
|
|
709
720
|
this.documentPassword = documentPassword
|
|
710
721
|
this.onShareSuccess = onShareSuccess
|
|
711
722
|
this.settings = settings
|
|
723
|
+
this.isOwner = isOwner
|
|
712
724
|
this.contactsApi = contactsApi as EditorContactsApi
|
|
713
725
|
this.documentApi = documentApi as EditorDocumentApi
|
|
714
726
|
}
|
|
@@ -723,7 +735,8 @@ export class DocumentAccessRightsDialog {
|
|
|
723
735
|
onShareSuccess: this.onShareSuccess,
|
|
724
736
|
settings: this.settings,
|
|
725
737
|
documentApi: this.documentApi,
|
|
726
|
-
contactsApi: this.contactsApi
|
|
738
|
+
contactsApi: this.contactsApi,
|
|
739
|
+
isOwner: this.isOwner
|
|
727
740
|
})
|
|
728
741
|
this.tab.load().then(() => this.createDialog())
|
|
729
742
|
}
|
|
@@ -821,8 +834,8 @@ export class DocumentAccessRightsDialog {
|
|
|
821
834
|
// Hide the share-link tab when multiple documents are selected
|
|
822
835
|
if (!this.tab.singleDocumentId) {
|
|
823
836
|
const shareTab = this.dialog.dialogEl.querySelector(
|
|
824
|
-
".fw-tabs-nav .fw-tab-link
|
|
825
|
-
)
|
|
837
|
+
".fw-tabs-nav .fw-tab-link a[href='#sharelink']"
|
|
838
|
+
)?.parentNode
|
|
826
839
|
if (shareTab) {
|
|
827
840
|
;(shareTab as HTMLElement).style.display = "none"
|
|
828
841
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import {Dialog, addAlert} from "fwtoolkit"
|
|
2
|
+
|
|
3
|
+
import type {EditorDocumentApi} from "../../types.js"
|
|
4
|
+
|
|
5
|
+
interface RequestableRight {
|
|
6
|
+
value: string
|
|
7
|
+
label: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const REQUESTABLE_RIGHTS: RequestableRight[] = [
|
|
11
|
+
{value: "read", label: gettext("Read")},
|
|
12
|
+
{value: "comment", label: gettext("Comment")},
|
|
13
|
+
{value: "review", label: gettext("Review")},
|
|
14
|
+
{value: "write-tracked", label: gettext("Write tracked")},
|
|
15
|
+
{value: "write", label: gettext("Write")}
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
const RIGHT_ORDER = REQUESTABLE_RIGHTS.map(right => right.value)
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Dialog for requesting access to a document.
|
|
22
|
+
*
|
|
23
|
+
* For users who already have some access, only rights that are higher than
|
|
24
|
+
* the current level are offered. Token users and users without any known
|
|
25
|
+
* access can choose from all requestable rights.
|
|
26
|
+
*/
|
|
27
|
+
export class RequestAccessDialog {
|
|
28
|
+
documentId: number
|
|
29
|
+
currentRights: string
|
|
30
|
+
documentApi: EditorDocumentApi
|
|
31
|
+
isTokenUser: boolean
|
|
32
|
+
|
|
33
|
+
constructor(
|
|
34
|
+
documentId: number,
|
|
35
|
+
currentRights = "",
|
|
36
|
+
documentApi: EditorDocumentApi,
|
|
37
|
+
isTokenUser = false
|
|
38
|
+
) {
|
|
39
|
+
this.documentId = documentId
|
|
40
|
+
this.currentRights = currentRights
|
|
41
|
+
this.documentApi = documentApi
|
|
42
|
+
this.isTokenUser = isTokenUser
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
open(): void {
|
|
46
|
+
const rightsOptions = this.getRightsOptions()
|
|
47
|
+
if (!rightsOptions.length) {
|
|
48
|
+
addAlert(
|
|
49
|
+
"error",
|
|
50
|
+
gettext("You already have the highest possible access level.")
|
|
51
|
+
)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
const defaultRights =
|
|
55
|
+
rightsOptions.find(right => right.value === "write")?.value ||
|
|
56
|
+
rightsOptions[rightsOptions.length - 1].value
|
|
57
|
+
const bodyText = this.currentRights
|
|
58
|
+
? gettext(
|
|
59
|
+
"Select a higher access level to request from the document owner."
|
|
60
|
+
)
|
|
61
|
+
: gettext(
|
|
62
|
+
"You do not have access to this document. Select the access level you would like to request from the document owner."
|
|
63
|
+
)
|
|
64
|
+
const dialog = new Dialog({
|
|
65
|
+
title: gettext("Request Access"),
|
|
66
|
+
id: "request-access-dialog",
|
|
67
|
+
width: 500,
|
|
68
|
+
body: `<p>${bodyText}</p>
|
|
69
|
+
<table class="fw-dialog-table">
|
|
70
|
+
<tbody>
|
|
71
|
+
<tr>
|
|
72
|
+
<th><label for="request-access-rights">${gettext(
|
|
73
|
+
"Access level"
|
|
74
|
+
)}</label></th>
|
|
75
|
+
<td class="entry-field">
|
|
76
|
+
<select id="request-access-rights" class="fw-button fw-light fw-large">
|
|
77
|
+
${rightsOptions
|
|
78
|
+
.map(
|
|
79
|
+
right =>
|
|
80
|
+
`<option value="${right.value}"${right.value === defaultRights ? " selected" : ""}>${right.label}</option>`
|
|
81
|
+
)
|
|
82
|
+
.join("")}
|
|
83
|
+
</select>
|
|
84
|
+
<div class="fw-select-arrow fa-solid fa-caret-down"></div>
|
|
85
|
+
</td>
|
|
86
|
+
</tr>
|
|
87
|
+
</tbody>
|
|
88
|
+
</table>`,
|
|
89
|
+
buttons: [
|
|
90
|
+
{
|
|
91
|
+
text: gettext("Request"),
|
|
92
|
+
classes: "fw-dark",
|
|
93
|
+
click: () => {
|
|
94
|
+
const rights = (
|
|
95
|
+
dialog.dialogEl.querySelector(
|
|
96
|
+
"#request-access-rights"
|
|
97
|
+
) as HTMLSelectElement
|
|
98
|
+
).value
|
|
99
|
+
this.documentApi
|
|
100
|
+
.requestAccess({
|
|
101
|
+
document_id: this.documentId,
|
|
102
|
+
rights
|
|
103
|
+
})
|
|
104
|
+
.then(({json}: {json: unknown}) => {
|
|
105
|
+
const data = json as {
|
|
106
|
+
success?: boolean
|
|
107
|
+
error?: string
|
|
108
|
+
}
|
|
109
|
+
if (data.success) {
|
|
110
|
+
addAlert(
|
|
111
|
+
"success",
|
|
112
|
+
gettext(
|
|
113
|
+
"Your access request has been sent to the document owner."
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
dialog.close()
|
|
117
|
+
} else {
|
|
118
|
+
addAlert(
|
|
119
|
+
"error",
|
|
120
|
+
data.error ||
|
|
121
|
+
gettext(
|
|
122
|
+
"Could not send access request."
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
.catch(() => {
|
|
128
|
+
addAlert(
|
|
129
|
+
"error",
|
|
130
|
+
gettext("Could not send access request.")
|
|
131
|
+
)
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{type: "cancel"}
|
|
136
|
+
]
|
|
137
|
+
})
|
|
138
|
+
dialog.open()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getRightsOptions(): RequestableRight[] {
|
|
142
|
+
if (this.isTokenUser || !this.currentRights) {
|
|
143
|
+
return REQUESTABLE_RIGHTS
|
|
144
|
+
}
|
|
145
|
+
const currentIndex = RIGHT_ORDER.indexOf(this.currentRights)
|
|
146
|
+
if (currentIndex < 0) {
|
|
147
|
+
return REQUESTABLE_RIGHTS
|
|
148
|
+
}
|
|
149
|
+
return REQUESTABLE_RIGHTS.filter((_, index) => index > currentIndex)
|
|
150
|
+
}
|
|
151
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -41,6 +41,7 @@ import {ModCollab} from "./collab/index.js"
|
|
|
41
41
|
import {ModComments} from "./comments/index.js"
|
|
42
42
|
import {ModDB} from "./databases/index.js"
|
|
43
43
|
import {ModDocumentTemplate} from "./document_template/index.js"
|
|
44
|
+
import {RequestAccessDialog} from "./documents/access_rights/request_access_dialog.js"
|
|
44
45
|
import {E2EESnapshotManager} from "./e2ee/snapshot-manager.js"
|
|
45
46
|
import {ExportFidusFile} from "./exporter/native/file.js"
|
|
46
47
|
import {ModFootnotes} from "./footnotes/index.js"
|
|
@@ -374,47 +375,68 @@ export class Editor {
|
|
|
374
375
|
token: this.docInfo.token
|
|
375
376
|
})
|
|
376
377
|
: Promise.resolve({json: {ws_base: ""}})
|
|
377
|
-
const stylesPromise = documentApi
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
378
|
+
const stylesPromise = documentApi
|
|
379
|
+
.getDocumentStyles(
|
|
380
|
+
stylesPayload as {id: number; token?: string}
|
|
381
|
+
)
|
|
382
|
+
.catch(() => {
|
|
383
|
+
return {json: {}}
|
|
384
|
+
})
|
|
385
|
+
const docDataPromise = documentApi
|
|
386
|
+
.getDocumentData(
|
|
387
|
+
stylesPayload as {id: number; token?: string}
|
|
388
|
+
)
|
|
389
|
+
.catch(error => {
|
|
390
|
+
// Only show "Invalid Share Link" for token validation errors.
|
|
391
|
+
// For authenticated users without access, offer to request access.
|
|
392
|
+
// This is also shown when the document does not exist so that we
|
|
393
|
+
// do not reveal whether a document with the given ID exists.
|
|
394
|
+
if (error.message === "Invalid or expired share link") {
|
|
395
|
+
deactivateWait()
|
|
396
|
+
const errorDialog = new Dialog({
|
|
397
|
+
title: gettext("Invalid Share Link"),
|
|
398
|
+
id: "invalid_share_link_dialog",
|
|
399
|
+
body: gettext(
|
|
400
|
+
"This share link has expired or is invalid. Please ask the document owner for a new link."
|
|
401
|
+
),
|
|
402
|
+
buttons: [
|
|
403
|
+
{
|
|
404
|
+
text: gettext("OK"),
|
|
405
|
+
classes: "fw-dark",
|
|
406
|
+
click: () => {
|
|
407
|
+
window.location.href = "/"
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
],
|
|
411
|
+
canClose: false
|
|
412
|
+
})
|
|
413
|
+
errorDialog.open()
|
|
414
|
+
return Promise.reject(false)
|
|
415
|
+
} else if (
|
|
416
|
+
error.status === 401 &&
|
|
417
|
+
this.user.is_authenticated
|
|
418
|
+
) {
|
|
419
|
+
deactivateWait()
|
|
420
|
+
const requestAccessDialog = new RequestAccessDialog(
|
|
421
|
+
this.docInfo.id as number,
|
|
422
|
+
"",
|
|
423
|
+
documentApi,
|
|
424
|
+
Boolean(this.docInfo.token)
|
|
425
|
+
)
|
|
426
|
+
requestAccessDialog.open()
|
|
427
|
+
return Promise.reject(false)
|
|
428
|
+
} else {
|
|
429
|
+
deactivateWait()
|
|
430
|
+
console.error("Editor initialization failed:", error)
|
|
431
|
+
}
|
|
432
|
+
return Promise.reject(error)
|
|
433
|
+
})
|
|
383
434
|
return Promise.all([
|
|
384
435
|
wsBasePromise,
|
|
385
436
|
stylesPromise,
|
|
386
437
|
docDataPromise
|
|
387
438
|
])
|
|
388
439
|
})
|
|
389
|
-
.catch(error => {
|
|
390
|
-
// Only show "Invalid Share Link" for token validation errors.
|
|
391
|
-
// Other errors (REST failures, etc.) should not show this dialog.
|
|
392
|
-
if (error.message === "Invalid or expired share link") {
|
|
393
|
-
deactivateWait()
|
|
394
|
-
const errorDialog = new Dialog({
|
|
395
|
-
title: gettext("Invalid Share Link"),
|
|
396
|
-
id: "invalid_share_link_dialog",
|
|
397
|
-
body: gettext(
|
|
398
|
-
"This share link has expired or is invalid. Please ask the document owner for a new link."
|
|
399
|
-
),
|
|
400
|
-
buttons: [
|
|
401
|
-
{
|
|
402
|
-
text: gettext("OK"),
|
|
403
|
-
classes: "fw-dark",
|
|
404
|
-
click: () => {
|
|
405
|
-
window.location.href = "/"
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
],
|
|
409
|
-
canClose: false
|
|
410
|
-
})
|
|
411
|
-
errorDialog.open()
|
|
412
|
-
} else {
|
|
413
|
-
deactivateWait()
|
|
414
|
-
console.error("Editor initialization failed:", error)
|
|
415
|
-
}
|
|
416
|
-
return Promise.reject(error)
|
|
417
|
-
})
|
|
418
440
|
.then(([wsResult, stylesResult, docResult]) => {
|
|
419
441
|
let resubScribed = false
|
|
420
442
|
this.render()
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import type {BibDB, ExportDoc, ImageDB} from "@fiduswriter/document"
|
|
8
8
|
import {CopyrightDialog} from "../../copyright_dialog/index.js"
|
|
9
9
|
import {DocumentAccessRightsDialog} from "../../documents/access_rights/index.js"
|
|
10
|
+
import {RequestAccessDialog} from "../../documents/access_rights/request_access_dialog.js"
|
|
10
11
|
import {SaveCopy, SaveRevision} from "../../exporter/native/index.js"
|
|
11
12
|
import {ExportFidusFile} from "../../exporter/native/file.js"
|
|
12
13
|
import {LanguageDialog, RevisionDialog} from "../../dialogs/index.js"
|
|
@@ -72,6 +73,13 @@ const exportProgress = (doc: {title: string; path?: string}) => {
|
|
|
72
73
|
task.update(percentage ?? null, message)
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
const showRequestAccess = (editor: Editor): boolean =>
|
|
77
|
+
editor.user.is_authenticated === true &&
|
|
78
|
+
!editor.docInfo.is_owner &&
|
|
79
|
+
(Boolean(editor.docInfo.token) ||
|
|
80
|
+
(Boolean(editor.docInfo.access_rights) &&
|
|
81
|
+
editor.docInfo.access_rights !== "write"))
|
|
82
|
+
|
|
75
83
|
const languageItem = (
|
|
76
84
|
language: string,
|
|
77
85
|
name: string,
|
|
@@ -115,62 +123,26 @@ export const headerbarModel = () => ({
|
|
|
115
123
|
content: [
|
|
116
124
|
{
|
|
117
125
|
title: (editor: Editor) =>
|
|
118
|
-
editor
|
|
119
|
-
editor.docInfo.token &&
|
|
120
|
-
!editor.docInfo.is_owner
|
|
126
|
+
showRequestAccess(editor)
|
|
121
127
|
? gettext("Request Access")
|
|
122
128
|
: gettext("Share"),
|
|
123
129
|
type: "action",
|
|
124
130
|
//icon: 'share',
|
|
125
131
|
tooltip: (editor: Editor) =>
|
|
126
|
-
editor
|
|
127
|
-
editor.docInfo.token &&
|
|
128
|
-
!editor.docInfo.is_owner
|
|
132
|
+
showRequestAccess(editor)
|
|
129
133
|
? gettext("Request to be added as a collaborator.")
|
|
130
134
|
: gettext("Share the document with other users."),
|
|
131
135
|
order: 0,
|
|
132
136
|
action: (editor: Editor) => {
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
rights: "write"
|
|
143
|
-
})
|
|
144
|
-
.then(({json}: {json: unknown}) => {
|
|
145
|
-
const data = json as {
|
|
146
|
-
success?: boolean
|
|
147
|
-
error?: string
|
|
148
|
-
}
|
|
149
|
-
if (data.success) {
|
|
150
|
-
addAlert(
|
|
151
|
-
"success",
|
|
152
|
-
gettext(
|
|
153
|
-
"Your access request has been sent to the document owner."
|
|
154
|
-
)
|
|
155
|
-
)
|
|
156
|
-
} else {
|
|
157
|
-
addAlert(
|
|
158
|
-
"error",
|
|
159
|
-
data.error ||
|
|
160
|
-
gettext(
|
|
161
|
-
"Could not send access request."
|
|
162
|
-
)
|
|
163
|
-
)
|
|
164
|
-
}
|
|
165
|
-
})
|
|
166
|
-
.catch(() => {
|
|
167
|
-
addAlert(
|
|
168
|
-
"error",
|
|
169
|
-
gettext(
|
|
170
|
-
"Could not send access request."
|
|
171
|
-
)
|
|
172
|
-
)
|
|
173
|
-
})
|
|
137
|
+
if (showRequestAccess(editor)) {
|
|
138
|
+
// Request higher access rights from the document owner
|
|
139
|
+
const requestAccessDialog = new RequestAccessDialog(
|
|
140
|
+
editor.docInfo.id as number,
|
|
141
|
+
editor.docInfo.access_rights || "",
|
|
142
|
+
editor.app.apiConnectors.document,
|
|
143
|
+
Boolean(editor.docInfo.token)
|
|
144
|
+
)
|
|
145
|
+
requestAccessDialog.open()
|
|
174
146
|
return
|
|
175
147
|
}
|
|
176
148
|
const onShareSuccess = async (
|
|
@@ -254,19 +226,40 @@ export const headerbarModel = () => ({
|
|
|
254
226
|
editor.e2ee?.password || "",
|
|
255
227
|
onShareSuccess,
|
|
256
228
|
editor.app.settings,
|
|
229
|
+
editor.docInfo.is_owner,
|
|
257
230
|
editor.app.apiConnectors.contacts,
|
|
258
231
|
editor.app.apiConnectors.document
|
|
259
232
|
)
|
|
260
233
|
shareDialog.init()
|
|
261
234
|
},
|
|
235
|
+
available: (editor: Editor) => {
|
|
236
|
+
if (editor.app.settings.EDITOR_SAVE_MODE === "external") {
|
|
237
|
+
return false
|
|
238
|
+
}
|
|
239
|
+
if (!editor.user.is_authenticated) {
|
|
240
|
+
return true
|
|
241
|
+
}
|
|
242
|
+
if (editor.docInfo.is_owner) {
|
|
243
|
+
return true
|
|
244
|
+
}
|
|
245
|
+
if (editor.docInfo.token) {
|
|
246
|
+
return true
|
|
247
|
+
}
|
|
248
|
+
if (!editor.docInfo.access_rights) {
|
|
249
|
+
return false
|
|
250
|
+
}
|
|
251
|
+
return editor.docInfo.access_rights !== "write"
|
|
252
|
+
},
|
|
262
253
|
disabled: (editor: Editor) => {
|
|
263
254
|
return (
|
|
264
255
|
editor.app.isOffline() ||
|
|
265
|
-
!editor.user.is_authenticated
|
|
256
|
+
!editor.user.is_authenticated ||
|
|
257
|
+
!editor.docInfo.owner ||
|
|
258
|
+
(!editor.docInfo.is_owner &&
|
|
259
|
+
!editor.docInfo.token &&
|
|
260
|
+
editor.docInfo.access_rights === "write")
|
|
266
261
|
)
|
|
267
|
-
}
|
|
268
|
-
available: (editor: Editor) =>
|
|
269
|
-
editor.app.settings.EDITOR_SAVE_MODE !== "external"
|
|
262
|
+
}
|
|
270
263
|
},
|
|
271
264
|
{
|
|
272
265
|
title: (editor: Editor) =>
|