restrict group and subgroup so they are always different

This commit is contained in:
Gregor Vostrak
2024-05-31 03:02:05 +02:00
parent 4943baa236
commit c9311780ed
3 changed files with 78 additions and 48 deletions

View File

@@ -1,50 +1,19 @@
<script setup lang="ts">
import { FolderIcon } from '@heroicons/vue/16/solid';
import SelectDropdown from '@/Components/Common/SelectDropdown.vue';
import Badge from '@/Components/Common/Badge.vue';
import { computed } from 'vue';
import {
CheckCircleIcon,
UserCircleIcon,
UserGroupIcon,
} from '@heroicons/vue/20/solid';
import BillableIcon from '@/Components/Common/Icons/BillableIcon.vue';
const groupByOptions = [
{
label: 'Members',
value: 'user',
icon: UserGroupIcon,
},
{
label: 'Projects',
value: 'project',
icon: FolderIcon,
},
{
label: 'Tasks',
value: 'task',
icon: CheckCircleIcon,
},
{
label: 'Clients',
value: 'client',
icon: UserCircleIcon,
},
{
label: 'Billable',
value: 'billable',
icon: BillableIcon,
},
];
import { type Component, computed } from 'vue';
const model = defineModel<string | null>({ default: null });
const props = defineProps<{
groupByOptions: { value: string; label: string; icon: Component }[];
}>();
const icon = computed(() => {
return groupByOptions.find((option) => option.value === model.value)?.icon;
return props.groupByOptions.find((option) => option.value === model.value)
?.icon;
});
const title = computed(() => {
return groupByOptions.find((option) => option.value === model.value)?.label;
return props.groupByOptions.find((option) => option.value === model.value)
?.label;
});
</script>

View File

@@ -14,7 +14,7 @@ import ReportingChart from '@/Components/Common/Reporting/ReportingChart.vue';
import BillableIcon from '@/Components/Common/Icons/BillableIcon.vue';
import { onMounted, ref } from 'vue';
import { formatHumanReadableDuration, getDayJsInstance } from '@/utils/time';
import { useReportingStore } from '@/utils/useReporting';
import { type GroupingOption, useReportingStore } from '@/utils/useReporting';
import { storeToRefs } from 'pinia';
import TagDropdown from '@/Components/Common/Tag/TagDropdown.vue';
import type { AggregatedTimeEntriesQueryParams } from '@/utils/api';
@@ -42,11 +42,16 @@ const selectedClients = ref<string[]>([]);
const billable = ref<'true' | 'false' | null>(null);
type GroupingOption = 'project' | 'task' | 'user' | 'billable' | 'client';
const group = ref<GroupingOption>('project');
const subGroup = ref<GroupingOption>('task');
const reportingStore = useReportingStore();
const { aggregatedGraphTimeEntries, aggregatedTableTimeEntries } =
storeToRefs(reportingStore);
const { groupByOptions } = reportingStore;
function getFilterAttributes() {
let params: AggregatedTimeEntriesQueryParams = {
start: getDayJsInstance()(startDate.value).utc().format(),
@@ -90,6 +95,14 @@ function updateGraphReporting() {
function updateTableReporting() {
const params = getFilterAttributes();
if (group.value === subGroup.value) {
const fallbackOption = groupByOptions.find(
(el) => el.value !== group.value
);
if (fallbackOption?.value) {
subGroup.value = fallbackOption.value;
}
}
if (getCurrentRole() === 'employee') {
params.member_id = getCurrentMembershipId();
}
@@ -103,11 +116,6 @@ function updateReporting() {
updateTableReporting();
}
const reportingStore = useReportingStore();
const { aggregatedGraphTimeEntries, aggregatedTableTimeEntries } =
storeToRefs(reportingStore);
function getOptimalGroupingOption(diff: number): 'day' | 'week' | 'month' {
if (diff <= 31) {
return 'day';
@@ -248,10 +256,16 @@ onMounted(() => {
class="text-sm flex text-white items-center space-x-3 font-medium px-6 border-b border-card-background-separator pb-3">
<span>Group by</span>
<ReportingGroupBySelect
:group-by-options="groupByOptions"
@changed="updateTableReporting"
v-model="group"></ReportingGroupBySelect>
<span>and</span>
<ReportingGroupBySelect
:group-by-options="
groupByOptions.filter(
(el) => el.value !== group
)
"
@changed="updateTableReporting"
v-model="subGroup"></ReportingGroupBySelect>
</div>

View File

@@ -1,6 +1,6 @@
import { defineStore, storeToRefs } from 'pinia';
import { api } from '../../../openapi.json.client';
import { computed, ref } from 'vue';
import { type Component, computed, ref } from 'vue';
import type {
AggregatedTimeEntries,
AggregatedTimeEntriesQueryParams,
@@ -12,6 +12,20 @@ import { useProjectsStore } from '@/utils/useProjects';
import { useMembersStore } from '@/utils/useMembers';
import { useTasksStore } from '@/utils/useTasks';
import { useClientsStore } from '@/utils/useClients';
import {
CheckCircleIcon,
UserCircleIcon,
UserGroupIcon,
} from '@heroicons/vue/20/solid';
import { FolderIcon } from '@heroicons/vue/16/solid';
import BillableIcon from '@/Components/Common/Icons/BillableIcon.vue';
export type GroupingOption =
| 'project'
| 'task'
| 'user'
| 'billable'
| 'client';
export const useReportingStore = defineStore('reporting', () => {
const reportingGraphResponse = ref<ReportingResponse | null>(null);
@@ -112,11 +126,44 @@ export const useReportingStore = defineStore('reporting', () => {
return key;
}
const groupByOptions: {
label: string;
value: GroupingOption;
icon: Component;
}[] = [
{
label: 'Members',
value: 'user',
icon: UserGroupIcon,
},
{
label: 'Projects',
value: 'project',
icon: FolderIcon,
},
{
label: 'Tasks',
value: 'task',
icon: CheckCircleIcon,
},
{
label: 'Clients',
value: 'client',
icon: UserCircleIcon,
},
{
label: 'Billable',
value: 'billable',
icon: BillableIcon,
},
];
return {
aggregatedGraphTimeEntries,
fetchGraphReporting,
fetchTableReporting,
aggregatedTableTimeEntries,
getNameForReportingRowEntry,
groupByOptions,
};
});