From a016710c3531305247a062954ce76b6447250565 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Mon, 24 Feb 2020 15:02:03 +0100 Subject: [PATCH 1/4] Sorted extension point entries with supplied extensionName --- CHANGELOG.md | 3 ++ .../src/config/ConfigurationBinder.tsx | 2 +- scm-ui/ui-extensions/src/binder.test.ts | 49 +++++++++++++------ scm-ui/ui-extensions/src/binder.ts | 28 ++++++++++- 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd845f009c..3f40686a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added +- Extension point entries with supplied extensionName are sorted ascending + ### Fixed - Modification for mercurial repositories with enabled XSRF protection diff --git a/scm-ui/ui-components/src/config/ConfigurationBinder.tsx b/scm-ui/ui-components/src/config/ConfigurationBinder.tsx index f2e3669a5e..d99c3d12ce 100644 --- a/scm-ui/ui-components/src/config/ConfigurationBinder.tsx +++ b/scm-ui/ui-components/src/config/ConfigurationBinder.tsx @@ -41,7 +41,7 @@ class ConfigurationBinder { }); // bind navigation link to extension point - binder.bind("admin.setting", ConfigNavLink, configPredicate); + binder.bind("admin.setting", ConfigNavLink, configPredicate, labelI18nKey); // route for global configuration, passes the link from the index resource to component const ConfigRoute = ({ url, links, ...additionalProps }: GlobalRouteProps) => { diff --git a/scm-ui/ui-extensions/src/binder.test.ts b/scm-ui/ui-extensions/src/binder.test.ts index 2bcd302a36..18cd969eb3 100644 --- a/scm-ui/ui-extensions/src/binder.test.ts +++ b/scm-ui/ui-extensions/src/binder.test.ts @@ -13,31 +13,31 @@ describe("binder tests", () => { }); it("should return the binded extensions", () => { - binder.bind("hitchhicker.trillian", "heartOfGold"); - binder.bind("hitchhicker.trillian", "earth"); + binder.bind("hitchhiker.trillian", "heartOfGold"); + binder.bind("hitchhiker.trillian", "earth"); - const extensions = binder.getExtensions("hitchhicker.trillian"); + const extensions = binder.getExtensions("hitchhiker.trillian"); expect(extensions).toEqual(["heartOfGold", "earth"]); }); it("should return the first bound extension", () => { - binder.bind("hitchhicker.trillian", "heartOfGold"); - binder.bind("hitchhicker.trillian", "earth"); + binder.bind("hitchhiker.trillian", "heartOfGold"); + binder.bind("hitchhiker.trillian", "earth"); - expect(binder.getExtension("hitchhicker.trillian")).toBe("heartOfGold"); + expect(binder.getExtension("hitchhiker.trillian")).toBe("heartOfGold"); }); it("should return null if no extension was bound", () => { - expect(binder.getExtension("hitchhicker.trillian")).toBe(null); + expect(binder.getExtension("hitchhiker.trillian")).toBe(null); }); it("should return true, if an extension is bound", () => { - binder.bind("hitchhicker.trillian", "heartOfGold"); - expect(binder.hasExtension("hitchhicker.trillian")).toBe(true); + binder.bind("hitchhiker.trillian", "heartOfGold"); + expect(binder.hasExtension("hitchhiker.trillian")).toBe(true); }); it("should return false, if no extension is bound", () => { - expect(binder.hasExtension("hitchhicker.trillian")).toBe(false); + expect(binder.hasExtension("hitchhiker.trillian")).toBe(false); }); type Props = { @@ -45,13 +45,34 @@ describe("binder tests", () => { }; it("should return only extensions which predicates matches", () => { - binder.bind("hitchhicker.trillian", "heartOfGold", (props: Props) => props.category === "a"); - binder.bind("hitchhicker.trillian", "earth", (props: Props) => props.category === "b"); - binder.bind("hitchhicker.trillian", "earth2", (props: Props) => props.category === "a"); + binder.bind("hitchhiker.trillian", "heartOfGold", (props: Props) => props.category === "a"); + binder.bind("hitchhiker.trillian", "earth", (props: Props) => props.category === "b"); + binder.bind("hitchhiker.trillian", "earth2", (props: Props) => props.category === "a"); - const extensions = binder.getExtensions("hitchhicker.trillian", { + const extensions = binder.getExtensions("hitchhiker.trillian", { category: "b" }); expect(extensions).toEqual(["earth"]); }); + + it("should return extensions in ascending order", () => { + binder.bind("hitchhiker.trillian", "planetA", () => true, "zeroWaste"); + binder.bind("hitchhiker.trillian", "planetB", () => true, "EPSILON"); + binder.bind("hitchhiker.trillian", "planetC", () => true, "emptyBin"); + binder.bind("hitchhiker.trillian", "planetD", () => true, "absolute"); + + const extensions = binder.getExtensions("hitchhiker.trillian"); + expect(extensions).toEqual(["planetD", "planetC", "planetB", "planetA"]); + }); + + it("should return extensions starting with entries with specified extensionName", () => { + binder.bind("hitchhiker.trillian", "planetA", () => true); + binder.bind("hitchhiker.trillian", "planetB", () => true, "zeroWaste"); + binder.bind("hitchhiker.trillian", "planetC", () => true); + binder.bind("hitchhiker.trillian", "planetD", () => true, "emptyBin"); + + const extensions = binder.getExtensions("hitchhiker.trillian"); + expect(extensions[0]).toEqual("planetD"); + expect(extensions[1]).toEqual("planetB"); + }); }); diff --git a/scm-ui/ui-extensions/src/binder.ts b/scm-ui/ui-extensions/src/binder.ts index a359973a50..e0077b0b67 100644 --- a/scm-ui/ui-extensions/src/binder.ts +++ b/scm-ui/ui-extensions/src/binder.ts @@ -3,6 +3,7 @@ type Predicate = (props: any) => boolean; type ExtensionRegistration = { predicate: Predicate; extension: any; + extensionName: string; }; /** @@ -25,13 +26,14 @@ export class Binder { * @param extension provided extension * @param predicate to decide if the extension gets rendered for the given props */ - bind(extensionPoint: string, extension: any, predicate?: Predicate) { + bind(extensionPoint: string, extension: any, predicate?: Predicate, extensionName?: string) { if (!this.extensionPoints[extensionPoint]) { this.extensionPoints[extensionPoint] = []; } const registration = { predicate: predicate ? predicate : () => true, - extension + extension, + extensionName: extensionName ? extensionName : "" }; this.extensionPoints[extensionPoint].push(registration); } @@ -61,6 +63,7 @@ export class Binder { if (props) { registrations = registrations.filter(reg => reg.predicate(props || {})); } + registrations.sort(this.sortExtensions); return registrations.map(reg => reg.extension); } @@ -70,6 +73,27 @@ export class Binder { hasExtension(extensionPoint: string, props?: object): boolean { return this.getExtensions(extensionPoint, props).length > 0; } + + /** + * Sort extensions in ascending order. + */ + sortExtensions = (a: ExtensionRegistration, b: ExtensionRegistration) => { + const regA = a.extensionName ? a.extensionName.toUpperCase() : ""; + const regB = b.extensionName ? b.extensionName.toUpperCase() : ""; + + if (regA === "" && regB === "") { + return 0; + } else if (regA === "") { + return 1; + } else if (regB === "") { + return -1; + } else if (regA > regB) { + return 1; + } else if (regA < regB) { + return -1; + } + return 0; + }; } // singleton binder From a5f27adc71073ef138c7a6da56b8ddadb5fc6aa0 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Mon, 24 Feb 2020 15:05:13 +0100 Subject: [PATCH 2/4] Described sort method in a more understandable way --- scm-ui/ui-extensions/src/binder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-ui/ui-extensions/src/binder.ts b/scm-ui/ui-extensions/src/binder.ts index e0077b0b67..32c814b8fd 100644 --- a/scm-ui/ui-extensions/src/binder.ts +++ b/scm-ui/ui-extensions/src/binder.ts @@ -75,7 +75,7 @@ export class Binder { } /** - * Sort extensions in ascending order. + * Sort extensions in ascending order, starting with entries with specified extensionName. */ sortExtensions = (a: ExtensionRegistration, b: ExtensionRegistration) => { const regA = a.extensionName ? a.extensionName.toUpperCase() : ""; From a557997fa4fc736061885125f73bc65dbb0ea4e0 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Tue, 25 Feb 2020 09:18:29 +0100 Subject: [PATCH 3/4] Simplify sort extensions method --- scm-ui/ui-extensions/src/binder.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scm-ui/ui-extensions/src/binder.ts b/scm-ui/ui-extensions/src/binder.ts index 32c814b8fd..693fbb655a 100644 --- a/scm-ui/ui-extensions/src/binder.ts +++ b/scm-ui/ui-extensions/src/binder.ts @@ -81,11 +81,9 @@ export class Binder { const regA = a.extensionName ? a.extensionName.toUpperCase() : ""; const regB = b.extensionName ? b.extensionName.toUpperCase() : ""; - if (regA === "" && regB === "") { - return 0; - } else if (regA === "") { + if (regA === "" && regB !== "") { return 1; - } else if (regB === "") { + } else if (regA !== "" && regB === "") { return -1; } else if (regA > regB) { return 1; From 2b0d4a65a078a59d0f7d51c70e9d331ad4bbffd4 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Tue, 25 Feb 2020 15:23:56 +0000 Subject: [PATCH 4/4] Close branch feature/sort_extensionpoint_entries