From 303e7f1e50239fd0968a329493a5163645c46308 Mon Sep 17 00:00:00 2001 From: Florian Scholdei Date: Wed, 12 Jun 2019 09:47:13 +0200 Subject: [PATCH] fix autocompletion --- .../ui-components/src/Autocomplete.js | 29 ++++--- .../ui-components/src/GroupAutocomplete.js | 37 ++++++++ .../ui-components/src/UserAutocomplete.js | 37 ++++++++ .../src/UserGroupAutocomplete.js | 57 ++++++++++++ scm-ui/public/locales/de/commons.json | 9 ++ scm-ui/public/locales/de/repos.json | 7 -- scm-ui/public/locales/en/commons.json | 9 ++ scm-ui/public/locales/en/repos.json | 7 -- .../containers/CreatePermissionForm.js | 87 ++++++------------- .../permissions/containers/Permissions.js | 86 +++++++++--------- 10 files changed, 235 insertions(+), 130 deletions(-) create mode 100644 scm-ui-components/packages/ui-components/src/GroupAutocomplete.js create mode 100644 scm-ui-components/packages/ui-components/src/UserAutocomplete.js create mode 100644 scm-ui-components/packages/ui-components/src/UserGroupAutocomplete.js diff --git a/scm-ui-components/packages/ui-components/src/Autocomplete.js b/scm-ui-components/packages/ui-components/src/Autocomplete.js index adf86e37b7..22107e75b6 100644 --- a/scm-ui-components/packages/ui-components/src/Autocomplete.js +++ b/scm-ui-components/packages/ui-components/src/Autocomplete.js @@ -4,7 +4,6 @@ import { AsyncCreatable, Async } from "react-select"; import type { AutocompleteObject, SelectValue } from "@scm-manager/ui-types"; import LabelWithHelpIcon from "./forms/LabelWithHelpIcon"; - type Props = { loadSuggestions: string => Promise, valueSelected: SelectValue => void, @@ -17,12 +16,9 @@ type Props = { creatable?: boolean }; - type State = {}; class Autocomplete extends React.Component { - - static defaultProps = { placeholder: "Type here", loadingMessage: "Loading...", @@ -34,7 +30,11 @@ class Autocomplete extends React.Component { }; // We overwrite this to avoid running into a bug (https://github.com/JedWatson/react-select/issues/2944) - isValidNewOption = (inputValue: string, selectValue: SelectValue, selectOptions: SelectValue[]) => { + isValidNewOption = ( + inputValue: string, + selectValue: SelectValue, + selectOptions: SelectValue[] + ) => { const isNotDuplicated = !selectOptions .map(option => option.label) .includes(inputValue); @@ -43,12 +43,21 @@ class Autocomplete extends React.Component { }; render() { - const { label, helpText, value, placeholder, loadingMessage, noOptionsMessage, loadSuggestions, creatable } = this.props; + const { + label, + helpText, + value, + placeholder, + loadingMessage, + noOptionsMessage, + loadSuggestions, + creatable + } = this.props; return (
- {creatable? + {creatable ? ( { }); }} /> - : + ) : ( { loadingMessage={() => loadingMessage} noOptionsMessage={() => noOptionsMessage} /> - - } + )}
); } } - export default Autocomplete; diff --git a/scm-ui-components/packages/ui-components/src/GroupAutocomplete.js b/scm-ui-components/packages/ui-components/src/GroupAutocomplete.js new file mode 100644 index 0000000000..2a9feeec14 --- /dev/null +++ b/scm-ui-components/packages/ui-components/src/GroupAutocomplete.js @@ -0,0 +1,37 @@ +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import type { SelectValue } from "@scm-manager/ui-types"; +import UserGroupAutocomplete from "./UserGroupAutocomplete"; + +type Props = { + groupAutocompleteLink: string, + valueSelected: SelectValue => void, + value?: SelectValue, + + // Context props + t: string => string +}; + +class GroupAutocomplete extends React.Component { + selectName = (selection: SelectValue) => { + this.props.valueSelected(selection); + }; + + render() { + const { groupAutocompleteLink, t, value } = this.props; + return ( + + ); + } +} + +export default translate("commons")(GroupAutocomplete); diff --git a/scm-ui-components/packages/ui-components/src/UserAutocomplete.js b/scm-ui-components/packages/ui-components/src/UserAutocomplete.js new file mode 100644 index 0000000000..3f9873608c --- /dev/null +++ b/scm-ui-components/packages/ui-components/src/UserAutocomplete.js @@ -0,0 +1,37 @@ +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import type { SelectValue } from "@scm-manager/ui-types"; +import UserGroupAutocomplete from "./UserGroupAutocomplete"; + +type Props = { + userAutocompleteLink: string, + valueSelected: SelectValue => void, + value?: SelectValue, + + // Context props + t: string => string +}; + +class UserAutocomplete extends React.Component { + selectName = (selection: SelectValue) => { + this.props.valueSelected(selection); + }; + + render() { + const { userAutocompleteLink, t, value } = this.props; + return ( + + ); + } +} + +export default translate("commons")(UserAutocomplete); diff --git a/scm-ui-components/packages/ui-components/src/UserGroupAutocomplete.js b/scm-ui-components/packages/ui-components/src/UserGroupAutocomplete.js new file mode 100644 index 0000000000..a6469c831e --- /dev/null +++ b/scm-ui-components/packages/ui-components/src/UserGroupAutocomplete.js @@ -0,0 +1,57 @@ +// @flow +import React from "react"; +import type { SelectValue } from "@scm-manager/ui-types"; +import Autocomplete from "./Autocomplete"; + +type Props = { + autocompleteLink: string, + label: string, + noOptionsMessage: string, + loadingMessage: string, + placeholder: string, + valueSelected: SelectValue => void, + value?: SelectValue +}; + +class UserGroupAutocomplete extends React.Component { + loadSuggestions = (inputValue: string) => { + const url = this.props.autocompleteLink; + const link = url + "?q="; + return fetch(link + inputValue) + .then(response => response.json()) + .then(json => { + return json.map(element => { + const label = element.displayName + ? `${element.displayName} (${element.id})` + : element.id; + return { + value: element, + label + }; + }); + }); + }; + + selectName = (selection: SelectValue) => { + this.props.valueSelected(selection); + }; + + render() { + const { autocompleteLink, label, noOptionsMessage, loadingMessage, placeholder, value } = this.props; + return ( + + ); // {...this.props} + } +} + +export default UserGroupAutocomplete; diff --git a/scm-ui/public/locales/de/commons.json b/scm-ui/public/locales/de/commons.json index b9cc93b1ed..7c0e326507 100644 --- a/scm-ui/public/locales/de/commons.json +++ b/scm-ui/public/locales/de/commons.json @@ -40,6 +40,15 @@ "config": "Einstellungen" }, "filterEntries": "Einträge filtern", + "autocomplete": { + "group": "Gruppe", + "user": "Benutzer", + "noGroupOptions": "Kein Gruppenname als Vorschlag verfügbar", + "groupPlaceholder": "Gruppe eingeben", + "noUserOptions": "Kein Benutzername als Vorschlag verfügbar", + "userPlaceholder": "Benutzer eingeben", + "loading": "suche..." + }, "paginator": { "next": "Weiter", "previous": "Zurück" diff --git a/scm-ui/public/locales/de/repos.json b/scm-ui/public/locales/de/repos.json index 4ba7a725e6..cf4f066120 100644 --- a/scm-ui/public/locales/de/repos.json +++ b/scm-ui/public/locales/de/repos.json @@ -150,13 +150,6 @@ "roleHelpText": "READ = read; WRITE = read und write; OWNER = read, write und auch die Möglichkeit Einstellungen und Berechtigungen zu verwalten. Wenn hier nichts angezeigt wird, den Erweitert-Button benutzen, um Details zu sehen.", "permissionsHelpText": "Hier können individuelle Berechtigungen unabhängig von vordefinierten Rollen vergeben werden." }, - "autocomplete": { - "no-group-options": "Kein Gruppenname als Vorschlag verfügbar", - "group-placeholder": "Gruppe eingeben", - "no-user-options": "Kein Benutzername als Vorschlag verfügbar", - "user-placeholder": "Benutzer eingeben", - "loading": "suche..." - }, "advanced": { "dialog": { "title": "Erweiterte Berechtigungen", diff --git a/scm-ui/public/locales/en/commons.json b/scm-ui/public/locales/en/commons.json index b5af3e9ef9..d360b557f2 100644 --- a/scm-ui/public/locales/en/commons.json +++ b/scm-ui/public/locales/en/commons.json @@ -40,6 +40,15 @@ "config": "Configuration" }, "filterEntries": "filter entries", + "autocomplete": { + "group": "Group", + "user": "User", + "noGroupOptions": "No group suggestion available", + "groupPlaceholder": "Enter group", + "noUserOptions": "No user suggestion available", + "userPlaceholder": "Enter user", + "loading": "Loading..." + }, "paginator": { "next": "Next", "previous": "Previous" diff --git a/scm-ui/public/locales/en/repos.json b/scm-ui/public/locales/en/repos.json index 9a2e83f983..a312287a68 100644 --- a/scm-ui/public/locales/en/repos.json +++ b/scm-ui/public/locales/en/repos.json @@ -153,13 +153,6 @@ "roleHelpText": "READ = read; WRITE = read and write; OWNER = read, write and also the ability to manage the properties and permissions. If nothing is selected here, use the 'Advanced' Button to see detailed permissions.", "permissionsHelpText": "Use this to specify your own set of permissions regardless of predefined roles." }, - "autocomplete": { - "no-group-options": "No group suggestion available", - "group-placeholder": "Enter group", - "no-user-options": "No user suggestion available", - "user-placeholder": "Enter user", - "loading": "Loading..." - }, "advanced": { "dialog": { "title": "Advanced Permissions", diff --git a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js index 112ecd1c20..51b43fc2ff 100644 --- a/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js +++ b/scm-ui/src/repos/permissions/containers/CreatePermissionForm.js @@ -9,11 +9,12 @@ import type { } from "@scm-manager/ui-types"; import { Subtitle, - Autocomplete, SubmitButton, Button, LabelWithHelpIcon, - Radio + Radio, + GroupAutocomplete, + UserAutocomplete } from "@scm-manager/ui-components"; import * as validator from "../components/permissionValidation"; import RoleSelector from "../components/RoleSelector"; @@ -26,8 +27,8 @@ type Props = { createPermission: (permission: PermissionCreateEntry) => void, loading: boolean, currentPermissions: PermissionCollection, - groupAutoCompleteLink: string, - userAutoCompleteLink: string, + groupAutocompleteLink: string, + userAutocompleteLink: string, // Context props t: string => string @@ -68,65 +69,27 @@ class CreatePermissionForm extends React.Component { }); }; - loadUserAutocompletion = (inputValue: string) => { - return this.loadAutocompletion(this.props.userAutoCompleteLink, inputValue); - }; - - loadGroupAutocompletion = (inputValue: string) => { - return this.loadAutocompletion( - this.props.groupAutoCompleteLink, - inputValue - ); - }; - - loadAutocompletion(url: string, inputValue: string) { - const link = url + "?q="; - return fetch(link + inputValue) - .then(response => response.json()) - .then(json => { - return json.map(element => { - const label = element.displayName - ? `${element.displayName} (${element.id})` - : element.id; - return { - value: element, - label - }; - }); - }); - } - renderAutocompletionField = () => { - const { t } = this.props; - if (this.state.groupPermission) { + const group = this.state.groupPermission; + if (group) { return ( - ); } return ( - ); }; - groupOrUserSelected = (value: SelectValue) => { + selectName = (value: SelectValue) => { this.setState({ value, name: value.value.id, @@ -150,15 +113,17 @@ class CreatePermissionForm extends React.Component { ) : null; return ( -
+ <>
- + {advancedDialog}
@@ -201,7 +166,7 @@ class CreatePermissionForm extends React.Component { />
@@ -217,16 +182,14 @@ class CreatePermissionForm extends React.Component { - + ); } - handleDetailedPermissionsPressed = () => { - this.setState({ showAdvancedDialog: true }); - }; - - closeAdvancedPermissionsDialog = () => { - this.setState({ showAdvancedDialog: false }); + toggleAdvancedPermissionsDialog = () => { + this.setState(prevState => ({ + showAdvancedDialog: !prevState.showAdvancedDialog + })); }; submitAdvancedPermissionsDialog = (newVerbs: string[]) => { diff --git a/scm-ui/src/repos/permissions/containers/Permissions.js b/scm-ui/src/repos/permissions/containers/Permissions.js index 39bd9e37c1..7d44328305 100644 --- a/scm-ui/src/repos/permissions/containers/Permissions.js +++ b/scm-ui/src/repos/permissions/containers/Permissions.js @@ -60,8 +60,8 @@ type Props = { repositoryRolesLink: string, repositoryVerbsLink: string, permissionsLink: string, - groupAutoCompleteLink: string, - userAutoCompleteLink: string, + groupAutocompleteLink: string, + userAutocompleteLink: string, //dispatch functions fetchAvailablePermissionsIfNeeded: ( @@ -129,8 +129,8 @@ class Permissions extends React.Component { repoName, loadingCreatePermission, hasPermissionToCreate, - userAutoCompleteLink, - groupAutoCompleteLink + userAutocompleteLink, + groupAutocompleteLink } = this.props; if (error) { return ( @@ -153,8 +153,8 @@ class Permissions extends React.Component { createPermission={permission => this.createPermission(permission)} loading={loadingCreatePermission} currentPermissions={permissions} - userAutoCompleteLink={userAutoCompleteLink} - groupAutoCompleteLink={groupAutoCompleteLink} + userAutocompleteLink={userAutocompleteLink} + groupAutocompleteLink={groupAutocompleteLink} /> ) : null; @@ -163,41 +163,41 @@ class Permissions extends React.Component { - - - - - + + + + + - {permissions.map(permission => { - return ( - - ); - })} + {permissions.map(permission => { + return ( + + ); + })}
- - - - - - -
+ + + + + + +
{createPermissionForm} @@ -228,8 +228,8 @@ const mapStateToProps = (state, ownProps) => { const repositoryRolesLink = getRepositoryRolesLink(state); const repositoryVerbsLink = getRepositoryVerbsLink(state); const permissionsLink = getPermissionsLink(state, namespace, repoName); - const groupAutoCompleteLink = getGroupAutoCompleteLink(state); - const userAutoCompleteLink = getUserAutoCompleteLink(state); + const groupAutocompleteLink = getGroupAutoCompleteLink(state); + const userAutocompleteLink = getUserAutoCompleteLink(state); const availablePermissions = getAvailablePermissions(state); const availableRepositoryRoles = getAvailableRepositoryRoles(state); const availableVerbs = getAvailableRepositoryVerbs(state); @@ -248,8 +248,8 @@ const mapStateToProps = (state, ownProps) => { hasPermissionToCreate, loadingCreatePermission, permissionsLink, - groupAutoCompleteLink, - userAutoCompleteLink + groupAutocompleteLink, + userAutocompleteLink }; };