Skip to content

Commit 97c593c

Browse files
Add publish draft button in staging page (#5077)
* Add publish draft button * [pre-commit.ci lite] apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 4534959 commit 97c593c

File tree

8 files changed

+148
-2
lines changed

8 files changed

+148
-2
lines changed

contentcuration/contentcuration/frontend/channelEdit/pages/StagingTreePage/index.vue

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@
226226
{{ $tr('openSummaryDetailsDialogBtn') }}
227227
</VBtn>
228228

229+
<VBtn
230+
color="primary"
231+
data-test="display-publish-draft-dialog-btn"
232+
@click="displayPublishDraftDialog = true"
233+
>
234+
{{ $tr('publishDraft') }}
235+
</VBtn>
236+
229237
<VBtn
230238
color="primary"
231239
data-test="display-deploy-dialog-btn"
@@ -289,6 +297,46 @@
289297
</VFlex>
290298
</VLayout>
291299
</KModal>
300+
301+
<KModal
302+
v-if="displayPublishDraftDialog"
303+
data-test="publish-draft-dialog"
304+
:title="$tr('publishDraft')"
305+
:submitText="$tr('confirmPublishDraftBtn')"
306+
:submitDisabled="isPublishingDraft"
307+
:cancelDisabled="isPublishingDraft"
308+
:cancelText="$tr('cancelPublishDraftBtn')"
309+
@submit="onPublishDraftClick"
310+
@cancel="displayPublishDraftDialog = false"
311+
>
312+
<p>{{ $tr('publishDraftDialogDescription') }}</p>
313+
314+
<VLayout data-test="deploy-dialog-live-resources">
315+
<VFlex
316+
xs4
317+
class="font-weight-bold"
318+
>
319+
{{ $tr('liveResources') }}:
320+
</VFlex>
321+
<VFlex>
322+
{{ $tr('topicsCount', { count: topicsCountLive }) }},
323+
{{ $tr('resourcesCount', { count: resourcesCountLive }) }}
324+
</VFlex>
325+
</VLayout>
326+
327+
<VLayout data-test="deploy-dialog-staged-resources">
328+
<VFlex
329+
xs4
330+
class="font-weight-bold"
331+
>
332+
{{ $tr('stagedResources') }}:
333+
</VFlex>
334+
<VFlex>
335+
{{ $tr('topicsCount', { count: topicsCountStaged }) }},
336+
{{ $tr('resourcesCount', { count: resourcesCountStaged }) }}
337+
</VFlex>
338+
</VLayout>
339+
</KModal>
292340
</template>
293341
</div>
294342

@@ -352,9 +400,11 @@
352400
isLoading: true,
353401
displaySummaryDetailsDialog: false,
354402
displayDeployDialog: false,
403+
displayPublishDraftDialog: false,
355404
drawer: false,
356405
elevated: false,
357406
isDeploying: false,
407+
isPublishingDraft: false,
358408
};
359409
},
360410
computed: {
@@ -502,6 +552,7 @@
502552
...mapActions('currentChannel', [
503553
'loadCurrentChannelStagingDiff',
504554
'deployCurrentChannel',
555+
'publishDraftChannel',
505556
'reloadCurrentChannelStagingDiff',
506557
]),
507558
...mapActions('currentChannel', { loadCurrentChannel: 'loadChannel' }),
@@ -591,6 +642,25 @@
591642
592643
this.deployCurrentChannel();
593644
},
645+
onPublishDraftClick() {
646+
this.displayPublishDraftDialog = false;
647+
this.isPublishingDraft = true;
648+
649+
this.publishDraftChannel()
650+
.then(() => {
651+
this.isPublishingDraft = false;
652+
this.showSnackbar({
653+
text: this.$tr('draftPublished'),
654+
});
655+
})
656+
.catch(error => {
657+
this.isPublishingDraft = false;
658+
this.showSnackbar({
659+
text: error.response?.data?.message || this.$tr('publishDraftError'),
660+
color: 'error',
661+
});
662+
});
663+
},
594664
},
595665
$trs: {
596666
deploy: 'Deploy',
@@ -617,6 +687,12 @@
617687
channelDeployed: 'Channel has been deployed',
618688
emptyTopicText: 'This topic is empty',
619689
viewDetails: 'View details',
690+
publishDraft: 'Publish draft',
691+
publishDraftDialogDescription: 'You are about to publish a draft of your staged changes.',
692+
cancelPublishDraftBtn: 'Cancel',
693+
confirmPublishDraftBtn: 'Publish',
694+
draftPublished: 'Draft channel has been published',
695+
publishDraftError: 'An error occurred while publishing the draft channel',
620696
},
621697
};
622698

contentcuration/contentcuration/frontend/channelEdit/vuex/currentChannel/actions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export function publishChannel(context, version_notes) {
5555
return Channel.publish(context.state.currentChannelId, version_notes);
5656
}
5757

58+
export function publishDraftChannel(context) {
59+
return Channel.publishDraft(context.state.currentChannelId);
60+
}
61+
5862
export function channelLanguageExistsInResources(context) {
5963
const channelId = context.state.currentChannelId;
6064
return Channel.languageExistsInResources(channelId);

contentcuration/contentcuration/frontend/shared/data/__tests__/changes.spec.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
MovedChange,
88
CopiedChange,
99
PublishedChange,
10+
PublishedNextChange,
1011
SyncedChange,
1112
DeployedChange,
1213
UpdatedDescendantsChange,
@@ -252,6 +253,21 @@ describe('Change Types', () => {
252253
});
253254
});
254255

