import {IdlService, IdlObject} from '@eg/core/idl.service';
import {OrgService} from '@eg/core/org.service';
import {LocaleService} from '@eg/core/locale.service';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
/**
* Format IDL vield values for display.
} else {
tz = this.wsOrgTimezone;
}
- const date = Moment(value).tz(tz);
+ const date = moment(value).tz(tz);
if (!date.isValid()) {
console.error('Invalid date in format service', value);
return '';
/**
* Create a Moment from an ISO string
*/
- momentizeIsoString(isoString: string, timezone: string): Moment {
- return (isoString.length) ? Moment(isoString, timezone) : Moment();
+ momentizeIsoString(isoString: string, timezone: string): moment.Moment {
+ return (isoString.length) ? moment(isoString, timezone) : moment();
}
/**
* Turn a date string into a Moment using the date format org setting.
*/
- momentizeDateString(date: string, timezone: string, strict?, locale?): Moment {
+ momentizeDateString(date: string, timezone: string, strict?, locale?): moment.Moment {
return this.momentize(date, this.makeFormatParseable(this.dateFormat, locale), timezone, strict);
}
/**
* Turn a datetime string into a Moment using the datetime format org setting.
*/
- momentizeDateTimeString(date: string, timezone: string, strict?, locale?): Moment {
+ momentizeDateTimeString(date: string, timezone: string, strict?, locale?): moment.Moment {
return this.momentize(date, this.makeFormatParseable(this.dateTimeFormat, locale), timezone, strict);
}
/**
* Turn a string into a Moment using the provided format string.
*/
- private momentize(date: string, format: string, timezone: string, strict: boolean): Moment {
+ private momentize(date: string, format: string, timezone: string, strict: boolean): moment.Moment {
if (format.length) {
- const result = Moment.tz(date, format, true, timezone);
- if (isNaN(result) || 'Invalid date' === result) {
+ const result = moment.tz(date, format, true, timezone);
+ if (!result.isValid()) {
if (strict) {
throw new Error('Error parsing date ' + date);
}
- return Moment.tz(date, format, false, timezone);
+ return moment.tz(date, format, false, timezone);
}
- return Moment(new Date(date), timezone);
+ return moment(new Date(date), timezone);
}
}
import {AbstractControl, ControlValueAccessor, FormControl, FormGroup, NgControl} from '@angular/forms';
import {NgbDatepicker, NgbTimeStruct, NgbDateStruct} from '@ng-bootstrap/ng-bootstrap';
import {DatetimeValidator} from '@eg/share/validators/datetime_validator.directive';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
@Component({
selector: 'eg-datetime-select',
) {
if (controlDir) { controlDir.valueAccessor = this; }
this.onChangeAsIso = new EventEmitter<string>();
- const startValue = Moment.tz([], this.timezone);
+ const startValue = moment.tz([], this.timezone);
this.dateTimeForm = new FormGroup({
'stringVersion': new FormControl(
this.format.transform({value: startValue, datatype: 'timestamp', datePlusTime: true}),
this.timezone = this.format.wsOrgTimezone;
}
if (this.initialIso) {
- this.writeValue(Moment(this.initialIso).tz(this.timezone));
+ this.writeValue(moment(this.initialIso).tz(this.timezone));
}
this.dateTimeForm.get('stringVersion').valueChanges.subscribe((value) => {
if ('VALID' === this.dateTimeForm.get('stringVersion').status) {
}
});
this.dateTimeForm.get('date').valueChanges.subscribe((date) => {
- const newDate = Moment.tz([date.year, (date.month - 1), date.day,
+ const newDate = moment.tz([date.year, (date.month - 1), date.day,
this.time.value.hour, this.time.value.minute, 0], this.timezone);
this.dateTimeForm.patchValue({stringVersion:
this.format.transform({value: newDate, datatype: 'timestamp', datePlusTime: true})},
});
this.dateTimeForm.get('time').valueChanges.subscribe((time) => {
- const newDate = Moment.tz([this.date.value.year,
+ const newDate = moment.tz([this.date.value.year,
(this.date.value.month - 1),
this.date.value.day,
time.hour, time.minute, 0],
});
}
- setDatePicker(current: Moment) {
- const withTZ = current ? current.tz(this.timezone) : Moment.tz([], this.timezone);
+ setDatePicker(current: moment.Moment) {
+ const withTZ = current ? current.tz(this.timezone) : moment.tz([], this.timezone);
this.dateTimeForm.patchValue({date: {
year: withTZ.year(),
month: withTZ.month() + 1,
day: withTZ.date() }});
}
- setTimePicker(current: Moment) {
- const withTZ = current ? current.tz(this.timezone) : Moment.tz([], this.timezone);
+ setTimePicker(current: moment.Moment) {
+ const withTZ = current ? current.tz(this.timezone) : moment.tz([], this.timezone);
this.dateTimeForm.patchValue({time: {
hour: withTZ.hour(),
minute: withTZ.minute(),
}
- writeValue(value: Moment) {
+ writeValue(value: moment.Moment) {
if (value !== undefined && value !== null) {
this.dateTimeForm.patchValue({
stringVersion: this.format.transform({value: value, datatype: 'timestamp', datePlusTime: true})});
}
}
- registerOnChange(fn: (value: Moment) => any): void {
+ registerOnChange(fn: (value: moment.Moment) => any): void {
this.onChange = fn;
}
registerOnTouched(fn: () => any): void {
import {NG_VALIDATORS, AbstractControl, FormControl, ValidationErrors, ValidatorFn} from '@angular/forms';
import {Injectable} from '@angular/core';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
-export function notBeforeMomentValidator(notBeforeMe: Moment): ValidatorFn {
+export function notBeforeMomentValidator(notBeforeMe: moment.Moment): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
return (control.value && control.value.isBefore(notBeforeMe)) ?
{tooEarly: 'This cannot be before ' + notBeforeMe.format('LLL')} : null;
}]
})
export class NotBeforeMomentValidatorDirective {
- @Input('egNotBeforeMoment') notBeforeMoment: Moment;
+ @Input('egNotBeforeMoment') notBeforeMoment: moment.Moment;
validate(control: AbstractControl): {[key: string]: any} | null {
return this.notBeforeMoment ?
import {ToastService} from '@eg/share/toast/toast.service';
import {AlertDialogComponent} from '@eg/share/dialog/alert.component';
import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
const startTimeIsBeforeEndTimeValidator: ValidatorFn = (fg: FormGroup): ValidationErrors | null => {
const start = fg.get('startTime').value;
[this.pbv.validate]
),
'emailNotify': new FormControl(true),
- 'startTime': new FormControl(null, notBeforeMomentValidator(Moment().add('15', 'minutes'))),
+ 'startTime': new FormControl(null, notBeforeMomentValidator(moment().add('15', 'minutes'))),
'endTime': new FormControl(),
'resourceList': new FormControl(),
'note': new FormControl(),
);
}
- setDefaultTimes(times: Moment[], granularity: number) {
- this.create.patchValue({startTime: Moment.min(times),
- endTime: Moment.max(times).clone().add(granularity, 'minutes')
+ setDefaultTimes(times: moment.Moment[], granularity: number) {
+ this.create.patchValue({startTime: moment.min(times),
+ endTime: moment.max(times).clone().add(granularity, 'minutes')
});
}
</eg-create-reservation-dialog>
<ng-template #reservationsTemplate let-row="row" let-col="col">
- <ng-container *ngIf="row[col.name]">
+ <ng-container *ngIf="row.patrons && row.patrons[col.name]">
<ul class="list-unstyled">
- <li *ngFor="let reservation of row[col.name]">
+ <li *ngFor="let reservation of row.patrons[col.name]">
<button class="btn btn-info" (click)="openReservationViewer(reservation['reservationId'])">
{{reservation['patronLabel']}}
</button>
import {ScheduleGridService, ScheduleRow} from './schedule-grid.service';
import {NoTimezoneSetComponent} from './no-timezone-set.component';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
const startOfDayIsBeforeEndOfDayValidator: ValidatorFn = (fg: FormGroup): ValidationErrors | null => {
const start = fg.get('startOfDay').value;
}),
takeLast(1),
switchMap(() => {
- let range = {startTime: Moment(), endTime: Moment()};
+ let range = {startTime: moment(), endTime: moment()};
if (this.multiday) {
range = this.scheduleService.momentizeDateRange(
};
this.resources.forEach(resource => {
this.cellTextGenerator[resource.barcode()] = row => {
- return row[resource.barcode()] ? row[resource.barcode()].map(reservation => reservation['patronLabel']).join(', ') : '';
+ return row.patrons[resource.barcode()] ? row.patrons[resource.barcode()].map(reservation => reservation['patronLabel']).join(', ') : '';
};
});
});
import {ReservationActionsService} from './reservation-actions.service';
import {CancelReservationDialogComponent} from './cancel-reservation-dialog.component';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
// A filterable grid of reservations used in various booking interfaces
where['pickup_time'] = {'!=': null};
where['return_time'] = null;
} else if ('returnedToday' === this.status) {
- where['return_time'] = {'>': Moment().startOf('day').toISOString()};
+ where['return_time'] = {'>': moment().startOf('day').toISOString()};
} else if ('capturedToday' === this.status) {
- where['capture_time'] = {'between': [Moment().startOf('day').toISOString(),
- Moment().add(1, 'day').startOf('day').toISOString()]};
+ where['capture_time'] = {'between': [moment().startOf('day').toISOString(),
+ moment().add(1, 'day').startOf('day').toISOString()]};
}
} else {
where['return_time'] = null;
enrichRow$ = (row: IdlObject): Observable<IdlObject> => {
return from(this.org.settings('lib.timezone', row.pickup_lib().id())).pipe(
switchMap((tz) => {
- row['length'] = Moment(row['end_time']()).from(Moment(row['start_time']()), true);
+ row['length'] = moment(row['end_time']()).from(moment(row['start_time']()), true);
row['timezone'] = tz['lib.timezone'];
return of(row);
})
this.router.navigate(['/staff', 'booking', 'manage_reservations', 'by_resource', barcode]);
}
- momentizeIsoString(isoString: string, timezone: string): Moment {
+ momentizeIsoString(isoString: string, timezone: string): moment.Moment {
return this.format.momentizeIsoString(isoString, timezone);
}
}
import {GridRowFlairEntry} from '@eg/share/grid/grid';
import {DateRange} from '@eg/share/daterange-select/daterange-select.component';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
export interface ReservationPatron {
patronId: number;
reservationId: number;
}
-export interface ScheduleRow {
- time: Moment;
+interface ScheduleRowPatrons {
[key: string]: ReservationPatron[];
}
+export interface ScheduleRow {
+ time: moment.Moment;
+ patrons: ScheduleRowPatrons;
+}
+
// Various methods that fetch data for and process the schedule of reservations
@Injectable({providedIn: 'root'})
resourceAvailabilityIcon = (row: ScheduleRow, numResources: number): GridRowFlairEntry => {
let icon = {icon: 'event_busy', title: 'All resources are reserved at this time'};
let busyColumns = 0;
- for (const key in row) {
- if (row[key] instanceof Array && row[key].length) {
+ for (const key in row.patrons) {
+ if (row.patrons[key] instanceof Array && row.patrons[key].length) {
busyColumns += 1;
}
}
});
}
- momentizeDateRange = (range: DateRange, timezone: string): {startTime: Moment, endTime: Moment} => {
+ momentizeDateRange = (range: DateRange, timezone: string): {startTime: moment.Moment, endTime: moment.Moment} => {
return {
- startTime: Moment.tz([
+ startTime: moment.tz([
range.fromDate.year,
range.fromDate.month - 1,
range.fromDate.day],
timezone),
- endTime: Moment.tz([
+ endTime: moment.tz([
range.toDate.year,
range.toDate.month - 1,
range.toDate.day + 1],
timezone)
};
}
- momentizeDay = (date: Date, start: NgbTimeStruct, end: NgbTimeStruct, timezone: string): {startTime: Moment, endTime: Moment} => {
+ momentizeDay = (date: Date, start: NgbTimeStruct, end: NgbTimeStruct, timezone: string): {startTime: moment.Moment, endTime: moment.Moment} => {
return {
- startTime: Moment.tz([
+ startTime: moment.tz([
date.getFullYear(),
date.getMonth(),
date.getDate(),
start.hour,
start.minute],
timezone),
- endTime: Moment.tz([
+ endTime: moment.tz([
date.getFullYear(),
date.getMonth(),
date.getDate(),
};
}
- createBasicSchedule = (range: {startTime: Moment, endTime: Moment}, granularity: number): ScheduleRow[] => {
+ createBasicSchedule = (range: {startTime: moment.Moment, endTime: moment.Moment}, granularity: number): ScheduleRow[] => {
const currentTime = range.startTime.clone();
const schedule = [];
while (currentTime < range.endTime) {
return schedule;
}
- fetchReservations = (range: {startTime: Moment, endTime: Moment}, resourceIds: number[]): Observable<IdlObject> => {
+ fetchReservations = (range: {startTime: moment.Moment, endTime: moment.Moment}, resourceIds: number[]): Observable<IdlObject> => {
return this.pcrud.search('bresv', {
'-or': {'target_resource': resourceIds, 'current_resource': resourceIds},
'end_time': {'>': range.startTime.toISOString()},
const end = (index + 1 < schedule.length) ?
schedule[index + 1].time :
schedule[index].time.clone().add(granularity, 'minutes');
- if ((Moment.tz(reservation.start_time(), timezone).isBefore(end)) &&
- (Moment.tz(reservation.end_time(), timezone).isAfter(start))) {
- if (!schedule[index][reservation.current_resource().barcode()]) {
- schedule[index][reservation.current_resource().barcode()] = [];
+ if ((moment.tz(reservation.start_time(), timezone).isBefore(end)) &&
+ (moment.tz(reservation.end_time(), timezone).isAfter(start))) {
+ if (!schedule[index]['patrons']) schedule[index].patrons = {};
+ if (!schedule[index].patrons[reservation.current_resource().barcode()]) {
+ schedule[index].patrons[reservation.current_resource().barcode()] = [];
}
- if (schedule[index][reservation.current_resource().barcode()]
+ if (schedule[index].patrons[reservation.current_resource().barcode()]
.findIndex(patron => patron.patronId === reservation.usr().id()) === -1) {
- schedule[index][reservation.current_resource().barcode()].push(
+ schedule[index].patrons[reservation.current_resource().barcode()].push(
{'patronLabel': reservation.usr().usrname(),
'patronId': reservation.usr().id(),
'reservationId': reservation.id()});
import { AuthService } from '@eg/core/auth.service';
import { PcrudService } from '@eg/core/pcrud.service';
import { ScheduleGridService, ScheduleRow } from './schedule-grid.service';
-import * as Moment from 'moment-timezone';
+import * as moment from 'moment-timezone';
describe('ScheduleGridService', () => {
let service: ScheduleGridService;
it('should recognize when a row is completely busy', () => {
const busyRow: ScheduleRow = {
- 'time': Moment(),
- 'barcode1': [{patronLabel: 'Joe', patronId: 1, reservationId: 3}],
- 'barcode2': [{patronLabel: 'Jill', patronId: 2, reservationId: 5}],
- 'barcode3': [{patronLabel: 'James', patronId: 3, reservationId: 12},
- {patronLabel: 'Juanes', patronId: 4, reservationId: 18}]
+ 'time': moment(),
+ 'patrons': {
+ 'barcode1': [{patronLabel: 'Joe', patronId: 1, reservationId: 3}],
+ 'barcode2': [{patronLabel: 'Jill', patronId: 2, reservationId: 5}],
+ 'barcode3': [{patronLabel: 'James', patronId: 3, reservationId: 12},
+ {patronLabel: 'Juanes', patronId: 4, reservationId: 18}]
+ }
};
expect(service.resourceAvailabilityIcon(busyRow, 3).icon).toBe('event_busy');
});
it('should recognize when a row has some availability', () => {
const rowWithAvailability: ScheduleRow = {
- 'time': Moment(),
- 'barcode3': [{patronLabel: 'James', patronId: 3, reservationId: 11},
- {patronLabel: 'Juanes', patronId: 4, reservationId: 17}]
+ 'time': moment(),
+ 'patrons': {
+ 'barcode3': [{patronLabel: 'James', patronId: 3, reservationId: 11},
+ {patronLabel: 'Juanes', patronId: 4, reservationId: 17}]
+ }
};
expect(service.resourceAvailabilityIcon(rowWithAvailability, 3).icon).toBe('event_available');
});