feat: onlyoffice editor
This commit is contained in:
parent
434e49bf59
commit
08f37b90ce
@ -42,6 +42,10 @@ override the options.`,
|
|||||||
Theme: mustGetString(flags, "branding.theme"),
|
Theme: mustGetString(flags, "branding.theme"),
|
||||||
Files: mustGetString(flags, "branding.files"),
|
Files: mustGetString(flags, "branding.files"),
|
||||||
},
|
},
|
||||||
|
OnlyOffice: settings.OnlyOffice{
|
||||||
|
URL: mustGetString(flags, "onlyoffice.url"),
|
||||||
|
JWTSecret: mustGetString(flags, "onlyoffice.jwtSecret"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ser := &settings.Server{
|
ser := &settings.Server{
|
||||||
|
|||||||
@ -63,6 +63,10 @@ you want to change. Other options will remain unchanged.`,
|
|||||||
set.Branding.DisableUsedPercentage = mustGetBool(flags, flag.Name)
|
set.Branding.DisableUsedPercentage = mustGetBool(flags, flag.Name)
|
||||||
case "branding.files":
|
case "branding.files":
|
||||||
set.Branding.Files = mustGetString(flags, flag.Name)
|
set.Branding.Files = mustGetString(flags, flag.Name)
|
||||||
|
case "onlyoffice.url":
|
||||||
|
set.OnlyOffice.URL = mustGetString(flags, flag.Name)
|
||||||
|
case "onlyoffice.jwtSecret":
|
||||||
|
set.OnlyOffice.JWTSecret = mustGetString(flags, flag.Name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -276,6 +276,9 @@ func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
|
|||||||
i.Content = string(content)
|
i.Content = string(content)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
case strings.HasPrefix(mimetype, "application/vnd.openxmlformats-officedocument"):
|
||||||
|
i.Type = "officedocument"
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
i.Type = "blob"
|
i.Type = "blob"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -195,6 +195,8 @@
|
|||||||
"newPassword": "كلمة المرور الجديدة",
|
"newPassword": "كلمة المرور الجديدة",
|
||||||
"newPasswordConfirm": "تأكيد كلمة المرور",
|
"newPasswordConfirm": "تأكيد كلمة المرور",
|
||||||
"newUser": "مستخدم جديد",
|
"newUser": "مستخدم جديد",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "كلمة المرور",
|
"password": "كلمة المرور",
|
||||||
"passwordUpdated": "تم تغيير كلمة المرور!",
|
"passwordUpdated": "تم تغيير كلمة المرور!",
|
||||||
"path": "المسار",
|
"path": "المسار",
|
||||||
|
|||||||
@ -182,6 +182,8 @@
|
|||||||
"newPassword": "Ihr neues Passwort.",
|
"newPassword": "Ihr neues Passwort.",
|
||||||
"newPasswordConfirm": "Bestätigen Sie Ihr neues Passwort",
|
"newPasswordConfirm": "Bestätigen Sie Ihr neues Passwort",
|
||||||
"newUser": "Neuer Benutzer",
|
"newUser": "Neuer Benutzer",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Passwort",
|
"password": "Passwort",
|
||||||
"passwordUpdated": "Passwort aktualisiert!",
|
"passwordUpdated": "Passwort aktualisiert!",
|
||||||
"path": "Pfad",
|
"path": "Pfad",
|
||||||
@ -247,4 +249,4 @@
|
|||||||
"seconds": "Sekunden",
|
"seconds": "Sekunden",
|
||||||
"unit": "Zeiteinheit"
|
"unit": "Zeiteinheit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,6 +195,9 @@
|
|||||||
"newPassword": "Your new password",
|
"newPassword": "Your new password",
|
||||||
"newPasswordConfirm": "Confirm your new password",
|
"newPasswordConfirm": "Confirm your new password",
|
||||||
"newUser": "New User",
|
"newUser": "New User",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
|
"onlyOfficeJwtSecret": "Only Office JWT Secret (works only with https, leave blank to disable)",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"passwordUpdated": "Password updated!",
|
"passwordUpdated": "Password updated!",
|
||||||
"path": "Path",
|
"path": "Path",
|
||||||
@ -261,4 +264,4 @@
|
|||||||
"seconds": "Seconds",
|
"seconds": "Seconds",
|
||||||
"unit": "Time Unit"
|
"unit": "Time Unit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,6 +182,8 @@
|
|||||||
"newPassword": "Tu nueva contraseña",
|
"newPassword": "Tu nueva contraseña",
|
||||||
"newPasswordConfirm": "Confirma tu contraseña",
|
"newPasswordConfirm": "Confirma tu contraseña",
|
||||||
"newUser": "Nuevo usuario",
|
"newUser": "Nuevo usuario",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Contraseña",
|
"password": "Contraseña",
|
||||||
"passwordUpdated": "¡Contraseña actualizada!",
|
"passwordUpdated": "¡Contraseña actualizada!",
|
||||||
"path": "Ruta",
|
"path": "Ruta",
|
||||||
@ -247,4 +249,4 @@
|
|||||||
"seconds": "Segundos",
|
"seconds": "Segundos",
|
||||||
"unit": "Unidad"
|
"unit": "Unidad"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,6 +181,8 @@
|
|||||||
"newPassword": "Votre nouveau mot de passe",
|
"newPassword": "Votre nouveau mot de passe",
|
||||||
"newPasswordConfirm": "Confirmation du nouveau mot de passe",
|
"newPasswordConfirm": "Confirmation du nouveau mot de passe",
|
||||||
"newUser": "Nouvel Utilisateur",
|
"newUser": "Nouvel Utilisateur",
|
||||||
|
"onlyOffice": "Intégration Only Office",
|
||||||
|
"onlyOfficeUrl": "URL vers OnlyOffice (laisser vide pour désactiver)",
|
||||||
"password": "Mot de passe",
|
"password": "Mot de passe",
|
||||||
"passwordUpdated": "Mot de passe mis à jour !",
|
"passwordUpdated": "Mot de passe mis à jour !",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -246,4 +248,4 @@
|
|||||||
"seconds": "Secondes",
|
"seconds": "Secondes",
|
||||||
"unit": "Unité de temps"
|
"unit": "Unité de temps"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "Nýja lykilorðið þitt",
|
"newPassword": "Nýja lykilorðið þitt",
|
||||||
"newPasswordConfirm": "Staðfestu nýja lykilorðið",
|
"newPasswordConfirm": "Staðfestu nýja lykilorðið",
|
||||||
"newUser": "Nýr notandi",
|
"newUser": "Nýr notandi",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Lykilorð",
|
"password": "Lykilorð",
|
||||||
"passwordUpdated": "Lykilorð vistað!",
|
"passwordUpdated": "Lykilorð vistað!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "Sekúndur",
|
"seconds": "Sekúndur",
|
||||||
"unit": "Tímastilling"
|
"unit": "Tímastilling"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,6 +170,8 @@
|
|||||||
"newPassword": "La tua nuova password",
|
"newPassword": "La tua nuova password",
|
||||||
"newPasswordConfirm": "Conferma la password",
|
"newPasswordConfirm": "Conferma la password",
|
||||||
"newUser": "Nuovo utente",
|
"newUser": "Nuovo utente",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"passwordUpdated": "Password aggiornata!",
|
"passwordUpdated": "Password aggiornata!",
|
||||||
"path": "Percorso",
|
"path": "Percorso",
|
||||||
@ -233,4 +235,4 @@
|
|||||||
"seconds": "Secondi",
|
"seconds": "Secondi",
|
||||||
"unit": "Unità di tempo"
|
"unit": "Unità di tempo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,6 +191,8 @@
|
|||||||
"newPassword": "新しいパスワード",
|
"newPassword": "新しいパスワード",
|
||||||
"newPasswordConfirm": "新しいパスワード(再入力)",
|
"newPasswordConfirm": "新しいパスワード(再入力)",
|
||||||
"newUser": "新規ユーザー作成",
|
"newUser": "新規ユーザー作成",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "パスワード",
|
"password": "パスワード",
|
||||||
"passwordUpdated": "パスワードを更新しました!",
|
"passwordUpdated": "パスワードを更新しました!",
|
||||||
"path": "パス",
|
"path": "パス",
|
||||||
@ -256,4 +258,4 @@
|
|||||||
"seconds": "秒",
|
"seconds": "秒",
|
||||||
"unit": "時間の単位"
|
"unit": "時間の単位"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "새로운 비밀번호",
|
"newPassword": "새로운 비밀번호",
|
||||||
"newPasswordConfirm": "새로운 비밀번호 확인",
|
"newPasswordConfirm": "새로운 비밀번호 확인",
|
||||||
"newUser": "새로운 사용자",
|
"newUser": "새로운 사용자",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "비밀번호",
|
"password": "비밀번호",
|
||||||
"passwordUpdated": "비밀번호 수정 완료!",
|
"passwordUpdated": "비밀번호 수정 완료!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "초",
|
"seconds": "초",
|
||||||
"unit": "Time Unit"
|
"unit": "Time Unit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "Uw nieuw wachtwoord",
|
"newPassword": "Uw nieuw wachtwoord",
|
||||||
"newPasswordConfirm": "Bevestig uw nieuw wachtwoord",
|
"newPasswordConfirm": "Bevestig uw nieuw wachtwoord",
|
||||||
"newUser": "Nieuwe gebruiker",
|
"newUser": "Nieuwe gebruiker",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Wachtwoord",
|
"password": "Wachtwoord",
|
||||||
"passwordUpdated": "Wachtwoord bijgewerkt!",
|
"passwordUpdated": "Wachtwoord bijgewerkt!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "Seconden",
|
"seconds": "Seconden",
|
||||||
"unit": "Tijdseenheid"
|
"unit": "Tijdseenheid"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "Twoje nowe hasło",
|
"newPassword": "Twoje nowe hasło",
|
||||||
"newPasswordConfirm": "Potwierdź swoje hasło",
|
"newPasswordConfirm": "Potwierdź swoje hasło",
|
||||||
"newUser": "Nowy Użytkownik",
|
"newUser": "Nowy Użytkownik",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Hasło",
|
"password": "Hasło",
|
||||||
"passwordUpdated": "Hasło zostało zapisane!",
|
"passwordUpdated": "Hasło zostało zapisane!",
|
||||||
"path": "Ścieżka",
|
"path": "Ścieżka",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "Sekundy",
|
"seconds": "Sekundy",
|
||||||
"unit": "Jednostka czasu"
|
"unit": "Jednostka czasu"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,6 +182,8 @@
|
|||||||
"newPassword": "Nova senha",
|
"newPassword": "Nova senha",
|
||||||
"newPasswordConfirm": "Confirme a nova senha",
|
"newPasswordConfirm": "Confirme a nova senha",
|
||||||
"newUser": "Novo usuário",
|
"newUser": "Novo usuário",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Senha",
|
"password": "Senha",
|
||||||
"passwordUpdated": "Senha atualizada!",
|
"passwordUpdated": "Senha atualizada!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -247,4 +249,4 @@
|
|||||||
"seconds": "Segundos",
|
"seconds": "Segundos",
|
||||||
"unit": "Unidades de Tempo"
|
"unit": "Unidades de Tempo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,6 +170,8 @@
|
|||||||
"newPassword": "Nova palavra-passe",
|
"newPassword": "Nova palavra-passe",
|
||||||
"newPasswordConfirm": "Confirme a nova palavra-passe",
|
"newPasswordConfirm": "Confirme a nova palavra-passe",
|
||||||
"newUser": "Novo utilizador",
|
"newUser": "Novo utilizador",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Palavra-passe",
|
"password": "Palavra-passe",
|
||||||
"passwordUpdated": "Palavra-passe atualizada!",
|
"passwordUpdated": "Palavra-passe atualizada!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -233,4 +235,4 @@
|
|||||||
"seconds": "Segundos",
|
"seconds": "Segundos",
|
||||||
"unit": "Unidades de tempo"
|
"unit": "Unidades de tempo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "Noua ta parolă",
|
"newPassword": "Noua ta parolă",
|
||||||
"newPasswordConfirm": "Confirmă noua parolă",
|
"newPasswordConfirm": "Confirmă noua parolă",
|
||||||
"newUser": "Utilizator nou",
|
"newUser": "Utilizator nou",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Parola",
|
"password": "Parola",
|
||||||
"passwordUpdated": "Parola actualizată!",
|
"passwordUpdated": "Parola actualizată!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "Secunde",
|
"seconds": "Secunde",
|
||||||
"unit": "Unitate de timp"
|
"unit": "Unitate de timp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,6 +177,8 @@
|
|||||||
"newPassword": "Новый пароль",
|
"newPassword": "Новый пароль",
|
||||||
"newPasswordConfirm": "Повтор нового пароля",
|
"newPasswordConfirm": "Повтор нового пароля",
|
||||||
"newUser": "Новый пользователь",
|
"newUser": "Новый пользователь",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Пароль",
|
"password": "Пароль",
|
||||||
"passwordUpdated": "Пароль обновлен!",
|
"passwordUpdated": "Пароль обновлен!",
|
||||||
"path": "Путь",
|
"path": "Путь",
|
||||||
@ -242,4 +244,4 @@
|
|||||||
"seconds": "Секунды",
|
"seconds": "Секунды",
|
||||||
"unit": "Единица времени"
|
"unit": "Единица времени"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "Ditt nya lösenord",
|
"newPassword": "Ditt nya lösenord",
|
||||||
"newPasswordConfirm": "Bekräfta ditt nya lösenord",
|
"newPasswordConfirm": "Bekräfta ditt nya lösenord",
|
||||||
"newUser": "Ny användare",
|
"newUser": "Ny användare",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "Lösenord",
|
"password": "Lösenord",
|
||||||
"passwordUpdated": "Lösenord uppdaterat",
|
"passwordUpdated": "Lösenord uppdaterat",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "Sekunder",
|
"seconds": "Sekunder",
|
||||||
"unit": "Tidsenhet"
|
"unit": "Tidsenhet"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,6 +191,8 @@
|
|||||||
"newPassword": "你的新密码",
|
"newPassword": "你的新密码",
|
||||||
"newPasswordConfirm": "再次输入以确认你的新密码",
|
"newPasswordConfirm": "再次输入以确认你的新密码",
|
||||||
"newUser": "新建用户",
|
"newUser": "新建用户",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "密码",
|
"password": "密码",
|
||||||
"passwordUpdated": "密码已更新!",
|
"passwordUpdated": "密码已更新!",
|
||||||
"path": "路径",
|
"path": "路径",
|
||||||
@ -256,4 +258,4 @@
|
|||||||
"seconds": "秒",
|
"seconds": "秒",
|
||||||
"unit": "时间单位"
|
"unit": "时间单位"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,6 +169,8 @@
|
|||||||
"newPassword": "您的新密碼",
|
"newPassword": "您的新密碼",
|
||||||
"newPasswordConfirm": "重輸一遍新密碼",
|
"newPasswordConfirm": "重輸一遍新密碼",
|
||||||
"newUser": "建立使用者",
|
"newUser": "建立使用者",
|
||||||
|
"onlyOffice": "Only Office Integration",
|
||||||
|
"onlyOfficeUrl": "Only Office URL (leave blank to disable)",
|
||||||
"password": "密碼",
|
"password": "密碼",
|
||||||
"passwordUpdated": "密碼已更新!",
|
"passwordUpdated": "密碼已更新!",
|
||||||
"path": "",
|
"path": "",
|
||||||
@ -232,4 +234,4 @@
|
|||||||
"seconds": "秒",
|
"seconds": "秒",
|
||||||
"unit": "時間單位"
|
"unit": "時間單位"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,6 +18,7 @@ const enableExec: boolean = window.FileBrowser.EnableExec;
|
|||||||
const tusSettings = window.FileBrowser.TusSettings;
|
const tusSettings = window.FileBrowser.TusSettings;
|
||||||
const origin = window.location.origin;
|
const origin = window.location.origin;
|
||||||
const tusEndpoint = `/api/tus`;
|
const tusEndpoint = `/api/tus`;
|
||||||
|
const onlyOffice = window.FileBrowser.OnlyOffice;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
name,
|
name,
|
||||||
@ -39,4 +40,5 @@ export {
|
|||||||
tusSettings,
|
tusSettings,
|
||||||
origin,
|
origin,
|
||||||
tusEndpoint,
|
tusEndpoint,
|
||||||
|
onlyOffice,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import { storeToRefs } from "pinia";
|
|||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import { useUploadStore } from "@/stores/upload";
|
import { useUploadStore } from "@/stores/upload";
|
||||||
|
import { onlyOffice } from "@/utils/constants";
|
||||||
|
|
||||||
import HeaderBar from "@/components/header/HeaderBar.vue";
|
import HeaderBar from "@/components/header/HeaderBar.vue";
|
||||||
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
||||||
@ -47,6 +48,7 @@ import FileListing from "@/views/files/FileListing.vue";
|
|||||||
import { StatusError } from "@/api/utils";
|
import { StatusError } from "@/api/utils";
|
||||||
const Editor = defineAsyncComponent(() => import("@/views/files/Editor.vue"));
|
const Editor = defineAsyncComponent(() => import("@/views/files/Editor.vue"));
|
||||||
const Preview = defineAsyncComponent(() => import("@/views/files/Preview.vue"));
|
const Preview = defineAsyncComponent(() => import("@/views/files/Preview.vue"));
|
||||||
|
const OnlyOfficeEditor = defineAsyncComponent(() => import("@/views/files/OnlyOfficeEditor.vue"));
|
||||||
|
|
||||||
const layoutStore = useLayoutStore();
|
const layoutStore = useLayoutStore();
|
||||||
const fileStore = useFileStore();
|
const fileStore = useFileStore();
|
||||||
@ -77,6 +79,8 @@ const currentView = computed(() => {
|
|||||||
fileStore.req.type === "textImmutable"
|
fileStore.req.type === "textImmutable"
|
||||||
) {
|
) {
|
||||||
return Editor;
|
return Editor;
|
||||||
|
} else if (fileStore.req.type === "officedocument" && onlyOffice !== "") {
|
||||||
|
return OnlyOfficeEditor;
|
||||||
} else {
|
} else {
|
||||||
return Preview;
|
return Preview;
|
||||||
}
|
}
|
||||||
|
|||||||
170
frontend/src/views/files/OnlyOfficeEditor.vue
Normal file
170
frontend/src/views/files/OnlyOfficeEditor.vue
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
<template>
|
||||||
|
<div id="editor-container">
|
||||||
|
<header-bar>
|
||||||
|
<action icon="close" :label="$t('buttons.close')" @action="close()" />
|
||||||
|
<title>{{ req.name }}</title>
|
||||||
|
</header-bar>
|
||||||
|
|
||||||
|
<breadcrumbs base="/files" noLink />
|
||||||
|
|
||||||
|
<div id="editor"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#editor-container {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState } from "vuex";
|
||||||
|
import url from "@/utils/url";
|
||||||
|
import { baseURL, onlyOffice } from "@/utils/constants";
|
||||||
|
import * as jose from "jose";
|
||||||
|
|
||||||
|
import HeaderBar from "@/components/header/HeaderBar.vue";
|
||||||
|
import Action from "@/components/header/Action.vue";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "onlyofficeeditor",
|
||||||
|
components: {
|
||||||
|
HeaderBar,
|
||||||
|
Action,
|
||||||
|
Breadcrumbs,
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(["req", "user", "jwt"]),
|
||||||
|
breadcrumbs() {
|
||||||
|
let parts = this.$route.path.split("/");
|
||||||
|
|
||||||
|
if (parts[0] === "") {
|
||||||
|
parts.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parts[parts.length - 1] === "") {
|
||||||
|
parts.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let breadcrumbs = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < parts.length; i++) {
|
||||||
|
breadcrumbs.push({ name: decodeURIComponent(parts[i]) });
|
||||||
|
}
|
||||||
|
|
||||||
|
breadcrumbs.shift();
|
||||||
|
|
||||||
|
if (breadcrumbs.length > 3) {
|
||||||
|
while (breadcrumbs.length !== 4) {
|
||||||
|
breadcrumbs.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
breadcrumbs[0].name = "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return breadcrumbs;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
window.addEventListener("keydown", this.keyEvent);
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener("keydown", this.keyEvent);
|
||||||
|
this.editor.destroyEditor();
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
let onlyofficeScript = document.createElement("script");
|
||||||
|
onlyofficeScript.setAttribute(
|
||||||
|
"src",
|
||||||
|
`${onlyOffice.url}/web-apps/apps/api/documents/api.js`
|
||||||
|
);
|
||||||
|
document.head.appendChild(onlyofficeScript);
|
||||||
|
|
||||||
|
/*eslint-disable */
|
||||||
|
onlyofficeScript.onload = () => {
|
||||||
|
let fileUrl = `${window.location.protocol}//${window.location.host}${baseURL}/api/raw${url.encodePath(
|
||||||
|
this.req.path
|
||||||
|
)}?auth=${this.jwt}`;
|
||||||
|
|
||||||
|
// create a key from the last modified timestamp and the reversed file path (most specific part first)
|
||||||
|
// replace all special characters (only these symbols are supported: 0-9, a-z, A-Z, -._=)
|
||||||
|
// and truncate it (max length is 20 characters)
|
||||||
|
const key = (
|
||||||
|
Date.parse(this.req.modified).valueOf()
|
||||||
|
+ url
|
||||||
|
.encodePath(this.req.path.split('/').reverse().join(''))
|
||||||
|
.replaceAll(/[!~[\]*'()/,;:\-%+. ]/g, "")
|
||||||
|
).substring(0, 20);
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
document: {
|
||||||
|
fileType: this.req.extension.substring(1),
|
||||||
|
key: key,
|
||||||
|
title: this.req.name,
|
||||||
|
url: fileUrl,
|
||||||
|
permissions: {
|
||||||
|
edit: this.user.perm.modify,
|
||||||
|
download: this.user.perm.download,
|
||||||
|
print: this.user.perm.download
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editorConfig: {
|
||||||
|
callbackUrl: `${window.location.protocol}//${window.location.host}${baseURL}/api/onlyoffice/callback?auth=${this.jwt}&save=${encodeURIComponent(this.req.path)}`,
|
||||||
|
user: {
|
||||||
|
id: this.user.id,
|
||||||
|
name: `User ${this.user.id}`
|
||||||
|
},
|
||||||
|
customization: {
|
||||||
|
autosave: true,
|
||||||
|
forcesave: true
|
||||||
|
},
|
||||||
|
lang: this.user.locale,
|
||||||
|
mode: this.user.perm.modify ? "edit" : "view"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(onlyOffice.jwtSecret != "") {
|
||||||
|
const alg = 'HS256';
|
||||||
|
new jose.SignJWT(config)
|
||||||
|
.setProtectedHeader({ alg })
|
||||||
|
.sign(new TextEncoder().encode(onlyOffice.jwtSecret)).then((jwt) => {
|
||||||
|
config.token = jwt;
|
||||||
|
this.editor = new DocsAPI.DocEditor("editor", config);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.editor = new DocsAPI.DocEditor("editor", config);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/*eslint-enable */
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
back() {
|
||||||
|
let uri = url.removeLastDir(this.$route.path) + "/";
|
||||||
|
this.$router.push({ path: uri });
|
||||||
|
},
|
||||||
|
keyEvent(event) {
|
||||||
|
if (!event.ctrlKey && !event.metaKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.fromCharCode(event.which).toLowerCase() !== "s") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.save();
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.$store.commit("updateRequest", {});
|
||||||
|
|
||||||
|
let uri = url.removeLastDir(this.$route.path) + "/";
|
||||||
|
this.$router.push({ path: uri });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -136,6 +136,31 @@
|
|||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3>{{ $t("settings.onlyOffice") }}</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="onlyoffice-url">{{
|
||||||
|
$t("settings.onlyOfficeUrl")
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="text"
|
||||||
|
v-model="settings.onlyoffice.url"
|
||||||
|
id="onlyoffice-url"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="onlyoffice-jwt">{{
|
||||||
|
$t("settings.onlyOfficeJwtSecret")
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
class="input input--block"
|
||||||
|
type="text"
|
||||||
|
v-model="settings.onlyoffice.jwtSecret"
|
||||||
|
id="onlyoffice-jwt"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-action">
|
<div class="card-action">
|
||||||
|
|||||||
@ -60,6 +60,8 @@ func NewHandler(
|
|||||||
users.Handle("/{id:[0-9]+}", monkey(userGetHandler, "")).Methods("GET")
|
users.Handle("/{id:[0-9]+}", monkey(userGetHandler, "")).Methods("GET")
|
||||||
users.Handle("/{id:[0-9]+}", monkey(userDeleteHandler, "")).Methods("DELETE")
|
users.Handle("/{id:[0-9]+}", monkey(userDeleteHandler, "")).Methods("DELETE")
|
||||||
|
|
||||||
|
api.PathPrefix("/onlyoffice").Handler(monkey(onlyofficeCallbackHandler, "/api/onlyoffice/callback")).Methods("POST")
|
||||||
|
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET")
|
api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET")
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE")
|
api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE")
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourcePostHandler(fileCache), "/api/resources")).Methods("POST")
|
api.PathPrefix("/resources").Handler(monkey(resourcePostHandler(fileCache), "/api/resources")).Methods("POST")
|
||||||
|
|||||||
64
http/onlyoffice.go
Normal file
64
http/onlyoffice.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OnlyOfficeCallback struct {
|
||||||
|
ChangesURL string `json:"changesurl,omitempty"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
Users []string `json:"users,omitempty"`
|
||||||
|
UserData string `json:"userdata,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var onlyofficeCallbackHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
|
body, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var data OnlyOfficeCallback
|
||||||
|
err = json.Unmarshal(body, &data)
|
||||||
|
if err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Status == 2 || data.Status == 6 {
|
||||||
|
docPath := r.URL.Query().Get("save")
|
||||||
|
if docPath == "" {
|
||||||
|
return http.StatusInternalServerError, errors.New("unable to get file save path")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !d.user.Perm.Modify || !d.Check(docPath) {
|
||||||
|
return http.StatusForbidden, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
doc, err := http.Get(data.URL)
|
||||||
|
if err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
defer doc.Body.Close()
|
||||||
|
|
||||||
|
err = d.RunHook(func() error {
|
||||||
|
_, writeErr := writeFile(d.user.Fs, docPath, doc.Body)
|
||||||
|
if writeErr != nil {
|
||||||
|
return writeErr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}, "save", docPath, "", d.user)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := map[string]int{
|
||||||
|
"error": 0,
|
||||||
|
}
|
||||||
|
return renderJSON(w, r, resp)
|
||||||
|
})
|
||||||
@ -18,6 +18,7 @@ type settingsData struct {
|
|||||||
Tus settings.Tus `json:"tus"`
|
Tus settings.Tus `json:"tus"`
|
||||||
Shell []string `json:"shell"`
|
Shell []string `json:"shell"`
|
||||||
Commands map[string][]string `json:"commands"`
|
Commands map[string][]string `json:"commands"`
|
||||||
|
OnlyOffice settings.OnlyOffice `json:"onlyoffice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
@ -31,6 +32,7 @@ var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request,
|
|||||||
Tus: d.settings.Tus,
|
Tus: d.settings.Tus,
|
||||||
Shell: d.settings.Shell,
|
Shell: d.settings.Shell,
|
||||||
Commands: d.settings.Commands,
|
Commands: d.settings.Commands,
|
||||||
|
OnlyOffice: d.settings.OnlyOffice,
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderJSON(w, r, data)
|
return renderJSON(w, r, data)
|
||||||
@ -52,6 +54,7 @@ var settingsPutHandler = withAdmin(func(_ http.ResponseWriter, r *http.Request,
|
|||||||
d.settings.Tus = req.Tus
|
d.settings.Tus = req.Tus
|
||||||
d.settings.Shell = req.Shell
|
d.settings.Shell = req.Shell
|
||||||
d.settings.Commands = req.Commands
|
d.settings.Commands = req.Commands
|
||||||
|
d.settings.OnlyOffice = req.OnlyOffice
|
||||||
|
|
||||||
err = d.store.Settings.Save(d.settings)
|
err = d.store.Settings.Save(d.settings)
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
|
|||||||
@ -46,6 +46,7 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys
|
|||||||
"ResizePreview": d.server.ResizePreview,
|
"ResizePreview": d.server.ResizePreview,
|
||||||
"EnableExec": d.server.EnableExec,
|
"EnableExec": d.server.EnableExec,
|
||||||
"TusSettings": d.settings.Tus,
|
"TusSettings": d.settings.Tus,
|
||||||
|
"OnlyOffice": d.settings.OnlyOffice,
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.settings.Branding.Files != "" {
|
if d.settings.Branding.Files != "" {
|
||||||
|
|||||||
7
settings/onlyoffice.go
Normal file
7
settings/onlyoffice.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package settings
|
||||||
|
|
||||||
|
// OnlyOffice contains the onlyoffice server connection settings of the app.
|
||||||
|
type OnlyOffice struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
JWTSecret string `json:"jwtSecret"`
|
||||||
|
}
|
||||||
@ -27,6 +27,7 @@ type Settings struct {
|
|||||||
Commands map[string][]string `json:"commands"`
|
Commands map[string][]string `json:"commands"`
|
||||||
Shell []string `json:"shell"`
|
Shell []string `json:"shell"`
|
||||||
Rules []rules.Rule `json:"rules"`
|
Rules []rules.Rule `json:"rules"`
|
||||||
|
OnlyOffice OnlyOffice `json:"onlyoffice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRules implements rules.Provider.
|
// GetRules implements rules.Provider.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user