mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-16 20:22:15 +01:00
respect start of week setting for charts
This commit is contained in:
@@ -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');
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)',
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user