mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 00:52:55 +00:00
feat: calendar plugin
This commit is contained in:
committed by
Rainer Killinger
parent
080e6fa3e8
commit
a57c3029df
@@ -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';
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
/**
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user