Aktualisiere Versionsnummer auf 3.2.1 in README.md, package.json, package-lock.json und package-solution.json. Füge Unterstützung für Root-Web-UserCustomActions in PortalSettingsDataService hinzu und aktualisiere Tests entsprechend.
This commit is contained in:
@@ -6,7 +6,7 @@ PortalSettings V3 ist ein providerbasiertes SPFx-WebPart für SharePoint Server
|
|||||||
|
|
||||||
| Eigenschaft | Wert |
|
| Eigenschaft | Wert |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Version | 3.2.0 |
|
| Version | 3.2.1 |
|
||||||
| SharePoint Framework | 1.4.1 |
|
| SharePoint Framework | 1.4.1 |
|
||||||
| Build-Node | 8.17.0 |
|
| Build-Node | 8.17.0 |
|
||||||
| npm | 6.x |
|
| npm | 6.x |
|
||||||
@@ -48,6 +48,7 @@ Die Oberfläche wird vollständig vom WebPart erzeugt und verwendet kein `innerH
|
|||||||
|
|
||||||
### ExpiryIndicator
|
### ExpiryIndicator
|
||||||
|
|
||||||
|
- Erkennung direkt nach der App-Installation über den Application Customizer im Root Web
|
||||||
- Site-Collection-Standard aus dem Root-Web-Property-Bag
|
- Site-Collection-Standard aus dem Root-Web-Property-Bag
|
||||||
- Übersicht registrierter Listen- und Bibliotheksbindungen
|
- Übersicht registrierter Listen- und Bibliotheksbindungen
|
||||||
- Web-, Listen- und Datumsfeldauswahl ohne Eingabe technischer IDs
|
- Web-, Listen- und Datumsfeldauswahl ohne Eingabe technischer IDs
|
||||||
@@ -164,7 +165,7 @@ sharepoint/solution/portal-settings.sppkg
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. `portal-settings.sppkg` im App Catalog durch Version `3.2.0.0` ersetzen.
|
1. `portal-settings.sppkg` im App Catalog durch Version `3.2.1.0` ersetzen.
|
||||||
2. Die App im Root Web der gewünschten Site Collection installieren oder aktualisieren.
|
2. Die App im Root Web der gewünschten Site Collection installieren oder aktualisieren.
|
||||||
3. Die App provisioniert automatisch die veröffentlichte Seite `SitePages/PortalSettings.aspx` mit dem WebPart.
|
3. Die App provisioniert automatisch die veröffentlichte Seite `SitePages/PortalSettings.aspx` mit dem WebPart.
|
||||||
4. Eine bereits vorhandene `PortalSettings.aspx` wird nicht überschrieben.
|
4. Eine bereits vorhandene `PortalSettings.aspx` wird nicht überschrieben.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Stand: 21.07.2026
|
Stand: 21.07.2026
|
||||||
Branch: `dev-3.0`
|
Branch: `dev-3.0`
|
||||||
Zielversion: 3.2.0
|
Zielversion: 3.2.1
|
||||||
|
|
||||||
## Architektur
|
## Architektur
|
||||||
|
|
||||||
@@ -40,6 +40,7 @@ Zielversion: 3.2.0
|
|||||||
- [x] CustomBranding-Vertragsmarker und Component-ID-Fallback unterstützt.
|
- [x] CustomBranding-Vertragsmarker und Component-ID-Fallback unterstützt.
|
||||||
- [x] Branding-Sicherheitsprüfung vor dem Speichern.
|
- [x] Branding-Sicherheitsprüfung vor dem Speichern.
|
||||||
- [x] ExpiryIndicator-Site-Collection-Standard abgebildet.
|
- [x] ExpiryIndicator-Site-Collection-Standard abgebildet.
|
||||||
|
- [x] ExpiryIndicator direkt über seine Root-Web-Application-Customizer-Action erkennen.
|
||||||
- [x] Expiry-Bindungsinventar dargestellt.
|
- [x] Expiry-Bindungsinventar dargestellt.
|
||||||
- [x] Web-, Listen- und Datumsfeld-Picker umgesetzt.
|
- [x] Web-, Listen- und Datumsfeld-Picker umgesetzt.
|
||||||
- [x] Neue Field-Customizer-Bindung aus dem WebPart möglich.
|
- [x] Neue Field-Customizer-Bindung aus dem WebPart möglich.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"solution": {
|
"solution": {
|
||||||
"name": "portal-settings-client-side-solution",
|
"name": "portal-settings-client-side-solution",
|
||||||
"id": "1c98e32d-bb7b-43b7-9625-074d6e4ea286",
|
"id": "1c98e32d-bb7b-43b7-9625-074d6e4ea286",
|
||||||
"version": "3.2.0.0",
|
"version": "3.2.1.0",
|
||||||
"includeClientSideAssets": true,
|
"includeClientSideAssets": true,
|
||||||
"skipFeatureDeployment": false,
|
"skipFeatureDeployment": false,
|
||||||
"features": [
|
"features": [
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "portal-settings",
|
"name": "portal-settings",
|
||||||
"version": "3.2.0",
|
"version": "3.2.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "portal-settings",
|
"name": "portal-settings",
|
||||||
"version": "3.2.0",
|
"version": "3.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -32,13 +32,16 @@ export class PortalSettingsDataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public load(providers: Array<ISettingsProvider<any>>): Promise<ILoadedSettingsProvider[]> {
|
public load(providers: Array<ISettingsProvider<any>>): Promise<ILoadedSettingsProvider[]> {
|
||||||
return Promise.all([this.getSiteActions(), this.getRootProperties()])
|
return Promise.all([this.getSiteActions(), this.getRootWebActions(), this.getRootProperties()])
|
||||||
.then((values: any[]): ILoadedSettingsProvider[] => {
|
.then((values: any[]): ILoadedSettingsProvider[] => {
|
||||||
const actions: IUserCustomActionInfo[] = values[0];
|
const siteActions: IUserCustomActionInfo[] = values[0];
|
||||||
const properties: any = values[1];
|
const registrationActions: IUserCustomActionInfo[] = siteActions.concat(values[1]);
|
||||||
|
const properties: any = values[2];
|
||||||
const loaded: ILoadedSettingsProvider[] = [];
|
const loaded: ILoadedSettingsProvider[] = [];
|
||||||
for (let i: number = 0; i < providers.length; i++) {
|
for (let i: number = 0; i < providers.length; i++) {
|
||||||
const result: ILoadedSettingsProvider = this.loadProvider(providers[i], actions, properties);
|
const result: ILoadedSettingsProvider = this.loadProvider(
|
||||||
|
providers[i], siteActions, registrationActions, properties
|
||||||
|
);
|
||||||
if (result) { loaded.push(result); }
|
if (result) { loaded.push(result); }
|
||||||
}
|
}
|
||||||
return loaded;
|
return loaded;
|
||||||
@@ -178,13 +181,14 @@ export class PortalSettingsDataService {
|
|||||||
|
|
||||||
private loadProvider(
|
private loadProvider(
|
||||||
provider: ISettingsProvider<any>,
|
provider: ISettingsProvider<any>,
|
||||||
actions: IUserCustomActionInfo[],
|
siteActions: IUserCustomActionInfo[],
|
||||||
|
registrationActions: IUserCustomActionInfo[],
|
||||||
properties: any
|
properties: any
|
||||||
): ILoadedSettingsProvider | undefined {
|
): ILoadedSettingsProvider | undefined {
|
||||||
let raw: any;
|
let raw: any;
|
||||||
const context: IProviderLoadContext = {};
|
const context: IProviderLoadContext = {};
|
||||||
if (provider.storage.kind === 'siteUserCustomAction') {
|
if (provider.storage.kind === 'siteUserCustomAction') {
|
||||||
const action: IUserCustomActionInfo = this.findAction(provider, actions);
|
const action: IUserCustomActionInfo = this.findAction(provider, siteActions);
|
||||||
if (!action && !provider.storage.action) { return undefined; }
|
if (!action && !provider.storage.action) { return undefined; }
|
||||||
if (action) {
|
if (action) {
|
||||||
context.action = action;
|
context.action = action;
|
||||||
@@ -197,7 +201,7 @@ export class PortalSettingsDataService {
|
|||||||
const stored: any = this.getProperty(properties, propertyKey);
|
const stored: any = this.getProperty(properties, propertyKey);
|
||||||
const descriptor: any = this.getProperty(properties, DescriptorProperty);
|
const descriptor: any = this.getProperty(properties, DescriptorProperty);
|
||||||
const bindingsValue: any = this.getProperty(properties, BindingsProperty);
|
const bindingsValue: any = this.getProperty(properties, BindingsProperty);
|
||||||
const registration: IUserCustomActionInfo = this.findAnyAction(provider, actions);
|
const registration: IUserCustomActionInfo = this.findAnyAction(provider, registrationActions);
|
||||||
if (!stored && !descriptor && !bindingsValue && !registration) { return undefined; }
|
if (!stored && !descriptor && !bindingsValue && !registration) { return undefined; }
|
||||||
if (registration) { context.action = registration; }
|
if (registration) { context.action = registration; }
|
||||||
raw = this.parseJson(stored, provider.createDefault());
|
raw = this.parseJson(stored, provider.createDefault());
|
||||||
@@ -218,8 +222,18 @@ export class PortalSettingsDataService {
|
|||||||
private getSiteActions(): Promise<IUserCustomActionInfo[]> {
|
private getSiteActions(): Promise<IUserCustomActionInfo[]> {
|
||||||
const url: string = this.siteUrl + '/_api/site/UserCustomActions' +
|
const url: string = this.siteUrl + '/_api/site/UserCustomActions' +
|
||||||
'?$select=Id,Title,Name,Location,ClientSideComponentId,ClientSideComponentProperties';
|
'?$select=Id,Title,Name,Location,ClientSideComponentId,ClientSideComponentProperties';
|
||||||
|
return this.getActions(url, 'Site-Collection-UserCustomActions konnten nicht gelesen werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRootWebActions(): Promise<IUserCustomActionInfo[]> {
|
||||||
|
const url: string = this.siteUrl + '/_api/site/rootweb/UserCustomActions' +
|
||||||
|
'?$select=Id,Title,Name,Location,ClientSideComponentId,ClientSideComponentProperties';
|
||||||
|
return this.getActions(url, 'Root-Web-UserCustomActions konnten nicht gelesen werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
private getActions(url: string, errorMessage: string): Promise<IUserCustomActionInfo[]> {
|
||||||
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1, { headers: this.readHeaders() })
|
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1, { headers: this.readHeaders() })
|
||||||
.then((response: SPHttpClientResponse): Promise<any> => this.ensureJson(response, 'UserCustomActions konnten nicht gelesen werden.'))
|
.then((response: SPHttpClientResponse): Promise<any> => this.ensureJson(response, errorMessage))
|
||||||
.then((payload: any): IUserCustomActionInfo[] => this.results(payload).map((source: any): IUserCustomActionInfo => ({
|
.then((payload: any): IUserCustomActionInfo[] => this.results(payload).map((source: any): IUserCustomActionInfo => ({
|
||||||
id: this.normalizeGuid(source.Id),
|
id: this.normalizeGuid(source.Id),
|
||||||
title: source.Title || '',
|
title: source.Title || '',
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ var sourceFiles = [
|
|||||||
'src/ui/DynamicFormRenderer.ts',
|
'src/ui/DynamicFormRenderer.ts',
|
||||||
'src/ui/PortalSettingsApp.ts'
|
'src/ui/PortalSettingsApp.ts'
|
||||||
].map(read).join('\n');
|
].map(read).join('\n');
|
||||||
|
var dataService = read('src/services/PortalSettingsDataService.ts');
|
||||||
|
|
||||||
assert(packageJson.version === '3.2.0', 'Package-Version ist nicht 3.2.0.');
|
assert(packageJson.version === '3.2.1', 'Package-Version ist nicht 3.2.1.');
|
||||||
assert(solution.version === '3.2.0.0', 'Solution-Version ist nicht 3.2.0.0.');
|
assert(solution.version === '3.2.1.0', 'Solution-Version ist nicht 3.2.1.0.');
|
||||||
assert(solution.features && solution.features.length === 1, 'Das Seiten-Provisioning-Feature fehlt.');
|
assert(solution.features && solution.features.length === 1, 'Das Seiten-Provisioning-Feature fehlt.');
|
||||||
assert(solution.features[0].assets.elementManifests.indexOf('elements.xml') >= 0 &&
|
assert(solution.features[0].assets.elementManifests.indexOf('elements.xml') >= 0 &&
|
||||||
solution.features[0].assets.elementFiles.indexOf('PortalSettings.aspx') >= 0 &&
|
solution.features[0].assets.elementFiles.indexOf('PortalSettings.aspx') >= 0 &&
|
||||||
@@ -47,6 +48,9 @@ assert(upgradeActions.indexOf('71841e33-8bbd-4007-83a6-d950453226a2\\elements.xm
|
|||||||
'Die Upgrade-Provisionierung fehlt.');
|
'Die Upgrade-Provisionierung fehlt.');
|
||||||
assert(!fs.existsSync(path.join(root, 'src/extensions/portalSettings/PortalSettingsApplicationCustomizer.ts')), 'Alter Application Customizer ist noch vorhanden.');
|
assert(!fs.existsSync(path.join(root, 'src/extensions/portalSettings/PortalSettingsApplicationCustomizer.ts')), 'Alter Application Customizer ist noch vorhanden.');
|
||||||
assert(sourceFiles.indexOf('innerHTML') < 0, 'UI darf innerHTML nicht verwenden.');
|
assert(sourceFiles.indexOf('innerHTML') < 0, 'UI darf innerHTML nicht verwenden.');
|
||||||
|
assert(dataService.indexOf('/_api/site/rootweb/UserCustomActions') >= 0 &&
|
||||||
|
dataService.indexOf('siteActions.concat(values[1])') >= 0,
|
||||||
|
'Root-Web-Actions werden nicht für die Provider-Erkennung berücksichtigt.');
|
||||||
['themePrimary', 'neutralPrimary', 'neutralLight', 'white'].forEach(function (slot) {
|
['themePrimary', 'neutralPrimary', 'neutralLight', 'white'].forEach(function (slot) {
|
||||||
assert(styles.indexOf('[theme: ' + slot + ', default:') >= 0, 'Themeslot fehlt: ' + slot);
|
assert(styles.indexOf('[theme: ' + slot + ', default:') >= 0, 'Themeslot fehlt: ' + slot);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user