Skip to content

Commit

Permalink
feat: add open Facebook Event button (#143)
Browse files Browse the repository at this point in the history
Co-authored-by: Marc Schmidt <[email protected]>
  • Loading branch information
AnSch1510 and MaSch0212 authored Jul 18, 2024
1 parent 3866477 commit ebfb77c
Show file tree
Hide file tree
Showing 31 changed files with 2,210 additions and 86 deletions.
53 changes: 0 additions & 53 deletions src/client/src/app/+state/events/actions/commit-event.action.ts

This file was deleted.

58 changes: 58 additions & 0 deletions src/client/src/app/+state/events/actions/update-event.action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { inject } from '@angular/core';
import { on } from '@ngrx/store';
import { produce } from 'immer';
import { switchMap } from 'rxjs';

import { EventAdministrationService } from '../../../api/services';
import { createHttpAction, handleHttpAction, onHttpAction, toHttpAction } from '../../action-state';
import { createFunctionalEffect } from '../../functional-effect';
import { Effects, Reducers } from '../../utils';
import { EVENTS_ACTION_SCOPE } from '../consts';
import { selectEventsActionState } from '../events.selectors';
import { EventsFeatureState, eventEntityAdapter } from '../events.state';

export const updateEventAction = createHttpAction<{
eventId: string;
commit?: boolean;
externalUri?: string;
}>()(EVENTS_ACTION_SCOPE, 'Update Event');

export const updateEventReducers: Reducers<EventsFeatureState> = [
on(updateEventAction.success, (state, { props }) =>
eventEntityAdapter.mapOne(
{
id: props.eventId,
map: produce(draft => {
draft.staged = props.commit ? props.commit : undefined;
draft.externalUri = props.externalUri != undefined ? props.externalUri : undefined;
}),
},
state
)
),
handleHttpAction('update', updateEventAction),
];

export const updateEventEffects: Effects = {
updateEvent$: createFunctionalEffect.dispatching((api = inject(EventAdministrationService)) =>
onHttpAction(updateEventAction, selectEventsActionState('update')).pipe(
switchMap(({ props }) => toHttpAction(updateEvent(api, props), updateEventAction, props))
)
),
};

async function updateEvent(
api: EventAdministrationService,
props: ReturnType<typeof updateEventAction>['props']
) {
const response = await api.updateEvent({
eventId: props.eventId,
body: {
commit: props.commit ? props.commit : undefined,
externalUri: props.externalUri ?? undefined,
},
});
return response.ok
? updateEventAction.success(props, undefined)
: updateEventAction.error(props, response);
}
2 changes: 1 addition & 1 deletion src/client/src/app/+state/events/events.actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export { addEventPreconfigAction } from './actions/add-event-preconfig.action';
export { addEventTimeslotAction } from './actions/add-event-timeslot.action';
export { addEventAction } from './actions/add-event.action';
export { commitEventAction } from './actions/commit-event.action';
export { updateEventAction } from './actions/update-event.action';
export { eventTimeslotRegistrationChangedAction } from './actions/event-timeslot-registration-changed.action';
export { addPlayerToEventPreconfigurationAction } from './actions/add-player-to-preconfig.action';
export { buildEventInstancesAction } from './actions/build-event-instances.action';
Expand Down
4 changes: 2 additions & 2 deletions src/client/src/app/+state/events/events.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { addEventTimeslotEffects } from './actions/add-event-timeslot.action';
import { addEventEffects } from './actions/add-event.action';
import { addPlayerToEventPreconfigurationEffects } from './actions/add-player-to-preconfig.action';
import { buildEventInstancesEffects } from './actions/build-event-instances.action';
import { commitEventEffects } from './actions/commit-event.action';
import { loadEventAction, loadEventEffects } from './actions/load-event.action';
import { loadEventsEffects } from './actions/load-events.action';
import { removeEventPreconfigEffects } from './actions/remove-event-preconfig.action';
Expand All @@ -15,6 +14,7 @@ import { removeEventAction, removeEventEffects } from './actions/remove-event.ac
import { removePlayerFromPreconfigEffects } from './actions/remove-player-from-preconfig.action';
import { startEventEffects } from './actions/start-event.action';
import { updateEventTimeslotEffects } from './actions/update-event-timeslot.action';
import { updateEventEffects } from './actions/update-event.action';
import {
eventTimeslotRegistrationChangedAction,
resetEventsActionStateAction,
Expand All @@ -36,7 +36,7 @@ export const eventsFeatureEffects: Effects[] = [
removeEventEffects,
removePlayerFromPreconfigEffects,
startEventEffects,
commitEventEffects,
updateEventEffects,
updateEventTimeslotEffects,
{
eventUpdated$: createFunctionalEffect.dispatching((events = inject(RealtimeEventsService)) =>
Expand Down
4 changes: 2 additions & 2 deletions src/client/src/app/+state/events/events.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { addEventTimeslotReducers } from './actions/add-event-timeslot.action';
import { addEventReducers } from './actions/add-event.action';
import { addPlayerToEventPreconfigurationReducers } from './actions/add-player-to-preconfig.action';
import { buildEventInstancesReducers } from './actions/build-event-instances.action';
import { commitEventReducers } from './actions/commit-event.action';
import { eventTimeslotRegistrationChangedReducers } from './actions/event-timeslot-registration-changed.action';
import { loadEventReducers } from './actions/load-event.action';
import { loadEventsReducers } from './actions/load-events.action';
Expand All @@ -16,6 +15,7 @@ import { removePlayerFromPreconfigReducers } from './actions/remove-player-from-
import { resetEventsActionStateReducers } from './actions/reset-events-action-state.action';
import { startEventReducers } from './actions/start-event.action';
import { updateEventTimeslotReducers } from './actions/update-event-timeslot.action';
import { updateEventReducers } from './actions/update-event.action';
import { EventsFeatureState, initialEventsFeatureState } from './events.state';

export const eventsReducer = createReducer<EventsFeatureState>(
Expand All @@ -26,7 +26,7 @@ export const eventsReducer = createReducer<EventsFeatureState>(
...addEventReducers,
...addPlayerToEventPreconfigurationReducers,
...buildEventInstancesReducers,
...commitEventReducers,
...updateEventReducers,
...eventTimeslotRegistrationChangedReducers,
...loadEventReducers,
...loadEventsReducers,
Expand Down
4 changes: 2 additions & 2 deletions src/client/src/app/+state/events/events.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type EventsFeatureState = EntityState<Event> & {
add: ActionState;
remove: ActionState;
start: ActionState;
commit: ActionState;
update: ActionState;
addTimeslot: ActionState;
removeTimeslot: ActionState;
buildInstances: ActionState;
Expand All @@ -36,7 +36,7 @@ export const initialEventsFeatureState: EventsFeatureState = eventEntityAdapter.
add: initialActionState,
remove: initialActionState,
start: initialActionState,
commit: initialActionState,
update: initialActionState,
addTimeslot: initialActionState,
removeTimeslot: initialActionState,
buildInstances: initialActionState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,37 @@
</div>
</p-card>

<div class="mt-4 flex flex-row items-center gap-2">
<h2 class="m-0 grow">{{ translations.events_facebookLink() }}</h2>
<div>
<p-inputGroup>
<button
type="button"
pButton
[label]="
externalUri() && externalUri() !== undefined && externalUri()?.length !== 0
? translations.shared_edit()
: translations.shared_add()
"
icon="i-[mdi--facebook]"
(click)="modifyExternalUriDialog.open(externalUri())"
></button>
<button
type="button"
pButton
class="bg-surface-a text-primary"
icon="i-[mdi--arrow-right-circle]"
[disabled]="
externalUri() && externalUri() !== undefined && externalUri()?.length !== 0
? false
: true
"
(click)="openExternalUri()"
></button>
</p-inputGroup>
</div>
</div>

<div class="mt-4 flex flex-row items-center gap-2">
<h2 class="m-0 grow">{{ translations.events_timeslots() }}</h2>
<span
Expand Down Expand Up @@ -189,6 +220,7 @@ <h3 class="m-0 flex flex-row items-center gap-4 px-2">
}

<app-event-timeslot-dialog #createTimeslotDialog [event]="event" />
<app-modify-external-uri-dialog #modifyExternalUriDialog [event]="event" />
} @else {
<div class="mt-16 flex flex-col items-center gap-8">
<span class="i-[mdi--close-octagon] text-[8rem] text-red-500"></span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CommonModule, formatDate } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { InterpolatePipe, interpolate } from '@ngneers/signal-translate';
import { Actions, ofType } from '@ngrx/effects';
Expand All @@ -9,19 +10,23 @@ import { AccordionModule } from 'primeng/accordion';
import { ConfirmationService } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
import { CardModule } from 'primeng/card';
import { InputGroupModule } from 'primeng/inputgroup';
import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
import { InputTextModule } from 'primeng/inputtext';
import { MessagesModule } from 'primeng/messages';
import { ProgressSpinnerModule } from 'primeng/progressspinner';
import { TooltipModule } from 'primeng/tooltip';
import { filter, map, timer } from 'rxjs';

import { ModifyExternalUriDialogComponent } from './modify-external-uri-dialog/modify-external-uri-dialog.component';
import { hasActionFailed, isActionBusy } from '../../../+state/action-state';
import {
buildEventInstancesAction,
removeEventAction,
selectEvent,
selectEventsActionState,
startEventAction,
commitEventAction,
updateEventAction,
} from '../../../+state/events';
import { keepEventLoaded } from '../../../+state/events/events.utils';
import { mapSelectors } from '../../../+state/maps';
Expand All @@ -44,8 +49,13 @@ import { EventTimeslotDialogComponent } from '../event-timeslot-dialog/event-tim
CommonModule,
EventFormComponent,
EventTimeslotDialogComponent,
FormsModule,
InputGroupAddonModule,
InputGroupModule,
InputTextModule,
InterpolatePipe,
MessagesModule,
ModifyExternalUriDialogComponent,
ProgressSpinnerModule,
RouterLink,
TooltipModule,
Expand Down Expand Up @@ -77,6 +87,8 @@ export class EventDetailsComponent {
protected readonly isStartBusy = computed(() => isActionBusy(this.startActionState()));
protected readonly isBuildBusy = computed(() => isActionBusy(this.buildActionState()));
protected readonly event = selectSignal(computed(() => selectEvent(this.eventId())));
protected readonly externalUri = computed(() => this.event()?.externalUri);
// protected readonly externalUriLoaded = computed(() => )
protected readonly timeslots = computed(() =>
[...(this.event()?.timeslots ?? [])].sort((a, b) => compareTimes(a.time, b.time))
);
Expand Down Expand Up @@ -198,7 +210,7 @@ export class EventDetailsComponent {
rejectButtonStyleClass: 'p-button-text',
accept: () => {
this._store.dispatch(
commitEventAction({
updateEventAction({
eventId: event.id,
commit: true,
})
Expand All @@ -207,6 +219,26 @@ export class EventDetailsComponent {
});
}

protected updateExternalUri() {
const event = this.event();
if (!event) return;

this._store.dispatch(
updateEventAction({
eventId: event.id,
externalUri:
this.externalUri() ?? undefined,
})
);
}

protected openExternalUri() {
const url = this.externalUri();
if (url) {
window.location.href = url;
}
}

protected buildInstances() {
this._store.dispatch(buildEventInstancesAction({ eventId: this.eventId() }));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<p-dialog
[visible]="visible()"
(visibleChange)="visible.set($event)"
[modal]="true"
[header]="translations.events_facebookLink()"
>
<p-inputGroup>
<input
#inputElement
class="w-full max-w-[350px]"
type="text"
pInputText
autocomplete="off"
[ngModel]="externalUri()"
(ngModelChange)="externalUri.set($event)"
/>
<button pButton icon="i-[mdi--backspace]" (click)="clearExternalUri()"></button>
</p-inputGroup>

<ng-template pTemplate="footer">
<p-button [text]="true" [label]="translations.shared_cancel()" (onClick)="visible.set(false)" />
<p-button [label]="translations.shared_save()" (onClick)="updateExternalUri()" />
</ng-template>
</p-dialog>
Loading

0 comments on commit ebfb77c

Please sign in to comment.