Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
51f1f96
feat: adds validation checks and saves a version when scheduling content
iOvergaard Feb 14, 2025
362e18e
chore: adds mock handler for validate
iOvergaard Feb 14, 2025
33f196c
docs: adds documentation for umbracoPath
iOvergaard Feb 14, 2025
324fad4
chore: adds deprecation and todos
iOvergaard Feb 14, 2025
37e9436
feat: adds a method to output a list format
iOvergaard Feb 14, 2025
8e26445
test: adds test for list format
iOvergaard Feb 14, 2025
fc16cf7
feat: rename to list
iOvergaard Feb 14, 2025
5d4a88a
feat: adds localization for scheduling
iOvergaard Feb 14, 2025
c42af69
feat: adds notifications for publishing by action
iOvergaard Feb 14, 2025
b8b795c
test: fixes naming
iOvergaard Feb 14, 2025
0ab5fee
feat: adds notification for publishing in bulk
iOvergaard Feb 14, 2025
f919d8a
feat: fixes todo by adding localization
iOvergaard Feb 14, 2025
605904c
feat: adds notification when publishing from workspace
iOvergaard Feb 14, 2025
89d6282
Merge branch 'v15/dev' into v15/feature/schedule-save
leekelleher Feb 17, 2025
acf68b6
Merge branch 'v15/dev' into v15/feature/schedule-save
leekelleher Feb 17, 2025
6ec0671
feat: rename 'Content' to 'Document'
iOvergaard Feb 17, 2025
f290dab
fix: uses text for variants when publishing variants
iOvergaard Feb 17, 2025
dea7db1
chore(mock): fix mock data
iOvergaard Feb 17, 2025
6697a0c
fix: uses correct text variables for bulk publishing
iOvergaard Feb 17, 2025
c4f67d6
fix: uses correct language variable for publishing variants
iOvergaard Feb 17, 2025
d8aaa92
Merge remote-tracking branch 'origin/v15/dev' into v15/feature/schedu…
iOvergaard Feb 17, 2025
3577209
fix: typo
iOvergaard Feb 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1412,14 +1412,14 @@ export default {
cssSavedText: 'Stylesheet saved without any errors',
dataTypeSaved: 'Datatype saved',
dictionaryItemSaved: 'Dictionary item saved',
editContentPublishedHeader: 'Content published',
editContentPublishedHeader: 'Document published',
editContentPublishedText: 'and is visible on the website',
editMultiContentPublishedText: '%0% documents published and visible on the website',
editVariantPublishedText: '%0% published and visible on the website',
editMultiVariantPublishedText: '%0% documents published for languages %1% and visible on the website',
editMultiContentPublishedText: '%0% documents published and are visible on the website',
editVariantPublishedText: '%0% published and is visible on the website',
editMultiVariantPublishedText: '%0% documents published for languages %1% and are visible on the website',
editBlueprintSavedHeader: 'Document Blueprint saved',
editBlueprintSavedText: 'Changes have been successfully saved',
editContentSavedHeader: 'Content saved',
editContentSavedHeader: 'Document saved',
editContentSavedText: 'Remember to publish to make changes visible',
editContentScheduledSavedText: 'A schedule for publishing has been updated',
editVariantSavedText: '%0% saved',
Expand Down
18 changes: 10 additions & 8 deletions src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1412,7 +1412,7 @@ export default {
folderUploadNotAllowed:
'This file is being uploaded as part of a folder, but creating a new folder is not allowed here',
folderCreationNotAllowed: 'Creating a new folder is not allowed here',
contentPublishedFailedByEvent: 'Content could not be published, a 3rd party add-in cancelled the action',
contentPublishedFailedByEvent: 'Document could not be published, a 3rd party add-in cancelled the action',
contentTypeDublicatePropertyType: 'Property type already exists',
contentTypePropertyTypeCreated: 'Property type created',
contentTypePropertyTypeCreatedText: 'Name: %0% <br /> DataType: %1%',
Expand All @@ -1426,12 +1426,13 @@ export default {
cssSavedText: 'Stylesheet saved without any errors',
dataTypeSaved: 'Datatype saved',
dictionaryItemSaved: 'Dictionary item saved',
editContentPublishedFailedByParent: 'Content could not be published, because a parent page is not published',
editContentPublishedHeader: 'Content published',
editContentPublishedText: 'and visible on the website',
editContentPublishedFailedByValidation: 'Document could not be published, but we saved it for you',
editContentPublishedFailedByParent: 'Document could not be published, because a parent page is not published',
editContentPublishedHeader: 'Document published',
editContentPublishedText: 'and is visible on the website',
editBlueprintSavedHeader: 'Document Blueprint saved',
editBlueprintSavedText: 'Changes have been successfully saved',
editContentSavedHeader: 'Content saved',
editContentSavedHeader: 'Document saved',
editContentSavedText: 'Remember to publish to make changes visible',
editContentSendToPublish: 'Sent For Approval',
editContentSendToPublishText: 'Changes have been sent for approval',
Expand Down Expand Up @@ -1493,10 +1494,11 @@ export default {
cannotCopyInformation: 'Could not copy your system information to the clipboard',
webhookSaved: 'Webhook saved',
operationSavedHeaderReloadUser: 'Saved. To view the changes please reload your browser',
editMultiContentPublishedText: '%0% documents published and visible on the website',
editVariantPublishedText: '%0% published and visible on the website',
editMultiVariantPublishedText: '%0% documents published for languages %1% and visible on the website',
editMultiContentPublishedText: '%0% documents published and are visible on the website',
editVariantPublishedText: '%0% published and is visible on the website',
editMultiVariantPublishedText: '%0% documents published for languages %1% and are visible on the website',
editContentScheduledSavedText: 'A schedule for publishing has been updated',
editContentScheduledNotSavedText: 'The schedule for publishing could not be updated',
editVariantSavedText: '%0% saved',
editVariantSendToPublishText: '%0% changes have been sent for approval',
contentCultureUnpublished: 'Content variation %0% unpublished',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,16 @@ describe('UmbLocalizeController', () => {
});
});

describe('list format', () => {
it('should return a list with conjunction', () => {
expect(controller.list(['one', 'two', 'three'], { type: 'conjunction' })).to.equal('one, two, and three');
});

it('should return a list with disjunction', () => {
expect(controller.list(['one', 'two', 'three'], { type: 'disjunction' })).to.equal('one, two, or three');
});
});

describe('duration', () => {
it('should return a duration', () => {
const now = new Date('2020-01-01T00:00:00');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -941,8 +941,16 @@ export const data: Array<UmbMockDataTypeModel> = [
{
alias: 'layouts',
value: [
{ icon: 'icon-grid', isSystem: true, name: 'Grid', path: '', selected: true },
{ icon: 'icon-list', isSystem: true, name: 'Table', path: '', selected: true },
{
icon: 'icon-grid',
name: 'Document Grid Collection View',
collectionView: 'Umb.CollectionView.Document.Grid',
},
{
icon: 'icon-list',
name: 'Document Table Collection View',
collectionView: 'Umb.CollectionView.Document.Table',
},
],
},
{ alias: 'icon', value: 'icon-layers' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ export const detailHandlers = [
return res(ctx.status(200), ctx.json<PagedIReferenceResponseModel>(PagedTrackedReference));
}),

rest.put(umbracoPath(`${UMB_SLUG}/:id/validate`, 'v1.1'), (_req, res, ctx) => {
const id = _req.params.id as string;
if (!id) return res(ctx.status(400));

return res(ctx.status(200));
}),

rest.get(umbracoPath(`${UMB_SLUG}/:id`), (req, res, ctx) => {
const id = req.params.id as string;
if (!id) return res(ctx.status(400));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// TODO: Rename to something more obvious, naming wise this can mean anything. I suggest: umbracoManagementApiPath()
/**
*
* @param path
* Generates a path to an Umbraco API endpoint.
* @param {string} path - The path to the Umbraco API endpoint.
* @param {string} version - The version of the Umbraco API (default is 'v1').
* @returns {string} The path to the Umbraco API endpoint.
*/
export function umbracoPath(path: string) {
return `/umbraco/management/api/v1${path}`;
export function umbracoPath(path: string, version = 'v1') {
return `/umbraco/management/api/${version}${path}`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user';
import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification';
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';

export class UmbPublishDocumentEntityAction extends UmbEntityActionBase<never> {
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<never>) {
Expand All @@ -19,6 +21,9 @@ export class UmbPublishDocumentEntityAction extends UmbEntityActionBase<never> {
override async execute() {
if (!this.args.unique) throw new Error('The document unique identifier is missing');

const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
const localize = new UmbLocalizationController(this);

const languageRepository = new UmbLanguageCollectionRepository(this._host);
const { data: languageData } = await languageRepository.requestCollection({});

Expand Down Expand Up @@ -65,7 +70,15 @@ export class UmbPublishDocumentEntityAction extends UmbEntityActionBase<never> {
if (options.length === 1) {
const variantId = UmbVariantId.Create(documentData.variants[0]);
const publishingRepository = new UmbDocumentPublishingRepository(this._host);
await publishingRepository.publish(this.args.unique, [{ variantId }]);
const { error } = await publishingRepository.publish(this.args.unique, [{ variantId }]);
if (!error) {
notificationContext.peek('positive', {
data: {
headline: localize.term('speechBubbles_editContentPublishedHeader'),
message: localize.term('speechBubbles_editContentPublishedText'),
},
});
}
actionEventContext.dispatchEvent(event);
return;
}
Expand Down Expand Up @@ -103,10 +116,24 @@ export class UmbPublishDocumentEntityAction extends UmbEntityActionBase<never> {

if (variantIds.length) {
const publishingRepository = new UmbDocumentPublishingRepository(this._host);
await publishingRepository.publish(
const { error } = await publishingRepository.publish(
this.args.unique,
variantIds.map((variantId) => ({ variantId })),
);

if (!error) {
const documentVariants = documentData.variants.filter((variant) => result.selection.includes(variant.culture!));
notificationContext.peek('positive', {
data: {
headline: localize.term('speechBubbles_editContentPublishedHeader'),
message: localize.term(
'speechBubbles_editVariantPublishedText',
localize.list(documentVariants.map((v) => v.culture ?? v.name)),
),
},
});
}

actionEventContext.dispatchEvent(event);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-
import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action';
import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification';

export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<object> {
async execute() {
const entityContext = await this.getContext(UMB_ENTITY_CONTEXT);
const entityType = entityContext.getEntityType();
const unique = entityContext.getUnique();

const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
const localize = new UmbLocalizationController(this);

if (!entityType) throw new Error('Entity type not found');
if (unique === undefined) throw new Error('Entity unique not found');

Expand Down Expand Up @@ -46,7 +50,7 @@ export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<
updateDate: null,
segment: null,
scheduledPublishDate: null,
scheduledUnpublishDate: null
scheduledUnpublishDate: null,
},
unique: new UmbVariantId(language.unique, null).toString(),
culture: language.unique,
Expand Down Expand Up @@ -79,11 +83,24 @@ export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<
if (confirm !== false) {
const variantId = new UmbVariantId(options[0].language.unique, null);
const publishingRepository = new UmbDocumentPublishingRepository(this._host);
let documentCnt = 0;

for (let i = 0; i < this.selection.length; i++) {
const id = this.selection[i];
await publishingRepository.publish(id, [{ variantId }]);
const { error } = await publishingRepository.publish(id, [{ variantId }]);

if (!error) {
documentCnt++;
}
}

notificationContext.peek('positive', {
data: {
headline: localize.term('speechBubbles_editContentPublishedHeader'),
message: localize.term('speechBubbles_editMultiContentPublishedText', documentCnt),
},
});

eventContext.dispatchEvent(event);
}
return;
Expand Down Expand Up @@ -116,13 +133,30 @@ export class UmbDocumentPublishEntityBulkAction extends UmbEntityBulkActionBase<
const repository = new UmbDocumentPublishingRepository(this._host);

if (variantIds.length) {
let documentCnt = 0;
for (const unique of this.selection) {
await repository.publish(
const { error } = await repository.publish(
unique,
variantIds.map((variantId) => ({ variantId })),
);
eventContext.dispatchEvent(event);

if (!error) {
documentCnt++;
}
}

notificationContext.peek('positive', {
data: {
headline: localize.term('speechBubbles_editContentPublishedHeader'),
message: localize.term(
'speechBubbles_editMultiVariantPublishedText',
documentCnt,
localize.list(variantIds.map((v) => v.culture ?? '')),
),
},
});

eventContext.dispatchEvent(event);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
export class UmbDocumentPublishingRepository extends UmbRepositoryBase {
#init!: Promise<unknown>;
#publishingDataSource: UmbDocumentPublishingServerDataSource;

/**
* @deprecated The calling workspace context should be used instead to show notifications
*/
#notificationContext?: UmbNotificationContext;

constructor(host: UmbControllerHost) {
Expand Down Expand Up @@ -36,14 +40,7 @@ export class UmbDocumentPublishingRepository extends UmbRepositoryBase {
if (!variants.length) throw new Error('variant IDs are missing');
await this.#init;

const { error } = await this.#publishingDataSource.publish(unique, variants);

if (!error) {
const notification = { data: { message: `Document published` } };
this.#notificationContext?.peek('positive', notification);
}

return { error };
return this.#publishingDataSource.publish(unique, variants);
}

/**
Expand All @@ -62,6 +59,7 @@ export class UmbDocumentPublishingRepository extends UmbRepositoryBase {

if (!error) {
const notification = { data: { message: `Document unpublished` } };
// TODO: Move this to the calling workspace context [JOV]
this.#notificationContext?.peek('positive', notification);
}

Expand All @@ -76,7 +74,12 @@ export class UmbDocumentPublishingRepository extends UmbRepositoryBase {
* @param forceRepublish
* @memberof UmbDocumentPublishingRepository
*/
async publishWithDescendants(id: string, variantIds: Array<UmbVariantId>, includeUnpublishedDescendants: boolean, forceRepublish: boolean) {
async publishWithDescendants(
id: string,
variantIds: Array<UmbVariantId>,
includeUnpublishedDescendants: boolean,
forceRepublish: boolean,
) {
if (!id) throw new Error('id is missing');
if (!variantIds) throw new Error('variant IDs are missing');
await this.#init;
Expand All @@ -90,6 +93,7 @@ export class UmbDocumentPublishingRepository extends UmbRepositoryBase {

if (!error) {
const notification = { data: { message: `Document published with descendants` } };
// TODO: Move this to the calling workspace context [JOV]
this.#notificationContext?.peek('positive', notification);
}

Expand Down
Loading