Edits to usability

This commit is contained in:
2024-05-09 12:57:21 -04:00
parent ea785887a1
commit 77619b0741
3 changed files with 139 additions and 91 deletions

View File

@@ -1,72 +1,87 @@
<template> <template>
<q-card> <q-expansion-item
<q-card-section horizontal> expand-icon-toggle
<div> draggable="true"
@dragstart="onDragStart($event, template)"
>
<template v-slot:header>
<q-item-section>
<q-input <q-input
label="Template name" label="Template name"
filled :borderless="!edit"
dense dense
v-model="template.name" v-model="template.name"
v-if="editable" v-if="edit"
/> /><q-item-label v-if="!edit" class="cursor-pointer">{{
<q-list dense> template.name
<q-item v-for="item in template.timeTuples" :key="item[0]"> }}</q-item-label></q-item-section
<q-input >
dense </template>
:filled="editable" <q-card flat>
v-model="item[0]" <q-card-section horizontal>
type="time" <q-card-section class="q-pt-xs">
label="Start" <q-list dense>
:readonly="!editable" <q-item v-for="item in template.timeTuples" :key="item[0]">
/> <q-input
<q-input class="q-mx-sm"
:filled="editable" dense
dense v-model="item[0]"
v-model="item[1]" type="time"
type="time" label="Start"
label="End" :borderless="!edit"
:readonly="!editable" :readonly="!edit"
/> </q-item></q-list />
><q-btn <q-input
v-if="editable" class="q-mx-sm"
dense
v-model="item[1]"
type="time"
label="End"
:borderless="!edit"
:readonly="!edit"
/> </q-item></q-list
></q-card-section>
<q-btn
v-if="edit"
dense dense
color="primary" color="primary"
size="sm" size="sm"
label="Add interval" label="Add interval"
@click="template.timeTuples.push(['00:00', '00:00'])" @click="template.timeTuples.push(['00:00', '00:00'])"
/> />
</div> <q-card-actions align="right" vertical>
<q-card-actions align="right" vertical> <q-btn
<q-btn v-if="!edit"
v-if="!editable" color="primary"
color="primary" icon="edit"
icon="edit" label="Edit"
label="Edit" @click="toggleEdit"
@click="editable = !editable" />
/> <q-btn
<q-btn v-if="edit"
v-if="editable" color="primary"
color="primary" icon="save"
icon="save" label="Save"
label="Save" @click="saveTemplate($event, template)"
@click="saveTemplate($event, template)" />
/> <q-btn
<q-btn v-if="edit"
v-if="editable" color="secondary"
color="secondary" icon="cancel"
icon="cancel" label="Cancel"
label="Cancel" @click="revert"
@click="revert" />
/> <q-btn
<q-btn color="negative"
color="negative" icon="delete"
icon="delete" label="Delete"
label="Delete" v-if="template.$id !== ''"
@click="deleteTemplate($event, template)" @click="deleteTemplate($event, template)"
/> />
</q-card-actions> </q-card-actions>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-expansion-item>
<q-dialog v-model="alert"> <q-dialog v-model="alert">
<q-card> <q-card>
<q-card-section> <q-card-section>
@@ -89,17 +104,31 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { timeTuplesOverlapped, useScheduleStore } from 'src/stores/schedule'; import {
copyTimeBlockTemplate,
timeTuplesOverlapped,
useScheduleStore,
} from 'src/stores/schedule';
import { TimeBlockTemplate } from 'src/stores/schedule.types'; import { TimeBlockTemplate } from 'src/stores/schedule.types';
import { ref } from 'vue'; import { ref } from 'vue';
const editable = ref(false);
const alert = ref(false); const alert = ref(false);
const overlapped = ref(); const overlapped = ref();
const scheduleStore = useScheduleStore(); const scheduleStore = useScheduleStore();
const template = defineModel<TimeBlockTemplate>({ required: true }); const props = defineProps<{ edit?: boolean; modelValue: TimeBlockTemplate }>();
const edit = ref(props.edit);
const template = ref(copyTimeBlockTemplate(props.modelValue));
const emit = defineEmits<{ (e: 'cancel'): void }>();
const revert = () => { const revert = () => {
editable.value = false; template.value = copyTimeBlockTemplate(props.modelValue);
console.log(template.value, props.modelValue);
edit.value = false;
emit('cancel');
};
const toggleEdit = () => {
edit.value = !edit.value;
}; };
const deleteTemplate = ( const deleteTemplate = (
@@ -108,22 +137,29 @@ const deleteTemplate = (
) => { ) => {
if (template?.$id) scheduleStore.deleteTimeBlockTemplate(template.$id); if (template?.$id) scheduleStore.deleteTimeBlockTemplate(template.$id);
}; };
// const edit = () => {
// // TODO: Make it so that editing the template does not affect the store. Need to be able to "cancel" editing, and revert to original data function onDragStart(e: DragEvent, template: TimeBlockTemplate) {
// }; if (e.dataTransfer) {
console.log('Drag start: ', e);
e.dataTransfer.dropEffect = 'copy';
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('ID', template.$id || '');
}
}
const saveTemplate = (evt: Event, template: TimeBlockTemplate | undefined) => { const saveTemplate = (evt: Event, template: TimeBlockTemplate | undefined) => {
if (!template) return false; if (!template) return false;
overlapped.value = timeTuplesOverlapped(template.timeTuples); overlapped.value = timeTuplesOverlapped(template.timeTuples);
if (overlapped.value.length > 0) { if (overlapped.value.length > 0) {
alert.value = true; alert.value = true;
} else { } else {
if (template.$id) { if (template.$id && template.$id !== 'unsaved') {
console.log(template.$id); console.log(template.$id);
scheduleStore.updateTimeBlockTemplate(template, template.$id); scheduleStore.updateTimeBlockTemplate(template, template.$id);
} else { } else {
scheduleStore.createTimeBlockTemplate(template); scheduleStore.createTimeBlockTemplate(template);
template.$id = '';
} }
editable.value = false; edit.value = false;
} }
}; };
</script> </script>

