Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.

Commit a740786

Browse files
feat: edit deck title in publish modal
1 parent e91e534 commit a740786

File tree

6 files changed

+118
-59
lines changed

6 files changed

+118
-59
lines changed

studio/src/app/components/feed/card/app-feed-card/app-feed-card.tsx

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import {Component, Prop, State, Watch} from '@stencil/core';
1+
import {Component, Event, EventEmitter, Prop, State, Watch} from '@stencil/core';
2+
3+
import {Subject, Subscription} from 'rxjs';
4+
import {debounceTime} from 'rxjs/operators';
25

36
import DateTimeFormatOptions = Intl.DateTimeFormatOptions;
47

@@ -39,8 +42,23 @@ export class AppFeedCard {
3942
@State()
4043
private formattedPublication: string;
4144

45+
@Event() private editCaption: EventEmitter<string>;
46+
47+
private captionSubscription: Subscription;
48+
private captionSubject: Subject<string> = new Subject<string>();
49+
4250
async componentWillLoad() {
4351
await this.formatPublication();
52+
53+
this.captionSubscription = this.captionSubject.pipe(debounceTime(500)).subscribe(async (title: string) => {
54+
this.editCaption.emit(title);
55+
});
56+
}
57+
58+
componentDidUnload() {
59+
if (this.captionSubscription) {
60+
this.captionSubscription.unsubscribe();
61+
}
4462
}
4563

4664
@Watch('publication')
@@ -53,7 +71,6 @@ export class AppFeedCard {
5371
});
5472
}
5573

56-
5774
private handleTagInput($event: UIEvent) {
5875
const tag: string = ($event.target as InputTargetEvent).value;
5976

@@ -88,6 +105,17 @@ export class AppFeedCard {
88105
});
89106
}
90107

