pull/3756/head
Laurynas Gadliauskas 2021-10-27 11:22:47 +03:00
commit c2ea58d7c9
17 changed files with 64 additions and 23 deletions

View File

@ -42,6 +42,7 @@ func addConfigFlags(flags *pflag.FlagSet) {
flags.String("recaptcha.secret", "", "ReCaptcha secret") flags.String("recaptcha.secret", "", "ReCaptcha secret")
flags.String("branding.name", "", "replace 'File Browser' by this name") flags.String("branding.name", "", "replace 'File Browser' by this name")
flags.String("branding.color", "", "set the theme color")
flags.String("branding.files", "", "path to directory with images and custom styles") flags.String("branding.files", "", "path to directory with images and custom styles")
flags.Bool("branding.disableExternal", false, "disable external links such as GitHub links") flags.Bool("branding.disableExternal", false, "disable external links such as GitHub links")
} }
@ -132,6 +133,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
fmt.Fprintf(w, "\tName:\t%s\n", set.Branding.Name) fmt.Fprintf(w, "\tName:\t%s\n", set.Branding.Name)
fmt.Fprintf(w, "\tFiles override:\t%s\n", set.Branding.Files) fmt.Fprintf(w, "\tFiles override:\t%s\n", set.Branding.Files)
fmt.Fprintf(w, "\tDisable external links:\t%t\n", set.Branding.DisableExternal) fmt.Fprintf(w, "\tDisable external links:\t%t\n", set.Branding.DisableExternal)
fmt.Fprintf(w, "\tColor:\t%s\n", set.Branding.Color)
fmt.Fprintln(w, "\nServer:") fmt.Fprintln(w, "\nServer:")
fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log) fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log)
fmt.Fprintf(w, "\tPort:\t%s\n", ser.Port) fmt.Fprintf(w, "\tPort:\t%s\n", ser.Port)

View File

