add TimeEntryCreateModal and MoreOptionsDropdown to ui package

This commit is contained in:
Gregor Vostrak
2024-11-12 18:54:54 +01:00
parent df0f3b2680
commit d880717749
6 changed files with 38 additions and 26 deletions

View File

@@ -24,7 +24,7 @@ import { useProjectsStore } from '@/utils/useProjects';
import TimeEntryGroupedTable from '@/packages/ui/src/TimeEntry/TimeEntryGroupedTable.vue'; import TimeEntryGroupedTable from '@/packages/ui/src/TimeEntry/TimeEntryGroupedTable.vue';
import { useTagsStore } from '@/utils/useTags'; import { useTagsStore } from '@/utils/useTags';
import { useClientsStore } from '@/utils/useClients'; import { useClientsStore } from '@/utils/useClients';
import TimeEntryCreateModal from '@/Components/Common/TimeEntry/TimeEntryCreateModal.vue'; import TimeEntryCreateModal from '@/packages/ui/src/TimeEntry/TimeEntryCreateModal.vue';
import { getOrganizationCurrencyString } from '@/utils/money'; import { getOrganizationCurrencyString } from '@/utils/money';
import TimeEntryMassActionRow from '@/packages/ui/src/TimeEntry/TimeEntryMassActionRow.vue'; import TimeEntryMassActionRow from '@/packages/ui/src/TimeEntry/TimeEntryMassActionRow.vue';
import type { UpdateMultipleTimeEntriesChangeset } from '@/packages/api/src'; import type { UpdateMultipleTimeEntriesChangeset } from '@/packages/api/src';
@@ -123,7 +123,12 @@ function deleteSelected() {
:enableEstimatedTime="isAllowedToPerformPremiumAction()" :enableEstimatedTime="isAllowedToPerformPremiumAction()"
:createProject="createProject" :createProject="createProject"
:createClient="createClient" :createClient="createClient"
:createTag="createTag"
:createTimeEntry="createTimeEntry" :createTimeEntry="createTimeEntry"
:projects
:tasks
:tags
:clients
v-model:show="showManualTimeEntryModal"></TimeEntryCreateModal> v-model:show="showManualTimeEntryModal"></TimeEntryCreateModal>
<AppLayout title="Dashboard" data-testid="time_view"> <AppLayout title="Dashboard" data-testid="time_view">
<MainContainer <MainContainer

View File

@@ -1,6 +1,6 @@
{ {
"name": "@solidtime/ui", "name": "@solidtime/ui",
"version": "0.0.9", "version": "0.0.10",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@solidtime/ui", "name": "@solidtime/ui",
"version": "0.0.9", "version": "0.0.10",
"description": "Package containing the solidtime ui components", "description": "Package containing the solidtime ui components",
"main": "./dist/solidtime-ui-lib.umd.cjs", "main": "./dist/solidtime-ui-lib.umd.cjs",
"module": "./dist/solidtime-ui-lib.js", "module": "./dist/solidtime-ui-lib.js",

View File

@@ -90,7 +90,12 @@ const emit = defineEmits(['changed']);
useFocus(timeInput, { initialValue: props.focus }); useFocus(timeInput, { initialValue: props.focus });
const getStartOptions = computed(() => { type TimeOption = {
timestamp: string;
name: string;
};
const getStartOptions = computed<TimeOption[]>(() => {
// options for the entire day in 15 minute intervals // options for the entire day in 15 minute intervals
const options = []; const options = [];
for (let hour = 0; hour < 24; hour++) { for (let hour = 0; hour < 24; hour++) {
@@ -141,8 +146,8 @@ const closestValue = computed({
:class="twMerge('mine-w-0 w-24', size === 'large' && 'w-28')" :class="twMerge('mine-w-0 w-24', size === 'large' && 'w-28')"
v-model="closestValue" v-model="closestValue"
v-model:open="open" v-model:open="open"
:get-key-from-item="(item) => item.timestamp" :get-key-from-item="(item: TimeOption) => item.timestamp"
:get-name-for-item="(item) => item.name" :get-name-for-item="(item: TimeOption) => item.name"
:items="getStartOptions"> :items="getStartOptions">
<template #trigger> <template #trigger>
<TextInput <TextInput

View File

@@ -5,17 +5,12 @@ import DialogModal from '@/packages/ui/src/DialogModal.vue';
import { computed, nextTick, ref, watch } from 'vue'; import { computed, nextTick, ref, watch } from 'vue';
import PrimaryButton from '@/packages/ui/src/Buttons/PrimaryButton.vue'; import PrimaryButton from '@/packages/ui/src/Buttons/PrimaryButton.vue';
import TimeTrackerProjectTaskDropdown from '@/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue'; import TimeTrackerProjectTaskDropdown from '@/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue';
import { getCurrentUserId } from '@/utils/useUser';
import InputLabel from '@/packages/ui/src/Input/InputLabel.vue'; import InputLabel from '@/packages/ui/src/Input/InputLabel.vue';
import { TagIcon } from '@heroicons/vue/20/solid'; import { TagIcon } from '@heroicons/vue/20/solid';
import { import {
getDayJsInstance, getDayJsInstance,
getLocalizedDayJs, getLocalizedDayJs,
} from '@/packages/ui/src/utils/time'; } from '@/packages/ui/src/utils/time';
import { storeToRefs } from 'pinia';
import { useTasksStore } from '@/utils/useTasks';
import { useProjectsStore } from '@/utils/useProjects';
import { useTagsStore } from '@/utils/useTags';
import type { import type {
CreateClientBody, CreateClientBody,
CreateProjectBody, CreateProjectBody,
@@ -23,24 +18,18 @@ import type {
Client, Client,
CreateTimeEntryBody, CreateTimeEntryBody,
} from '@/packages/api/src'; } from '@/packages/api/src';
import { useClientsStore } from '@/utils/useClients';
import TimePicker from '@/packages/ui/src/Input/TimePicker.vue'; import TimePicker from '@/packages/ui/src/Input/TimePicker.vue';
import { getOrganizationCurrencyString } from '@/utils/money'; import { getOrganizationCurrencyString } from '@/utils/money';
import { canCreateProjects } from '@/utils/permissions'; import { canCreateProjects } from '@/utils/permissions';
import TagDropdown from '@/packages/ui/src/Tag/TagDropdown.vue'; import TagDropdown from '@/packages/ui/src/Tag/TagDropdown.vue';
import { Badge } from '@/packages/ui/src'; import { Badge } from '@/packages/ui/src';
import BillableIcon from '@/packages/ui/src/Icons/BillableIcon.vue'; import BillableIcon from '@/packages/ui/src/Icons/BillableIcon.vue';
import SelectDropdown from '../../../packages/ui/src/Input/SelectDropdown.vue'; import SelectDropdown from '@/packages/ui/src/Input/SelectDropdown.vue';
import DatePicker from '@/packages/ui/src/Input/DatePicker.vue'; import DatePicker from '@/packages/ui/src/Input/DatePicker.vue';
import DurationHumanInput from '@/packages/ui/src/Input/DurationHumanInput.vue'; import DurationHumanInput from '@/packages/ui/src/Input/DurationHumanInput.vue';
import { InformationCircleIcon } from '@heroicons/vue/20/solid'; import { InformationCircleIcon } from '@heroicons/vue/20/solid';
const projectStore = useProjectsStore(); import type { Tag, Task } from '@/packages/api';
const { projects } = storeToRefs(projectStore);
const taskStore = useTasksStore();
const { tasks } = storeToRefs(taskStore);
const clientStore = useClientsStore();
const { clients } = storeToRefs(clientStore);
const show = defineModel('show', { default: false }); const show = defineModel('show', { default: false });
const saving = ref(false); const saving = ref(false);
@@ -52,6 +41,11 @@ const props = defineProps<{
) => Promise<void>; ) => Promise<void>;
createClient: (client: CreateClientBody) => Promise<Client | undefined>; createClient: (client: CreateClientBody) => Promise<Client | undefined>;
createProject: (project: CreateProjectBody) => Promise<Project | undefined>; createProject: (project: CreateProjectBody) => Promise<Project | undefined>;
createTag: (name: string) => Promise<Tag | undefined>;
tags: Tag[];
projects: Project[];
tasks: Task[];
clients: Client[];
}>(); }>();
const description = ref<HTMLInputElement | null>(null); const description = ref<HTMLInputElement | null>(null);
@@ -72,7 +66,6 @@ const timeEntryDefaultValues = {
billable: false, billable: false,
start: getDayJsInstance().utc().subtract(1, 'h').format(), start: getDayJsInstance().utc().subtract(1, 'h').format(),
end: getDayJsInstance().utc().format(), end: getDayJsInstance().utc().format(),
user_id: getCurrentUserId(),
}; };
const timeEntry = ref({ ...timeEntryDefaultValues }); const timeEntry = ref({ ...timeEntryDefaultValues });
@@ -101,10 +94,6 @@ async function submit() {
localEnd.value = getLocalizedDayJs(timeEntryDefaultValues.end).format(); localEnd.value = getLocalizedDayJs(timeEntryDefaultValues.end).format();
show.value = false; show.value = false;
} }
const { tags } = storeToRefs(useTagsStore());
async function createTag(tag: string) {
return await useTagsStore().createTag(tag);
}
const billableProxy = computed({ const billableProxy = computed({
get: () => (timeEntry.value.billable ? 'true' : 'false'), get: () => (timeEntry.value.billable ? 'true' : 'false'),
@@ -112,6 +101,11 @@ const billableProxy = computed({
timeEntry.value.billable = value === 'true'; timeEntry.value.billable = value === 'true';
}, },
}); });
type BillableOption = {
label: string;
value: string;
};
</script> </script>
<template> <template>
@@ -183,8 +177,12 @@ const billableProxy = computed({
<div class="flex-col"> <div class="flex-col">
<SelectDropdown <SelectDropdown
v-model="billableProxy" v-model="billableProxy"
:get-key-from-item="(item) => item.value" :get-key-from-item="
:get-name-for-item="(item) => item.label" (item: BillableOption) => item.value
"
:get-name-for-item="
(item: BillableOption) => item.label
"
:items="[ :items="[
{ {
label: 'Billable', label: 'Billable',

View File

@@ -26,6 +26,8 @@ import Badge from './Badge.vue';
import Checkbox from './Input/Checkbox.vue'; import Checkbox from './Input/Checkbox.vue';
import TimeEntryGroupedTable from './TimeEntry/TimeEntryGroupedTable.vue'; import TimeEntryGroupedTable from './TimeEntry/TimeEntryGroupedTable.vue';
import TimeEntryMassActionRow from './TimeEntry/TimeEntryMassActionRow.vue'; import TimeEntryMassActionRow from './TimeEntry/TimeEntryMassActionRow.vue';
import TimeEntryCreateModal from './TimeEntry/TimeEntryCreateModal.vue';
import MoreOptionsDropdown from './MoreOptionsDropdown.vue';
export { export {
money, money,
@@ -48,4 +50,6 @@ export {
Checkbox, Checkbox,
TimeEntryGroupedTable, TimeEntryGroupedTable,
TimeEntryMassActionRow, TimeEntryMassActionRow,
MoreOptionsDropdown,
TimeEntryCreateModal,
}; };