basic single event dashboard
This commit is contained in:
parent
02442a162a
commit
aec1fd5ad1
@ -34,7 +34,13 @@ export class DetailView<T> {
|
|||||||
config = input.required<DetailViewConfig<T>>();
|
config = input.required<DetailViewConfig<T>>();
|
||||||
|
|
||||||
getFormattedValue(row: DetailViewRow<T>, data: T): string {
|
getFormattedValue(row: DetailViewRow<T>, data: T): string {
|
||||||
const value = row.getValue ? row.getValue(data) : data[row.attribute];
|
let value : any;
|
||||||
|
try {
|
||||||
|
value = row.getValue ? row.getValue(data) : data[row.attribute];
|
||||||
|
}catch (e) {
|
||||||
|
value = '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (row.component) {
|
if (row.component) {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<full-calendar #calendar [options]="calendarOptions"></full-calendar>
|
<full-calendar #calendar [options]="calendarOptions"></full-calendar>
|
||||||
</div>
|
</div>
|
||||||
{{"workflow:"+workflow()}}
|
|
||||||
<rs-daisy-modal [isOpen]="workflow() == 'create'" (closeClick)="closeDialog()">
|
<rs-daisy-modal [isOpen]="workflow() == 'create'" (closeClick)="closeDialog()">
|
||||||
@if (workflow() == 'create') {
|
@if (workflow() == 'create') {
|
||||||
<app-create-event-form (ready)="closeDialog()" [date]="selectedDate()"
|
<app-create-event-form (ready)="closeDialog()" [date]="selectedDate()"
|
||||||
@ -14,10 +14,29 @@
|
|||||||
}
|
}
|
||||||
</rs-daisy-modal>
|
</rs-daisy-modal>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@if (workflow() == 'event-dashboard' && selectedEvent()) {
|
@if (workflow() == 'event-dashboard' && selectedEvent()) {
|
||||||
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()" [modalBoxStyleClass]="'max-w-none w-2xl'">
|
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()" [modalBoxStyleClass]="'max-w-none w-2xl'">
|
||||||
<app-single-event-dashboard [event]="selectedEvent()"></app-single-event-dashboard>
|
<app-single-event-dashboard [event]="selectedEvent()"
|
||||||
|
(action)="onDashboardAction($event)"
|
||||||
|
></app-single-event-dashboard>
|
||||||
</rs-daisy-modal>
|
</rs-daisy-modal>
|
||||||
}
|
}
|
||||||
|
<!--@if (workflow() == 'event-delete' && selectedEvent()) {
|
||||||
|
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()" []="'max-w-none w-2xl'">
|
||||||
|
delete event
|
||||||
|
</rs-daisy-modal>
|
||||||
|
}-->
|
||||||
|
@if (workflow() == 'event-cancel' && selectedEvent()) {
|
||||||
|
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()" [modalBoxStyleClass]="'max-w-none w-2xl'">
|
||||||
|
cancel
|
||||||
|
</rs-daisy-modal>
|
||||||
|
}
|
||||||
|
|
||||||
|
@for (dialogDefinition of dialogs; track dialogDefinition) {
|
||||||
|
|
||||||
|
@if (dialogDefinition.isRendered()) {
|
||||||
|
<rs-daisy-modal [isOpen]="true" (closeClick)="closeDialog()" [modalBoxStyleClass]="'max-w-none w-2xl'">
|
||||||
|
<ng-container *ngComponentOutlet="dialogDefinition.component; inputs: dialogDefinition.componentInputs ? dialogDefinition.componentInputs() : {}"></ng-container>
|
||||||
|
</rs-daisy-modal>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { AfterViewInit, Component, effect, ElementRef, inject, OnInit, signal, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, effect, ElementRef, inject, OnInit, signal, Type, ViewChild } from '@angular/core';
|
||||||
import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular';
|
import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular';
|
||||||
import { CalendarOptions, EventInput } from '@fullcalendar/core';
|
import { CalendarOptions, EventInput } from '@fullcalendar/core';
|
||||||
|
|
||||||
@ -6,17 +6,20 @@ import dayGridPlugin from '@fullcalendar/daygrid';
|
|||||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||||
import listPlugin from '@fullcalendar/list';
|
import listPlugin from '@fullcalendar/list';
|
||||||
import interactionPlugin from '@fullcalendar/interaction';
|
import interactionPlugin from '@fullcalendar/interaction';
|
||||||
import { Modal } from '@rschneider/ng-daisyui';
|
import { Button, Modal } from '@rschneider/ng-daisyui';
|
||||||
import { CreateEventForm } from '../create-event-form/create-event-form';
|
import { CreateEventForm } from '../create-event-form/create-event-form';
|
||||||
import { CalendarService } from '../../services/calendar.service';
|
import { CalendarService } from '../../services/calendar.service';
|
||||||
import { CalendarEventDto, EventsInRangeDTO } from '../../models/events-in-range-dto.model';
|
import { CalendarEventDto, EventsInRangeDTO } from '../../models/events-in-range-dto.model';
|
||||||
import { map } from 'rxjs';
|
import { map } from 'rxjs';
|
||||||
import { SingleEventDashboard } from './single-event-dashboard/single-event-dashboard';
|
import { SingleEventDashboard } from './single-event-dashboard/single-event-dashboard';
|
||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe, NgComponentOutlet } from '@angular/common';
|
||||||
|
import {
|
||||||
|
SingleEventDashboardEventDelete
|
||||||
|
} from './single-event-dashboard-event-delete/single-event-dashboard-event-delete';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-calendar-view',
|
selector: 'app-calendar-view',
|
||||||
imports: [FullCalendarModule, Modal, CreateEventForm, SingleEventDashboard, JsonPipe],
|
imports: [FullCalendarModule, Modal,NgComponentOutlet, CreateEventForm, SingleEventDashboard, JsonPipe],
|
||||||
templateUrl: './calendar-view.html',
|
templateUrl: './calendar-view.html',
|
||||||
styleUrl: './calendar-view.css',
|
styleUrl: './calendar-view.css',
|
||||||
})
|
})
|
||||||
@ -32,6 +35,7 @@ export class CalendarView implements OnInit, AfterViewInit {
|
|||||||
selectedEvent = signal<CalendarEventDto|undefined>(undefined)
|
selectedEvent = signal<CalendarEventDto|undefined>(undefined)
|
||||||
|
|
||||||
calendarOptions: CalendarOptions;
|
calendarOptions: CalendarOptions;
|
||||||
|
dialogs: DialogConfig[] = [];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
@ -62,6 +66,21 @@ export class CalendarView implements OnInit, AfterViewInit {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.dialogs = [
|
||||||
|
{
|
||||||
|
component: SingleEventDashboardEventDelete,
|
||||||
|
isRendered: () => this.workflow() == 'event-delete',
|
||||||
|
// isRendered: () => true,
|
||||||
|
closeClick: () => this.closeDialog(),
|
||||||
|
modalBoxStyleClass: 'max-w-none w-2xl',
|
||||||
|
componentInputs: () => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchEvents(fetchInfo: any, successCallback: (events: EventInput[]) => void, failureCallback: (error: any) => void): void {
|
fetchEvents(fetchInfo: any, successCallback: (events: EventInput[]) => void, failureCallback: (error: any) => void): void {
|
||||||
@ -139,4 +158,23 @@ export class CalendarView implements OnInit, AfterViewInit {
|
|||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.workflow.set('');
|
this.workflow.set('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDashboardAction(action: string){
|
||||||
|
console.info("dashboard event", action);
|
||||||
|
switch (action) {
|
||||||
|
case 'event_delete':
|
||||||
|
this.workflow.set('event-delete');
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DialogConfig{
|
||||||
|
component: Type<any>;
|
||||||
|
componentInputs?: () => { [key: string]: any };
|
||||||
|
closeClick: () => void,
|
||||||
|
modalBoxStyleClass: string
|
||||||
|
isRendered: () => boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<h2 class="card-title text-center">{{ title() }}</h2>
|
<h2 class="card-title text-center">{{ title() }}</h2>
|
||||||
<p class="text-center">{{ description() }}</p>
|
<p class="text-center">{{ description() }}</p>
|
||||||
<div class="card-actions justify-end">
|
<div class="card-actions justify-end">
|
||||||
<button class="btn btn-primary">
|
<button class="btn btn-primary" (click)="onClick();">
|
||||||
<!-- Using the new @if control flow -->
|
<!-- Using the new @if control flow -->
|
||||||
@if (svgIcon()) {
|
@if (svgIcon()) {
|
||||||
<span [innerHTML]="svgIcon() | safeHtml"></span>
|
<span [innerHTML]="svgIcon() | safeHtml"></span>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, computed, HostBinding, input } from '@angular/core';
|
import { Component, computed, HostBinding, input, output } from '@angular/core';
|
||||||
import { SafeHtmlPipe } from '../../../../../pipes/safe-html-pipe';
|
import { SafeHtmlPipe } from '../../../../../pipes/safe-html-pipe';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -11,10 +11,12 @@ import { SafeHtmlPipe } from '../../../../../pipes/safe-html-pipe';
|
|||||||
styleUrl: './single-event-dashboard-card.css',
|
styleUrl: './single-event-dashboard-card.css',
|
||||||
})
|
})
|
||||||
export class SingleEventDashboardCard {
|
export class SingleEventDashboardCard {
|
||||||
title= input<string>();
|
title = input<string>();
|
||||||
description= input<string>();
|
description = input<string>();
|
||||||
buttonTitle= input<string>();
|
buttonTitle = input<string>();
|
||||||
svgIcon= input<string>();
|
svgIcon = input<string>();
|
||||||
|
onAction = output<void>();
|
||||||
|
|
||||||
|
|
||||||
// 1. Define the Input Signal to receive class names as a string or array
|
// 1. Define the Input Signal to receive class names as a string or array
|
||||||
// Example: 'grow-2 align-center'
|
// Example: 'grow-2 align-center'
|
||||||
@ -41,4 +43,7 @@ export class SingleEventDashboardCard {
|
|||||||
return this.hostClasses();
|
return this.hostClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected onClick() {
|
||||||
|
this.onAction.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
@if (config) {
|
||||||
|
<app-detail-view
|
||||||
|
[config]="config"
|
||||||
|
></app-detail-view>
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
import { Component, effect, input } from '@angular/core';
|
||||||
|
import { CalendarEventDto } from '../../../models/events-in-range-dto.model';
|
||||||
|
import { DetailView, DetailViewConfig } from '../../../../../components/detail-view/detail-view';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-single-event-dashboard-event-delete',
|
||||||
|
imports: [
|
||||||
|
|
||||||
|
DetailView,
|
||||||
|
],
|
||||||
|
templateUrl: './single-event-dashboard-event-delete.html',
|
||||||
|
styleUrl: './single-event-dashboard-event-delete.css',
|
||||||
|
})
|
||||||
|
export class SingleEventDashboardEventDelete {
|
||||||
|
|
||||||
|
event = input<CalendarEventDto>();
|
||||||
|
|
||||||
|
config: DetailViewConfig<CalendarEventDto> | undefined;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
effect(() => {
|
||||||
|
|
||||||
|
this.config = {
|
||||||
|
data: this.event()!,
|
||||||
|
|
||||||
|
rows: [{
|
||||||
|
attribute: 'id',
|
||||||
|
getTitle: 'Esemény azonosító',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attribute: 'title',
|
||||||
|
getTitle: 'Esemény neve',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attribute: 'startTime',
|
||||||
|
getTitle: 'Kezdési időpont',
|
||||||
|
format: 'datetime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attribute: 'eventType',
|
||||||
|
getTitle: 'Esemény típusa',
|
||||||
|
getValue: obj => obj.eventType.name,
|
||||||
|
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -15,6 +15,7 @@
|
|||||||
[description]="card.description"
|
[description]="card.description"
|
||||||
[buttonTitle]="card.buttonTitle"
|
[buttonTitle]="card.buttonTitle"
|
||||||
[styleClass]="'flex-1'"
|
[styleClass]="'flex-1'"
|
||||||
|
(onAction)="onCardAction(card.action)"
|
||||||
|
|
||||||
></app-single-event-dashboard-card>
|
></app-single-event-dashboard-card>
|
||||||
<!-- [customClasses]="'flex-[50_1_0] w-50' "-->
|
<!-- [customClasses]="'flex-[50_1_0] w-50' "-->
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, effect, input } from '@angular/core';
|
import { Component, effect, input, output } from '@angular/core';
|
||||||
import { CalendarEventDto } from '../../../models/events-in-range-dto.model';
|
import { CalendarEventDto } from '../../../models/events-in-range-dto.model';
|
||||||
import { DetailView, DetailViewConfig } from '../../../../../components/detail-view/detail-view';
|
import { DetailView, DetailViewConfig } from '../../../../../components/detail-view/detail-view';
|
||||||
import { SvgIcons } from '../../../../../svg-icons';
|
import { SvgIcons } from '../../../../../svg-icons';
|
||||||
@ -16,42 +16,15 @@ import { SingleEventDashboardCard } from '../single-event-dashboard-card/single-
|
|||||||
export class SingleEventDashboard {
|
export class SingleEventDashboard {
|
||||||
|
|
||||||
event = input<CalendarEventDto>();
|
event = input<CalendarEventDto>();
|
||||||
|
action = output<string>();
|
||||||
config: DetailViewConfig<CalendarEventDto> | undefined;
|
config: DetailViewConfig<CalendarEventDto> | undefined;
|
||||||
|
|
||||||
cards: CardConfig[] = [
|
cards: CardConfig[] = [];
|
||||||
{
|
|
||||||
buttonTitle: 'Szerkesztés',
|
|
||||||
title: 'Szerkesztés',
|
|
||||||
svgIcon: SvgIcons.heorPencilSquare,
|
|
||||||
description: 'Az esemény módosítása',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonTitle: 'Lemondás',
|
|
||||||
title: 'Esemény lemondása',
|
|
||||||
svgIcon: SvgIcons.heroXcircle,
|
|
||||||
description: 'Az esemény lemondása, email küldése a jelentkezőknek',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonTitle: 'Törlése',
|
|
||||||
title: 'Esemény törlése',
|
|
||||||
svgIcon: SvgIcons.heroTrash,
|
|
||||||
description: 'Az esemény törlése',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonTitle: 'Bejelentkezés',
|
|
||||||
title: 'Időpont foglalás',
|
|
||||||
svgIcon: SvgIcons.heroUserPlus,
|
|
||||||
description: 'Időpont foglalása eseményre',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttonTitle: 'Lemondás',
|
|
||||||
title: 'Lemondása',
|
|
||||||
svgIcon: SvgIcons.heroUserMinus,
|
|
||||||
description: 'Az időpont lemondása',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
|
|
||||||
effect(() => {
|
effect(() => {
|
||||||
this.config = {
|
this.config = {
|
||||||
data: this.event()!,
|
data: this.event()!,
|
||||||
@ -78,8 +51,60 @@ export class SingleEventDashboard {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
this.cards = [
|
||||||
|
{
|
||||||
|
buttonTitle: 'Szerkesztés',
|
||||||
|
title: 'Szerkesztés',
|
||||||
|
svgIcon: SvgIcons.heorPencilSquare,
|
||||||
|
description: 'Az esemény módosítása',
|
||||||
|
action: 'event_edit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonTitle: 'Lemondás',
|
||||||
|
title: 'Esemény lemondása',
|
||||||
|
svgIcon: SvgIcons.heroXcircle,
|
||||||
|
description: 'Az esemény lemondása',
|
||||||
|
action: 'event_cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonTitle: 'Törlés',
|
||||||
|
title: 'Esemény törlése',
|
||||||
|
svgIcon: SvgIcons.heroTrash,
|
||||||
|
description: 'Az esemény törlése',
|
||||||
|
action: 'event_delete',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonTitle: 'Megnézem',
|
||||||
|
title: 'Foglalások',
|
||||||
|
svgIcon: SvgIcons.heroUserGroup,
|
||||||
|
description: 'Foglalások megtekintése',
|
||||||
|
action: 'event_bookings',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonTitle: 'Bejelentkezés',
|
||||||
|
title: 'Időpont foglalás',
|
||||||
|
svgIcon: SvgIcons.heroUserPlus,
|
||||||
|
description: 'Időpont foglalása eseményre',
|
||||||
|
action: 'user_booking',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonTitle: 'Lemondás',
|
||||||
|
title: 'Lemondás',
|
||||||
|
svgIcon: SvgIcons.heroUserMinus,
|
||||||
|
description: 'Az időpont lemondása',
|
||||||
|
action: 'user_cancel',
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCardAction (action: string|undefined) {
|
||||||
|
if ( action ){
|
||||||
|
this.action.emit(action);
|
||||||
|
}
|
||||||
|
console.info("card action", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected readonly SvgIcons = SvgIcons;
|
protected readonly SvgIcons = SvgIcons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,4 +113,5 @@ export interface CardConfig {
|
|||||||
description?: string;
|
description?: string;
|
||||||
buttonTitle?: string;
|
buttonTitle?: string;
|
||||||
svgIcon?: string;
|
svgIcon?: string;
|
||||||
|
action?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,5 +35,9 @@ export class SvgIcons {
|
|||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
|
public static heroUserGroup = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
|
||||||
|
</svg>
|
||||||
|
`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user