Skip to content

Commit 6cfba9b

Browse files
committed
Merge branch 'release/16.0'
2 parents 29b98ba + 02f963d commit 6cfba9b

File tree

46 files changed

+625
-248
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+625
-248
lines changed

src/Umbraco.Core/Configuration/ContentSettingsExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public static class ContentSettingsExtensions
1414
/// <c>true</c> if the file extension is allowed for upload; otherwise, <c>false</c>.
1515
/// </returns>
1616
public static bool IsFileAllowedForUpload(this ContentSettings contentSettings, string extension)
17-
=> contentSettings.AllowedUploadedFileExtensions.Any(x => x.InvariantEquals(extension)) ||
18-
(contentSettings.AllowedUploadedFileExtensions.Any() == false && contentSettings.DisallowedUploadedFileExtensions.Any(x => x.InvariantEquals(extension)) == false);
17+
=> contentSettings.AllowedUploadedFileExtensions.Any(x => x.InvariantEquals(extension.Trim())) ||
18+
(contentSettings.AllowedUploadedFileExtensions.Any() == false && contentSettings.DisallowedUploadedFileExtensions.Any(x => x.InvariantEquals(extension.Trim())) == false);
1919

2020
/// <summary>
2121
/// Gets the auto-fill configuration for a specified property alias.