108+
private onCaptionInput($event: UIEvent) {
109+
if (!this.editable) {
110+
return;
111+
}
112+
113+
const title: string = ($event as InputUIEvent).target.textContent;
114+
if (title && title !== undefined && title !== '') {
115+
this.captionSubject.next(title);
116+
}
117+
}
118+
91119
render() {
92120
return <ion-card class={this.editable ? "ion-no-margin" : undefined}>
93121
{this.renderCardContent()}
@@ -99,7 +127,7 @@ export class AppFeedCard {
99127
{this.renderMiniature()}
100128

101129
<ion-card-header>
102-
<ion-card-title class="ion-text-uppercase" contentEditable={this.editable}>{this.caption}</ion-card-title>
130+
<ion-card-title class="ion-text-uppercase" contentEditable={this.editable} onInput={(e: UIEvent) => this.onCaptionInput(e)}>{this.caption}</ion-card-title>
103131

104132
<ion-card-subtitle class="ion-text-lowercase">
105133
{this.renderTags()}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
interface InputTargetEvent extends EventTarget {
22
value: string;
33
}
4+
5+
interface InputUIEvent extends UIEvent {
6+
target: HTMLElement;
7+
}

studio/src/app/handlers/editor/deck-events/deck-events.handler.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ export class DeckEventsHandler {
286286
return;
287287
}
288288

289+
// TODO: Add a check, we should not update the title from the slide in case it would have been set in the publication
290+
289291
currentDeck.name = title;
290292

291293
const updatedDeck: Deck = await this.deckService.put(currentDeck);

studio/src/app/modals/editor/app-publish/app-publish.tsx

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
import {Component, Element, Listen, Prop, State} from '@stencil/core';
1+
import {Component, Element, Listen, State} from '@stencil/core';
22

33
import {take} from 'rxjs/operators';
44

55
import {AuthUser} from '../../../models/auth-user';
66

7+
8+
import {Deck} from '../../../models/deck';
9+
710
import {AuthService} from '../../../services/auth/auth.service';
11+
import {DeckEditorService} from '../../../services/deck/deck-editor.service';
12+
import {DeckService} from '../../../services/deck/deck.service';
13+
import {ErrorService} from '../../../services/error/error.service';
814

915
@Component({
1016
tag: 'app-publish',
@@ -16,20 +22,41 @@ export class AppPublish {
1622

1723
private authService: AuthService;
1824

19-
@Prop()
20-
caption: string;
25+
@State()
26+
private caption: string;
2127

22-
@Prop()
23-
description: string;
28+
@State()
29+
private description: string;
2430

2531
@State()
2632
private author: string;
2733

2834
@State()
2935
private today: Date = new Date();
3036

37+
@State()
38+
private disablePublish: boolean = false;
39+
40+
private deckEditorService: DeckEditorService;
41+
private deckService: DeckService;
42+
43+
private errorService: ErrorService;
44+
3145
constructor() {
3246
this.authService = AuthService.getInstance();
47+
48+
this.deckEditorService = DeckEditorService.getInstance();
49+
this.deckService = DeckService.getInstance();
50+
51+
this.errorService = ErrorService.getInstance();
52+
}
53+
54+
async componentWillLoad() {
55+
this.deckEditorService.watch().pipe(take(1)).subscribe(async (deck: Deck) => {
56+
if (deck) {
57+
this.caption = deck.name;
58+
}
59+
});
3360
}
3461

3562
async componentDidLoad() {
@@ -49,6 +76,44 @@ export class AppPublish {
4976
await (this.el.closest('ion-modal') as HTMLIonModalElement).dismiss();
5077
}
5178

79+
@Listen('editCaption')
80+
async onEditCaption(e: CustomEvent) {
81+
await this.updateDeck(e.detail);
82+
}
83+
84+
private updateDeck(title: string): Promise<void> {
85+
return new Promise<void>(async (resolve) => {
86+
if (!title || title === undefined || title === '') {
87+
resolve();
88+
return;
89+
}
90+
91+
this.disablePublish = true;
92+
93+
try {
94+
this.deckEditorService.watch().pipe(take(1)).subscribe(async (deck: Deck) => {
95+
if (!deck || !deck.id) {
96+
this.disablePublish = false;
97+
resolve();
98+
return;
99+
}
100+
101+
deck.name = title;
102+
103+
const updatedDeck: Deck = await this.deckService.put(deck);
104+
this.deckEditorService.next(updatedDeck);
105+
106+
this.disablePublish = false;
107+
});
108+
} catch (err) {
109+
this.disablePublish = false;
110+
this.errorService.error(err);
111+
}
112+
113+
resolve();
114+
});
115+
}
116+
52117
render() {
53118
return [
54119
<ion-header>
@@ -62,12 +127,15 @@ export class AppPublish {
62127
</ion-toolbar>
63128
</ion-header>,
64129
<ion-content padding>
65-
<p>Edit the title and summary of your presentation and add or change tags (up to 5) to make your presentation more inviting to readers</p>
130+
<p>Edit the title and summary of your presentation and add or change tags (up to 5) to make your
131+
presentation more inviting to readers</p>
66132

67-
<app-feed-card compact={false} miniature={false} editable={true} author={this.author} publication={this.today} caption={this.caption} description={this.description}></app-feed-card>
133+
<app-feed-card compact={false} miniature={false} editable={true} author={this.author}
134+
publication={this.today} caption={this.caption}
135+
description={this.description}></app-feed-card>
68136

69137
<div class="ion-padding ion-text-center">
70-
<ion-button shape="round" color="primary">
138+
<ion-button shape="round" color="primary" disabled={this.disablePublish}>
71139
<ion-label class="ion-text-uppercase">Publish now</ion-label>
72140
</ion-button>
73141
</div>

studio/src/app/pages/editor/app-editor/app-editor.tsx

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ import {EditorHelper} from '../../../helpers/editor/editor.helper';
2222
import {DeckAction} from '../../../popovers/editor/app-deck-actions/deck-action';
2323
import {DeckEditorService} from '../../../services/deck/deck-editor.service';
2424

25-
interface FirstSlideContent {
26-
title: string;
27-
content: string;
28-
}
29-
3025
@Component({
3126
tag: 'app-editor',
3227
styleUrl: 'app-editor.scss'
@@ -309,33 +304,6 @@ export class AppEditor {
309304
});
310305
}
311306

312-
private getFirstSlideContent(): Promise<FirstSlideContent> {
313-
return new Promise<FirstSlideContent>(async (resolve) => {
314-
let title: string = '';
315-
let content: string = '';
316-
317-
const slide: HTMLElement = this.el.querySelector('deckgo-deck > *:first-child');
318-
319-
if (slide && slide.tagName && slide.tagName.toLowerCase().indexOf('deckgo-slide') > -1) {
320-
const titleElement: HTMLElement = slide.querySelector('[slot="title"]');
321-
const contentElement: HTMLElement = slide.querySelector('[slot="content"]');
322-
323-
if (titleElement) {
324-
title = titleElement.textContent;
325-
}
326-
327-
if (contentElement) {
328-
content = contentElement.textContent;
329-
}
330-
}
331-
332-
resolve({
333-
title: title,
334-
content: content
335-
});
336-
});
337-
}
338-
339307
@Listen('actionOpenSlideAdd')
340308
async onActionOpenSlideAdd($event: CustomEvent) {
341309
if (!$event || !$event.detail) {
@@ -403,14 +371,8 @@ export class AppEditor {
403371
return;
404372
}
405373

406-
const firstSlide: FirstSlideContent = await this.getFirstSlideContent();
407-
408374
const modal: HTMLIonModalElement = await this.modalController.create({
409-
component: 'app-publish',
410-
componentProps: {
411-
caption: firstSlide.title,
412-
description: firstSlide.content
413-
}
375+
component: 'app-publish'
414376
});
415377

416378
modal.onDidDismiss().then(async (_detail: OverlayEventDetail) => {

studio/src/components.d.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import '@stencil/core';
99

1010
import '@ionic/core';
11+
import 'ionicons';
1112
import 'deckdeckgo';
1213
import 'deckdeckgo-inline-editor';
13-
import 'ionicons';
1414
import {
1515
EventEmitter,
1616
} from '@stencil/core';
@@ -107,6 +107,7 @@ export namespace Components {
107107
'description'?: string;
108108
'editable'?: boolean;
109109
'miniature'?: boolean;
110+
'onEditCaption'?: (event: CustomEvent<string>) => void;
110111
'publication'?: Date;
111112
}
112113

@@ -119,14 +120,8 @@ export namespace Components {
119120
interface AppGif {}
120121
interface AppGifAttributes extends StencilHTMLAttributes {}
121122

122-
interface AppPublish {
123-
'caption': string;
124-
'description': string;
125-
}
126-
interface AppPublishAttributes extends StencilHTMLAttributes {
127-
'caption'?: string;
128-
'description'?: string;
129-
}
123+
interface AppPublish {}
124+
interface AppPublishAttributes extends StencilHTMLAttributes {}
130125

131126
interface AppSlideNavigate {
132127
'slides': string[];

0 commit comments

Comments
 (0)