From 17ecec03b2177bf9510ed1e88014520d5389f02e Mon Sep 17 00:00:00 2001 From: Konstantin Schaper Date: Tue, 15 Jun 2021 15:36:21 +0200 Subject: [PATCH] tidy up suggestions api (#1699) Streamlines the suggestions/autocomplete api and removes redundancy. All logic accessing the backend is now in hooks in ui-api. --- scm-ui/ui-api/src/groupSuggestions.ts | 32 +++++++++++++ scm-ui/ui-api/src/index.ts | 2 + scm-ui/ui-api/src/suggestions.ts | 47 +++++++++++++++++++ scm-ui/ui-api/src/userSuggestions.ts | 28 ++--------- .../ui-components/src/GroupAutocomplete.tsx | 35 +++++++------- scm-ui/ui-components/src/UserAutocomplete.tsx | 35 +++++++------- .../src/UserGroupAutocomplete.tsx | 46 +++++------------- 7 files changed, 129 insertions(+), 96 deletions(-) create mode 100644 scm-ui/ui-api/src/groupSuggestions.ts create mode 100644 scm-ui/ui-api/src/suggestions.ts diff --git a/scm-ui/ui-api/src/groupSuggestions.ts b/scm-ui/ui-api/src/groupSuggestions.ts new file mode 100644 index 0000000000..e78f7733e7 --- /dev/null +++ b/scm-ui/ui-api/src/groupSuggestions.ts @@ -0,0 +1,32 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import { Link } from "@scm-manager/ui-types"; +import { useIndexLinks } from "./base"; +import { useSuggestions } from "./suggestions"; + +export const useGroupSuggestions = () => { + const indexLinks = useIndexLinks(); + const autocompleteLink = (indexLinks.autocomplete as Link[]).find((i) => i.name === "groups"); + return useSuggestions(autocompleteLink?.href); +}; diff --git a/scm-ui/ui-api/src/index.ts b/scm-ui/ui-api/src/index.ts index aec6bfe796..410cb85045 100644 --- a/scm-ui/ui-api/src/index.ts +++ b/scm-ui/ui-api/src/index.ts @@ -32,7 +32,9 @@ export * from "./base"; export * from "./login"; export * from "./groups"; export * from "./users"; +export * from "./suggestions"; export * from "./userSuggestions"; +export * from "./groupSuggestions"; export * from "./repositories"; export * from "./namespaces"; export * from "./branches"; diff --git a/scm-ui/ui-api/src/suggestions.ts b/scm-ui/ui-api/src/suggestions.ts new file mode 100644 index 0000000000..559d3b5c4a --- /dev/null +++ b/scm-ui/ui-api/src/suggestions.ts @@ -0,0 +1,47 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import { AutocompleteObject, SelectValue } from "@scm-manager/ui-types"; +import { apiClient } from "./apiclient"; + +export const useSuggestions: (link?: string) => (query: string) => Promise = (link) => { + if (!link) { + return () => Promise.resolve([]); + } + const url = link + "?q="; + return (inputValue) => { + // Prevent violate input condition of api call because parameter length is too short + if (inputValue.length < 2) { + return Promise.resolve([]); + } + return apiClient + .get(url + inputValue) + .then((response) => response.json()) + .then((json: AutocompleteObject[]) => + json.map((element) => ({ + value: element, + label: element.displayName ? `${element.displayName} (${element.id})` : element.id, + })) + ); + }; +}; diff --git a/scm-ui/ui-api/src/userSuggestions.ts b/scm-ui/ui-api/src/userSuggestions.ts index f2e7221add..f5c6d56644 100644 --- a/scm-ui/ui-api/src/userSuggestions.ts +++ b/scm-ui/ui-api/src/userSuggestions.ts @@ -21,32 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -import {DisplayedUser, Link, SelectValue} from "@scm-manager/ui-types"; +import { Link } from "@scm-manager/ui-types"; import { useIndexLinks } from "./base"; -import { apiClient } from "./apiclient"; +import { useSuggestions } from "./suggestions"; export const useUserSuggestions = () => { const indexLinks = useIndexLinks(); - const autocompleteLink = (indexLinks.autocomplete as Link[]).find(i => i.name === "users"); - if (!autocompleteLink) { - return []; - } - const url = autocompleteLink.href + "?q="; - return (inputValue: string): never[] | Promise => { - // Prevent violate input condition of api call because parameter length is too short - if (inputValue.length < 2) { - return []; - } - return apiClient - .get(url + inputValue) - .then(response => response.json()) - .then(json => { - return json.map((element: DisplayedUser) => { - return { - value: element, - label: `${element.displayName} (${element.id})` - }; - }); - }); - }; + const autocompleteLink = (indexLinks.autocomplete as Link[]).find((i) => i.name === "users"); + return useSuggestions(autocompleteLink?.href); }; diff --git a/scm-ui/ui-components/src/GroupAutocomplete.tsx b/scm-ui/ui-components/src/GroupAutocomplete.tsx index 662cb53e62..2b407ad94b 100644 --- a/scm-ui/ui-components/src/GroupAutocomplete.tsx +++ b/scm-ui/ui-components/src/GroupAutocomplete.tsx @@ -21,24 +21,21 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -import React from "react"; -import { WithTranslation, withTranslation } from "react-i18next"; -import AutocompleteProps from "./UserGroupAutocomplete"; -import UserGroupAutocomplete from "./UserGroupAutocomplete"; +import React, { FC } from "react"; +import UserGroupAutocomplete, { AutocompleteProps } from "./UserGroupAutocomplete"; +import { useTranslation } from "react-i18next"; -class GroupAutocomplete extends React.Component { - render() { - const { t } = this.props; - return ( - - ); - } -} +const GroupAutocomplete: FC = (props) => { + const [t] = useTranslation("commons"); + return ( + + ); +}; -export default withTranslation("commons")(GroupAutocomplete); +export default GroupAutocomplete; diff --git a/scm-ui/ui-components/src/UserAutocomplete.tsx b/scm-ui/ui-components/src/UserAutocomplete.tsx index 2b80a3d7e1..d618c7f3da 100644 --- a/scm-ui/ui-components/src/UserAutocomplete.tsx +++ b/scm-ui/ui-components/src/UserAutocomplete.tsx @@ -21,24 +21,21 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -import React from "react"; -import { WithTranslation, withTranslation } from "react-i18next"; -import AutocompleteProps from "./UserGroupAutocomplete"; -import UserGroupAutocomplete from "./UserGroupAutocomplete"; +import React, { FC } from "react"; +import { useTranslation } from "react-i18next"; +import UserGroupAutocomplete, { AutocompleteProps } from "./UserGroupAutocomplete"; -class UserAutocomplete extends React.Component { - render() { - const { t } = this.props; - return ( - - ); - } -} +const UserAutocomplete: FC = (props) => { + const [t] = useTranslation("commons"); + return ( + + ); +}; -export default withTranslation("commons")(UserAutocomplete); +export default UserAutocomplete; diff --git a/scm-ui/ui-components/src/UserGroupAutocomplete.tsx b/scm-ui/ui-components/src/UserGroupAutocomplete.tsx index c4a755d792..2eae39c1fd 100644 --- a/scm-ui/ui-components/src/UserGroupAutocomplete.tsx +++ b/scm-ui/ui-components/src/UserGroupAutocomplete.tsx @@ -21,10 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -import React from "react"; -import { SelectValue, AutocompleteObject } from "@scm-manager/ui-types"; +import React, { FC } from "react"; +import { SelectValue } from "@scm-manager/ui-types"; import Autocomplete from "./Autocomplete"; -import { apiClient } from "@scm-manager/ui-api"; +import { useSuggestions } from "@scm-manager/ui-api"; export type AutocompleteProps = { autocompleteLink?: string; @@ -39,38 +39,16 @@ type Props = AutocompleteProps & { placeholder: string; }; -export default class UserGroupAutocomplete extends React.Component { - loadSuggestions = (inputValue: string): Promise => { - const url = this.props.autocompleteLink; - const link = url + "?q="; - return apiClient - .get(link + inputValue) - .then(response => response.json()) - .then((json: AutocompleteObject[]) => { - return json.map(element => { - const label = element.displayName ? `${element.displayName} (${element.id})` : element.id; - return { - value: element, - label - }; - }); - }); - }; +const UserGroupAutocomplete: FC = ({ autocompleteLink, valueSelected, ...props }) => { + const loadSuggestions = useSuggestions(autocompleteLink); - selectName = (selection: SelectValue) => { - if (this.props.valueSelected) { - this.props.valueSelected(selection); + const selectName = (selection: SelectValue) => { + if (valueSelected) { + valueSelected(selection); } }; - render() { - return ( - - ); - } -} + return ; +}; + +export default UserGroupAutocomplete;