diff --git a/auth/hook.go b/auth/hook.go index c659e57b..213784b7 100644 --- a/auth/hook.go +++ b/auth/hook.go @@ -157,16 +157,17 @@ func (a *HookAuth) SaveUser() (*users.User, error) { // create user with the provided credentials d := &users.User{ - Username: a.Cred.Username, - Password: pass, - Scope: a.Settings.Defaults.Scope, - Locale: a.Settings.Defaults.Locale, - ViewMode: a.Settings.Defaults.ViewMode, - SingleClick: a.Settings.Defaults.SingleClick, - Sorting: a.Settings.Defaults.Sorting, - Perm: a.Settings.Defaults.Perm, - Commands: a.Settings.Defaults.Commands, - HideDotfiles: a.Settings.Defaults.HideDotfiles, + Username: a.Cred.Username, + Password: pass, + Scope: a.Settings.Defaults.Scope, + Locale: a.Settings.Defaults.Locale, + DateTimeFormat: a.Settings.Defaults.DateTimeFormat, + ViewMode: a.Settings.Defaults.ViewMode, + SingleClick: a.Settings.Defaults.SingleClick, + Sorting: a.Settings.Defaults.Sorting, + Perm: a.Settings.Defaults.Perm, + Commands: a.Settings.Defaults.Commands, + HideDotfiles: a.Settings.Defaults.HideDotfiles, } u = a.GetUser(d) @@ -218,13 +219,14 @@ func (a *HookAuth) GetUser(d *users.User) *users.User { Download: isAdmin || a.Fields.GetBoolean("user.perm.download", d.Perm.Download), } user := users.User{ - ID: d.ID, - Username: d.Username, - Password: d.Password, - Scope: a.Fields.GetString("user.scope", d.Scope), - Locale: a.Fields.GetString("user.locale", d.Locale), - ViewMode: users.ViewMode(a.Fields.GetString("user.viewMode", string(d.ViewMode))), - SingleClick: a.Fields.GetBoolean("user.singleClick", d.SingleClick), + ID: d.ID, + Username: d.Username, + Password: d.Password, + Scope: a.Fields.GetString("user.scope", d.Scope), + Locale: a.Fields.GetString("user.locale", d.Locale), + ViewMode: users.ViewMode(a.Fields.GetString("user.viewMode", string(d.ViewMode))), + SingleClick: a.Fields.GetBoolean("user.singleClick", d.SingleClick), + DateTimeFormat: a.Fields.GetString("user.dateTimeFormat", d.DateTimeFormat), Sorting: files.Sorting{ Asc: a.Fields.GetBoolean("user.sorting.asc", d.Sorting.Asc), By: a.Fields.GetString("user.sorting.by", d.Sorting.By), diff --git a/cmd/config.go b/cmd/config.go index de55c28e..e31d3904 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -166,6 +166,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintln(w, "\nDefaults:") fmt.Fprintf(w, "\tScope:\t%s\n", set.Defaults.Scope) fmt.Fprintf(w, "\tLocale:\t%s\n", set.Defaults.Locale) + fmt.Fprintf(w, "\tDateTimeFormat:\t%s\n", set.Defaults.DateTimeFormat) fmt.Fprintf(w, "\tView mode:\t%s\n", set.Defaults.ViewMode) fmt.Fprintf(w, "\tSingle Click:\t%t\n", set.Defaults.SingleClick) fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " ")) diff --git a/cmd/root.go b/cmd/root.go index 27c0a8db..075b728f 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -323,9 +323,10 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { CreateUserDir: false, UserHomeBasePath: settings.DefaultUsersHomeBasePath, Defaults: settings.UserDefaults{ - Scope: ".", - Locale: "en", - SingleClick: false, + Scope: ".", + Locale: "en", + DateTimeFormat: "MM/DD/YYYY h:mm A", + SingleClick: false, Perm: users.Permissions{ Admin: false, Execute: true, diff --git a/cmd/users.go b/cmd/users.go index d3f97da6..1d04d017 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -27,10 +27,10 @@ var usersCmd = &cobra.Command{ func printUsers(usrs []*users.User) { w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - fmt.Fprintln(w, "ID\tUsername\tScope\tLocale\tV. Mode\tS.Click\tAdmin\tExecute\tCreate\tRename\tModify\tDelete\tShare\tDownload\tPwd Lock") + fmt.Fprintln(w, "ID\tUsername\tScope\tLocale\tV. Mode\tS.Click\tAdmin\tExecute\tCreate\tRename\tModify\tDelete\tShare\tDownload\tPwd Lock\tDateTimeFormat") for _, u := range usrs { - fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t\n", + fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%s\t\n", u.ID, u.Username, u.Scope, @@ -46,6 +46,7 @@ func printUsers(usrs []*users.User) { u.Perm.Share, u.Perm.Download, u.LockPassword, + u.DateTimeFormat, ) } @@ -75,6 +76,7 @@ func addUserFlags(flags *pflag.FlagSet) { flags.StringSlice("commands", nil, "a list of the commands a user can execute") flags.String("scope", ".", "scope for users") flags.String("locale", "en", "locale for users") + flags.String("dateTimeFormat", "MM/DD/YYYY h:mm A", "date time format for users") flags.String("viewMode", string(users.ListViewMode), "view mode for users") flags.Bool("singleClick", false, "use single clicks only") } diff --git a/cmd/users_update.go b/cmd/users_update.go index 822bb6dc..ef81438a 100644 --- a/cmd/users_update.go +++ b/cmd/users_update.go @@ -41,17 +41,19 @@ options you want to change.`, checkErr(err) defaults := settings.UserDefaults{ - Scope: user.Scope, - Locale: user.Locale, - ViewMode: user.ViewMode, - SingleClick: user.SingleClick, - Perm: user.Perm, - Sorting: user.Sorting, - Commands: user.Commands, + Scope: user.Scope, + Locale: user.Locale, + DateTimeFormat: user.DateTimeFormat, + ViewMode: user.ViewMode, + SingleClick: user.SingleClick, + Perm: user.Perm, + Sorting: user.Sorting, + Commands: user.Commands, } getUserDefaults(flags, &defaults, false) user.Scope = defaults.Scope user.Locale = defaults.Locale + user.DateTimeFormat = defaults.DateTimeFormat user.ViewMode = defaults.ViewMode user.SingleClick = defaults.SingleClick user.Perm = defaults.Perm diff --git a/frontend/src/components/files/ListingItem.vue b/frontend/src/components/files/ListingItem.vue index 01937c8a..577e905b 100644 --- a/frontend/src/components/files/ListingItem.vue +++ b/frontend/src/components/files/ListingItem.vue @@ -110,7 +110,8 @@ const humanSize = () => { const humanTime = () => { if (!props.readOnly && authStore.user?.dateFormat) { - return dayjs(props.modified).format("L LT"); + const format = authStore.user?.dateTimeFormat || "L LT"; + return dayjs(props.modified).format(format); } return dayjs(props.modified).fromNow(); }; diff --git a/frontend/src/components/settings/DateTimeFormats.vue b/frontend/src/components/settings/DateTimeFormats.vue new file mode 100644 index 00000000..c77265d8 --- /dev/null +++ b/frontend/src/components/settings/DateTimeFormats.vue @@ -0,0 +1,48 @@ + + + diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 00d43b9d..d704f6a8 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -191,6 +191,7 @@ "insertRegex": "Insert regex expression", "instanceName": "Instance name", "language": "Language", + "dateTimeFormat": "Date and time format", "lockPassword": "Prevent the user from changing the password", "newPassword": "Your new password", "newPasswordConfirm": "Confirm your new password", diff --git a/frontend/src/types/settings.d.ts b/frontend/src/types/settings.d.ts index a2c19f76..06416dad 100644 --- a/frontend/src/types/settings.d.ts +++ b/frontend/src/types/settings.d.ts @@ -13,6 +13,7 @@ interface ISettings { interface SettingsDefaults { scope: string; locale: string; + dateTimeFormat: string; viewMode: ViewModeType; singleClick: boolean; sorting: Sorting; diff --git a/frontend/src/types/user.d.ts b/frontend/src/types/user.d.ts index b81806fc..eca9d767 100644 --- a/frontend/src/types/user.d.ts +++ b/frontend/src/types/user.d.ts @@ -4,6 +4,7 @@ interface IUser { password: string; scope: string; locale: string; + dateTimeFormat: string; perm: Permissions; commands: string[]; rules: IRule[]; @@ -23,6 +24,7 @@ interface IUserForm { password?: string; scope?: string; locale?: string; + dateTimeFormat?: string; perm?: Permissions; commands?: string[]; rules?: IRule[]; diff --git a/frontend/src/views/settings/Profile.vue b/frontend/src/views/settings/Profile.vue index c677092f..ce19e174 100644 --- a/frontend/src/views/settings/Profile.vue +++ b/frontend/src/views/settings/Profile.vue @@ -24,6 +24,11 @@ class="input input--block" v-model:locale="locale" > +

{{ t("settings.dateTimeFormat") }}

+
@@ -82,6 +87,7 @@ import { useAuthStore } from "@/stores/auth"; import { useLayoutStore } from "@/stores/layout"; import { users as api } from "@/api"; import Languages from "@/components/settings/Languages.vue"; +import DateTimeFormat from "@/components/settings/DateTimeFormats.vue"; import { computed, inject, onMounted, ref } from "vue"; import { useI18n } from "vue-i18n"; @@ -97,6 +103,7 @@ const passwordConf = ref(""); const hideDotfiles = ref(false); const singleClick = ref(false); const dateFormat = ref(false); +const dateTimeFormatValue = ref(""); const locale = ref(""); const passwordClass = computed(() => { @@ -117,6 +124,7 @@ onMounted(() => { layoutStore.loading = true; if (authStore.user === null) return false; locale.value = authStore.user.locale; + dateTimeFormatValue.value = authStore.user.dateTimeFormat; hideDotfiles.value = authStore.user.hideDotfiles; singleClick.value = authStore.user.singleClick; dateFormat.value = authStore.user.dateFormat; @@ -160,6 +168,7 @@ const updateSettings = async (event: Event) => { ...authStore.user, id: authStore.user.id, locale: locale.value, + dateTimeFormat: dateTimeFormatValue.value, hideDotfiles: hideDotfiles.value, singleClick: singleClick.value, dateFormat: dateFormat.value, @@ -170,6 +179,7 @@ const updateSettings = async (event: Event) => { "hideDotfiles", "singleClick", "dateFormat", + "dateTimeFormat", ]); authStore.updateUser(data); $showSuccess(t("settings.settingsUpdated")); diff --git a/http/auth.go b/http/auth.go index 23dc7b77..107bf857 100644 --- a/http/auth.go +++ b/http/auth.go @@ -21,15 +21,16 @@ const ( ) type userInfo struct { - ID uint `json:"id"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - LockPassword bool `json:"lockPassword"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + ID uint `json:"id"` + Locale string `json:"locale"` + DateTimeFormat string `json:"dateTimeFormat"` + ViewMode users.ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Perm users.Permissions `json:"perm"` + Commands []string `json:"commands"` + LockPassword bool `json:"lockPassword"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` } type authToken struct { @@ -186,15 +187,16 @@ func renewHandler(tokenExpireTime time.Duration) handleFunc { func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User, tokenExpirationTime time.Duration) (int, error) { claims := &authToken{ User: userInfo{ - ID: user.ID, - Locale: user.Locale, - ViewMode: user.ViewMode, - SingleClick: user.SingleClick, - Perm: user.Perm, - LockPassword: user.LockPassword, - Commands: user.Commands, - HideDotfiles: user.HideDotfiles, - DateFormat: user.DateFormat, + ID: user.ID, + Locale: user.Locale, + DateTimeFormat: user.DateTimeFormat, + ViewMode: user.ViewMode, + SingleClick: user.SingleClick, + Perm: user.Perm, + LockPassword: user.LockPassword, + Commands: user.Commands, + HideDotfiles: user.HideDotfiles, + DateFormat: user.DateFormat, }, RegisteredClaims: jwt.RegisteredClaims{ IssuedAt: jwt.NewNumericDate(time.Now()), diff --git a/settings/defaults.go b/settings/defaults.go index d60e36dc..0216f871 100644 --- a/settings/defaults.go +++ b/settings/defaults.go @@ -8,21 +8,23 @@ import ( // UserDefaults is a type that holds the default values // for some fields on User. type UserDefaults struct { - Scope string `json:"scope"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Sorting files.Sorting `json:"sorting"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + Scope string `json:"scope"` + Locale string `json:"locale"` + DateTimeFormat string `json:"dateTimeFormat"` + ViewMode users.ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Sorting files.Sorting `json:"sorting"` + Perm users.Permissions `json:"perm"` + Commands []string `json:"commands"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` } // Apply applies the default options to a user. func (d *UserDefaults) Apply(u *users.User) { u.Scope = d.Scope u.Locale = d.Locale + u.DateTimeFormat = d.DateTimeFormat u.ViewMode = d.ViewMode u.SingleClick = d.SingleClick u.Perm = d.Perm diff --git a/users/users.go b/users/users.go index ec613856..1dcafe57 100644 --- a/users/users.go +++ b/users/users.go @@ -21,21 +21,22 @@ const ( // User describes a user. type User struct { - ID uint `storm:"id,increment" json:"id"` - Username string `storm:"unique" json:"username"` - Password string `json:"password"` - Scope string `json:"scope"` - Locale string `json:"locale"` - LockPassword bool `json:"lockPassword"` - ViewMode ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Perm Permissions `json:"perm"` - Commands []string `json:"commands"` - Sorting files.Sorting `json:"sorting"` - Fs afero.Fs `json:"-" yaml:"-"` - Rules []rules.Rule `json:"rules"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + ID uint `storm:"id,increment" json:"id"` + Username string `storm:"unique" json:"username"` + Password string `json:"password"` + Scope string `json:"scope"` + Locale string `json:"locale"` + DateTimeFormat string `json:"dateTimeFormat"` + LockPassword bool `json:"lockPassword"` + ViewMode ViewMode `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Perm Permissions `json:"perm"` + Commands []string `json:"commands"` + Sorting files.Sorting `json:"sorting"` + Fs afero.Fs `json:"-" yaml:"-"` + Rules []rules.Rule `json:"rules"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` } // GetRules implements rules.Provider.