Skip to content

Commit 6255a2f

Browse files
authored
Add setting to use browser native date-time picker (#204)
* style: autoformat Running `make format` on a clean copy of this repository made these changes * feat(datetimeinputstyle): add `DatetimeInputStyle` setting This boilerplate commit adds a `DatetimeInputStyle` field to user settings on both the client and server. It can represent either "Fancy" (this is the input element currently present in Traggo) or "Standard" (unimplemented, the <input type="datetime-local"> HTML element). A later commit will actually do something with this commit. * feat(datetimeinputstyle): add `<input type=datetime-local>` time picker option * fix(datetimeinputstyle): fix date formatting * refactor(datetimeinputstyle): rename `Standard` to `Native` * refactor(datetimeinputstyle): change snackbar message * refactor(datetimeinputstyle): replace `DatetimeInput` with `DateTimeInput`
1 parent ab3995a commit 6255a2f

File tree

10 files changed

+112
-24
lines changed

10 files changed

+112
-24
lines changed

model/setting.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import "time"
44

55
// UserSetting a setting for a user.
66
type UserSetting struct {
7-
UserID int `gorm:"primary_key;unique_index"`
8-
Theme string
9-
DateLocale string
10-
FirstDayOfTheWeek string
7+
UserID int `gorm:"primary_key;unique_index"`
8+
Theme string
9+
DateLocale string
10+
FirstDayOfTheWeek string
11+
DateTimeInputStyle string
1112
}
1213

1314
// Settings constants
@@ -22,6 +23,9 @@ const (
2223
DateLocaleAmerican24h = "American24h"
2324
DateLocaleBritish = "British"
2425
DateLocaleAustralian = "Australian"
26+
27+
DateTimeInputFancy = "Fancy"
28+
DateTimeInputNative = "Native"
2529
)
2630

2731
var daysOfWeek = map[string]time.Weekday{

schema.graphql

+6
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,14 @@ input InputUserSettings {
6868
theme: Theme!
6969
dateLocale: DateLocale!
7070
firstDayOfTheWeek: WeekDay!
71+
dateTimeInputStyle: DateTimeInputStyle!
7172
}
7273

7374
type UserSettings {
7475
theme: Theme!
7576
dateLocale: DateLocale!
7677
firstDayOfTheWeek: WeekDay!
78+
dateTimeInputStyle: DateTimeInputStyle!
7779
}
7880

7981
enum WeekDay {
@@ -88,6 +90,10 @@ enum DateLocale {
8890
American, American24h, German, Australian, British
8991
}
9092

93+
enum DateTimeInputStyle {
94+
Fancy, Native
95+
}
96+
9197
input InputReplaceOptions {
9298
override: OverrideMode!
9399
}

setting/get.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ func Get(ctx context.Context, db *gorm.DB) (model.UserSetting, error) {
1414
internal := model.UserSetting{}
1515
user := auth.GetUser(ctx)
1616
defaultSettings := model.UserSetting{
17-
Theme: model.ThemeGruvboxDark,
18-
DateLocale: model.DateLocaleAmerican,
19-
FirstDayOfTheWeek: time.Monday.String(),
17+
Theme: model.ThemeGruvboxDark,
18+
DateLocale: model.DateLocaleAmerican,
19+
FirstDayOfTheWeek: time.Monday.String(),
20+
DateTimeInputStyle: model.DateTimeInputFancy,
2021
}
2122

2223
if user == nil {

setting/usersettings.go

+31-7
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ import (
1212
// SetUserSettings sets the user settings.
1313
func (r *ResolverForSettings) SetUserSettings(ctx context.Context, settings gqlmodel.InputUserSettings) (*gqlmodel.UserSettings, error) {
1414
internal := model.UserSetting{
15-
Theme: toInternalTheme(settings.Theme),
16-
FirstDayOfTheWeek: toInternalWeekday(settings.FirstDayOfTheWeek).String(),
17-
UserID: auth.GetUser(ctx).ID,
18-
DateLocale: toInternalDateLocale(settings.DateLocale),
15+
Theme: toInternalTheme(settings.Theme),
16+
FirstDayOfTheWeek: toInternalWeekday(settings.FirstDayOfTheWeek).String(),
17+
UserID: auth.GetUser(ctx).ID,
18+
DateLocale: toInternalDateLocale(settings.DateLocale),
19+
DateTimeInputStyle: toInternalDateTimeInputStyle(settings.DateTimeInputStyle),
1920
}
2021

2122
save := r.DB.Save(internal)
@@ -31,9 +32,10 @@ func (r *ResolverForSettings) UserSettings(ctx context.Context) (*gqlmodel.UserS
3132

3233
func toExternal(internal model.UserSetting) *gqlmodel.UserSettings {
3334
return &gqlmodel.UserSettings{
34-
Theme: toExternalTheme(internal.Theme),
35-
DateLocale: toExternalDateLocale(internal.DateLocale),
36-
FirstDayOfTheWeek: toExternalWeekday(internal.FirstDayOfTheWeekTimeWeekday()),
35+
Theme: toExternalTheme(internal.Theme),
36+
DateLocale: toExternalDateLocale(internal.DateLocale),
37+
FirstDayOfTheWeek: toExternalWeekday(internal.FirstDayOfTheWeekTimeWeekday()),
38+
DateTimeInputStyle: toExternalDateTimeInputStyle(internal.DateTimeInputStyle),
3739
}
3840
}
3941

@@ -113,3 +115,25 @@ func toInternalWeekday(weekday gqlmodel.WeekDay) time.Weekday {
113115
panic("unknown weekday")
114116
}
115117
}
118+
119+
func toExternalDateTimeInputStyle(style string) gqlmodel.DateTimeInputStyle {
120+
switch style {
121+
case model.DateTimeInputFancy:
122+
return model.DateTimeInputFancy
123+
case model.DateTimeInputNative:
124+
return model.DateTimeInputNative
125+
default:
126+
panic("unknown datetime input style")
127+
}
128+
}
129+
130+
func toInternalDateTimeInputStyle(style gqlmodel.DateTimeInputStyle) string {
131+
switch style {
132+
case gqlmodel.DateTimeInputStyleFancy:
133+
return model.DateTimeInputFancy
134+
case gqlmodel.DateTimeInputStyleNative:
135+
return model.DateTimeInputNative
136+
default:
137+
panic("unknown datetime input style")
138+
}
139+
}

setting/usersettings_test.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,20 @@ func TestSettingsResolver(t *testing.T) {
2828
require.Equal(t, gqlmodel.ThemeGruvboxDark, settings.Theme)
2929

3030
_, err = resolver.SetUserSettings(fake.User(1), gqlmodel.InputUserSettings{
31-
Theme: gqlmodel.ThemeGruvboxLight,
32-
DateLocale: gqlmodel.DateLocaleGerman,
33-
FirstDayOfTheWeek: gqlmodel.WeekDayWednesday,
31+
Theme: gqlmodel.ThemeGruvboxLight,
32+
DateLocale: gqlmodel.DateLocaleGerman,
33+
FirstDayOfTheWeek: gqlmodel.WeekDayWednesday,
34+
DateTimeInputStyle: gqlmodel.DateTimeInputStyleFancy,
3435
})
3536
require.NoError(t, err)
3637

3738
settings, err = resolver.UserSettings(fake.User(1))
3839
require.NoError(t, err)
3940
require.Equal(t, &gqlmodel.UserSettings{
40-
Theme: gqlmodel.ThemeGruvboxLight,
41-
DateLocale: gqlmodel.DateLocaleGerman,
42-
FirstDayOfTheWeek: gqlmodel.WeekDayWednesday,
41+
Theme: gqlmodel.ThemeGruvboxLight,
42+
DateLocale: gqlmodel.DateLocaleGerman,
43+
FirstDayOfTheWeek: gqlmodel.WeekDayWednesday,
44+
DateTimeInputStyle: gqlmodel.DateTimeInputStyleFancy,
4345
}, settings)
4446
}
4547

tag/suggest_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ func TestGQL_SuggestTag_noMatchingTags(t *testing.T) {
4242
tags, err := resolver.SuggestTag(fake.User(1), "fire")
4343

4444
require.Nil(t, err)
45-
expected := []*gqlmodel.TagDefinition{}
45+
expected := []*gqlmodel.TagDefinition{}
4646
require.Equal(t, expected, tags)
4747
}

ui/serve.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func Register(r *mux.Router) {
2727
r.Handle("/favicon.ico", serveFile("favicon.ico", "image/x-icon"))
2828
for _, size := range []string{"16x16", "32x32", "192x192", "256x256"} {
2929
fileName := fmt.Sprintf("favicon-%s.png", size)
30-
r.Handle("/" + fileName, serveFile(fileName, "image/png"))
30+
r.Handle("/"+fileName, serveFile(fileName, "image/png"))
3131
}
3232
}
3333

ui/src/common/DateTimeSelector.tsx

+20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as React from 'react';
22
import {KeyboardDateTimePicker} from '@material-ui/pickers';
33
import * as moment from 'moment';
44
import {uglyConvertToLocalTime} from '../timespan/timeutils';
5+
import {useSettings} from '../gql/settings';
6+
import {DateTimeInputStyle} from '../gql/__generated__/globalTypes';
57

68
interface DateTimeSelectorProps {
79
selectedDate: moment.Moment;
@@ -13,6 +15,24 @@ interface DateTimeSelectorProps {
1315

1416
export const DateTimeSelector: React.FC<DateTimeSelectorProps> = React.memo(
1517
({selectedDate, onSelectDate, showDate, label, popoverOpen = () => {}}) => {
18+
const {done, dateTimeInputStyle} = useSettings();
19+
20+
if (!done) {
21+
return <span>...</span>;
22+
}
23+
24+
if (dateTimeInputStyle === DateTimeInputStyle.Native) {
25+
return (
26+
<input
27+
type="datetime-local"
28+
value={selectedDate.format(selectedDate.format('YYYY-MM-DDTHH:mm'))}
29+
onChange={(e) => {
30+
onSelectDate(moment.default(e.target.value));
31+
}}
32+
/>
33+
);
34+
}
35+
1636
const [open, setOpen] = React.useState(false);
1737
const localeData = moment.localeData();
1838
const time = localeData.longDateFormat('LT').replace('A', 'a');

ui/src/gql/settings.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {gql} from 'apollo-boost';
22
import {useQuery} from '@apollo/react-hooks';
33
import {Settings as SettingsQueryResponse} from './__generated__/Settings';
4-
import {DateLocale, Theme, WeekDay} from './__generated__/globalTypes';
4+
import {DateLocale, Theme, WeekDay, DateTimeInputStyle} from './__generated__/globalTypes';
55
import {stripTypename} from '../utils/strip';
66

77
export const Settings = gql`
@@ -10,6 +10,7 @@ export const Settings = gql`
1010
theme
1111
dateLocale
1212
firstDayOfTheWeek
13+
dateTimeInputStyle
1314
}
1415
}
1516
`;
@@ -18,6 +19,7 @@ export const SetSettings = gql`
1819
mutation SetSettings($settings: InputUserSettings!) {
1920
setUserSettings(settings: $settings) {
2021
theme
22+
dateTimeInputStyle
2123
}
2224
}
2325
`;
@@ -26,6 +28,7 @@ const defaultSettings = {
2628
theme: Theme.GruvboxDark,
2729
dateLocale: DateLocale.American,
2830
firstDayOfTheWeek: WeekDay.Monday,
31+
dateTimeInputStyle: DateTimeInputStyle.Fancy,
2932
} as const;
3033

3134
export const useSettings = (): {done: boolean} & Omit<SettingsQueryResponse['userSettings'], '__typename'> => {

ui/src/setting/SettingsPage.tsx

+29-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {SetSettings, SetSettingsVariables} from '../gql/__generated__/SetSetting
77
import FormControl from '@material-ui/core/FormControl';
88
import InputLabel from '@material-ui/core/InputLabel';
99
import Select from '@material-ui/core/NativeSelect/NativeSelect';
10-
import {DateLocale, Theme, WeekDay} from '../gql/__generated__/globalTypes';
10+
import {DateLocale, Theme, WeekDay, DateTimeInputStyle} from '../gql/__generated__/globalTypes';
1111
import {useSnackbar} from 'notistack';
1212
import {handleError} from '../utils/errors';
1313

@@ -120,6 +120,34 @@ export const SettingsPage: React.FC = () => {
120120
))}
121121
</Select>
122122
</FormControl>
123+
<FormControl margin={'normal'} fullWidth>
124+
<InputLabel>Datetime input style</InputLabel>
125+
<Select
126+
fullWidth
127+
value={settings.dateTimeInputStyle}
128+
onChange={(e) => {
129+
setSettings({
130+
variables: {
131+
settings: {
132+
...settings,
133+
dateTimeInputStyle: e.target.value as DateTimeInputStyle,
134+
},
135+
},
136+
})
137+
.then(() =>
138+
enqueueSnackbar('datetime input style changed', {
139+
variant: 'success',
140+
})
141+
)
142+
.catch(handleError('set datetime input style', enqueueSnackbar));
143+
}}>
144+
{[DateTimeInputStyle.Fancy, DateTimeInputStyle.Native].map((type) => (
145+
<option key={type} value={type}>
146+
{type}
147+
</option>
148+
))}
149+
</Select>
150+
</FormControl>
123151
</Paper>
124152
);
125153
};

0 commit comments

Comments
 (0)