Merge branch 'master' of github.com:ONLYOFFICE/CommunityServer-AspNetCore
This commit is contained in:
commit
a643750162
@ -4,14 +4,11 @@ import PropTypes from "prop-types";
|
||||
import { PageLayout, Loader } from "asc-web-components";
|
||||
import { ArticleHeaderContent, ArticleMainButtonContent, ArticleBodyContent } from '../../Article';
|
||||
import { SectionHeaderContent, SectionBodyContent } from './Section';
|
||||
import { setProfile, fetchProfile, resetProfile } from '../../../store/profile/actions';
|
||||
import { fetchProfile } from '../../../store/profile/actions';
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
|
||||
class Profile extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { match, fetchProfile } = this.props;
|
||||
@ -66,6 +63,7 @@ Profile.propTypes = {
|
||||
history: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
profile: PropTypes.object,
|
||||
fetchProfile: PropTypes.func.isRequired,
|
||||
isLoaded: PropTypes.bool
|
||||
};
|
||||
|
||||
@ -76,7 +74,5 @@ function mapStateToProps(state) {
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
setProfile,
|
||||
fetchProfile,
|
||||
resetProfile
|
||||
fetchProfile
|
||||
})(Profile);
|
@ -17,7 +17,7 @@ const DepartmentField = React.memo((props) => {
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
>
|
||||
{departments.map((department) => (
|
||||
{departments && departments.map((department) => (
|
||||
<SelectedItem
|
||||
key={`department_${department.id}`}
|
||||
text={department.name}
|
||||
|
@ -3,7 +3,7 @@ import { withRouter } from 'react-router'
|
||||
import { connect } from 'react-redux'
|
||||
import { Avatar, Button, Textarea, Text, toastr } from 'asc-web-components'
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { toEmployeeWrapper, getUserRole, profileEqual, createProfile } from '../../../../../store/profile/actions';
|
||||
import { toEmployeeWrapper, getUserRole, createProfile } from '../../../../../store/profile/actions';
|
||||
import { MainContainer, AvatarContainer, MainFieldsContainer } from './FormFields/Form'
|
||||
import TextField from './FormFields/TextField'
|
||||
import PasswordField from './FormFields/PasswordField'
|
||||
@ -30,12 +30,14 @@ class CreateUserForm extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (!profileEqual(this.props.profile, prevProps.profile)) {
|
||||
if (this.props.match.params.type !== prevProps.match.params.type) {
|
||||
this.setState(this.mapPropsToState(this.props));
|
||||
}
|
||||
}
|
||||
|
||||
mapPropsToState = (props) => {
|
||||
const isVisitor = props.match.params.type === "guest";
|
||||
|
||||
return {
|
||||
isLoading: false,
|
||||
showPassword: false,
|
||||
@ -45,10 +47,7 @@ class CreateUserForm extends React.Component {
|
||||
email: false,
|
||||
password: false,
|
||||
},
|
||||
profile: {
|
||||
...{ passwordType: "link" },
|
||||
...toEmployeeWrapper(props.profile)
|
||||
}
|
||||
profile: toEmployeeWrapper({ isVisitor: isVisitor})
|
||||
};
|
||||
}
|
||||
|
||||
@ -99,9 +98,9 @@ class CreateUserForm extends React.Component {
|
||||
this.setState({isLoading: true});
|
||||
|
||||
this.props.createProfile(this.state.profile)
|
||||
.then(() => {
|
||||
.then((profile) => {
|
||||
toastr.success("Success");
|
||||
this.props.history.goBack();
|
||||
this.props.history.push(`${this.props.settings.homepage}/view/${profile.userName}`);
|
||||
})
|
||||
.catch((error) => {
|
||||
toastr.error(error.message)
|
||||
@ -110,7 +109,7 @@ class CreateUserForm extends React.Component {
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
this.props.history.goBack();
|
||||
this.props.history.push(this.props.settings.homepage)
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -236,7 +235,7 @@ class CreateUserForm extends React.Component {
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
profile: state.profile.targetUser
|
||||
settings: state.auth.settings
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { withRouter } from 'react-router'
|
||||
import { connect } from 'react-redux'
|
||||
import { Avatar, Button, Textarea, Text, toastr, ModalDialog } from 'asc-web-components'
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { toEmployeeWrapper, getUserRole, profileEqual, updateProfile } from '../../../../../store/profile/actions';
|
||||
import { toEmployeeWrapper, getUserRole, updateProfile } from '../../../../../store/profile/actions';
|
||||
import { MainContainer, AvatarContainer, MainFieldsContainer } from './FormFields/Form'
|
||||
import TextField from './FormFields/TextField'
|
||||
import TextChangeField from './FormFields/TextChangeField'
|
||||
@ -32,7 +32,7 @@ class UpdateUserForm extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (!profileEqual(this.props.profile, prevProps.profile)) {
|
||||
if (this.props.match.params.userId !== prevProps.match.params.userId) {
|
||||
this.setState(this.mapPropsToState(this.props));
|
||||
}
|
||||
}
|
||||
@ -47,10 +47,7 @@ class UpdateUserForm extends React.Component {
|
||||
email: false,
|
||||
password: false,
|
||||
},
|
||||
profile: {
|
||||
...{ passwordType: "link" },
|
||||
...toEmployeeWrapper(props.profile)
|
||||
}
|
||||
profile: toEmployeeWrapper(props.profile)
|
||||
};
|
||||
}
|
||||
|
||||
@ -97,9 +94,9 @@ class UpdateUserForm extends React.Component {
|
||||
this.setState({isLoading: true});
|
||||
|
||||
this.props.updateProfile(this.state.profile)
|
||||
.then(() => {
|
||||
.then((profile) => {
|
||||
toastr.success("Success");
|
||||
this.props.history.goBack();
|
||||
this.props.history.push(`${this.props.settings.homepage}/view/${profile.userName}`);
|
||||
})
|
||||
.catch((error) => {
|
||||
toastr.error(error.message)
|
||||
@ -256,7 +253,8 @@ class UpdateUserForm extends React.Component {
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
profile: state.profile.targetUser
|
||||
profile: state.profile.targetUser,
|
||||
settings: state.auth.settings
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,14 +15,17 @@ const Header = styled(Text.ContentHeader)`
|
||||
`;
|
||||
|
||||
const SectionHeaderContent = (props) => {
|
||||
const {profile, history, settings} = props;
|
||||
const { profile, history, settings, match } = props;
|
||||
const { type } = match.params;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const headerText = profile && profile.displayName
|
||||
? profile.displayName
|
||||
: profile.isVisitor
|
||||
const headerText = type
|
||||
? type === "guest"
|
||||
? t('NewGuest')
|
||||
: t('NewEmployee');
|
||||
: t('NewEmployee')
|
||||
: profile
|
||||
? profile.displayName
|
||||
: "";
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
history.push(settings.homepage)
|
||||
|
@ -4,31 +4,27 @@ import PropTypes from "prop-types";
|
||||
import { PageLayout, Loader } from "asc-web-components";
|
||||
import { ArticleHeaderContent, ArticleMainButtonContent, ArticleBodyContent } from '../../Article';
|
||||
import { SectionHeaderContent, CreateUserForm, UpdateUserForm } from './Section';
|
||||
import { setProfile, fetchProfile, resetProfile } from '../../../store/profile/actions';
|
||||
import { fetchProfile } from '../../../store/profile/actions';
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
|
||||
class ProfileAction extends React.Component {
|
||||
componentDidMount() {
|
||||
const { match, setProfile, fetchProfile } = this.props;
|
||||
const { userId, type } = match.params;
|
||||
|
||||
if (!userId) {
|
||||
setProfile({ isVisitor: type === "guest" });
|
||||
} else {
|
||||
componentDidMount() {
|
||||
const { match, fetchProfile } = this.props;
|
||||
const { userId } = match.params;
|
||||
|
||||
if (userId) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { match, setProfile, fetchProfile } = this.props;
|
||||
const { userId, type } = match.params;
|
||||
const { match, fetchProfile } = this.props;
|
||||
const { userId } = match.params;
|
||||
const prevUserId = prevProps.match.params.userId;
|
||||
const prevType = prevProps.match.params.type;
|
||||
|
||||
if (!userId && type !== prevType) {
|
||||
setProfile({ isVisitor: type === "guest" });
|
||||
} else if (userId !== prevUserId) {
|
||||
if (userId !== undefined && userId !== prevUserId) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
}
|
||||
@ -36,17 +32,17 @@ class ProfileAction extends React.Component {
|
||||
render() {
|
||||
console.log("ProfileAction render")
|
||||
|
||||
const { profile } = this.props;
|
||||
const { profile, match } = this.props;
|
||||
|
||||
return (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
{profile
|
||||
{profile || match.params.type
|
||||
? <PageLayout
|
||||
articleHeaderContent={<ArticleHeaderContent />}
|
||||
articleMainButtonContent={<ArticleMainButtonContent />}
|
||||
articleBodyContent={<ArticleBodyContent />}
|
||||
sectionHeaderContent={<SectionHeaderContent />}
|
||||
sectionBodyContent={profile.id ? <UpdateUserForm /> : <CreateUserForm />}
|
||||
sectionBodyContent={match.params.type ? <CreateUserForm /> : <UpdateUserForm />}
|
||||
/>
|
||||
: <PageLayout
|
||||
articleHeaderContent={<ArticleHeaderContent />}
|
||||
@ -62,9 +58,7 @@ class ProfileAction extends React.Component {
|
||||
ProfileAction.propTypes = {
|
||||
match: PropTypes.object.isRequired,
|
||||
profile: PropTypes.object,
|
||||
setProfile: PropTypes.func.isRequired,
|
||||
fetchProfile: PropTypes.func.isRequired,
|
||||
resetProfile: PropTypes.func.isRequired
|
||||
fetchProfile: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
@ -74,7 +68,5 @@ function mapStateToProps(state) {
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, {
|
||||
setProfile,
|
||||
fetchProfile,
|
||||
resetProfile
|
||||
fetchProfile
|
||||
})(ProfileAction);
|
@ -33,32 +33,6 @@ export function getUserRole(profile) {
|
||||
return "user";
|
||||
};
|
||||
|
||||
export function profileEqual(profileA, profileB) {
|
||||
const keys = Object.keys(profileA);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let key = keys[i];
|
||||
|
||||
if (key === "groups") {
|
||||
if (profileA[key].length !== profileB[key].length)
|
||||
return false;
|
||||
|
||||
const groupsA = profileA[key].map(group => group.id);
|
||||
const groupsB = profileA[key].map(group => group.id);
|
||||
|
||||
for (let j = 0; j < groupsA.length; j++) {
|
||||
if (!groupsB.includes(groupsA[j]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(profileA[key] !== profileB[key])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function toEmployeeWrapper(profile) {
|
||||
const emptyData = {
|
||||
id: "",
|
||||
@ -68,6 +42,7 @@ export function toEmployeeWrapper(profile) {
|
||||
password: "",
|
||||
birthday: "",
|
||||
sex: "male",
|
||||
passwordType: "link",
|
||||
workFrom: "",
|
||||
location: "",
|
||||
title: "",
|
||||
@ -111,12 +86,16 @@ export function createProfile(profile) {
|
||||
const {people} = getState();
|
||||
const {filter} = people;
|
||||
const member = employeeWrapperToMemberModel(profile);
|
||||
let result;
|
||||
|
||||
return api.createUser(member).then(res => {
|
||||
checkResponseError(res);
|
||||
return Promise.resolve(dispatch(setProfile(res.data.response)));
|
||||
result = res.data.response;
|
||||
return dispatch(setProfile(result));
|
||||
}).then(() => {
|
||||
return fetchPeopleByFilter(dispatch, filter);
|
||||
}).then(() => {
|
||||
return Promise.resolve(result);
|
||||
});
|
||||
};
|
||||
};
|
||||
@ -126,12 +105,16 @@ export function updateProfile(profile) {
|
||||
const {people} = getState();
|
||||
const {filter} = people;
|
||||
const member = employeeWrapperToMemberModel(profile);
|
||||
let result;
|
||||
|
||||
return api.updateUser(member).then(res => {
|
||||
checkResponseError(res);
|
||||
return Promise.resolve(dispatch(setProfile(res.data.response)));
|
||||
result = res.data.response;
|
||||
return Promise.resolve(dispatch(setProfile(result)));
|
||||
}).then(() => {
|
||||
return fetchPeopleByFilter(dispatch, filter);
|
||||
}).then(() => {
|
||||
return Promise.resolve(result);
|
||||
});
|
||||
};
|
||||
};
|
@ -27,7 +27,26 @@ or
|
||||
{toastr.success('Some text for toast')}
|
||||
</Toast>
|
||||
```
|
||||
You can use simple html tags. For this action you should wrap your message by empty tags:
|
||||
```js
|
||||
|
||||
<Toast />
|
||||
<button onClick={() => toastr.success(<>You have <b>bold text</b></>)}>Click</button>
|
||||
```
|
||||
|
||||
If your notification include only text in html tags or data in JSX tags, you can omit empty tags:
|
||||
```js
|
||||
|
||||
<Toast />
|
||||
<button onClick={() => toastr.success(<b>Bold text</b>)}>Click</button>
|
||||
```
|
||||
|
||||
```js
|
||||
import { Text } from 'asc-web-components';
|
||||
|
||||
<Toast />
|
||||
<button onClick={() => toastr.success(<Text.Body>The email activation instructions have been sent to the <b>{user.email}</b> email address</Text.Body>))}>Click</button>
|
||||
```
|
||||
|
||||
#### Properties
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user