mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 12:42:15 +01:00
add TimeEntryCreateModal and MoreOptionsDropdown to ui package
This commit is contained in:
@@ -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
|
||||||
|
|||||||
2
resources/js/packages/ui/package-lock.json
generated
2
resources/js/packages/ui/package-lock.json
generated
@@ -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": {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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',
|
||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user