feat: calendar plugin

This commit is contained in:
Thea Schöbl
2022-01-31 15:57:38 +00:00
committed by Rainer Killinger
parent 080e6fa3e8
commit a57c3029df
54 changed files with 2880 additions and 70 deletions

View File

@@ -25,7 +25,7 @@ import {
materialManualFade,
materialSharedAxisX,
} from '../../../animation/material-motion';
import {ScheduleProvider} from '../schedule.provider';
import {ScheduleProvider} from '../../calendar/schedule.provider';
import {ScheduleEvent, ScheduleResponsiveBreakpoint} from './schema/schema';
import {SwiperComponent} from 'swiper/angular';

View File

@@ -14,7 +14,7 @@
*/
import {Component, Input, OnInit} from '@angular/core';
import moment from 'moment';
import {ScheduleProvider} from '../../schedule.provider';
import {ScheduleProvider} from '../../../calendar/schedule.provider';
import {ScheduleEvent} from '../schema/schema';
/**
@@ -87,9 +87,9 @@ export class ScheduleCardComponent implements OnInit {
*/
removeEvent(): false {
if (confirm('Remove event?')) {
this.scheduleProvider.uuids$.next(
this.scheduleProvider.uuids$.value.filter(
it => it !== this.scheduleEvent.dateSeries.uid,
this.scheduleProvider.partialEvents$.next(
this.scheduleProvider.partialEvents$.value.filter(
it => it.uid !== this.scheduleEvent.dateSeries.uid,
),
);
}

View File

@@ -15,7 +15,7 @@
import {Component, Input} from '@angular/core';
import moment from 'moment';
import {Range, ScheduleEvent} from '../schema/schema';
import {ScheduleProvider} from '../../schedule.provider';
import {ScheduleProvider} from '../../../calendar/schedule.provider';
import {SCISO8601Duration, SCUuid} from '@openstapps/core';
import {materialFade} from '../../../../animation/material-motion';

View File

@@ -18,7 +18,7 @@ import {flatMap, groupBy, isNil, omit, sortBy} from 'lodash-es';
import moment from 'moment';
import {Subscription} from 'rxjs';
import {materialFade} from '../../../animation/material-motion';
import {ScheduleProvider} from '../schedule.provider';
import {ScheduleProvider} from '../../calendar/schedule.provider';
import {ScheduleEvent} from './schema/schema';
/**

View File

@@ -22,7 +22,7 @@ import {
materialManualFade,
materialSharedAxisX,
} from '../../../animation/material-motion';
import {ScheduleProvider} from '../schedule.provider';
import {ScheduleProvider} from '../../calendar/schedule.provider';
import {CalendarViewComponent} from './calendar-view.component';
import {SwiperComponent} from 'swiper/angular';

View File

@@ -30,11 +30,12 @@ import {ModalEventCreatorComponent} from './page/modal/modal-event-creator.compo
import {SchedulePageComponent} from './page/schedule-page.component';
import {ScheduleSingleEventsComponent} from './page/schedule-single-events.component';
import {ScheduleViewComponent} from './page/schedule-view.component';
import {ScheduleProvider} from './schedule.provider';
import {ScheduleProvider} from '../calendar/schedule.provider';
import {SwiperModule} from 'swiper/angular';
import {ScheduleDayComponent} from './page/grid/schedule-day.component';
import {ThingTranslateModule} from '../../translation/thing-translate.module';
import {InfiniteSwiperComponent} from './page/grid/infinite-swiper.component';
import {FileOpener} from '@ionic-native/file-opener/ngx';
const settingsRoutes: Routes = [
{path: 'schedule', redirectTo: 'schedule/calendar/now'},
@@ -72,6 +73,6 @@ const settingsRoutes: Routes = [
UtilModule,
ThingTranslateModule,
],
providers: [ScheduleProvider, DataProvider, DateFormatPipe],
providers: [ScheduleProvider, DataProvider, DateFormatPipe, FileOpener],
})
export class ScheduleModule {}

View File

@@ -1,217 +0,0 @@
/*
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* eslint-disable unicorn/no-null */
import {Injectable, OnDestroy} from '@angular/core';
import {
Bounds,
SCDateSeries,
SCISO8601Date,
SCISO8601Duration,
SCSearchFilter,
SCThingType,
SCUuid,
} from '@openstapps/core';
import {BehaviorSubject, Subscription} from 'rxjs';
import {DataProvider} from '../data/data.provider';
/**
* Provider for app settings
*/
@Injectable()
export class ScheduleProvider implements OnDestroy {
// tslint:disable:prefer-function-over-method
/**
* Storage key for event UUIDs
*/
private static uuidStorageKey = 'schedule::event_uuids';
private _uuids$?: BehaviorSubject<SCUuid[]>;
private _uuidSubscription?: Subscription;
constructor(private readonly dataProvider: DataProvider) {
window.addEventListener('storage', this.storageListener);
}
/**
* Push one or more values to local storage
*/
private static get<T>(key: string): T[] {
const item = localStorage.getItem(key);
if (item == undefined) {
return [];
}
return JSON.parse(item) as T[];
}
/**
* Push one or more values to local storage
*/
private static set<T>(key: string, item: T[]) {
const newValue = JSON.stringify(item);
// prevent feedback loop from storageEvent -> _uuids$.next() -> set -> storageEvent
if (newValue !== localStorage.getItem(key)) {
localStorage.setItem(key, newValue);
}
}
/**
* TODO
*/
public get uuids$(): BehaviorSubject<SCUuid[]> {
if (!this._uuids$) {
this._uuids$ = new BehaviorSubject(
ScheduleProvider.get<SCUuid>(ScheduleProvider.uuidStorageKey),
);
this._uuidSubscription = this._uuids$.subscribe(result => {
ScheduleProvider.set(ScheduleProvider.uuidStorageKey, result);
});
}
return this._uuids$;
}
/**
* What to do when local storage updates
*/
private storageEventHandler(event: StorageEvent) {
if (
event.newValue &&
event.storageArea === localStorage &&
event.key === ScheduleProvider.uuidStorageKey
) {
this._uuids$?.next(JSON.parse(event.newValue));
}
}
/**
* Listen to updates in local storage
*/
private storageListener = this.storageEventHandler.bind(this);
/**
* Load Date Series
*/
async getDateSeries(
uuids: SCUuid[],
frequencies?: Array<SCISO8601Duration>,
from?: SCISO8601Date | 'now',
to?: SCISO8601Date | 'now',
): Promise<{
dates: SCDateSeries[];
min: SCISO8601Date;
max: SCISO8601Date;
}> {
if (uuids.length === 0) {
return {
dates: [],
min: '',
max: '',
};
}
const filters: SCSearchFilter[] = [
{
arguments: {
field: 'type',
value: SCThingType.DateSeries,
},
type: 'value',
},
{
arguments: {
filters: uuids.map(uid => ({
arguments: {
field: 'uid',
value: uid,
},
type: 'value',
})),
operation: 'or',
},
type: 'boolean',
},
];
if (frequencies) {
filters.push({
arguments: {
filters: frequencies.map(frequency => ({
arguments: {
field: 'repeatFrequency',
value: frequency,
},
type: 'value',
})),
operation: 'or',
},
type: 'boolean',
});
}
if (from || to) {
const bounds: Bounds<string> = {};
if (from) {
console.log(from);
bounds.lowerBound = {
limit: from,
mode: 'inclusive',
};
}
if (to) {
console.log(to);
bounds.upperBound = {
limit: to,
mode: 'inclusive',
};
}
filters.push({
arguments: {
field: 'dates',
bounds: bounds,
},
type: 'date range',
});
}
const result = await this.dataProvider.search({
filter: {
arguments: {
filters: filters,
operation: 'and',
},
type: 'boolean',
},
});
return {
dates: result.data as SCDateSeries[],
// TODO: https://gitlab.com/openstapps/backend/-/issues/100
min: new Date(2021, 11, 1).toISOString(),
max: new Date(2022, 1, 24).toISOString(),
};
}
/**
* TODO
*/
ngOnDestroy(): void {
this._uuidSubscription?.unsubscribe();
window.removeEventListener('storage', this.storageListener);
}
}