refactor: rename "recurring" to "week overview"

refactor: replace dashboard calendar icon
resolves #128

refactor: route dashboard "next unit" to date series instead of events
resolves #126
This commit is contained in:
Thea Schöbl
2023-08-07 15:51:23 +00:00
parent 9abd397578
commit e1cc33bba2
14 changed files with 120 additions and 52 deletions

View File

@@ -0,0 +1,5 @@
---
'@openstapps/app': minor
---
Added the ability to remove and add date series from their detail page

View File

@@ -0,0 +1,9 @@
---
'@openstapps/app': minor
---
Improved calendar descriptions
- The dashboard quick link now has a more intuitive icon
- "Recurring" has been renamed to "Week Overview"
- Long words in calendar tabs will now break instead of overflowing

View File

@@ -0,0 +1,5 @@
---
'@openstapps/app': minor
---
Replaced simple links with list items in date-series detail

View File

@@ -20,12 +20,14 @@ describe('dashboard', async function () {
describe('schedule section', function () { describe('schedule section', function () {
it('should lead to the schedule', function () { it('should lead to the schedule', function () {
cy.visit('/overview'); cy.visit('/overview');
cy.get('.schedule').contains('a', 'Stundenplan').click(); cy.get('.schedule')
cy.url().should('include', '/schedule/recurring'); .contains('a', /Wochen.*übersicht/)
.click();
cy.url().should('include', '/schedule/week-overview');
cy.visit('/overview'); cy.visit('/overview');
cy.get('.schedule').contains('a', 'Kein Eintrag gefunden').click(); cy.get('.schedule').contains('a', 'Kein Eintrag gefunden').click();
cy.url().should('include', '/schedule/recurring'); cy.url().should('include', '/schedule/calendar');
}); });
// TODO: Reenable and stabilize tests // TODO: Reenable and stabilize tests

View File

@@ -19,19 +19,19 @@
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<div #schedule class="schedule"> <div #schedule class="schedule">
<a [routerLink]="['/schedule/recurring']"> <a [routerLink]="['/schedule/week-overview']">
<ion-icon size="40" weight="300" name="grid_view"></ion-icon> <ion-icon size="36" weight="300" name="calendar_month"></ion-icon>
<ion-label>{{ 'schedule.recurring' | translate }}</ion-label> <ion-label [innerHTML]="'schedule.recurring' | translate"></ion-label>
</a> </a>
<!-- Avoid structural directives here, they might interfere with the collapse animation --> <!-- Avoid structural directives here, they might interfere with the collapse animation -->
<a <a
[routerLink]="nextEvent?.event ? ['/data-detail', nextEvent!.event.uid] : ['/schedule/recurring']" [routerLink]="nextEvent ? ['/data-detail', nextEvent!.uid] : ['/schedule/calendar']"
class="schedule-item-button" class="schedule-item-button"
> >
<ion-label>{{ 'dashboard.schedule.title' | translate }}</ion-label> <ion-label>{{ 'dashboard.schedule.title' | translate }}</ion-label>
<ion-label> <ion-label>
{{ {{
nextEvent?.event nextEvent
? (nextEvent!.dates | nextDateInList | amDateFormat : 'll, HH:mm') ? (nextEvent!.dates | nextDateInList | amDateFormat : 'll, HH:mm')
: ('dashboard.schedule.noEvent' | translate) : ('dashboard.schedule.noEvent' | translate)
}} }}

View File

@@ -117,6 +117,7 @@ ion-content {
ion-label { ion-label {
font-size: var(--font-size-xxs); font-size: var(--font-size-xxs);
font-weight: var(--font-weight-semi-bold); font-weight: var(--font-weight-semi-bold);
word-break: break-word;
} }
&:hover ::ng-deep stapps-icon { &:hover ::ng-deep stapps-icon {

View File

@@ -12,19 +12,49 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Component, Input} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {SCDateSeries} from '@openstapps/core'; import {SCDateSeries} from '@openstapps/core';
import {ScheduleProvider, toDateSeriesRelevantData} from '../../../calendar/schedule.provider';
import {Observable} from 'rxjs';
import {map} from 'rxjs/operators';
import {DataRoutingService} from '../../data-routing.service';
import {Router} from '@angular/router';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
/**
* TODO
*/
@Component({ @Component({
selector: 'stapps-date-series-detail-content', selector: 'stapps-date-series-detail-content',
templateUrl: 'date-series-detail-content.html', templateUrl: 'date-series-detail-content.html',
styleUrls: ['date-series-detail-content.scss'],
}) })
export class DateSeriesDetailContentComponent { export class DateSeriesDetailContentComponent implements OnInit {
/**
* TODO
*/
@Input() item: SCDateSeries; @Input() item: SCDateSeries;
isInCalendar: Observable<boolean>;
constructor(
readonly scheduleProvider: ScheduleProvider,
dataRoutingService: DataRoutingService,
router: Router,
) {
dataRoutingService
.itemSelectListener()
.pipe(takeUntilDestroyed())
.subscribe(item => {
void router.navigate(['/data-detail', item.uid]);
});
}
ngOnInit() {
this.isInCalendar = this.scheduleProvider.uuids$.pipe(map(it => it.includes(this.item.uid)));
}
addToCalendar() {
const current = this.scheduleProvider.partialEvents$.value;
this.scheduleProvider.partialEvents$.next([...current, toDateSeriesRelevantData(this.item)]);
}
removeFromCalendar() {
const filtered = this.scheduleProvider.partialEvents$.value.filter(it => it.uid !== this.item.uid);
this.scheduleProvider.partialEvents$.next(filtered);
}
} }

View File

@@ -12,23 +12,18 @@
~ You should have received a copy of the GNU General Public License along with ~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>. ~ this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<ion-card> <ng-container *ngIf="isInCalendar | async; else add">
<ion-card-header> {{ 'event' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-chip outline="true" color="success" (click)="removeFromCalendar()">
<ion-card-content> <ion-icon name="event_available" fill="true"></ion-icon>
<a [routerLink]="['/data-detail', item.event.uid]">{{ 'name' | thingTranslate : item.event }}</a> <ion-label>{{'chips.addEvent.addedToEvents' | translate}}</ion-label>
</ion-card-content> </ion-chip>
</ion-card> </ng-container>
<ion-card *ngIf="item.inPlace"> <ng-template #add>
<ion-card-header> {{ 'inPlace' | propertyNameTranslate : item | titlecase }} </ion-card-header> <ion-chip outline="true" color="primary" (click)="addToCalendar()">
<ion-card-content> <ion-icon name="calendar_today"></ion-icon>
<ion-icon name="pin_drop"> </ion-icon> <ion-label>{{'chips.addEvent.addEvent' | translate}}</ion-label>
<a [routerLink]="['/data-detail', item.inPlace.uid]">{{ 'name' | thingTranslate : item.inPlace }}</a> </ion-chip>
<stapps-address-detail </ng-template>
*ngIf="item.inPlace.address"
[address]="item.inPlace.address"
></stapps-address-detail>
</ion-card-content>
</ion-card>
<stapps-simple-card <stapps-simple-card
title="{{ 'duration' | propertyNameTranslate : item | titlecase }}" title="{{ 'duration' | propertyNameTranslate : item | titlecase }}"
[content]="[item.duration | amDuration : 'minutes']" [content]="[item.duration | amDuration : 'minutes']"
@@ -56,3 +51,15 @@
[content]="item.performers" [content]="item.performers"
></stapps-simple-card> ></stapps-simple-card>
<stapps-offers-detail *ngIf="item.offers" [offers]="item.offers"></stapps-offers-detail> <stapps-offers-detail *ngIf="item.offers" [offers]="item.offers"></stapps-offers-detail>
<ion-card>
<ion-card-header> {{ 'event' | propertyNameTranslate : item | titlecase }} </ion-card-header>
<ion-card-content>
<stapps-data-list-item [item]="$any(item.event)"></stapps-data-list-item>
</ion-card-content>
</ion-card>
<ion-card *ngIf="item.inPlace">
<ion-card-header> {{ 'inPlace' | propertyNameTranslate : item | titlecase }} </ion-card-header>
<ion-card-content>
<stapps-data-list-item [item]="$any(item.inPlace)"></stapps-data-list-item>
</ion-card-content>
</ion-card>

View File

@@ -0,0 +1,6 @@
ion-chip {
position: absolute;
z-index: 1;
top: 0;
right: 0;
}

View File

@@ -136,7 +136,7 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
onInit() { onInit() {
this.tabChoreographer = new SharedAxisChoreographer(this.activatedRoute.snapshot.paramMap.get('mode'), [ this.tabChoreographer = new SharedAxisChoreographer(this.activatedRoute.snapshot.paramMap.get('mode'), [
'calendar', 'calendar',
'recurring', 'week-overview',
'single', 'single',
]); ]);
} }

View File

@@ -18,15 +18,18 @@
<ion-buttons slot="start"> <ion-buttons slot="start">
<ion-back-button></ion-back-button> <ion-back-button></ion-back-button>
</ion-buttons> </ion-buttons>
<ion-title *ngIf="tabChoreographer.currentValue === 'calendar'" <ion-title
>{{ 'schedule.calendar' | translate | titlecase }}</ion-title *ngIf="tabChoreographer.currentValue === 'calendar'"
> [innerHTML]="'schedule.calendar' | translate | titlecase"
<ion-title *ngIf="tabChoreographer.currentValue === 'recurring'" ></ion-title>
>{{ 'schedule.recurring' | translate | titlecase }}</ion-title <ion-title
> *ngIf="tabChoreographer.currentValue === 'week-overview'"
<ion-title *ngIf="tabChoreographer.currentValue === 'single'" [innerHTML]="'schedule.recurring' | translate | titlecase"
>{{ 'schedule.single' | translate | titlecase }}</ion-title ></ion-title>
> <ion-title
*ngIf="tabChoreographer.currentValue === 'single'"
[innerHTML]="'schedule.single' | translate | titlecase"
></ion-title>
<ion-buttons slot="end"> <ion-buttons slot="end">
<ion-button (click)="onTodayClick()"> <ion-button (click)="onTodayClick()">
<ion-icon name="today" slot="icon-only"></ion-icon> <ion-icon name="today" slot="icon-only"></ion-icon>
@@ -36,15 +39,15 @@
<ion-toolbar color="primary" mode="md" class="tabs-toolbar"> <ion-toolbar color="primary" mode="md" class="tabs-toolbar">
<ion-segment #segment value="calendar" (ionChange)="onSegmentChange()"> <ion-segment #segment value="calendar" (ionChange)="onSegmentChange()">
<ion-segment-button value="calendar" layout="icon-start"> <ion-segment-button value="calendar" layout="icon-start">
<ion-label>{{ 'schedule.calendar' | translate }}</ion-label> <ion-label class="ion-text-wrap" [innerHTML]="'schedule.calendar' | translate"></ion-label>
<ion-icon name="calendar_today"></ion-icon> <ion-icon name="calendar_today"></ion-icon>
</ion-segment-button> </ion-segment-button>
<ion-segment-button value="recurring" layout="icon-start"> <ion-segment-button value="week-overview" layout="icon-start">
<ion-label>{{ 'schedule.recurring' | translate }}</ion-label> <ion-label class="ion-text-wrap" [innerHTML]="'schedule.recurring' | translate"></ion-label>
<ion-icon name="event_repeat"></ion-icon> <ion-icon name="event_repeat"></ion-icon>
</ion-segment-button> </ion-segment-button>
<ion-segment-button value="single" layout="icon-start"> <ion-segment-button value="single" layout="icon-start">
<ion-label>{{ 'schedule.single' | translate }}</ion-label> <ion-label class="ion-text-wrap" [innerHTML]="'schedule.single' | translate"></ion-label>
<ion-icon name="event_upcoming"></ion-icon> <ion-icon name="event_upcoming"></ion-icon>
</ion-segment-button> </ion-segment-button>
</ion-segment> </ion-segment>
@@ -59,7 +62,7 @@
> >
<stapps-calendar-view *ngSwitchCase="'calendar'" [layout]="layout"></stapps-calendar-view> <stapps-calendar-view *ngSwitchCase="'calendar'" [layout]="layout"></stapps-calendar-view>
<!-- Schedule view needs full week --> <!-- Schedule view needs full week -->
<stapps-schedule-view *ngSwitchCase="'recurring'" [layout]="layout"></stapps-schedule-view> <stapps-schedule-view *ngSwitchCase="'week-overview'" [layout]="layout"></stapps-schedule-view>
<stapps-single-events *ngSwitchCase="'single'"></stapps-single-events> <stapps-single-events *ngSwitchCase="'single'"></stapps-single-events>
</div> </div>

View File

@@ -41,7 +41,7 @@ import {ChooseEventsPageComponent} from './page/choose-events-page.component';
const settingsRoutes: Routes = [ const settingsRoutes: Routes = [
{path: 'schedule', redirectTo: 'schedule/calendar/now'}, {path: 'schedule', redirectTo: 'schedule/calendar/now'},
{path: 'schedule/calendar', redirectTo: 'schedule/calendar/now'}, {path: 'schedule/calendar', redirectTo: 'schedule/calendar/now'},
{path: 'schedule/recurring', redirectTo: 'schedule/recurring/now'}, {path: 'schedule/week-overview', redirectTo: 'schedule/week-overview/now'},
{path: 'schedule/single', redirectTo: 'schedule/single/now'}, {path: 'schedule/single', redirectTo: 'schedule/single/now'},
// calendar | recurring | single // calendar | recurring | single
{path: 'schedule/:mode/:date', component: SchedulePageComponent}, {path: 'schedule/:mode/:date', component: SchedulePageComponent},

View File

@@ -459,9 +459,9 @@
"view": { "view": {
"today": "Heute" "today": "Heute"
}, },
"recurring": "Stundenplan", "recurring": "Wochen&shy;übersicht",
"calendar": "Kalender", "calendar": "Kalender",
"single": "Einzeltermine", "single": "Einzel&shy;termine",
"addEventPage": { "addEventPage": {
"TITLE": "Termine Hinzufügen", "TITLE": "Termine Hinzufügen",
"PLACEHOLDER": "Termine", "PLACEHOLDER": "Termine",

View File

@@ -459,7 +459,7 @@
"view": { "view": {
"today": "Today" "today": "Today"
}, },
"recurring": "Recurring", "recurring": "Week Overview",
"calendar": "Calendar", "calendar": "Calendar",
"single": "Single Events", "single": "Single Events",
"addEventPage": { "addEventPage": {