respect start of week setting for charts

This commit is contained in:
Gregor Vostrak
2024-04-29 16:47:46 +02:00
parent 492be92592
commit fb3d326c28
6 changed files with 75 additions and 9 deletions

View File

@@ -35,6 +35,7 @@ test('test that starting and stopping a timer with a description works', async (
page, page,
}) => { }) => {
await goToDashboard(page); await goToDashboard(page);
// TODO: Fix flakyness by disabling description input field until timer is loaded
await page await page
.getByTestId('time_entry_description') .getByTestId('time_entry_description')
.fill('New Time Entry Description'); .fill('New Time Entry Description');

View File

@@ -5,9 +5,7 @@ import { computed } from 'vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { formatHumanReadableDuration } from '@/utils/time'; import { formatHumanReadableDuration } from '@/utils/time';
import TimeTrackerStartStop from '@/Components/Common/TimeTrackerStartStop.vue'; import TimeTrackerStartStop from '@/Components/Common/TimeTrackerStartStop.vue';
import { getCurrentOrganizationId } from "@/utils/useUser"; import { getCurrentOrganizationId } from '@/utils/useUser';
import { switchOrganization } from "@/utils/useOrganization";
import SecondaryButton from "@/Components/SecondaryButton.vue";
const store = useCurrentTimeEntryStore(); const store = useCurrentTimeEntryStore();
const { currentTimeEntry, now, isActive } = storeToRefs(store); const { currentTimeEntry, now, isActive } = storeToRefs(store);
const { onToggleButtonPress } = store; const { onToggleButtonPress } = store;

View File

@@ -13,7 +13,12 @@ import {
} from 'echarts/components'; } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { formatDate, formatHumanReadableDuration } from '@/utils/time'; import {
firstDayIndex,
formatDate,
formatHumanReadableDuration,
getDayJsInstance,
} from '@/utils/time';
const props = defineProps<{ const props = defineProps<{
dailyHoursTracked: { duration: number; date: string }[]; dailyHoursTracked: { duration: number; date: string }[];
@@ -55,12 +60,18 @@ const option = ref({
left: 40, left: 40,
right: 10, right: 10,
cellSize: [40, 40], cellSize: [40, 40],
dayLabel: {
firstDay: firstDayIndex.value,
},
splitLine: { splitLine: {
show: false, show: false,
}, },
range: [ range: [
dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD'),
dayjs().subtract(50, 'day').startOf('week').format('YYYY-MM-DD'), getDayJsInstance()()
.subtract(50, 'day')
.startOf('week')
.format('YYYY-MM-DD'),
], ],
itemStyle: { itemStyle: {
borderWidth: 8, borderWidth: 8,

View File

@@ -9,7 +9,7 @@ import {
TooltipComponent, TooltipComponent,
} from 'echarts/components'; } from 'echarts/components';
import VChart, { THEME_KEY } from 'vue-echarts'; import VChart, { THEME_KEY } from 'vue-echarts';
import { provide, ref } from 'vue'; import { computed, provide, ref } from 'vue';
import StatCard from '@/Components/Common/StatCard.vue'; import StatCard from '@/Components/Common/StatCard.vue';
import { ClockIcon } from '@heroicons/vue/20/solid'; import { ClockIcon } from '@heroicons/vue/20/solid';
import CardTitle from '@/Components/Common/CardTitle.vue'; import CardTitle from '@/Components/Common/CardTitle.vue';
@@ -17,6 +17,7 @@ import LinearGradient from 'zrender/lib/graphic/LinearGradient';
import ProjectsChartCard from '@/Components/Dashboard/ProjectsChartCard.vue'; import ProjectsChartCard from '@/Components/Dashboard/ProjectsChartCard.vue';
import { formatHumanReadableDuration } from '@/utils/time'; import { formatHumanReadableDuration } from '@/utils/time';
import { formatCents } from '@/utils/money'; import { formatCents } from '@/utils/money';
import { getWeekStart } from '@/utils/useUser';
use([ use([
CanvasRenderer, CanvasRenderer,
@@ -78,6 +79,33 @@ const seriesData = props.weeklyHistory.map((el) => {
}, },
}; };
}); });
const weekdays = computed(() => {
const daysOrder = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
const dayMapping: Record<string, string> = {
monday: 'Mon',
tuesday: 'Tue',
wednesday: 'Wed',
thursday: 'Thu',
friday: 'Fri',
saturday: 'Sat',
sunday: 'Sun',
};
if (dayMapping[getWeekStart()]) {
const customOrder = [];
const startIndex = daysOrder.indexOf(dayMapping[getWeekStart()]);
for (let i = startIndex; i < 7 + startIndex; i++) {
customOrder.push(daysOrder[i % daysOrder.length]);
}
return customOrder;
} else {
return daysOrder;
}
});
const option = ref({ const option = ref({
grid: { grid: {
top: 0, top: 0,
@@ -88,7 +116,7 @@ const option = ref({
backgroundColor: 'transparent', backgroundColor: 'transparent',
xAxis: { xAxis: {
type: 'category', type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], data: weekdays.value,
markLine: { markLine: {
lineStyle: { lineStyle: {
color: 'rgba(125,156,188,0.1)', color: 'rgba(125,156,188,0.1)',

View File

@@ -5,7 +5,9 @@ import isToday from 'dayjs/plugin/isToday';
import isYesterday from 'dayjs/plugin/isYesterday'; import isYesterday from 'dayjs/plugin/isYesterday';
import utc from 'dayjs/plugin/utc'; import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone'; import timezone from 'dayjs/plugin/timezone';
import { getUserTimezone } from '@/utils/useUser'; import { getUserTimezone, getWeekStart } from '@/utils/useUser';
import updateLocale from 'dayjs/plugin/updateLocale';
import { computed } from 'vue';
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
dayjs.extend(isToday); dayjs.extend(isToday);
@@ -13,11 +15,28 @@ dayjs.extend(isYesterday);
dayjs.extend(duration); dayjs.extend(duration);
dayjs.extend(utc); dayjs.extend(utc);
dayjs.extend(timezone); dayjs.extend(timezone);
dayjs.extend(updateLocale);
export function getDayJsInstance() { export function getDayJsInstance() {
dayjs.updateLocale('en', {
weekStart: firstDayIndex.value,
});
return dayjs; return dayjs;
} }
export const firstDayIndex = computed(() => {
const apiDayOrder = [
'sunday',
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
];
return apiDayOrder.indexOf(getWeekStart());
});
export function formatHumanReadableDuration(duration: number): string { export function formatHumanReadableDuration(duration: number): string {
const dayJsDuration = dayjs.duration(duration, 's'); const dayJsDuration = dayjs.duration(duration, 's');
const hours = dayJsDuration.hours() + dayJsDuration.days() * 24; const hours = dayJsDuration.hours() + dayJsDuration.days() * 24;

View File

@@ -10,6 +10,10 @@ function getCurrentUserId() {
return page.props.auth.user.id; return page.props.auth.user.id;
} }
function getWeekStart() {
return page.props.auth.user.week_start;
}
function getCurrentOrganizationId() { function getCurrentOrganizationId() {
return page.props.auth.user.current_team_id; return page.props.auth.user.current_team_id;
} }
@@ -18,4 +22,9 @@ function getUserTimezone() {
return page.props.auth.user.timezone; return page.props.auth.user.timezone;
} }
export { getCurrentOrganizationId, getCurrentUserId, getUserTimezone }; export {
getCurrentOrganizationId,
getCurrentUserId,
getUserTimezone,
getWeekStart,
};