Merge branch 'main' of https://github.com/pnp/sp-dev-fx-webparts
This commit is contained in:
commit
5820cd56ef
File diff suppressed because it is too large
Load Diff
|
@ -23,7 +23,7 @@
|
|||
"office-ui-fabric-react": "6.189.2",
|
||||
"@types/webpack-env": "1.13.1",
|
||||
"botframework-directlinejs": "^0.11.4",
|
||||
"botframework-webchat": "^4.5.2",
|
||||
"botframework-webchat": "^4.15.6",
|
||||
"react": "16.8.5",
|
||||
"react-dom": "16.8.5",
|
||||
"swagger-client": "^2.1.23"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
v14.20.0
|
|
@ -30,6 +30,7 @@ Version|Date|Comments
|
|||
1.4|June 29, 2022|Adds the capability to find collapsible section headers and insert them into the navigation
|
||||
1.5|July 19, 2022|Bug fixes
|
||||
1.6|August 8, 2022|Add theme provider and bug fixes
|
||||
1.7|December 22, 2022|Fixed issue with duplicated level 2 headings
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"This web part fetches all the automatically added Header anchor tags in a SharePoint page and displays them in a Navigation component."
|
||||
],
|
||||
"creationDateTime": "2019-09-05",
|
||||
"updateDateTime": "2022-08-17",
|
||||
"updateDateTime": "2022-12-22",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"preset": "@voitanos/jest-preset-spfx-react16",
|
||||
"rootDir": "../src"
|
||||
"rootDir": "../src",
|
||||
"collectCoverage": false
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
import { IHierarchyEntry, navLinkBuilder } from "./NavLinkBuilder";
|
||||
|
||||
interface IMockLink extends IHierarchyEntry<IMockLink> {
|
||||
name: string;
|
||||
}
|
||||
|
||||
const DEPTH_NO_COLLAPSABLE_HEADER = 0;
|
||||
const DEPTH_COLLAPSABLE_HEADER = 1;
|
||||
|
||||
describe("The NavLinkBuilder without a preceding collapsable header", () => {
|
||||
|
||||
const depth = DEPTH_NO_COLLAPSABLE_HEADER;
|
||||
const h1 = depth;
|
||||
const h2 = h1+1;
|
||||
const h3 = h2+1;
|
||||
const h4 = h3+1;
|
||||
|
||||
it("should add a single item to an empty list", () => {
|
||||
const lnk: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
|
||||
const actual = [];
|
||||
navLinkBuilder.build(actual, lnk, h1);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a two items on the same level", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
|
||||
const actual = [];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h1);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it("should add a two items on different levels", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
|
||||
const actual = [];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a two items on the same level and two items on different levels", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
const lnk11: IMockLink = {
|
||||
name: "xyz.1",
|
||||
};
|
||||
const lnk21: IMockLink = {
|
||||
name: "abc.1",
|
||||
};
|
||||
|
||||
const actual = [];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk11, h2);
|
||||
navLinkBuilder.build(actual, lnk2, h1);
|
||||
navLinkBuilder.build(actual, lnk21, h2);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a four items on different levels", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "def",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "geh",
|
||||
};
|
||||
|
||||
const actual = [];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
navLinkBuilder.build(actual, lnk3, h3);
|
||||
navLinkBuilder.build(actual, lnk4, h4);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not nest two h2", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
|
||||
const actual = []
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
navLinkBuilder.build(actual, lnk3, h2);
|
||||
navLinkBuilder.build(actual, lnk4, h3);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not nest two h3", () => {
|
||||
const lnk0: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk5: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk6: IMockLink = {
|
||||
name: "h4",
|
||||
};
|
||||
|
||||
const actual = [];
|
||||
navLinkBuilder.build(actual, lnk0, h1);
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
navLinkBuilder.build(actual, lnk3, h2);
|
||||
navLinkBuilder.build(actual, lnk4, h3);
|
||||
navLinkBuilder.build(actual, lnk5, h3);
|
||||
navLinkBuilder.build(actual, lnk6, h4);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("The NavLinkBuilder with a collapsable header", () => {
|
||||
let head: IMockLink;
|
||||
const depth = DEPTH_COLLAPSABLE_HEADER;
|
||||
const h1 = depth;
|
||||
const h2 = h1+1;
|
||||
const h3 = h2+1;
|
||||
const h4 = h3+1;
|
||||
|
||||
beforeEach(() => {
|
||||
head = {
|
||||
name: "head",
|
||||
};
|
||||
});
|
||||
|
||||
it("should add a single item to the heading", () => {
|
||||
const lnk: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
|
||||
const actual = [ head ];
|
||||
navLinkBuilder.build(actual, lnk, h1);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should add a two items on the same level", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
|
||||
const actual = [ head ];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h1);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it("should add a one item in a collapsable section two inside that one", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "xyz",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "abc",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "def",
|
||||
};
|
||||
|
||||
const actual = [ head ];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
navLinkBuilder.build(actual, lnk3, h2);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
})
|
||||
|
||||
it("should not nest two h2", () => {
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
|
||||
const actual = [ head ];
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
navLinkBuilder.build(actual, lnk3, h2);
|
||||
navLinkBuilder.build(actual, lnk4, h3);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not nest two h3", () => {
|
||||
const lnk0: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk1: IMockLink = {
|
||||
name: "h1",
|
||||
};
|
||||
const lnk2: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk3: IMockLink = {
|
||||
name: "h2",
|
||||
};
|
||||
const lnk4: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk5: IMockLink = {
|
||||
name: "h3",
|
||||
};
|
||||
const lnk6: IMockLink = {
|
||||
name: "h4",
|
||||
};
|
||||
|
||||
const actual = [ head ];
|
||||
navLinkBuilder.build(actual, lnk0, h1);
|
||||
navLinkBuilder.build(actual, lnk1, h1);
|
||||
navLinkBuilder.build(actual, lnk2, h2);
|
||||
navLinkBuilder.build(actual, lnk3, h2);
|
||||
navLinkBuilder.build(actual, lnk4, h3);
|
||||
navLinkBuilder.build(actual, lnk5, h3);
|
||||
navLinkBuilder.build(actual, lnk6, h4);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
export interface IHierarchyEntry<T extends IHierarchyEntry<T>> {
|
||||
links?: IHierarchyEntry<T>[];
|
||||
}
|
||||
|
||||
export class navLinkBuilder {
|
||||
/**
|
||||
* Nests a new nav link within the nav links tree. Modifies the current tree IN PLACE.
|
||||
* @param currentLinks current nav links
|
||||
* @param newLink the new nav link to be added to the structure
|
||||
* @param order place order of the new link
|
||||
* @returns navLinks
|
||||
*/
|
||||
public static build<T extends IHierarchyEntry<T>>(currentLinks: T[], newLink: T, order: number) {
|
||||
const lastIndex = currentLinks.length - 1;
|
||||
|
||||
if (lastIndex < 0 || order <= 0) {
|
||||
currentLinks.push(newLink);
|
||||
return;
|
||||
}
|
||||
|
||||
const lastTopLevelLink = currentLinks[lastIndex];
|
||||
lastTopLevelLink.links = lastTopLevelLink.links || [];
|
||||
|
||||
order--;
|
||||
this.build(lastTopLevelLink.links, newLink, order);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { INavLink } from 'office-ui-fabric-react/lib/Nav';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { SPHttpClient } from '@microsoft/sp-http';
|
||||
import { navLinkBuilder } from './NavLinkBuilder';
|
||||
|
||||
export class SPService {
|
||||
/* Array to store all unique anchor URLs */
|
||||
|
@ -37,33 +38,6 @@ export class SPService {
|
|||
return anchorUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nests a new nav link within the nav links tree
|
||||
* @param currentLinks current nav links
|
||||
* @param newLink the new nav link to be added to the structure
|
||||
* @param order place order of the new link
|
||||
* @param depth sequence depth
|
||||
* @returns navLinks
|
||||
*/
|
||||
public static navLinkBuilder(currentLinks: INavLink[], newLink: INavLink, order: number, depth: number): INavLink[] {
|
||||
const lastIndex = currentLinks.length - 1;
|
||||
|
||||
if (lastIndex === -1) {
|
||||
currentLinks.push(newLink);
|
||||
} else if (currentLinks[lastIndex].links.length === 0 || order === depth) {
|
||||
if (order !== depth || depth !== 0) {
|
||||
currentLinks[lastIndex].links.push(newLink);
|
||||
} else {
|
||||
currentLinks.push(newLink);
|
||||
}
|
||||
} else {
|
||||
depth++;
|
||||
currentLinks[lastIndex].links.concat(this.navLinkBuilder(currentLinks[lastIndex].links, newLink, order, depth));
|
||||
}
|
||||
|
||||
return currentLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Anchor Links for Nav element
|
||||
* @param context Web part context
|
||||
|
@ -126,7 +100,7 @@ export class SPService {
|
|||
|
||||
// Add link to nav element
|
||||
const newNavLink: INavLink = { name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true };
|
||||
anchorLinks = this.navLinkBuilder(anchorLinks, newNavLink, headingOrder, hasCollapsableHeader ? 1 : 0);
|
||||
navLinkBuilder.build<INavLink>(anchorLinks, newNavLink, headingOrder);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should add a one item in a collapsable section two inside that one 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
Object {
|
||||
"name": "def",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should add a single item to the heading 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should add a two items on the same level 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should not nest two h2 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder with a collapsable header should not nest two h3 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h1",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h4",
|
||||
},
|
||||
],
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
],
|
||||
"name": "head",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a four items on different levels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "geh",
|
||||
},
|
||||
],
|
||||
"name": "def",
|
||||
},
|
||||
],
|
||||
"name": "abc",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a single item to an empty list 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a two items on different levels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a two items on the same level 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"name": "xyz",
|
||||
},
|
||||
Object {
|
||||
"name": "abc",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should add a two items on the same level and two items on different levels 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "xyz.1",
|
||||
},
|
||||
],
|
||||
"name": "xyz",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "abc.1",
|
||||
},
|
||||
],
|
||||
"name": "abc",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should not nest two h2 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`The NavLinkBuilder without a preceding collapsable header should not nest two h3 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"name": "h1",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h2",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h3",
|
||||
},
|
||||
Object {
|
||||
"links": Array [
|
||||
Object {
|
||||
"name": "h4",
|
||||
},
|
||||
],
|
||||
"name": "h3",
|
||||
},
|
||||
],
|
||||
"name": "h2",
|
||||
},
|
||||
],
|
||||
"name": "h1",
|
||||
},
|
||||
]
|
||||
`;
|
Loading…
Reference in New Issue