View File

@@ -19,6 +19,7 @@
:drag-leave-func="onDragLeave" :drag-leave-func="onDragLeave"
:drop-func="onDrop" :drop-func="onDrop"
:day-min-height="50" :day-min-height="50"
:cell-width="140"
:day-height="0" :day-height="0"
> >
<template #day="{ scope }"> <template #day="{ scope }">
@@ -59,24 +60,21 @@
</q-item-section> </q-item-section>
</q-item> </q-item>
<q-card-actions align="right"> <q-card-actions align="right">
<q-btn label="Add Template" color="primary" @click="addTemplate" /> <q-btn label="Add Template" color="primary" @click="createTemplate" />
</q-card-actions> </q-card-actions>
<q-item v-if="newTemplate.$id === 'unsaved'"
><TimeBlockTemplateComponent
:model-value="newTemplate"
:edit="true"
@cancel="cancelNewTemplate"
/></q-item>
<q-separator spaced /> <q-separator spaced />
<q-expansion-item <TimeBlockTemplateComponent
v-for="template in timeblockTemplates" v-for="template in timeblockTemplates"
:key="template.$id" :key="template.$id"
dense :model-value="template"
dense-toggle />
expand-separator </q-list>
:label="template.name"
style="font-size: 0.8em"
draggable="true"
@dragstart="onDragStart($event, template)"
>
<TimeBlockTemplateComponent
:model-value="template"
/> </q-expansion-item
></q-list>
</div> </div>
</div> </div>
</template> </template>
@@ -103,6 +101,12 @@ const { getTimeBlocks, fetchTimeBlocks, fetchTimeBlockTemplates } =
const { boats } = storeToRefs(useBoatStore()); const { boats } = storeToRefs(useBoatStore());
const { timeblockTemplates } = storeToRefs(useScheduleStore()); const { timeblockTemplates } = storeToRefs(useScheduleStore());
const calendar = ref(); const calendar = ref();
const blankTemplate: TimeBlockTemplate = {
$id: '',
name: 'NewTemplate',
timeTuples: [['00:00', '00:00']],
};
const newTemplate = ref<TimeBlockTemplate>({ ...blankTemplate });
onMounted(async () => { onMounted(async () => {
await fetchBoats(); await fetchBoats();
@@ -110,8 +114,12 @@ onMounted(async () => {
await fetchTimeBlockTemplates(); await fetchTimeBlockTemplates();
}); });
function addTemplate() { function cancelNewTemplate() {
timeblockTemplates.value.push({ name: 'New Template', timeTuples: [] }); newTemplate.value = { ...blankTemplate };
console.log(newTemplate.value);
}
function createTemplate() {
newTemplate.value.$id = 'unsaved';
} }
function createTimeBlock(boat: Boat, templateId: string, date: string) { function createTimeBlock(boat: Boat, templateId: string, date: string) {
const timeBlock = timeblockTemplates.value.find((t) => t.$id === templateId); const timeBlock = timeblockTemplates.value.find((t) => t.$id === templateId);
@@ -120,14 +128,6 @@ function createTimeBlock(boat: Boat, templateId: string, date: string) {
); );
} }
function onDragStart(e: DragEvent, template: TimeBlockTemplate) {
if (e.dataTransfer) {
console.log('Drag start: ', e);
e.dataTransfer.dropEffect = 'copy';
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('ID', template.$id || '');
}
}
function onDragEnter(e: DragEvent, type: string) { function onDragEnter(e: DragEvent, type: string) {
console.log('onDragEnter', e, type); console.log('onDragEnter', e, type);
if (type === 'day' || type === 'head-day') { if (type === 'day' || type === 'head-day') {

View File

@@ -57,6 +57,18 @@ export function blocksOverlapped(blocks: TimeBlock[] | Interval[]): Interval[] {
); );
} }
export function copyTimeTuples(tuples: TimeTuple[]): TimeTuple[] {
return tuples.map((t) => Object.assign([], t));
}
export function copyTimeBlockTemplate(
template: TimeBlockTemplate
): TimeBlockTemplate {
return {
...template,
timeTuples: copyTimeTuples(template.timeTuples),
};
}
export function buildTimeBlock( export function buildTimeBlock(
resource: Boat, resource: Boat,
time: TimeTuple, time: TimeTuple,