256+
it('should persist only the specified fields in the PublishedNextChange', async () => {
257+
const change = new PublishedNextChange({
258+
key: '1',
259+
table: TABLE_NAMES.CHANNEL,
260+
source: CLIENTID,
261+
});
262+
const rev = await change.saveChange();
263+
const persistedChange = await db[CHANGES_TABLE].get(rev);
264+
expect(persistedChange).toEqual({
265+
rev,
266+
channel_id: change.key,
267+
...pick(change, ['type', 'key', 'table', 'source']),
268+
});
269+
});
270+
255271
it('should persist only the specified fields in the SyncedChange', async () => {
256272
const change = new SyncedChange({
257273
key: '1',
@@ -593,6 +609,19 @@ describe('Change Types Unhappy Paths', () => {
593609
).toThrow(new TypeError('language is required for a PublishedChange but it was undefined'));
594610
});
595611

612+
// PublishedNextChange
613+
it('should throw error when PublishedNextChange is instantiated without key', () => {
614+
expect(() => new PublishedNextChange({ table: TABLE_NAMES.CHANNEL, source: CLIENTID })).toThrow(
615+
new TypeError('key is required for a PublishedNextChange but it was undefined'),
616+
);
617+
});
618+
619+
it('should throw error when PublishedNextChange is instantiated with invalid table', () => {
620+
expect(() => new PublishedNextChange({ key: '1', table: 'test', source: CLIENTID })).toThrow(
621+
new ReferenceError('test is not a valid table value'),
622+
);
623+
});
624+
596625
// SyncedChange
597626
it('should throw error when SyncedChange is instantiated without titles_and_descriptions', () => {
598627
expect(

contentcuration/contentcuration/frontend/shared/data/applyRemoteChanges.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,17 @@ import { INDEXEDDB_RESOURCES } from './registry';
88
import { RolesNames } from 'shared/leUtils/Roles';
99
import { ContentKindsNames } from 'shared/leUtils/ContentKinds';
1010

11-
const { CREATED, DELETED, UPDATED, MOVED, PUBLISHED, SYNCED, DEPLOYED, UPDATED_DESCENDANTS } =
12-
CHANGE_TYPES;
11+
const {
12+
CREATED,
13+
DELETED,
14+
UPDATED,
15+
MOVED,
16+
PUBLISHED,
17+
PUBLISHED_NEXT,
18+
SYNCED,
19+
DEPLOYED,
20+
UPDATED_DESCENDANTS,
21+
} = CHANGE_TYPES;
1322

1423
export function applyMods(obj, mods) {
1524
for (const keyPath in mods) {
@@ -32,6 +41,7 @@ export function collectChanges(changes) {
3241
[UPDATED]: [],
3342
[MOVED]: [],
3443
[PUBLISHED]: [],
44+
[PUBLISHED_NEXT]: [],
3545
[SYNCED]: [],
3646
[DEPLOYED]: [],
3747
[UPDATED_DESCENDANTS]: [],

contentcuration/contentcuration/frontend/shared/data/changes.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,19 @@ export class PublishedChange extends Change {
438438
}
439439
}
440440

441+
export class PublishedNextChange extends Change {
442+
constructor(fields) {
443+
fields.type = CHANGE_TYPES.PUBLISHED_NEXT;
444+
super(fields);
445+
if (this.table !== TABLE_NAMES.CHANNEL) {
446+
throw TypeError(
447+
`${this.changeType} is only supported by ${TABLE_NAMES.CHANNEL} table but ${this.table} was passed instead`,
448+
);
449+
}
450+
this.setChannelAndUserId({ id: this.key });
451+
}
452+
}
453+
441454
export class SyncedChange extends Change {
442455
constructor({ titles_and_descriptions, resource_details, files, assessment_items, ...fields }) {
443456
fields.type = CHANGE_TYPES.SYNCED;

contentcuration/contentcuration/frontend/shared/data/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const CHANGE_TYPES = {
1010
SYNCED: 7,
1111
DEPLOYED: 8,
1212
UPDATED_DESCENDANTS: 9,
13+
PUBLISHED_NEXT: 10,
1314
};
1415
/**
1516
* An array of change types that directly result in the creation of nodes

contentcuration/contentcuration/frontend/shared/data/resources.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
SyncedChange,
4343
DeployedChange,
4444
UpdatedDescendantsChange,
45+
PublishedNextChange,
4546
} from './changes';
4647
import urls from 'shared/urls';
4748
import { currentLanguage } from 'shared/i18n';
@@ -1233,6 +1234,17 @@ export const Channel = new CreateModelResource({
12331234
});
12341235
},
12351236

1237+
publishDraft(id) {
1238+
const change = new PublishedNextChange({
1239+
key: id,
1240+
table: this.tableName,
1241+
source: CLIENTID,
1242+
});
1243+
return this.transaction({ mode: 'rw' }, CHANGES_TABLE, () => {
1244+
return this._saveAndQueueChange(change);
1245+
});
1246+
},
1247+
12361248
deploy(id) {
12371249
const change = new DeployedChange({
12381250
key: id,

contentcuration/contentcuration/frontend/shared/data/serverSync.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const ChangeTypeMapFields = {
3636
'excluded_descendants',
3737
]),
3838
[CHANGE_TYPES.PUBLISHED]: commonFields.concat(['version_notes', 'language']),
39+
[CHANGE_TYPES.PUBLISHED_NEXT]: commonFields,
3940
[CHANGE_TYPES.SYNCED]: commonFields.concat([
4041
'titles_and_descriptions',
4142
'resource_details',

0 commit comments

Comments
 (0)