@ -55,6 +55,8 @@ you want to change. Other options will remain unchanged.`,
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
case "branding.name": case "branding.name":
set.Branding.Name = mustGetString(flags, flag.Name) set.Branding.Name = mustGetString(flags, flag.Name)
case "branding.color":
set.Branding.Color = mustGetString(flags, flag.Name)
case "branding.disableExternal": case "branding.disableExternal":
set.Branding.DisableExternal = mustGetBool(flags, flag.Name) set.Branding.DisableExternal = mustGetBool(flags, flag.Name)
case "branding.files": case "branding.files":

View File

@ -16,7 +16,7 @@
<!-- Add to home screen for Android and modern mobile browsers --> <!-- Add to home screen for Android and modern mobile browsers -->
<link rel="manifest" id="manifestPlaceholder" crossorigin="use-credentials"> <link rel="manifest" id="manifestPlaceholder" crossorigin="use-credentials">
<meta name="theme-color" content="#2979ff"> <meta name="theme-color" content="[{[ if .Color -]}][{[ .Color ]}][{[ else ]}]#2979ff[{[ end ]}]">
<!-- Add to home screen for Safari on iOS/iPadOS --> <!-- Add to home screen for Safari on iOS/iPadOS -->
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
@ -26,7 +26,7 @@
<!-- Add to home screen for Windows --> <!-- Add to home screen for Windows -->
<meta name="msapplication-TileImage" content="[{[ .StaticURL ]}]/img/icons/mstile-144x144.png"> <meta name="msapplication-TileImage" content="[{[ .StaticURL ]}]/img/icons/mstile-144x144.png">
<meta name="msapplication-TileColor" content="#2979ff"> <meta name="msapplication-TileColor" content="[{[ if .Color -]}][{[ .Color ]}][{[ else ]}]#2979ff[{[ end ]}]">
<!-- Inject Some Variables and generate the manifest json --> <!-- Inject Some Variables and generate the manifest json -->
<script> <script>
@ -51,7 +51,7 @@
"start_url": window.location.origin + window.FileBrowser.BaseURL, "start_url": window.location.origin + window.FileBrowser.BaseURL,
"display": "standalone", "display": "standalone",
"background_color": "#ffffff", "background_color": "#ffffff",
"theme_color": "#455a64" "theme_color": window.FileBrowser.Color || "#455a64"
} }
const stringManifest = JSON.stringify(dynamicManifest); const stringManifest = JSON.stringify(dynamicManifest);

View File

@ -1,15 +1,15 @@
<template> <template>
<nav :class="{ active }"> <nav :class="{ active }">
<template v-if="isLogged"> <template v-if="isLogged">
<router-link <button
class="action" class="action"
to="/files/" @click="toRoot"
:aria-label="$t('sidebar.myFiles')" :aria-label="$t('sidebar.myFiles')"
:title="$t('sidebar.myFiles')" :title="$t('sidebar.myFiles')"
> >
<i class="material-icons">folder</i> <i class="material-icons">folder</i>
<span>{{ $t("sidebar.myFiles") }}</span> <span>{{ $t("sidebar.myFiles") }}</span>
</router-link> </button>
<div v-if="user.perm.create"> <div v-if="user.perm.create">
<button <button
@ -48,15 +48,15 @@
<quota v-if="quotaExists"></quota> <quota v-if="quotaExists"></quota>
<div> <div>
<router-link <button
class="action" class="action"
to="/settings" @click="toSettings"
:aria-label="$t('sidebar.settings')" :aria-label="$t('sidebar.settings')"
:title="$t('sidebar.settings')" :title="$t('sidebar.settings')"
> >
<i class="material-icons">settings_applications</i> <i class="material-icons">settings_applications</i>
<span>{{ $t("sidebar.settings") }}</span> <span>{{ $t("sidebar.settings") }}</span>
</router-link> </button>
<button <button
v-if=" v-if="
@ -150,6 +150,14 @@ export default {
authLogoutURL: () => authLogoutURL, authLogoutURL: () => authLogoutURL,
}, },
methods: { methods: {
toRoot() {
this.$router.push({ path: "/files/" }, () => {});
this.$store.commit("closeHovers");
},
toSettings() {
this.$router.push({ path: "/settings" }, () => {});
this.$store.commit("closeHovers");
},
help() { help() {
this.$store.commit("showHover", "help"); this.$store.commit("showHover", "help");
}, },

View File

@ -44,6 +44,7 @@ export default {
lastX: null, lastX: null,
lastY: null, lastY: null,
inDrag: false, inDrag: false,
touches: 0,
lastTouchDistance: 0, lastTouchDistance: 0,
moveDisabled: false, moveDisabled: false,
disabledTimer: null, disabledTimer: null,

View File

@ -189,6 +189,9 @@ export default {
return filesize(this.size); return filesize(this.size);
}, },
humanTime: function () { humanTime: function () {
if (this.user.dateFormat) {
return moment(this.modified).format("L LT");
}
return moment(this.modified).fromNow(); return moment(this.modified).fromNow();
}, },
dragStart: function () { dragStart: function () {

View File

@ -84,7 +84,8 @@ header .menu-button {
#search #input { #search #input {
background-color: #f5f5f5; background-color: #f5f5f5;
display: flex; display: flex;
padding: 0.75em; height: 100%;
padding: 0em 0.75em;
border-radius: 0.3em; border-radius: 0.3em;
transition: .1s ease all; transition: .1s ease all;
align-items: center; align-items: center;

View File

@ -291,18 +291,21 @@ main .spinner .bounce2 {
/* EDITOR */ /* EDITOR */
#editor-container { #editor-container {
display: flex;
flex-direction: column;
background-color: #fafafa; background-color: #fafafa;
position: fixed; position: fixed;
padding-top: 4em; padding-top: 4em;
top: 0; top: 0;
left: 0; left: 0;
height: 100%;
width: 100%; width: 100%;
z-index: 9999; z-index: 9999;
overflow: hidden; overflow: hidden;
} }
#editor-container #editor { #editor-container #editor {
height: calc(100vh - 8.4em); flex: 1;
} }
#editor-container .breadcrumbs { #editor-container .breadcrumbs {

View File

@ -244,6 +244,7 @@
"rules": "Rules", "rules": "Rules",
"rulesHelp": "Here you can define a set of allow and disallow rules for this specific user. The blocked files won't show up in the listings and they wont be accessible to the user. We support regex and paths relative to the users scope.\n", "rulesHelp": "Here you can define a set of allow and disallow rules for this specific user. The blocked files won't show up in the listings and they wont be accessible to the user. We support regex and paths relative to the users scope.\n",
"scope": "Scope", "scope": "Scope",
"setDateFormat": "Set exact date format",
"settingsUpdated": "Settings updated!", "settingsUpdated": "Settings updated!",
"shareDeleted": "Share deleted!", "shareDeleted": "Share deleted!",
"shareDuration": "Share Duration", "shareDuration": "Share Duration",

View File

@ -4,7 +4,6 @@
<action icon="close" :label="$t('buttons.close')" @action="close()" /> <action icon="close" :label="$t('buttons.close')" @action="close()" />
<title>{{ req.name }}</title> <title>{{ req.name }}</title>
<template #actions>
<action <action
v-if="user.perm.modify" v-if="user.perm.modify"
id="save-button" id="save-button"
@ -12,7 +11,6 @@
:label="$t('buttons.save')" :label="$t('buttons.save')"
@action="save()" @action="save()"
/> />
</template>
</header-bar> </header-bar>
<breadcrumbs base="/files" noLink /> <breadcrumbs base="/files" noLink />

View File

@ -241,11 +241,11 @@ export default {
}, },
prev() { prev() {
this.hoverNav = false; this.hoverNav = false;
this.$router.push({ path: this.previousLink }); this.$router.replace({ path: this.previousLink });
}, },
next() { next() {
this.hoverNav = false; this.hoverNav = false;
this.$router.push({ path: this.nextLink }); this.$router.replace({ path: this.nextLink });
}, },
key(event) { key(event) {
if (this.show !== null) { if (this.show !== null) {

View File

@ -7,6 +7,18 @@
</div> </div>
<div class="card-content"> <div class="card-content">
<p>
<input type="checkbox" v-model="hideDotfiles" />
{{ $t("settings.hideDotfiles") }}
</p>
<p>
<input type="checkbox" v-model="singleClick" />
{{ $t("settings.singleClick") }}
</p>
<p>
<input type="checkbox" v-model="dateFormat" />
{{ $t("settings.setDateFormat") }}
</p>
<h3>{{ $t("settings.language") }}</h3> <h3>{{ $t("settings.language") }}</h3>
<languages <languages
class="input input--block" class="input input--block"
@ -75,6 +87,7 @@ export default {
passwordConf: "", passwordConf: "",
hideDotfiles: false, hideDotfiles: false,
singleClick: false, singleClick: false,
dateFormat: false,
locale: "", locale: "",
}; };
}, },
@ -99,6 +112,7 @@ export default {
this.locale = this.user.locale; this.locale = this.user.locale;
this.hideDotfiles = this.user.hideDotfiles; this.hideDotfiles = this.user.hideDotfiles;
this.singleClick = this.user.singleClick; this.singleClick = this.user.singleClick;
this.dateFormat = this.user.dateFormat;
}, },
methods: { methods: {
...mapMutations(["updateUser", "setLoading"]), ...mapMutations(["updateUser", "setLoading"]),
@ -127,8 +141,9 @@ export default {
locale: this.locale, locale: this.locale,
hideDotfiles: this.hideDotfiles, hideDotfiles: this.hideDotfiles,
singleClick: this.singleClick, singleClick: this.singleClick,
dateFormat: this.dateFormat,
}; };
await api.update(data, ["locale", "hideDotfiles", "singleClick"]); await api.update(data, ["locale", "hideDotfiles", "singleClick", "dateFormat"]);
this.updateUser(data); this.updateUser(data);
this.$showSuccess(this.$t("settings.settingsUpdated")); this.$showSuccess(this.$t("settings.settingsUpdated"));
} catch (e) { } catch (e) {

View File

@ -28,6 +28,7 @@ type userInfo struct {
Commands []string `json:"commands"` Commands []string `json:"commands"`
LockPassword bool `json:"lockPassword"` LockPassword bool `json:"lockPassword"`
HideDotfiles bool `json:"hideDotfiles"` HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"`
} }
type authToken struct { type authToken struct {
@ -184,6 +185,7 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use
LockPassword: user.LockPassword, LockPassword: user.LockPassword,
Commands: user.Commands, Commands: user.Commands,
HideDotfiles: user.HideDotfiles, HideDotfiles: user.HideDotfiles,
DateFormat: user.DateFormat,
}, },
StandardClaims: jwt.StandardClaims{ StandardClaims: jwt.StandardClaims{
IssuedAt: time.Now().Unix(), IssuedAt: time.Now().Unix(),

View File

@ -29,6 +29,7 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys
data := map[string]interface{}{ data := map[string]interface{}{
"Name": d.settings.Branding.Name, "Name": d.settings.Branding.Name,
"DisableExternal": d.settings.Branding.DisableExternal, "DisableExternal": d.settings.Branding.DisableExternal,
"Color": d.settings.Branding.Color,
"BaseURL": d.server.BaseURL, "BaseURL": d.server.BaseURL,
"Version": version.Version, "Version": version.Version,
"StaticURL": path.Join(d.server.BaseURL, "/static"), "StaticURL": path.Join(d.server.BaseURL, "/static"),

View File

@ -6,4 +6,5 @@ type Branding struct {
DisableExternal bool `json:"disableExternal"` DisableExternal bool `json:"disableExternal"`
Files string `json:"files"` Files string `json:"files"`
Theme string `json:"theme"` Theme string `json:"theme"`
Color string `json:"color"`
} }

View File

@ -18,6 +18,7 @@ type UserDefaults struct {
Perm users.Permissions `json:"perm"` Perm users.Permissions `json:"perm"`
Commands []string `json:"commands"` Commands []string `json:"commands"`
HideDotfiles bool `json:"hideDotfiles"` HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"`
} }
// Apply applies the default options to a user. // Apply applies the default options to a user.
@ -32,4 +33,5 @@ func (d *UserDefaults) Apply(u *users.User) {
u.Sorting = d.Sorting u.Sorting = d.Sorting
u.Commands = d.Commands u.Commands = d.Commands
u.HideDotfiles = d.HideDotfiles u.HideDotfiles = d.HideDotfiles
u.DateFormat = d.DateFormat
} }

View File

@ -37,6 +37,7 @@ type User struct {
Fs afero.Fs `json:"-" yaml:"-"` Fs afero.Fs `json:"-" yaml:"-"`
Rules []rules.Rule `json:"rules"` Rules []rules.Rule `json:"rules"`
HideDotfiles bool `json:"hideDotfiles"` HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"`
} }
// GetRules implements rules.Provider. // GetRules implements rules.Provider.