Skip to content

Commit

Permalink
Merge pull request #17 from bcgov/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
ychung-mot authored Mar 15, 2024
2 parents fcc911e + 742bd6d commit 3f63c3c
Show file tree
Hide file tree
Showing 27 changed files with 249 additions and 52 deletions.
2 changes: 1 addition & 1 deletion crunchydb/charts/crunchy-postgres/values.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fullnameOverride: strdss-dev
fullnameOverride: strdss-db

# crunchyImage: # it's not necessary to specify an image as the images specified in the Crunchy Postgres Operator will be pulled by default
crunchyImage: artifacts.developer.gov.bc.ca/bcgov-docker-local/crunchy-postgres-gis:ubi8-15.2-3.3-0 # use this image for POSTGIS
Expand Down
7 changes: 5 additions & 2 deletions crunchydb/readme
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
helm install strdss-dev .
helm install strdss-dev . --values values-dev.yaml


Warning: this deletes the database file and backups
oc delete PostgresCluster/strdss-dev

helm delete strdss-dev

oc port-forward svc/strdss-dev-pgbouncer 5433:5432

2 changes: 2 additions & 0 deletions crunchydb/values-uat.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
crunchy-postgres:
fullnameOverride: strdss-uat
Empty file removed crunchydb/values.yaml
Empty file.
3 changes: 2 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 28 additions & 4 deletions frontend/src/app/common/consts/validators.const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,40 @@ export function validateUrl(): ValidatorFn {
};
}

export function validateEmailChips(): ValidatorFn {
export function validatePhone(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const emailList = control.value as Array<string>;
const url = control.value;

if (!url) {
return null;
}

const phoneRegex = new RegExp(/^\(\d{3}\) \d{3}-\d{4}$/);
const validUrl = phoneRegex.test(url);

return validUrl ? null : { invalidPhone: true };
};
}

