Compare commits

26 Commits

Author SHA1 Message Date
2d585d499e Final build working
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m50s
2024-01-01 18:56:12 -05:00
284d5ffcb4 Move env file creation to the right place
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m2s
2024-01-01 18:48:58 -05:00
27a476ae00 Test
Some checks failed
Build BAB Application Deployment Artifact / build (push) Has been cancelled
2024-01-01 18:47:11 -05:00
ee7f79550c Fix name of .env file
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m1s
2024-01-01 18:42:57 -05:00
2ef801905b Update envfile
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m3s
2024-01-01 18:30:54 -05:00
752421c9fc Add the env file, so app builds with correct API info
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 3m3s
2024-01-01 17:39:11 -05:00
ce169f6a61 reorder install
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m56s
2024-01-01 13:42:03 -05:00
622b9fc82d Install dependencies with yarn
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m58s
2024-01-01 13:19:10 -05:00
275f23c421 Remove npm package-lock.json
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 59s
2024-01-01 13:12:48 -05:00
88ed4caf5b Update all yarn packages
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m2s
2024-01-01 13:10:30 -05:00
346e395e15 Build tar, as all the dates are messed up with zip
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m23s
2023-12-31 15:32:09 -05:00
f30848803b Update Boat selection component
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m33s
2023-12-31 15:04:53 -05:00
96dab93483 Fix URL Path
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m29s
2023-12-29 23:58:04 -05:00
a6abee1ddf Enable verbosity for debugging
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m29s
2023-12-29 12:45:19 -05:00
b20f2bffd6 Remove Secret
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m29s
2023-12-29 12:33:36 -05:00
f6689cbc5c Change url from secret to var
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m37s
2023-12-29 12:19:39 -05:00
8383605115 Disable SSL verification
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m31s
2023-12-29 12:14:20 -05:00
f69614d5c7 Fix URL again
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m40s
2023-12-29 12:06:24 -05:00
f7902011cc Fix action url
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 5s
2023-12-29 12:04:21 -05:00
e86876ba69 Update Actions
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 5s
2023-12-29 11:29:31 -05:00
cd6f2e3ba2 Updates to selection component
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m27s
2023-12-29 09:22:28 -05:00
66e2169f45 Adapting to time blocks for bookings
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m11s
2023-12-23 11:39:54 -05:00
489cc2646b Try v4 of the upload-artifact action
Some checks failed
Build BAB Application Deployment Artifact / build (push) Failing after 2m15s
2023-12-20 14:23:42 -05:00
295f1f7449 Don't bother tar/gz, as it's adding an extra, unnecessary step
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m20s
2023-12-20 13:59:50 -05:00
33a1bc24f6 Test run number addition to build
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m21s
2023-12-20 12:27:27 -05:00
d18780bb21 Begin implementation of timeblocks. Update workflow to build on devel branch
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m21s
2023-12-20 10:48:51 -05:00
8 changed files with 850 additions and 10062 deletions

View File

@@ -1,9 +1,10 @@
name: Build BAB Application Deployment Artifact
run-name: ${{ gitea.actor }} is building an artifact 🚀
run-name: ${{ gitea.actor }} is building a BAB App artifact 🚀
on:
push:
branches:
- main
- devel
jobs:
build:
@@ -15,21 +16,35 @@ jobs:
uses: actions/setup-node@v2
with:
node-version: '20.x'
- name: Install dependencies
run: npm install
- name: Install yarn
run: npm install --global yarn
- name: Install yarn dependencies
run: yarn install
- name: Install Quasar CLI
run: npm install -g @quasar/cli
run: yarn global add @quasar/cli
- name: Create env file
run: |
echo "${{ vars.ENV_FILE }}" > .env.local
- name: Show env file
run: |
/bin/cat .env.local
- name: Build Project
run: quasar build -m pwa
- name: Get Version Number
id: get_version
run: echo "::set-output name=VERSION::$(node -p "require('./package.json').version")"
- name: Create Tarball of Build
run: tar -czvf build-${{ steps.get_version.outputs.VERSION }}.tar.gz dist/pwa
- name: Upload Tarball
- name: Tarfile
run: |
cd dist/pwa
tar czf ../../build-${{ steps.get_version.outputs.VERSION }}.tar.gz .
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: build-artifact-${{ steps.get_version.outputs.VERSION }}
name: build-artifact-${{ steps.get_version.outputs.VERSION }}.${{ gitea.run_number }}
path: build-${{ steps.get_version.outputs.VERSION }}.tar.gz
- name: Trigger Ansible Deploy Playbook
uses: https://github.com/distributhor/workflow-webhook@v3
with:
webhook_url: ${{ vars.WEBHOOK_URL }}
verbose: true
data: '{ "artifact_url": "${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id}}/artifacts/build-artifact-${{ steps.get_version.outputs.VERSION }}.${{ gitea.run_number }}" }'

