Skip to content

Commit

Permalink
Persist period selection using local storage
Browse files Browse the repository at this point in the history
  • Loading branch information
petterhj committed Nov 17, 2023
1 parent 2a92074 commit da8e8a8
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 42 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. The format

- The team member listing on the about page has been reintroduced, but is now
only visible to members of the same organization.
- The selected period for OKRs and KPIs is now remembered between visits.

### Changed

Expand Down
8 changes: 2 additions & 6 deletions src/components/period/PeriodSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

<script>
import { endOfDay, startOfDay } from 'date-fns';
import { periodDates } from '@/util';
import { periodObjectFromDates } from '@/util';
import PeriodShortcut from './PeriodShortcut.vue';
export default {
Expand Down Expand Up @@ -111,11 +111,7 @@ export default {
}
}
this.$emit('input', {
startDate: selectedStart,
endDate: selectedEnd,
label: periodDates({ startDate: selectedStart, endDate: selectedEnd }),
});
this.$emit('input', periodObjectFromDates(selectedStart, selectedEnd));
},
},
};
Expand Down
10 changes: 6 additions & 4 deletions src/config/periods.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import {
endOfDay,
endOfQuarter,
getQuarter,
subQuarters,
startOfDay,
startOfQuarter,
endOfQuarter,
subQuarters,
} from 'date-fns';
import i18n from '@/locale/i18n';

export const DEFAULT_OKR_PERIOD = 'quarter';
export const DEFAULT_KPI_PERIOD = 'all';
export const FALLBACK_PERIOD = 'all';