export function validateEmailListString(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
let emailList;

if (control.value.constructor === Array) {
emailList = control.value;
}
else {
emailList = (control.value as string).split(',').filter(x => !!x).map(x => x.trim()) as Array<string>;
}

if (!emailList) {
if (!emailList || !emailList.length) {
return null;
}

const emailRegex = new RegExp(/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/);
const allValid = emailList.every((email) => emailRegex.test(email))
const allValid = emailList.every((email: string) => {
return emailRegex.test(email)
})

return allValid ? null : { invalidEmailChips: true };
};
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/app/common/models/compliance-notice.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
export interface ComplianceNotice {
platformId: number;
listingId?: string;
listingUrl: string;
hostEmail: string;
hostEmail?: string;
sentAlternatively: boolean;
reasonId: number;
sendCopy: boolean;
ccList: Array<string>;
LgContactEmail: string;
LgContactPhone?: string;
StrBylawUrl?: string;
comment: string;
}
2 changes: 2 additions & 0 deletions frontend/src/app/common/models/delisting-request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export interface DelistingRequest {
municipalityId: number;
platformId: number;
listingId: string;
listingUrl: string;
sendCopy: boolean;
ccList: Array<string>;
Expand Down
22 changes: 9 additions & 13 deletions frontend/src/app/common/services/delisting.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,22 @@ export class DelistingService {
}

getReasons(): Observable<Array<DropdownOption>> {
return this.httpClient.get<Array<DropdownOption>>(`${environment.API_HOST}/compliancenotices/reasons/dropdown`)
return this.httpClient.get<Array<DropdownOption>>(`${environment.API_HOST}/delisting/reasons/dropdown`)
}

complianceNoticePreview(complianceNotice: ComplianceNotice): Observable<string> {
return this.httpClient.post<string>(`${environment.API_HOST}/compliancenotices/preview`, complianceNotice, {
headers: this.textHeaders, responseType: 'text' as any
})
complianceNoticePreview(complianceNotice: ComplianceNotice): Observable<{ content: string }> {
return this.httpClient.post<{ content: string }>(`${environment.API_HOST}/delisting/warnings/preview`, complianceNotice)
}

createComplianceNotice(complianceNotice: ComplianceNotice): Observable<string> {
return this.httpClient.post<string>(`${environment.API_HOST}/compliancenotices`, complianceNotice)
createComplianceNotice(complianceNotice: ComplianceNotice): Observable<void> {
return this.httpClient.post<void>(`${environment.API_HOST}/delisting/warnings`, complianceNotice)
}

delistingRequestPreview(delistingRequest: ComplianceNotice): Observable<string> {
return this.httpClient.post<string>(`${environment.API_HOST}/delisting/requests/preview`, delistingRequest, {
headers: this.textHeaders, responseType: 'text' as any
})
delistingRequestPreview(delistingRequest: ComplianceNotice): Observable<{ content: string }> {
return this.httpClient.post<{ content: string }>(`${environment.API_HOST}/delisting/requests/preview`, delistingRequest)
}

createDelistingRequest(delistingRequest: ComplianceNotice): Observable<string> {
return this.httpClient.post<string>(`${environment.API_HOST}/delisting/requests`, delistingRequest)
createDelistingRequest(delistingRequest: ComplianceNotice): Observable<void> {
return this.httpClient.post<void>(`${environment.API_HOST}/delisting/requests`, delistingRequest)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="title">Compliance notice</div>
<div class="title">Send Notice of Takedown</div>
<div class="sub-title">All fields are required except where stated</div>

<form [formGroup]="myForm" (ngSubmit)="onPreview()">
Expand All @@ -14,7 +14,20 @@

<div class="form-group-row">
<div class="form-group-row-col">
<label for="listingUrl">Add listing URL</label>
<label for="listingId">Add Listing ID Number if known (Optional)</label>
</div>
<div class="form-group-row-col">
<input class="long-text-field" type="text" pInputText formControlName="listingId" id="listingId"
name="listingId" />
</div>
</div>

<div class="form-group-row">
<div class="form-group-row-col">
<span class="info-tooltip" pTooltip="Copy and paste the external listing URL
from the STR platform website" tooltipPosition="top" placeholder="Top"></span>
<label for="listingUrl">Add listing
URL</label>
</div>
<div class="form-group-row-col">
<input class="long-text-field" type="text" pInputText formControlName="listingUrl" id="listingUrl"
Expand All @@ -24,13 +37,25 @@

<div class="form-group-row">
<div class="form-group-row-col">
<label for="hostEmail">Host E-mail Address (optional)</label>
<span class="info-tooltip"
pTooltip="Add the host's email address or check the box if there has been previous communications with the host"
tooltipPosition="top" placeholder="Top"></span>
<label for="hostEmail">Host’s Email Address (This is mandatory unless the checkbox below is checked)</label>
</div>
<div class="form-group-row-col">
<input type="text" pInputText formControlName="hostEmail" id="hostEmail" name="hostEmail" />
</div>
</div>

<div class="form-group-row">
<div class="form-group-row-col has-checkbox">
<p-checkbox formControlName="sentAlternatively" [binary]="true" id="sentAlternatively"
name="sentAlternatively" inputId="sentAlternativelyInput"></p-checkbox>
<label for="sentAlternatively">A notice has been sent to the host through an alternate delivery
method.</label>
</div>
</div>

<div class="form-group-row">
<div class="form-group-row-col">
<label for="reasonId">Select Reason for request</label>
Expand All @@ -44,26 +69,65 @@
<div class="form-group-row">
<div class="form-group-row-col has-checkbox">
<p-checkbox formControlName="sendCopy" [binary]="true" id="sendCopy" name="sendCopy"
inputId="binary"></p-checkbox>
inputId="sendCopyInput"></p-checkbox>
<label for="sendCopy">Send me a copy of this request</label>
</div>
</div>

<div class="form-group-row">
<div class="form-group-row-col">
<span class="info-tooltip" pTooltip="Enter additional email addresses in the CC field separated by commas"
tooltipPosition="top" placeholder="Top"></span>
<label for="ccList">Additional CCs (optional)</label>
</div>
<div class="form-group-row-col">
<p-chips formControlName="ccList" id="ccList" name="ccList"></p-chips>
<textarea formControlName="ccList" rows="1" cols="20" pInputTextarea id="ccList" name="ccList"></textarea>
</div>
</div>

<div class="sub-title">Local Government Contact Information</div>

<div class="form-group-row inline-block">
<div class="form-group-row-col">
<label for="LgContactEmail">Email</label>
</div>
<div class="form-group-row-col">
<input type="text" pInputText formControlName="LgContactEmail" id="LgContactEmail" name="LgContactEmail"
required />
</div>
</div>

<div class="form-group-row inline-block">
<div class="form-group-row-col">
<label for="LgContactPhone">Phone Number (Optional)</label>
</div>
<div class="form-group-row-col">
<p-inputMask mask="(999) 999-9999" placeholder="(999) 999-9999" formControlName="LgContactPhone"
id="LgContactPhone" name="LgContactPhone">
</p-inputMask>
</div>
</div>

<div class="form-group-row">
<div class="form-group-row-col">
<span class="info-tooltip" pTooltip="Enter additional email addresses in the CC field separated by commas."
tooltipPosition="top" placeholder="Top"></span>
<label for="StrBylawUrl">URL for Local Government Short-Term Rental Bylaw Information
(Optional)</label>
</div>
<div class="form-group-row-col">
<input class="long-text-field" type="text" pInputText formControlName="StrBylawUrl" id="StrBylawUrl"
name="StrBylawUrl" />
</div>
</div>

<button type="submit" id="form-preview-btn" pButton pRipple [disabled]="!myForm.valid" label="Review"
class="p-button-success"></button>
</form>

<p-dialog [modal]="true" id="preview-dialog" [closable]="false" header="Preview" [(visible)]="isPreviewVisible"
[style]="{width: '50vw'}">
<p [innerText]="previewText">
</p>
<p [innerText]="previewText"> </p>
<hr>
<div class="comment-section">
<div class="form-group-row">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@
.form-group-row {
width: 100%;

&.inline-block {
width: 368px;
margin-right: 24px;
display: inline-block;

&:last-of-type {
margin-right: 0;
}
}

span.info-tooltip {
background-image: url(../../../../assets/images/info-icon.svg);
border-radius: 50%;
width: 16px;
height: 16px;
display: inline-flex;
justify-content: center;
align-items: center;
margin-right: 4px;
}

&-col {
font-size: 16px;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ import { DelistingService } from '../../../common/services/delisting.service';
import { DropdownOption } from '../../../common/models/dropdown-option';
import { DialogModule } from 'primeng/dialog';
import { ButtonModule } from 'primeng/button';
import { validateEmailChips, validateUrl } from '../../../common/consts/validators.const';
import { validateEmailListString, validatePhone, validateUrl } from '../../../common/consts/validators.const';
import { ToastModule } from 'primeng/toast';
import { MessageService } from 'primeng/api';
import { HttpErrorResponse } from '@angular/common/http';
import { InputMaskModule } from 'primeng/inputmask';
import { TooltipModule } from 'primeng/tooltip';
import { ComplianceNotice } from '../../../common/models/compliance-notice';

@Component({
selector: 'app-compliance-notice',
standalone: true,
imports: [ReactiveFormsModule, DropdownModule, InputTextModule, InputTextareaModule,
CheckboxModule, CommonModule, ChipsModule, DialogModule, ButtonModule, ToastModule],
CheckboxModule, CommonModule, ChipsModule, DialogModule, TooltipModule, InputMaskModule, ButtonModule, ToastModule],
templateUrl: './compliance-notice.component.html',
styleUrl: './compliance-notice.component.scss'
})
Expand All @@ -44,10 +47,14 @@ export class ComplianceNoticeComponent implements OnInit {

onPreview(): void {
if (this.myForm.valid) {
this.delistingService.complianceNoticePreview(this.myForm.value).subscribe(
const model: ComplianceNotice = Object.assign({}, this.myForm.value);

model.ccList = this.myForm.value['ccList'].prototype === Array ? this.myForm.value : (this.myForm.value['ccList'] as string).split(',').filter(x => !!x).map(x => x.trim())

this.delistingService.complianceNoticePreview(model).subscribe(
{
next: preview => {
this.previewText = preview;
this.previewText = preview.content;
this.isPreviewVisible = true;
},
error: error => {
Expand All @@ -63,10 +70,10 @@ export class ComplianceNoticeComponent implements OnInit {

onSubmit(comment: string): void {
if (this.myForm.valid) {
const formValue = this.myForm.value;
formValue.comment = comment;
const model: ComplianceNotice = this.myForm.value;
model.comment = comment;

this.delistingService.createComplianceNotice(formValue).subscribe({
this.delistingService.createComplianceNotice(model).subscribe({
next: (_) => {
this.myForm.reset();
this.initForm();
Expand All @@ -79,7 +86,7 @@ export class ComplianceNoticeComponent implements OnInit {
this.onPreviewClose();
this.showErrors(error);
}
})
});
}
}

Expand All @@ -90,16 +97,21 @@ export class ComplianceNoticeComponent implements OnInit {
private initForm(): void {
this.myForm = this.fb.group({
platformId: [0, Validators.required],
listingId: [''],
listingUrl: ['', [Validators.required, validateUrl()]],
hostEmail: ['', Validators.email],
sentAlternatively: [false],
reasonId: [0, Validators.required,],
sendCopy: [true],
ccList: [[], validateEmailChips()],
ccList: ['', validateEmailListString()],
LgContactEmail: ['', [Validators.required, Validators.email]],
LgContactPhone: [''],
StrBylawUrl: ['', validateUrl()],
comment: [''],
});
}

showErrors(error: HttpErrorResponse | any): void {
private showErrors(error: HttpErrorResponse | any): void {
let errorObject = typeof error.error === 'string' ? JSON.parse(error.error) : error.error;
if (error.error['detail']) {
this.messageService.add({ severity: 'error', summary: 'Validation error', detail: error.error['detail'], life: 10000 });
Expand Down
Loading

0 comments on commit 3f63c3c

Please sign in to comment.