9655
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@
"@quasar/extras": "^1.16.4",
"appwrite": "^13.0.0",
"pinia": "^2.1.7",
"quasar": "^2.6.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0"
},
@@ -32,6 +31,7 @@
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-vue": "^9.0.0",
"prettier": "^2.5.1",
"quasar": "^2.14.2",
"typescript": "^4.5.4",
"workbox-build": "^7.0.0",
"workbox-cacheable-response": "^7.0.0",

View File

@@ -1,3 +1,4 @@
<!-- This has been abandoned for now. Going to block-based booking. Will probably need the schedule viewer functionality at some point in the future, though -->
<template>
<q-card-section>
<div class="text-caption text-justify">
@@ -117,6 +118,16 @@ import { date } from 'quasar';
import { computed } from 'vue';
import type { StatusTypes } from 'src/stores/schedule';
type EventData = {
event: object;
scope: {
timestamp: object;
columnindex: number;
activeDate: boolean;
droppable: boolean;
};
};
const durations = [1, 1.5, 2, 2.5, 3, 3.5, 4];
type ResourceIntervalScope = {
@@ -202,14 +213,16 @@ function onPrev() {
function onNext() {
calendar.value.next();
}
function onClickDate(data) {
return;
function onClickDate(data: EventData) {
return data;
}
function onClickTime(data) {
function onClickTime(data: EventData) {
// TODO: Add a duration picker, here.
emit('onClickTime', data);
}
function onUpdateDuration(value) {
function onUpdateDuration(value: EventData) {
emit('onUpdateDuration', value);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function

View File

@@ -0,0 +1,193 @@
<template>
<q-card-section style="max-width: 320px">
<div class="text-caption">
Use the calendar to pick a date. Select an available boat and timeslot
below.
</div>
<div
style="
width: 100%;
max-width: 320px;
display: flex;
justify-content: center;
"
>
<div
style="
width: 50%;
max-width: 350px;
display: flex;
justify-content: space-between;
"
>
<span
class="q-button"
style="cursor: pointer; user-select: none"
@click="onPrev"
>&lt;</span
>
{{ formattedMonth }}
<span
class="q-button"
style="cursor: pointer; user-select: none"
@click="onNext"
>&gt;</span
>
</div>
</div>
<div
style="
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
"
>
<div style="display: flex; width: 100%">
<q-calendar-month
ref="calendar"
v-model="selectedDate"
:disabled-before="disabledBefore"
:disabled-days="disabledDays()"
animated
bordered
mini-mode
date-type="rounded"
@click-date="onClickDate"
@change="onChange"
/>
</div></div
></q-card-section>
<q-card-section style="max-width: 320px">
<div v-for="boat in boatStore.boats" :key="boat.name">
<q-item-label header>{{ boat.name }}</q-item-label>
<q-item>
<q-item-section>
<q-option-group
:options="boatoptions(boat)"
type="radio"
v-model="selectedBoatTime"
>
<template v-slot:label="opt">
<div class="row items-center">
{{ opt.label }} &nbsp;
<span class="text-caption" v-if="opt.disable"
>Reserved by {{ opt.user }}</span
>
</div></template
>
</q-option-group>
</q-item-section>
</q-item>
</div>
</q-card-section>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import {
today,
parseTimestamp,
addToDate,
Timestamp,
} from '@quasar/quasar-ui-qcalendar';
import { Boat, useBoatStore } from 'src/stores/boat';
import { useScheduleStore, Timeblock } from 'src/stores/schedule';
import { computed } from 'vue';
import { date } from 'quasar';
type EventData = {
event: object;
scope: {
timestamp: object;
columnindex: number;
activeDate: boolean;
droppable: boolean;
};
};
const calendar = ref();
const boatStore = useBoatStore();
const scheduleStore = useScheduleStore();
const selectedDate = ref(today());
const selectedBoatTime = ref();
const formattedMonth = computed(() => {
const date = new Date(selectedDate.value);
return monthFormatter()?.format(date);
});
const disabledBefore = computed(() => {
const todayTs = parseTimestamp(today()) as Timestamp;
return addToDate(todayTs, { day: -1 }).date;
});
function monthFormatter() {
try {
return new Intl.DateTimeFormat('en-CA' || undefined, {
month: 'long',
timeZone: 'UTC',
});
} catch (e) {
//
}
}
const disabledDays = () => {
// Placeholder. This should actually compute days when boats aren't available.
const days = [];
const todayTs = parseTimestamp(today()) as Timestamp;
days.push(addToDate(todayTs, { day: 2 }).date);
return days;
};
const boatoptions = (boat: Boat) => {
const options = useScheduleStore()
.getTimeblocksForDate(date.extractDate(selectedDate.value, 'YYYY-MM-DD'))
.map((x: Timeblock) => {
const conflicts = getConflicts(x, boat);
return {
label: x.start.time + ' to ' + x.end.time,
value: boat.id + ':' + x.start.time,
disable: conflicts.length > 0,
user: conflicts[0]?.user,
boat: boat,
timeblock: x,
};
});
return options;
};
const emit = defineEmits(['onClickTime', 'onUpdateDuration']);
function onPrev() {
calendar.value.prev();
}
function onNext() {
calendar.value.next();
}
function onClickDate(data: EventData) {
return data;
}
function onChange(data: EventData) {
return data;
}
const getConflicts = (timeblock: Timeblock, boat: Boat) => {
const start = date.buildDate({
hour: timeblock.start.hour,
minute: timeblock.start.minute,
second: 0,
millisecond: 0,
});
const end = date.buildDate({
hour: timeblock.end.hour,
minute: timeblock.end.minute,
second: 0,
millisecond: 0,
});
return scheduleStore.getConflictingReservations(boat, start, end);
};
</script>

View File

@@ -21,14 +21,8 @@
:caption="bookingSummary"
>
<q-separator />
<resource-schedule-viewer-component
@on-click-time="onClickTime"
@on-update-duration="
(value) => {
bookingForm.duration = value;
}
"
/>
<boat-selection />
<q-banner
rounded
class="bg-warning text-grey-10"
@@ -78,7 +72,7 @@ import { reactive, ref, computed, watch } from 'vue';
import { useAuthStore } from 'src/stores/auth';
import { Boat, useBoatStore } from 'src/stores/boat';
import { Dialog, date } from 'quasar';
import ResourceScheduleViewerComponent from 'src/components/ResourceScheduleViewerComponent.vue';
import BoatSelection from 'src/components/scheduling/BoatSelection.vue';
import { makeDateTime } from '@quasar/quasar-ui-qcalendar';
import { useScheduleStore, Reservation } from 'src/stores/schedule';
@@ -113,7 +107,7 @@ watch(bookingForm, (b, a) => {
status: 'tentative',
};
//TODO: Turn this into a validator.
scheduleStore.isOverlapped(newRes)
scheduleStore.isReservationOverlapped(newRes)
? Dialog.create({ message: 'This booking overlaps another!' })
: scheduleStore.addOrCreateReservation(newRes);
});

View File

@@ -3,9 +3,15 @@ import { ref } from 'vue';
import { Boat, useBoatStore } from './boat';
import { date } from 'quasar';
import { DateOptions } from 'quasar';
import {
Timestamp,
parseTimestamp,
TimestampArray,
} from '@quasar/quasar-ui-qcalendar';
import { timeStamp } from 'console';
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
export interface Reservation {
export type Reservation = {
id: number;
user: string;
start: Date;
@@ -13,15 +19,39 @@ export interface Reservation {
resource: Boat;
reservationDate: Date;
status?: StatusTypes;
}
};
function getSampleData(): Reservation[] {
export type Timeblock = {
start: Timestamp;
end: Timestamp;
};
const sampleBlocks = [
{
start: { time: '09:00', hour: 9, minute: 0, hasDay: false, hasTime: true },
end: { time: '12:00', hour: 12, minute: 0, hasDay: false, hasTime: true },
},
{
start: { time: '12:00', hour: 12, minute: 0, hasDay: false, hasTime: true },
end: { time: '15:00', hour: 15, minute: 0, hasDay: false, hasTime: true },
},
{
start: { time: '15:00', hour: 15, minute: 0, hasDay: false, hasTime: true },
end: { time: '18:00', hour: 18, minute: 0, hasDay: false, hasTime: true },
},
{
start: { time: '18:00', hour: 18, minute: 0, hasDay: false, hasTime: true },
end: { time: '21:00', hour: 21, minute: 0, hasDay: false, hasTime: true },
},
] as Timeblock[];
function getSampleReservations(): Reservation[] {
const sampleData = [
{
id: 1,
user: 'John Smith',
start: '12:00',
end: '14:00',
end: '15:00',
boat: 1,
status: 'confirmed',
},
@@ -29,31 +59,31 @@ function getSampleData(): Reservation[] {
id: 2,
user: 'Bob Barker',
start: '18:00',
end: '20:00',
end: '21:00',
boat: 1,
status: 'confirmed',
},
{
id: 3,
user: 'Peter Parker',
start: '8:00',
end: '10:00',
start: '9:00',
end: '12:00',
boat: 2,
status: 'tentative',
},
{
id: 4,
user: 'Vince McMahon',
start: '13:00',
end: '17:00',
start: '15:00',
end: '18:00',
boat: 2,
status: 'pending',
},
{
id: 5,
user: 'Heather Graham',
start: '06:00',
end: '09:00',
start: '09:00',
end: '12:00',
boat: 3,
status: 'confirmed',
},
@@ -61,7 +91,7 @@ function getSampleData(): Reservation[] {
id: 6,
user: 'Lawrence Fishburne',
start: '18:00',
end: '20:00',
end: '21:00',
boat: 3,
},
];
@@ -71,7 +101,12 @@ function getSampleData(): Reservation[] {
return x.split(':');
};
const makeOpts = (x: string[]): DateOptions => {
return { hour: parseInt(x[0]), minute: parseInt(x[1]) };
return {
hour: parseInt(x[0]),
minute: parseInt(x[1]),
seconds: 0,
milliseconds: 0,
};
};
return sampleData.map((entry): Reservation => {
@@ -83,13 +118,18 @@ function getSampleData(): Reservation[] {
end: date.adjustDate(now, makeOpts(splitTime(entry.end))),
resource: boat,
reservationDate: now,
status: entry.status,
status: entry.status as StatusTypes,
};
});
}
export const useScheduleStore = defineStore('schedule', () => {
const reservations = ref<Reservation[]>(getSampleData());
// TODO: Implement functions to dynamically pull this data.
const reservations = ref<Reservation[]>(getSampleReservations());
const timeblocks = sampleBlocks;
const getTimeblocksForDate = (date: Date): Timeblock[] => timeblocks;
const getBoatReservations = (
boat: number | string,
curDate: Date
@@ -106,15 +146,30 @@ export const useScheduleStore = defineStore('schedule', () => {
});
};
const isOverlapped = (res: Reservation) => {
const lapped = reservations.value.filter(
const getConflictingReservations = (
resource: Boat,
start: Date,
end: Date
): Reservation[] => {
const overlapped = reservations.value.filter(
(entry: Reservation) =>
entry.id != res.id &&
entry.resource == res.resource &&
((entry.start <= res.start && entry.end > res.start) ||
(entry.end >= res.end && entry.start <= res.end))
entry.resource.id == resource.id &&
entry.start < end &&
entry.end > start
);
return lapped.length > 0;
return overlapped;
};
const isResourceTimeOverlapped = (
resource: Boat,
start: Date,
end: Date
): boolean => {
return getConflictingReservations(resource, start, end).length > 0;
};
const isReservationOverlapped = (res: Reservation): boolean => {
return isResourceTimeOverlapped(res.resource, res.start, res.end);
};
const getNewId = () => {
@@ -134,8 +189,11 @@ export const useScheduleStore = defineStore('schedule', () => {
return {
reservations,
getBoatReservations,
getConflictingReservations,
getTimeblocksForDate,
getNewId,
addOrCreateReservation,
isOverlapped,
isReservationOverlapped,
isResourceTimeOverlapped,
};
});

892
yarn.lock

File diff suppressed because it is too large Load Diff