diff --git a/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs index 7da51b51ad..62e77b4f2d 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs @@ -19,6 +19,9 @@ public class Issuu : EmbedProviderBase public override Dictionary RequestParams => new() { + // ApiUrl/?iframe=true + { "iframe", "true" }, + // ApiUrl/?format=xml { "format", "xml" }, }; diff --git a/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs b/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs index b09baba0db..9385dcf6c9 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs @@ -55,11 +55,12 @@ public abstract class OEmbedProviderBase : IEmbedProvider if (_httpClient == null) { _httpClient = new HttpClient(); + _httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("Umbraco-CMS"); } using (var request = new HttpRequestMessage(HttpMethod.Get, url)) { - HttpResponseMessage response = _httpClient.SendAsync(request).Result; + HttpResponseMessage response = _httpClient.SendAsync(request).GetAwaiter().GetResult(); return response.Content.ReadAsStringAsync().Result; } } diff --git a/src/Umbraco.Infrastructure/ModelsBuilder/PublishedModelUtility.cs b/src/Umbraco.Infrastructure/ModelsBuilder/PublishedModelUtility.cs index cfcbd82229..bac3dcf0d8 100644 --- a/src/Umbraco.Infrastructure/ModelsBuilder/PublishedModelUtility.cs +++ b/src/Umbraco.Infrastructure/ModelsBuilder/PublishedModelUtility.cs @@ -37,6 +37,7 @@ public static class PublishedModelUtility switch (itemType) { case PublishedItemType.Content: + case PublishedItemType.Element: return publishedSnapshot.Content?.GetContentType(alias); case PublishedItemType.Media: return publishedSnapshot.Media?.GetContentType(alias); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html index 56c7a9cf48..be6f21ed96 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html @@ -5,7 +5,7 @@ ng-repeat="subView in subViews track by subView.alias" ng-class="'sub-view-' + subView.name" val-sub-view="subView" - ng-if="subView.active" + ng-show="subView.active" >
diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts index 8dcadef04d..0c99d46ab5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts @@ -6,24 +6,26 @@ import {BlockListDataTypeBuilder} from "@umbraco/json-models-builders/dist/lib/b test.describe('BlockListEditorContent', () => { const documentName = 'DocumentTestName'; const blockListName = 'BlockListTest'; - const elementName = 'TestElement'; + const contentElementName = 'ContentElement'; + const settingElementName = 'SettingsElement'; const documentAlias = AliasHelper.toAlias(documentName); const blockListAlias = AliasHelper.toAlias(blockListName); - // Won't work if I use the to alias for the elementAlias - const elementAlias = 'testElement'; - + // Won't work if we use the to alias for the elementAliases + const contentElementAlias = 'contentElement'; + const settingsElementAlias = 'settingsElement'; + test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => { await umbracoApi.report.report(testInfo); await umbracoApi.login(); await umbracoApi.documentTypes.ensureNameNotExists(documentName); - await umbracoApi.documentTypes.ensureNameNotExists(elementName); + await umbracoApi.documentTypes.ensureNameNotExists(contentElementName); await umbracoApi.dataTypes.ensureNameNotExists(blockListName); }); - + test.afterEach(async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.documentTypes.ensureNameNotExists(documentName); - await umbracoApi.documentTypes.ensureNameNotExists(elementName); + await umbracoApi.documentTypes.ensureNameNotExists(contentElementName); await umbracoApi.dataTypes.ensureNameNotExists(blockListName); }); @@ -31,23 +33,22 @@ test.describe('BlockListEditorContent', () => { const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .addBlock() - .withContentElementTypeKey(element['key']) - .withSettingsElementTypeKey(element['key']) + .withContentElementTypeKey(element['key']) + .withSettingsElementTypeKey(element['key']) .done() .build(); return await umbracoApi.dataTypes.save(dataTypeBlockList); } - - async function createDocumentWithOneBlockListEditor(umbracoApi, element, dataType){ - + + async function createDocumentWithOneBlockListEditor(umbracoApi, element, dataType, elementName?, elementAlias?){ if(element == null) { element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); } - + if(dataType == null) { dataType = await createDefaultBlockList(umbracoApi, blockListName, element); } - + const docType = new DocumentTypeBuilder() .withName(documentName) .withAlias(documentAlias) @@ -61,16 +62,15 @@ test.describe('BlockListEditorContent', () => { .done() .build(); await umbracoApi.documentTypes.save(docType); - + return element; } - - async function createContentWithOneBlockListEditor(umbracoApi, element) { - + + async function createContentWithOneBlockListEditor(umbracoApi, element, datatype?, elementName?, elementAlias?) { if(element == null) { - element = await createDocumentWithOneBlockListEditor(umbracoApi, null, null); + element = await createDocumentWithOneBlockListEditor(umbracoApi, null, datatype, elementName, elementAlias); } - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -89,13 +89,35 @@ test.describe('BlockListEditorContent', () => { .done() .build(); await umbracoApi.content.save(rootContentNode); - + return element; } + async function createElementWithSlider(umbracoApi, name, alias, sliderId, sliderName?, sliderDefaultValue?) { + if (sliderId == null) { + const sliderData = await umbracoApi.dataTypes.createSliderWithDefaultValue(sliderName, sliderDefaultValue); + sliderId = sliderData.id; + } + + const contentElement = new DocumentTypeBuilder() + .withName(name) + .withAlias(alias) + .AsElementType() + .addGroup() + .withName('Content') + .withAlias('content') + .addCustomProperty(sliderId) + .withLabel('Slider') + .withAlias('slider') + .done() + .done() + .build(); + return await umbracoApi.documentTypes.save(contentElement); + } + test('can create content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - await createDocumentWithOneBlockListEditor(umbracoApi, null, null); - + await createDocumentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -113,7 +135,7 @@ test.describe('BlockListEditorContent', () => { await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName); // Adds TestElement - await page.locator('[key="blockEditor_addThis"]', {hasText: elementName}).click(); + await page.locator('[key="blockEditor_addThis"]', {hasText: contentElementName}).click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill('Testing...'); await page.locator('[label="Create"]').click(); @@ -121,17 +143,17 @@ test.describe('BlockListEditorContent', () => { // Assert await umbracoUi.isSuccessNotificationVisible(); - + // Checks if the content was created await expect(page.locator('.umb-block-list__block--view')).toHaveCount(1); - await expect(page.locator('.umb-block-list__block--view').nth(0)).toHaveText(elementName); + await expect(page.locator('.umb-block-list__block--view')).toHaveText(contentElementName); // Checks if the content contains the correct value - await page.locator('.umb-block-list__block--view').nth(0).click(); + await page.locator('.umb-block-list__block--view', {hasText: contentElementName}).click(); await expect(page.locator('[id="sub-view-0"]').locator('[id="title"]')).toHaveValue('Testing...'); }); test('can update content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - await createContentWithOneBlockListEditor(umbracoApi, null); + await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -154,7 +176,7 @@ test.describe('BlockListEditorContent', () => { }); test('can delete a block list editor in content', async ({page, umbracoApi, umbracoUi}) => { - await createContentWithOneBlockListEditor(umbracoApi, null); + await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -172,13 +194,13 @@ test.describe('BlockListEditorContent', () => { // Assert await umbracoUi.isSuccessNotificationVisible(); - + // Checks if the content is actually deleted await expect(page.locator('[ui-sortable="vm.sortableOptions"]').nth(0)).not.toBeVisible(); }); test('can copy block list content and paste it', async ({page, umbracoApi, umbracoUi}) => { - await createContentWithOneBlockListEditor(umbracoApi, null); + await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -194,7 +216,7 @@ test.describe('BlockListEditorContent', () => { await expect(page.locator('.alert-success', {hasText: 'Copied to clipboard'})).toBeVisible(); // Pastes block list content await page.locator('[title="Clipboard"]').click(); - await page.locator('umb-block-card', {hasText: elementName}).click(); + await page.locator('umb-block-card', {hasText: contentElementName}).click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); // Assert @@ -204,9 +226,9 @@ test.describe('BlockListEditorContent', () => { }); test('can copy block list content and paste it into another group with the same block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); - const dataType = await createDefaultBlockList(umbracoApi, blockListName, element); + const dataType = await createDefaultBlockList(umbracoApi, blockListName, contentElement); const docType = new DocumentTypeBuilder() .withName(documentName) @@ -227,7 +249,7 @@ test.describe('BlockListEditorContent', () => { .build(); await umbracoApi.documentTypes.save(docType); - await createContentWithOneBlockListEditor(umbracoApi, element); + await createContentWithOneBlockListEditor(umbracoApi, contentElement); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -245,7 +267,7 @@ test.describe('BlockListEditorContent', () => { await expect(page.locator('.alert-success', {hasText: 'Copied to clipboard'})).toBeVisible(); // Pastes into the second group await page.locator('[title="Clipboard"]').nth(1).click(); - await page.locator('umb-block-card', {hasText: elementName}).click(); + await page.locator('umb-block-card', {hasText: contentElementName}).click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); await expect(page.locator('.alert-success', {hasText: 'Content Published'})).toBeVisible(); @@ -257,20 +279,20 @@ test.describe('BlockListEditorContent', () => { }); test('can set a minimum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .withMin(2) .addBlock() - .withContentElementTypeKey(element['key']) + .withContentElementTypeKey(contentElement['key']) .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList); - await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType); - - await createContentWithOneBlockListEditor(umbracoApi, element); + await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType); + + await createContentWithOneBlockListEditor(umbracoApi, contentElement); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -294,18 +316,18 @@ test.describe('BlockListEditorContent', () => { }); test('can set a maximum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .withMax(2) .addBlock() - .withContentElementTypeKey(element['key']) + .withContentElementTypeKey(contentElement['key']) .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList); - await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType); + await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -317,16 +339,16 @@ test.describe('BlockListEditorContent', () => { .withAlias(blockListAlias) .addBlockListValue() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "aliasTest") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTest") .done() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "aliasTests") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTests") .done() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "aliasTester") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTester") .done() .done() .done() @@ -357,20 +379,20 @@ test.describe('BlockListEditorContent', () => { }); test('can use inline editing mode in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .withUseInlineEditingAsDefault(true) .addBlock() - .withContentElementTypeKey(element['key']) + .withContentElementTypeKey(contentElement['key']) .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList); - await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType); - - await createContentWithOneBlockListEditor(umbracoApi, element); + await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType); + + await createContentWithOneBlockListEditor(umbracoApi, contentElement); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -387,11 +409,11 @@ test.describe('BlockListEditorContent', () => { test('can see rendered content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.templates.ensureNameNotExists(documentName); - await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',elementAlias + '.cshtml'); + await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',contentElementAlias + '.cshtml'); - const element = new DocumentTypeBuilder() - .withName(elementName) - .withAlias(elementAlias) + const contentElement = new DocumentTypeBuilder() + .withName(contentElementName) + .withAlias(contentElementAlias) .AsElementType() .addGroup() .withName("TestString") @@ -406,9 +428,9 @@ test.describe('BlockListEditorContent', () => { .done() .done() .build(); - await umbracoApi.documentTypes.save(element); + await umbracoApi.documentTypes.save(contentElement); - const dataType = await createDefaultBlockList(umbracoApi, blockListName, element); + const dataType = await createDefaultBlockList(umbracoApi, blockListName, contentElement); const docType = new DocumentTypeBuilder() .withName(documentName) @@ -418,7 +440,7 @@ test.describe('BlockListEditorContent', () => { .addGroup() .withName('BlockListGroup') .addCustomProperty(dataType['id']) - .withAlias(elementAlias) + .withAlias(contentElementAlias) .done() .done() .build(); @@ -431,15 +453,15 @@ test.describe('BlockListEditorContent', () => { '\n Layout = null;' + '\n}' + '\n' + - '@Html.GetBlockListHtml(Model.' + elementName + ')'); + '@Html.GetBlockListHtml(Model.' + contentElementName + ')'); const partialView = new PartialViewBuilder() - .withName(elementAlias) + .withName(contentElementAlias) .withContent("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage;\n" + "@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;\n" + "@{\n" + - "var content = (ContentModels." + elementName + ")Model.Content;\n" + - "var settings = (ContentModels." + elementName + ")Model.Settings;\n" + + "var content = (ContentModels." + contentElementName + ")Model.Content;\n" + + "var settings = (ContentModels." + contentElementName + ")Model.Settings;\n" + "}\n" + "\n" + "

@content.Title

" + @@ -459,15 +481,15 @@ test.describe('BlockListEditorContent', () => { .withSave(true) .withPublish(true) .addProperty() - .withAlias(elementAlias) + .withAlias(contentElementAlias) .addBlockListValue() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "ContentTest") - .appendContentProperties(element.groups[0].properties[1].alias, "RTEContent") - .withSettingsTypeKey(element['key']) - .appendSettingsProperties(element.groups[0].properties[0].alias, "SettingTest") - .appendSettingsProperties(element.groups[0].properties[1].alias, "RTESetting") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "ContentTest") + .appendContentProperties(contentElement.groups[0].properties[1].alias, "RTEContent") + .withSettingsTypeKey(contentElement['key']) + .appendSettingsProperties(contentElement.groups[0].properties[0].alias, "SettingTest") + .appendSettingsProperties(contentElement.groups[0].properties[1].alias, "RTESetting") .done() .done() .done() @@ -479,9 +501,83 @@ test.describe('BlockListEditorContent', () => { // Ensure that the view gets rendered correctly const expected = `

ContentTest

RTEContent

SettingTest

RTESetting

`; await expect(await umbracoApi.content.verifyRenderedContent('/', expected, true)).toBeTruthy(); - + // Clean await umbracoApi.templates.ensureNameNotExists(documentName); - await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',elementAlias + '.cshtml'); + await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',contentElementAlias + '.cshtml'); }); -}); \ No newline at end of file + + test('Checks if the settings content model contains a default value when created', async ({page, umbracoApi, umbracoUi}) => { + const contentSliderName = 'ContentSlider'; + const contentSliderDefaultValue = 5; + const settingsSliderName = 'SettingsSlider'; + const settingsSliderDefaultValue = 9; + + await umbracoApi.documentTypes.ensureNameNotExists(settingElementName); + await umbracoApi.dataTypes.ensureNameNotExists(contentSliderName); + await umbracoApi.dataTypes.ensureNameNotExists(settingsSliderName); + + const contentElement = await createElementWithSlider(umbracoApi, contentElementName, contentElementAlias, null, contentSliderName, contentSliderDefaultValue); + + const settingsElement = await createElementWithSlider(umbracoApi, settingElementName, settingsElementAlias, null, settingsSliderName, settingsSliderDefaultValue); + + const blockList = new BlockListDataTypeBuilder() + .withName(blockListName) + .addBlock() + .withContentElementTypeKey(contentElement['key']) + .withSettingsElementTypeKey(settingsElement['key']) + .done() + .build(); + const blockListDataType = await umbracoApi.dataTypes.save(blockList); + + const document = new DocumentTypeBuilder() + .withName(documentName) + .withAlias(documentAlias) + .withAllowAsRoot(true) + .addGroup() + .withName('Content') + .withAlias('content') + .addCustomProperty(blockListDataType['id']) + .withLabel('BlockListTest') + .withAlias('blockListTest') + .done() + .done() + .build(); + await umbracoApi.documentTypes.save(document); + + const content = new ContentBuilder() + .withContentTypeAlias(documentAlias) + .withAction(ConstantHelper.actions.publish) + .addVariant() + .withName(blockListName) + .withSave(true) + .withPublish(true) + .done() + .build(); + const contentNode = await umbracoApi.content.save(content); + + await umbracoUi.goToSection(ConstantHelper.sections.content); + await umbracoUi.refreshContentTree(); + await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName); + await page.locator('[key="blockEditor_addThis"]', {hasText: contentElementName}).click(); + await page.locator('[label="Create"]').click(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + + // Assert + // Checks if the content contains the BlockListEditor block + await umbracoUi.clickDataElementByElementName("tree-root"); + await umbracoUi.refreshContentTree(); + await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName); + await expect(page.locator('.umb-block-list__block--view')).toHaveCount(1); + + // Checks if both the content and settings have been assigned their DefaultValues + const contentData = await umbracoApi.content.getContent(contentNode.id); + await expect(contentData.variants[0].tabs[0].properties[0].value.contentData[0].slider).toEqual(contentSliderDefaultValue.toString()); + await expect(contentData.variants[0].tabs[0].properties[0].value.settingsData[0].slider).toEqual(settingsSliderDefaultValue.toString()); + + // Clean + await umbracoApi.documentTypes.ensureNameNotExists(settingElementName); + await umbracoApi.dataTypes.ensureNameNotExists(contentSliderName); + await umbracoApi.dataTypes.ensureNameNotExists(settingsSliderName); + }); +});