+
settings_applications
{{ $t('sidebar.settings') }}
@@ -59,7 +59,7 @@
- {{ $t('sidebar.servedWith') }} File Manager.
+ File Manager v{{ version }}
{{ $t('sidebar.help') }}
@@ -72,7 +72,7 @@ import auth from '@/utils/auth'
export default {
name: 'sidebar',
computed: {
- ...mapState(['user', 'staticGen']),
+ ...mapState(['user', 'staticGen', 'version']),
active () {
return this.$store.state.show === 'sidebar'
}
diff --git a/assets/src/components/buttons/SwitchView.vue b/assets/src/components/buttons/SwitchView.vue
index 48b1fb1c..bc954caa 100644
--- a/assets/src/components/buttons/SwitchView.vue
+++ b/assets/src/components/buttons/SwitchView.vue
@@ -1,32 +1,35 @@
diff --git a/assets/src/components/prompts/FileList.vue b/assets/src/components/prompts/FileList.vue
index 652dc742..15e9c538 100644
--- a/assets/src/components/prompts/FileList.vue
+++ b/assets/src/components/prompts/FileList.vue
@@ -53,7 +53,7 @@ export default {
// so we fetch the data from the previous directory.
api.fetch(url.removeLastDir(this.$route.path))
.then(this.fillOptions)
- .catch(this.showError)
+ .catch(this.$showError)
},
methods: {
fillOptions (req) {
@@ -96,7 +96,7 @@ export default {
api.fetch(uri)
.then(this.fillOptions)
- .catch(this.showError)
+ .catch(this.$showError)
},
touchstart (event) {
let url = event.currentTarget.dataset.url
diff --git a/assets/src/components/prompts/Info.vue b/assets/src/components/prompts/Info.vue
index be7fdca2..ff3a7991 100644
--- a/assets/src/components/prompts/Info.vue
+++ b/assets/src/components/prompts/Info.vue
@@ -111,7 +111,7 @@ export default {
api.checksum(link, hash)
.then((hash) => { event.target.innerHTML = hash })
- .catch(error => { this.$store.commit('showError', error) })
+ .catch(this.$showError)
}
}
}
diff --git a/assets/src/components/prompts/Move.vue b/assets/src/components/prompts/Move.vue
index 7155d53f..7e7f41e3 100644
--- a/assets/src/components/prompts/Move.vue
+++ b/assets/src/components/prompts/Move.vue
@@ -56,7 +56,7 @@ export default {
})
.catch(error => {
buttons.done('move')
- this.$store.commit('showError', error)
+ this.$showError(error)
})
event.preventDefault()
diff --git a/assets/src/components/prompts/NewArchetype.vue b/assets/src/components/prompts/NewArchetype.vue
index 09823763..0356bcc5 100644
--- a/assets/src/components/prompts/NewArchetype.vue
+++ b/assets/src/components/prompts/NewArchetype.vue
@@ -37,9 +37,7 @@ export default {
.then((url) => {
this.$router.push({ path: url })
})
- .catch(error => {
- this.$store.commit('showError', error)
- })
+ .catch(this.$showError)
},
new (url, type) {
url = removePrefix(url)
@@ -47,7 +45,7 @@ export default {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('POST', `${this.$store.state.baseURL}/api/resource${url}`, true)
- request.setRequestHeader('Authorization', `Bearer ${this.$store.state.jwt}`)
+ if (!this.$store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${this.$store.state.jwt}`)
request.setRequestHeader('Archetype', encodeURIComponent(type))
request.onload = () => {
diff --git a/assets/src/components/prompts/NewDir.vue b/assets/src/components/prompts/NewDir.vue
index 42559a0f..25137e6b 100644
--- a/assets/src/components/prompts/NewDir.vue
+++ b/assets/src/components/prompts/NewDir.vue
@@ -43,7 +43,7 @@ export default {
api.post(uri)
.then(() => { this.$router.push({ path: uri }) })
- .catch(error => { this.$store.commit('showError', error) })
+ .catch(this.$showError)
// Close the prompt
this.$store.commit('closeHovers')
diff --git a/assets/src/components/prompts/NewFile.vue b/assets/src/components/prompts/NewFile.vue
index 94ea0c94..c43826c1 100644
--- a/assets/src/components/prompts/NewFile.vue
+++ b/assets/src/components/prompts/NewFile.vue
@@ -44,7 +44,7 @@ export default {
// Create the new file.
api.post(uri)
.then(() => { this.$router.push({ path: uri }) })
- .catch(error => { this.$store.commit('showError', error) })
+ .catch(this.$showError)
// Close the prompt.
this.$store.commit('closeHovers')
diff --git a/assets/src/components/prompts/Prompts.vue b/assets/src/components/prompts/Prompts.vue
index a840ae82..84bc4e12 100644
--- a/assets/src/components/prompts/Prompts.vue
+++ b/assets/src/components/prompts/Prompts.vue
@@ -9,8 +9,6 @@
-
-
@@ -27,8 +25,6 @@ import Rename from './Rename'
import Download from './Download'
import Move from './Move'
import Copy from './Copy'
-import Error from './Error'
-import Success from './Success'
import NewFile from './NewFile'
import NewDir from './NewDir'
import NewArchetype from './NewArchetype'
@@ -47,9 +43,7 @@ export default {
NewArchetype,
Schedule,
Rename,
- Error,
Download,
- Success,
Move,
Copy,
Share,
@@ -70,8 +64,6 @@ export default {
},
computed: {
...mapState(['show', 'plugins']),
- showError: function () { return this.show === 'error' },
- showSuccess: function () { return this.show === 'success' },
showInfo: function () { return this.show === 'info' },
showHelp: function () { return this.show === 'help' },
showDelete: function () { return this.show === 'delete' },
diff --git a/assets/src/components/prompts/Rename.vue b/assets/src/components/prompts/Rename.vue
index 434bf7cd..231c34bf 100644
--- a/assets/src/components/prompts/Rename.vue
+++ b/assets/src/components/prompts/Rename.vue
@@ -68,7 +68,7 @@ export default {
}
this.$store.commit('setReload', true)
}).catch(error => {
- this.$store.commit('showError', error)
+ this.$showError(error)
})
this.$store.commit('closeHovers')
diff --git a/assets/src/components/prompts/Share.vue b/assets/src/components/prompts/Share.vue
index db2ec429..20dfbe7c 100644
--- a/assets/src/components/prompts/Share.vue
+++ b/assets/src/components/prompts/Share.vue
@@ -18,7 +18,7 @@
:aria-label="$t('buttons.delete')"
:title="$t('buttons.delete')">
delete
-
@@ -54,7 +54,7 @@
diff --git a/assets/src/css/base.css b/assets/src/css/base.css
index f5582857..e6f4018a 100644
--- a/assets/src/css/base.css
+++ b/assets/src/css/base.css
@@ -2,7 +2,6 @@ body {
font-family: 'Roboto', sans-serif;
padding-top: 4em;
background-color: #f8f8f8;
- user-select: none;
color: #212121;
}
diff --git a/assets/src/css/dashboard.css b/assets/src/css/dashboard.css
index 003ced21..f7e9b23f 100644
--- a/assets/src/css/dashboard.css
+++ b/assets/src/css/dashboard.css
@@ -131,18 +131,21 @@ p code {
display: flex;
color: rgb(84, 110, 122);
font-weight: 500;
- padding: 0 0 1em;
margin: 0 0 1em;
font-size: .8em;
- border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+ text-align: center;
+ justify-content: space-between;
+ padding: 0;
}
.dashboard #nav li {
width: 100%;
+ padding: 0 0 1em;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
-.dashboard #nav li:last-child {
- text-align: right
+.dashboard #nav li.active {
+ border-color: #2196f3
}
.dashboard #nav i {
diff --git a/assets/src/css/prompts.css b/assets/src/css/prompts.css
index b1a7fbe6..e85d9e0f 100644
--- a/assets/src/css/prompts.css
+++ b/assets/src/css/prompts.css
@@ -206,3 +206,24 @@
margin-right: .5em;
border: 1px solid #dadada;
}
+
+.prompt#share .action.copy-clipboard::after {
+ content: 'Copied!';
+ position: absolute;
+ left: -25%;
+ width: 150%;
+ font-size: .6em;
+ text-align: center;
+ background: #44a6f5;
+ color: #fff;
+ padding: .5em .2em;
+ border-radius: .4em;
+ top: -2em;
+ transition: .1s ease opacity;
+ opacity: 0;
+}
+
+.prompt#share .action.copy-clipboard.active::after {
+ opacity: 1;
+}
+
diff --git a/assets/src/css/styles.css b/assets/src/css/styles.css
index f9c2f488..a90d60bd 100644
--- a/assets/src/css/styles.css
+++ b/assets/src/css/styles.css
@@ -1,4 +1,5 @@
@import "~normalize.css/normalize.css";
+@import "~noty/lib/noty.css";
@import "./fonts.css";
@import "./base.css";
@import "./header.css";
@@ -180,6 +181,17 @@
* PROMPT *
* * * * * * * * * * * * * * * */
+.noty_buttons {
+ text-align: right;
+ padding: 0 10px 10px !important;
+}
+
+.noty_buttons button {
+ background: rgba(0, 0, 0, 0.05);
+ border: 1px solid rgba(0,0,0,0.1);
+ box-shadow: 0 0 0 0;
+ font-size: 14px;
+}
/* * * * * * * * * * * * * * * *
* FOOTER *
diff --git a/assets/src/i18n/en.yaml b/assets/src/i18n/en.yaml
index b6903679..5b078c2b 100644
--- a/assets/src/i18n/en.yaml
+++ b/assets/src/i18n/en.yaml
@@ -26,11 +26,13 @@ buttons:
publish: Publish
selectMultiple: Select multiple
schedule: Schedule
- switchView: Swicth view
+ switchView: Switch view
toggleSidebar: Toggle sidebar
update: Update
upload: Upload
permalink: Get Permanent Link
+success:
+ linkCopied: Link copied!
errors:
forbidden: You're not welcome here.
internal: Something really went wrong.
@@ -122,6 +124,7 @@ settings:
examples: Examples
globalSettings: Global Settings
language: Language
+ lockPassword: Prevent the user from changing the password
newPassword: Your new password
newPasswordConfirm: Confirm your new password
newUser: New User
@@ -165,7 +168,6 @@ sidebar:
myFiles: My files
newFile: New file
newFolder: New folder
- servedWith: Served with
settings: Settings
siteSettings: Site Settings
hugoNew: Hugo New
@@ -185,6 +187,7 @@ search:
writeToSearch: Write here to search
languages:
en: English
+ fr: Français
pt: Português
ja: 日本語
zhCN: 中文 (简体)
diff --git a/assets/src/i18n/fr.yaml b/assets/src/i18n/fr.yaml
new file mode 100644
index 00000000..b1eafdc6
--- /dev/null
+++ b/assets/src/i18n/fr.yaml
@@ -0,0 +1,193 @@
+permanent: Permanent
+buttons:
+ cancel: Annuler
+ close: Fermer
+ copy: Copier
+ copyFile: Copier le fichier
+ copyToClipboard: Copier dans le presse-papier
+ create: Créer
+ delete: Supprimer
+ download: Télécharger
+ info: Info
+ more: Plus
+ move: Déplacer
+ moveFile: Déplacer le fichier
+ new: Nouveau
+ next: Suivant
+ ok: OK
+ replace: Remplacer
+ previous: Précédent
+ rename: Renommer
+ reportIssue: Rapport d'erreur
+ save: Enregistrer
+ search: Chercher
+ select: Sélectionner
+ share: Partager
+ publish: Publier
+ selectMultiple: Sélection multiple
+ schedule: Fixer la date
+ switchView: Changer le mode d'affichage
+ toggleSidebar: Afficher/Masquer la barre latérale
+ update: Mettre à jour
+ upload: Importer
+ permalink: Obtenir un lien permanent
+errors:
+ forbidden: Vous n'êtes pas autorisé à être ici.
+ internal: Aïe ! Quelque chose s'est mal passé.
+ notFound: Impossible d'accéder à cet emplacement.
+files:
+ folders: Dossiers
+ files: Fichiers
+ body: Corps
+ clear: Fermer
+ closePreview: Fermer la prévisualisation
+ home: Accueil
+ lastModified: Dernière modification
+ loading: Chargement...
+ lonely: Il semble qu'il n'y ai rien par ici...
+ metadata: Metadonnées
+ multipleSelectionEnabled: Sélection multiple activée
+ name: Nom
+ size: Taille
+ sortByName: Trier par nom
+ sortBySize: Trier par taille
+ sortByLastModified: Trier par date de dernière modification
+help:
+ click: Sélectionner un élément
+ ctrl:
+ click: Sélectionner plusieurs éléments
+ f: Ouvrir l'invité de recherche
+ s: Télécharger l'élément actuel
+ del: Supprimer les éléments sélectionnés
+ doubleClick: Ouvrir un élément
+ esc: Désélectionner et/ou fermer la boîte de dialogue
+ f1: Ouvrir l'aide
+ f2: Renommer le fichier
+ help: Aide
+login:
+ password: Mot de passe
+ submit: Se connecter
+ username: Utilisateur
+ wrongCredentials: Identifiants incorrects !
+prompts:
+ copy: Copier
+ copyMessage: 'Choisissez l''emplacement où copier la sélection :'
+ currentlyNavigating: 'Dossier courant :'
+ deleteMessageMultiple: Etes-vous sûr de vouloir supprimer ces {count} élément(s) ?
+ deleteMessageSingle: Etes-vous sûr de vouloir supprimer cet élément ?
+ deleteTitle: Supprimer
+ displayName: 'Nom :'
+ download: Télécharger
+ downloadMessage: 'Choisissez le format de téléchargement :'
+ error: Quelque chose s'est mal passé
+ fileInfo: Informations
+ filesSelected: "{count} éléments sélectionnés"
+ lastModified: Dernière modification
+ move: Déplacer
+ moveMessage: 'Choisissez l''emplacement où déplacer la sélection :'
+ newDir: Nouveau dossier
+ newDirMessage: 'Nom du nouveau dossier :'
+ newFile: Nouveau fichier
+ newFileMessage: 'Nom du nouveau fichier :'
+ numberDirs: Nombre de dossiers
+ numberFiles: Nombre de fichiers
+ replace: Remplacer
+ replaceMessage: >
+ Un des fichiers que vous êtes en train d'importer a le même nom qu'un autre déjà présent.
+ Voulez-vous remplacer le fichier actuel par le nouveau ?
+ rename: Renommer
+ renameMessage: Nouveau nom pour
+ show: Montrer
+ size: Taille
+ schedule: Fixer la date
+ scheduleMessage: Choisissez une date pour planifier la publication de ce post
+ newArchetype: Créer un nouveau post basé sur un archétype. Votre fichier sera créé dans le dossier de contenu.
+settings:
+ admin: Admin
+ administrator: Administrateur
+ allowCommands: Exécuter des commandes
+ allowEdit: Editer, renommer et supprimer des fichiers ou des dossiers
+ allowNew: Créer de nouveaux fichiers et dossiers
+ allowPublish: Publier de nouveaux posts et pages
+ avoidChanges: "(Laisser vide pour conserver l'actuel)"
+ changePassword: Modifier le mot de passe
+ commands: Commandes
+ commandsHelp: >
+ Ici vous pouvez définir des commandes qui seront exécutées lors de l'évènement correspondant.
+ Vous devez indiquer une commande par ligne. Si l'évènement est en rapport avec des fichiers,
+ par exemple avant et après enregistrement, la variable d'environement "file" sera disponible
+ et contiendra le chemin d'accès vers le fichier.
+ commandsUpdated: Commandes mises à jour !
+ customStylesheet: Feuille de style personnalisée
+ examples: Exemples
+ globalSettings: Paramètres généraux
+ language: Langue
+ newPassword: Votre nouveau mot de passe
+ newPasswordConfirm: Confirmation du nouveau mot de passe
+ newUser: Nouvel Utilisateur
+ password: Mot de passe
+ passwordUpdated: Mot de passe mis à jour !
+ permissions: Permissions
+ permissionsHelp: >
+ Vous pouvez définir l'utilisateur comme étant un administrateur ou encore choisir les
+ permissions individuellement. Si vous sélectionnez "Administrateur", toutes les autres
+ options seront automatiquement activées. La gestion des utilisateurs est un privilège que
+ seul l'administrateur possède.
+ profileSettings: Paramètres du profil
+ ruleExample1: Bloque l'accès à tous les fichiers commençant par un point (comme par exemple .git, .gitignore) dans tous les dossiers
+ ruleExample2: Bloque l'accès au fichier nommé "Caddyfile" à la racine du dossier utilisateur
+ rules: Règles
+ rulesHelp1: >
+ Vous pouvez définir ici un ensemble de règles pour cet utilisateur.
+ Les fichiers bloqués ne seront pas affichés et ne seront pas accessibles par l'utilisateur.
+ Les expressions régulières sont supportées et les chemins d'accès sont relatifs par rapport au dossier de l'utilisateur.
+ rulesHelp2: >
+ Chaque règle est définie sur une ligne différente et doit commencer par le mot clé {0} ou {1}.
+ Vous devez ensuite ajouter {2} si vous utilisez une expression régulière puis l'expression en question ou bien seulement le chemin d'accès.
+ scope: Portée du dossier utilisateur
+ settingsUpdated: Les paramètres ont été mis à jour !
+ user: Utilisateur
+ userCommands: Commandes
+ userCommandsHelp: 'Une liste séparée par des espaces des commandes permises pour l''utilisateur. Exemple :'
+ userCreated: Utilisateur créé !
+ userDeleted: Utilisateur supprimé !
+ userManagement: Gestion des utilisateurs
+ username: Nom d'utilisateur
+ users: Utilisateurs
+ userUpdated: Utilisateur mis à jour !
+sidebar:
+ help: Aide
+ logout: Se déconnecter
+ myFiles: Mes fichiers
+ newFile: Nouveau fichier
+ newFolder: Nouveau dossier
+ settings: Paramètres
+ siteSettings: Paramètres du site
+ hugoNew: Nouveau Hugo
+ preview: Prévisualiser
+search:
+ images: Images
+ music: Musique
+ pdf: PDF
+ pressToExecute: Appuyez sur Entrée pour exécuter
+ pressToSearch: Appuyez sur Entrée pour lancer la recherche
+ search: Recherche en cours...
+ searchOrCommand: Rechercher ou exécuter une commande...
+ searchOrSupportedCommand: 'Lancez une recherche ou exécutez une commande parmis les suivantes :'
+ type: Tapez votre recherche et appuyez sur Entrée
+ types: Types
+ video: Video
+ writeToSearch: Ecrivez ici pour lancer une recherche
+languages:
+ en: English
+ fr: Français
+ pt: Português
+ ja: 日本語
+ zhCN: 中文 (简体)
+ zhTW: 中文 (繁體)
+time:
+ unit: Unité de temps
+ seconds: Secondes
+ minutes: Minutes
+ hours: Heures
+ days: Jours
diff --git a/assets/src/i18n/index.js b/assets/src/i18n/index.js
index 8022eb05..1afe0925 100644
--- a/assets/src/i18n/index.js
+++ b/assets/src/i18n/index.js
@@ -1,6 +1,7 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from './en.yaml'
+import fr from './fr.yaml'
import pt from './pt.yaml'
import ja from './ja.yaml'
import zhCN from './zh-cn.yaml'
@@ -13,6 +14,7 @@ const i18n = new VueI18n({
fallbackLocale: 'en',
messages: {
'en': en,
+ 'fr': fr,
'pt': pt,
'ja': ja,
'zh-cn': zhCN,
diff --git a/assets/src/i18n/ja.yaml b/assets/src/i18n/ja.yaml
index 6d6241f1..fd1f130b 100644
--- a/assets/src/i18n/ja.yaml
+++ b/assets/src/i18n/ja.yaml
@@ -31,6 +31,8 @@ buttons:
update: 更新
upload: アップロード
permalink: 固定リンク
+success:
+ linkCopied: リンクがコピーされました!
errors:
forbidden: アクセスが拒否されました。
internal: 内部エラーが発生しました。
@@ -122,6 +124,7 @@ settings:
examples: 例
globalSettings: グローバル設定
language: 言語
+ lockPassowrd: 新しいパスワードを変更に禁止
newPassword: 新しいパスワード
newPasswordConfirm: 新しいパスワードを確認します
newUser: 新しいユーザー
@@ -165,7 +168,6 @@ sidebar:
myFiles: 私のファイル
newFile: 新しいファイルを作成
newFolder: 新しいフォルダを作成
- servedWith: サービス提供者
settings: 設定
siteSettings: サイト設定
hugoNew: Hugo New
@@ -185,6 +187,7 @@ search:
writeToSearch: ここにキーワードを入力してください
languages:
en: English
+ fr: Français
pt: Português
ja: 日本語
zhCN: 中文 (简体)
diff --git a/assets/src/i18n/pt.yaml b/assets/src/i18n/pt.yaml
index 775b1716..20872831 100644
--- a/assets/src/i18n/pt.yaml
+++ b/assets/src/i18n/pt.yaml
@@ -31,6 +31,8 @@ buttons:
update: Atualizar
upload: Enviar
permalink: Obter link permanente
+success:
+ linkCopied: Link copiado!
errors:
forbidden: Tu não és bem-vindo aqui.
internal: Algo correu bastante mal.
@@ -66,6 +68,7 @@ help:
help: Ajuda
languages:
en: English
+ fr: Français
pt: Português
ja: 日本語
zhCN: 中文 (简体)
@@ -142,6 +145,7 @@ settings:
examples: Exemplos
globalSettings: Configurações Globais
language: Linguagem
+ lockPassword: Não permitir que o utilizador altere a palavra-passe
newPassword: Nova palavra-passe
newPasswordConfirm: Confirme a nova palavra-passe
newUser: Novo Utilizador
@@ -189,7 +193,6 @@ sidebar:
newFile: Novo ficheiro
newFolder: Nova pasta
preview: Pré-visualizar
- servedWith: Servido com
settings: Configurações
siteSettings: Configurações do Site
time:
diff --git a/assets/src/i18n/zh-cn.yaml b/assets/src/i18n/zh-cn.yaml
index c70b5c7b..ef15298a 100644
--- a/assets/src/i18n/zh-cn.yaml
+++ b/assets/src/i18n/zh-cn.yaml
@@ -31,6 +31,8 @@ buttons:
update: 更新
upload: 上传
permalink: 获取永久链接
+success:
+ linkCopied: 链接已复制!
errors:
forbidden: 你被禁止访问。
internal: 内部出现麻烦了。
@@ -121,6 +123,7 @@ settings:
examples: 例子
globalSettings: 全局设置
language: 语言
+ lockPassowrd: 禁止用户修改密码
newPassword: 您的新密码
newPasswordConfirm: 重输一遍新密码
newUser: 新建用户
@@ -163,7 +166,6 @@ sidebar:
myFiles: 我的文件
newFile: 新建文件
newFolder: 新建文件夹
- servedWith: '服务提供者:'
settings: 设置
siteSettings: 网站设置
hugoNew: Hugo New
@@ -183,6 +185,7 @@ search:
writeToSearch: 请输入要搜索的内容
languages:
en: English
+ fr: Français
pt: Português
ja: 日本語
zhCN: 中文 (简体)
diff --git a/assets/src/i18n/zh-tw.yaml b/assets/src/i18n/zh-tw.yaml
index f6f5db5d..62d88fc6 100644
--- a/assets/src/i18n/zh-tw.yaml
+++ b/assets/src/i18n/zh-tw.yaml
@@ -4,7 +4,7 @@ buttons:
close: 關閉
copy: 複製
copyFile: 複製檔案
- copyToClipboard: 複製到剪貼板
+ copyToClipboard: 複製到剪貼簿
create: 建立
delete: 刪除
download: 下載
@@ -31,8 +31,10 @@ buttons:
update: 更新
upload: 上傳
permalink: 獲取永久連結
+success:
+ linkCopied: 連結已複製!
errors:
- forbidden: 你被禁止訪問。
+ forbidden: 你被禁止存取。
internal: 內部出現麻煩了。
notFound: 找不到檔案。
files:
@@ -45,7 +47,7 @@ files:
lastModified: 最後修改
loading: 讀取中...
lonely: 這裡沒有任何檔案...
- metadata: 中繼資料
+ metadata: 詮釋資料
multipleSelectionEnabled: 多選模式已開啟
name: 名稱
size: 大小
@@ -100,15 +102,15 @@ prompts:
show: 顯示
size: 大小
schedule: 計畫
- scheduleMessage: 請選擇發佈這篇帖子的日期。
- newArchetype: 建立一個基於原型的新帖子。您的檔案將會建立在內容資料夾中。
+ scheduleMessage: 請選擇發佈這篇貼文的日期。
+ newArchetype: 建立一個基於原型的新貼文。您的檔案將會建立在內容資料夾中。
settings:
admin: 管理員
administrator: 管理員
allowCommands: 執行命令
allowEdit: 編輯、重命名或刪除檔案/目錄
allowNew: 創建新檔案和目錄
- allowPublish: 發佈新的帖子與頁面
+ allowPublish: 發佈新的貼文與頁面
avoidChanges: '(留空以避免更改)'
changePassword: 更改密碼
commands: 命令
@@ -118,52 +120,52 @@ settings:
則檔案的路徑會被賦值給環境變數 \"file\"。"
commandsUpdated: 命令已更新!
customStylesheet: 自定義樣式表
- examples: 例子
+ examples: 範例
globalSettings: 全域設定
language: 語言
+ lockPassword: 禁止使用者修改密碼
newPassword: 您的新密碼
newPasswordConfirm: 重輸一遍新密碼
- newUser: 建立用戶
+ newUser: 建立使用者
password: 密碼
passwordUpdated: 密碼已更新!
permissions: 權限
permissionsHelp: "\
- 您可以將該用戶設置為管理員,也可以單獨選擇各項權限。\
+ 您可以將該使用者設置為管理員,也可以單獨選擇各項權限。\
如果選擇了“管理員”,則其他的選項會被自動勾上,\
- 同時該用戶可以管理其他用戶。"
+ 同時該使用者可以管理其他使用者。"
profileSettings: 設定檔設定
ruleExample1: "\
- 封鎖用戶訪問所有資料夾下任何以 . 開頭的檔案\
+ 封鎖使用者存取所有資料夾下任何以 . 開頭的檔案\
(隱藏文件, 例如: .git, .gitignore)。"
- ruleExample2: 封鎖用戶訪問其目錄範圍的根目錄下名為 Caddyfile 的檔案。
+ ruleExample2: 封鎖使用者存取其目錄範圍的根目錄下名為 Caddyfile 的檔案。
rules: 規則
rulesHelp1: "\
- 您可以為該用戶製定一組黑名單或白名單式的規則,\
- 被屏蔽的檔案將不會顯示在清單中,用戶也無權限訪問,\
+ 您可以為該使用者製定一組黑名單或白名單式的規則,\
+ 被屏蔽的檔案將不會顯示在清單中,使用者也無權限存取,\
支持相對於目錄範圍的路徑。"
rulesHelp2: "\
每行一條規則,且必須以關鍵字 {0} 或 {1} 開頭。\
如要使用規則運算式,請在加上 {2} 之後再附上運算式或路徑。"
scope: 目錄範圍
settingsUpdated: 設定已更新!
- user: 用戶
- userCommands: 用戶命令
+ user: 使用者
+ userCommands: 使用者命令
userCommandsHelp: "\
- 指定該用戶可以執行的命令,用空格分隔。\
+ 指定該使用者可以執行的命令,用空格分隔。\
例如:"
- userCreated: 用戶已建立!
- userDeleted: 用戶已刪除!
- userManagement: 用戶管理
- username: 用戶名
- users: 用戶
- userUpdated: 用戶已更新!
+ userCreated: 使用者已建立!
+ userDeleted: 使用者已刪除!
+ userManagement: 使用者管理
+ username: 使用者名稱
+ users: 使用者
+ userUpdated: 使用者已更新!
sidebar:
help: 幫助
logout: 登出
myFiles: 我的檔案
newFile: 建立檔案
newFolder: 建立資料夾
- servedWith: '服務提供者:'
settings: 設定
siteSettings: 網站設定
hugoNew: Hugo New
@@ -183,12 +185,14 @@ search:
writeToSearch: 請輸入要搜尋的內容
languages:
en: English
+ fr: Français
pt: Português
ja: 日本語
zhCN: 中文 (简体)
+ zhTW: 中文 (繁體)
time:
unit: 時間單位
seconds: 秒
minutes: 分鐘
hours: 小時
- days: 天
\ No newline at end of file
+ days: 天
diff --git a/assets/src/main.js b/assets/src/main.js
index 33c69173..57e7b930 100644
--- a/assets/src/main.js
+++ b/assets/src/main.js
@@ -3,9 +3,47 @@ import App from './App'
import store from './store'
import router from './router'
import i18n from './i18n'
+import Noty from 'noty'
Vue.config.productionTip = true
+const notyDefault = {
+ type: 'info',
+ layout: 'bottomRight',
+ timeout: 1000,
+ progressBar: true
+}
+
+Vue.prototype.$noty = function (opts) {
+ new Noty(Object.assign({}, notyDefault, opts)).show()
+}
+
+Vue.prototype.$showSuccess = function (message) {
+ new Noty(Object.assign({}, notyDefault, {
+ text: message,
+ type: 'success'
+ })).show()
+}
+
+Vue.prototype.$showError = function (error) {
+ // TODO: add btns: close and report issue
+ let n = new Noty(Object.assign({}, notyDefault, {
+ text: error,
+ type: 'error',
+ timeout: null,
+ buttons: [
+ Noty.button(i18n.t('buttons.reportIssue'), 'cancel', function () {
+ window.open('https://github.com/hacdias/filemanager/issues/new')
+ }),
+ Noty.button(i18n.t('buttons.close'), '', function () {
+ n.close()
+ })
+ ]
+ }))
+
+ n.show()
+}
+
/* eslint-disable no-new */
new Vue({
el: '#app',
diff --git a/assets/src/store/index.js b/assets/src/store/index.js
index cdecc09b..0a479147 100644
--- a/assets/src/store/index.js
+++ b/assets/src/store/index.js
@@ -14,6 +14,8 @@ const state = {
},
staticGen: document.querySelector('meta[name="staticgen"]').getAttribute('content'),
baseURL: document.querySelector('meta[name="base"]').getAttribute('content'),
+ noAuth: (document.querySelector('meta[name="noauth"]').getAttribute('content') === 'true'),
+ version: document.querySelector('meta[name="version"]').getAttribute('content'),
jwt: '',
progress: 0,
schedule: '',
diff --git a/assets/src/store/mutations.js b/assets/src/store/mutations.js
index 6caa26ee..b8bf3fd9 100644
--- a/assets/src/store/mutations.js
+++ b/assets/src/store/mutations.js
@@ -45,8 +45,12 @@ const mutations = {
resetSelected: (state) => {
state.selected = []
},
- listingDisplay: (state, value) => {
- state.req.display = value
+ updateUser: (state, value) => {
+ if (typeof value !== 'object') return
+
+ for (let field in value) {
+ state.user[field] = value[field]
+ }
},
updateRequest: (state, value) => {
state.req = value
diff --git a/assets/src/utils/api.js b/assets/src/utils/api.js
index 087165cf..9d429062 100644
--- a/assets/src/utils/api.js
+++ b/assets/src/utils/api.js
@@ -18,7 +18,7 @@ export function fetch (url) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/resource${url}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -41,7 +41,7 @@ export function remove (url) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('DELETE', `${store.state.baseURL}/api/resource${url}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
if (request.status === 200) {
@@ -62,7 +62,7 @@ export function post (url, content = '', overwrite = false, onupload) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('POST', `${store.state.baseURL}/api/resource${url}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
if (typeof onupload === 'function') {
request.upload.onprogress = onupload
@@ -95,7 +95,7 @@ export function put (url, content = '', publish = false, date = '') {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('PUT', `${store.state.baseURL}/api/resource${url}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.setRequestHeader('Publish', publish)
if (date !== '') {
@@ -125,7 +125,7 @@ function moveCopy (items, copy = false) {
promises.push(new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('PATCH', `${store.state.baseURL}/api/resource${from}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.setRequestHeader('Destination', to)
if (copy) {
@@ -162,7 +162,7 @@ export function checksum (url, algo) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/checksum${url}?algo=${algo}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
if (request.status === 200) {
@@ -226,7 +226,7 @@ export function getSettings () {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/settings/`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -255,7 +255,7 @@ export function updateSettings (param, which) {
let request = new window.XMLHttpRequest()
request.open('PUT', `${store.state.baseURL}/api/settings/`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -278,7 +278,7 @@ export function getUsers () {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/users/`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -299,7 +299,7 @@ export function getUser (id) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/users/${id}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -320,7 +320,7 @@ export function newUser (user) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('POST', `${store.state.baseURL}/api/users/`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -345,7 +345,7 @@ export function updateUser (user, which) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('PUT', `${store.state.baseURL}/api/users/${user.ID}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -370,7 +370,7 @@ export function deleteUser (id) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('DELETE', `${store.state.baseURL}/api/users/${id}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
switch (request.status) {
@@ -395,7 +395,7 @@ export function getShare (url) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/share${url}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
if (request.status === 200) {
@@ -414,7 +414,7 @@ export function deleteShare (hash) {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('DELETE', `${store.state.baseURL}/api/share/${hash}`, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
if (request.status === 200) {
@@ -439,7 +439,7 @@ export function share (url, expires = '', unit = 'hours') {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('POST', url, true)
- request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${store.state.jwt}`)
request.onload = () => {
if (request.status === 200) {
diff --git a/assets/src/utils/auth.js b/assets/src/utils/auth.js
index cde1de92..5be964f6 100644
--- a/assets/src/utils/auth.js
+++ b/assets/src/utils/auth.js
@@ -16,7 +16,7 @@ function loggedIn () {
return new Promise((resolve, reject) => {
let request = new window.XMLHttpRequest()
request.open('GET', `${store.state.baseURL}/api/auth/renew`, true)
- request.setRequestHeader('Authorization', `Bearer ${cookie('auth')}`)
+ if (!store.state.noAuth) request.setRequestHeader('Authorization', `Bearer ${cookie('auth')}`)
request.onload = () => {
if (request.status === 200) {
diff --git a/assets/src/views/GlobalSettings.vue b/assets/src/views/GlobalSettings.vue
index 28c23829..4b4a5085 100644
--- a/assets/src/views/GlobalSettings.vue
+++ b/assets/src/views/GlobalSettings.vue
@@ -1,16 +1,9 @@
- -
-
- keyboard_arrow_left {{ $t('settings.profileSettings') }}
-
-
- -
-
- {{ $t('settings.userManagement') }} keyboard_arrow_right
-
-
+ - {{ $t('settings.profileSettings') }}
+ - {{ $t('settings.globalSettings') }}
+ - {{ $t('settings.userManagement') }}
{{ $t('settings.globalSettings') }}
@@ -45,7 +38,7 @@