Aktualisiere Version auf 1.1.0, füge Unterstützung für verwaltete Metadatenkategorien hinzu und verbessere die Filterung in der Accordion-Komponente
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Accordion
|
# Accordion
|
||||||
|
|
||||||
Accordion 1.0.0 ist ein listenbasiertes SPFx-WebPart für SharePoint Server Subscription Edition. Es orientiert
|
Accordion 1.1.0 ist ein listenbasiertes SPFx-WebPart für SharePoint Server Subscription Edition. Es orientiert
|
||||||
sich funktional am PnP-Beispiel `react-accordion-dynamic-section`, verwendet aber die mit SharePoint SE
|
sich funktional am PnP-Beispiel `react-accordion-dynamic-section`, verwendet aber die mit SharePoint SE
|
||||||
kompatible SPFx-1.4.1-/React-15-Toolchain.
|
kompatible SPFx-1.4.1-/React-15-Toolchain.
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ kompatible SPFx-1.4.1-/React-15-Toolchain.
|
|||||||
- dynamische Auswahl von Überschrift-, Inhalt-, Kategorie- und Sortierspalte
|
- dynamische Auswahl von Überschrift-, Inhalt-, Kategorie- und Sortierspalte
|
||||||
- optionales Gruppieren nach Kategorien
|
- optionales Gruppieren nach Kategorien
|
||||||
- Filter auf eine konkrete, aktuell in der Liste verwendete Kategorie
|
- Filter auf eine konkrete, aktuell in der Liste verwendete Kategorie
|
||||||
|
- ein- und mehrwertige Managed-Metadata-Spalten als Kategorien
|
||||||
- auf- oder absteigende Sortierung
|
- auf- oder absteigende Sortierung
|
||||||
- initial vollständig geschlossen, erster Eintrag geöffnet oder alle Einträge geöffnet
|
- initial vollständig geschlossen, erster Eintrag geöffnet oder alle Einträge geöffnet
|
||||||
- wahlweise genau ein oder mehrere gleichzeitig geöffnete Bereiche
|
- wahlweise genau ein oder mehrere gleichzeitig geöffnete Bereiche
|
||||||
@@ -26,7 +27,7 @@ Es wird keine fachliche Liste provisioniert. Eine einfache FAQ-Liste kann beispi
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `Title` | Eine Textzeile | Überschrift |
|
| `Title` | Eine Textzeile | Überschrift |
|
||||||
| `Content` | Mehrere Textzeilen mit Rich Text | Inhalt |
|
| `Content` | Mehrere Textzeilen mit Rich Text | Inhalt |
|
||||||
| `Category` | Auswahl oder Text | optionale Gruppierung |
|
| `Category` | Auswahl, Text oder Managed Metadata | optionale Gruppierung |
|
||||||
| `SortOrder` | Zahl | optionale Sortierung |
|
| `SortOrder` | Zahl | optionale Sortierung |
|
||||||
|
|
||||||
Nach dem Hinzufügen des WebParts werden Liste und Spalten im Property Pane ausgewählt. Sobald eine
|
Nach dem Hinzufügen des WebParts werden Liste und Spalten im Property Pane ausgewählt. Sobald eine
|
||||||
@@ -38,7 +39,7 @@ nächsten Laden beziehungsweise Rendern der Seite automatisch.
|
|||||||
|
|
||||||
| Eigenschaft | Wert |
|
| Eigenschaft | Wert |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Version | 1.0.0 |
|
| Version | 1.1.0 |
|
||||||
| SharePoint Framework | 1.4.1 |
|
| SharePoint Framework | 1.4.1 |
|
||||||
| React | 15.6.2 |
|
| React | 15.6.2 |
|
||||||
| Node.js | 8.17.0 |
|
| Node.js | 8.17.0 |
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"name": "accordion-web-part",
|
"name": "accordion-web-part",
|
||||||
"title": "accordion-web-part",
|
"title": "accordion-web-part",
|
||||||
"id": "27a6fd90-42a1-4e39-8862-08ed0e7803bc",
|
"id": "27a6fd90-42a1-4e39-8862-08ed0e7803bc",
|
||||||
"version": "1.0.0.0",
|
"version": "1.1.0.0",
|
||||||
"includeClientSideAssets": true,
|
"includeClientSideAssets": true,
|
||||||
"skipFeatureDeployment": true
|
"skipFeatureDeployment": true
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "accordion-web-part",
|
"name": "accordion-web-part",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "gulp bundle",
|
"build": "gulp bundle",
|
||||||
"clean": "gulp clean",
|
"clean": "gulp clean",
|
||||||
"test": "tsc --noEmit -p . && node tests/validate-project.js",
|
"test": "tsc -p tests/tsconfig.json && node temp/tests/tests/AccordionCategoryValues.test.js && tsc --noEmit -p . && node tests/validate-project.js",
|
||||||
"package": "npm test && gulp clean && gulp bundle --ship && gulp package-solution --ship"
|
"package": "npm test && gulp clean && gulp bundle --ship && gulp package-solution --ship"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
export function getAccordionCategoryValues(value: any): string[] { // tslint:disable-line:no-any
|
||||||
|
if (value === undefined || value === null) { return []; }
|
||||||
|
const source: any[] = value && Array.isArray(value.results) ? value.results : [value]; // tslint:disable-line:no-any
|
||||||
|
const values: string[] = [];
|
||||||
|
const keys: { [key: string]: boolean } = {};
|
||||||
|
for (let i: number = 0; i < source.length; i++) {
|
||||||
|
const current: string[] = categoryEntryValues(source[i]);
|
||||||
|
for (let valueIndex: number = 0; valueIndex < current.length; valueIndex++) {
|
||||||
|
const text: string = current[valueIndex].trim();
|
||||||
|
const key: string = '$' + text.toLocaleLowerCase();
|
||||||
|
if (text && !keys[key]) { keys[key] = true; values.push(text); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
function categoryEntryValues(entry: any): string[] { // tslint:disable-line:no-any
|
||||||
|
if (entry === undefined || entry === null) { return []; }
|
||||||
|
if (entry.Label) { return [String(entry.Label)]; }
|
||||||
|
if (typeof entry !== 'string') {
|
||||||
|
if (typeof entry === 'number' || typeof entry === 'boolean') { return [String(entry)]; }
|
||||||
|
if (entry.Description || entry.Url) { return [String(entry.Description || entry.Url)]; }
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidate: string = entry.trim();
|
||||||
|
if (!candidate) { return []; }
|
||||||
|
let parts: string[] = [candidate];
|
||||||
|
if (candidate.indexOf(';#') >= 0) {
|
||||||
|
parts = candidate.split(';#');
|
||||||
|
} else if (candidate.indexOf(';') >= 0) {
|
||||||
|
const semicolonParts: string[] = candidate.split(';');
|
||||||
|
const allTaxonomyValues: boolean = semicolonParts.every((part: string): boolean =>
|
||||||
|
/\|[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(part.trim()));
|
||||||
|
if (allTaxonomyValues) { parts = semicolonParts; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const values: string[] = [];
|
||||||
|
for (let i: number = 0; i < parts.length; i++) {
|
||||||
|
const part: string = parts[i].trim();
|
||||||
|
if (!part || /^-?\d+$/.test(part)) { continue; }
|
||||||
|
const taxonomyMatch: RegExpMatchArray = part.match(/^(.*)\|[0-9a-f]{8}-[0-9a-f-]{27}$/i);
|
||||||
|
values.push(taxonomyMatch ? taxonomyMatch[1].trim() : part);
|
||||||
|
}
|
||||||
|
return values.filter((text: string): boolean => !!text);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
|
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
|
||||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||||
|
import { getAccordionCategoryValues } from './AccordionCategoryValues';
|
||||||
import { IAccordionFieldOption, IAccordionItem, IAccordionListOption } from './AccordionTypes';
|
import { IAccordionFieldOption, IAccordionItem, IAccordionListOption } from './AccordionTypes';
|
||||||
|
|
||||||
export class AccordionDataService {
|
export class AccordionDataService {
|
||||||
@@ -51,13 +52,16 @@ export class AccordionDataService {
|
|||||||
.then((response: SPHttpClientResponse): Promise<any> => this.ensureJson(response)) // tslint:disable-line:no-any
|
.then((response: SPHttpClientResponse): Promise<any> => this.ensureJson(response)) // tslint:disable-line:no-any
|
||||||
.then((payload: any): IAccordionItem[] => this.results(payload) // tslint:disable-line:no-any
|
.then((payload: any): IAccordionItem[] => this.results(payload) // tslint:disable-line:no-any
|
||||||
.filter((item: any): boolean => !categoryValue || // tslint:disable-line:no-any
|
.filter((item: any): boolean => !categoryValue || // tslint:disable-line:no-any
|
||||||
this.toValues(item[categoryField]).indexOf(categoryValue) >= 0)
|
getAccordionCategoryValues(item[categoryField]).indexOf(categoryValue) >= 0)
|
||||||
.map((item: any): IAccordionItem => ({ // tslint:disable-line:no-any
|
.map((item: any): IAccordionItem => { // tslint:disable-line:no-any
|
||||||
id: Number(item.Id),
|
const categories: string[] = categoryField ? getAccordionCategoryValues(item[categoryField]) : [];
|
||||||
title: this.toText(item[titleField]),
|
return {
|
||||||
content: this.toText(item[contentField]),
|
id: Number(item.Id),
|
||||||
category: categoryField ? this.toText(item[categoryField]) : ''
|
title: this.toText(item[titleField]),
|
||||||
})));
|
content: this.toText(item[contentField]),
|
||||||
|
categories: categories
|
||||||
|
};
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCategoryValues(listId: string, categoryField: string): Promise<string[]> {
|
public getCategoryValues(listId: string, categoryField: string): Promise<string[]> {
|
||||||
@@ -71,9 +75,9 @@ export class AccordionDataService {
|
|||||||
const keys: { [key: string]: boolean } = {};
|
const keys: { [key: string]: boolean } = {};
|
||||||
const items: any[] = this.results(payload); // tslint:disable-line:no-any
|
const items: any[] = this.results(payload); // tslint:disable-line:no-any
|
||||||
for (let i: number = 0; i < items.length; i++) {
|
for (let i: number = 0; i < items.length; i++) {
|
||||||
const current: string[] = this.toValues(items[i][categoryField]);
|
const current: string[] = getAccordionCategoryValues(items[i][categoryField]);
|
||||||
for (let valueIndex: number = 0; valueIndex < current.length; valueIndex++) {
|
for (let valueIndex: number = 0; valueIndex < current.length; valueIndex++) {
|
||||||
const key: string = current[valueIndex].toLocaleLowerCase();
|
const key: string = '$' + current[valueIndex].toLocaleLowerCase();
|
||||||
if (!keys[key]) { keys[key] = true; values.push(current[valueIndex]); }
|
if (!keys[key]) { keys[key] = true; values.push(current[valueIndex]); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,15 +117,9 @@ export class AccordionDataService {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
private toValues(value: any): string[] { // tslint:disable-line:no-any
|
|
||||||
if (value === undefined || value === null) { return []; }
|
|
||||||
const source: any[] = value && Array.isArray(value.results) ? value.results : [value]; // tslint:disable-line:no-any
|
|
||||||
return source.map((entry: any): string => this.toText(entry).trim()) // tslint:disable-line:no-any
|
|
||||||
.filter((entry: string): boolean => !!entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
private isSupportedField(type: string): boolean {
|
private isSupportedField(type: string): boolean {
|
||||||
return ['Text', 'Note', 'Choice', 'MultiChoice', 'Number', 'Integer', 'Boolean', 'DateTime', 'Computed'].indexOf(String(type)) >= 0;
|
return ['Text', 'Note', 'Choice', 'MultiChoice', 'Number', 'Integer', 'Boolean', 'DateTime', 'Computed',
|
||||||
|
'TaxonomyFieldType', 'TaxonomyFieldTypeMulti'].indexOf(String(type)) >= 0;
|
||||||
}
|
}
|
||||||
private isFieldName(value: string): boolean { return /^[A-Za-z_][A-Za-z0-9_]*$/.test(String(value || '')); }
|
private isFieldName(value: string): boolean { return /^[A-Za-z_][A-Za-z0-9_]*$/.test(String(value || '')); }
|
||||||
private isGuid(value: string): boolean { return /^[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(this.cleanGuid(value)); }
|
private isGuid(value: string): boolean { return /^[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(this.cleanGuid(value)); }
|
||||||
|
|||||||
@@ -15,6 +15,5 @@ export interface IAccordionItem {
|
|||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
category: string;
|
categories: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,13 +126,18 @@ export default class AccordionWebPart extends BaseClientSideWebPart<IAccordionWe
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||||
const fieldOptions: IPropertyPaneDropdownOption[] = this.fields.map((field: IAccordionFieldOption): IPropertyPaneDropdownOption => ({
|
const standardFields: IAccordionFieldOption[] = this.fields.filter((field: IAccordionFieldOption): boolean =>
|
||||||
|
!this.isTaxonomyField(field));
|
||||||
|
const fieldOptions: IPropertyPaneDropdownOption[] = standardFields.map((field: IAccordionFieldOption): IPropertyPaneDropdownOption => ({
|
||||||
|
key: field.internalName, text: field.title + ' (' + field.internalName + ')'
|
||||||
|
}));
|
||||||
|
const categoryFieldOptions: IPropertyPaneDropdownOption[] = this.fields.map((field: IAccordionFieldOption): IPropertyPaneDropdownOption => ({
|
||||||
key: field.internalName, text: field.title + ' (' + field.internalName + ')'
|
key: field.internalName, text: field.title + ' (' + field.internalName + ')'
|
||||||
}));
|
}));
|
||||||
const categoryOptions: IPropertyPaneDropdownOption[] = [{ key: '', text: strings.NoCategoryOption }];
|
const categoryOptions: IPropertyPaneDropdownOption[] = [{ key: '', text: strings.NoCategoryOption }];
|
||||||
const categoryValueOptions: IPropertyPaneDropdownOption[] = [{ key: '', text: strings.AllCategoriesOption }];
|
const categoryValueOptions: IPropertyPaneDropdownOption[] = [{ key: '', text: strings.AllCategoriesOption }];
|
||||||
const listOptions: IPropertyPaneDropdownOption[] = [{ key: '', text: strings.SelectOption }];
|
const listOptions: IPropertyPaneDropdownOption[] = [{ key: '', text: strings.SelectOption }];
|
||||||
for (let i: number = 0; i < fieldOptions.length; i++) { categoryOptions.push(fieldOptions[i]); }
|
for (let i: number = 0; i < categoryFieldOptions.length; i++) { categoryOptions.push(categoryFieldOptions[i]); }
|
||||||
for (let i: number = 0; i < this.categories.length; i++) {
|
for (let i: number = 0; i < this.categories.length; i++) {
|
||||||
categoryValueOptions.push({ key: this.categories[i], text: this.categories[i] });
|
categoryValueOptions.push({ key: this.categories[i], text: this.categories[i] });
|
||||||
}
|
}
|
||||||
@@ -247,26 +252,35 @@ export default class AccordionWebPart extends BaseClientSideWebPart<IAccordionWe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private applyFieldDefaults(): void {
|
private applyFieldDefaults(): void {
|
||||||
const names: string[] = this.fields.map((field: IAccordionFieldOption): string => field.internalName);
|
const standardFields: IAccordionFieldOption[] = this.fields.filter((field: IAccordionFieldOption): boolean =>
|
||||||
|
!this.isTaxonomyField(field));
|
||||||
|
const names: string[] = standardFields.map((field: IAccordionFieldOption): string => field.internalName);
|
||||||
|
const categoryNames: string[] = this.fields.map((field: IAccordionFieldOption): string => field.internalName);
|
||||||
if (names.indexOf(this.properties.titleField) < 0) {
|
if (names.indexOf(this.properties.titleField) < 0) {
|
||||||
this.properties.titleField = names.indexOf('Title') >= 0 ? 'Title' : (names[0] || '');
|
this.properties.titleField = names.indexOf('Title') >= 0 ? 'Title' : (names[0] || '');
|
||||||
}
|
}
|
||||||
if (names.indexOf(this.properties.contentField) < 0) {
|
if (names.indexOf(this.properties.contentField) < 0) {
|
||||||
const note: IAccordionFieldOption = this.fields.filter((field: IAccordionFieldOption): boolean =>
|
const note: IAccordionFieldOption = standardFields.filter((field: IAccordionFieldOption): boolean =>
|
||||||
field.type === 'Note' && field.internalName !== this.properties.titleField)[0];
|
field.type === 'Note' && field.internalName !== this.properties.titleField)[0];
|
||||||
this.properties.contentField = note ? note.internalName : this.firstDifferentField(this.properties.titleField);
|
this.properties.contentField = note ? note.internalName : this.firstDifferentField(this.properties.titleField);
|
||||||
}
|
}
|
||||||
if (names.indexOf(this.properties.categoryField) < 0) { this.properties.categoryField = ''; }
|
if (categoryNames.indexOf(this.properties.categoryField) < 0) { this.properties.categoryField = ''; }
|
||||||
if (names.indexOf(this.properties.sortField) < 0) { this.properties.sortField = this.properties.titleField; }
|
if (names.indexOf(this.properties.sortField) < 0) { this.properties.sortField = this.properties.titleField; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private firstDifferentField(excluded: string): string {
|
private firstDifferentField(excluded: string): string {
|
||||||
for (let i: number = 0; i < this.fields.length; i++) {
|
for (let i: number = 0; i < this.fields.length; i++) {
|
||||||
if (this.fields[i].internalName !== excluded) { return this.fields[i].internalName; }
|
if (this.fields[i].internalName !== excluded && !this.isTaxonomyField(this.fields[i])) {
|
||||||
|
return this.fields[i].internalName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isTaxonomyField(field: IAccordionFieldOption): boolean {
|
||||||
|
return field.type === 'TaxonomyFieldType' || field.type === 'TaxonomyFieldTypeMulti';
|
||||||
|
}
|
||||||
|
|
||||||
private isConfigured(): boolean {
|
private isConfigured(): boolean {
|
||||||
return !!(this.service && this.properties.listId && this.properties.titleField && this.properties.contentField);
|
return !!(this.service && this.properties.listId && this.properties.titleField && this.properties.contentField);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,17 +28,17 @@ export default class Accordion extends React.Component<IAccordionProps, IAccordi
|
|||||||
{this.props.showCategories && group.name
|
{this.props.showCategories && group.name
|
||||||
? <h2 className={styles.categoryTitle}>{group.name}</h2>
|
? <h2 className={styles.categoryTitle}>{group.name}</h2>
|
||||||
: undefined}
|
: undefined}
|
||||||
<div>{group.items.map((item: IAccordionItem) => this.renderItem(item))}</div>
|
<div>{group.items.map((item: IAccordionItem) => this.renderItem(item, groupIndex))}</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderItem(item: IAccordionItem): React.ReactElement<any> { // tslint:disable-line:no-any
|
private renderItem(item: IAccordionItem, groupIndex: number): React.ReactElement<any> { // tslint:disable-line:no-any
|
||||||
const open: boolean = this.state.openIds.indexOf(item.id) >= 0;
|
const open: boolean = this.state.openIds.indexOf(item.id) >= 0;
|
||||||
const buttonId: string = this.instanceId + '-button-' + item.id;
|
const buttonId: string = this.instanceId + '-button-' + groupIndex + '-' + item.id;
|
||||||
const panelId: string = this.instanceId + '-panel-' + item.id;
|
const panelId: string = this.instanceId + '-panel-' + groupIndex + '-' + item.id;
|
||||||
return <div className={styles.item} key={item.id}>
|
return <div className={styles.item} key={groupIndex + '-' + item.id}>
|
||||||
<h3 className={styles.heading}>
|
<h3 className={styles.heading}>
|
||||||
<button type='button' id={buttonId} className={styles.trigger}
|
<button type='button' id={buttonId} className={styles.trigger}
|
||||||
aria-expanded={open} aria-controls={panelId}
|
aria-expanded={open} aria-controls={panelId}
|
||||||
@@ -75,12 +75,18 @@ export default class Accordion extends React.Component<IAccordionProps, IAccordi
|
|||||||
const result: Array<{ name: string; items: IAccordionItem[] }> = [];
|
const result: Array<{ name: string; items: IAccordionItem[] }> = [];
|
||||||
const byName: { [name: string]: { name: string; items: IAccordionItem[] } } = {};
|
const byName: { [name: string]: { name: string; items: IAccordionItem[] } } = {};
|
||||||
for (let i: number = 0; i < this.props.items.length; i++) {
|
for (let i: number = 0; i < this.props.items.length; i++) {
|
||||||
const name: string = this.props.items[i].category || this.props.defaultCategory;
|
const names: string[] = this.props.items[i].categories.length
|
||||||
if (!byName[name]) {
|
? this.props.items[i].categories
|
||||||
byName[name] = { name: name, items: [] };
|
: [this.props.defaultCategory];
|
||||||
result.push(byName[name]);
|
for (let nameIndex: number = 0; nameIndex < names.length; nameIndex++) {
|
||||||
|
const name: string = names[nameIndex];
|
||||||
|
const groupKey: string = '$' + name.toLocaleLowerCase();
|
||||||
|
if (!byName[groupKey]) {
|
||||||
|
byName[groupKey] = { name: name, items: [] };
|
||||||
|
result.push(byName[groupKey]);
|
||||||
|
}
|
||||||
|
byName[groupKey].items.push(this.props.items[i]);
|
||||||
}
|
}
|
||||||
byName[name].items.push(this.props.items[i]);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { getAccordionCategoryValues } from '../src/webparts/accordion/AccordionCategoryValues';
|
||||||
|
|
||||||
|
let passed: number = 0;
|
||||||
|
function assertValues(actual: string[], expected: string[], message: string): void {
|
||||||
|
if (actual.join('|') !== expected.join('|')) {
|
||||||
|
throw new Error(message + ': ' + actual.join('|'));
|
||||||
|
}
|
||||||
|
passed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstGuid: string = '11111111-1111-1111-1111-111111111111';
|
||||||
|
const secondGuid: string = '22222222-2222-2222-2222-222222222222';
|
||||||
|
|
||||||
|
assertValues(getAccordionCategoryValues({ Label: 'Human Resources', TermGuid: firstGuid }),
|
||||||
|
['Human Resources'], 'Single taxonomy value was not parsed.');
|
||||||
|
assertValues(getAccordionCategoryValues({ results: [
|
||||||
|
{ Label: 'Policies', TermGuid: firstGuid },
|
||||||
|
{ Label: 'Benefits', TermGuid: secondGuid }
|
||||||
|
] }), ['Policies', 'Benefits'], 'Multi-value taxonomy collection was not parsed.');
|
||||||
|
assertValues(getAccordionCategoryValues('-1;#Policies|' + firstGuid + ';#-1;#Benefits|' + secondGuid),
|
||||||
|
['Policies', 'Benefits'], 'Serialized SharePoint taxonomy value was not parsed.');
|
||||||
|
assertValues(getAccordionCategoryValues('Policies|' + firstGuid + ';Benefits|' + secondGuid),
|
||||||
|
['Policies', 'Benefits'], 'Compact serialized taxonomy value was not parsed.');
|
||||||
|
assertValues(getAccordionCategoryValues({ results: ['General', 'General', 'News'] }),
|
||||||
|
['General', 'News'], 'Choice values were not retained and de-duplicated.');
|
||||||
|
|
||||||
|
console.log('Accordion category value tests passed:', passed);
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"outDir": "../temp/tests",
|
||||||
|
"rootDir": "..",
|
||||||
|
"lib": ["es5", "dom"],
|
||||||
|
"types": [],
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"../src/webparts/accordion/AccordionCategoryValues.ts",
|
||||||
|
"AccordionCategoryValues.test.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -18,8 +18,8 @@ var component = read('src/webparts/accordion/components/Accordion.tsx');
|
|||||||
var sanitizer = read('src/webparts/accordion/AccordionHtmlSanitizer.ts');
|
var sanitizer = read('src/webparts/accordion/AccordionHtmlSanitizer.ts');
|
||||||
var styles = read('src/webparts/accordion/components/Accordion.module.scss');
|
var styles = read('src/webparts/accordion/components/Accordion.module.scss');
|
||||||
|
|
||||||
assert(packageJson.version === '1.0.0', 'Package version must be 1.0.0.');
|
assert(packageJson.version === '1.1.0', 'Package version must be 1.1.0.');
|
||||||
assert(solution.version === '1.0.0.0', 'Solution version must be 1.0.0.0.');
|
assert(solution.version === '1.1.0.0', 'Solution version must be 1.1.0.0.');
|
||||||
assert(solution.includeClientSideAssets === true, 'Client-side assets must be included.');
|
assert(solution.includeClientSideAssets === true, 'Client-side assets must be included.');
|
||||||
assert(solution.skipFeatureDeployment === true, 'Solution must support central deployment.');
|
assert(solution.skipFeatureDeployment === true, 'Solution must support central deployment.');
|
||||||
assert(packageJson.name === 'accordion-web-part' && solution.name === 'accordion-web-part' &&
|
assert(packageJson.name === 'accordion-web-part' && solution.name === 'accordion-web-part' &&
|
||||||
@@ -34,6 +34,15 @@ assert(webPart.indexOf("PropertyPaneDropdown('categoryField'") >= 0, 'Category f
|
|||||||
assert(webPart.indexOf("PropertyPaneDropdown('selectedCategory'") >= 0, 'Category value filter is missing.');
|
assert(webPart.indexOf("PropertyPaneDropdown('selectedCategory'") >= 0, 'Category value filter is missing.');
|
||||||
assert(read('src/webparts/accordion/AccordionDataService.ts').indexOf('getCategoryValues') >= 0,
|
assert(read('src/webparts/accordion/AccordionDataService.ts').indexOf('getCategoryValues') >= 0,
|
||||||
'Dynamic category values are missing.');
|
'Dynamic category values are missing.');
|
||||||
|
var dataService = read('src/webparts/accordion/AccordionDataService.ts');
|
||||||
|
var categoryValues = read('src/webparts/accordion/AccordionCategoryValues.ts');
|
||||||
|
assert(dataService.indexOf("'TaxonomyFieldType'") >= 0 &&
|
||||||
|
dataService.indexOf("'TaxonomyFieldTypeMulti'") >= 0 &&
|
||||||
|
dataService.indexOf('getAccordionCategoryValues') >= 0 &&
|
||||||
|
categoryValues.indexOf('entry.Label') >= 0 && categoryValues.indexOf("candidate.indexOf(';#')") >= 0,
|
||||||
|
'Managed Metadata category support is missing.');
|
||||||
|
assert(component.indexOf('items[i].categories') >= 0 && component.indexOf('nameIndex') >= 0,
|
||||||
|
'Multi-value category grouping is missing.');
|
||||||
assert(component.indexOf("aria-expanded={open}") >= 0 && component.indexOf("role='region'") >= 0,
|
assert(component.indexOf("aria-expanded={open}") >= 0 && component.indexOf("role='region'") >= 0,
|
||||||
'Accessible accordion semantics are missing.');
|
'Accessible accordion semantics are missing.');
|
||||||
assert(component.indexOf('sanitizeAccordionHtml(item.content)') >= 0, 'Rich text is not sanitized before rendering.');
|
assert(component.indexOf('sanitizeAccordionHtml(item.content)') >= 0, 'Rich text is not sanitized before rendering.');
|
||||||
|
|||||||
Reference in New Issue
Block a user