diff --git a/gradle/changelog/redirect_after_update.yaml b/gradle/changelog/redirect_after_update.yaml new file mode 100644 index 0000000000..e5d9a0bf79 --- /dev/null +++ b/gradle/changelog/redirect_after_update.yaml @@ -0,0 +1,2 @@ +- type: fixed + description: Do not redirect after simple data updates ([#1965](https://github.com/scm-manager/scm-manager/pull/1965)) diff --git a/scm-ui/ui-webapp/public/locales/de/commons.json b/scm-ui/ui-webapp/public/locales/de/commons.json index c1bf59505d..7cdda9eb94 100644 --- a/scm-ui/ui-webapp/public/locales/de/commons.json +++ b/scm-ui/ui-webapp/public/locales/de/commons.json @@ -162,7 +162,8 @@ "bellTitle": "Benachrichtigungen", "empty": "Keine Benachrichtigungen", "dismiss": "Löschen", - "dismissAll": "Alle löschen" + "dismissAll": "Alle löschen", + "updateSuccessful": "Die Änderungen wurden gespeichert." }, "alerts": { "shieldTitle": "Alerts" diff --git a/scm-ui/ui-webapp/public/locales/de/groups.json b/scm-ui/ui-webapp/public/locales/de/groups.json index 05d5321e15..3e101ddf8c 100644 --- a/scm-ui/ui-webapp/public/locales/de/groups.json +++ b/scm-ui/ui-webapp/public/locales/de/groups.json @@ -41,9 +41,6 @@ "add-member-button": { "label": "Mitglied hinzufügen" }, - "add-member-textfield": { - "error": "Ungültiger Name für Mitglied" - }, "add-member-autocomplete": { "placeholder": "Mitglied hinzufügen", "loading": "Suche ...", diff --git a/scm-ui/ui-webapp/public/locales/en/commons.json b/scm-ui/ui-webapp/public/locales/en/commons.json index 094227b0c5..b9913f14c2 100644 --- a/scm-ui/ui-webapp/public/locales/en/commons.json +++ b/scm-ui/ui-webapp/public/locales/en/commons.json @@ -163,7 +163,8 @@ "bellTitle": "Notifications", "empty": "No notifications", "dismiss": "Dismiss", - "dismissAll": "Dismiss all" + "dismissAll": "Dismiss all", + "updateSuccessful": "The update was successful." }, "alerts": { "shieldTitle": "Alerts" diff --git a/scm-ui/ui-webapp/public/locales/en/groups.json b/scm-ui/ui-webapp/public/locales/en/groups.json index da4b91c222..3e8988d6a9 100644 --- a/scm-ui/ui-webapp/public/locales/en/groups.json +++ b/scm-ui/ui-webapp/public/locales/en/groups.json @@ -41,9 +41,6 @@ "add-member-button": { "label": "Add Member" }, - "add-member-textfield": { - "error": "Invalid member name" - }, "add-member-autocomplete": { "placeholder": "Add Member", "loading": "Loading ...", diff --git a/scm-ui/ui-webapp/public/locales/es/groups.json b/scm-ui/ui-webapp/public/locales/es/groups.json index ecb01ffd89..3f39696665 100644 --- a/scm-ui/ui-webapp/public/locales/es/groups.json +++ b/scm-ui/ui-webapp/public/locales/es/groups.json @@ -38,9 +38,6 @@ "add-member-button": { "label": "Añadir miembro" }, - "add-member-textfield": { - "error": "El nombre del miembro es incorrecto" - }, "add-member-autocomplete": { "placeholder": "Añadir miembro", "loading": "Cargando...", diff --git a/scm-ui/ui-webapp/src/components/UpdateNotification.tsx b/scm-ui/ui-webapp/src/components/UpdateNotification.tsx new file mode 100644 index 0000000000..3805535c0c --- /dev/null +++ b/scm-ui/ui-webapp/src/components/UpdateNotification.tsx @@ -0,0 +1,51 @@ +/* + * 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 React, { FC, useEffect, useState } from "react"; +import { Notification } from "@scm-manager/ui-components"; +import { useTranslation } from "react-i18next"; + +type Props = { + isUpdated: boolean; +}; + +const UpdateNotification: FC = ({ isUpdated }) => { + const [t] = useTranslation("commons"); + const [showSuccess, setShowSuccess] = useState(false); + useEffect(() => { + setShowSuccess(isUpdated); + }, [isUpdated]); + + if (showSuccess) { + return ( + setShowSuccess(false)}> + {t("notifications.updateSuccessful")} + + ); + } + + return null; +}; + +export default UpdateNotification; diff --git a/scm-ui/ui-webapp/src/groups/components/GroupForm.tsx b/scm-ui/ui-webapp/src/groups/components/GroupForm.tsx index 73ad1cfee4..7c58a0d872 100644 --- a/scm-ui/ui-webapp/src/groups/components/GroupForm.tsx +++ b/scm-ui/ui-webapp/src/groups/components/GroupForm.tsx @@ -21,9 +21,9 @@ * 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 { Group, SelectValue } from "@scm-manager/ui-types"; +import React, { FC, FormEvent, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Group, Member, SelectValue } from "@scm-manager/ui-types"; import { AutocompleteAddEntryToTableField, Checkbox, @@ -36,83 +36,61 @@ import { } from "@scm-manager/ui-components"; import * as validator from "./groupValidation"; -type Props = WithTranslation & { +type Props = { submitForm: (p: Group) => void; loading?: boolean; group?: Group; loadUserSuggestions: (p: string) => Promise; }; -type State = { - group: Group; - nameValidationError: boolean; -}; +const GroupForm: FC = ({ submitForm, loading, group, loadUserSuggestions }) => { + const [t] = useTranslation("groups"); + const [groupState, setGroupState] = useState({ + name: "", + description: "", + _embedded: { + members: [] as Member[] + }, + _links: {}, + members: [] as string[], + type: "", + external: false + }); + const [nameValidationError, setNameValidationError] = useState(false); -class GroupForm extends React.Component { - constructor(props) { - super(props); - this.state = { - group: { - name: "", - description: "", - _embedded: { - members: [] - }, - _links: {}, - members: [], - type: "", - external: false - }, - nameValidationError: false - }; - } - - componentDidMount() { - const { group } = this.props; + useEffect(() => { if (group) { - this.setState({ - ...this.state, - group: { - ...group - } - }); + setGroupState(group); } - } + }, [group]); - isFalsy(value) { - return !value; - } + const isValid = !(nameValidationError || !groupState.name); - isValid = () => { - const group = this.state.group; - return !(this.state.nameValidationError || this.isFalsy(group.name)); - }; - - submit = (event: Event) => { + const submit = (event: FormEvent) => { event.preventDefault(); - if (this.isValid()) { - const { group } = this.state; - if (group.external) { - group.members = []; + if (isValid) { + if (groupState.external) { + groupState.members = []; } - this.props.submitForm(group); + submitForm(groupState); } }; - renderMemberfields = (group: Group) => { - if (group.external) { + const renderMemberfields = () => { + if (groupState.external) { return null; } - const { loadUserSuggestions, t } = this.props; return ( <> - + setGroupState({ ...groupState, members: memberNames })} + /> { ); }; - renderExternalField = (group: Group) => { - const { t } = this.props; - if (this.isExistingGroup()) { + const renderExternalField = () => { + if (!groupState) { return null; } return ( setGroupState({ ...groupState, external })} /> ); }; - isExistingGroup = () => !!this.props.group; - - render() { - const { loading, t } = this.props; - const { group } = this.state; - let nameField = null; - let subtitle = null; - if (!this.isExistingGroup()) { - // create new group - nameField = ( - - ); - } else if (group.external) { - subtitle = ; - } else { - subtitle = ; - } - - return ( - <> - {subtitle} -
- {nameField} -