Compare commits
8 Commits
c92f737612
...
ea785887a1
| Author | SHA1 | Date | |
|---|---|---|---|
|
ea785887a1
|
|||
|
b860e1d977
|
|||
|
274d0193f7
|
|||
|
033993b1b8
|
|||
|
2872fb867e
|
|||
|
8e73650462
|
|||
|
634cff507c
|
|||
|
fa4d83e42d
|
4
appwrite.json
Normal file
4
appwrite.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"projectId": "65ede55a213134f2b688",
|
||||||
|
"projectName": ""
|
||||||
|
}
|
||||||
12
package.json
12
package.json
@@ -14,14 +14,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@quasar/extras": "^1.16.11",
|
"@quasar/extras": "^1.16.11",
|
||||||
"appwrite": "^13.0.0",
|
"appwrite": "^14.0.1",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "3",
|
"vue": "3",
|
||||||
"vue-router": "4"
|
"vue-router": "4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@quasar/app-vite": "^1.7.4",
|
"@quasar/app-vite": "^1.9.1",
|
||||||
"@quasar/quasar-app-extension-qcalendar": "^4.0.0-beta.15",
|
"@quasar/quasar-app-extension-qcalendar": "^4.0.0-beta.16",
|
||||||
"@types/node": "^12.20.21",
|
"@types/node": "^12.20.21",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||||
"@typescript-eslint/parser": "^5.10.0",
|
"@typescript-eslint/parser": "^5.10.0",
|
||||||
@@ -31,8 +31,10 @@
|
|||||||
"eslint-config-prettier": "^8.1.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-plugin-vue": "^9.0.0",
|
"eslint-plugin-vue": "^9.0.0",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"quasar": "^2.15.2",
|
"quasar": "^2.16.0",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "~5.3.0",
|
||||||
|
"vite-plugin-checker": "^0.6.4",
|
||||||
|
"vue-tsc": "^1.8.22",
|
||||||
"workbox-build": "^7.0.0",
|
"workbox-build": "^7.0.0",
|
||||||
"workbox-cacheable-response": "^7.0.0",
|
"workbox-cacheable-response": "^7.0.0",
|
||||||
"workbox-core": "^7.0.0",
|
"workbox-core": "^7.0.0",
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
|
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
|
||||||
|
|
||||||
const { configure } = require('quasar/wrappers');
|
const { configure } = require('quasar/wrappers');
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
module.exports = configure(function (/* ctx */) {
|
module.exports = configure(function (/* ctx */) {
|
||||||
return {
|
return {
|
||||||
@@ -73,9 +72,20 @@ module.exports = configure(function (/* ctx */) {
|
|||||||
// extendViteConf (viteConf) {},
|
// extendViteConf (viteConf) {},
|
||||||
// viteVuePluginOptions: {},
|
// viteVuePluginOptions: {},
|
||||||
|
|
||||||
// vitePlugins: [
|
vitePlugins: [
|
||||||
// [ 'package-name', { ..options.. } ]
|
[
|
||||||
// ]
|
'vite-plugin-checker',
|
||||||
|
{
|
||||||
|
vueTsc: {
|
||||||
|
tsconfigPath: 'tsconfig.vue-tsc.json',
|
||||||
|
},
|
||||||
|
eslint: {
|
||||||
|
lintCommand: 'eslint "./**/*.{js,ts,mjs,cjs,vue}"',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ server: false },
|
||||||
|
],
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
|
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
|
||||||
@@ -104,7 +114,7 @@ module.exports = configure(function (/* ctx */) {
|
|||||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
|
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
|
||||||
framework: {
|
framework: {
|
||||||
config: {
|
config: {
|
||||||
autoImportComponentCase: 'combined', // or 'kebab' (default) or 'combined'
|
autoImportComponentCase: 'kebab', // or 'kebab' (default) or 'combined'
|
||||||
},
|
},
|
||||||
|
|
||||||
// iconSet: 'material-icons', // Quasar icon set
|
// iconSet: 'material-icons', // Quasar icon set
|
||||||
|
|||||||
16
src/App.vue
16
src/App.vue
@@ -2,10 +2,20 @@
|
|||||||
<router-view />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent, onMounted } from 'vue';
|
||||||
|
import { useScheduleStore } from './stores/schedule';
|
||||||
|
import { useBoatStore } from './stores/boat';
|
||||||
|
import { useAuthStore } from './stores/auth';
|
||||||
|
|
||||||
export default defineComponent({
|
defineComponent({
|
||||||
name: 'OYS Borrow-a-Boat',
|
name: 'OYS Borrow-a-Boat',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await useAuthStore().init();
|
||||||
|
await useScheduleStore().fetchTimeBlockTemplates();
|
||||||
|
await useScheduleStore().fetchTimeBlocks();
|
||||||
|
await useBoatStore().fetchBoats();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ const client = new Client();
|
|||||||
// const appDatabaseId = '654ac5044d1c446feb71';
|
// const appDatabaseId = '654ac5044d1c446feb71';
|
||||||
|
|
||||||
// Private self-hosted appwrite
|
// Private self-hosted appwrite
|
||||||
client
|
if (process.env.APPWRITE_API_ENDPOINT && process.env.APPWRITE_API_PROJECT)
|
||||||
.setEndpoint(process.env.APPWRITE_API_ENDPOINT)
|
client
|
||||||
.setProject(process.env.APPWRITE_API_PROJECT);
|
.setEndpoint(process.env.APPWRITE_API_ENDPOINT)
|
||||||
|
.setProject(process.env.APPWRITE_API_PROJECT);
|
||||||
|
|
||||||
//TODO move this to config file
|
//TODO move this to config file
|
||||||
const AppwriteIds = {
|
const AppwriteIds = {
|
||||||
@@ -24,7 +25,9 @@ const AppwriteIds = {
|
|||||||
task: '65ee1cd5b550023fae4f',
|
task: '65ee1cd5b550023fae4f',
|
||||||
taskTags: '65ee21d72d5c8007c34c',
|
taskTags: '65ee21d72d5c8007c34c',
|
||||||
skillTags: '66072582a74d94a4bd01',
|
skillTags: '66072582a74d94a4bd01',
|
||||||
boats: '66341910003e287cd71c',
|
boat: '66341910003e287cd71c',
|
||||||
|
timeBlock: '66361869002883fb4c4b',
|
||||||
|
timeBlockTemplate: '66361f480007fdd639af',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<p>{{ title }}</p>
|
|
||||||
<ul>
|
|
||||||
<li v-for="todo in todos" :key="todo.id" @click="increment">
|
|
||||||
{{ todo.id }} - {{ todo.content }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
|
|
||||||
<p>Active: {{ active ? 'yes' : 'no' }}</p>
|
|
||||||
<p>Clicks on todos: {{ clickCount }}</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import {
|
|
||||||
defineComponent,
|
|
||||||
PropType,
|
|
||||||
computed,
|
|
||||||
ref,
|
|
||||||
toRef,
|
|
||||||
Ref,
|
|
||||||
} from 'vue';
|
|
||||||
import { Todo, Meta } from './models';
|
|
||||||
|
|
||||||
function useClickCount() {
|
|
||||||
const clickCount = ref(0);
|
|
||||||
function increment() {
|
|
||||||
clickCount.value += 1
|
|
||||||
return clickCount.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { clickCount, increment };
|
|
||||||
}
|
|
||||||
|
|
||||||
function useDisplayTodo(todos: Ref<Todo[]>) {
|
|
||||||
const todoCount = computed(() => todos.value.length);
|
|
||||||
return { todoCount };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'ExampleComponent',
|
|
||||||
props: {
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
todos: {
|
|
||||||
type: Array as PropType<Todo[]>,
|
|
||||||
default: () => []
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
type: Object as PropType<Meta>,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
type: Boolean
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setup (props) {
|
|
||||||
return { ...useClickCount(), ...useDisplayTodo(toRef(props, 'todos')) };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -116,7 +116,7 @@ import { Boat, useBoatStore } from 'src/stores/boat';
|
|||||||
import { useScheduleStore } from 'src/stores/schedule';
|
import { useScheduleStore } from 'src/stores/schedule';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type { StatusTypes } from 'src/stores/schedule';
|
import type { StatusTypes } from 'src/stores/schedule.types';
|
||||||
|
|
||||||
interface EventData {
|
interface EventData {
|
||||||
event: object;
|
event: object;
|
||||||
@@ -172,7 +172,7 @@ function monthFormatter() {
|
|||||||
|
|
||||||
function getEvents(scope: ResourceIntervalScope) {
|
function getEvents(scope: ResourceIntervalScope) {
|
||||||
const resourceEvents = scheduleStore.getBoatReservations(
|
const resourceEvents = scheduleStore.getBoatReservations(
|
||||||
date.extractDate(selectedDate.value, 'YYYY-MM-DD'),
|
parseDate(date.extractDate(selectedDate.value, 'YYYY-MM-DD')) as Timestamp,
|
||||||
scope.resource.$id
|
scope.resource.$id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-card v-for="boat in boats" :key="boat.id" flat class="mobile-card">
|
<div v-if="boats">
|
||||||
<q-card-section>
|
<q-card v-for="boat in boats" :key="boat.id" flat class="mobile-card">
|
||||||
<q-img :src="boat.imgSrc" :fit="'scale-down'">
|
<q-card-section>
|
||||||
<div class="row absolute-top">
|
<q-img :src="boat.imgSrc" :fit="'scale-down'">
|
||||||
<div class="col text-h6 text-left">{{ boat.name }}</div>
|
<div class="row absolute-top">
|
||||||
<div class="col text-right">{{ boat.class }}</div>
|
<div class="col text-h6 text-left">{{ boat.name }}</div>
|
||||||
</div>
|
<div class="col text-right">{{ boat.class }}</div>
|
||||||
</q-img>
|
</div>
|
||||||
</q-card-section>
|
</q-img>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
<q-separator />
|
<q-separator />
|
||||||
|
|
||||||
<q-card-actions align="evenly">
|
<q-card-actions align="evenly">
|
||||||
<q-btn flat>Info</q-btn>
|
<q-btn flat>Info</q-btn>
|
||||||
<q-btn flat>Book</q-btn>
|
<q-btn flat>Book</q-btn>
|
||||||
<q-btn flat>Check-Out</q-btn>
|
<q-btn flat>Check-Out</q-btn>
|
||||||
<q-btn flat>Check-In</q-btn>
|
<q-btn flat>Check-In</q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<div v-else><q-card>Sorry, no boats to show you!</q-card></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
19
src/components/scheduling/NavigationBar.vue
Normal file
19
src/components/scheduling/NavigationBar.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row justify-center">
|
||||||
|
<div class="q-pa-md q-gutter-sm row">
|
||||||
|
<q-btn no-caps class="button" style="margin: 2px" @click="$emit('today')">
|
||||||
|
Today
|
||||||
|
</q-btn>
|
||||||
|
<q-btn no-caps class="button" style="margin: 2px" @click="$emit('prev')">
|
||||||
|
< Prev
|
||||||
|
</q-btn>
|
||||||
|
<q-btn no-caps class="button" style="margin: 2px" @click="$emit('next')">
|
||||||
|
Next >
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineEmits(['today', 'prev', 'next']);
|
||||||
|
</script>
|
||||||
129
src/components/scheduling/TimeBlockTemplateComponent.vue
Normal file
129
src/components/scheduling/TimeBlockTemplateComponent.vue
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<q-card>
|
||||||
|
<q-card-section horizontal>
|
||||||
|
<div>
|
||||||
|
<q-input
|
||||||
|
label="Template name"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="template.name"
|
||||||
|
v-if="editable"
|
||||||
|
/>
|
||||||
|
<q-list dense>
|
||||||
|
<q-item v-for="item in template.timeTuples" :key="item[0]">
|
||||||
|
<q-input
|
||||||
|
dense
|
||||||
|
:filled="editable"
|
||||||
|
v-model="item[0]"
|
||||||
|
type="time"
|
||||||
|
label="Start"
|
||||||
|
:readonly="!editable"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
:filled="editable"
|
||||||
|
dense
|
||||||
|
v-model="item[1]"
|
||||||
|
type="time"
|
||||||
|
label="End"
|
||||||
|
:readonly="!editable"
|
||||||
|
/> </q-item></q-list
|
||||||
|
><q-btn
|
||||||
|
v-if="editable"
|
||||||
|
dense
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
label="Add interval"
|
||||||
|
@click="template.timeTuples.push(['00:00', '00:00'])"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<q-card-actions align="right" vertical>
|
||||||
|
<q-btn
|
||||||
|
v-if="!editable"
|
||||||
|
color="primary"
|
||||||
|
icon="edit"
|
||||||
|
label="Edit"
|
||||||
|
@click="editable = !editable"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
v-if="editable"
|
||||||
|
color="primary"
|
||||||
|
icon="save"
|
||||||
|
label="Save"
|
||||||
|
@click="saveTemplate($event, template)"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
v-if="editable"
|
||||||
|
color="secondary"
|
||||||
|
icon="cancel"
|
||||||
|
label="Cancel"
|
||||||
|
@click="revert"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
color="negative"
|
||||||
|
icon="delete"
|
||||||
|
label="Delete"
|
||||||
|
@click="deleteTemplate($event, template)"
|
||||||
|
/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
<q-dialog v-model="alert">
|
||||||
|
<q-card>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">Overlapped blocks!</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section class="q-pt-none">
|
||||||
|
<q-chip
|
||||||
|
square
|
||||||
|
icon="schedule"
|
||||||
|
v-for="item in overlapped"
|
||||||
|
:key="item.start"
|
||||||
|
>
|
||||||
|
{{ item.start }}-{{ item.end }}</q-chip
|
||||||
|
>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn flat label="OK" color="primary" v-close-popup />
|
||||||
|
</q-card-actions> </q-card
|
||||||
|
></q-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { timeTuplesOverlapped, useScheduleStore } from 'src/stores/schedule';
|
||||||
|
import { TimeBlockTemplate } from 'src/stores/schedule.types';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
const editable = ref(false);
|
||||||
|
const alert = ref(false);
|
||||||
|
const overlapped = ref();
|
||||||
|
const scheduleStore = useScheduleStore();
|
||||||
|
const template = defineModel<TimeBlockTemplate>({ required: true });
|
||||||
|
|
||||||
|
const revert = () => {
|
||||||
|
editable.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTemplate = (
|
||||||
|
event: Event,
|
||||||
|
template: TimeBlockTemplate | undefined
|
||||||
|
) => {
|
||||||
|
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
|
||||||
|
// };
|
||||||
|
const saveTemplate = (evt: Event, template: TimeBlockTemplate | undefined) => {
|
||||||
|
if (!template) return false;
|
||||||
|
overlapped.value = timeTuplesOverlapped(template.timeTuples);
|
||||||
|
if (overlapped.value.length > 0) {
|
||||||
|
alert.value = true;
|
||||||
|
} else {
|
||||||
|
if (template.$id) {
|
||||||
|
console.log(template.$id);
|
||||||
|
scheduleStore.updateTimeBlockTemplate(template, template.$id);
|
||||||
|
} else {
|
||||||
|
scheduleStore.createTimeBlockTemplate(template);
|
||||||
|
}
|
||||||
|
editable.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -14,36 +14,32 @@
|
|||||||
interval-start="06:00"
|
interval-start="06:00"
|
||||||
:short-interval-label="true"
|
:short-interval-label="true"
|
||||||
v-model="selectedDate"
|
v-model="selectedDate"
|
||||||
:column-count="boatData.length"
|
:column-count="boats.length"
|
||||||
@change="changeEvent"
|
|
||||||
v-touch-swipe.left.right="handleSwipe"
|
v-touch-swipe.left.right="handleSwipe"
|
||||||
>
|
>
|
||||||
<template #head-day="{ scope }">
|
<template #head-day="{ scope }">
|
||||||
<div style="text-align: center; font-weight: 800">
|
<div style="text-align: center; font-weight: 800">
|
||||||
{{ boatData[scope.columnIndex].displayName }}
|
{{ getBoatDisplayName(scope) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #day-body="{ scope }">
|
<template #day-body="{ scope }">
|
||||||
<div
|
<div v-for="block in getBoatBlocks(scope)" :key="block.$id">
|
||||||
v-for="block in boatData[scope.columnIndex].blocks"
|
|
||||||
:key="block.id"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="timeblock"
|
class="timeblock"
|
||||||
:class="selectedBlock?.id === block.id ? 'selected' : ''"
|
:class="selectedBlock?.$id === block.$id ? 'selected' : ''"
|
||||||
:style="
|
:style="
|
||||||
blockStyles(block, scope.timeStartPos, scope.timeDurationHeight)
|
blockStyles(block, scope.timeStartPos, scope.timeDurationHeight)
|
||||||
"
|
"
|
||||||
:id="block.id"
|
:id="block.id"
|
||||||
@click="selectBlock($event, scope, block)"
|
@click="selectBlock($event, scope, block)"
|
||||||
>
|
>
|
||||||
{{ boatData[scope.columnIndex].name }}<br />
|
{{ boats[scope.columnIndex].name }}<br />
|
||||||
{{ selectedBlock?.id === block.id ? 'Selected' : 'Available' }}
|
{{ selectedBlock?.$id === block.$id ? 'Selected' : 'Available' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<!-- <div
|
||||||
v-for="r in boatData[scope.columnIndex].reservations"
|
v-for="r in boats[scope.columnIndex].reservations"
|
||||||
:key="r.id"
|
:key="r.id"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -58,7 +54,7 @@
|
|||||||
>
|
>
|
||||||
{{ r.user }}
|
{{ r.user }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</template>
|
</template>
|
||||||
</QCalendarDay>
|
</QCalendarDay>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,61 +67,58 @@ import {
|
|||||||
Timestamp,
|
Timestamp,
|
||||||
diffTimestamp,
|
diffTimestamp,
|
||||||
today,
|
today,
|
||||||
parsed,
|
|
||||||
parseTimestamp,
|
parseTimestamp,
|
||||||
parseDate,
|
parseDate,
|
||||||
addToDate,
|
addToDate,
|
||||||
makeDateTime,
|
|
||||||
} from '@quasar/quasar-ui-qcalendar';
|
} from '@quasar/quasar-ui-qcalendar';
|
||||||
import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
|
import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
|
||||||
|
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
import { useBoatStore } from 'src/stores/boat';
|
||||||
import { useScheduleStore } from 'src/stores/schedule';
|
import { useScheduleStore } from 'src/stores/schedule';
|
||||||
import { Reservation, Timeblock } from 'src/stores/schedule.types';
|
import { TimeBlock } from 'src/stores/schedule.types';
|
||||||
import { date } from 'quasar';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
interface BoatData extends Boat {
|
|
||||||
blocks?: Timeblock[];
|
|
||||||
reservations?: Reservation[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const scheduleStore = useScheduleStore();
|
const scheduleStore = useScheduleStore();
|
||||||
const boatStore = useBoatStore();
|
const { boats } = storeToRefs(useBoatStore());
|
||||||
const selectedBlock = defineModel<Timeblock | null>();
|
const selectedBlock = defineModel<TimeBlock | null>();
|
||||||
const selectedDate = ref(today());
|
const selectedDate = ref(today());
|
||||||
|
|
||||||
const boatData = ref<BoatData[]>(boatStore.boats);
|
|
||||||
|
|
||||||
const calendar = ref<QCalendarDay | null>(null);
|
const calendar = ref<QCalendarDay | null>(null);
|
||||||
|
|
||||||
function handleSwipe({ ...event }) {
|
function handleSwipe({ ...event }) {
|
||||||
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
|
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
|
||||||
}
|
}
|
||||||
function reservationStyles(
|
// function reservationStyles(
|
||||||
reservation: Reservation,
|
// reservation: Reservation,
|
||||||
|
// timeStartPos: (t: string) => string,
|
||||||
|
// timeDurationHeight: (d: number) => string
|
||||||
|
// ) {
|
||||||
|
// return genericBlockStyle(
|
||||||
|
// parseDate(reservation.start) as Timestamp,
|
||||||
|
// parseDate(reservation.end) as Timestamp,
|
||||||
|
// timeStartPos,
|
||||||
|
// timeDurationHeight
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
function blockStyles(
|
||||||
|
block: TimeBlock,
|
||||||
timeStartPos: (t: string) => string,
|
timeStartPos: (t: string) => string,
|
||||||
timeDurationHeight: (d: number) => string
|
timeDurationHeight: (d: number) => string
|
||||||
) {
|
) {
|
||||||
return genericBlockStyle(
|
return genericBlockStyle(
|
||||||
parseDate(reservation.start) as Timestamp,
|
parseDate(new Date(block.start)) as Timestamp,
|
||||||
parseDate(reservation.end) as Timestamp,
|
parseDate(new Date(block.end)) as Timestamp,
|
||||||
timeStartPos,
|
timeStartPos,
|
||||||
timeDurationHeight
|
timeDurationHeight
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function blockStyles(
|
function getBoatDisplayName(scope: DayBodyScope) {
|
||||||
block: Timeblock,
|
return boats && boats.value[scope.columnIndex]
|
||||||
timeStartPos: (t: string) => string,
|
? boats.value[scope.columnIndex].displayName
|
||||||
timeDurationHeight: (d: number) => string
|
: '';
|
||||||
) {
|
|
||||||
return genericBlockStyle(
|
|
||||||
parsed(block.start) as Timestamp,
|
|
||||||
parsed(block.end) as Timestamp,
|
|
||||||
timeStartPos,
|
|
||||||
timeDurationHeight
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function genericBlockStyle(
|
function genericBlockStyle(
|
||||||
@@ -161,42 +154,61 @@ interface DayBodyScope {
|
|||||||
timestamp: Timestamp;
|
timestamp: Timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) {
|
function selectBlock(event: MouseEvent, scope: DayBodyScope, block: TimeBlock) {
|
||||||
// TODO: Disable blocks before today with updateDisabled and/or comparison
|
// TODO: Disable blocks before today with updateDisabled and/or comparison
|
||||||
selectedBlock.value === block
|
selectedBlock.value === block
|
||||||
? (selectedBlock.value = null)
|
? (selectedBlock.value = null)
|
||||||
: (selectedBlock.value = block);
|
: (selectedBlock.value = block);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeEvent({ start }: { start: string }) {
|
interface BoatBlocks {
|
||||||
const newBlocks = scheduleStore.getTimeblocksForDate(start);
|
[key: string]: TimeBlock[];
|
||||||
const reservations = scheduleStore.getBoatReservations(
|
|
||||||
parsed(start) as Timestamp
|
|
||||||
);
|
|
||||||
boatData.value.map((boat) => {
|
|
||||||
boat.reservations = reservations.filter(
|
|
||||||
(reservation) => reservation.resource === boat
|
|
||||||
);
|
|
||||||
boat.blocks = newBlocks.filter(
|
|
||||||
(block) =>
|
|
||||||
block.boatId === boat.$id &&
|
|
||||||
boat.reservations?.filter(
|
|
||||||
(r) =>
|
|
||||||
r.start <
|
|
||||||
date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
|
|
||||||
hours: 4,
|
|
||||||
}) &&
|
|
||||||
r.end >
|
|
||||||
date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
|
|
||||||
hours: 4,
|
|
||||||
})
|
|
||||||
).length == 0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const boatBlocks = computed((): BoatBlocks => {
|
||||||
|
return scheduleStore
|
||||||
|
.getTimeBlocksForDate(selectedDate.value)
|
||||||
|
.reduce((result, tb) => {
|
||||||
|
if (!result[tb.boatId]) result[tb.boatId] = [];
|
||||||
|
result[tb.boatId].push(tb);
|
||||||
|
return result;
|
||||||
|
}, <BoatBlocks>{});
|
||||||
|
});
|
||||||
|
|
||||||
|
function getBoatBlocks(scope: DayBodyScope): TimeBlock[] {
|
||||||
|
return boats.value[scope.columnIndex]
|
||||||
|
? boatBlocks.value[boats.value[scope.columnIndex].$id]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// function changeEvent({ start }: { start: string }) {
|
||||||
|
// const newBlocks = scheduleStore.getTimeBlocksForDate(start);
|
||||||
|
// const reservations = scheduleStore.getBoatReservations(
|
||||||
|
// parsed(start) as Timestamp
|
||||||
|
// );
|
||||||
|
// boats.value.map((boat) => {
|
||||||
|
// boat.reservations = reservations.filter(
|
||||||
|
// (reservation) => reservation.resource === boat
|
||||||
|
// );
|
||||||
|
// boat.blocks = newBlocks.filter(
|
||||||
|
// (block) =>
|
||||||
|
// block.boatId === boat.$id &&
|
||||||
|
// boat.reservations?.filter(
|
||||||
|
// (r: Reservation) =>
|
||||||
|
// r.start <
|
||||||
|
// date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
|
||||||
|
// hours: 4,
|
||||||
|
// }) &&
|
||||||
|
// r.end >
|
||||||
|
// date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
|
||||||
|
// hours: 4,
|
||||||
|
// })
|
||||||
|
// ).length == 0
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
// setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout...
|
||||||
|
// }
|
||||||
|
|
||||||
const disabledBefore = computed(() => {
|
const disabledBefore = computed(() => {
|
||||||
const todayTs = parseTimestamp(today()) as Timestamp;
|
const todayTs = parseTimestamp(today()) as Timestamp;
|
||||||
return addToDate(todayTs, { day: -1 }).date;
|
return addToDate(todayTs, { day: -1 }).date;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ import { ref, reactive, computed } from 'vue';
|
|||||||
|
|
||||||
const selectedDate = defineModel<string>();
|
const selectedDate = defineModel<string>();
|
||||||
|
|
||||||
const weekdays = reactive([0, 1, 2, 3, 4, 5, 6]),
|
const weekdays = reactive([1, 2, 3, 4, 5, 6, 0]),
|
||||||
locale = ref('en-CA'),
|
locale = ref('en-CA'),
|
||||||
monthFormatter = monthFormatterFunc(),
|
monthFormatter = monthFormatterFunc(),
|
||||||
dayFormatter = dayFormatterFunc(),
|
dayFormatter = dayFormatterFunc(),
|
||||||
@@ -124,8 +124,14 @@ function dayClass(day: Timestamp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function monthFormatterFunc() {
|
function monthFormatterFunc() {
|
||||||
const longOptions = { timeZone: 'UTC', month: 'long' };
|
const longOptions: Intl.DateTimeFormatOptions = {
|
||||||
const shortOptions = { timeZone: 'UTC', month: 'short' };
|
timeZone: 'UTC',
|
||||||
|
month: 'long',
|
||||||
|
};
|
||||||
|
const shortOptions: Intl.DateTimeFormatOptions = {
|
||||||
|
timeZone: 'UTC',
|
||||||
|
month: 'short',
|
||||||
|
};
|
||||||
|
|
||||||
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
|
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
|
||||||
short ? shortOptions : longOptions
|
short ? shortOptions : longOptions
|
||||||
@@ -133,17 +139,28 @@ function monthFormatterFunc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function weekdayFormatterFunc() {
|
function weekdayFormatterFunc() {
|
||||||
const longOptions = { timeZone: 'UTC', weekday: 'long' };
|
const longOptions: Intl.DateTimeFormatOptions = {
|
||||||
const shortOptions = { timeZone: 'UTC', weekday: 'short' };
|
timeZone: 'UTC',
|
||||||
|
weekday: 'long',
|
||||||
|
};
|
||||||
|
const shortOptions: Intl.DateTimeFormatOptions = {
|
||||||
|
timeZone: 'UTC',
|
||||||
|
weekday: 'short',
|
||||||
|
};
|
||||||
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
|
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
|
||||||
short ? shortOptions : longOptions
|
short ? shortOptions : longOptions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dayFormatterFunc() {
|
function dayFormatterFunc() {
|
||||||
const longOptions = { timeZone: 'UTC', day: '2-digit' };
|
const longOptions: Intl.DateTimeFormatOptions = {
|
||||||
const shortOptions = { timeZone: 'UTC', day: 'numeric' };
|
timeZone: 'UTC',
|
||||||
|
day: '2-digit',
|
||||||
|
};
|
||||||
|
const shortOptions: Intl.DateTimeFormatOptions = {
|
||||||
|
timeZone: 'UTC',
|
||||||
|
day: 'numeric',
|
||||||
|
};
|
||||||
|
|
||||||
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
|
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
|
||||||
short ? shortOptions : longOptions
|
short ? shortOptions : longOptions
|
||||||
|
|||||||
@@ -20,5 +20,5 @@
|
|||||||
import { defineProps } from 'vue';
|
import { defineProps } from 'vue';
|
||||||
import type { Task } from 'src/stores/task';
|
import type { Task } from 'src/stores/task';
|
||||||
|
|
||||||
const props = defineProps<{ task: Task }>();
|
defineProps<{ task: Task }>();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ import { useRouter } from 'vue-router';
|
|||||||
import { useTaskStore, TASKSTATUS } from 'src/stores/task';
|
import { useTaskStore, TASKSTATUS } from 'src/stores/task';
|
||||||
import type { TaskTag, SkillTag, Task } from 'src/stores/task';
|
import type { TaskTag, SkillTag, Task } from 'src/stores/task';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
import { useBoatStore } from 'src/stores/boat';
|
||||||
|
|
||||||
const props = defineProps<{ taskId?: string }>();
|
const props = defineProps<{ taskId?: string }>();
|
||||||
const taskStore = useTaskStore();
|
const taskStore = useTaskStore();
|
||||||
@@ -187,7 +187,7 @@ const targetTask = taskId && taskStore.tasks.find((t) => t.$id === taskId);
|
|||||||
const modifiedTask = reactive(targetTask ? targetTask : defaultTask);
|
const modifiedTask = reactive(targetTask ? targetTask : defaultTask);
|
||||||
|
|
||||||
let tasks = taskStore.tasks;
|
let tasks = taskStore.tasks;
|
||||||
const boatList = ref<Boat[]>(useBoatStore().boats);
|
const boatList = useBoatStore().boats;
|
||||||
|
|
||||||
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
|
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
|
||||||
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
|
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
|
||||||
|
|||||||
@@ -9,9 +9,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineProps } from 'vue';
|
|
||||||
import type { Task } from 'src/stores/task';
|
import type { Task } from 'src/stores/task';
|
||||||
import TaskCardComponent from './TaskCardComponent.vue';
|
import TaskCardComponent from './TaskCardComponent.vue';
|
||||||
|
|
||||||
const props = defineProps<{ tasks: Task[] }>();
|
defineProps<{ tasks: Task[] }>();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
<q-separator />
|
<q-separator />
|
||||||
<q-list dense>
|
<q-list dense>
|
||||||
<q-item
|
<q-item
|
||||||
v-for="col in props.cols.filter((col) => col.name !== 'desc')"
|
v-for="col in props.cols.filter((col:Boat) => col.name !== 'desc')"
|
||||||
:key="col.name"
|
:key="col.name"
|
||||||
>
|
>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
@@ -215,10 +215,8 @@
|
|||||||
import { computed, defineProps, ref } from 'vue';
|
import { computed, defineProps, ref } from 'vue';
|
||||||
import { useTaskStore, Task, SkillTag, TaskTag } from 'src/stores/task';
|
import { useTaskStore, Task, SkillTag, TaskTag } from 'src/stores/task';
|
||||||
import { QTableProps, date, useQuasar } from 'quasar';
|
import { QTableProps, date, useQuasar } from 'quasar';
|
||||||
import { useBoatStore } from 'src/stores/boat';
|
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const selected = ref([]);
|
const selected = ref([]);
|
||||||
const loading = ref(false); // Placeholder
|
const loading = ref(false); // Placeholder
|
||||||
const fabShow = ref(false);
|
const fabShow = ref(false);
|
||||||
@@ -301,44 +299,51 @@ const columns = <QTableProps['columns']>[
|
|||||||
{ name: 'actions', align: 'center', label: 'Actions', field: '$id' },
|
{ name: 'actions', align: 'center', label: 'Actions', field: '$id' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const props = defineProps<{ tasks: Task[] }>();
|
defineProps<{ tasks: Task[] }>();
|
||||||
const taskStore = useTaskStore();
|
const taskStore = useTaskStore();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
||||||
const searchFilter = ref({
|
interface SearchObject {
|
||||||
|
title: string;
|
||||||
|
skillTags: SkillTag[];
|
||||||
|
taskTags: TaskTag[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchFilter = ref<SearchObject>({
|
||||||
title: '',
|
title: '',
|
||||||
skillTags: <SkillTag[]>[],
|
skillTags: [],
|
||||||
taskTags: <TaskTag[]>[],
|
taskTags: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
|
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
|
||||||
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
|
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
|
||||||
|
|
||||||
function onRowClick(evt: Event, row: Task) {
|
// function onRowClick(evt: Event, row: Task) {
|
||||||
router.push({ name: 'edit-task', params: { id: row.$id } });
|
// router.push({ name: 'edit-task', params: { id: row.$id } });
|
||||||
}
|
// }
|
||||||
// TODO: Implement server side search
|
// TODO: Implement server side search
|
||||||
const filterRows = computed(
|
const filterRows = computed(
|
||||||
() => (rows: readonly Task[], terms: any, cols: any, cellValueFn: any) => {
|
() => (rows: readonly Task[], terms: SearchObject) => {
|
||||||
let result = rows;
|
return rows
|
||||||
result = rows.filter((row) =>
|
.filter((row) =>
|
||||||
terms.title
|
terms.title
|
||||||
? row.title.toLowerCase().includes(terms.title.toLowerCase())
|
? row.title.toLowerCase().includes(terms.title.toLowerCase())
|
||||||
: true
|
: true
|
||||||
);
|
)
|
||||||
result = result.filter((row) =>
|
.filter((row) =>
|
||||||
terms.skillTags && terms.skillTags.length > 0
|
terms.skillTags && terms.skillTags.length > 0
|
||||||
? row.required_skills.some((req_skill) =>
|
? row.required_skills.some((req_skill) =>
|
||||||
terms.skillTags.map((t) => t.$id).includes(req_skill)
|
terms.skillTags.map((t) => t.$id).includes(req_skill)
|
||||||
)
|
)
|
||||||
: true
|
: true
|
||||||
);
|
)
|
||||||
result = result.filter((row) =>
|
.filter((row) =>
|
||||||
terms.taskTags && terms.taskTags.length > 0
|
terms.taskTags && terms.taskTags.length > 0
|
||||||
? row.tags.some((tag) => terms.taskTags.map((t) => t.$id).includes(tag))
|
? row.tags.some((tag) =>
|
||||||
: true
|
terms.taskTags.map((t) => t.$id).includes(tag)
|
||||||
);
|
)
|
||||||
return result;
|
: true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ import { ref } from 'vue';
|
|||||||
import { useBoatStore } from 'src/stores/boat';
|
import { useBoatStore } from 'src/stores/boat';
|
||||||
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
|
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
|
||||||
|
|
||||||
|
const boatStore = useBoatStore();
|
||||||
|
boatStore.fetchBoats();
|
||||||
const boats = ref(useBoatStore().boats);
|
const boats = ref(useBoatStore().boats);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -8,32 +8,25 @@
|
|||||||
<q-avatar icon="person" />
|
<q-avatar icon="person" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
Ricky Gervais
|
{{ authStore.currentUser?.name }}
|
||||||
<q-item-label caption>Name</q-item-label>
|
<q-item-label caption>Name</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-avatar icon="numbers" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>
|
|
||||||
123456
|
|
||||||
<q-item-label caption>Member ID</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-separator />
|
<q-separator />
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label overline>Certifications</q-item-label>
|
<q-item-label overline>Certifications</q-item-label>
|
||||||
<q-chip square icon="verified" color="green" text-color="white"
|
<div>
|
||||||
>J/27</q-chip
|
<q-chip square icon="verified" color="green" text-color="white"
|
||||||
>
|
>J/27</q-chip
|
||||||
<q-chip square icon="verified" color="blue" text-color="white"
|
>
|
||||||
>Capri25</q-chip
|
<q-chip square icon="verified" color="blue" text-color="white"
|
||||||
>
|
>Capri25</q-chip
|
||||||
<q-chip square icon="verified" color="red" text-color="white"
|
>
|
||||||
>Night</q-chip
|
<q-chip square icon="verified" color="grey-9" text-color="white"
|
||||||
>
|
>Night</q-chip
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
@@ -42,4 +35,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
|
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
|
||||||
|
import { useAuthStore } from 'src/stores/auth';
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
rounded
|
rounded
|
||||||
class="bg-warning text-grey-10"
|
class="bg-warning text-grey-10"
|
||||||
style="max-width: 95vw; margin: auto"
|
style="max-width: 95vw; margin: auto"
|
||||||
v-if="bookingForm.boat?.defects"
|
v-if="bookingForm.boat && bookingForm.boat.defects.length > 0"
|
||||||
>
|
>
|
||||||
<template v-slot:avatar>
|
<template v-slot:avatar>
|
||||||
<q-icon name="warning" color="grey-10" />
|
<q-icon name="warning" color="grey-10" />
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
><q-banner v-if="bookingForm.boat"
|
><q-banner v-if="bookingForm.boat"
|
||||||
>Passengers:
|
>Passengers:
|
||||||
{{ bookingForm.members.length + bookingForm.guests.length }} /
|
{{ bookingForm.members.length + bookingForm.guests.length }} /
|
||||||
{{ bookingForm.boat.booking?.maxPassengers }}</q-banner
|
{{ bookingForm.boat.maxPassengers }}</q-banner
|
||||||
>
|
>
|
||||||
<q-item
|
<q-item
|
||||||
class="q-my-sm"
|
class="q-my-sm"
|
||||||
@@ -102,7 +102,7 @@ import { useAuthStore } from 'src/stores/auth';
|
|||||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { useScheduleStore } from 'src/stores/schedule';
|
import { useScheduleStore } from 'src/stores/schedule';
|
||||||
import { Timeblock } from 'src/stores/schedule.types';
|
import { TimeBlock } from 'src/stores/schedule.types';
|
||||||
import BoatScheduleTableComponent from 'src/components/scheduling/boat/BoatScheduleTableComponent.vue';
|
import BoatScheduleTableComponent from 'src/components/scheduling/boat/BoatScheduleTableComponent.vue';
|
||||||
|
|
||||||
interface BookingForm {
|
interface BookingForm {
|
||||||
@@ -119,7 +119,7 @@ const auth = useAuthStore();
|
|||||||
const dateFormat = 'MMM D, YYYY h:mm A';
|
const dateFormat = 'MMM D, YYYY h:mm A';
|
||||||
const resourceView = ref(true);
|
const resourceView = ref(true);
|
||||||
const scheduleStore = useScheduleStore();
|
const scheduleStore = useScheduleStore();
|
||||||
const timeblock = ref<Timeblock>();
|
const timeblock = ref<TimeBlock>();
|
||||||
const bookingForm = ref<BookingForm>({
|
const bookingForm = ref<BookingForm>({
|
||||||
bookingId: scheduleStore.getNewId(),
|
bookingId: scheduleStore.getNewId(),
|
||||||
name: auth.currentUser?.name,
|
name: auth.currentUser?.name,
|
||||||
@@ -131,7 +131,6 @@ const bookingForm = ref<BookingForm>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
watch(timeblock, (tb_new) => {
|
watch(timeblock, (tb_new) => {
|
||||||
console.log('Hi');
|
|
||||||
bookingForm.value.boat = useBoatStore().boats.find(
|
bookingForm.value.boat = useBoatStore().boats.find(
|
||||||
(b) => b.$id === tb_new?.boatId
|
(b) => b.$id === tb_new?.boatId
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,25 +50,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Reservation, useScheduleStore } from 'src/stores/schedule';
|
import { useScheduleStore } from 'src/stores/schedule';
|
||||||
|
import { Reservation } from 'src/stores/schedule.types';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
const scheduleStore = useScheduleStore();
|
const scheduleStore = useScheduleStore();
|
||||||
import {
|
import { TimestampOrNull, parseDate, today } from '@quasar/quasar-ui-qcalendar';
|
||||||
TimestampOrNull,
|
|
||||||
makeDateTime,
|
|
||||||
makeDate,
|
|
||||||
parseDate,
|
|
||||||
today,
|
|
||||||
} from '@quasar/quasar-ui-qcalendar';
|
|
||||||
import { QCalendarDay } from '@quasar/quasar-ui-qcalendar';
|
import { QCalendarDay } from '@quasar/quasar-ui-qcalendar';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { Timestamp } from '@quasar/quasar-ui-qcalendar';
|
import { Timestamp } from '@quasar/quasar-ui-qcalendar';
|
||||||
|
|
||||||
const selectedDate = ref(today());
|
const selectedDate = ref(today());
|
||||||
|
|
||||||
// Use ref to get a reference to the QCalendarDay component
|
|
||||||
const calendarRef = ref(QCalendarDay);
|
|
||||||
|
|
||||||
// Method declarations
|
// Method declarations
|
||||||
|
|
||||||
function slotStyle(
|
function slotStyle(
|
||||||
@@ -93,32 +85,22 @@ function slotStyle(
|
|||||||
function reservationEvents(timestamp: Timestamp) {
|
function reservationEvents(timestamp: Timestamp) {
|
||||||
return scheduleStore.getBoatReservations(timestamp);
|
return scheduleStore.getBoatReservations(timestamp);
|
||||||
}
|
}
|
||||||
|
function onMoved(data: Event) {
|
||||||
function onToday() {
|
|
||||||
calendarRef.value.moveToToday();
|
|
||||||
}
|
|
||||||
function onPrev() {
|
|
||||||
calendarRef.value.prev();
|
|
||||||
}
|
|
||||||
function onNext() {
|
|
||||||
calendarRef.value.next();
|
|
||||||
}
|
|
||||||
function onMoved(data) {
|
|
||||||
console.log('onMoved', data);
|
console.log('onMoved', data);
|
||||||
}
|
}
|
||||||
function onChange(data) {
|
function onChange(data: Event) {
|
||||||
console.log('onChange', data);
|
console.log('onChange', data);
|
||||||
}
|
}
|
||||||
function onClickDate(data) {
|
function onClickDate(data: Event) {
|
||||||
console.log('onClickDate', data);
|
console.log('onClickDate', data);
|
||||||
}
|
}
|
||||||
function onClickTime(data) {
|
function onClickTime(data: Event) {
|
||||||
console.log('onClickTime', data);
|
console.log('onClickTime', data);
|
||||||
}
|
}
|
||||||
function onClickInterval(data) {
|
function onClickInterval(data: Event) {
|
||||||
console.log('onClickInterval', data);
|
console.log('onClickInterval', data);
|
||||||
}
|
}
|
||||||
function onClickHeadDay(data) {
|
function onClickHeadDay(data: Event) {
|
||||||
console.log('onClickHeadDay', data);
|
console.log('onClickHeadDay', data);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
188
src/pages/schedule/ManageCalendar.vue
Normal file
188
src/pages/schedule/ManageCalendar.vue
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<template>
|
||||||
|
<div class="fit row wrap justify-start items-start content-start">
|
||||||
|
<div class="col-9 q-pa-md">
|
||||||
|
<div class="scheduler">
|
||||||
|
<NavigationBar @next="onNext" @today="onToday" @prev="onPrev" />
|
||||||
|
<q-calendar-scheduler
|
||||||
|
ref="calendar"
|
||||||
|
v-model="selectedDate"
|
||||||
|
v-model:model-resources="boats"
|
||||||
|
resource-key="$id"
|
||||||
|
resource-label="name"
|
||||||
|
view="week"
|
||||||
|
:weekdays="[1, 2, 3, 4, 5, 6, 0]"
|
||||||
|
hoverable
|
||||||
|
animated
|
||||||
|
bordered
|
||||||
|
:drag-enter-func="onDragEnter"
|
||||||
|
:drag-over-func="onDragOver"
|
||||||
|
:drag-leave-func="onDragLeave"
|
||||||
|
:drop-func="onDrop"
|
||||||
|
:day-min-height="50"
|
||||||
|
:day-height="0"
|
||||||
|
>
|
||||||
|
<template #day="{ scope }">
|
||||||
|
<div
|
||||||
|
v-if="getTimeBlocks(scope.timestamp, scope.resource)"
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-for="event in getTimeBlocks(scope.timestamp, scope.resource)"
|
||||||
|
:key="event.id"
|
||||||
|
>
|
||||||
|
<q-chip clickable square icon="schedule">
|
||||||
|
{{ date.formatDate(event.start, 'HH:mm') }} -
|
||||||
|
{{ date.formatDate(event.end, 'HH:mm') }}</q-chip
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-calendar-scheduler>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-3 q-pa-md">
|
||||||
|
<q-list padding bordered class="rounded-borders">
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label overline>Availability Templates</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Drag and drop a template to a boat / date to create booking
|
||||||
|
availability</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn label="Add Template" color="primary" @click="addTemplate" />
|
||||||
|
</q-card-actions>
|
||||||
|
<q-separator spaced />
|
||||||
|
<q-expansion-item
|
||||||
|
v-for="template in timeblockTemplates"
|
||||||
|
:key="template.$id"
|
||||||
|
dense
|
||||||
|
dense-toggle
|
||||||
|
expand-separator
|
||||||
|
: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>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
QCalendarScheduler,
|
||||||
|
Timestamp,
|
||||||
|
today,
|
||||||
|
} from '@quasar/quasar-ui-qcalendar';
|
||||||
|
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||||
|
import { buildTimeBlock, useScheduleStore } from 'src/stores/schedule';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import type { TimeBlockTemplate, TimeTuple } from 'src/stores/schedule.types';
|
||||||
|
import { date } from 'quasar';
|
||||||
|
import TimeBlockTemplateComponent from 'src/components/scheduling/TimeBlockTemplateComponent.vue';
|
||||||
|
import NavigationBar from 'src/components/scheduling/NavigationBar.vue';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
|
const selectedDate = ref(today());
|
||||||
|
const { fetchBoats } = useBoatStore();
|
||||||
|
const { getTimeBlocks, fetchTimeBlocks, fetchTimeBlockTemplates } =
|
||||||
|
useScheduleStore();
|
||||||
|
const { boats } = storeToRefs(useBoatStore());
|
||||||
|
const { timeblockTemplates } = storeToRefs(useScheduleStore());
|
||||||
|
const calendar = ref();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await fetchBoats();
|
||||||
|
await fetchTimeBlocks();
|
||||||
|
await fetchTimeBlockTemplates();
|
||||||
|
});
|
||||||
|
|
||||||
|
function addTemplate() {
|
||||||
|
timeblockTemplates.value.push({ name: 'New Template', timeTuples: [] });
|
||||||
|
}
|
||||||
|
function createTimeBlock(boat: Boat, templateId: string, date: string) {
|
||||||
|
const timeBlock = timeblockTemplates.value.find((t) => t.$id === templateId);
|
||||||
|
timeBlock?.timeTuples.map((tb: TimeTuple) =>
|
||||||
|
useScheduleStore().createTimeBlock(buildTimeBlock(boat, tb, date))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
console.log('onDragEnter', e, type);
|
||||||
|
if (type === 'day' || type === 'head-day') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (e.target instanceof HTMLDivElement)
|
||||||
|
e.target.classList.add('bg-secondary');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDragOver(e: DragEvent, type: string) {
|
||||||
|
console.log('onDragOver');
|
||||||
|
if (type === 'day' || type === 'head-day') {
|
||||||
|
e.preventDefault();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDragLeave(e: DragEvent, type: string) {
|
||||||
|
console.log('onDragLeave');
|
||||||
|
if (type === 'day' || type === 'head-day') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (e.target instanceof HTMLDivElement)
|
||||||
|
e.target.classList.remove('bg-secondary');
|
||||||
|
console.log(e.target);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDrop(
|
||||||
|
e: DragEvent,
|
||||||
|
type: string,
|
||||||
|
scope: { resource: Boat; timestamp: Timestamp }
|
||||||
|
) {
|
||||||
|
console.log('onDrop', e, type, scope);
|
||||||
|
if ((type === 'day' || type === 'head-day') && e.dataTransfer) {
|
||||||
|
const templateId = e.dataTransfer.getData('ID');
|
||||||
|
const date = scope.timestamp.date;
|
||||||
|
if (type === 'head-day') {
|
||||||
|
boats.value.map((r) => createTimeBlock(r, templateId, date));
|
||||||
|
} else {
|
||||||
|
createTimeBlock(scope.resource, templateId, date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.target instanceof HTMLDivElement)
|
||||||
|
e.target.classList.remove('bg-secondary');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onToday() {
|
||||||
|
calendar.value.moveToToday();
|
||||||
|
}
|
||||||
|
function onPrev() {
|
||||||
|
calendar.value.prev();
|
||||||
|
}
|
||||||
|
function onNext() {
|
||||||
|
calendar.value.next();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<q-item v-for="link in navlinks" :key="link.label">
|
<q-item v-for="link in navlinks" :key="link.label">
|
||||||
<q-btn
|
<q-btn
|
||||||
:icon="link.icon"
|
:icon="link.icon"
|
||||||
color="primary"
|
:color="link.color"
|
||||||
size="1.25em"
|
size="1.25em"
|
||||||
:to="link.to"
|
:to="link.to"
|
||||||
:label="link.label"
|
:label="link.label"
|
||||||
@@ -21,7 +21,19 @@ const navlinks = [
|
|||||||
icon: 'more_time',
|
icon: 'more_time',
|
||||||
to: '/schedule/book',
|
to: '/schedule/book',
|
||||||
label: 'Create a Reservation',
|
label: 'Create a Reservation',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'calendar_month',
|
||||||
|
to: '/schedule/view',
|
||||||
|
label: 'View Schedule',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'edit_calendar',
|
||||||
|
to: '/schedule/manage',
|
||||||
|
label: 'Manage Calendar',
|
||||||
|
color: 'accent',
|
||||||
},
|
},
|
||||||
{ icon: 'calendar_month', to: '/schedule/view', label: 'View Schedule' },
|
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ export default route(function (/* { store, ssrContext } */) {
|
|||||||
Router.beforeEach((to) => {
|
Router.beforeEach((to) => {
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
|
|
||||||
if (!auth.ready) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (auth.currentUser) {
|
if (auth.currentUser) {
|
||||||
return to.meta.accountRoute ? { name: 'index' } : true;
|
return to.meta.accountRoute ? { name: 'index' } : true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import('src/pages/schedule/BoatScheduleView.vue'),
|
component: () => import('src/pages/schedule/BoatScheduleView.vue'),
|
||||||
name: 'boat-schedule',
|
name: 'boat-schedule',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'manage',
|
||||||
|
component: () => import('src/pages/schedule/ManageCalendar.vue'),
|
||||||
|
name: 'manage-schedule',
|
||||||
|
meta: { requiresScheduleAdmin: true },
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -96,6 +102,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
component: () => import('layouts/AdminLayout.vue'),
|
component: () => import('layouts/AdminLayout.vue'),
|
||||||
|
meta: { requiresAdmin: true },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/user',
|
path: '/user',
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { ID, account } from 'boot/appwrite';
|
import { ID, account } from 'boot/appwrite';
|
||||||
import type { Models } from 'appwrite';
|
import { OAuthProvider, type Models } from 'appwrite';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
const currentUser = ref<Models.User<Models.Preferences> | null>(null);
|
const currentUser = ref<Models.User<Models.Preferences> | null>(null);
|
||||||
const ready = ref(false);
|
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
try {
|
try {
|
||||||
@@ -13,7 +12,6 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
} catch {
|
} catch {
|
||||||
currentUser.value = null;
|
currentUser.value = null;
|
||||||
}
|
}
|
||||||
ready.value = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function register(email: string, password: string) {
|
async function register(email: string, password: string) {
|
||||||
@@ -21,12 +19,12 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
return await login(email, password);
|
return await login(email, password);
|
||||||
}
|
}
|
||||||
async function login(email: string, password: string) {
|
async function login(email: string, password: string) {
|
||||||
await account.createEmailSession(email, password);
|
await account.createEmailPasswordSession(email, password);
|
||||||
currentUser.value = await account.get();
|
currentUser.value = await account.get();
|
||||||
}
|
}
|
||||||
async function googleLogin() {
|
async function googleLogin() {
|
||||||
account.createOAuth2Session(
|
account.createOAuth2Session(
|
||||||
'google',
|
OAuthProvider.Google,
|
||||||
'https://bab.toal.ca/',
|
'https://bab.toal.ca/',
|
||||||
'https://bab.toal.ca/#/login'
|
'https://bab.toal.ca/#/login'
|
||||||
);
|
);
|
||||||
@@ -37,5 +35,5 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
return account.deleteSession('current').then((currentUser.value = null));
|
return account.deleteSession('current').then((currentUser.value = null));
|
||||||
}
|
}
|
||||||
|
|
||||||
return { currentUser, register, login, googleLogin, logout, init, ready };
|
return { currentUser, register, login, googleLogin, logout, init };
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { Models } from 'appwrite';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
import { AppwriteIds, databases } from 'src/boot/appwrite';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
// const boatSource = null;
|
// const boatSource = null;
|
||||||
|
|
||||||
export interface Boat {
|
export interface Boat extends Models.Document {
|
||||||
$id: string;
|
$id: string;
|
||||||
name: string;
|
name: string;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
@@ -10,10 +13,10 @@ export interface Boat {
|
|||||||
year?: number;
|
year?: number;
|
||||||
imgSrc?: string;
|
imgSrc?: string;
|
||||||
iconSrc?: string;
|
iconSrc?: string;
|
||||||
bookingAvailable?: boolean;
|
bookingAvailable: boolean;
|
||||||
requiredCerts: string[];
|
requiredCerts: string[];
|
||||||
maxPassengers: number;
|
maxPassengers: number;
|
||||||
defects?: {
|
defects: {
|
||||||
type: string;
|
type: string;
|
||||||
severity: string;
|
severity: string;
|
||||||
description: string;
|
description: string;
|
||||||
@@ -21,81 +24,20 @@ export interface Boat {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSampleData = () => [
|
export const useBoatStore = defineStore('boat', () => {
|
||||||
{
|
const boats = ref<Boat[]>([]);
|
||||||
$id: '1',
|
|
||||||
name: 'ProjectX',
|
|
||||||
displayName: 'PX',
|
|
||||||
class: 'J/27',
|
|
||||||
year: 1981,
|
|
||||||
imgSrc: '/tmpimg/j27.png',
|
|
||||||
iconSrc: '/tmpimg/projectx_avatar256.png',
|
|
||||||
bookingAvailable: true,
|
|
||||||
maxPassengers: 8,
|
|
||||||
requiredCerts: [],
|
|
||||||
defects: [
|
|
||||||
{
|
|
||||||
type: 'engine',
|
|
||||||
severity: 'moderate',
|
|
||||||
description: 'Fuel line leaks at engine fitting.',
|
|
||||||
detail: `The gasket in the end of the fuel hose is damaged, and does not properly seal.
|
|
||||||
This will cause fuel to leak, and will allow air into the fuel chamber, causing a lean mixture,
|
|
||||||
and rough engine performance.`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'rigging',
|
|
||||||
severity: 'moderate',
|
|
||||||
description: 'Tiller extension is broken.',
|
|
||||||
detail:
|
|
||||||
'The tiller extension swivel is broken, and will not attach to the tiller.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$id: '2',
|
|
||||||
name: 'Take5',
|
|
||||||
displayName: 'T5',
|
|
||||||
class: 'J/27',
|
|
||||||
year: 1985,
|
|
||||||
imgSrc: '/tmpimg/j27.png',
|
|
||||||
iconsrc: '/tmpimg/take5_avatar32.png',
|
|
||||||
bookingAvailable: true,
|
|
||||||
maxPassengers: 8,
|
|
||||||
requiredCerts: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$id: '3',
|
|
||||||
name: 'WeeBeestie',
|
|
||||||
displayName: 'WB',
|
|
||||||
class: 'Capri 25',
|
|
||||||
year: 1989,
|
|
||||||
imgSrc: '/tmpimg/capri25.png',
|
|
||||||
bookingAvailable: true,
|
|
||||||
maxPassengers: 6,
|
|
||||||
requiredCerts: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$id: '4',
|
|
||||||
name: 'Just My Imagination',
|
|
||||||
displayName: 'JMI',
|
|
||||||
class: 'Sirius 28',
|
|
||||||
year: 1989,
|
|
||||||
imgSrc: '/tmpimg/JMI.jpg',
|
|
||||||
bookingAvailable: true,
|
|
||||||
maxPassengers: 8,
|
|
||||||
requiredCerts: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const useBoatStore = defineStore('boat', {
|
async function fetchBoats() {
|
||||||
state: () => ({
|
try {
|
||||||
boats: getSampleData(),
|
const response = await databases.listDocuments(
|
||||||
}),
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.boat
|
||||||
|
);
|
||||||
|
boats.value = response.documents as Boat[];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch boats', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getters: {},
|
return { boats, fetchBoats };
|
||||||
|
|
||||||
actions: {
|
|
||||||
// update () {
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|||||||
65
src/stores/sampledata/boat.ts
Normal file
65
src/stores/sampledata/boat.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
export const getSampleData = () => [
|
||||||
|
{
|
||||||
|
$id: '1',
|
||||||
|
name: 'ProjectX',
|
||||||
|
displayName: 'PX',
|
||||||
|
class: 'J/27',
|
||||||
|
year: 1981,
|
||||||
|
imgSrc: '/tmpimg/j27.png',
|
||||||
|
iconSrc: '/tmpimg/projectx_avatar256.png',
|
||||||
|
bookingAvailable: true,
|
||||||
|
maxPassengers: 8,
|
||||||
|
requiredCerts: [],
|
||||||
|
defects: [
|
||||||
|
{
|
||||||
|
type: 'engine',
|
||||||
|
severity: 'moderate',
|
||||||
|
description: 'Fuel line leaks at engine fitting.',
|
||||||
|
detail: `The gasket in the end of the fuel hose is damaged, and does not properly seal.
|
||||||
|
This will cause fuel to leak, and will allow air into the fuel chamber, causing a lean mixture,
|
||||||
|
and rough engine performance.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'rigging',
|
||||||
|
severity: 'moderate',
|
||||||
|
description: 'Tiller extension is broken.',
|
||||||
|
detail:
|
||||||
|
'The tiller extension swivel is broken, and will not attach to the tiller.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$id: '2',
|
||||||
|
name: 'Take5',
|
||||||
|
displayName: 'T5',
|
||||||
|
class: 'J/27',
|
||||||
|
year: 1985,
|
||||||
|
imgSrc: '/tmpimg/j27.png',
|
||||||
|
iconsrc: '/tmpimg/take5_avatar32.png',
|
||||||
|
bookingAvailable: true,
|
||||||
|
maxPassengers: 8,
|
||||||
|
requiredCerts: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$id: '3',
|
||||||
|
name: 'WeeBeestie',
|
||||||
|
displayName: 'WB',
|
||||||
|
class: 'Capri 25',
|
||||||
|
year: 1989,
|
||||||
|
imgSrc: '/tmpimg/capri25.png',
|
||||||
|
bookingAvailable: true,
|
||||||
|
maxPassengers: 6,
|
||||||
|
requiredCerts: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$id: '4',
|
||||||
|
name: 'Just My Imagination',
|
||||||
|
displayName: 'JMI',
|
||||||
|
class: 'Sirius 28',
|
||||||
|
year: 1989,
|
||||||
|
imgSrc: '/tmpimg/JMI.jpg',
|
||||||
|
bookingAvailable: true,
|
||||||
|
maxPassengers: 8,
|
||||||
|
requiredCerts: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -11,13 +11,14 @@ import type {
|
|||||||
StatusTypes,
|
StatusTypes,
|
||||||
Reservation,
|
Reservation,
|
||||||
TimeBlockTemplate,
|
TimeBlockTemplate,
|
||||||
Timeblock,
|
TimeBlock,
|
||||||
|
TimeTuple,
|
||||||
} from '../schedule.types';
|
} from '../schedule.types';
|
||||||
|
|
||||||
export const templateA: TimeBlockTemplate = {
|
export const templateA: TimeBlockTemplate = {
|
||||||
id: '1',
|
id: '1',
|
||||||
name: 'WeekdayBlocks',
|
name: 'WeekdayBlocks',
|
||||||
blocks: [
|
timeTuples: [
|
||||||
['08:00', '12:00'],
|
['08:00', '12:00'],
|
||||||
['12:00', '16:00'],
|
['12:00', '16:00'],
|
||||||
['17:00', '21:00'],
|
['17:00', '21:00'],
|
||||||
@@ -27,7 +28,7 @@ export const templateA: TimeBlockTemplate = {
|
|||||||
export const templateB: TimeBlockTemplate = {
|
export const templateB: TimeBlockTemplate = {
|
||||||
id: '2',
|
id: '2',
|
||||||
name: 'WeekendBlocks',
|
name: 'WeekendBlocks',
|
||||||
blocks: [
|
timeTuples: [
|
||||||
['07:00', '10:00'],
|
['07:00', '10:00'],
|
||||||
['10:00', '13:00'],
|
['10:00', '13:00'],
|
||||||
['13:00', '16:00'],
|
['13:00', '16:00'],
|
||||||
@@ -35,20 +36,20 @@ export const templateB: TimeBlockTemplate = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getSampleTimeBlocks(): Timeblock[] {
|
export function getSampleTimeBlocks(): TimeBlock[] {
|
||||||
// Hard-code 30 days worth of blocks, for now. Make them random templates
|
// Hard-code 30 days worth of blocks, for now. Make them random templates
|
||||||
const boats = useBoatStore().boats;
|
const boats = useBoatStore().boats;
|
||||||
const result: Timeblock[] = [];
|
const result: TimeBlock[] = [];
|
||||||
const tsToday: Timestamp = parseTimestamp(today()) as Timestamp;
|
const tsToday: Timestamp = parseTimestamp(today()) as Timestamp;
|
||||||
|
|
||||||
for (let i = 0; i <= 30; i++) {
|
for (let i = 0; i <= 30; i++) {
|
||||||
const template = templateB;
|
const template = templateB;
|
||||||
result.push(
|
result.push(
|
||||||
...boats
|
...boats
|
||||||
.map((b): Timeblock[] => {
|
.map((b): TimeBlock[] => {
|
||||||
return template.blocks.map((t): Timeblock => {
|
return template.blocks.map((t: TimeTuple): TimeBlock => {
|
||||||
return {
|
return {
|
||||||
id: 'id' + Math.random().toString(32).slice(2),
|
$id: 'id' + Math.random().toString(32).slice(2),
|
||||||
boatId: b.$id,
|
boatId: b.$id,
|
||||||
start: addToDate(tsToday, { day: i }).date + ' ' + t[0],
|
start: addToDate(tsToday, { day: i }).date + ' ' + t[0],
|
||||||
end: addToDate(tsToday, { day: i }).date + ' ' + t[1],
|
end: addToDate(tsToday, { day: i }).date + ' ' + t[1],
|
||||||
|
|||||||
@@ -8,21 +8,92 @@ import {
|
|||||||
compareDate,
|
compareDate,
|
||||||
} from '@quasar/quasar-ui-qcalendar';
|
} from '@quasar/quasar-ui-qcalendar';
|
||||||
|
|
||||||
import { Reservation, Timeblock } from './schedule.types';
|
|
||||||
import {
|
import {
|
||||||
getSampleReservations,
|
Reservation,
|
||||||
getSampleTimeBlocks,
|
TimeBlockTemplate,
|
||||||
} from './sampledata/schedule';
|
TimeTuple,
|
||||||
|
TimeBlock,
|
||||||
|
} from './schedule.types';
|
||||||
|
import { AppwriteIds, databases } from 'src/boot/appwrite';
|
||||||
|
import { ID, Models } from 'appwrite';
|
||||||
|
|
||||||
|
export type Interval = {
|
||||||
|
start: string;
|
||||||
|
end: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function arrayToTimeTuples(arr: string[]) {
|
||||||
|
const timeTuples: TimeTuple[] = [];
|
||||||
|
for (let i = 0; i < arr.length; i += 2) {
|
||||||
|
timeTuples.push([arr[i], arr[i + 1]]);
|
||||||
|
}
|
||||||
|
return timeTuples;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function timeTuplesOverlapped(tuples: TimeTuple[]): Interval[] {
|
||||||
|
return blocksOverlapped(
|
||||||
|
tuples.map((tuples) => {
|
||||||
|
return {
|
||||||
|
start: '01/01/2001 ' + tuples[0],
|
||||||
|
end: '01/01/2001 ' + tuples[1],
|
||||||
|
};
|
||||||
|
})
|
||||||
|
).map((t) => {
|
||||||
|
return { start: t.start.split(' ')[1], end: t.end.split(' ')[1] };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function blocksOverlapped(blocks: TimeBlock[] | Interval[]): Interval[] {
|
||||||
|
return Array.from(
|
||||||
|
new Set(
|
||||||
|
blocks
|
||||||
|
.sort((a, b) => Date.parse(a.start) - Date.parse(b.start))
|
||||||
|
.reduce((acc: Interval[], block, i, arr) => {
|
||||||
|
if (i > 0 && block.start < arr[i - 1].end)
|
||||||
|
acc.push(arr[i - 1], block);
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildTimeBlock(
|
||||||
|
resource: Boat,
|
||||||
|
time: TimeTuple,
|
||||||
|
blockDate: string
|
||||||
|
): TimeBlock {
|
||||||
|
/* When the time zone offset is absent, date-only forms are interpreted
|
||||||
|
as a UTC time and date-time forms are interpreted as local time. */
|
||||||
|
const result = {
|
||||||
|
boatId: resource.$id,
|
||||||
|
start: new Date(blockDate + 'T' + time[0]).toISOString(),
|
||||||
|
end: new Date(blockDate + 'T' + time[1]).toISOString(),
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export const useScheduleStore = defineStore('schedule', () => {
|
export const useScheduleStore = defineStore('schedule', () => {
|
||||||
// TODO: Implement functions to dynamically pull this data.
|
// TODO: Implement functions to dynamically pull this data.
|
||||||
const reservations = ref<Reservation[]>(getSampleReservations());
|
const reservations = ref<Reservation[]>([]);
|
||||||
const timeblocks = ref<Timeblock[]>(getSampleTimeBlocks());
|
const timeblocks = ref<TimeBlock[]>([]);
|
||||||
|
const timeblockTemplates = ref<TimeBlockTemplate[]>([]);
|
||||||
|
|
||||||
const getTimeblocksForDate = (date: string): Timeblock[] => {
|
const getTimeBlocks = (date: Timestamp, boat: Boat): TimeBlock[] => {
|
||||||
return timeblocks.value.filter((b) =>
|
return timeblocks.value.filter((block) => {
|
||||||
compareDate(parsed(b.start) as Timestamp, parsed(date) as Timestamp)
|
return (
|
||||||
);
|
compareDate(parseDate(new Date(block.start)) as Timestamp, date) &&
|
||||||
|
block.boatId === boat.$id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getTimeBlocksForDate = (date: string): TimeBlock[] => {
|
||||||
|
// TODO: This needs to actually make sure we have the dates we need, stay in sync, etc.
|
||||||
|
return timeblocks.value.filter((b) => {
|
||||||
|
return compareDate(
|
||||||
|
parseDate(new Date(b.start)) as Timestamp,
|
||||||
|
parsed(date) as Timestamp
|
||||||
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBoatReservations = (
|
const getBoatReservations = (
|
||||||
@@ -40,7 +111,37 @@ export const useScheduleStore = defineStore('schedule', () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// const getConflicts = (timeblock: Timeblock, boat: Boat) => {
|
async function fetchTimeBlocks() {
|
||||||
|
try {
|
||||||
|
const response = await databases.listDocuments(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.timeBlock
|
||||||
|
);
|
||||||
|
timeblocks.value = response.documents as TimeBlock[];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch timeblocks', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchTimeBlockTemplates() {
|
||||||
|
try {
|
||||||
|
const response = await databases.listDocuments(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.timeBlockTemplate
|
||||||
|
);
|
||||||
|
timeblockTemplates.value = response.documents.map(
|
||||||
|
(d: Models.Document): TimeBlockTemplate => {
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
timeTuples: arrayToTimeTuples(d.timeTuple),
|
||||||
|
} as TimeBlockTemplate;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch timeblock templates', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const getConflicts = (timeblock: TimeBlock, boat: Boat) => {
|
||||||
// const start = date.buildDate({
|
// const start = date.buildDate({
|
||||||
// hour: timeblock.start.hour,
|
// hour: timeblock.start.hour,
|
||||||
// minute: timeblock.start.minute,
|
// minute: timeblock.start.minute,
|
||||||
@@ -55,6 +156,7 @@ export const useScheduleStore = defineStore('schedule', () => {
|
|||||||
// });
|
// });
|
||||||
// return scheduleStore.getConflictingReservations(boat, start, end);
|
// return scheduleStore.getConflictingReservations(boat, start, end);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const getConflictingReservations = (
|
const getConflictingReservations = (
|
||||||
resource: Boat,
|
resource: Boat,
|
||||||
start: Date,
|
start: Date,
|
||||||
@@ -98,13 +200,85 @@ export const useScheduleStore = defineStore('schedule', () => {
|
|||||||
: reservations.value.push(reservation);
|
: reservations.value.push(reservation);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createTimeBlock = async (block: TimeBlock) => {
|
||||||
|
try {
|
||||||
|
const response = await databases.createDocument(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.timeBlock,
|
||||||
|
ID.unique(),
|
||||||
|
block
|
||||||
|
);
|
||||||
|
timeblocks.value.push(response as TimeBlock);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error creating TimeBlock: ' + e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createTimeBlockTemplate = async (template: TimeBlockTemplate) => {
|
||||||
|
try {
|
||||||
|
const response = await databases.createDocument(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.timeBlockTemplate,
|
||||||
|
ID.unique(),
|
||||||
|
{ name: template.name, timeTuple: template.timeTuples.flat(2) }
|
||||||
|
);
|
||||||
|
timeblockTemplates.value.push(response as TimeBlockTemplate);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error updating TimeBlockTemplate: ' + e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const deleteTimeBlockTemplate = async (id: string) => {
|
||||||
|
try {
|
||||||
|
await databases.deleteDocument(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.timeBlockTemplate,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
timeblockTemplates.value = timeblockTemplates.value.filter(
|
||||||
|
(template) => template.$id !== id
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error deleting TimeBlockTemplate: ' + e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const updateTimeBlockTemplate = async (
|
||||||
|
template: TimeBlockTemplate,
|
||||||
|
id: string
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const response = await databases.updateDocument(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.timeBlockTemplate,
|
||||||
|
id,
|
||||||
|
{
|
||||||
|
name: template.name,
|
||||||
|
timeTuple: template.timeTuples.flat(2),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
timeblockTemplates.value = timeblockTemplates.value.map((b) =>
|
||||||
|
b.$id !== id ? b : (response as TimeBlockTemplate)
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error updating TimeBlockTemplate: ' + e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
reservations,
|
reservations,
|
||||||
|
timeblocks,
|
||||||
|
timeblockTemplates,
|
||||||
getBoatReservations,
|
getBoatReservations,
|
||||||
getConflictingReservations,
|
getConflictingReservations,
|
||||||
getTimeblocksForDate,
|
getTimeBlocksForDate,
|
||||||
|
getTimeBlocks,
|
||||||
|
fetchTimeBlocks,
|
||||||
|
fetchTimeBlockTemplates,
|
||||||
getNewId,
|
getNewId,
|
||||||
addOrCreateReservation,
|
addOrCreateReservation,
|
||||||
|
createTimeBlock,
|
||||||
|
createTimeBlockTemplate,
|
||||||
|
deleteTimeBlockTemplate,
|
||||||
|
updateTimeBlockTemplate,
|
||||||
isReservationOverlapped,
|
isReservationOverlapped,
|
||||||
isResourceTimeOverlapped,
|
isResourceTimeOverlapped,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Models } from 'appwrite';
|
||||||
import type { Boat } from './boat';
|
import type { Boat } from './boat';
|
||||||
|
|
||||||
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
|
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
|
||||||
@@ -16,17 +17,15 @@ export interface Reservation {
|
|||||||
e.g.: Should there be any qcalendar stuff in this store? Or should we have just JS Date
|
e.g.: Should there be any qcalendar stuff in this store? Or should we have just JS Date
|
||||||
objects in here? */
|
objects in here? */
|
||||||
|
|
||||||
export type timeTuple = [start: string, end: string];
|
export type TimeTuple = [start: string, end: string];
|
||||||
export interface Timeblock {
|
export type TimeBlock = Partial<Models.Document> & {
|
||||||
id: string;
|
|
||||||
boatId: string;
|
boatId: string;
|
||||||
start: string;
|
start: string;
|
||||||
end: string;
|
end: string;
|
||||||
selected?: false;
|
selected?: false;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface TimeBlockTemplate {
|
export type TimeBlockTemplate = Partial<Models.Document> & {
|
||||||
id: string;
|
|
||||||
name: string;
|
name: string;
|
||||||
blocks: timeTuple[];
|
timeTuples: TimeTuple[];
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const useTaskStore = defineStore('tasks', {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await databases.deleteDocument(
|
await databases.deleteDocument(
|
||||||
AppwriteIds.databaseId,
|
AppwriteIds.databaseId,
|
||||||
AppwriteIds.collection.task,
|
AppwriteIds.collection.task,
|
||||||
docId
|
docId
|
||||||
|
|||||||
6
tsconfig.vue-tsc.json
Normal file
6
tsconfig.vue-tsc.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"skipLibCheck": true
|
||||||
|
}
|
||||||
|
}
|
||||||
260
yarn.lock
260
yarn.lock
@@ -19,7 +19,7 @@
|
|||||||
jsonpointer "^5.0.0"
|
jsonpointer "^5.0.0"
|
||||||
leven "^3.1.0"
|
leven "^3.1.0"
|
||||||
|
|
||||||
"@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
|
"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
|
||||||
version "7.24.2"
|
version "7.24.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
|
||||||
integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
|
integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
|
||||||
@@ -1077,13 +1077,13 @@
|
|||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
"@quasar/app-vite@^1.7.4":
|
"@quasar/app-vite@^1.9.1":
|
||||||
version "1.8.5"
|
version "1.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/@quasar/app-vite/-/app-vite-1.8.5.tgz#f4345be5f22c9a5309ec98b40b5ca56e2e376f90"
|
resolved "https://registry.yarnpkg.com/@quasar/app-vite/-/app-vite-1.9.1.tgz#eb5a5e3fbc4bccf866c5555513df1fd986cb497d"
|
||||||
integrity sha512-OB5nU9qKIl3p7Ton9fLWkSQTv1I/7slfQl8izhZPPJZRY755Jn4Kz1exYUoEgJJ4cLSaUI/cpnVOL59pw53NEg==
|
integrity sha512-IC50irZQ3kPhyhdjG15+GRav4KOMN82uesApIg91HlxdMrLNw4FJrFbwVsRgJfFjS1dT1h2qK3bhYICb8goECg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@quasar/render-ssr-error" "^1.0.3"
|
"@quasar/render-ssr-error" "^1.0.3"
|
||||||
"@quasar/vite-plugin" "^1.3.3"
|
"@quasar/vite-plugin" "^1.7.0"
|
||||||
"@rollup/pluginutils" "^4.1.2"
|
"@rollup/pluginutils" "^4.1.2"
|
||||||
"@types/chrome" "^0.0.208"
|
"@types/chrome" "^0.0.208"
|
||||||
"@types/compression" "^1.7.2"
|
"@types/compression" "^1.7.2"
|
||||||
@@ -1122,14 +1122,14 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.16.11.tgz#84b1efb9097a6e58c3ebfdd5da83ac658056a35c"
|
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.16.11.tgz#84b1efb9097a6e58c3ebfdd5da83ac658056a35c"
|
||||||
integrity sha512-sbTBHOA+Hi7ah0P6qSm+xfRXqwJ94ct3NKA3Lkq3iNPYuHD7VXbSWtP2eA7Cu9Fd0WjVoPbngf6yFGg46U3IfQ==
|
integrity sha512-sbTBHOA+Hi7ah0P6qSm+xfRXqwJ94ct3NKA3Lkq3iNPYuHD7VXbSWtP2eA7Cu9Fd0WjVoPbngf6yFGg46U3IfQ==
|
||||||
|
|
||||||
"@quasar/quasar-app-extension-qcalendar@^4.0.0-beta.15":
|
"@quasar/quasar-app-extension-qcalendar@^4.0.0-beta.16":
|
||||||
version "4.0.0-beta.15"
|
version "4.0.0-beta.16"
|
||||||
resolved "https://registry.yarnpkg.com/@quasar/quasar-app-extension-qcalendar/-/quasar-app-extension-qcalendar-4.0.0-beta.15.tgz#1e85626a104c3a33083b7237f50ccf5f9048926a"
|
resolved "https://registry.yarnpkg.com/@quasar/quasar-app-extension-qcalendar/-/quasar-app-extension-qcalendar-4.0.0-beta.16.tgz#5b0bdfb04db59cf6017892ff91563dd9759c7bb5"
|
||||||
integrity sha512-i6hQkcP70LXLfVMPZMKQjSg3681gjZmASV3vq6ULzc0LhtBiPneLdVNNtH2itkWxAmaUj+1heQDI5Pa0F7VKLQ==
|
integrity sha512-Rj3KKjPFrE13cswlZAPcqdqi1YH9CeHMpWIw8xsNqdLhCoaRhMGbRas9fvHFLJOXpnsDaVwWINNgN/bBUyn99w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@quasar/quasar-ui-qcalendar" "^4.0.0-beta.15"
|
"@quasar/quasar-ui-qcalendar" "^4.0.0-beta.16"
|
||||||
|
|
||||||
"@quasar/quasar-ui-qcalendar@^4.0.0-beta.15":
|
"@quasar/quasar-ui-qcalendar@^4.0.0-beta.16":
|
||||||
version "4.0.0-beta.16"
|
version "4.0.0-beta.16"
|
||||||
resolved "https://registry.yarnpkg.com/@quasar/quasar-ui-qcalendar/-/quasar-ui-qcalendar-4.0.0-beta.16.tgz#90dca0962f1fe1068361f387893df6c5da7522e2"
|
resolved "https://registry.yarnpkg.com/@quasar/quasar-ui-qcalendar/-/quasar-ui-qcalendar-4.0.0-beta.16.tgz#90dca0962f1fe1068361f387893df6c5da7522e2"
|
||||||
integrity sha512-KVbFJD1HQp91tiklv+6XsG7bq8FKK6mhhnoVzmjgoyhUAEb9csfbDPbpegy1/FzXy3o0wITe6mmRZ8nbaiMEZg==
|
integrity sha512-KVbFJD1HQp91tiklv+6XsG7bq8FKK6mhhnoVzmjgoyhUAEb9csfbDPbpegy1/FzXy3o0wITe6mmRZ8nbaiMEZg==
|
||||||
@@ -1141,10 +1141,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
stack-trace "^1.0.0-pre2"
|
stack-trace "^1.0.0-pre2"
|
||||||
|
|
||||||
"@quasar/vite-plugin@^1.3.3":
|
"@quasar/vite-plugin@^1.7.0":
|
||||||
version "1.6.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@quasar/vite-plugin/-/vite-plugin-1.6.0.tgz#3b8f82656b14782fafe66b30dfac0775b87ab9dd"
|
resolved "https://registry.yarnpkg.com/@quasar/vite-plugin/-/vite-plugin-1.7.0.tgz#8873391ed7f69677948180f6eb14aa0821747478"
|
||||||
integrity sha512-LmbV76G1CwWZbrEQhqyZpkRQTJyO3xpW55aXY1zWN+JhyUeG77CcMCEWteBVnJ6I6ehUPFDC9ONd2+WlwH6rNQ==
|
integrity sha512-ia4w1n4DuPYm92MQLPNpMqLJID1WGGRyVGxkVeg8V+V25Vh3p9QBo++iuXR4sW/bCmzzx66Ko6VStsr1zp90GQ==
|
||||||
|
|
||||||
"@rollup/plugin-babel@^5.2.0":
|
"@rollup/plugin-babel@^5.2.0":
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
@@ -1464,6 +1464,28 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz#966a6279060eb2d9d1a02ea1a331af071afdcf9e"
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz#966a6279060eb2d9d1a02ea1a331af071afdcf9e"
|
||||||
integrity sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==
|
integrity sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==
|
||||||
|
|
||||||
|
"@volar/language-core@1.11.1", "@volar/language-core@~1.11.1":
|
||||||
|
version "1.11.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-1.11.1.tgz#ecdf12ea8dc35fb8549e517991abcbf449a5ad4f"
|
||||||
|
integrity sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==
|
||||||
|
dependencies:
|
||||||
|
"@volar/source-map" "1.11.1"
|
||||||
|
|
||||||
|
"@volar/source-map@1.11.1", "@volar/source-map@~1.11.1":
|
||||||
|
version "1.11.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-1.11.1.tgz#535b0328d9e2b7a91dff846cab4058e191f4452f"
|
||||||
|
integrity sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==
|
||||||
|
dependencies:
|
||||||
|
muggle-string "^0.3.1"
|
||||||
|
|
||||||
|
"@volar/typescript@~1.11.1":
|
||||||
|
version "1.11.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-1.11.1.tgz#ba86c6f326d88e249c7f5cfe4b765be3946fd627"
|
||||||
|
integrity sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==
|
||||||
|
dependencies:
|
||||||
|
"@volar/language-core" "1.11.1"
|
||||||
|
path-browserify "^1.0.1"
|
||||||
|
|
||||||
"@vue/compiler-core@3.4.25":
|
"@vue/compiler-core@3.4.25":
|
||||||
version "3.4.25"
|
version "3.4.25"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.25.tgz#691f59ee5014f6f2a2488fd4465f892e1e82f729"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.25.tgz#691f59ee5014f6f2a2488fd4465f892e1e82f729"
|
||||||
@@ -1475,6 +1497,17 @@
|
|||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
source-map-js "^1.2.0"
|
source-map-js "^1.2.0"
|
||||||
|
|
||||||
|
"@vue/compiler-core@3.4.26":
|
||||||
|
version "3.4.26"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.26.tgz#d507886520e83a6f8339ed55ed0b2b5d84b44b73"
|
||||||
|
integrity sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/parser" "^7.24.4"
|
||||||
|
"@vue/shared" "3.4.26"
|
||||||
|
entities "^4.5.0"
|
||||||
|
estree-walker "^2.0.2"
|
||||||
|
source-map-js "^1.2.0"
|
||||||
|
|
||||||
"@vue/compiler-dom@3.4.25":
|
"@vue/compiler-dom@3.4.25":
|
||||||
version "3.4.25"
|
version "3.4.25"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.25.tgz#b367e0c84e11d9e9f70beabdd6f6b2277fde375f"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.25.tgz#b367e0c84e11d9e9f70beabdd6f6b2277fde375f"
|
||||||
@@ -1483,6 +1516,14 @@
|
|||||||
"@vue/compiler-core" "3.4.25"
|
"@vue/compiler-core" "3.4.25"
|
||||||
"@vue/shared" "3.4.25"
|
"@vue/shared" "3.4.25"
|
||||||
|
|
||||||
|
"@vue/compiler-dom@^3.3.0":
|
||||||
|
version "3.4.26"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.26.tgz#acc7b788b48152d087d4bb9e655b795e3dbec554"
|
||||||
|
integrity sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==
|
||||||
|
dependencies:
|
||||||
|
"@vue/compiler-core" "3.4.26"
|
||||||
|
"@vue/shared" "3.4.26"
|
||||||
|
|
||||||
"@vue/compiler-sfc@3.4.25":
|
"@vue/compiler-sfc@3.4.25":
|
||||||
version "3.4.25"
|
version "3.4.25"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.25.tgz#ceab148f81571c8b251e8a8b75a9972addf1db8b"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.25.tgz#ceab148f81571c8b251e8a8b75a9972addf1db8b"
|
||||||
@@ -1511,6 +1552,21 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.1.tgz#7c14346383751d9f6ad4bea0963245b30220ef83"
|
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.1.tgz#7c14346383751d9f6ad4bea0963245b30220ef83"
|
||||||
integrity sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==
|
integrity sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==
|
||||||
|
|
||||||
|
"@vue/language-core@1.8.27":
|
||||||
|
version "1.8.27"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-1.8.27.tgz#2ca6892cb524e024a44e554e4c55d7a23e72263f"
|
||||||
|
integrity sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==
|
||||||
|
dependencies:
|
||||||
|
"@volar/language-core" "~1.11.1"
|
||||||
|
"@volar/source-map" "~1.11.1"
|
||||||
|
"@vue/compiler-dom" "^3.3.0"
|
||||||
|
"@vue/shared" "^3.3.0"
|
||||||
|
computeds "^0.0.1"
|
||||||
|
minimatch "^9.0.3"
|
||||||
|
muggle-string "^0.3.1"
|
||||||
|
path-browserify "^1.0.1"
|
||||||
|
vue-template-compiler "^2.7.14"
|
||||||
|
|
||||||
"@vue/reactivity@3.4.25":
|
"@vue/reactivity@3.4.25":
|
||||||
version "3.4.25"
|
version "3.4.25"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.25.tgz#74983b146e06ce3341d15382669350125375d36f"
|
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.25.tgz#74983b146e06ce3341d15382669350125375d36f"
|
||||||
@@ -1548,6 +1604,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.25.tgz#243ba8543e7401751e0ca319f75a80f153edd273"
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.25.tgz#243ba8543e7401751e0ca319f75a80f153edd273"
|
||||||
integrity sha512-k0yappJ77g2+KNrIaF0FFnzwLvUBLUYr8VOwz+/6vLsmItFp51AcxLL7Ey3iPd7BIRyWPOcqUjMnm7OkahXllA==
|
integrity sha512-k0yappJ77g2+KNrIaF0FFnzwLvUBLUYr8VOwz+/6vLsmItFp51AcxLL7Ey3iPd7BIRyWPOcqUjMnm7OkahXllA==
|
||||||
|
|
||||||
|
"@vue/shared@3.4.26", "@vue/shared@^3.3.0":
|
||||||
|
version "3.4.26"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.26.tgz#f17854fb1faf889854aed4b23b60e86a8cab6403"
|
||||||
|
integrity sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==
|
||||||
|
|
||||||
accepts@~1.3.5, accepts@~1.3.8:
|
accepts@~1.3.5, accepts@~1.3.8:
|
||||||
version "1.3.8"
|
version "1.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||||
@@ -1586,7 +1647,7 @@ ajv@^8.0.1, ajv@^8.6.0:
|
|||||||
require-from-string "^2.0.2"
|
require-from-string "^2.0.2"
|
||||||
uri-js "^4.2.2"
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
ansi-escapes@^4.2.1:
|
ansi-escapes@^4.2.1, ansi-escapes@^4.3.0:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
|
||||||
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
|
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
|
||||||
@@ -1620,10 +1681,10 @@ anymatch@~3.1.2:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
picomatch "^2.0.4"
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
appwrite@^13.0.0:
|
appwrite@^14.0.1:
|
||||||
version "13.0.2"
|
version "14.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/appwrite/-/appwrite-13.0.2.tgz#225f38225a012bb7dc2a70ea777fae363f9188fa"
|
resolved "https://registry.yarnpkg.com/appwrite/-/appwrite-14.0.1.tgz#8a7e653597b370f0b9472c007e29ca0be8af182a"
|
||||||
integrity sha512-ISkUXO8pojDWGx5XqknCwwikgAQye4Ni4FL+Ns8Hg42rXeyehLlmvHGjFOmpS+odT6nsWYUaXzVjV4SZuDorog==
|
integrity sha512-ORlvfqVif/2K3qKGgGiGfMP33Zwm+xxB1fIC4Lm3sojOkDd8u8YvgKQO0Meq5UXb8Dc0Rl66Z7qlGBAfRQ04bA==
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-fetch "3.1.5"
|
cross-fetch "3.1.5"
|
||||||
isomorphic-form-data "2.0.0"
|
isomorphic-form-data "2.0.0"
|
||||||
@@ -1936,7 +1997,7 @@ chardet@^0.7.0:
|
|||||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||||
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
||||||
|
|
||||||
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3:
|
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1, chokidar@^3.5.3:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
||||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||||
@@ -2044,6 +2105,11 @@ commander@^2.20.0:
|
|||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
|
|
||||||
|
commander@^8.0.0:
|
||||||
|
version "8.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||||
|
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||||
|
|
||||||
common-tags@^1.8.0:
|
common-tags@^1.8.0:
|
||||||
version "1.8.2"
|
version "1.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
|
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
|
||||||
@@ -2079,6 +2145,11 @@ compression@^1.7.4:
|
|||||||
safe-buffer "5.1.2"
|
safe-buffer "5.1.2"
|
||||||
vary "~1.1.2"
|
vary "~1.1.2"
|
||||||
|
|
||||||
|
computeds@^0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/computeds/-/computeds-0.0.1.tgz#215b08a4ba3e08a11ff6eee5d6d8d7166a97ce2e"
|
||||||
|
integrity sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
@@ -2194,6 +2265,11 @@ data-view-byte-offset@^1.0.0:
|
|||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
is-data-view "^1.0.1"
|
is-data-view "^1.0.1"
|
||||||
|
|
||||||
|
de-indent@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||||
|
integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
@@ -2904,7 +2980,7 @@ fast-glob@3.2.12:
|
|||||||
merge2 "^1.3.0"
|
merge2 "^1.3.0"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
|
|
||||||
fast-glob@^3.2.9:
|
fast-glob@^3.2.7, fast-glob@^3.2.9:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
|
||||||
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
|
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
|
||||||
@@ -3240,6 +3316,11 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.2"
|
function-bind "^1.1.2"
|
||||||
|
|
||||||
|
he@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
|
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||||
|
|
||||||
html-minifier-terser@^7.2.0:
|
html-minifier-terser@^7.2.0:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz#18752e23a2f0ed4b0f550f217bb41693e975b942"
|
resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz#18752e23a2f0ed4b0f550f217bb41693e975b942"
|
||||||
@@ -3846,7 +3927,7 @@ mimic-fn@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||||
|
|
||||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||||
@@ -3860,6 +3941,13 @@ minimatch@^5.0.1, minimatch@^5.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^2.0.1"
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
|
minimatch@^9.0.3:
|
||||||
|
version "9.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51"
|
||||||
|
integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
minimist@^1.2.6:
|
minimist@^1.2.6:
|
||||||
version "1.2.8"
|
version "1.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||||
@@ -3880,6 +3968,11 @@ ms@2.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
|
muggle-string@^0.3.1:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.3.1.tgz#e524312eb1728c63dd0b2ac49e3282e6ed85963a"
|
||||||
|
integrity sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==
|
||||||
|
|
||||||
mute-stream@0.0.8:
|
mute-stream@0.0.8:
|
||||||
version "0.0.8"
|
version "0.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
||||||
@@ -3935,6 +4028,13 @@ normalize-range@^0.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||||
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
||||||
|
|
||||||
|
npm-run-path@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
||||||
|
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
|
||||||
|
dependencies:
|
||||||
|
path-key "^3.0.0"
|
||||||
|
|
||||||
nth-check@^2.1.1:
|
nth-check@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
||||||
@@ -4071,6 +4171,11 @@ pascal-case@^3.1.2:
|
|||||||
no-case "^3.0.4"
|
no-case "^3.0.4"
|
||||||
tslib "^2.0.3"
|
tslib "^2.0.3"
|
||||||
|
|
||||||
|
path-browserify@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
|
||||||
|
integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
|
||||||
|
|
||||||
path-exists@^4.0.0:
|
path-exists@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||||
@@ -4081,7 +4186,7 @@ path-is-absolute@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||||
|
|
||||||
path-key@^3.1.0:
|
path-key@^3.0.0, path-key@^3.1.0:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||||
@@ -4186,10 +4291,10 @@ qs@6.11.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
side-channel "^1.0.4"
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
quasar@^2.15.2:
|
quasar@^2.16.0:
|
||||||
version "2.15.4"
|
version "2.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.15.4.tgz#764bd886671f98d75f682b1df917adaf7dc4a849"
|
resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.16.0.tgz#c168a3a135fb67c39bd1e8e5fa82880a7dd2a412"
|
||||||
integrity sha512-6Rtj0KrsVA0IV9zMZ6R7U7hOpwLS/6E06hsISVHRPn21KEm3XAwHdvy9xWz5kwqWraHRlcisFSDu/KPL4VQK1w==
|
integrity sha512-j0MSuGuIAOQdtg/zEn/7jMIZjqS00Kp4t4h/0+HCqEkf6mxtwOJoaC7s0rIC+6AVYIErCTiXrp7Hmkt32Hom1w==
|
||||||
|
|
||||||
queue-microtask@^1.2.2:
|
queue-microtask@^1.2.2:
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
@@ -4457,7 +4562,7 @@ semver@^6.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.6.0:
|
semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.5.0, semver@^7.5.4, semver@^7.6.0:
|
||||||
version "7.6.0"
|
version "7.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
|
||||||
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
|
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
|
||||||
@@ -4796,6 +4901,11 @@ through@^2.3.6:
|
|||||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||||
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
|
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
|
||||||
|
|
||||||
|
tiny-invariant@^1.1.0:
|
||||||
|
version "1.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
|
||||||
|
integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
|
||||||
|
|
||||||
tmp@^0.0.33:
|
tmp@^0.0.33:
|
||||||
version "0.0.33"
|
version "0.0.33"
|
||||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||||
@@ -4923,10 +5033,10 @@ typed-array-length@^1.0.6:
|
|||||||
is-typed-array "^1.1.13"
|
is-typed-array "^1.1.13"
|
||||||
possible-typed-array-names "^1.0.0"
|
possible-typed-array-names "^1.0.0"
|
||||||
|
|
||||||
typescript@^4.5.4:
|
typescript@~5.3.0:
|
||||||
version "4.9.5"
|
version "5.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
|
||||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
|
||||||
|
|
||||||
unbox-primitive@^1.0.2:
|
unbox-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@@ -5018,6 +5128,27 @@ vary@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||||
|
|
||||||
|
vite-plugin-checker@^0.6.4:
|
||||||
|
version "0.6.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.6.4.tgz#aca186ab605aa15bd2c5dd9cc6d7c8fdcbe214ec"
|
||||||
|
integrity sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.12.13"
|
||||||
|
ansi-escapes "^4.3.0"
|
||||||
|
chalk "^4.1.1"
|
||||||
|
chokidar "^3.5.1"
|
||||||
|
commander "^8.0.0"
|
||||||
|
fast-glob "^3.2.7"
|
||||||
|
fs-extra "^11.1.0"
|
||||||
|
npm-run-path "^4.0.1"
|
||||||
|
semver "^7.5.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
tiny-invariant "^1.1.0"
|
||||||
|
vscode-languageclient "^7.0.0"
|
||||||
|
vscode-languageserver "^7.0.0"
|
||||||
|
vscode-languageserver-textdocument "^1.0.1"
|
||||||
|
vscode-uri "^3.0.2"
|
||||||
|
|
||||||
vite@^2.9.13:
|
vite@^2.9.13:
|
||||||
version "2.9.18"
|
version "2.9.18"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.18.tgz#74e2a83b29da81e602dac4c293312cc575f091c7"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.18.tgz#74e2a83b29da81e602dac4c293312cc575f091c7"
|
||||||
@@ -5030,6 +5161,50 @@ vite@^2.9.13:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
vscode-jsonrpc@6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz#108bdb09b4400705176b957ceca9e0880e9b6d4e"
|
||||||
|
integrity sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==
|
||||||
|
|
||||||
|
vscode-languageclient@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz#b505c22c21ffcf96e167799757fca07a6bad0fb2"
|
||||||
|
integrity sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==
|
||||||
|
dependencies:
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
semver "^7.3.4"
|
||||||
|
vscode-languageserver-protocol "3.16.0"
|
||||||
|
|
||||||
|
vscode-languageserver-protocol@3.16.0:
|
||||||
|
version "3.16.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz#34135b61a9091db972188a07d337406a3cdbe821"
|
||||||
|
integrity sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==
|
||||||
|
dependencies:
|
||||||
|
vscode-jsonrpc "6.0.0"
|
||||||
|
vscode-languageserver-types "3.16.0"
|
||||||
|
|
||||||
|
vscode-languageserver-textdocument@^1.0.1:
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz#0822a000e7d4dc083312580d7575fe9e3ba2e2bf"
|
||||||
|
integrity sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==
|
||||||
|
|
||||||
|
vscode-languageserver-types@3.16.0:
|
||||||
|
version "3.16.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247"
|
||||||
|
integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==
|
||||||
|
|
||||||
|
vscode-languageserver@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz#49b068c87cfcca93a356969d20f5d9bdd501c6b0"
|
||||||
|
integrity sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==
|
||||||
|
dependencies:
|
||||||
|
vscode-languageserver-protocol "3.16.0"
|
||||||
|
|
||||||
|
vscode-uri@^3.0.2:
|
||||||
|
version "3.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f"
|
||||||
|
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
|
||||||
|
|
||||||
vue-demi@>=0.14.5:
|
vue-demi@>=0.14.5:
|
||||||
version "0.14.7"
|
version "0.14.7"
|
||||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.7.tgz#8317536b3ef74c5b09f268f7782e70194567d8f2"
|
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.7.tgz#8317536b3ef74c5b09f268f7782e70194567d8f2"
|
||||||
@@ -5055,6 +5230,23 @@ vue-router@4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@vue/devtools-api" "^6.5.1"
|
"@vue/devtools-api" "^6.5.1"
|
||||||
|
|
||||||
|
vue-template-compiler@^2.7.14:
|
||||||
|
version "2.7.16"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz#c81b2d47753264c77ac03b9966a46637482bb03b"
|
||||||
|
integrity sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==
|
||||||
|
dependencies:
|
||||||
|
de-indent "^1.0.2"
|
||||||
|
he "^1.2.0"
|
||||||
|
|
||||||
|
vue-tsc@^1.8.22:
|
||||||
|
version "1.8.27"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-1.8.27.tgz#feb2bb1eef9be28017bb9e95e2bbd1ebdd48481c"
|
||||||
|
integrity sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==
|
||||||
|
dependencies:
|
||||||
|
"@volar/typescript" "~1.11.1"
|
||||||
|
"@vue/language-core" "1.8.27"
|
||||||
|
semver "^7.5.4"
|
||||||
|
|
||||||
vue@3:
|
vue@3:
|
||||||
version "3.4.25"
|
version "3.4.25"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.25.tgz#e59d4ed36389647b52ff2fd7aa84bb6691f4205b"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.25.tgz#e59d4ed36389647b52ff2fd7aa84bb6691f4205b"
|
||||||
|
|||||||
Reference in New Issue
Block a user