mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
use reflow to migrate from flow to typescript
This commit is contained in:
@@ -1,26 +1,25 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import React from 'react';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import {
|
||||
SubmitButton,
|
||||
Notification,
|
||||
ErrorNotification,
|
||||
PasswordConfirmation
|
||||
} from "@scm-manager/ui-components";
|
||||
import { translate } from "react-i18next";
|
||||
import { setPassword } from "./setPassword";
|
||||
PasswordConfirmation,
|
||||
} from '@scm-manager/ui-components';
|
||||
import { translate } from 'react-i18next';
|
||||
import { setPassword } from './setPassword';
|
||||
|
||||
type Props = {
|
||||
user: User,
|
||||
t: string => string
|
||||
user: User;
|
||||
t: (p: string) => string;
|
||||
};
|
||||
|
||||
type State = {
|
||||
password: string,
|
||||
loading: boolean,
|
||||
error?: Error,
|
||||
passwordChanged: boolean,
|
||||
passwordValid: boolean
|
||||
password: string;
|
||||
loading: boolean;
|
||||
error?: Error;
|
||||
passwordChanged: boolean;
|
||||
passwordValid: boolean;
|
||||
};
|
||||
|
||||
class SetUserPassword extends React.Component<Props, State> {
|
||||
@@ -28,20 +27,20 @@ class SetUserPassword extends React.Component<Props, State> {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
password: "",
|
||||
password: '',
|
||||
loading: false,
|
||||
passwordConfirmationError: false,
|
||||
validatePasswordError: false,
|
||||
validatePassword: "",
|
||||
validatePassword: '',
|
||||
passwordChanged: false,
|
||||
passwordValid: false
|
||||
passwordValid: false,
|
||||
};
|
||||
}
|
||||
|
||||
setLoadingState = () => {
|
||||
this.setState({
|
||||
...this.state,
|
||||
loading: true
|
||||
loading: true,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -49,7 +48,7 @@ class SetUserPassword extends React.Component<Props, State> {
|
||||
this.setState({
|
||||
...this.state,
|
||||
error: error,
|
||||
loading: false
|
||||
loading: false,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -58,7 +57,7 @@ class SetUserPassword extends React.Component<Props, State> {
|
||||
...this.state,
|
||||
loading: false,
|
||||
passwordChanged: true,
|
||||
password: ""
|
||||
password: '',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -89,8 +88,8 @@ class SetUserPassword extends React.Component<Props, State> {
|
||||
if (passwordChanged) {
|
||||
message = (
|
||||
<Notification
|
||||
type={"success"}
|
||||
children={t("singleUserPassword.setPasswordSuccessful")}
|
||||
type={'success'}
|
||||
children={t('singleUserPassword.setPasswordSuccessful')}
|
||||
onClose={() => this.onClose()}
|
||||
/>
|
||||
);
|
||||
@@ -103,14 +102,14 @@ class SetUserPassword extends React.Component<Props, State> {
|
||||
{message}
|
||||
<PasswordConfirmation
|
||||
passwordChanged={this.passwordChanged}
|
||||
key={this.state.passwordChanged ? "changed" : "unchanged"}
|
||||
key={this.state.passwordChanged ? 'changed' : 'unchanged'}
|
||||
/>
|
||||
<div className="columns">
|
||||
<div className="column">
|
||||
<SubmitButton
|
||||
disabled={!this.state.passwordValid}
|
||||
loading={loading}
|
||||
label={t("singleUserPassword.button")}
|
||||
label={t('singleUserPassword.button')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,16 +121,16 @@ class SetUserPassword extends React.Component<Props, State> {
|
||||
this.setState({
|
||||
...this.state,
|
||||
password,
|
||||
passwordValid: !!password && passwordValid
|
||||
passwordValid: !!password && passwordValid,
|
||||
});
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
this.setState({
|
||||
...this.state,
|
||||
passwordChanged: false
|
||||
passwordChanged: false,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default translate("users")(SetUserPassword);
|
||||
export default translate('users')(SetUserPassword);
|
||||
@@ -1,30 +1,29 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import React from 'react';
|
||||
import { translate } from 'react-i18next';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import {
|
||||
Subtitle,
|
||||
Checkbox,
|
||||
InputField,
|
||||
PasswordConfirmation,
|
||||
SubmitButton,
|
||||
validation as validator
|
||||
} from "@scm-manager/ui-components";
|
||||
import * as userValidator from "./userValidation";
|
||||
validation as validator,
|
||||
} from '@scm-manager/ui-components';
|
||||
import * as userValidator from './userValidation';
|
||||
|
||||
type Props = {
|
||||
submitForm: User => void,
|
||||
user?: User,
|
||||
loading?: boolean,
|
||||
t: string => string
|
||||
submitForm: (p: User) => void;
|
||||
user?: User;
|
||||
loading?: boolean;
|
||||
t: (p: string) => string;
|
||||
};
|
||||
|
||||
type State = {
|
||||
user: User,
|
||||
mailValidationError: boolean,
|
||||
nameValidationError: boolean,
|
||||
displayNameValidationError: boolean,
|
||||
passwordValid: boolean
|
||||
user: User;
|
||||
mailValidationError: boolean;
|
||||
nameValidationError: boolean;
|
||||
displayNameValidationError: boolean;
|
||||
passwordValid: boolean;
|
||||
};
|
||||
|
||||
class UserForm extends React.Component<Props, State> {
|
||||
@@ -33,24 +32,28 @@ class UserForm extends React.Component<Props, State> {
|
||||
|
||||
this.state = {
|
||||
user: {
|
||||
name: "",
|
||||
displayName: "",
|
||||
mail: "",
|
||||
password: "",
|
||||
name: '',
|
||||
displayName: '',
|
||||
mail: '',
|
||||
password: '',
|
||||
active: true,
|
||||
_links: {}
|
||||
_links: {},
|
||||
},
|
||||
mailValidationError: false,
|
||||
displayNameValidationError: false,
|
||||
nameValidationError: false,
|
||||
passwordValid: false
|
||||
passwordValid: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { user } = this.props;
|
||||
if (user) {
|
||||
this.setState({ user: { ...user } });
|
||||
this.setState({
|
||||
user: {
|
||||
...user,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,12 +121,12 @@ class UserForm extends React.Component<Props, State> {
|
||||
nameField = (
|
||||
<div className="column is-half">
|
||||
<InputField
|
||||
label={t("user.name")}
|
||||
label={t('user.name')}
|
||||
onChange={this.handleUsernameChange}
|
||||
value={user ? user.name : ""}
|
||||
value={user ? user.name : ''}
|
||||
validationError={this.state.nameValidationError}
|
||||
errorMessage={t("validation.name-invalid")}
|
||||
helpText={t("help.usernameHelpText")}
|
||||
errorMessage={t('validation.name-invalid')}
|
||||
helpText={t('help.usernameHelpText')}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -133,7 +136,7 @@ class UserForm extends React.Component<Props, State> {
|
||||
);
|
||||
} else {
|
||||
// edit existing user
|
||||
subtitle = <Subtitle subtitle={t("userForm.subtitle")} />;
|
||||
subtitle = <Subtitle subtitle={t('userForm.subtitle')} />;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
@@ -143,22 +146,22 @@ class UserForm extends React.Component<Props, State> {
|
||||
{nameField}
|
||||
<div className="column is-half">
|
||||
<InputField
|
||||
label={t("user.displayName")}
|
||||
label={t('user.displayName')}
|
||||
onChange={this.handleDisplayNameChange}
|
||||
value={user ? user.displayName : ""}
|
||||
value={user ? user.displayName : ''}
|
||||
validationError={this.state.displayNameValidationError}
|
||||
errorMessage={t("validation.displayname-invalid")}
|
||||
helpText={t("help.displayNameHelpText")}
|
||||
errorMessage={t('validation.displayname-invalid')}
|
||||
helpText={t('help.displayNameHelpText')}
|
||||
/>
|
||||
</div>
|
||||
<div className="column is-half">
|
||||
<InputField
|
||||
label={t("user.mail")}
|
||||
label={t('user.mail')}
|
||||
onChange={this.handleEmailChange}
|
||||
value={user ? user.mail : ""}
|
||||
value={user ? user.mail : ''}
|
||||
validationError={this.state.mailValidationError}
|
||||
errorMessage={t("validation.mail-invalid")}
|
||||
helpText={t("help.mailHelpText")}
|
||||
errorMessage={t('validation.mail-invalid')}
|
||||
helpText={t('help.mailHelpText')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -166,10 +169,10 @@ class UserForm extends React.Component<Props, State> {
|
||||
<div className="columns">
|
||||
<div className="column">
|
||||
<Checkbox
|
||||
label={t("user.active")}
|
||||
label={t('user.active')}
|
||||
onChange={this.handleActiveChange}
|
||||
checked={user ? user.active : false}
|
||||
helpText={t("help.activeHelpText")}
|
||||
helpText={t('help.activeHelpText')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -178,7 +181,7 @@ class UserForm extends React.Component<Props, State> {
|
||||
<SubmitButton
|
||||
disabled={!this.isValid()}
|
||||
loading={loading}
|
||||
label={t("userForm.button")}
|
||||
label={t('userForm.button')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -190,36 +193,53 @@ class UserForm extends React.Component<Props, State> {
|
||||
handleUsernameChange = (name: string) => {
|
||||
this.setState({
|
||||
nameValidationError: !validator.isNameValid(name),
|
||||
user: { ...this.state.user, name }
|
||||
user: {
|
||||
...this.state.user,
|
||||
name,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
handleDisplayNameChange = (displayName: string) => {
|
||||
this.setState({
|
||||
displayNameValidationError: !userValidator.isDisplayNameValid(
|
||||
displayName
|
||||
displayName,
|
||||
),
|
||||
user: { ...this.state.user, displayName }
|
||||
user: {
|
||||
...this.state.user,
|
||||
displayName,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
handleEmailChange = (mail: string) => {
|
||||
this.setState({
|
||||
mailValidationError: !validator.isMailValid(mail),
|
||||
user: { ...this.state.user, mail }
|
||||
user: {
|
||||
...this.state.user,
|
||||
mail,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
handlePasswordChange = (password: string, passwordValid: boolean) => {
|
||||
this.setState({
|
||||
user: { ...this.state.user, password },
|
||||
passwordValid: !this.isFalsy(password) && passwordValid
|
||||
user: {
|
||||
...this.state.user,
|
||||
password,
|
||||
},
|
||||
passwordValid: !this.isFalsy(password) && passwordValid,
|
||||
});
|
||||
};
|
||||
|
||||
handleActiveChange = (active: boolean) => {
|
||||
this.setState({ user: { ...this.state.user, active } });
|
||||
this.setState({
|
||||
user: {
|
||||
...this.state.user,
|
||||
active,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default translate("users")(UserForm);
|
||||
export default translate('users')(UserForm);
|
||||
@@ -1,28 +0,0 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { NavLink } from "@scm-manager/ui-components";
|
||||
import { translate } from "react-i18next";
|
||||
|
||||
type Props = {
|
||||
user: User,
|
||||
editUrl: String,
|
||||
t: string => string
|
||||
};
|
||||
|
||||
class EditUserNavLink extends React.Component<Props> {
|
||||
isEditable = () => {
|
||||
return this.props.user._links.update;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, editUrl } = this.props;
|
||||
|
||||
if (!this.isEditable()) {
|
||||
return null;
|
||||
}
|
||||
return <NavLink to={editUrl} label={t("singleUser.menu.generalNavLink")} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default translate("users")(EditUserNavLink);
|
||||
@@ -1,27 +0,0 @@
|
||||
import React from "react";
|
||||
import { shallow } from "enzyme";
|
||||
import "@scm-manager/ui-tests/enzyme";
|
||||
import "@scm-manager/ui-tests/i18n";
|
||||
import EditUserNavLink from "./EditUserNavLink";
|
||||
|
||||
it("should render nothing, if the edit link is missing", () => {
|
||||
const user = {
|
||||
_links: {}
|
||||
};
|
||||
|
||||
const navLink = shallow(<EditUserNavLink user={user} editUrl='/user/edit'/>);
|
||||
expect(navLink.text()).toBe("");
|
||||
});
|
||||
|
||||
it("should render the navLink", () => {
|
||||
const user = {
|
||||
_links: {
|
||||
update: {
|
||||
href: "/users"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = shallow(<EditUserNavLink user={user} editUrl='/user/edit'/>);
|
||||
expect(navLink.text()).not.toBe("");
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import '@scm-manager/ui-tests/enzyme';
|
||||
import '@scm-manager/ui-tests/i18n';
|
||||
import EditUserNavLink from './EditUserNavLink';
|
||||
|
||||
it('should render nothing, if the edit link is missing', () => {
|
||||
const user = {
|
||||
_links: {},
|
||||
};
|
||||
|
||||
const navLink = shallow(<EditUserNavLink user={user} editUrl="/user/edit" />);
|
||||
expect(navLink.text()).toBe('');
|
||||
});
|
||||
|
||||
it('should render the navLink', () => {
|
||||
const user = {
|
||||
_links: {
|
||||
update: {
|
||||
href: '/users',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const navLink = shallow(<EditUserNavLink user={user} editUrl="/user/edit" />);
|
||||
expect(navLink.text()).not.toBe('');
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { NavLink } from '@scm-manager/ui-components';
|
||||
import { translate } from 'react-i18next';
|
||||
|
||||
type Props = {
|
||||
user: User;
|
||||
editUrl: string;
|
||||
t: (p: string) => string;
|
||||
};
|
||||
|
||||
class EditUserNavLink extends React.Component<Props> {
|
||||
isEditable = () => {
|
||||
return this.props.user._links.update;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, editUrl } = this.props;
|
||||
|
||||
if (!this.isEditable()) {
|
||||
return null;
|
||||
}
|
||||
return <NavLink to={editUrl} label={t('singleUser.menu.generalNavLink')} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default translate('users')(EditUserNavLink);
|
||||
@@ -1,28 +0,0 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { NavLink } from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
t: string => string,
|
||||
user: User,
|
||||
passwordUrl: String
|
||||
};
|
||||
|
||||
class ChangePasswordNavLink extends React.Component<Props> {
|
||||
render() {
|
||||
const { t, passwordUrl } = this.props;
|
||||
|
||||
if (!this.hasPermissionToSetPassword()) {
|
||||
return null;
|
||||
}
|
||||
return <NavLink to={passwordUrl} label={t("singleUser.menu.setPasswordNavLink")} />;
|
||||
}
|
||||
|
||||
hasPermissionToSetPassword = () => {
|
||||
return this.props.user._links.password;
|
||||
};
|
||||
}
|
||||
|
||||
export default translate("users")(ChangePasswordNavLink);
|
||||
@@ -1,31 +0,0 @@
|
||||
import React from "react";
|
||||
import { shallow } from "enzyme";
|
||||
import "@scm-manager/ui-tests/enzyme";
|
||||
import "@scm-manager/ui-tests/i18n";
|
||||
import ChangePasswordNavLink from "./SetPasswordNavLink";
|
||||
|
||||
it("should render nothing, if the password link is missing", () => {
|
||||
const user = {
|
||||
_links: {}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<ChangePasswordNavLink user={user} passwordUrl="/user/password" />
|
||||
);
|
||||
expect(navLink.text()).toBe("");
|
||||
});
|
||||
|
||||
it("should render the navLink", () => {
|
||||
const user = {
|
||||
_links: {
|
||||
password: {
|
||||
href: "/password"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<ChangePasswordNavLink user={user} passwordUrl="/user/password" />
|
||||
);
|
||||
expect(navLink.text()).not.toBe("");
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import '@scm-manager/ui-tests/enzyme';
|
||||
import '@scm-manager/ui-tests/i18n';
|
||||
import ChangePasswordNavLink from './SetPasswordNavLink';
|
||||
|
||||
it('should render nothing, if the password link is missing', () => {
|
||||
const user = {
|
||||
_links: {},
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<ChangePasswordNavLink user={user} passwordUrl="/user/password" />,
|
||||
);
|
||||
expect(navLink.text()).toBe('');
|
||||
});
|
||||
|
||||
it('should render the navLink', () => {
|
||||
const user = {
|
||||
_links: {
|
||||
password: {
|
||||
href: '/password',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<ChangePasswordNavLink user={user} passwordUrl="/user/password" />,
|
||||
);
|
||||
expect(navLink.text()).not.toBe('');
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { translate } from 'react-i18next';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { NavLink } from '@scm-manager/ui-components';
|
||||
|
||||
type Props = {
|
||||
t: (p: string) => string;
|
||||
user: User;
|
||||
passwordUrl: string;
|
||||
};
|
||||
|
||||
class ChangePasswordNavLink extends React.Component<Props> {
|
||||
render() {
|
||||
const { t, passwordUrl } = this.props;
|
||||
|
||||
if (!this.hasPermissionToSetPassword()) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<NavLink
|
||||
to={passwordUrl}
|
||||
label={t('singleUser.menu.setPasswordNavLink')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
hasPermissionToSetPassword = () => {
|
||||
return this.props.user._links.password;
|
||||
};
|
||||
}
|
||||
|
||||
export default translate('users')(ChangePasswordNavLink);
|
||||
@@ -1,28 +0,0 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { NavLink } from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
t: string => string,
|
||||
user: User,
|
||||
permissionsUrl: String
|
||||
};
|
||||
|
||||
class ChangePermissionNavLink extends React.Component<Props> {
|
||||
render() {
|
||||
const { t, permissionsUrl } = this.props;
|
||||
|
||||
if (!this.hasPermissionToSetPermission()) {
|
||||
return null;
|
||||
}
|
||||
return <NavLink to={permissionsUrl} label={t("singleUser.menu.setPermissionsNavLink")} />;
|
||||
}
|
||||
|
||||
hasPermissionToSetPermission = () => {
|
||||
return this.props.user._links.permissions;
|
||||
};
|
||||
}
|
||||
|
||||
export default translate("users")(ChangePermissionNavLink);
|
||||
@@ -1,31 +0,0 @@
|
||||
import React from "react";
|
||||
import "@scm-manager/ui-tests/enzyme";
|
||||
import "@scm-manager/ui-tests/i18n";
|
||||
import SetPermissionsNavLink from "./SetPermissionsNavLink";
|
||||
import { shallow } from "enzyme";
|
||||
|
||||
it("should render nothing, if the permissions link is missing", () => {
|
||||
const user = {
|
||||
_links: {}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<SetPermissionsNavLink user={user} permissionsUrl="/user/permissions" />
|
||||
);
|
||||
expect(navLink.text()).toBe("");
|
||||
});
|
||||
|
||||
it("should render the navLink", () => {
|
||||
const user = {
|
||||
_links: {
|
||||
permissions: {
|
||||
href: "/permissions"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<SetPermissionsNavLink user={user} permissionsUrl="/user/permissions" />
|
||||
);
|
||||
expect(navLink.text()).not.toBe("");
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import '@scm-manager/ui-tests/enzyme';
|
||||
import '@scm-manager/ui-tests/i18n';
|
||||
import SetPermissionsNavLink from './SetPermissionsNavLink';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
it('should render nothing, if the permissions link is missing', () => {
|
||||
const user = {
|
||||
_links: {},
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<SetPermissionsNavLink user={user} permissionsUrl="/user/permissions" />,
|
||||
);
|
||||
expect(navLink.text()).toBe('');
|
||||
});
|
||||
|
||||
it('should render the navLink', () => {
|
||||
const user = {
|
||||
_links: {
|
||||
permissions: {
|
||||
href: '/permissions',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const navLink = shallow(
|
||||
<SetPermissionsNavLink user={user} permissionsUrl="/user/permissions" />,
|
||||
);
|
||||
expect(navLink.text()).not.toBe('');
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { translate } from 'react-i18next';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { NavLink } from '@scm-manager/ui-components';
|
||||
|
||||
type Props = {
|
||||
t: (p: string) => string;
|
||||
user: User;
|
||||
permissionsUrl: string;
|
||||
};
|
||||
|
||||
class ChangePermissionNavLink extends React.Component<Props> {
|
||||
render() {
|
||||
const { t, permissionsUrl } = this.props;
|
||||
|
||||
if (!this.hasPermissionToSetPermission()) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<NavLink
|
||||
to={permissionsUrl}
|
||||
label={t('singleUser.menu.setPermissionsNavLink')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
hasPermissionToSetPermission = () => {
|
||||
return this.props.user._links.permissions;
|
||||
};
|
||||
}
|
||||
|
||||
export default translate('users')(ChangePermissionNavLink);
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as EditUserNavLink } from "./EditUserNavLink";
|
||||
export { default as SetPasswordNavLink } from "./SetPasswordNavLink";
|
||||
export { default as SetPermissionsNavLink } from "./SetPermissionsNavLink";
|
||||
3
scm-ui/ui-webapp/src/users/components/navLinks/index.ts
Normal file
3
scm-ui/ui-webapp/src/users/components/navLinks/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as EditUserNavLink } from './EditUserNavLink';
|
||||
export { default as SetPasswordNavLink } from './SetPasswordNavLink';
|
||||
export { default as SetPermissionsNavLink } from './SetPermissionsNavLink';
|
||||
@@ -1,13 +0,0 @@
|
||||
//@flow
|
||||
import { apiClient } from "@scm-manager/ui-components";
|
||||
|
||||
export const CONTENT_TYPE_PASSWORD_OVERWRITE =
|
||||
"application/vnd.scmm-passwordOverwrite+json;v=2";
|
||||
|
||||
export function setPassword(url: string, password: string) {
|
||||
return apiClient
|
||||
.put(url, { newPassword: password }, CONTENT_TYPE_PASSWORD_OVERWRITE)
|
||||
.then(response => {
|
||||
return response;
|
||||
});
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
//@flow
|
||||
import fetchMock from "fetch-mock";
|
||||
import { CONTENT_TYPE_PASSWORD_OVERWRITE, setPassword } from "./setPassword";
|
||||
|
||||
describe("password change", () => {
|
||||
const SET_PASSWORD_URL = "/users/testuser/password";
|
||||
const newPassword = "testpw123";
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.reset();
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
it("should set password", done => {
|
||||
fetchMock.put("/api/v2" + SET_PASSWORD_URL, 204, {
|
||||
headers: {
|
||||
"content-type": CONTENT_TYPE_PASSWORD_OVERWRITE
|
||||
}
|
||||
});
|
||||
|
||||
setPassword(SET_PASSWORD_URL, newPassword).then(content => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
24
scm-ui/ui-webapp/src/users/components/setPassword.test.ts
Normal file
24
scm-ui/ui-webapp/src/users/components/setPassword.test.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { CONTENT_TYPE_PASSWORD_OVERWRITE, setPassword } from './setPassword';
|
||||
|
||||
describe('password change', () => {
|
||||
const SET_PASSWORD_URL = '/users/testuser/password';
|
||||
const newPassword = 'testpw123';
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.reset();
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
it('should set password', done => {
|
||||
fetchMock.put('/api/v2' + SET_PASSWORD_URL, 204, {
|
||||
headers: {
|
||||
'content-type': CONTENT_TYPE_PASSWORD_OVERWRITE,
|
||||
},
|
||||
});
|
||||
|
||||
setPassword(SET_PASSWORD_URL, newPassword).then(content => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
18
scm-ui/ui-webapp/src/users/components/setPassword.ts
Normal file
18
scm-ui/ui-webapp/src/users/components/setPassword.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { apiClient } from '@scm-manager/ui-components';
|
||||
|
||||
export const CONTENT_TYPE_PASSWORD_OVERWRITE =
|
||||
'application/vnd.scmm-passwordOverwrite+json;v=2';
|
||||
|
||||
export function setPassword(url: string, password: string) {
|
||||
return apiClient
|
||||
.put(
|
||||
url,
|
||||
{
|
||||
newPassword: password,
|
||||
},
|
||||
CONTENT_TYPE_PASSWORD_OVERWRITE,
|
||||
)
|
||||
.then(response => {
|
||||
return response;
|
||||
});
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { translate } from "react-i18next";
|
||||
import { Checkbox, MailLink, DateFromNow } from "@scm-manager/ui-components";
|
||||
import React from 'react';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Checkbox, MailLink, DateFromNow } from '@scm-manager/ui-components';
|
||||
|
||||
type Props = {
|
||||
user: User,
|
||||
t: string => string
|
||||
user: User;
|
||||
t: (p: string) => string;
|
||||
};
|
||||
|
||||
class Details extends React.Component<Props> {
|
||||
@@ -16,37 +15,37 @@ class Details extends React.Component<Props> {
|
||||
<table className="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{t("user.name")}</th>
|
||||
<th>{t('user.name')}</th>
|
||||
<td>{user.name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("user.displayName")}</th>
|
||||
<th>{t('user.displayName')}</th>
|
||||
<td>{user.displayName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("user.mail")}</th>
|
||||
<th>{t('user.mail')}</th>
|
||||
<td>
|
||||
<MailLink address={user.mail} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("user.active")}</th>
|
||||
<th>{t('user.active')}</th>
|
||||
<td>
|
||||
<Checkbox checked={user.active} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("user.type")}</th>
|
||||
<th>{t('user.type')}</th>
|
||||
<td>{user.type}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("user.creationDate")}</th>
|
||||
<th>{t('user.creationDate')}</th>
|
||||
<td>
|
||||
<DateFromNow date={user.creationDate} />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{t("user.lastModified")}</th>
|
||||
<th>{t('user.lastModified')}</th>
|
||||
<td>
|
||||
<DateFromNow date={user.lastModified} />
|
||||
</td>
|
||||
@@ -57,4 +56,4 @@ class Details extends React.Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
export default translate("users")(Details);
|
||||
export default translate('users')(Details);
|
||||
@@ -1,43 +0,0 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import { Icon } from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
user: User,
|
||||
|
||||
// context props
|
||||
t: string => string
|
||||
};
|
||||
|
||||
class UserRow extends React.Component<Props> {
|
||||
renderLink(to: string, label: string) {
|
||||
return <Link to={to}>{label}</Link>;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user, t } = this.props;
|
||||
const to = `/user/${user.name}`;
|
||||
const iconType = user.active ? (
|
||||
<Icon title={t("user.active")} name="user" />
|
||||
) : (
|
||||
<Icon title={t("user.inactive")} name="user-slash" />
|
||||
);
|
||||
|
||||
return (
|
||||
<tr className={user.active ? "border-is-green" : "border-is-yellow"}>
|
||||
<td>{iconType} {this.renderLink(to, user.name)}</td>
|
||||
<td className="is-hidden-mobile">
|
||||
{this.renderLink(to, user.displayName)}
|
||||
</td>
|
||||
<td>
|
||||
<a href={`mailto:${user.mail}`}>{user.mail}</a>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate("users")(UserRow);
|
||||
44
scm-ui/ui-webapp/src/users/components/table/UserRow.tsx
Normal file
44
scm-ui/ui-webapp/src/users/components/table/UserRow.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { translate } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { Icon } from '@scm-manager/ui-components';
|
||||
|
||||
type Props = {
|
||||
user: User;
|
||||
|
||||
// context props
|
||||
t: (p: string) => string;
|
||||
};
|
||||
|
||||
class UserRow extends React.Component<Props> {
|
||||
renderLink(to: string, label: string) {
|
||||
return <Link to={to}>{label}</Link>;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user, t } = this.props;
|
||||
const to = `/user/${user.name}`;
|
||||
const iconType = user.active ? (
|
||||
<Icon title={t('user.active')} name="user" />
|
||||
) : (
|
||||
<Icon title={t('user.inactive')} name="user-slash" />
|
||||
);
|
||||
|
||||
return (
|
||||
<tr className={user.active ? 'border-is-green' : 'border-is-yellow'}>
|
||||
<td>
|
||||
{iconType} {this.renderLink(to, user.name)}
|
||||
</td>
|
||||
<td className="is-hidden-mobile">
|
||||
{this.renderLink(to, user.displayName)}
|
||||
</td>
|
||||
<td>
|
||||
<a href={`mailto:${user.mail}`}>{user.mail}</a>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default translate('users')(UserRow);
|
||||
@@ -1,12 +1,11 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import UserRow from "./UserRow";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import React from 'react';
|
||||
import { translate } from 'react-i18next';
|
||||
import UserRow from './UserRow';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
|
||||
type Props = {
|
||||
t: string => string,
|
||||
users: User[]
|
||||
t: (p: string) => string;
|
||||
users: User[];
|
||||
};
|
||||
|
||||
class UserTable extends React.Component<Props> {
|
||||
@@ -16,9 +15,9 @@ class UserTable extends React.Component<Props> {
|
||||
<table className="card-table table is-hoverable is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="is-hidden-mobile">{t("user.name")}</th>
|
||||
<th>{t("user.displayName")}</th>
|
||||
<th>{t("user.mail")}</th>
|
||||
<th className="is-hidden-mobile">{t('user.name')}</th>
|
||||
<th>{t('user.displayName')}</th>
|
||||
<th>{t('user.mail')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -31,4 +30,4 @@ class UserTable extends React.Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
export default translate("users")(UserTable);
|
||||
export default translate('users')(UserTable);
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as Details } from "./Details";
|
||||
export { default as UserRow } from "./UserRow";
|
||||
export { default as UserTable } from "./UserTable";
|
||||
3
scm-ui/ui-webapp/src/users/components/table/index.ts
Normal file
3
scm-ui/ui-webapp/src/users/components/table/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as Details } from './Details';
|
||||
export { default as UserRow } from './UserRow';
|
||||
export { default as UserTable } from './UserTable';
|
||||
@@ -1,40 +0,0 @@
|
||||
// @flow
|
||||
import * as validator from "./userValidation";
|
||||
|
||||
describe("test displayName validation", () => {
|
||||
it("should return false", () => {
|
||||
expect(validator.isDisplayNameValid("")).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true", () => {
|
||||
// valid names taken from ValidationUtilTest.java
|
||||
const validNames = [
|
||||
"Arthur Dent",
|
||||
"Tricia.McMillan@hitchhiker.com",
|
||||
"Ford Prefect (ford.prefect@hitchhiker.com)",
|
||||
"Zaphod Beeblebrox <zaphod.beeblebrox@hitchhiker.com>",
|
||||
"Marvin, der depressive Roboter"
|
||||
];
|
||||
for (let name of validNames) {
|
||||
expect(validator.isDisplayNameValid(name)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("test password validation", () => {
|
||||
it("should return false", () => {
|
||||
// invalid taken from ValidationUtilTest.java
|
||||
const invalid = ["", "abc", "aaabbbcccdddeeefffggghhhiiijjjkkk"];
|
||||
for (let password of invalid) {
|
||||
expect(validator.isPasswordValid(password)).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it("should return true", () => {
|
||||
// valid taken from ValidationUtilTest.java
|
||||
const valid = ["secret123", "mySuperSecretPassword"];
|
||||
for (let password of valid) {
|
||||
expect(validator.isPasswordValid(password)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
39
scm-ui/ui-webapp/src/users/components/userValidation.test.ts
Normal file
39
scm-ui/ui-webapp/src/users/components/userValidation.test.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as validator from './userValidation';
|
||||
|
||||
describe('test displayName validation', () => {
|
||||
it('should return false', () => {
|
||||
expect(validator.isDisplayNameValid('')).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
// valid names taken from ValidationUtilTest.java
|
||||
const validNames = [
|
||||
'Arthur Dent',
|
||||
'Tricia.McMillan@hitchhiker.com',
|
||||
'Ford Prefect (ford.prefect@hitchhiker.com)',
|
||||
'Zaphod Beeblebrox <zaphod.beeblebrox@hitchhiker.com>',
|
||||
'Marvin, der depressive Roboter',
|
||||
];
|
||||
for (let name of validNames) {
|
||||
expect(validator.isDisplayNameValid(name)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('test password validation', () => {
|
||||
it('should return false', () => {
|
||||
// invalid taken from ValidationUtilTest.java
|
||||
const invalid = ['', 'abc', 'aaabbbcccdddeeefffggghhhiiijjjkkk'];
|
||||
for (let password of invalid) {
|
||||
expect(validator.isPasswordValid(password)).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('should return true', () => {
|
||||
// valid taken from ValidationUtilTest.java
|
||||
const valid = ['secret123', 'mySuperSecretPassword'];
|
||||
for (let password of valid) {
|
||||
expect(validator.isPasswordValid(password)).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,4 @@
|
||||
// @flow
|
||||
|
||||
import { validation } from "@scm-manager/ui-components";
|
||||
import { validation } from '@scm-manager/ui-components';
|
||||
|
||||
const { isNameValid, isMailValid, isPathValid } = validation;
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import UserForm from "../components/UserForm";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import type { History } from "history";
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import UserForm from '../components/UserForm';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { History } from 'history';
|
||||
import {
|
||||
createUser,
|
||||
createUserReset,
|
||||
isCreateUserPending,
|
||||
getCreateUserFailure
|
||||
} from "../modules/users";
|
||||
import { Page } from "@scm-manager/ui-components";
|
||||
import { translate } from "react-i18next";
|
||||
import { getUsersLink } from "../../modules/indexResource";
|
||||
getCreateUserFailure,
|
||||
} from '../modules/users';
|
||||
import { Page } from '@scm-manager/ui-components';
|
||||
import { translate } from 'react-i18next';
|
||||
import { getUsersLink } from '../../modules/indexResource';
|
||||
|
||||
type Props = {
|
||||
loading?: boolean,
|
||||
error?: Error,
|
||||
usersLink: string,
|
||||
loading?: boolean;
|
||||
error?: Error;
|
||||
usersLink: string;
|
||||
|
||||
// dispatcher functions
|
||||
addUser: (link: string, user: User, callback?: () => void) => void,
|
||||
resetForm: () => void,
|
||||
addUser: (link: string, user: User, callback?: () => void) => void;
|
||||
resetForm: () => void;
|
||||
|
||||
// context objects
|
||||
t: string => string,
|
||||
history: History
|
||||
t: (p: string) => string;
|
||||
history: History;
|
||||
};
|
||||
|
||||
class CreateUser extends React.Component<Props> {
|
||||
@@ -35,12 +34,12 @@ class CreateUser extends React.Component<Props> {
|
||||
|
||||
userCreated = (user: User) => {
|
||||
const { history } = this.props;
|
||||
history.push("/user/" + user.name);
|
||||
history.push('/user/' + user.name);
|
||||
};
|
||||
|
||||
createUser = (user: User) => {
|
||||
this.props.addUser(this.props.usersLink, user, () =>
|
||||
this.userCreated(user)
|
||||
this.userCreated(user),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -49,8 +48,8 @@ class CreateUser extends React.Component<Props> {
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={t("createUser.title")}
|
||||
subtitle={t("createUser.subtitle")}
|
||||
title={t('createUser.title')}
|
||||
subtitle={t('createUser.subtitle')}
|
||||
error={error}
|
||||
showContentOnError={true}
|
||||
>
|
||||
@@ -70,7 +69,7 @@ const mapDispatchToProps = dispatch => {
|
||||
},
|
||||
resetForm: () => {
|
||||
dispatch(createUserReset());
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -81,11 +80,11 @@ const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
usersLink,
|
||||
loading,
|
||||
error
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(translate("users")(CreateUser));
|
||||
mapDispatchToProps,
|
||||
)(translate('users')(CreateUser));
|
||||
@@ -1,41 +1,40 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import React from 'react';
|
||||
import { translate } from 'react-i18next';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import {
|
||||
Subtitle,
|
||||
DeleteButton,
|
||||
confirmAlert,
|
||||
ErrorNotification
|
||||
} from "@scm-manager/ui-components";
|
||||
ErrorNotification,
|
||||
} from '@scm-manager/ui-components';
|
||||
import {
|
||||
deleteUser,
|
||||
getDeleteUserFailure,
|
||||
isDeleteUserPending
|
||||
} from "../modules/users";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import type { History } from "history";
|
||||
isDeleteUserPending,
|
||||
} from '../modules/users';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { History } from 'history';
|
||||
|
||||
type Props = {
|
||||
loading: boolean,
|
||||
error: Error,
|
||||
user: User,
|
||||
confirmDialog?: boolean,
|
||||
deleteUser: (user: User, callback?: () => void) => void,
|
||||
loading: boolean;
|
||||
error: Error;
|
||||
user: User;
|
||||
confirmDialog?: boolean;
|
||||
deleteUser: (user: User, callback?: () => void) => void;
|
||||
|
||||
// context props
|
||||
history: History,
|
||||
t: string => string
|
||||
history: History;
|
||||
t: (p: string) => string;
|
||||
};
|
||||
|
||||
class DeleteUser extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
confirmDialog: true
|
||||
confirmDialog: true,
|
||||
};
|
||||
|
||||
userDeleted = () => {
|
||||
this.props.history.push("/users/");
|
||||
this.props.history.push('/users/');
|
||||
};
|
||||
|
||||
deleteUser = () => {
|
||||
@@ -45,18 +44,18 @@ class DeleteUser extends React.Component<Props> {
|
||||
confirmDelete = () => {
|
||||
const { t } = this.props;
|
||||
confirmAlert({
|
||||
title: t("deleteUser.confirmAlert.title"),
|
||||
message: t("deleteUser.confirmAlert.message"),
|
||||
title: t('deleteUser.confirmAlert.title'),
|
||||
message: t('deleteUser.confirmAlert.message'),
|
||||
buttons: [
|
||||
{
|
||||
label: t("deleteUser.confirmAlert.submit"),
|
||||
onClick: () => this.deleteUser()
|
||||
label: t('deleteUser.confirmAlert.submit'),
|
||||
onClick: () => this.deleteUser(),
|
||||
},
|
||||
{
|
||||
label: t("deleteUser.confirmAlert.cancel"),
|
||||
onClick: () => null
|
||||
}
|
||||
]
|
||||
label: t('deleteUser.confirmAlert.cancel'),
|
||||
onClick: () => null,
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -74,12 +73,12 @@ class DeleteUser extends React.Component<Props> {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Subtitle subtitle={t("deleteUser.subtitle")} />
|
||||
<Subtitle subtitle={t('deleteUser.subtitle')} />
|
||||
<ErrorNotification error={error} />
|
||||
<div className="columns">
|
||||
<div className="column">
|
||||
<DeleteButton
|
||||
label={t("deleteUser.button")}
|
||||
label={t('deleteUser.button')}
|
||||
action={action}
|
||||
loading={loading}
|
||||
/>
|
||||
@@ -95,7 +94,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const error = getDeleteUserFailure(state, ownProps.user.name);
|
||||
return {
|
||||
loading,
|
||||
error
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -103,11 +102,11 @@ const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
deleteUser: (user: User, callback?: () => void) => {
|
||||
dispatch(deleteUser(user, callback));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(withRouter(translate("users")(DeleteUser)));
|
||||
mapDispatchToProps,
|
||||
)(withRouter(translate('users')(DeleteUser)));
|
||||
@@ -1,30 +1,29 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import UserForm from "../components/UserForm";
|
||||
import DeleteUser from "./DeleteUser";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import UserForm from '../components/UserForm';
|
||||
import DeleteUser from './DeleteUser';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import {
|
||||
modifyUser,
|
||||
isModifyUserPending,
|
||||
getModifyUserFailure,
|
||||
modifyUserReset
|
||||
} from "../modules/users";
|
||||
import type { History } from "history";
|
||||
import { ErrorNotification } from "@scm-manager/ui-components";
|
||||
modifyUserReset,
|
||||
} from '../modules/users';
|
||||
import { History } from 'history';
|
||||
import { ErrorNotification } from '@scm-manager/ui-components';
|
||||
|
||||
type Props = {
|
||||
loading: boolean,
|
||||
error: Error,
|
||||
loading: boolean;
|
||||
error: Error;
|
||||
|
||||
// dispatch functions
|
||||
modifyUser: (user: User, callback?: () => void) => void,
|
||||
modifyUserReset: User => void,
|
||||
modifyUser: (user: User, callback?: () => void) => void;
|
||||
modifyUserReset: (p: User) => void;
|
||||
|
||||
// context objects
|
||||
user: User,
|
||||
history: History
|
||||
user: User;
|
||||
history: History;
|
||||
};
|
||||
|
||||
class EditUser extends React.Component<Props> {
|
||||
@@ -63,7 +62,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
const error = getModifyUserFailure(state, ownProps.user.name);
|
||||
return {
|
||||
loading,
|
||||
error
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -74,11 +73,11 @@ const mapDispatchToProps = dispatch => {
|
||||
},
|
||||
modifyUserReset: (user: User) => {
|
||||
dispatch(modifyUserReset(user));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
mapDispatchToProps,
|
||||
)(withRouter(EditUser));
|
||||
@@ -1,6 +1,5 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
Page,
|
||||
Loading,
|
||||
@@ -8,40 +7,44 @@ import {
|
||||
SubNavigation,
|
||||
Section,
|
||||
NavLink,
|
||||
ErrorPage
|
||||
} from "@scm-manager/ui-components";
|
||||
import { Route } from "react-router-dom";
|
||||
import { Details } from "./../components/table";
|
||||
import EditUser from "./EditUser";
|
||||
import type { User } from "@scm-manager/ui-types";
|
||||
import type { History } from "history";
|
||||
ErrorPage,
|
||||
} from '@scm-manager/ui-components';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { Details } from './../components/table';
|
||||
import EditUser from './EditUser';
|
||||
import { User } from '@scm-manager/ui-types';
|
||||
import { History } from 'history';
|
||||
import {
|
||||
fetchUserByName,
|
||||
getUserByName,
|
||||
isFetchUserPending,
|
||||
getFetchUserFailure
|
||||
} from "../modules/users";
|
||||
import { EditUserNavLink, SetPasswordNavLink, SetPermissionsNavLink } from "./../components/navLinks";
|
||||
import { translate } from "react-i18next";
|
||||
import { getUsersLink } from "../../modules/indexResource";
|
||||
import SetUserPassword from "../components/SetUserPassword";
|
||||
import SetPermissions from "../../permissions/components/SetPermissions";
|
||||
import {ExtensionPoint} from "@scm-manager/ui-extensions";
|
||||
getFetchUserFailure,
|
||||
} from '../modules/users';
|
||||
import {
|
||||
EditUserNavLink,
|
||||
SetPasswordNavLink,
|
||||
SetPermissionsNavLink,
|
||||
} from './../components/navLinks';
|
||||
import { translate } from 'react-i18next';
|
||||
import { getUsersLink } from '../../modules/indexResource';
|
||||
import SetUserPassword from '../components/SetUserPassword';
|
||||
import SetPermissions from '../../permissions/components/SetPermissions';
|
||||
import { ExtensionPoint } from '@scm-manager/ui-extensions';
|
||||
|
||||
type Props = {
|
||||
name: string,
|
||||
user: User,
|
||||
loading: boolean,
|
||||
error: Error,
|
||||
usersLink: string,
|
||||
name: string;
|
||||
user: User;
|
||||
loading: boolean;
|
||||
error: Error;
|
||||
usersLink: string;
|
||||
|
||||
// dispatcher function
|
||||
fetchUserByName: (string, string) => void,
|
||||
fetchUserByName: (p1: string, p2: string) => void;
|
||||
|
||||
// context objects
|
||||
t: string => string,
|
||||
match: any,
|
||||
history: History
|
||||
t: (p: string) => string;
|
||||
match: any;
|
||||
history: History;
|
||||
};
|
||||
|
||||
class SingleUser extends React.Component<Props> {
|
||||
@@ -50,7 +53,7 @@ class SingleUser extends React.Component<Props> {
|
||||
}
|
||||
|
||||
stripEndingSlash = (url: string) => {
|
||||
if (url.endsWith("/")) {
|
||||
if (url.endsWith('/')) {
|
||||
return url.substring(0, url.length - 2);
|
||||
}
|
||||
return url;
|
||||
@@ -66,8 +69,8 @@ class SingleUser extends React.Component<Props> {
|
||||
if (error) {
|
||||
return (
|
||||
<ErrorPage
|
||||
title={t("singleUser.errorTitle")}
|
||||
subtitle={t("singleUser.errorSubtitle")}
|
||||
title={t('singleUser.errorTitle')}
|
||||
subtitle={t('singleUser.errorSubtitle')}
|
||||
error={error}
|
||||
/>
|
||||
);
|
||||
@@ -81,7 +84,7 @@ class SingleUser extends React.Component<Props> {
|
||||
|
||||
const extensionProps = {
|
||||
user,
|
||||
url
|
||||
url,
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -113,15 +116,15 @@ class SingleUser extends React.Component<Props> {
|
||||
</div>
|
||||
<div className="column">
|
||||
<Navigation>
|
||||
<Section label={t("singleUser.menu.navigationLabel")}>
|
||||
<Section label={t('singleUser.menu.navigationLabel')}>
|
||||
<NavLink
|
||||
to={`${url}`}
|
||||
icon="fas fa-info-circle"
|
||||
label={t("singleUser.menu.informationNavLink")}
|
||||
label={t('singleUser.menu.informationNavLink')}
|
||||
/>
|
||||
<SubNavigation
|
||||
to={`${url}/settings/general`}
|
||||
label={t("singleUser.menu.settingsNavLink")}
|
||||
label={t('singleUser.menu.settingsNavLink')}
|
||||
>
|
||||
<EditUserNavLink
|
||||
user={user}
|
||||
@@ -161,7 +164,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
name,
|
||||
user,
|
||||
loading,
|
||||
error
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -169,11 +172,11 @@ const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
fetchUserByName: (link: string, name: string) => {
|
||||
dispatch(fetchUserByName(link, name));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(translate("users")(SingleUser));
|
||||
mapDispatchToProps,
|
||||
)(translate('users')(SingleUser));
|
||||
@@ -1,17 +1,16 @@
|
||||
// @flow
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { translate } from "react-i18next";
|
||||
import type { History } from "history";
|
||||
import type { User, PagedCollection } from "@scm-manager/ui-types";
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { translate } from 'react-i18next';
|
||||
import { History } from 'history';
|
||||
import { User, PagedCollection } from '@scm-manager/ui-types';
|
||||
import {
|
||||
fetchUsersByPage,
|
||||
getUsersFromState,
|
||||
selectListAsCollection,
|
||||
isPermittedToCreateUsers,
|
||||
isFetchUsersPending,
|
||||
getFetchUsersFailure
|
||||
} from "../modules/users";
|
||||
getFetchUsersFailure,
|
||||
} from '../modules/users';
|
||||
import {
|
||||
Page,
|
||||
PageActions,
|
||||
@@ -19,27 +18,27 @@ import {
|
||||
Notification,
|
||||
LinkPaginator,
|
||||
urls,
|
||||
CreateButton
|
||||
} from "@scm-manager/ui-components";
|
||||
import { UserTable } from "./../components/table";
|
||||
import { getUsersLink } from "../../modules/indexResource";
|
||||
CreateButton,
|
||||
} from '@scm-manager/ui-components';
|
||||
import { UserTable } from './../components/table';
|
||||
import { getUsersLink } from '../../modules/indexResource';
|
||||
|
||||
type Props = {
|
||||
users: User[],
|
||||
loading: boolean,
|
||||
error: Error,
|
||||
canAddUsers: boolean,
|
||||
list: PagedCollection,
|
||||
page: number,
|
||||
usersLink: string,
|
||||
users: User[];
|
||||
loading: boolean;
|
||||
error: Error;
|
||||
canAddUsers: boolean;
|
||||
list: PagedCollection;
|
||||
page: number;
|
||||
usersLink: string;
|
||||
|
||||
// context objects
|
||||
t: string => string,
|
||||
history: History,
|
||||
location: any,
|
||||
t: (p: string) => string;
|
||||
history: History;
|
||||
location: any;
|
||||
|
||||
// dispatch functions
|
||||
fetchUsersByPage: (link: string, page: number, filter?: string) => void
|
||||
fetchUsersByPage: (link: string, page: number, filter?: string) => void;
|
||||
};
|
||||
|
||||
class Users extends React.Component<Props> {
|
||||
@@ -48,7 +47,7 @@ class Users extends React.Component<Props> {
|
||||
fetchUsersByPage(
|
||||
usersLink,
|
||||
page,
|
||||
urls.getQueryStringFromLocation(location)
|
||||
urls.getQueryStringFromLocation(location),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -59,7 +58,7 @@ class Users extends React.Component<Props> {
|
||||
page,
|
||||
usersLink,
|
||||
location,
|
||||
fetchUsersByPage
|
||||
fetchUsersByPage,
|
||||
} = this.props;
|
||||
if (list && page && !loading) {
|
||||
const statePage: number = list.page + 1;
|
||||
@@ -67,7 +66,7 @@ class Users extends React.Component<Props> {
|
||||
fetchUsersByPage(
|
||||
usersLink,
|
||||
page,
|
||||
urls.getQueryStringFromLocation(location)
|
||||
urls.getQueryStringFromLocation(location),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -77,8 +76,8 @@ class Users extends React.Component<Props> {
|
||||
const { users, loading, error, canAddUsers, t } = this.props;
|
||||
return (
|
||||
<Page
|
||||
title={t("users.title")}
|
||||
subtitle={t("users.subtitle")}
|
||||
title={t('users.title')}
|
||||
subtitle={t('users.subtitle')}
|
||||
loading={loading || !users}
|
||||
error={error}
|
||||
>
|
||||
@@ -88,7 +87,7 @@ class Users extends React.Component<Props> {
|
||||
<OverviewPageActions
|
||||
showCreateButton={canAddUsers}
|
||||
link="users"
|
||||
label={t("users.createButton")}
|
||||
label={t('users.createButton')}
|
||||
/>
|
||||
</PageActions>
|
||||
</Page>
|
||||
@@ -109,14 +108,14 @@ class Users extends React.Component<Props> {
|
||||
</>
|
||||
);
|
||||
}
|
||||
return <Notification type="info">{t("users.noUsers")}</Notification>;
|
||||
return <Notification type="info">{t('users.noUsers')}</Notification>;
|
||||
}
|
||||
|
||||
renderCreateButton() {
|
||||
const { canAddUsers, t } = this.props;
|
||||
if (canAddUsers) {
|
||||
return (
|
||||
<CreateButton label={t("users.createButton")} link="/users/create" />
|
||||
<CreateButton label={t('users.createButton')} link="/users/create" />
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -140,7 +139,7 @@ const mapStateToProps = (state, ownProps) => {
|
||||
canAddUsers,
|
||||
list,
|
||||
page,
|
||||
usersLink
|
||||
usersLink,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -148,11 +147,11 @@ const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
fetchUsersByPage: (link: string, page: number, filter?: string) => {
|
||||
dispatch(fetchUsersByPage(link, page, filter));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(translate("users")(Users));
|
||||
mapDispatchToProps,
|
||||
)(translate('users')(Users));
|
||||
@@ -1,7 +1,6 @@
|
||||
//@flow
|
||||
import configureMockStore from "redux-mock-store";
|
||||
import thunk from "redux-thunk";
|
||||
import fetchMock from "fetch-mock";
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import reducer, {
|
||||
FETCH_USERS,
|
||||
@@ -46,53 +45,53 @@ import reducer, {
|
||||
deleteUserSuccess,
|
||||
getDeleteUserFailure,
|
||||
selectListAsCollection,
|
||||
isPermittedToCreateUsers
|
||||
} from "./users";
|
||||
isPermittedToCreateUsers,
|
||||
} from './users';
|
||||
|
||||
const userZaphod = {
|
||||
active: true,
|
||||
admin: true,
|
||||
creationDate: "2018-07-11T12:23:49.027Z",
|
||||
displayName: "Z. Beeblebrox",
|
||||
mail: "president@heartofgold.universe",
|
||||
name: "zaphod",
|
||||
password: "",
|
||||
type: "xml",
|
||||
creationDate: '2018-07-11T12:23:49.027Z',
|
||||
displayName: 'Z. Beeblebrox',
|
||||
mail: 'president@heartofgold.universe',
|
||||
name: 'zaphod',
|
||||
password: '',
|
||||
type: 'xml',
|
||||
properties: {},
|
||||
_links: {
|
||||
self: {
|
||||
href: "http://localhost:8081/api/v2/users/zaphod"
|
||||
href: 'http://localhost:8081/api/v2/users/zaphod',
|
||||
},
|
||||
delete: {
|
||||
href: "http://localhost:8081/api/v2/users/zaphod"
|
||||
href: 'http://localhost:8081/api/v2/users/zaphod',
|
||||
},
|
||||
update: {
|
||||
href: "http://localhost:8081/api/v2/users/zaphod"
|
||||
}
|
||||
}
|
||||
href: 'http://localhost:8081/api/v2/users/zaphod',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const userFord = {
|
||||
active: true,
|
||||
admin: false,
|
||||
creationDate: "2018-07-06T13:21:18.459Z",
|
||||
displayName: "F. Prefect",
|
||||
mail: "ford@prefect.universe",
|
||||
name: "ford",
|
||||
password: "",
|
||||
type: "xml",
|
||||
creationDate: '2018-07-06T13:21:18.459Z',
|
||||
displayName: 'F. Prefect',
|
||||
mail: 'ford@prefect.universe',
|
||||
name: 'ford',
|
||||
password: '',
|
||||
type: 'xml',
|
||||
properties: {},
|
||||
_links: {
|
||||
self: {
|
||||
href: "http://localhost:8081/api/v2/users/ford"
|
||||
href: 'http://localhost:8081/api/v2/users/ford',
|
||||
},
|
||||
delete: {
|
||||
href: "http://localhost:8081/api/v2/users/ford"
|
||||
href: 'http://localhost:8081/api/v2/users/ford',
|
||||
},
|
||||
update: {
|
||||
href: "http://localhost:8081/api/v2/users/ford"
|
||||
}
|
||||
}
|
||||
href: 'http://localhost:8081/api/v2/users/ford',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const responseBody = {
|
||||
@@ -100,50 +99,54 @@ const responseBody = {
|
||||
pageTotal: 1,
|
||||
_links: {
|
||||
self: {
|
||||
href: "http://localhost:3000/api/v2/users/?page=0&pageSize=10"
|
||||
href: 'http://localhost:3000/api/v2/users/?page=0&pageSize=10',
|
||||
},
|
||||
first: {
|
||||
href: "http://localhost:3000/api/v2/users/?page=0&pageSize=10"
|
||||
href: 'http://localhost:3000/api/v2/users/?page=0&pageSize=10',
|
||||
},
|
||||
last: {
|
||||
href: "http://localhost:3000/api/v2/users/?page=0&pageSize=10"
|
||||
href: 'http://localhost:3000/api/v2/users/?page=0&pageSize=10',
|
||||
},
|
||||
create: {
|
||||
href: "http://localhost:3000/api/v2/users/"
|
||||
}
|
||||
href: 'http://localhost:3000/api/v2/users/',
|
||||
},
|
||||
},
|
||||
_embedded: {
|
||||
users: [userZaphod, userFord]
|
||||
}
|
||||
users: [userZaphod, userFord],
|
||||
},
|
||||
};
|
||||
|
||||
const response = {
|
||||
headers: { "content-type": "application/json" },
|
||||
responseBody
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
responseBody,
|
||||
};
|
||||
|
||||
const URL = "users";
|
||||
const USERS_URL = "/api/v2/users";
|
||||
const USER_ZAPHOD_URL = "http://localhost:8081/api/v2/users/zaphod";
|
||||
const URL = 'users';
|
||||
const USERS_URL = '/api/v2/users';
|
||||
const USER_ZAPHOD_URL = 'http://localhost:8081/api/v2/users/zaphod';
|
||||
|
||||
const error = new Error("KAPUTT");
|
||||
const error = new Error('KAPUTT');
|
||||
|
||||
describe("users fetch()", () => {
|
||||
describe('users fetch()', () => {
|
||||
const mockStore = configureMockStore([thunk]);
|
||||
afterEach(() => {
|
||||
fetchMock.reset();
|
||||
fetchMock.restore();
|
||||
});
|
||||
|
||||
it("should successfully fetch users", () => {
|
||||
it('should successfully fetch users', () => {
|
||||
fetchMock.getOnce(USERS_URL, response);
|
||||
|
||||
const expectedActions = [
|
||||
{ type: FETCH_USERS_PENDING },
|
||||
{
|
||||
type: FETCH_USERS_PENDING,
|
||||
},
|
||||
{
|
||||
type: FETCH_USERS_SUCCESS,
|
||||
payload: response
|
||||
}
|
||||
payload: response,
|
||||
},
|
||||
];
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -153,9 +156,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail getting users on HTTP 500", () => {
|
||||
it('should fail getting users on HTTP 500', () => {
|
||||
fetchMock.getOnce(USERS_URL, {
|
||||
status: 500
|
||||
status: 500,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -167,11 +170,11 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should sucessfully fetch single user by name", () => {
|
||||
fetchMock.getOnce(USERS_URL + "/zaphod", userZaphod);
|
||||
it('should sucessfully fetch single user by name', () => {
|
||||
fetchMock.getOnce(USERS_URL + '/zaphod', userZaphod);
|
||||
|
||||
const store = mockStore({});
|
||||
return store.dispatch(fetchUserByName(URL, "zaphod")).then(() => {
|
||||
return store.dispatch(fetchUserByName(URL, 'zaphod')).then(() => {
|
||||
const actions = store.getActions();
|
||||
expect(actions[0].type).toEqual(FETCH_USER_PENDING);
|
||||
expect(actions[1].type).toEqual(FETCH_USER_SUCCESS);
|
||||
@@ -179,13 +182,13 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail fetching single user by name on HTTP 500", () => {
|
||||
fetchMock.getOnce(USERS_URL + "/zaphod", {
|
||||
status: 500
|
||||
it('should fail fetching single user by name on HTTP 500', () => {
|
||||
fetchMock.getOnce(USERS_URL + '/zaphod', {
|
||||
status: 500,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
return store.dispatch(fetchUserByName(URL, "zaphod")).then(() => {
|
||||
return store.dispatch(fetchUserByName(URL, 'zaphod')).then(() => {
|
||||
const actions = store.getActions();
|
||||
expect(actions[0].type).toEqual(FETCH_USER_PENDING);
|
||||
expect(actions[1].type).toEqual(FETCH_USER_FAILURE);
|
||||
@@ -193,7 +196,7 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should sucessfully fetch single user", () => {
|
||||
it('should sucessfully fetch single user', () => {
|
||||
fetchMock.getOnce(USER_ZAPHOD_URL, userZaphod);
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -205,9 +208,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail fetching single user on HTTP 500", () => {
|
||||
it('should fail fetching single user on HTTP 500', () => {
|
||||
fetchMock.getOnce(USER_ZAPHOD_URL, {
|
||||
status: 500
|
||||
status: 500,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -219,10 +222,10 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should add a user successfully", () => {
|
||||
it('should add a user successfully', () => {
|
||||
// unmatched
|
||||
fetchMock.postOnce(USERS_URL, {
|
||||
status: 204
|
||||
status: 204,
|
||||
});
|
||||
|
||||
// after create, the users are fetched again
|
||||
@@ -236,9 +239,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail adding a user on HTTP 500", () => {
|
||||
it('should fail adding a user on HTTP 500', () => {
|
||||
fetchMock.postOnce(USERS_URL, {
|
||||
status: 500
|
||||
status: 500,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -250,27 +253,27 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should call the callback after user successfully created", () => {
|
||||
it('should call the callback after user successfully created', () => {
|
||||
// unmatched
|
||||
fetchMock.postOnce(USERS_URL, {
|
||||
status: 204
|
||||
status: 204,
|
||||
});
|
||||
|
||||
let callMe = "not yet";
|
||||
let callMe = 'not yet';
|
||||
|
||||
const callback = () => {
|
||||
callMe = "yeah";
|
||||
callMe = 'yeah';
|
||||
};
|
||||
|
||||
const store = mockStore({});
|
||||
return store.dispatch(createUser(URL, userZaphod, callback)).then(() => {
|
||||
expect(callMe).toBe("yeah");
|
||||
expect(callMe).toBe('yeah');
|
||||
});
|
||||
});
|
||||
|
||||
it("successfully update user", () => {
|
||||
it('successfully update user', () => {
|
||||
fetchMock.putOnce(USER_ZAPHOD_URL, {
|
||||
status: 204
|
||||
status: 204,
|
||||
});
|
||||
fetchMock.getOnce(USER_ZAPHOD_URL, userZaphod);
|
||||
|
||||
@@ -284,9 +287,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should call callback, after successful modified user", () => {
|
||||
it('should call callback, after successful modified user', () => {
|
||||
fetchMock.putOnce(USER_ZAPHOD_URL, {
|
||||
status: 204
|
||||
status: 204,
|
||||
});
|
||||
fetchMock.getOnce(USER_ZAPHOD_URL, userZaphod);
|
||||
|
||||
@@ -301,9 +304,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail updating user on HTTP 500", () => {
|
||||
it('should fail updating user on HTTP 500', () => {
|
||||
fetchMock.putOnce(USER_ZAPHOD_URL, {
|
||||
status: 500
|
||||
status: 500,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -315,9 +318,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should delete successfully user zaphod", () => {
|
||||
it('should delete successfully user zaphod', () => {
|
||||
fetchMock.deleteOnce(USER_ZAPHOD_URL, {
|
||||
status: 204
|
||||
status: 204,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -330,9 +333,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should call the callback, after successful delete", () => {
|
||||
it('should call the callback, after successful delete', () => {
|
||||
fetchMock.deleteOnce(USER_ZAPHOD_URL, {
|
||||
status: 204
|
||||
status: 204,
|
||||
});
|
||||
|
||||
let called = false;
|
||||
@@ -346,9 +349,9 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail to delete user zaphod", () => {
|
||||
it('should fail to delete user zaphod', () => {
|
||||
fetchMock.deleteOnce(USER_ZAPHOD_URL, {
|
||||
status: 500
|
||||
status: 500,
|
||||
});
|
||||
|
||||
const store = mockStore({});
|
||||
@@ -362,296 +365,325 @@ describe("users fetch()", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("users reducer", () => {
|
||||
it("should update state correctly according to FETCH_USERS_SUCCESS action", () => {
|
||||
describe('users reducer', () => {
|
||||
it('should update state correctly according to FETCH_USERS_SUCCESS action', () => {
|
||||
const newState = reducer({}, fetchUsersSuccess(responseBody));
|
||||
|
||||
expect(newState.list).toEqual({
|
||||
entries: ["zaphod", "ford"],
|
||||
entries: ['zaphod', 'ford'],
|
||||
entry: {
|
||||
userCreatePermission: true,
|
||||
page: 0,
|
||||
pageTotal: 1,
|
||||
_links: responseBody._links
|
||||
}
|
||||
_links: responseBody._links,
|
||||
},
|
||||
});
|
||||
|
||||
expect(newState.byNames).toEqual({
|
||||
zaphod: userZaphod,
|
||||
ford: userFord
|
||||
ford: userFord,
|
||||
});
|
||||
|
||||
expect(newState.list.entry.userCreatePermission).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should set userCreatePermission to true if update link is present", () => {
|
||||
it('should set userCreatePermission to true if update link is present', () => {
|
||||
const newState = reducer({}, fetchUsersSuccess(responseBody));
|
||||
|
||||
expect(newState.list.entry.userCreatePermission).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should not replace whole byNames map when fetching users", () => {
|
||||
it('should not replace whole byNames map when fetching users', () => {
|
||||
const oldState = {
|
||||
byNames: {
|
||||
ford: userFord
|
||||
}
|
||||
ford: userFord,
|
||||
},
|
||||
};
|
||||
|
||||
const newState = reducer(oldState, fetchUsersSuccess(responseBody));
|
||||
expect(newState.byNames["zaphod"]).toBeDefined();
|
||||
expect(newState.byNames["ford"]).toBeDefined();
|
||||
expect(newState.byNames['zaphod']).toBeDefined();
|
||||
expect(newState.byNames['ford']).toBeDefined();
|
||||
});
|
||||
|
||||
it("should remove user from state when delete succeeds", () => {
|
||||
it('should remove user from state when delete succeeds', () => {
|
||||
const state = {
|
||||
list: {
|
||||
entries: ["ford", "zaphod"]
|
||||
entries: ['ford', 'zaphod'],
|
||||
},
|
||||
byNames: {
|
||||
zaphod: userZaphod,
|
||||
ford: userFord
|
||||
}
|
||||
ford: userFord,
|
||||
},
|
||||
};
|
||||
|
||||
const newState = reducer(state, deleteUserSuccess(userFord));
|
||||
expect(newState.byNames["zaphod"]).toBeDefined();
|
||||
expect(newState.byNames["ford"]).toBeFalsy();
|
||||
expect(newState.list.entries).toEqual(["zaphod"]);
|
||||
expect(newState.byNames['zaphod']).toBeDefined();
|
||||
expect(newState.byNames['ford']).toBeFalsy();
|
||||
expect(newState.list.entries).toEqual(['zaphod']);
|
||||
});
|
||||
|
||||
it("should set userCreatePermission to true if create link is present", () => {
|
||||
it('should set userCreatePermission to true if create link is present', () => {
|
||||
const newState = reducer({}, fetchUsersSuccess(responseBody));
|
||||
|
||||
expect(newState.list.entry.userCreatePermission).toBeTruthy();
|
||||
expect(newState.list.entries).toEqual(["zaphod", "ford"]);
|
||||
expect(newState.byNames["ford"]).toBeTruthy();
|
||||
expect(newState.byNames["zaphod"]).toBeTruthy();
|
||||
expect(newState.list.entries).toEqual(['zaphod', 'ford']);
|
||||
expect(newState.byNames['ford']).toBeTruthy();
|
||||
expect(newState.byNames['zaphod']).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should update state according to FETCH_USER_SUCCESS action", () => {
|
||||
it('should update state according to FETCH_USER_SUCCESS action', () => {
|
||||
const newState = reducer({}, fetchUserSuccess(userFord));
|
||||
expect(newState.byNames["ford"]).toBe(userFord);
|
||||
expect(newState.byNames['ford']).toBe(userFord);
|
||||
});
|
||||
|
||||
it("should affect users state nor the state of other users", () => {
|
||||
it('should affect users state nor the state of other users', () => {
|
||||
const newState = reducer(
|
||||
{
|
||||
list: {
|
||||
entries: ["zaphod"]
|
||||
}
|
||||
entries: ['zaphod'],
|
||||
},
|
||||
},
|
||||
fetchUserSuccess(userFord)
|
||||
fetchUserSuccess(userFord),
|
||||
);
|
||||
expect(newState.byNames["ford"]).toBe(userFord);
|
||||
expect(newState.list.entries).toEqual(["zaphod"]);
|
||||
expect(newState.byNames['ford']).toBe(userFord);
|
||||
expect(newState.list.entries).toEqual(['zaphod']);
|
||||
});
|
||||
});
|
||||
|
||||
describe("selector tests", () => {
|
||||
it("should return an empty object", () => {
|
||||
describe('selector tests', () => {
|
||||
it('should return an empty object', () => {
|
||||
expect(selectListAsCollection({})).toEqual({});
|
||||
expect(selectListAsCollection({ users: { a: "a" } })).toEqual({});
|
||||
expect(
|
||||
selectListAsCollection({
|
||||
users: {
|
||||
a: 'a',
|
||||
},
|
||||
}),
|
||||
).toEqual({});
|
||||
});
|
||||
|
||||
it("should return a state slice collection", () => {
|
||||
it('should return a state slice collection', () => {
|
||||
const collection = {
|
||||
page: 3,
|
||||
totalPages: 42
|
||||
totalPages: 42,
|
||||
};
|
||||
|
||||
const state = {
|
||||
users: {
|
||||
list: {
|
||||
entry: collection
|
||||
}
|
||||
}
|
||||
entry: collection,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(selectListAsCollection(state)).toBe(collection);
|
||||
});
|
||||
|
||||
it("should return false", () => {
|
||||
it('should return false', () => {
|
||||
expect(isPermittedToCreateUsers({})).toBe(false);
|
||||
expect(isPermittedToCreateUsers({ users: { list: { entry: {} } } })).toBe(
|
||||
false
|
||||
);
|
||||
expect(
|
||||
isPermittedToCreateUsers({
|
||||
users: { list: { entry: { userCreatePermission: false } } }
|
||||
})
|
||||
users: {
|
||||
list: {
|
||||
entry: {},
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isPermittedToCreateUsers({
|
||||
users: {
|
||||
list: {
|
||||
entry: {
|
||||
userCreatePermission: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true", () => {
|
||||
it('should return true', () => {
|
||||
const state = {
|
||||
users: {
|
||||
list: {
|
||||
entry: {
|
||||
userCreatePermission: true
|
||||
}
|
||||
}
|
||||
}
|
||||
userCreatePermission: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(isPermittedToCreateUsers(state)).toBe(true);
|
||||
});
|
||||
|
||||
it("should get users from state", () => {
|
||||
it('should get users from state', () => {
|
||||
const state = {
|
||||
users: {
|
||||
list: {
|
||||
entries: ["a", "b"]
|
||||
entries: ['a', 'b'],
|
||||
},
|
||||
byNames: {
|
||||
a: { name: "a" },
|
||||
b: { name: "b" }
|
||||
}
|
||||
}
|
||||
a: {
|
||||
name: 'a',
|
||||
},
|
||||
b: {
|
||||
name: 'b',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getUsersFromState(state)).toEqual([{ name: "a" }, { name: "b" }]);
|
||||
expect(getUsersFromState(state)).toEqual([
|
||||
{
|
||||
name: 'a',
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("should return true, when fetch users is pending", () => {
|
||||
it('should return true, when fetch users is pending', () => {
|
||||
const state = {
|
||||
pending: {
|
||||
[FETCH_USERS]: true
|
||||
}
|
||||
[FETCH_USERS]: true,
|
||||
},
|
||||
};
|
||||
expect(isFetchUsersPending(state)).toEqual(true);
|
||||
});
|
||||
|
||||
it("should return false, when fetch users is not pending", () => {
|
||||
it('should return false, when fetch users is not pending', () => {
|
||||
expect(isFetchUsersPending({})).toEqual(false);
|
||||
});
|
||||
|
||||
it("should return error when fetch users did fail", () => {
|
||||
it('should return error when fetch users did fail', () => {
|
||||
const state = {
|
||||
failure: {
|
||||
[FETCH_USERS]: error
|
||||
}
|
||||
[FETCH_USERS]: error,
|
||||
},
|
||||
};
|
||||
expect(getFetchUsersFailure(state)).toEqual(error);
|
||||
});
|
||||
|
||||
it("should return undefined when fetch users did not fail", () => {
|
||||
it('should return undefined when fetch users did not fail', () => {
|
||||
expect(getFetchUsersFailure({})).toBe(undefined);
|
||||
});
|
||||
|
||||
it("should return true if create user is pending", () => {
|
||||
it('should return true if create user is pending', () => {
|
||||
const state = {
|
||||
pending: {
|
||||
[CREATE_USER]: true
|
||||
}
|
||||
[CREATE_USER]: true,
|
||||
},
|
||||
};
|
||||
expect(isCreateUserPending(state)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if create user is not pending", () => {
|
||||
it('should return false if create user is not pending', () => {
|
||||
const state = {
|
||||
pending: {
|
||||
[CREATE_USER]: false
|
||||
}
|
||||
[CREATE_USER]: false,
|
||||
},
|
||||
};
|
||||
expect(isCreateUserPending(state)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return error when create user did fail", () => {
|
||||
it('should return error when create user did fail', () => {
|
||||
const state = {
|
||||
failure: {
|
||||
[CREATE_USER]: error
|
||||
}
|
||||
[CREATE_USER]: error,
|
||||
},
|
||||
};
|
||||
expect(getCreateUserFailure(state)).toEqual(error);
|
||||
});
|
||||
|
||||
it("should return undefined when create user did not fail", () => {
|
||||
it('should return undefined when create user did not fail', () => {
|
||||
expect(getCreateUserFailure({})).toBe(undefined);
|
||||
});
|
||||
|
||||
it("should return user ford", () => {
|
||||
it('should return user ford', () => {
|
||||
const state = {
|
||||
users: {
|
||||
byNames: {
|
||||
ford: userFord
|
||||
}
|
||||
}
|
||||
ford: userFord,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getUserByName(state, "ford")).toEqual(userFord);
|
||||
expect(getUserByName(state, 'ford')).toEqual(userFord);
|
||||
});
|
||||
|
||||
it("should return true, when fetch user zaphod is pending", () => {
|
||||
it('should return true, when fetch user zaphod is pending', () => {
|
||||
const state = {
|
||||
pending: {
|
||||
[FETCH_USER + "/zaphod"]: true
|
||||
}
|
||||
[FETCH_USER + '/zaphod']: true,
|
||||
},
|
||||
};
|
||||
expect(isFetchUserPending(state, "zaphod")).toEqual(true);
|
||||
expect(isFetchUserPending(state, 'zaphod')).toEqual(true);
|
||||
});
|
||||
|
||||
it("should return false, when fetch user zaphod is not pending", () => {
|
||||
expect(isFetchUserPending({}, "zaphod")).toEqual(false);
|
||||
it('should return false, when fetch user zaphod is not pending', () => {
|
||||
expect(isFetchUserPending({}, 'zaphod')).toEqual(false);
|
||||
});
|
||||
|
||||
it("should return error when fetch user zaphod did fail", () => {
|
||||
it('should return error when fetch user zaphod did fail', () => {
|
||||
const state = {
|
||||
failure: {
|
||||
[FETCH_USER + "/zaphod"]: error
|
||||
}
|
||||
[FETCH_USER + '/zaphod']: error,
|
||||
},
|
||||
};
|
||||
expect(getFetchUserFailure(state, "zaphod")).toEqual(error);
|
||||
expect(getFetchUserFailure(state, 'zaphod')).toEqual(error);
|
||||
});
|
||||
|
||||
it("should return undefined when fetch user zaphod did not fail", () => {
|
||||
expect(getFetchUserFailure({}, "zaphod")).toBe(undefined);
|
||||
it('should return undefined when fetch user zaphod did not fail', () => {
|
||||
expect(getFetchUserFailure({}, 'zaphod')).toBe(undefined);
|
||||
});
|
||||
|
||||
it("should return true, when modify user ford is pending", () => {
|
||||
it('should return true, when modify user ford is pending', () => {
|
||||
const state = {
|
||||
pending: {
|
||||
[MODIFY_USER + "/ford"]: true
|
||||
}
|
||||
[MODIFY_USER + '/ford']: true,
|
||||
},
|
||||
};
|
||||
expect(isModifyUserPending(state, "ford")).toEqual(true);
|
||||
expect(isModifyUserPending(state, 'ford')).toEqual(true);
|
||||
});
|
||||
|
||||
it("should return false, when modify user ford is not pending", () => {
|
||||
expect(isModifyUserPending({}, "ford")).toEqual(false);
|
||||
it('should return false, when modify user ford is not pending', () => {
|
||||
expect(isModifyUserPending({}, 'ford')).toEqual(false);
|
||||
});
|
||||
|
||||
it("should return error when modify user ford did fail", () => {
|
||||
it('should return error when modify user ford did fail', () => {
|
||||
const state = {
|
||||
failure: {
|
||||
[MODIFY_USER + "/ford"]: error
|
||||
}
|
||||
[MODIFY_USER + '/ford']: error,
|
||||
},
|
||||
};
|
||||
expect(getModifyUserFailure(state, "ford")).toEqual(error);
|
||||
expect(getModifyUserFailure(state, 'ford')).toEqual(error);
|
||||
});
|
||||
|
||||
it("should return undefined when modify user ford did not fail", () => {
|
||||
expect(getModifyUserFailure({}, "ford")).toBe(undefined);
|
||||
it('should return undefined when modify user ford did not fail', () => {
|
||||
expect(getModifyUserFailure({}, 'ford')).toBe(undefined);
|
||||
});
|
||||
|
||||
it("should return true, when delete user zaphod is pending", () => {
|
||||
it('should return true, when delete user zaphod is pending', () => {
|
||||
const state = {
|
||||
pending: {
|
||||
[DELETE_USER + "/zaphod"]: true
|
||||
}
|
||||
[DELETE_USER + '/zaphod']: true,
|
||||
},
|
||||
};
|
||||
expect(isDeleteUserPending(state, "zaphod")).toEqual(true);
|
||||
expect(isDeleteUserPending(state, 'zaphod')).toEqual(true);
|
||||
});
|
||||
|
||||
it("should return false, when delete user zaphod is not pending", () => {
|
||||
expect(isDeleteUserPending({}, "zaphod")).toEqual(false);
|
||||
it('should return false, when delete user zaphod is not pending', () => {
|
||||
expect(isDeleteUserPending({}, 'zaphod')).toEqual(false);
|
||||
});
|
||||
|
||||
it("should return error when delete user zaphod did fail", () => {
|
||||
it('should return error when delete user zaphod did fail', () => {
|
||||
const state = {
|
||||
failure: {
|
||||
[DELETE_USER + "/zaphod"]: error
|
||||
}
|
||||
[DELETE_USER + '/zaphod']: error,
|
||||
},
|
||||
};
|
||||
expect(getDeleteUserFailure(state, "zaphod")).toEqual(error);
|
||||
expect(getDeleteUserFailure(state, 'zaphod')).toEqual(error);
|
||||
});
|
||||
|
||||
it("should return undefined when delete user zaphod did not fail", () => {
|
||||
expect(getDeleteUserFailure({}, "zaphod")).toBe(undefined);
|
||||
it('should return undefined when delete user zaphod did not fail', () => {
|
||||
expect(getDeleteUserFailure({}, 'zaphod')).toBe(undefined);
|
||||
});
|
||||
});
|
||||
@@ -1,39 +1,38 @@
|
||||
// @flow
|
||||
import { apiClient } from "@scm-manager/ui-components";
|
||||
import { isPending } from "../../modules/pending";
|
||||
import { getFailure } from "../../modules/failure";
|
||||
import * as types from "../../modules/types";
|
||||
import { combineReducers, Dispatch } from "redux";
|
||||
import type { User, Action, PagedCollection } from "@scm-manager/ui-types";
|
||||
import { apiClient } from '@scm-manager/ui-components';
|
||||
import { isPending } from '../../modules/pending';
|
||||
import { getFailure } from '../../modules/failure';
|
||||
import * as types from '../../modules/types';
|
||||
import { combineReducers, Dispatch } from 'redux';
|
||||
import { User, Action, PagedCollection } from '@scm-manager/ui-types';
|
||||
|
||||
export const FETCH_USERS = "scm/users/FETCH_USERS";
|
||||
export const FETCH_USERS = 'scm/users/FETCH_USERS';
|
||||
export const FETCH_USERS_PENDING = `${FETCH_USERS}_${types.PENDING_SUFFIX}`;
|
||||
export const FETCH_USERS_SUCCESS = `${FETCH_USERS}_${types.SUCCESS_SUFFIX}`;
|
||||
export const FETCH_USERS_FAILURE = `${FETCH_USERS}_${types.FAILURE_SUFFIX}`;
|
||||
|
||||
export const FETCH_USER = "scm/users/FETCH_USER";
|
||||
export const FETCH_USER = 'scm/users/FETCH_USER';
|
||||
export const FETCH_USER_PENDING = `${FETCH_USER}_${types.PENDING_SUFFIX}`;
|
||||
export const FETCH_USER_SUCCESS = `${FETCH_USER}_${types.SUCCESS_SUFFIX}`;
|
||||
export const FETCH_USER_FAILURE = `${FETCH_USER}_${types.FAILURE_SUFFIX}`;
|
||||
|
||||
export const CREATE_USER = "scm/users/CREATE_USER";
|
||||
export const CREATE_USER = 'scm/users/CREATE_USER';
|
||||
export const CREATE_USER_PENDING = `${CREATE_USER}_${types.PENDING_SUFFIX}`;
|
||||
export const CREATE_USER_SUCCESS = `${CREATE_USER}_${types.SUCCESS_SUFFIX}`;
|
||||
export const CREATE_USER_FAILURE = `${CREATE_USER}_${types.FAILURE_SUFFIX}`;
|
||||
export const CREATE_USER_RESET = `${CREATE_USER}_${types.RESET_SUFFIX}`;
|
||||
|
||||
export const MODIFY_USER = "scm/users/MODIFY_USER";
|
||||
export const MODIFY_USER = 'scm/users/MODIFY_USER';
|
||||
export const MODIFY_USER_PENDING = `${MODIFY_USER}_${types.PENDING_SUFFIX}`;
|
||||
export const MODIFY_USER_SUCCESS = `${MODIFY_USER}_${types.SUCCESS_SUFFIX}`;
|
||||
export const MODIFY_USER_FAILURE = `${MODIFY_USER}_${types.FAILURE_SUFFIX}`;
|
||||
export const MODIFY_USER_RESET = `${MODIFY_USER}_${types.RESET_SUFFIX}`;
|
||||
|
||||
export const DELETE_USER = "scm/users/DELETE_USER";
|
||||
export const DELETE_USER = 'scm/users/DELETE_USER';
|
||||
export const DELETE_USER_PENDING = `${DELETE_USER}_${types.PENDING_SUFFIX}`;
|
||||
export const DELETE_USER_SUCCESS = `${DELETE_USER}_${types.SUCCESS_SUFFIX}`;
|
||||
export const DELETE_USER_FAILURE = `${DELETE_USER}_${types.FAILURE_SUFFIX}`;
|
||||
|
||||
const CONTENT_TYPE_USER = "application/vnd.scmm-user+json;v=2";
|
||||
const CONTENT_TYPE_USER = 'application/vnd.scmm-user+json;v=2';
|
||||
|
||||
// TODO i18n for error messages
|
||||
|
||||
@@ -47,7 +46,7 @@ export function fetchUsersByPage(link: string, page: number, filter?: string) {
|
||||
// backend start counting by 0
|
||||
if (filter) {
|
||||
return fetchUsersByLink(
|
||||
`${link}?page=${page - 1}&q=${decodeURIComponent(filter)}`
|
||||
`${link}?page=${page - 1}&q=${decodeURIComponent(filter)}`,
|
||||
);
|
||||
}
|
||||
return fetchUsersByLink(`${link}?page=${page - 1}`);
|
||||
@@ -70,14 +69,14 @@ export function fetchUsersByLink(link: string) {
|
||||
|
||||
export function fetchUsersPending(): Action {
|
||||
return {
|
||||
type: FETCH_USERS_PENDING
|
||||
type: FETCH_USERS_PENDING,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchUsersSuccess(users: any): Action {
|
||||
return {
|
||||
type: FETCH_USERS_SUCCESS,
|
||||
payload: users
|
||||
payload: users,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,14 +85,14 @@ export function fetchUsersFailure(url: string, error: Error): Action {
|
||||
type: FETCH_USERS_FAILURE,
|
||||
payload: {
|
||||
error,
|
||||
url
|
||||
}
|
||||
url,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
//fetch user
|
||||
export function fetchUserByName(link: string, name: string) {
|
||||
const userUrl = link.endsWith("/") ? link + name : link + "/" + name;
|
||||
const userUrl = link.endsWith('/') ? link + name : link + '/' + name;
|
||||
return fetchUser(userUrl, name);
|
||||
}
|
||||
|
||||
@@ -122,7 +121,7 @@ export function fetchUserPending(name: string): Action {
|
||||
return {
|
||||
type: FETCH_USER_PENDING,
|
||||
payload: name,
|
||||
itemId: name
|
||||
itemId: name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -130,7 +129,7 @@ export function fetchUserSuccess(user: any): Action {
|
||||
return {
|
||||
type: FETCH_USER_SUCCESS,
|
||||
payload: user,
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,9 +138,9 @@ export function fetchUserFailure(name: string, error: Error): Action {
|
||||
type: FETCH_USER_FAILURE,
|
||||
payload: {
|
||||
name,
|
||||
error
|
||||
error,
|
||||
},
|
||||
itemId: name
|
||||
itemId: name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -165,26 +164,26 @@ export function createUser(link: string, user: User, callback?: () => void) {
|
||||
export function createUserPending(user: User): Action {
|
||||
return {
|
||||
type: CREATE_USER_PENDING,
|
||||
user
|
||||
user,
|
||||
};
|
||||
}
|
||||
|
||||
export function createUserSuccess(): Action {
|
||||
return {
|
||||
type: CREATE_USER_SUCCESS
|
||||
type: CREATE_USER_SUCCESS,
|
||||
};
|
||||
}
|
||||
|
||||
export function createUserFailure(error: Error): Action {
|
||||
return {
|
||||
type: CREATE_USER_FAILURE,
|
||||
payload: error
|
||||
payload: error,
|
||||
};
|
||||
}
|
||||
|
||||
export function createUserReset() {
|
||||
return {
|
||||
type: CREATE_USER_RESET
|
||||
type: CREATE_USER_RESET,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -214,7 +213,7 @@ export function modifyUserPending(user: User): Action {
|
||||
return {
|
||||
type: MODIFY_USER_PENDING,
|
||||
payload: user,
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -222,7 +221,7 @@ export function modifyUserSuccess(user: User): Action {
|
||||
return {
|
||||
type: MODIFY_USER_SUCCESS,
|
||||
payload: user,
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -231,16 +230,16 @@ export function modifyUserFailure(user: User, error: Error): Action {
|
||||
type: MODIFY_USER_FAILURE,
|
||||
payload: {
|
||||
error,
|
||||
user
|
||||
user,
|
||||
},
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
export function modifyUserReset(user: User): Action {
|
||||
return {
|
||||
type: MODIFY_USER_RESET,
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -267,7 +266,7 @@ export function deleteUserPending(user: User): Action {
|
||||
return {
|
||||
type: DELETE_USER_PENDING,
|
||||
payload: user,
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -275,7 +274,7 @@ export function deleteUserSuccess(user: User): Action {
|
||||
return {
|
||||
type: DELETE_USER_SUCCESS,
|
||||
payload: user,
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -284,16 +283,16 @@ export function deleteUserFailure(user: User, error: Error): Action {
|
||||
type: DELETE_USER_FAILURE,
|
||||
payload: {
|
||||
error,
|
||||
user
|
||||
user,
|
||||
},
|
||||
itemId: user.name
|
||||
itemId: user.name,
|
||||
};
|
||||
}
|
||||
|
||||
function extractUsersByNames(
|
||||
users: User[],
|
||||
userNames: string[],
|
||||
oldUsersByNames: Object
|
||||
oldUsersByNames: object,
|
||||
) {
|
||||
const usersByNames = {};
|
||||
|
||||
@@ -326,7 +325,7 @@ function deleteUserInEntries(users: [], userName: string) {
|
||||
const reducerByName = (state: any, username: string, newUserState: any) => {
|
||||
return {
|
||||
...state,
|
||||
[username]: newUserState
|
||||
[username]: newUserState,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -342,19 +341,19 @@ function listReducer(state: any = {}, action: any = {}) {
|
||||
userCreatePermission: !!action.payload._links.create,
|
||||
page: action.payload.page,
|
||||
pageTotal: action.payload.pageTotal,
|
||||
_links: action.payload._links
|
||||
}
|
||||
_links: action.payload._links,
|
||||
},
|
||||
};
|
||||
|
||||
// Delete single user actions
|
||||
case DELETE_USER_SUCCESS:
|
||||
const newUserEntries = deleteUserInEntries(
|
||||
state.entries,
|
||||
action.payload.name
|
||||
action.payload.name,
|
||||
);
|
||||
return {
|
||||
...state,
|
||||
entries: newUserEntries
|
||||
entries: newUserEntries,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
@@ -369,7 +368,7 @@ function byNamesReducer(state: any = {}, action: any = {}) {
|
||||
const userNames = users.map(user => user.name);
|
||||
const byNames = extractUsersByNames(users, userNames, state.byNames);
|
||||
return {
|
||||
...byNames
|
||||
...byNames,
|
||||
};
|
||||
|
||||
// Fetch single user actions
|
||||
@@ -377,10 +376,7 @@ function byNamesReducer(state: any = {}, action: any = {}) {
|
||||
return reducerByName(state, action.payload.name, action.payload);
|
||||
|
||||
case DELETE_USER_SUCCESS:
|
||||
return deleteUserInUsersByNames(
|
||||
state,
|
||||
action.payload.name
|
||||
);
|
||||
return deleteUserInUsersByNames(state, action.payload.name);
|
||||
|
||||
default:
|
||||
return state;
|
||||
@@ -389,19 +385,19 @@ function byNamesReducer(state: any = {}, action: any = {}) {
|
||||
|
||||
export default combineReducers({
|
||||
list: listReducer,
|
||||
byNames: byNamesReducer
|
||||
byNames: byNamesReducer,
|
||||
});
|
||||
|
||||
// selectors
|
||||
|
||||
const selectList = (state: Object) => {
|
||||
const selectList = (state: object) => {
|
||||
if (state.users && state.users.list) {
|
||||
return state.users.list;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
const selectListEntry = (state: Object): Object => {
|
||||
const selectListEntry = (state: object): object => {
|
||||
const list = selectList(state);
|
||||
if (list.entry) {
|
||||
return list.entry;
|
||||
@@ -409,15 +405,15 @@ const selectListEntry = (state: Object): Object => {
|
||||
return {};
|
||||
};
|
||||
|
||||
export const selectListAsCollection = (state: Object): PagedCollection => {
|
||||
export const selectListAsCollection = (state: object): PagedCollection => {
|
||||
return selectListEntry(state);
|
||||
};
|
||||
|
||||
export const isPermittedToCreateUsers = (state: Object): boolean => {
|
||||
export const isPermittedToCreateUsers = (state: object): boolean => {
|
||||
return !!selectListEntry(state).userCreatePermission;
|
||||
};
|
||||
|
||||
export function getUsersFromState(state: Object) {
|
||||
export function getUsersFromState(state: object) {
|
||||
const userNames = selectList(state).entries;
|
||||
if (!userNames) {
|
||||
return null;
|
||||
@@ -431,48 +427,48 @@ export function getUsersFromState(state: Object) {
|
||||
return userEntries;
|
||||
}
|
||||
|
||||
export function isFetchUsersPending(state: Object) {
|
||||
export function isFetchUsersPending(state: object) {
|
||||
return isPending(state, FETCH_USERS);
|
||||
}
|
||||
|
||||
export function getFetchUsersFailure(state: Object) {
|
||||
export function getFetchUsersFailure(state: object) {
|
||||
return getFailure(state, FETCH_USERS);
|
||||
}
|
||||
|
||||
export function isCreateUserPending(state: Object) {
|
||||
export function isCreateUserPending(state: object) {
|
||||
return isPending(state, CREATE_USER);
|
||||
}
|
||||
|
||||
export function getCreateUserFailure(state: Object) {
|
||||
export function getCreateUserFailure(state: object) {
|
||||
return getFailure(state, CREATE_USER);
|
||||
}
|
||||
|
||||
export function getUserByName(state: Object, name: string) {
|
||||
export function getUserByName(state: object, name: string) {
|
||||
if (state.users && state.users.byNames) {
|
||||
return state.users.byNames[name];
|
||||
}
|
||||
}
|
||||
|
||||
export function isFetchUserPending(state: Object, name: string) {
|
||||
export function isFetchUserPending(state: object, name: string) {
|
||||
return isPending(state, FETCH_USER, name);
|
||||
}
|
||||
|
||||
export function getFetchUserFailure(state: Object, name: string) {
|
||||
export function getFetchUserFailure(state: object, name: string) {
|
||||
return getFailure(state, FETCH_USER, name);
|
||||
}
|
||||
|
||||
export function isModifyUserPending(state: Object, name: string) {
|
||||
export function isModifyUserPending(state: object, name: string) {
|
||||
return isPending(state, MODIFY_USER, name);
|
||||
}
|
||||
|
||||
export function getModifyUserFailure(state: Object, name: string) {
|
||||
export function getModifyUserFailure(state: object, name: string) {
|
||||
return getFailure(state, MODIFY_USER, name);
|
||||
}
|
||||
|
||||
export function isDeleteUserPending(state: Object, name: string) {
|
||||
export function isDeleteUserPending(state: object, name: string) {
|
||||
return isPending(state, DELETE_USER, name);
|
||||
}
|
||||
|
||||
export function getDeleteUserFailure(state: Object, name: string) {
|
||||
export function getDeleteUserFailure(state: object, name: string) {
|
||||
return getFailure(state, DELETE_USER, name);
|
||||
}
|
||||
Reference in New Issue
Block a user