src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default {
1616
'In order to improve Umbraco and add new functionality based on as relevant information as possible, we would like to collect system- and usage information from your installation.<br>Aggregate data will be shared on a regular basis as well as learnings from these metrics.<br>Hopefully, you will help us collect some valuable data.<br><br>We <strong>WILL NOT</strong> collect any personal data such as content, code, user information, and all data will be fully anonymized.',
1717
basicLevelDescription: 'We will send an anonymized site ID, Umbraco version, and packages installed',
1818
detailedLevelDescription:
19-
'We will send: <ul>li>Anonymized site ID, Umbraco version, and packages installed.</li><li>Number of: Root nodes, Content nodes, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, and Property Editors in use.</li><li>System information: Webserver, server OS, server framework, server OS language, and database provider.</li><li>Configuration settings: ModelsBuilder mode, if custom Umbraco path exists, ASP environment, whether the delivery API is enabled, and allows public access, and if you are in debug mode.</li></ul><em>We might change what we send on the Detailed level in the future. If so, it will be listed above.<br>By choosing "Detailed" you agree to current and future anonymized information being collected.</em>',
19+
'We will send: <ul><li>Anonymized site ID, Umbraco version, and packages installed.</li><li>Number of: Root nodes, Content nodes, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, and Property Editors in use.</li><li>System information: Webserver, server OS, server framework, server OS language, and database provider.</li><li>Configuration settings: ModelsBuilder mode, if custom Umbraco path exists, ASP environment, whether the delivery API is enabled, and allows public access, and if you are in debug mode.</li></ul><em>We might change what we send on the Detailed level in the future. If so, it will be listed above.<br>By choosing "Detailed" you agree to current and future anonymized information being collected.</em>',
2020
minimalLevelDescription: 'We will only send an anonymized site ID to let us know that the site exists.',
2121
},
2222
blockEditor: {
Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
export {
2+
BehaviorSubject,
3+
Observable,
24
ReplaySubject,
35
Subject,
4-
Observable,
5-
BehaviorSubject,
66
Subscription,
7-
map,
8-
distinctUntilChanged,
7+
catchError,
98
combineLatest,
10-
shareReplay,
11-
takeUntil,
129
debounceTime,
13-
tap,
14-
of,
15-
lastValueFrom,
16-
firstValueFrom,
17-
switchMap,
10+
distinctUntilChanged,
1811
filter,
19-
startWith,
20-
skip,
2112
first,
13+
firstValueFrom,
14+
from,
15+
lastValueFrom,
16+
map,
17+
of,
18+
shareReplay,
19+
skip,
20+
startWith,
21+
switchMap,
22+
takeUntil,
23+
tap,
2224
} from 'rxjs';

src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/server-extension-registrator.controller.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ export class UmbServerExtensionRegistrator extends UmbControllerBase {
3434
* @remark Users must have the BACKOFFICE_ACCESS permission to access this method.
3535
*/
3636
public async registerPrivateExtensions() {
37-
const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPrivate());
37+
const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPrivate(), {
38+
disableNotifications: true,
39+
});
3840
if (packages) {
3941
await this.#loadServerPackages(packages);
4042
}
@@ -46,7 +48,9 @@ export class UmbServerExtensionRegistrator extends UmbControllerBase {
4648
* @remark Any user can access this method without any permissions.
4749
*/
4850
public async registerPublicExtensions() {
49-
const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPublic());
51+
const { data: packages } = await tryExecute(this, ManifestService.getManifestManifestPublic(), {
52+
disableNotifications: true,
53+
});
5054
if (packages) {
5155
await this.#loadServerPackages(packages);
5256
}

src/Umbraco.Web.UI.Client/src/packages/content/content/components/property-type-based-property/property-type-based-property.context-token.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ export const UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT = new UmbContextToken<UmbP
1010
* This will be removed in v.18
1111
*/
1212
export const UMB_CONTENT_PROPERTY_CONTEXT = new UmbContextToken<UmbPropertyTypeBasedPropertyContext>(
13-
'UmbContentPropertyContext',
13+
'UmbPropertyTypeBasedPropertyContext',
1414
);

src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-filter-field.element.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export class UmbCollectionFilterFieldElement extends UmbLitElement {
3434
static override readonly styles = [
3535
css`
3636
uui-input {
37-
display: block;
37+
width: 100%;
3838
}
3939
`,
4040
];

src/Umbraco.Web.UI.Client/src/packages/core/localization/localize.element.test.ts

Lines changed: 111 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { aTimeout, elementUpdated, expect, fixture, html } from '@open-wc/testin
33
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
44
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
55
import { umbLocalizationRegistry } from './registry/localization.registry.js';
6+
import type { ManifestLocalization } from './extensions/localization.extension.js';
67

7-
const english = {
8+
const english: ManifestLocalization = {
89
type: 'localization',
910
alias: 'test.en',
1011
name: 'Test English',
12+
weight: 100,
1113
meta: {
1214
culture: 'en',
1315
localizations: {
@@ -27,7 +29,75 @@ const english = {
2729
},
2830
};
2931

30-
const danish = {
32+
const englishUs: ManifestLocalization = {
33+
type: 'localization',
34+
alias: 'test.en-us',
35+
name: 'Test English (US)',
36+
weight: 100,
37+
meta: {
38+
culture: 'en-us',
39+
localizations: {
40+
general: {
41+
close: 'Close US',
42+
overridden: 'Overridden',
43+
},
44+
},
45+
},
46+
};
47+
48+
// This is a factory function that returns the localization object.
49+
const asyncFactory = async (localizations: Record<string, any>, delay: number) => {
50+
await aTimeout(delay); // Simulate async loading
51+
return {
52+
// Simulate a JS module that exports a localization object.
53+
default: localizations,
54+
};
55+
};
56+
57+
// This is an async localization that overrides the previous one.
58+
const englishAsyncOverride: ManifestLocalization = {
59+
type: 'localization',
60+
alias: 'test.en.async-override',
61+
name: 'Test English Async Override',
62+
weight: -100,
63+
meta: {
64+
culture: 'en-us',
65+
},
66+
js: () =>
67+
asyncFactory(
68+
{
69+
general: {
70+
close: 'Close Async',
71+
overridden: 'Overridden Async',
72+
},
73+
},
74+
100,
75+
),
76+
};
77+
78+
// This is another async localization that loads later than the previous one and overrides it because of a lower weight.
79+
const english2AsyncOverride: ManifestLocalization = {
80+
type: 'localization',
81+
alias: 'test.en.async-override-2',
82+
name: 'Test English Async Override 2',
83+
weight: -200,
84+
meta: {
85+
culture: 'en-us',
86+
},
87+
js: () =>
88+
asyncFactory(
89+
{
90+
general: {
91+
close: 'Another Async Close',
92+
},
93+
},
94+
200, // This will load after the first async override
95+
// so it should override the close translation.
96+
// The overridden translation should not be overridden.
97+
),
98+
};
99+
100+
const danish: ManifestLocalization = {
31101
type: 'localization',
32102
alias: 'test.da',
33103
name: 'Test Danish',
@@ -53,8 +123,7 @@ describe('umb-localize', () => {
53123
});
54124

55125
describe('localization', () => {
56-
umbExtensionsRegistry.register(english);
57-
umbExtensionsRegistry.register(danish);
126+
umbExtensionsRegistry.registerMany([english, englishUs, danish]);
58127

59128
beforeEach(async () => {
60129
umbLocalizationRegistry.loadLanguage(english.meta.culture);
@@ -123,13 +192,50 @@ describe('umb-localize', () => {
123192
it('should change the value if the language is changed', async () => {
124193
expect(element.shadowRoot?.innerHTML).to.contain('Close');
125194

195+
// Change to Danish
126196
umbLocalizationRegistry.loadLanguage(danish.meta.culture);
127197
await aTimeout(0);
128198
await elementUpdated(element);
129-
130199
expect(element.shadowRoot?.innerHTML).to.contain('Luk');
131200
});
132201

202+
it('should fall back to the fallback language if the key is not found', async () => {
203+
expect(element.shadowRoot?.innerHTML).to.contain('Close');
204+
205+
// Change to US English
206+
umbLocalizationRegistry.loadLanguage(englishUs.meta.culture);
207+
await aTimeout(0);
208+
await elementUpdated(element);
209+
expect(element.shadowRoot?.innerHTML).to.contain('Close US');
210+
211+
element.key = 'general_overridden';
212+
await elementUpdated(element);
213+
expect(element.shadowRoot?.innerHTML).to.contain('Overridden');
214+
215+
element.key = 'general_logout';
216+
await elementUpdated(element);
217+
expect(element.shadowRoot?.innerHTML).to.contain('Log out');
218+
});
219+
220+
it('should accept a lazy loaded localization', async () => {
221+
umbExtensionsRegistry.registerMany([englishAsyncOverride, english2AsyncOverride]);
222+
umbLocalizationRegistry.loadLanguage(englishAsyncOverride.meta.culture);
223+
await aTimeout(200); // Wait for the async override to load
224+
225+
await elementUpdated(element);
226+
expect(element.shadowRoot?.innerHTML).to.contain(
227+
'Another Async Close',
228+
'(async) Should have overridden the close (from first language)',
229+
);
230+
231+
element.key = 'general_overridden';
232+
await elementUpdated(element);
233+
expect(element.shadowRoot?.innerHTML).to.contain(
234+
'Overridden Async',
235+
'(async) Should not have overridden the overridden (from first language)',
236+
);
237+
});
238+
133239
it('should use the slot if translation is not found', async () => {
134240
element.key = 'non-existing-key';
135241
await elementUpdated(element);

0 commit comments

Comments
 (0)