Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LCSD-7141: Merge develop to master for UATL: Convert User Entered Time into PST #4205

Merged
merged 5 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .github/workflows/cd-portal-build-dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Portal & API - Development build
on:
workflow_dispatch:
defaults:
run:
working-directory: "."

jobs:

openshift-compile-client-app:
name: Compile Client App
# needs: []
runs-on: ubuntu-latest
steps:
- name: OpenShift Build
env:
BUILD_NAME: cllc-public-angular
NAMESPACE: ${{ secrets.OpenShiftBuildNamespace }}
uses: redhat-developer/[email protected]
with:
version: "latest"
openshift_server_url: ${{ secrets.OpenShiftServerURL }}
parameters: '{"apitoken": "${{ secrets.OpenShiftToken }}", "acceptUntrustedCerts": "true"}'
cmd: |
'version'
'project ${NAMESPACE}'
'start-build ${BUILD_NAME} -n ${NAMESPACE} -w --follow'

openshift-build-client-image:
name: Build Client Nginx Image
needs: openshift-compile-client-app
runs-on: ubuntu-latest
steps:
- name: OpenShift Build
env:
BUILD_NAME: cllc-public-frontend
NAMESPACE: ${{ secrets.OpenShiftBuildNamespace }}
uses: redhat-developer/[email protected]
with:
version: "latest"
openshift_server_url: ${{ secrets.OpenShiftServerURL }}
parameters: '{"apitoken": "${{ secrets.OpenShiftToken }}", "acceptUntrustedCerts": "true"}'
cmd: |
'version'
'project ${NAMESPACE}'
'start-build ${BUILD_NAME} -n ${NAMESPACE} -w --follow'

openshift-build-client-api:
name: Build Client API
# needs: []
runs-on: ubuntu-latest
steps:
- name: OpenShift Build
env:
BUILD_NAME: cllc-public-api
NAMESPACE: ${{ secrets.OpenShiftBuildNamespace }}
uses: redhat-developer/[email protected]
with:
version: "latest"
openshift_server_url: ${{ secrets.OpenShiftServerURL }}
parameters: '{"apitoken": "${{ secrets.OpenShiftToken }}", "acceptUntrustedCerts": "true"}'
cmd: |
'version'
'project ${NAMESPACE}'
'start-build ${BUILD_NAME} -n ${NAMESPACE} -w --follow'

openshift-tag-images:
name: Tag Images
needs: [openshift-build-client-image, openshift-build-client-api]
runs-on: ubuntu-latest
steps:
- name: OpenShift Tag
env:
BUILD_NAME: cllc-public-api
NAMESPACE: ${{ secrets.OpenShiftBuildNamespace }}
uses: redhat-developer/[email protected]
with:
version: "latest"
openshift_server_url: ${{ secrets.OpenShiftServerURL }}
parameters: '{"apitoken": "${{ secrets.OpenShiftToken }}", "acceptUntrustedCerts": "true"}'
cmd: |
'version'
'project ${NAMESPACE}'
'tag -n ${NAMESPACE} cllc-public-api:latest cllc-public-api:dev'
'tag -n ${NAMESPACE} cllc-public-frontend:latest cllc-public-frontend:dev'
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.env
.DS_Store


