mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-16 12:12:15 +01:00
use prop function createTag instead of event to make sure it is handled by the parent
This commit is contained in:
@@ -304,7 +304,7 @@ test('test that deleting a time entry from the overview works', async ({
|
|||||||
await goToTimeOverview(page);
|
await goToTimeOverview(page);
|
||||||
const timeEntryRows = page.locator('[data-testid="time_entry_row"]');
|
const timeEntryRows = page.locator('[data-testid="time_entry_row"]');
|
||||||
await createEmptyTimeEntry(page);
|
await createEmptyTimeEntry(page);
|
||||||
const timeEntryCount = await timeEntryRows.count();
|
await expect(timeEntryRows).toHaveCount(1);
|
||||||
|
|
||||||
const newTimeEntry = timeEntryRows.first();
|
const newTimeEntry = timeEntryRows.first();
|
||||||
const actionsDropdown = newTimeEntry
|
const actionsDropdown = newTimeEntry
|
||||||
@@ -313,7 +313,7 @@ test('test that deleting a time entry from the overview works', async ({
|
|||||||
await actionsDropdown.click();
|
await actionsDropdown.click();
|
||||||
const deleteButton = page.getByText('Delete');
|
const deleteButton = page.getByText('Delete');
|
||||||
await deleteButton.click();
|
await deleteButton.click();
|
||||||
await expect(timeEntryRows).toHaveCount(timeEntryCount - 1);
|
await expect(timeEntryRows).toHaveCount(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.skip('test that load more works when the end of page is reached', async ({
|
test.skip('test that load more works when the end of page is reached', async ({
|
||||||
|
|||||||
@@ -13,14 +13,15 @@ const tag = ref<CreateTagBody>({
|
|||||||
name: '',
|
name: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const props = defineProps<{
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
emit('createTag', tag.value.name, () => {
|
const newTag = props.createTag(tag.value.name);
|
||||||
|
if (newTag !== undefined) {
|
||||||
show.value = false;
|
show.value = false;
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagNameInput = ref<HTMLInputElement | null>(null);
|
const tagNameInput = ref<HTMLInputElement | null>(null);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import type { Tag } from '@/utils/api';
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const model = defineModel<string[]>({
|
const model = defineModel<string[]>({
|
||||||
@@ -66,14 +67,13 @@ const filteredTags = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function createTag(name: string, callback: (tag: Tag) => void) {
|
async function createAndAddTag(name: string) {
|
||||||
emit('createTag', name, (newTag: Tag) => {
|
const newTag = await props.createTag(name);
|
||||||
if (newTag) {
|
if (newTag) {
|
||||||
addOrRemoveTagFromSelection(newTag.id);
|
addOrRemoveTagFromSelection(newTag.id);
|
||||||
}
|
}
|
||||||
searchValue.value = '';
|
searchValue.value = '';
|
||||||
callback(newTag);
|
return newTag;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addTagIfNoneExists() {
|
async function addTagIfNoneExists() {
|
||||||
@@ -109,7 +109,6 @@ function updateSearchValue(event: Event) {
|
|||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
changed: [];
|
changed: [];
|
||||||
submit: [];
|
submit: [];
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function toggleTag(newValue: string) {
|
function toggleTag(newValue: string) {
|
||||||
@@ -160,7 +159,7 @@ const showCreateTagModal = ref(false);
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TagCreateModal
|
<TagCreateModal
|
||||||
@createTag="createTag"
|
:createTag="createAndAddTag"
|
||||||
v-model:show="showCreateTagModal"></TagCreateModal>
|
v-model:show="showCreateTagModal"></TagCreateModal>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
@submit="emit('submit')"
|
@submit="emit('submit')"
|
||||||
|
|||||||
@@ -9,13 +9,18 @@ import TagTableRow from '@/Components/Common/Tag/TagTableRow.vue';
|
|||||||
import TagCreateModal from '@/Components/Common/Tag/TagCreateModal.vue';
|
import TagCreateModal from '@/Components/Common/Tag/TagCreateModal.vue';
|
||||||
import TagTableHeading from '@/Components/Common/Tag/TagTableHeading.vue';
|
import TagTableHeading from '@/Components/Common/Tag/TagTableHeading.vue';
|
||||||
import { canCreateTags } from '@/utils/permissions';
|
import { canCreateTags } from '@/utils/permissions';
|
||||||
|
import type { Tag } from '@/utils/api';
|
||||||
|
defineProps<{
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
|
}>();
|
||||||
const { tags } = storeToRefs(useTagsStore());
|
const { tags } = storeToRefs(useTagsStore());
|
||||||
const createTag = ref(false);
|
const showCreateTagModal = ref(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TagCreateModal v-model:show="createTag"></TagCreateModal>
|
<TagCreateModal
|
||||||
|
:createTag
|
||||||
|
v-model:show="showCreateTagModal"></TagCreateModal>
|
||||||
<div class="flow-root">
|
<div class="flow-root">
|
||||||
<div class="inline-block min-w-full align-middle">
|
<div class="inline-block min-w-full align-middle">
|
||||||
<div
|
<div
|
||||||
@@ -34,7 +39,7 @@ const createTag = ref(false);
|
|||||||
</p>
|
</p>
|
||||||
<SecondaryButton
|
<SecondaryButton
|
||||||
v-if="canCreateTags()"
|
v-if="canCreateTags()"
|
||||||
@click="createTag = true"
|
@click="showCreateTagModal = true"
|
||||||
:icon="PlusIcon"
|
:icon="PlusIcon"
|
||||||
>Create your First Tag</SecondaryButton
|
>Create your First Tag</SecondaryButton
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ const props = defineProps<{
|
|||||||
projects: Project[];
|
projects: Project[];
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
onStartStopClick: [timeEntry: TimeEntry];
|
onStartStopClick: [timeEntry: TimeEntry];
|
||||||
updateTimeEntries: [timeEntries: TimeEntry[]];
|
updateTimeEntries: [timeEntries: TimeEntry[]];
|
||||||
deleteTimeEntries: [timeEntries: TimeEntry[]];
|
deleteTimeEntries: [timeEntries: TimeEntry[]];
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function updateTimeEntryDescription(description: string) {
|
function updateTimeEntryDescription(description: string) {
|
||||||
@@ -95,7 +95,7 @@ const expanded = ref(false);
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center font-medium lg:space-x-2">
|
<div class="flex items-center font-medium lg:space-x-2">
|
||||||
<TimeEntryRowTagDropdown
|
<TimeEntryRowTagDropdown
|
||||||
@createTag="(...args) => emit('createTag', ...args)"
|
:createTag
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
@changed="updateTimeEntryTags"
|
@changed="updateTimeEntryTags"
|
||||||
:modelValue="timeEntry.tags"></TimeEntryRowTagDropdown>
|
:modelValue="timeEntry.tags"></TimeEntryRowTagDropdown>
|
||||||
@@ -142,7 +142,7 @@ const expanded = ref(false);
|
|||||||
@updateTimeEntry="(arg) => emit('updateTimeEntries', [arg])"
|
@updateTimeEntry="(arg) => emit('updateTimeEntries', [arg])"
|
||||||
@onStartStopClick="emit('onStartStopClick', subEntry)"
|
@onStartStopClick="emit('onStartStopClick', subEntry)"
|
||||||
@deleteTimeEntry="emit('deleteTimeEntries', [subEntry])"
|
@deleteTimeEntry="emit('deleteTimeEntries', [subEntry])"
|
||||||
@createTag="(...args) => emit('createTag', ...args)"
|
:createTag
|
||||||
:key="subEntry.id"
|
:key="subEntry.id"
|
||||||
v-for="subEntry in timeEntry.timeEntries"
|
v-for="subEntry in timeEntry.timeEntries"
|
||||||
:time-entry="subEntry"></TimeEntryRow>
|
:time-entry="subEntry"></TimeEntryRow>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { storeToRefs } from 'pinia';
|
|||||||
import { useTasksStore } from '@/utils/useTasks';
|
import { useTasksStore } from '@/utils/useTasks';
|
||||||
import { useProjectsStore } from '@/utils/useProjects';
|
import { useProjectsStore } from '@/utils/useProjects';
|
||||||
import { useTagsStore } from '@/utils/useTags';
|
import { useTagsStore } from '@/utils/useTags';
|
||||||
import type { Tag } from '@/utils/api';
|
|
||||||
const projectStore = useProjectsStore();
|
const projectStore = useProjectsStore();
|
||||||
const { projects } = storeToRefs(projectStore);
|
const { projects } = storeToRefs(projectStore);
|
||||||
const taskStore = useTasksStore();
|
const taskStore = useTasksStore();
|
||||||
@@ -75,11 +74,8 @@ async function submit() {
|
|||||||
show.value = false;
|
show.value = false;
|
||||||
}
|
}
|
||||||
const { tags } = storeToRefs(useTagsStore());
|
const { tags } = storeToRefs(useTagsStore());
|
||||||
async function createTag(tag: string, callback: (tag: Tag) => void) {
|
async function createTag(tag: string) {
|
||||||
const newTag = await useTagsStore().createTag(tag);
|
return await useTagsStore().createTag(tag);
|
||||||
if (newTag !== undefined) {
|
|
||||||
callback(newTag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -118,7 +114,7 @@ async function createTag(tag: string, callback: (tag: Tag) => void) {
|
|||||||
<div class="flex items-center space-x-2 px-4">
|
<div class="flex items-center space-x-2 px-4">
|
||||||
<TimeTrackerTagDropdown
|
<TimeTrackerTagDropdown
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
@createTag="createTag"
|
:createTag="createTag"
|
||||||
v-model="timeEntry.tags"></TimeTrackerTagDropdown>
|
v-model="timeEntry.tags"></TimeTrackerTagDropdown>
|
||||||
<BillableToggleButton
|
<BillableToggleButton
|
||||||
v-model="timeEntry.billable"></BillableToggleButton>
|
v-model="timeEntry.billable"></BillableToggleButton>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const props = defineProps<{
|
|||||||
projects: Project[];
|
projects: Project[];
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -26,7 +27,6 @@ const emit = defineEmits<{
|
|||||||
updateTimeEntries: [entries: TimeEntry[]];
|
updateTimeEntries: [entries: TimeEntry[]];
|
||||||
deleteTimeEntries: [entries: TimeEntry[]];
|
deleteTimeEntries: [entries: TimeEntry[]];
|
||||||
createTimeEntry: [entry: Omit<CreateTimeEntryBody, 'member_id'>];
|
createTimeEntry: [entry: Omit<CreateTimeEntryBody, 'member_id'>];
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const groupedTimeEntries = computed(() => {
|
const groupedTimeEntries = computed(() => {
|
||||||
@@ -118,14 +118,14 @@ function startTimeEntryFromExisting(entry: TimeEntry) {
|
|||||||
@onStartStopClick="startTimeEntryFromExisting(entry)"
|
@onStartStopClick="startTimeEntryFromExisting(entry)"
|
||||||
@updateTimeEntries="(arg) => emit('updateTimeEntries', arg)"
|
@updateTimeEntries="(arg) => emit('updateTimeEntries', arg)"
|
||||||
@deleteTimeEntries="(arg) => emit('deleteTimeEntries', arg)"
|
@deleteTimeEntries="(arg) => emit('deleteTimeEntries', arg)"
|
||||||
@createTag="(...args) => emit('createTag', ...args)"
|
:createTag
|
||||||
v-if="'timeEntries' in entry && entry.timeEntries.length > 1"
|
v-if="'timeEntries' in entry && entry.timeEntries.length > 1"
|
||||||
:time-entry="entry"></TimeEntryAggregateRow>
|
:time-entry="entry"></TimeEntryAggregateRow>
|
||||||
<TimeEntryRow
|
<TimeEntryRow
|
||||||
:projects="projects"
|
:projects="projects"
|
||||||
:tasks="tasks"
|
:tasks="tasks"
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
@createTag="(...args) => emit('createTag', ...args)"
|
:createTag
|
||||||
@updateTimeEntry="(arg) => emit('updateTimeEntry', arg)"
|
@updateTimeEntry="(arg) => emit('updateTimeEntry', arg)"
|
||||||
@onStartStopClick="startTimeEntryFromExisting(entry)"
|
@onStartStopClick="startTimeEntryFromExisting(entry)"
|
||||||
@deleteTimeEntry="() => emit('deleteTimeEntries', [entry])"
|
@deleteTimeEntry="() => emit('deleteTimeEntries', [entry])"
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ const props = defineProps<{
|
|||||||
projects: Project[];
|
projects: Project[];
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
onStartStopClick: [];
|
onStartStopClick: [];
|
||||||
deleteTimeEntry: [];
|
deleteTimeEntry: [];
|
||||||
updateTimeEntry: [timeEntry: TimeEntry];
|
updateTimeEntry: [timeEntry: TimeEntry];
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function updateTimeEntryDescription(description: string) {
|
function updateTimeEntryDescription(description: string) {
|
||||||
@@ -81,7 +81,7 @@ function updateProjectAndTask(projectId: string, taskId: string) {
|
|||||||
<div class="flex items-center font-medium lg:space-x-2">
|
<div class="flex items-center font-medium lg:space-x-2">
|
||||||
<TimeEntryRowTagDropdown
|
<TimeEntryRowTagDropdown
|
||||||
@changed="updateTimeEntryTags"
|
@changed="updateTimeEntryTags"
|
||||||
@createTag="(...args) => emit('createTag', ...args)"
|
:createTag
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
:modelValue="timeEntry.tags"></TimeEntryRowTagDropdown>
|
:modelValue="timeEntry.tags"></TimeEntryRowTagDropdown>
|
||||||
<BillableToggleButton
|
<BillableToggleButton
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import type { Tag } from '@/utils/api';
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
|
||||||
changed: [model: string[]];
|
changed: [model: string[]];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ const timeEntryTags = computed<Tag[]>(() => {
|
|||||||
<template>
|
<template>
|
||||||
<TagDropdown
|
<TagDropdown
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
@createTag="(...args) => emit('createTag', ...args)"
|
:createTag
|
||||||
@changed="emit('changed', model)"
|
@changed="emit('changed', model)"
|
||||||
v-model="model">
|
v-model="model">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import type { Tag } from '@/utils/api';
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
changed: [];
|
changed: [];
|
||||||
createTag: [name: string, callback: (tag: Tag) => void];
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const model = defineModel({
|
const model = defineModel({
|
||||||
@@ -22,12 +21,13 @@ const iconColorClasses = computed(() => {
|
|||||||
});
|
});
|
||||||
defineProps<{
|
defineProps<{
|
||||||
tags: Tag[];
|
tags: Tag[];
|
||||||
|
createTag: (name: string) => Promise<Tag | undefined>;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TagDropdown
|
<TagDropdown
|
||||||
@createTag="(...args) => $emit('createTag', ...args)"
|
:createTag
|
||||||
@changed="emit('changed')"
|
@changed="emit('changed')"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
:tags="tags">
|
:tags="tags">
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import TimeTrackerRangeSelector from '@/Components/Common/TimeTracker/TimeTracke
|
|||||||
import { useProjectsStore } from '@/utils/useProjects';
|
import { useProjectsStore } from '@/utils/useProjects';
|
||||||
import { useTasksStore } from '@/utils/useTasks';
|
import { useTasksStore } from '@/utils/useTasks';
|
||||||
import { useTagsStore } from '@/utils/useTags';
|
import { useTagsStore } from '@/utils/useTags';
|
||||||
import type { Tag } from '@/utils/api';
|
|
||||||
|
|
||||||
const page = usePage<{
|
const page = usePage<{
|
||||||
auth: {
|
auth: {
|
||||||
@@ -105,11 +104,8 @@ function switchToTimeEntryOrganization() {
|
|||||||
switchOrganization(currentTimeEntry.value.organization_id);
|
switchOrganization(currentTimeEntry.value.organization_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function createTag(tag: string, callback: (tag: Tag) => void) {
|
async function createTag(tag: string) {
|
||||||
const newTag = await useTagsStore().createTag(tag);
|
return await useTagsStore().createTag(tag);
|
||||||
if (newTag !== undefined) {
|
|
||||||
callback(newTag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { tags } = storeToRefs(useTagsStore());
|
const { tags } = storeToRefs(useTagsStore());
|
||||||
@@ -160,7 +156,7 @@ const { tags } = storeToRefs(useTagsStore());
|
|||||||
<div class="flex items-center space-x-2 px-4">
|
<div class="flex items-center space-x-2 px-4">
|
||||||
<TimeTrackerTagDropdown
|
<TimeTrackerTagDropdown
|
||||||
@changed="updateTimeEntry"
|
@changed="updateTimeEntry"
|
||||||
@createTag="createTag"
|
:createTag
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
v-model="
|
v-model="
|
||||||
currentTimeEntry.tags
|
currentTimeEntry.tags
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
import { type GroupingOption, useReportingStore } from '@/utils/useReporting';
|
import { type GroupingOption, useReportingStore } from '@/utils/useReporting';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import TagDropdown from '@/Components/Common/Tag/TagDropdown.vue';
|
import TagDropdown from '@/Components/Common/Tag/TagDropdown.vue';
|
||||||
import type { AggregatedTimeEntriesQueryParams, Tag } from '@/utils/api';
|
import type { AggregatedTimeEntriesQueryParams } from '@/utils/api';
|
||||||
import ReportingFilterBadge from '@/Components/Common/Reporting/ReportingFilterBadge.vue';
|
import ReportingFilterBadge from '@/Components/Common/Reporting/ReportingFilterBadge.vue';
|
||||||
import ProjectMultiselectDropdown from '@/Components/Common/Project/ProjectMultiselectDropdown.vue';
|
import ProjectMultiselectDropdown from '@/Components/Common/Project/ProjectMultiselectDropdown.vue';
|
||||||
import MemberMultiselectDropdown from '@/Components/Common/Member/MemberMultiselectDropdown.vue';
|
import MemberMultiselectDropdown from '@/Components/Common/Member/MemberMultiselectDropdown.vue';
|
||||||
@@ -139,11 +139,8 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { tags } = storeToRefs(useTagsStore());
|
const { tags } = storeToRefs(useTagsStore());
|
||||||
async function createTag(tag: string, callback: (tag: Tag) => void) {
|
async function createTag(tag: string) {
|
||||||
const newTag = await useTagsStore().createTag(tag);
|
return await useTagsStore().createTag(tag);
|
||||||
if (newTag !== undefined) {
|
|
||||||
callback(newTag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -205,7 +202,7 @@ async function createTag(tag: string, callback: (tag: Tag) => void) {
|
|||||||
</ClientMultiselectDropdown>
|
</ClientMultiselectDropdown>
|
||||||
<TagDropdown
|
<TagDropdown
|
||||||
@submit="updateReporting"
|
@submit="updateReporting"
|
||||||
@createTag="createTag"
|
:createTag
|
||||||
v-model="selectedTags"
|
v-model="selectedTags"
|
||||||
:tags="tags">
|
:tags="tags">
|
||||||
<template v-slot:trigger>
|
<template v-slot:trigger>
|
||||||
|
|||||||
@@ -9,13 +9,11 @@ import TagCreateModal from '@/Components/Common/Tag/TagCreateModal.vue';
|
|||||||
import PageTitle from '@/Components/Common/PageTitle.vue';
|
import PageTitle from '@/Components/Common/PageTitle.vue';
|
||||||
import { canCreateTags } from '@/utils/permissions';
|
import { canCreateTags } from '@/utils/permissions';
|
||||||
import { useTagsStore } from '@/utils/useTags';
|
import { useTagsStore } from '@/utils/useTags';
|
||||||
import type { Tag } from '@/utils/api';
|
|
||||||
const showCreateTagModal = ref(false);
|
const showCreateTagModal = ref(false);
|
||||||
async function createTag(tag: string, callback: (tag: Tag) => void) {
|
|
||||||
const newTag = await useTagsStore().createTag(tag);
|
async function createTag(tag: string) {
|
||||||
if (newTag !== undefined) {
|
return await useTagsStore().createTag(tag);
|
||||||
callback(newTag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -24,18 +22,18 @@ async function createTag(tag: string, callback: (tag: Tag) => void) {
|
|||||||
<MainContainer
|
<MainContainer
|
||||||
class="py-5 border-b border-default-background-separator flex justify-between items-center">
|
class="py-5 border-b border-default-background-separator flex justify-between items-center">
|
||||||
<div class="flex items-center space-x-6">
|
<div class="flex items-center space-x-6">
|
||||||
<PageTitle :icon="TagIcon" title="Tags"> </PageTitle>
|
<PageTitle :icon="TagIcon" title="Tags"></PageTitle>
|
||||||
</div>
|
</div>
|
||||||
<SecondaryButton
|
<SecondaryButton
|
||||||
v-if="canCreateTags()"
|
v-if="canCreateTags()"
|
||||||
:icon="PlusIcon"
|
:icon="PlusIcon"
|
||||||
@click="showCreateTagModal = true"
|
@click="showCreateTagModal = true"
|
||||||
>Create Tag</SecondaryButton
|
>Create Tag
|
||||||
>
|
</SecondaryButton>
|
||||||
<TagCreateModal
|
<TagCreateModal
|
||||||
@createTag="createTag"
|
:createTag="createTag"
|
||||||
v-model:show="showCreateTagModal"></TagCreateModal>
|
v-model:show="showCreateTagModal"></TagCreateModal>
|
||||||
</MainContainer>
|
</MainContainer>
|
||||||
<TagTable></TagTable>
|
<TagTable :createTag="createTag"></TagTable>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { onMounted, ref, watch } from 'vue';
|
|||||||
import MainContainer from '@/Pages/MainContainer.vue';
|
import MainContainer from '@/Pages/MainContainer.vue';
|
||||||
import { useTimeEntriesStore } from '@/utils/useTimeEntries';
|
import { useTimeEntriesStore } from '@/utils/useTimeEntries';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import type { CreateTimeEntryBody, Tag, TimeEntry } from '@/utils/api';
|
import type { CreateTimeEntryBody, TimeEntry } from '@/utils/api';
|
||||||
import { useElementVisibility } from '@vueuse/core';
|
import { useElementVisibility } from '@vueuse/core';
|
||||||
import { ClockIcon } from '@heroicons/vue/20/solid';
|
import { ClockIcon } from '@heroicons/vue/20/solid';
|
||||||
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
||||||
@@ -77,11 +77,8 @@ const { projects } = storeToRefs(projectStore);
|
|||||||
const taskStore = useTasksStore();
|
const taskStore = useTasksStore();
|
||||||
const { tasks } = storeToRefs(taskStore);
|
const { tasks } = storeToRefs(taskStore);
|
||||||
|
|
||||||
async function createTag(name: string, callback: (tag: Tag) => void) {
|
async function createTag(name: string) {
|
||||||
const newTag = await useTagsStore().createTag(name);
|
return await useTagsStore().createTag(name);
|
||||||
if (newTag !== undefined) {
|
|
||||||
callback(newTag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -111,7 +108,7 @@ async function createTag(name: string, callback: (tag: Tag) => void) {
|
|||||||
@updateTimeEntries="updateTimeEntries"
|
@updateTimeEntries="updateTimeEntries"
|
||||||
@deleteTimeEntries="deleteTimeEntries"
|
@deleteTimeEntries="deleteTimeEntries"
|
||||||
@createTimeEntry="startTimeEntry"
|
@createTimeEntry="startTimeEntry"
|
||||||
@createTag="createTag"
|
:createTag
|
||||||
:projects="projects"
|
:projects="projects"
|
||||||
:tasks="tasks"
|
:tasks="tasks"
|
||||||
:timeEntries="timeEntries"
|
:timeEntries="timeEntries"
|
||||||
|
|||||||
Reference in New Issue
Block a user