export function getPeriods() {
const currentDate = new Date();
const currentDate = startOfDay(new Date());
const endDate = endOfDay(currentDate);
const currentYear = currentDate.getFullYear();
const currentQuarter = getQuarter(currentDate);
const prevQuarterDate = subQuarters(currentDate, 1);
const sixMonthsBack = new Date();
const sixMonthsBack = startOfDay(new Date());
sixMonthsBack.setMonth(sixMonthsBack.getMonth() - 6);

return {
Expand Down
21 changes: 6 additions & 15 deletions src/router/router-guards/itemMeasurements.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import store from '@/store';
import { DEFAULT_KPI_PERIOD, getPeriods } from '@/config/periods';
import { periodDates } from '@/util';

const { state } = store;

Expand All @@ -13,23 +12,15 @@ export default async function itemMeasurements(to, from, next) {

try {
const periods = getPeriods();
const { resultIndicatorPeriod } = to.query;
const { selectedPeriod } = state.kpis;

if (!selectedPeriod) {
const { resultIndicatorPeriod } = to.query;
const period =
resultIndicatorPeriod && Object.keys(periods).includes(resultIndicatorPeriod)
? periods[resultIndicatorPeriod]
: periods[DEFAULT_KPI_PERIOD];
await store.dispatch('kpis/setSelectedPeriod', period);
} else if (selectedPeriod.key && !periods[selectedPeriod.key]) {
const { startDate, endDate } = selectedPeriod;
await store.dispatch('kpis/setSelectedPeriod', {
startDate,
endDate,
label: periodDates({ startDate, endDate }),
});
if (resultIndicatorPeriod && Object.keys(periods).includes(resultIndicatorPeriod)) {
await store.dispatch('kpis/setSelectedPeriod', periods[resultIndicatorPeriod]);
} else if (!selectedPeriod) {
await store.dispatch('kpis/setSelectedPeriod', periods[DEFAULT_KPI_PERIOD]);
}

return next();
} catch (error) {
console.error(error);
Expand Down
18 changes: 3 additions & 15 deletions src/router/router-guards/itemOKRs.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
import store from '@/store';
import { DEFAULT_OKR_PERIOD, getPeriods } from '@/config/periods';
import { periodDates } from '@/util';

const { state } = store;

export default async function itemMeasurements(to, from, next) {
export default async function itemOKRs(to, from, next) {
try {
const periods = getPeriods();
const { selectedPeriod } = state.okrs;

if (!selectedPeriod) {
const { resultIndicatorPeriod } = to.query;
const period =
resultIndicatorPeriod && Object.keys(periods).includes(resultIndicatorPeriod)
? periods[resultIndicatorPeriod]
: periods[DEFAULT_OKR_PERIOD];
await store.dispatch('okrs/setSelectedPeriod', period);
} else if (selectedPeriod.key && !periods[selectedPeriod.key]) {
const { startDate, endDate } = selectedPeriod;
await store.dispatch('okrs/setSelectedPeriod', {
startDate,
endDate,
label: periodDates({ startDate, endDate }),
});
await store.dispatch('kpis/setSelectedPeriod', periods[DEFAULT_OKR_PERIOD]);
}

next();
} catch (error) {
console.error(error);
Expand Down
7 changes: 6 additions & 1 deletion src/store/modules/kpis.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { useLocalStorage } from '@vueuse/core';
import { firestoreAction } from 'vuexfire';
import { db } from '@/config/firebaseConfig';
import { DEFAULT_KPI_PERIOD, getPeriods } from '@/config/periods';
import { PeriodSerializer } from '@/util/period';
import { isDepartment } from '@/util/getActiveItemType';

export default {
namespaced: true,

state: () => ({
selectedPeriod: null,
selectedPeriod: useLocalStorage('kpi-period', getPeriods()[DEFAULT_KPI_PERIOD], {
serializer: PeriodSerializer,
}),
kpis: [],
subKpis: [],
}),
Expand Down
7 changes: 6 additions & 1 deletion src/store/modules/okrs.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import Vue from 'vue';
import { useLocalStorage } from '@vueuse/core';
import { firestoreAction } from 'vuexfire';
import { db } from '@/config/firebaseConfig';
import { DEFAULT_OKR_PERIOD, getPeriods } from '@/config/periods';
import { PeriodSerializer } from '@/util/period';
import { isDepartment, isOrganization } from '@/util/getActiveItemType';

export default {
namespaced: true,

state: () => ({
selectedPeriod: null,
selectedPeriod: useLocalStorage('okr-period', getPeriods()[DEFAULT_OKR_PERIOD], {
serializer: PeriodSerializer,
}),
activeObjective: null,
activeKeyResult: null,
workbenchObjectives: {},
Expand Down
1 change: 1 addition & 0 deletions src/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { default as findSlugAndRedirect } from './findSlugAndRedirect';
export { default as tableOfContent } from './tableOfContent';
export { default as toastArchiveAndRevert } from './toastUtils';
export { default as validateEmail } from './validateEmail';
export { default as periodObjectFromDates } from './period';

/**
* Return an array of all members of `arr` that are unique with respect to the
Expand Down
57 changes: 57 additions & 0 deletions src/util/period.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { endOfDay, isValid, parseISO, startOfDay } from 'date-fns';
import { FALLBACK_PERIOD, getPeriods } from '@/config/periods';
import { periodDates } from '@/util/format';

function _validatedPeriodDates(period) {
let { startDate, endDate } = period;

startDate = startDate === false || startDate?.getTime ? startDate : new Date(startDate);
endDate = endDate?.getTime ? endDate : new Date(endDate);

if ((startDate !== false && !isValid(startDate)) || !isValid(endDate)) {
return null;
}

return { startDate, endDate };
}

export default function periodObjectFromDates(startDate, endDate) {
const period = _validatedPeriodDates({ startDate, endDate });

if (!period) {
return getPeriods()[FALLBACK_PERIOD];
}

period.startDate = startOfDay(period.startDate);
period.endDate = endOfDay(period.endDate);

return {
startDate,
endDate,
label: periodDates(period),
};
}

export const PeriodSerializer = {
read: (v) => {
const periods = getPeriods();
if (Object.keys(periods).includes(v)) {
return periods[v];
}
try {
const [startDate, endDate] = v.split('|');
return periodObjectFromDates(parseISO(startDate), parseISO(endDate));
} catch {
return periods[FALLBACK_PERIOD];
}
},
write: (v) => {
if (v.key) {
return v.key;
}
if (_validatedPeriodDates(v)) {
return `${v.startDate.toISOString()}|${v.endDate.toISOString()}`;
}
return FALLBACK_PERIOD;
},
};

0 comments on commit da8e8a8

Please sign in to comment.