| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- /*
- Copyright (C) 2017 Cloudbase Solutions SRL
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- import React from 'react'
- import { observer } from 'mobx-react'
- import styled from 'styled-components'
- import type { User } from '@src/@types/User'
- import type { Project } from '@src/@types/Project'
- import type { Field as FieldType } from '@src/@types/Field'
- import Button from '@src/components/ui/Button'
- import Modal from '@src/components/ui/Modal'
- import FieldInput from '@src/components/ui/FieldInput'
- import LabelDictionary from '@src/utils/LabelDictionary'
- import KeyboardManager from '@src/utils/KeyboardManager'
- import { ThemeProps } from '@src/components/Theme'
- import userImage from './images/user.svg'
- const Wrapper = styled.div<any>`
- padding: 48px 0 32px 0;
- display: flex;
- flex-direction: column;
- min-height: 0;
- `
- const Image = styled.div<any>`
- width: 96px;
- height: 96px;
- background: url('${userImage}') center no-repeat;
- margin: 0 auto;
- `
- const Form = styled.div<any>`
- display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
- margin-top: 64px;
- overflow: auto;
- padding: 0 32px;
- > div {
- margin-top: 16px;
- }
- `
- const Buttons = styled.div<any>`
- margin-top: 32px;
- display: flex;
- justify-content: space-between;
- padding: 0 32px;
- `
- type Props = {
- user?: User,
- isLoggedUser?: boolean,
- loading: boolean,
- isNewUser?: boolean,
- projects: Project[],
- editPassword?: boolean,
- onRequestClose: () => void,
- onUpdateClick: (user: User) => void,
- }
- type State = {
- name: string,
- email: string,
- enabled?: boolean,
- projectId?: string,
- highlightFieldNames: string[],
- password: string,
- confirmPassword: string,
- description?: string,
- }
- const testName = 'userModal'
- @observer
- class UserModal extends React.Component<Props, State> {
- UNSAFE_componentWillMount() {
- this.setState({
- name: this.props.user ? this.props.user.name : '',
- email: this.props.user ? this.props.user.email : '',
- description: this.props.user ? this.props.user.description : '',
- projectId: this.props.user ? this.props.user.project_id : '',
- enabled: this.props.user ? this.props.user.enabled : true,
- highlightFieldNames: [],
- password: '',
- confirmPassword: '',
- })
- }
- componentDidMount() {
- KeyboardManager.onEnter('editUserModal', () => {
- this.handleUpdateClick()
- }, 2)
- }
- componentWillUnmount() {
- KeyboardManager.removeKeyDown('editUserModal')
- }
- handleUpdateClick() {
- if (
- (this.props.isNewUser && this.highlightAllFields())
- || (!this.props.isNewUser && !this.props.editPassword && this.highlightDetailsFields())
- || (!this.props.isNewUser && this.props.editPassword && this.highlightPasswordFields())
- ) {
- return
- }
- this.props.onUpdateClick({
- id: '',
- project: { id: '', name: '' },
- project_id: this.state.projectId,
- name: this.state.name,
- email: this.state.email,
- description: this.state.description,
- password: this.state.password,
- enabled: this.state.enabled,
- })
- }
- highlightAllFields() {
- const highlightFieldNames = []
- if (!this.state.name) {
- highlightFieldNames.push('username')
- }
- if (!this.state.password) {
- highlightFieldNames.push('new_password')
- }
- if (this.state.password && this.state.password !== this.state.confirmPassword) {
- highlightFieldNames.push('confirm_password')
- }
- if (highlightFieldNames.length > 0) {
- this.setState({ highlightFieldNames })
- return true
- }
- this.setState({ highlightFieldNames: [] })
- return false
- }
- highlightDetailsFields(): boolean {
- if (!this.state.name) {
- this.setState({ highlightFieldNames: ['username'] })
- return true
- }
- this.setState({ highlightFieldNames: [] })
- return false
- }
- highlightPasswordFields(): boolean {
- if (!this.state.password) {
- this.setState({ highlightFieldNames: ['new_password'] })
- return true
- }
- if (this.state.password !== this.state.confirmPassword) {
- this.setState({ highlightFieldNames: ['confirm_password'] })
- return true
- }
- this.setState({ highlightFieldNames: [] })
- return false
- }
- renderField(field: FieldType, value: any, onChange: (value: any) => void) {
- const disabled = this.props.loading || (this.props.isLoggedUser && field.name === 'enabled')
- return (
- <FieldInput
- layout="modal"
- data-test-id={`${testName}-field-${field.name}`}
- key={field.name}
- name={field.name}
- label={LabelDictionary.get(field.name)}
- type={field.type || 'string'}
- value={value}
- onChange={onChange}
- width={ThemeProps.inputSizes.large.width}
- disabled={disabled}
- enum={field.enum}
- password={field.name === 'new_password' || field.name === 'confirm_password'}
- required={field.required}
- highlight={Boolean(this.state.highlightFieldNames.find(n => n === field.name))}
- noSelectionMessage="Choose a project"
- />
- )
- }
- renderForm() {
- let fields
- const passwordFields = [
- this.renderField(
- { name: 'new_password', required: true },
- this.state.password,
- password => { this.setState({ password }) },
- ),
- this.renderField(
- { name: 'confirm_password', required: true },
- this.state.confirmPassword,
- confirmPassword => { this.setState({ confirmPassword }) },
- ),
- ]
- const detailsFields = [
- this.renderField(
- { name: 'username', required: true },
- this.state.name,
- name => { this.setState({ name }) },
- ),
- this.renderField(
- { name: 'description' },
- this.state.description,
- description => { this.setState({ description }) },
- ),
- this.renderField(
- { name: 'Email' },
- this.state.email,
- email => { this.setState({ email }) },
- ),
- this.renderField(
- {
- name: 'Primary Project',
- enum: [({ name: 'Choose a project', id: null } as any)].concat(this.props.projects.concat([])),
- },
- this.state.projectId,
- projectId => { this.setState({ projectId }) },
- ),
- ]
- const enabledField = this.renderField(
- { name: 'enabled', type: 'boolean' },
- this.state.enabled,
- enabled => { this.setState({ enabled }) },
- )
- if (this.props.isNewUser) {
- fields = detailsFields.concat(passwordFields).concat(enabledField)
- } else if (this.props.editPassword) {
- fields = passwordFields
- } else {
- fields = detailsFields.concat(enabledField)
- }
- return (
- <Form>
- {fields}
- </Form>
- )
- }
- render() {
- const label = this.props.isNewUser ? 'New User' : this.props.editPassword ? 'Change Password' : 'Update User'
- return (
- <Modal
- isOpen
- title={label}
- onRequestClose={this.props.onRequestClose}
- >
- <Wrapper>
- <Image />
- {this.renderForm()}
- <Buttons>
- <Button
- secondary
- large
- onClick={this.props.onRequestClose}
- >Cancel
- </Button>
- <Button
- data-test-id={`${testName}-updateButton`}
- large
- disabled={this.props.loading}
- onClick={() => { this.handleUpdateClick() }}
- >{label}
- </Button>
- </Buttons>
- </Wrapper>
- </Modal>
- )
- }
- }
- export default UserModal
|