secrets.json
/cllc-interfaces-test/SharePoint/Properties/launchSettings.json
cllc-public-app/ClientApp/e2e-reports
/functional-tests/bin
Expand Down
1 change: 1 addition & 0 deletions cllc-public-app/ClientApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"leaflet": "^1.7.1",
"lodash": "^4.17.21",
"material-design-icons": "^3.0.1",
"moment-timezone": "^0.5.45",
"mygovbc-bootstrap-theme": "^0.4.1",
"ng-busy": "^12.0.2",
"ng2-currency-mask": "^12.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ export class PoliceSummaryComponent extends FormBase implements OnInit {
if (loc.eventDates?.length > 0) {
const formatterdDates = [];
loc.eventDates.forEach(ed => {
ed = Object.assign(new SepSchedule(null), ed);
ed = Object.assign(new SepSchedule(null, null), ed);
formatterdDates.push({ ed, ...ed.toEventFormValue() });
});
loc.eventDates = formatterdDates;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,22 @@ <h3>Event Date(s)</h3>
</td>
</tr>
<tr>
<td>
<app-field label="Time Zone" errorMessage="Please select a value" [valid]="!item.get('isPacificTimeZone').touched || item.get('isPacificTimeZone').valid">
<div class="form-check">
<input class="form-check-input" type="radio" formControlName="isPacificTimeZone" [value]="true" id="pacific">
<label class="form-check-label" for="pacific">
&nbsp;America / Vancouver
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" formControlName="isPacificTimeZone" [value]="false" id="mountain">
<label class="form-check-label" for="mountain">
&nbsp;America / Edmonton
</label>
</div>
</app-field>
</td>
<td class="text-right">
<label>Liquor will be served:</label>
</td>
Expand All @@ -323,8 +339,8 @@ <h3>Event Date(s)</h3>
<select class="form-control"
formControlName="serviceStartValue">
<option value=""></option>
<option [value]="item.value" *ngFor="let item of timeSlots">
{{item.name}}
<option [value]="timeSlot.value" *ngFor="let timeSlot of timeSlots">
{{timeSlot.name}}
</option>
</select>
</app-field>
Expand All @@ -334,8 +350,8 @@ <h3>Event Date(s)</h3>
[valid]="!item.get('serviceEndValue').touched || item.get('serviceEndValue').valid">
<select class="form-control" formControlName="serviceEndValue">
<option value=""></option>
<option [value]="item.value" *ngFor="let item of timeSlots">
{{item.name}}
<option [value]="timeSlot.value" *ngFor="let timeSlot of timeSlots">
{{timeSlot.name}}
</option>
</select>
</app-field>
Expand All @@ -346,12 +362,11 @@ <h3>Event Date(s)</h3>
<tr>
<td colspan="4">
<div>
<button (click)="checkTimeZone()">Is the event located outside of Pacific Standard Time? </button>
<app-error-alert *ngIf="!isPacificTimeZone">
<app-error-notice *ngIf="!item.get('isPacificTimeZone').value">
<p>
If the area you’re applying from or if the event is located outside of PST, please note the time on your permit may not accurately reflect the time your event is scheduled to start. Please contact the LCRB team at <a href="mailto:[email protected]">[email protected]</a>
Please note that the time on the license you receive will be in America / Vancouver time zone. For more information please contact the LCRB team at <a href="mailto:[email protected]">[email protected]</a>
</p>
</app-error-alert>
</app-error-notice>
</div>
</td>
</tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class EventComponent extends FormBase implements OnInit {
validationMessages: string[];
previewCities: AutoCompleteItem[] = [];
autocompleteCities: AutoCompleteItem[] = [];
isPacificTimeZone: boolean;
isPacificTimeZone: boolean = true;
isOpen: boolean[][] = [];
get minDate() {
return new Date();
Expand Down Expand Up @@ -86,7 +86,7 @@ export class EventComponent extends FormBase implements OnInit {
}

ngOnInit(): void {
this.isPacificTimeZone = true;

// create a form for the basic details
this.form = this.fb.group({
sepCity: ["", [Validators.required, Validators.minLength(2)]],
Expand Down Expand Up @@ -122,9 +122,7 @@ export class EventComponent extends FormBase implements OnInit {
}
});
}
checkTimeZone() {
this.isPacificTimeZone = !this.isPacificTimeZone;
}

setFormValue(app: SepApplication) {
// if there's an app
if (app) {
Expand Down Expand Up @@ -272,20 +270,26 @@ export class EventComponent extends FormBase implements OnInit {
serviceStartValue: ["9:00 AM", [Validators.required]],
serviceEndValue: ["9:30 PM", [Validators.required]],
liquorServiceHoursExtensionReason: [""],
disturbancePreventionMeasuresDetails: [""]
disturbancePreventionMeasuresDetails: [""],
isPacificTimeZone: [this.isPacificTimeZone]
}, { validators: eventTimesValidator });

eventDate = Object.assign(new SepSchedule(null), eventDate);
eventDate = Object.assign(new SepSchedule(null, this.isPacificTimeZone), eventDate);
const val = eventDate.toEventFormValue();

// Set default to event start date
if (!val.eventDate) {
val.eventDate = this?.sepApplication?.eventStartDate;
}
datesForm.patchValue(val);

datesForm.get('isPacificTimeZone').valueChanges.subscribe(value => {
this.isPacificTimeZone = value;
});

return datesForm;
}

getIsOpen(locationIndex: number, eventIndex: number): boolean {
if(this.isOpen[locationIndex] === undefined) {
return true;
Expand Down Expand Up @@ -450,7 +454,7 @@ export class EventComponent extends FormBase implements OnInit {
formData?.eventLocations.forEach(location => {
const dateValues = [];
location?.eventDates.forEach(sched => {
dateValues.push(new SepSchedule(sched));
dateValues.push(new SepSchedule(sched, this.isPacificTimeZone));
});
location.eventDates = dateValues;
});
Expand Down Expand Up @@ -506,5 +510,4 @@ export class EventComponent extends FormBase implements OnInit {
this.showValidationMessages = true;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export class SummaryComponent implements OnInit {
if (loc.eventDates?.length > 0) {
const formatterdDates = [];
loc.eventDates.forEach(ed => {
ed = Object.assign(new SepSchedule(null), ed);
ed = Object.assign(new SepSchedule(null, null), ed);
formatterdDates.push({ ed, ...ed.toEventFormValue() });
});
loc.eventDates = formatterdDates;
Expand Down
84 changes: 54 additions & 30 deletions cllc-public-app/ClientApp/src/app/models/sep-schedule.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { format, addDays } from "date-fns";
import * as moment from 'moment-timezone';

export class SepSchedule {
id: string; // server side primary key
Expand All @@ -10,80 +11,103 @@ export class SepSchedule {
serviceEnd: Date;
liquorServiceHoursExtensionReason: string;
disturbancePreventionMeasuresDetails: string;
readonly vancouverTimeZone: string = "America/Vancouver";
readonly edmontonTimeZone: string = "America/Edmonton";

constructor(sched: IEventFormValue) {

constructor(sched: IEventFormValue, isPacificTimeZone: boolean) {
const timeZone = isPacificTimeZone ? this.vancouverTimeZone : this.edmontonTimeZone;
if (sched) {
this.id = sched.id;
this.eventStart = this.formatDate(sched.eventDate, sched.eventStartValue);
this.eventEnd = this.formatDate(sched.eventDate, sched.eventEndValue);
this.serviceStart = this.formatDate(sched.eventDate, sched.serviceStartValue);
this.serviceEnd = this.formatDate(sched.eventDate, sched.serviceEndValue);
this.eventStart = this.formatDate(sched.eventDate, sched.eventStartValue, isPacificTimeZone);
this.eventEnd = this.formatDate(sched.eventDate, sched.eventEndValue, isPacificTimeZone);
this.serviceStart = this.formatDate(sched.eventDate, sched.serviceStartValue, isPacificTimeZone);
this.serviceEnd = this.formatDate(sched.eventDate, sched.serviceEndValue, isPacificTimeZone);
this.liquorServiceHoursExtensionReason = sched.liquorServiceHoursExtensionReason;
this.disturbancePreventionMeasuresDetails = sched.disturbancePreventionMeasuresDetails;
}
}

// Convert the SepSchedule object to an IEventFormValue object
toEventFormValue(): IEventFormValue {
const result = { id: this.id } as IEventFormValue;
result.eventDate = this.eventStart;



if (this.eventStart) {
result.eventStartValue = format(new Date(this.eventStart), "h:mm aa");
}

if (this.eventEnd) {
result.eventEndValue = format(new Date(this.eventEnd), "h:mm aa");
}

if (this.serviceStart) {
result.serviceStartValue = format(new Date(this.serviceStart), "h:mm aa");
}

if (this.serviceEnd) {
result.serviceEndValue = format(new Date(this.serviceEnd), "h:mm aa");
}

result.liquorServiceHoursExtensionReason = this.liquorServiceHoursExtensionReason;
result.disturbancePreventionMeasuresDetails = this.disturbancePreventionMeasuresDetails;

return result;
}

// Get the number of service hours
getServiceHours(): number {
const serviceHours = parseInt(format(new Date(this.serviceEnd), "H")) - parseInt(format(new Date(this.serviceStart), "H"));
return serviceHours;
}

// Check if the time is after 12:00 AM
private isNextDay(time: string): boolean {
const dayBreakIndex = TIME_SLOTS.indexOf(TIME_SLOTS.find(slot => slot.dayBreak === true));
const timeIndex = TIME_SLOTS.indexOf(TIME_SLOTS.find(slot => slot.value === time));
return timeIndex >= dayBreakIndex;
}

/**
*
* @param eventDate
* @param time, assumed format "HH:MM [AM,PM]" e.g. '6:30 PM'
*/
private formatDate(eventDate: Date, time: string): Date {

// Convert the time to 24-hour format and convert the date to Pacific Time
private formatDate(eventDate: Date, time: string, isPacificTimeZone: boolean): Date {
let tempDate = new Date(eventDate);

// let day = parseInt(format(new Date(eventDate), "dd"), 10);

// console.log("formatting date: ", eventDate, time)

if (this.isNextDay(time)) {
// console.log("is next day")
tempDate = addDays(tempDate, 1);
// day += 1;
}
// const dateString = `${day} ${format(tempDate, "d MMM yyyy")} ${time}`;
const dateString = `${format(tempDate, "d MMM yyyy")} ${time}`;
// console.log("dateString:",dateString);
const result = new Date(dateString);
// console.log("result is: ", result);
return result;

// Convert time to 24-hour format
const time24 = convertTo24Hour(time);

// Create a date string in the format "yyyy-MM-ddTHH:mm:ss"
const dateString = `${format(tempDate, "yyyy-MM-dd")}T${time24}`;

// Convert the date string to Pacific Time
let dateInPacific = moment.tz(dateString, "America/Los_Angeles");

// Convert to UTC, subtract an hour if isPacificTimeZone is false
if (!isPacificTimeZone) {
dateInPacific = dateInPacific.clone().tz("UTC").add(-1, 'hours');
} else {
dateInPacific = dateInPacific.clone().tz("UTC");
}

return dateInPacific.toDate();
}
}

private isNextDay(time: string): boolean {
const dayBreakIndex = TIME_SLOTS.indexOf(TIME_SLOTS.find(slot => slot.dayBreak === true));
const timeIndex = TIME_SLOTS.indexOf(TIME_SLOTS.find(slot => slot.value === time));
return timeIndex >= dayBreakIndex;
// Convert the time to 24-hour format
function convertTo24Hour(time) {
const [main, period] = time.split(' ');
let [hours, minutes] = main.split(':');

if (period === 'PM' && hours !== '12') {
hours = (Number(hours) + 12).toString();
} else if (period === 'AM' && hours === '12') {
hours = '00';
}

return `${hours.padStart(2, '0')}:${minutes}`;
}


Expand Down