Client: delete useless
This commit is contained in:
parent
00d281fba1
commit
f69bf45e31
@ -8,7 +8,6 @@ import AppLoader from "@docspace/common/components/AppLoader";
|
||||
import { /*combineUrl,*/ updateTempContent } from "@docspace/common/utils";
|
||||
import Home from "./AccountsHome";
|
||||
import Profile from "./Profile";
|
||||
import ProfileAction from "./ProfileAction";
|
||||
|
||||
import Filter from "@docspace/common/api/people/filter";
|
||||
import { showLoader, hideLoader } from "@docspace/common/utils";
|
||||
@ -23,17 +22,6 @@ const PeopleSection = React.memo(() => {
|
||||
path={["/accounts/view/:userId"]}
|
||||
component={Profile}
|
||||
/>
|
||||
<PrivateRoute
|
||||
path={["/accounts/edit/:userId"]}
|
||||
restricted
|
||||
allowForMe
|
||||
component={ProfileAction}
|
||||
/>
|
||||
<PrivateRoute
|
||||
path={["/accounts/create/:type"]}
|
||||
restricted
|
||||
component={ProfileAction}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={["/accounts"]}
|
||||
|
@ -1,39 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import Backend from "@docspace/common/utils/i18next-http-backend";
|
||||
import { LANGUAGE } from "@docspace/common/constants";
|
||||
import config from "PACKAGE_FILE";
|
||||
import { loadLanguagePath } from "@docspace/common/utils";
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: localStorage.getItem(LANGUAGE) || "en",
|
||||
fallbackLng: "en",
|
||||
load: "currentOnly",
|
||||
//debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === "lowercase") return value.toLowerCase();
|
||||
return value;
|
||||
},
|
||||
},
|
||||
|
||||
backend: {
|
||||
loadPath: loadLanguagePath(config.homepage),
|
||||
},
|
||||
|
||||
ns: ["Profile", "ProfileAction", "Common"],
|
||||
defaultNS: "Profile",
|
||||
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default newInstance;
|
@ -1,161 +0,0 @@
|
||||
import React from "react";
|
||||
import MyProfileI18n from "./i18n";
|
||||
import PeopleStore from "../../store/PeopleStore";
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import Section from "@docspace/common/components/Section";
|
||||
import toastr from "client/toastr";
|
||||
import { withRouter } from "react-router";
|
||||
|
||||
import { Provider as PeopleProvider, inject, observer } from "mobx-react";
|
||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||
import {
|
||||
SectionBodyContent as ViewBodyContent,
|
||||
SectionHeaderContent as ViewHeaderContent,
|
||||
} from "../Profile/Section";
|
||||
import { SectionHeaderContent as EditHeaderContent } from "../ProfileAction/Section";
|
||||
import EditBodyContent from "../ProfileAction/Section/Body";
|
||||
import Link from "@docspace/components/link";
|
||||
import { Trans } from "react-i18next";
|
||||
|
||||
class My extends React.Component {
|
||||
componentDidMount() {
|
||||
const {
|
||||
fetchProfile,
|
||||
profile,
|
||||
location,
|
||||
t,
|
||||
setDocumentTitle,
|
||||
setLoadedProfile,
|
||||
setIsLoading,
|
||||
setFirstLoad,
|
||||
} = this.props;
|
||||
|
||||
setDocumentTitle(t("Common:Profile"));
|
||||
setFirstLoad(false);
|
||||
|
||||
const queryString = ((location && location.search) || "").slice(1);
|
||||
const queryParams = queryString.split("&");
|
||||
const arrayOfQueryParams = queryParams.map((queryParam) =>
|
||||
queryParam.split("=")
|
||||
);
|
||||
const linkParams = Object.fromEntries(arrayOfQueryParams);
|
||||
|
||||
if (linkParams.email_change && linkParams.email_change === "success") {
|
||||
toastr.success(t("ChangeEmailSuccess"));
|
||||
}
|
||||
|
||||
if (!profile) {
|
||||
setIsLoading(true);
|
||||
setLoadedProfile(false);
|
||||
fetchProfile("@self").finally(() => {
|
||||
setIsLoading(false);
|
||||
setLoadedProfile(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.resetProfile();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { tipsSubscription, t, changeEmailSubscription } = this.props;
|
||||
if (location?.search !== "?unsubscribe=tips" || tipsSubscription === null)
|
||||
return;
|
||||
|
||||
if (!tipsSubscription) {
|
||||
window.history.replaceState("", "", window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
changeEmailSubscription(false)
|
||||
.then(() => {
|
||||
window.history.replaceState("", "", window.location.pathname);
|
||||
toastr.success(
|
||||
<Trans t={t} i18nKey="SubscriptionTurnOffToast" ns="Profile">
|
||||
You have been successfully unsubscribed from the the mailing list.
|
||||
<Link
|
||||
color="#5387AD"
|
||||
isHovered={true}
|
||||
onClick={() => {
|
||||
changeEmailSubscription(true);
|
||||
toastr.clear();
|
||||
}}
|
||||
>
|
||||
Subscribe again
|
||||
</Link>
|
||||
</Trans>,
|
||||
null,
|
||||
0,
|
||||
true,
|
||||
true
|
||||
);
|
||||
})
|
||||
.catch((e) => console.error(e));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { tReady, location } = this.props;
|
||||
|
||||
const isEdit = (location && location.search === "?action=edit") || false;
|
||||
|
||||
//console.log("My Profile render", this.props, isEdit);
|
||||
|
||||
return (
|
||||
<Section withBodyAutoFocus>
|
||||
<Section.SectionHeader>
|
||||
{isEdit ? (
|
||||
<EditHeaderContent isMy={true} tReady={tReady} />
|
||||
) : (
|
||||
<ViewHeaderContent isMy={true} tReady={tReady} />
|
||||
)}
|
||||
</Section.SectionHeader>
|
||||
|
||||
<Section.SectionBody>
|
||||
{isEdit ? (
|
||||
<EditBodyContent isMy={true} tReady={tReady} />
|
||||
) : (
|
||||
<ViewBodyContent isMy={true} tReady={tReady} />
|
||||
)}
|
||||
</Section.SectionBody>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
My.propTypes = {
|
||||
fetchProfile: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
profile: PropTypes.object,
|
||||
language: PropTypes.string,
|
||||
};
|
||||
|
||||
const MyProfile = withRouter(
|
||||
inject(({ auth, peopleStore }) => ({
|
||||
setDocumentTitle: auth.setDocumentTitle,
|
||||
language: auth.language,
|
||||
resetProfile: peopleStore.targetUserStore.resetTargetUser,
|
||||
fetchProfile: peopleStore.targetUserStore.getTargetUser,
|
||||
profile: peopleStore.targetUserStore.targetUser,
|
||||
setLoadedProfile: peopleStore.loadingStore.setLoadedProfile,
|
||||
setIsLoading: peopleStore.loadingStore.setIsLoading,
|
||||
setFirstLoad: peopleStore.loadingStore.setFirstLoad,
|
||||
tipsSubscription: peopleStore.targetUserStore.tipsSubscription,
|
||||
changeEmailSubscription:
|
||||
peopleStore.targetUserStore.changeEmailSubscription,
|
||||
}))(withTranslation(["Profile", "ProfileAction"])(observer(My)))
|
||||
);
|
||||
|
||||
const peopleStore = new PeopleStore();
|
||||
|
||||
export default ({ i18n, ...rest }) => {
|
||||
return (
|
||||
<PeopleProvider peopleStore={peopleStore}>
|
||||
<I18nextProvider i18n={MyProfileI18n}>
|
||||
<MyProfile {...rest} />
|
||||
</I18nextProvider>
|
||||
</PeopleProvider>
|
||||
);
|
||||
};
|
@ -12,7 +12,6 @@ import { withTranslation } from "react-i18next";
|
||||
class Profile extends React.Component {
|
||||
componentDidMount() {
|
||||
const {
|
||||
match,
|
||||
fetchProfile,
|
||||
profile,
|
||||
location,
|
||||
@ -23,13 +22,11 @@ class Profile extends React.Component {
|
||||
setIsEditTargetUser,
|
||||
setLoadedProfile,
|
||||
} = this.props;
|
||||
let { userId } = match.params;
|
||||
const userId = "@self";
|
||||
|
||||
setFirstLoad(false);
|
||||
setIsEditTargetUser(false);
|
||||
|
||||
if (!userId) userId = "@self";
|
||||
|
||||
setDocumentTitle(t("Common:Profile"));
|
||||
this.documentElement = document.getElementsByClassName("hidingHeader");
|
||||
const queryString = ((location && location.search) || "").slice(1);
|
||||
|
@ -1,79 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import ComboBox from "@docspace/components/combobox";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
import IconButton from "@docspace/components/icon-button";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
margin: 0 0 16px 0;
|
||||
align-items: center;
|
||||
|
||||
.remove_icon {
|
||||
padding-left: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
class ContactField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isDisabled,
|
||||
|
||||
comboBoxName,
|
||||
comboBoxOptions,
|
||||
comboBoxSelectedOption,
|
||||
comboBoxOnChange,
|
||||
|
||||
inputName,
|
||||
inputValue,
|
||||
inputOnChange,
|
||||
|
||||
removeButtonName,
|
||||
removeButtonOnChange,
|
||||
} = this.props;
|
||||
|
||||
const setDropDownMaxHeight =
|
||||
comboBoxOptions && comboBoxOptions.length > 6
|
||||
? { dropDownMaxHeight: 200 }
|
||||
: {};
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<ComboBox
|
||||
name={comboBoxName}
|
||||
options={comboBoxOptions}
|
||||
onSelect={comboBoxOnChange}
|
||||
selectedOption={comboBoxSelectedOption}
|
||||
isDisabled={isDisabled}
|
||||
scaled={true}
|
||||
directionY="both"
|
||||
className="field-select"
|
||||
scaledOptions={comboBoxOptions.length < 7}
|
||||
{...setDropDownMaxHeight}
|
||||
/>
|
||||
<TextInput
|
||||
name={inputName}
|
||||
value={inputValue}
|
||||
isDisabled={isDisabled}
|
||||
onChange={inputOnChange}
|
||||
/>
|
||||
<IconButton
|
||||
id={removeButtonName}
|
||||
className="remove_icon"
|
||||
size="16"
|
||||
onClick={removeButtonOnChange}
|
||||
iconName={"/static/images/catalog.trash.react.svg"}
|
||||
isFill={true}
|
||||
isClickable={true}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ContactField;
|
@ -1,118 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import ContactField from "./ContactField";
|
||||
import ComboBox from "@docspace/components/combobox";
|
||||
|
||||
const Container = styled.div`
|
||||
width: 100%;
|
||||
max-width: 450px;
|
||||
|
||||
.field-select {
|
||||
width: 120px;
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const getOptions = (patterns, keyPrefix) => {
|
||||
return patterns.map((item, index) => {
|
||||
return {
|
||||
key: keyPrefix + index,
|
||||
label: item.type, //from resource
|
||||
icon: item.icon,
|
||||
value: item.type,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const renderItems = (
|
||||
contacts,
|
||||
pattern,
|
||||
onTypeChange,
|
||||
onTextChange,
|
||||
onRemove,
|
||||
isDisabled
|
||||
) => {
|
||||
const items = contacts.map((contact, index) => {
|
||||
const prefix = contact.id + "_";
|
||||
const itemOptions = getOptions(pattern, prefix);
|
||||
const itemSelectedOption = itemOptions.filter(
|
||||
(option) => option.value === contact.type
|
||||
)[0];
|
||||
|
||||
return (
|
||||
<ContactField
|
||||
key={prefix + "item_" + index}
|
||||
isDisabled={isDisabled}
|
||||
comboBoxName={prefix + "type"}
|
||||
comboBoxOptions={itemOptions}
|
||||
comboBoxSelectedOption={itemSelectedOption}
|
||||
comboBoxOnChange={onTypeChange}
|
||||
inputName={prefix + "value"}
|
||||
inputValue={contact.value}
|
||||
inputOnChange={onTextChange}
|
||||
removeButtonName={prefix + "remove"}
|
||||
removeButtonOnChange={onRemove}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
class ContactsField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
pattern,
|
||||
contacts,
|
||||
addItemText,
|
||||
onItemAdd,
|
||||
onItemTypeChange,
|
||||
onItemTextChange,
|
||||
onItemRemove,
|
||||
isDisabled,
|
||||
} = this.props;
|
||||
|
||||
const existItems = renderItems(
|
||||
contacts,
|
||||
pattern,
|
||||
onItemTypeChange,
|
||||
onItemTextChange,
|
||||
onItemRemove,
|
||||
isDisabled
|
||||
);
|
||||
|
||||
const prefix = "null_";
|
||||
const options = getOptions(pattern, prefix);
|
||||
const setDropDownMaxHeight =
|
||||
options && options.length > 6 ? { dropDownMaxHeight: 200 } : {};
|
||||
|
||||
return (
|
||||
<Container>
|
||||
{existItems}
|
||||
<ComboBox
|
||||
options={options}
|
||||
onSelect={onItemAdd}
|
||||
scaledOptions={options.length < 6}
|
||||
selectedOption={{
|
||||
key: prefix,
|
||||
label: addItemText,
|
||||
value: "",
|
||||
default: true,
|
||||
}}
|
||||
isDisabled={isDisabled}
|
||||
scaled={true}
|
||||
className="field-select"
|
||||
directionY="both"
|
||||
{...setDropDownMaxHeight}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ContactsField;
|
@ -1,56 +0,0 @@
|
||||
import React from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import DatePicker from "@docspace/components/date-picker";
|
||||
|
||||
class DateField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
calendarHeaderContent,
|
||||
inputName,
|
||||
inputClassName,
|
||||
inputValue,
|
||||
inputIsDisabled,
|
||||
inputOnChange,
|
||||
inputTabIndex,
|
||||
calendarMinDate,
|
||||
calendarMaxDate,
|
||||
locale,
|
||||
maxLabelWidth,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
maxLabelWidth={maxLabelWidth}
|
||||
>
|
||||
<DatePicker
|
||||
inputClassName={inputClassName}
|
||||
name={inputName}
|
||||
selectedDate={inputValue}
|
||||
isDisabled={inputIsDisabled}
|
||||
onChange={inputOnChange}
|
||||
hasError={hasError}
|
||||
tabIndex={inputTabIndex}
|
||||
displayType="dropdown"
|
||||
calendarHeaderContent={calendarHeaderContent}
|
||||
minDate={calendarMinDate ? calendarMinDate : new Date("1900/01/01")}
|
||||
maxDate={calendarMaxDate ? calendarMaxDate : new Date()}
|
||||
locale={locale}
|
||||
fixedDirection={true}
|
||||
/>
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DateField;
|
@ -1,77 +0,0 @@
|
||||
import React from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import SelectorAddButton from "@docspace/components/selector-add-button";
|
||||
import SelectedItem from "@docspace/components/selected-item";
|
||||
import GroupSelector from "../../../../../components/GroupSelector";
|
||||
|
||||
class DepartmentField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
onRemoveGroup = (e) => {
|
||||
const groupId = e.currentTarget.parentElement.dataset.id;
|
||||
this.props.onRemoveGroup(groupId);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
isDisabled,
|
||||
hasError,
|
||||
labelText,
|
||||
|
||||
showGroupSelectorButtonTitle,
|
||||
|
||||
onShowGroupSelector,
|
||||
onCloseGroupSelector,
|
||||
|
||||
selectorIsVisible,
|
||||
selectorSelectedOptions,
|
||||
selectorOnSelectGroups,
|
||||
maxLabelWidth,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
className="departments-field"
|
||||
maxLabelWidth={maxLabelWidth}
|
||||
>
|
||||
<SelectorAddButton
|
||||
isDisabled={isDisabled}
|
||||
title={showGroupSelectorButtonTitle}
|
||||
onClick={onShowGroupSelector}
|
||||
className="department-add-btn"
|
||||
/>
|
||||
{selectorIsVisible && (
|
||||
<GroupSelector
|
||||
isOpen={selectorIsVisible}
|
||||
isMultiSelect={true}
|
||||
onSelect={selectorOnSelectGroups}
|
||||
onCancel={onCloseGroupSelector}
|
||||
onArrowClick={onCloseGroupSelector}
|
||||
showCounter
|
||||
selectedOptions={selectorSelectedOptions}
|
||||
/>
|
||||
)}
|
||||
{selectorSelectedOptions.map((option) => (
|
||||
<SelectedItem
|
||||
key={`department_${option.key}`}
|
||||
text={option.label}
|
||||
data-id={option.key}
|
||||
onClose={this.onRemoveGroup}
|
||||
isInline={true}
|
||||
className="department-item"
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
))}
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DepartmentField;
|
@ -1,53 +0,0 @@
|
||||
import React from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import EmailInput from "@docspace/components/email-input";
|
||||
|
||||
class EmailField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
emailSettings,
|
||||
|
||||
inputName,
|
||||
inputValue,
|
||||
inputOnChange,
|
||||
inputTabIndex,
|
||||
placeholder,
|
||||
scale,
|
||||
inputIsDisabled,
|
||||
onValidateInput,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
>
|
||||
<EmailInput
|
||||
className="field-input"
|
||||
name={inputName}
|
||||
value={inputValue}
|
||||
onChange={inputOnChange}
|
||||
emailSettings={emailSettings}
|
||||
tabIndex={inputTabIndex}
|
||||
placeholder={placeholder}
|
||||
scale={scale}
|
||||
autoComplete="email"
|
||||
isDisabled={inputIsDisabled}
|
||||
onValidateInput={onValidateInput}
|
||||
hasError={hasError}
|
||||
/>
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EmailField;
|
@ -1,54 +0,0 @@
|
||||
import styled from "styled-components";
|
||||
import { tablet } from "@docspace/components/utils/device";
|
||||
import NoUserSelect from "@docspace/components/utils/commonStyles";
|
||||
|
||||
const MainContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.field-input {
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
|
||||
label:not(:first-child) {
|
||||
margin-left: 33px;
|
||||
}
|
||||
}
|
||||
|
||||
.departments-field {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
max-width: 835px;
|
||||
|
||||
.department-add-btn {
|
||||
margin: 0 8px 8px 0;
|
||||
float: left;
|
||||
}
|
||||
.department-item {
|
||||
margin: 0 8px 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
flex-direction: column;
|
||||
}
|
||||
`;
|
||||
|
||||
const AvatarContainer = styled.div`
|
||||
margin: 0 32px 32px 0;
|
||||
width: 160px;
|
||||
`;
|
||||
|
||||
const MainFieldsContainer = styled.div`
|
||||
flex-grow: 1;
|
||||
${(props) => props.noSelect && NoUserSelect}
|
||||
margin: ${(props) =>
|
||||
`0 0 ${props.marginBottom ? props.marginBottom : "40px"} 0`};
|
||||
`;
|
||||
|
||||
export { MainContainer, AvatarContainer, MainFieldsContainer };
|
@ -1,35 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import Heading from "@docspace/components/heading";
|
||||
import PropTypes from "prop-types";
|
||||
const Container = styled.div`
|
||||
margin: ${(props) => `0 0 ${props.marginBottom} 0`};
|
||||
max-width: 1024px;
|
||||
`;
|
||||
|
||||
const StyledHeader = styled(Heading)`
|
||||
margin: 0 0 24px 0;
|
||||
line-height: unset;
|
||||
`;
|
||||
|
||||
const InfoFieldContainer = React.memo((props) => {
|
||||
const { headerText, children, marginBottom } = props;
|
||||
|
||||
return (
|
||||
<Container marginBottom={marginBottom}>
|
||||
<StyledHeader level={2} size="small">
|
||||
{headerText}
|
||||
</StyledHeader>
|
||||
{children}
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
|
||||
InfoFieldContainer.propTypes = {
|
||||
marginBottom: PropTypes.string,
|
||||
};
|
||||
|
||||
InfoFieldContainer.defaultProps = {
|
||||
marginBottom: "40px",
|
||||
};
|
||||
export default InfoFieldContainer;
|
@ -1,82 +0,0 @@
|
||||
import React from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import RadioButtonGroup from "@docspace/components/radio-button-group";
|
||||
import PasswordInput from "@docspace/components/password-input";
|
||||
import { PasswordLimitSpecialCharacters } from "@docspace/common/constants";
|
||||
|
||||
class PasswordField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
passwordSettings,
|
||||
|
||||
radioName,
|
||||
radioValue,
|
||||
radioOptions,
|
||||
radioIsDisabled,
|
||||
radioOnChange,
|
||||
|
||||
inputName,
|
||||
emailInputName,
|
||||
inputValue,
|
||||
inputIsDisabled,
|
||||
inputOnChange,
|
||||
inputTabIndex,
|
||||
|
||||
copyLinkText,
|
||||
copiedResourceText,
|
||||
t,
|
||||
} = this.props;
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
>
|
||||
<RadioButtonGroup
|
||||
name={radioName}
|
||||
selected={radioValue}
|
||||
options={radioOptions}
|
||||
isDisabled={radioIsDisabled}
|
||||
onClick={radioOnChange}
|
||||
className="radio-group"
|
||||
spacing="33px"
|
||||
/>
|
||||
<PasswordInput
|
||||
inputName={inputName}
|
||||
emailInputName={emailInputName}
|
||||
inputValue={inputValue}
|
||||
inputWidth="320px"
|
||||
inputTabIndex={inputTabIndex}
|
||||
onChange={inputOnChange}
|
||||
clipActionResource={copyLinkText}
|
||||
clipCopiedResource={copiedResourceText}
|
||||
clipEmailResource={`${t("Common:Email")}: `}
|
||||
clipPasswordResource={`${t("Common:Password")}: `}
|
||||
tooltipPasswordTitle={`${t("Common:PasswordLimitMessage")}:`}
|
||||
tooltipPasswordLength={`${t("Common:PasswordLimitLength", {
|
||||
fromNumber: passwordSettings ? passwordSettings.minLength : 8,
|
||||
toNumber: 30,
|
||||
})}`}
|
||||
tooltipPasswordDigits={`${t("Common:PasswordLimitDigits")}`}
|
||||
tooltipPasswordCapital={`${t("Common:PasswordLimitUpperCase")}`}
|
||||
tooltipPasswordSpecial={`${t(
|
||||
"Common:PasswordLimitSpecialSymbols"
|
||||
)} (${PasswordLimitSpecialCharacters})`}
|
||||
generatorSpecial={PasswordLimitSpecialCharacters}
|
||||
passwordSettings={passwordSettings}
|
||||
isDisabled={inputIsDisabled}
|
||||
/>
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PasswordField;
|
@ -1,51 +0,0 @@
|
||||
import React from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import RadioButtonGroup from "@docspace/components/radio-button-group";
|
||||
|
||||
class RadioField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
|
||||
radioName,
|
||||
radioValue,
|
||||
radioOptions,
|
||||
radioIsDisabled,
|
||||
radioOnChange,
|
||||
|
||||
tooltipContent,
|
||||
helpButtonHeaderContent,
|
||||
maxLabelWidth,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
tooltipContent={tooltipContent}
|
||||
helpButtonHeaderContent={helpButtonHeaderContent}
|
||||
maxLabelWidth={maxLabelWidth}
|
||||
>
|
||||
<RadioButtonGroup
|
||||
name={radioName}
|
||||
selected={radioValue}
|
||||
options={radioOptions}
|
||||
isDisabled={radioIsDisabled}
|
||||
onClick={radioOnChange}
|
||||
className="radio-group"
|
||||
spacing="33px"
|
||||
/>
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default RadioField;
|
@ -1,73 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
import Button from "@docspace/components/button";
|
||||
|
||||
const InputContainer = styled.div`
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
class TextChangeField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
|
||||
inputName,
|
||||
inputValue,
|
||||
inputTabIndex,
|
||||
|
||||
buttonText,
|
||||
buttonIsDisabled,
|
||||
buttonOnClick,
|
||||
buttonTabIndex,
|
||||
|
||||
tooltipContent,
|
||||
helpButtonHeaderContent,
|
||||
maxLabelWidth,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
labelText={labelText}
|
||||
tooltipContent={tooltipContent}
|
||||
helpButtonHeaderContent={helpButtonHeaderContent}
|
||||
maxLabelWidth={maxLabelWidth}
|
||||
offsetRight={100}
|
||||
tooltipMaxWidth="300px"
|
||||
>
|
||||
<InputContainer>
|
||||
<TextInput
|
||||
name={inputName}
|
||||
value={inputValue}
|
||||
isDisabled={true}
|
||||
hasError={hasError}
|
||||
tabIndex={inputTabIndex}
|
||||
/>
|
||||
<Button
|
||||
label={buttonText}
|
||||
onClick={buttonOnClick}
|
||||
isDisabled={buttonIsDisabled}
|
||||
size="small"
|
||||
style={{ marginLeft: "8px" }}
|
||||
tabIndex={buttonTabIndex}
|
||||
/>
|
||||
</InputContainer>
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextChangeField;
|
@ -1,56 +0,0 @@
|
||||
import React from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
|
||||
class TextField extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !equal(this.props, nextProps);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isRequired,
|
||||
hasError,
|
||||
labelText,
|
||||
errorMessage,
|
||||
|
||||
inputName,
|
||||
inputValue,
|
||||
inputIsDisabled,
|
||||
inputOnChange,
|
||||
inputAutoFocussed,
|
||||
inputTabIndex,
|
||||
tooltipContent,
|
||||
helpButtonHeaderContent,
|
||||
maxLength,
|
||||
maxLabelWidth,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<FieldContainer
|
||||
isRequired={isRequired}
|
||||
hasError={hasError}
|
||||
errorMessage={errorMessage}
|
||||
labelText={labelText}
|
||||
tooltipContent={tooltipContent}
|
||||
helpButtonHeaderContent={helpButtonHeaderContent}
|
||||
maxLabelWidth={maxLabelWidth}
|
||||
>
|
||||
<TextInput
|
||||
name={inputName}
|
||||
value={inputValue}
|
||||
isDisabled={inputIsDisabled}
|
||||
onChange={inputOnChange}
|
||||
hasError={hasError}
|
||||
className="field-input"
|
||||
isAutoFocussed={inputAutoFocussed}
|
||||
tabIndex={inputTabIndex}
|
||||
maxLength={maxLength}
|
||||
/>
|
||||
</FieldContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextField;
|
@ -1,340 +0,0 @@
|
||||
import React from "react";
|
||||
import { withRouter } from "react-router";
|
||||
import styled from "styled-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import AvatarEditor from "@docspace/components/avatar-editor";
|
||||
import Loader from "@docspace/components/loader";
|
||||
import { isTablet, isMobile } from "@docspace/components/utils/device";
|
||||
import {
|
||||
createThumbnailsAvatar,
|
||||
loadAvatar,
|
||||
deleteAvatar,
|
||||
} from "@docspace/common/api/people";
|
||||
import toastr from "client/toastr";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { toEmployeeWrapper } from "../../../../helpers/people-helpers";
|
||||
|
||||
const dialogsDataset = {
|
||||
changeEmail: "changeEmail",
|
||||
changePassword: "changePassword",
|
||||
changePhone: "changePhone",
|
||||
};
|
||||
|
||||
const AvatarEditorBody = styled.div`
|
||||
${isMobile() && "margin-left: -8px"}
|
||||
margin-bottom: 24px;
|
||||
`;
|
||||
|
||||
class AvatarEditorPage extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = this.mapPropsToState(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { match, fetchProfile, t, profile, setDocumentTitle } = this.props;
|
||||
const { avatar } = this.state;
|
||||
const { userId } = match.params;
|
||||
|
||||
setDocumentTitle(t("ProfileAction"));
|
||||
if (userId && !profile) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
|
||||
if (avatar.image === undefined) {
|
||||
this.setUserPhotoToState();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { match, fetchProfile /*, profile*/ } = this.props;
|
||||
const { userId } = match.params;
|
||||
const { avatar } = this.state;
|
||||
const prevUserId = prevProps.match.params.userId;
|
||||
|
||||
if (userId !== undefined && userId !== prevUserId) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
|
||||
if (avatar.image === undefined) {
|
||||
this.setUserPhotoToState();
|
||||
}
|
||||
}
|
||||
|
||||
onCancel = () => {
|
||||
const { toggleAvatarEditor } = this.props;
|
||||
toggleAvatarEditor(false);
|
||||
};
|
||||
|
||||
updateUserPhotoInState = () => {
|
||||
var profile = toEmployeeWrapper(this.props.profile);
|
||||
this.props.getUserPhoto(profile.id).then((userPhotoData) => {
|
||||
if (userPhotoData.original) {
|
||||
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
|
||||
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
|
||||
this.setState({
|
||||
avatar: {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
image: userPhotoData.original
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? null
|
||||
: userPhotoData.original
|
||||
: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
mapPropsToState = (props) => {
|
||||
var profile = toEmployeeWrapper(props.profile);
|
||||
|
||||
this.props.getUserPhoto(profile.id).then((userPhotoData) => {
|
||||
if (userPhotoData.original) {
|
||||
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
|
||||
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
|
||||
this.setState({
|
||||
avatar: {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
image: userPhotoData.original
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? undefined
|
||||
: userPhotoData.original
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const newState = {
|
||||
isLoading: false,
|
||||
pageIsLoaded: true,
|
||||
errors: {
|
||||
firstName: false,
|
||||
lastName: false,
|
||||
},
|
||||
profile: profile,
|
||||
visibleAvatarEditor: false,
|
||||
avatar: {
|
||||
tmpFile: "",
|
||||
image: null,
|
||||
defaultWidth: 0,
|
||||
defaultHeight: 0,
|
||||
},
|
||||
dialogsVisible: {
|
||||
[dialogsDataset.changePassword]: false,
|
||||
[dialogsDataset.changePhone]: false,
|
||||
[dialogsDataset.changeEmail]: false,
|
||||
currentDialog: "",
|
||||
},
|
||||
isMobile: isMobile || isTablet,
|
||||
};
|
||||
|
||||
//Set unique contacts id
|
||||
const now = new Date().getTime();
|
||||
|
||||
newState.profile.contacts.forEach((contact, index) => {
|
||||
contact.id = (now + index).toString();
|
||||
});
|
||||
|
||||
return newState;
|
||||
};
|
||||
|
||||
onSaveAvatar = (isUpdate, result, avatar) => {
|
||||
this.setState({ isLoading: true });
|
||||
const { profile, toggleAvatarEditor, setAvatarMax, personal } = this.props;
|
||||
|
||||
if (isUpdate) {
|
||||
createThumbnailsAvatar(profile.id, {
|
||||
x: Math.round(result.x * avatar.defaultWidth - result.width / 2),
|
||||
y: Math.round(result.y * avatar.defaultHeight - result.height / 2),
|
||||
width: result.width,
|
||||
height: result.height,
|
||||
tmpFile: avatar.tmpFile,
|
||||
})
|
||||
.then((response) => {
|
||||
const avatarMax =
|
||||
response.max +
|
||||
"?_=" +
|
||||
Math.floor(Math.random() * Math.floor(10000));
|
||||
|
||||
let stateCopy = Object.assign({}, this.state);
|
||||
setAvatarMax(avatarMax);
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.setState(stateCopy);
|
||||
})
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
})
|
||||
.then(() => {
|
||||
this.props.updateProfile(this.props.profile);
|
||||
})
|
||||
.then(() => {
|
||||
this.setState(this.mapPropsToState(this.props));
|
||||
})
|
||||
.then(() => !personal && this.props.fetchProfile(profile.id))
|
||||
.then((res) => {
|
||||
//this.props.isMe && this.props.setUser(res);
|
||||
return toggleAvatarEditor(false);
|
||||
});
|
||||
} else {
|
||||
deleteAvatar(profile.id)
|
||||
.then((response) => {
|
||||
let stateCopy = Object.assign({}, this.state);
|
||||
setAvatarMax(response.big);
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.setState(stateCopy);
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.then(() => this.props.updateProfile(this.props.profile))
|
||||
.then(() => {
|
||||
this.setState(this.mapPropsToState(this.props));
|
||||
})
|
||||
.then(() => !personal && this.props.fetchProfile(profile.id))
|
||||
.then((res) => {
|
||||
//this.props.isMe && this.props.setUser(res);
|
||||
return toggleAvatarEditor(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onSaveClick = () => this.setState({ isLoading: true });
|
||||
|
||||
onLoadFileAvatar = (file, fileData) => {
|
||||
const { profile } = this.props;
|
||||
|
||||
let data = new FormData();
|
||||
let _this = this;
|
||||
|
||||
if (!file) {
|
||||
_this.onSaveAvatar(false);
|
||||
return;
|
||||
}
|
||||
|
||||
data.append("file", file);
|
||||
data.append("Autosave", false);
|
||||
loadAvatar(profile.id, data)
|
||||
.then((response) => {
|
||||
if (!response.success && response.message) {
|
||||
throw response.message;
|
||||
}
|
||||
var img = new Image();
|
||||
img.onload = () => {
|
||||
if (fileData) {
|
||||
fileData.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
if (!fileData.existImage) {
|
||||
_this.onSaveAvatar(fileData.existImage); // saving empty avatar
|
||||
} else {
|
||||
_this.onSaveAvatar(
|
||||
fileData.existImage,
|
||||
fileData.position,
|
||||
fileData.avatar
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
img.src = response.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
};
|
||||
|
||||
setUserPhotoToState = () => {
|
||||
const { profile } = this.props;
|
||||
|
||||
if (!profile) {
|
||||
this.setState({ pageIsLoaded: true });
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.getUserPhoto(profile.id).then((userPhotoData) => {
|
||||
if (userPhotoData.original) {
|
||||
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
|
||||
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
|
||||
this.setState({
|
||||
avatar: {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
image: userPhotoData.original
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? null
|
||||
: userPhotoData.original
|
||||
: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ pageIsLoaded: true });
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
const { pageIsLoaded } = this.state;
|
||||
|
||||
return pageIsLoaded ? (
|
||||
<AvatarEditorBody>
|
||||
<AvatarEditor
|
||||
useModalDialog={false}
|
||||
image={this.state.avatar.image}
|
||||
visible={true}
|
||||
onSave={this.onSaveClick}
|
||||
onCancel={this.onCancel}
|
||||
onLoadFile={this.onLoadFileAvatar}
|
||||
headerLabel={t("EditPhoto")}
|
||||
selectNewPhotoLabel={t("PeopleTranslations:selectNewPhotoLabel")}
|
||||
orDropFileHereLabel={t("PeopleTranslations:orDropFileHereLabel")}
|
||||
unknownTypeError={t("PeopleTranslations:ErrorUnknownFileImageType")}
|
||||
maxSizeFileError={t("PeopleTranslations:maxSizeFileError")}
|
||||
unknownError={t("Common:Error")}
|
||||
saveButtonLabel={
|
||||
this.state.isLoading ? t("UpdatingProcess") : t("Common:SaveButton")
|
||||
}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
saveButtonLoading={this.state.isLoading}
|
||||
maxSizeLabel={t("PeopleTranslations:MaxSizeLabel")}
|
||||
/>
|
||||
</AvatarEditorBody>
|
||||
) : (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
inject(({ auth, peopleStore }) => ({
|
||||
setDocumentTitle: auth.setDocumentTitle,
|
||||
//setUser: auth.userStore.setUser,
|
||||
toggleAvatarEditor: peopleStore.avatarEditorStore.toggleAvatarEditor,
|
||||
fetchProfile: peopleStore.targetUserStore.getTargetUser,
|
||||
profile: peopleStore.targetUserStore.targetUser,
|
||||
//isMe: peopleStore.targetUserStore.isMe,
|
||||
avatarMax: peopleStore.avatarEditorStore.avatarMax,
|
||||
setAvatarMax: peopleStore.avatarEditorStore.setAvatarMax,
|
||||
updateProfile: peopleStore.targetUserStore.updateProfile,
|
||||
getUserPhoto: peopleStore.targetUserStore.getUserPhoto,
|
||||
personal: auth.settingsStore.personal,
|
||||
}))(
|
||||
observer(
|
||||
withTranslation(["ProfileAction", "Common", "PeopleTranslations"])(
|
||||
AvatarEditorPage
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
@ -1,305 +0,0 @@
|
||||
import React from "react";
|
||||
import { withRouter } from "react-router";
|
||||
import styled from "styled-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import AvatarEditor from "@docspace/components/avatar-editor";
|
||||
import Loader from "@docspace/components/loader";
|
||||
import { isTablet } from "@docspace/components/utils/device";
|
||||
import {
|
||||
/*createThumbnailsAvatar,*/ loadAvatar,
|
||||
} from "@docspace/common/api/people";
|
||||
import toastr from "client/toastr";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { toEmployeeWrapper } from "../../../../helpers/people-helpers";
|
||||
|
||||
// const dialogsDataset = {
|
||||
// changeEmail: "changeEmail",
|
||||
// changePassword: "changePassword",
|
||||
// changePhone: "changePhone",
|
||||
// };
|
||||
|
||||
const AvatarEditorBody = styled.div`
|
||||
margin-bottom: 24px;
|
||||
`;
|
||||
|
||||
class CreateAvatarEditorPage extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = this.mapPropsToState(props);
|
||||
|
||||
this.onLoadFileAvatar = this.onLoadFileAvatar.bind(this);
|
||||
this.onSaveAvatar = this.onSaveAvatar.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { match, fetchProfile, t, profile, setDocumentTitle } = this.props;
|
||||
const { avatar } = this.state;
|
||||
const { userId } = match.params;
|
||||
|
||||
setDocumentTitle(t("ProfileAction"));
|
||||
if (userId && !profile) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
|
||||
if (avatar.image === undefined) {
|
||||
this.setUserPhotoToState();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { match, fetchProfile /*, profile*/ } = this.props;
|
||||
const { userId } = match.params;
|
||||
const { avatar } = this.state;
|
||||
const prevUserId = prevProps.match.params.userId;
|
||||
|
||||
if (this.props.match.params.type !== prevProps.match.params.type) {
|
||||
this.setState(this.mapPropsToState(this.props));
|
||||
}
|
||||
|
||||
if (userId !== undefined && userId !== prevUserId) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
|
||||
if (avatar.image === undefined) {
|
||||
this.setUserPhotoToState();
|
||||
}
|
||||
}
|
||||
|
||||
onCancel = () => {
|
||||
const { toggleAvatarEditor } = this.props;
|
||||
toggleAvatarEditor(false);
|
||||
};
|
||||
|
||||
updateUserPhotoInState = () => {
|
||||
var profile = toEmployeeWrapper(this.props.profile);
|
||||
this.props.getUserPhoto(profile.id).then((userPhotoData) => {
|
||||
if (userPhotoData.original) {
|
||||
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
|
||||
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
|
||||
this.setState({
|
||||
avatar: {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
image: userPhotoData.original
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? null
|
||||
: userPhotoData.original
|
||||
: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
mapPropsToState = (props) => {
|
||||
var profile = toEmployeeWrapper({
|
||||
isVisitor: props.match.params.type === "guest",
|
||||
passwordType: "link",
|
||||
});
|
||||
return {
|
||||
pageIsLoaded: true,
|
||||
visibleAvatarEditor: false,
|
||||
croppedAvatarImage: "",
|
||||
isLoading: false,
|
||||
errors: {
|
||||
firstName: false,
|
||||
lastName: false,
|
||||
email: false,
|
||||
password: false,
|
||||
},
|
||||
profile: profile,
|
||||
avatar: {
|
||||
tmpFile: "",
|
||||
image: null,
|
||||
defaultWidth: 0,
|
||||
defaultHeight: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
isMobile: isMobile || isTablet,
|
||||
};
|
||||
};
|
||||
|
||||
setIsEdit(hasChanges) {
|
||||
const { setIsEditingForm } = this.props;
|
||||
setIsEditingForm(hasChanges);
|
||||
}
|
||||
|
||||
onLoadFileAvatar(file, fileData) {
|
||||
let data = new FormData();
|
||||
let _this = this;
|
||||
data.append("file", file);
|
||||
data.append("Autosave", false);
|
||||
|
||||
if (!file) {
|
||||
_this.onSaveAvatar(false);
|
||||
return;
|
||||
}
|
||||
|
||||
loadAvatar(0, data)
|
||||
.then((response) => {
|
||||
if (!response.success && response.message) {
|
||||
throw response.message;
|
||||
}
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
if (fileData) {
|
||||
fileData.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
|
||||
var stateCopy = Object.assign({}, _this.state);
|
||||
|
||||
stateCopy.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
|
||||
_this.setState(stateCopy);
|
||||
|
||||
if (fileData.existImage) {
|
||||
_this.onSaveAvatar(
|
||||
fileData.existImage,
|
||||
fileData.position,
|
||||
fileData.avatar,
|
||||
fileData.croppedImage
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
img.src = response.data;
|
||||
})
|
||||
.catch((error) => toastr.error(error));
|
||||
}
|
||||
|
||||
onSaveAvatar(isUpdate, result, avatar, croppedImage) {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
const {
|
||||
setCreatedAvatar,
|
||||
toggleAvatarEditor,
|
||||
setCroppedAvatar,
|
||||
resetProfile,
|
||||
} = this.props;
|
||||
|
||||
stateCopy.visibleAvatarEditor = false;
|
||||
stateCopy.croppedAvatarImage = croppedImage;
|
||||
if (isUpdate) {
|
||||
stateCopy.avatar.x = Math.round(
|
||||
result.x * avatar.defaultWidth - result.width / 2
|
||||
);
|
||||
stateCopy.avatar.y = Math.round(
|
||||
result.y * avatar.defaultHeight - result.height / 2
|
||||
);
|
||||
stateCopy.avatar.width = result.width;
|
||||
stateCopy.avatar.height = result.height;
|
||||
|
||||
setCreatedAvatar(stateCopy.avatar);
|
||||
setCroppedAvatar(croppedImage);
|
||||
this.setIsEdit(true);
|
||||
} else {
|
||||
resetProfile();
|
||||
this.setIsEdit(false);
|
||||
}
|
||||
|
||||
toggleAvatarEditor(false);
|
||||
}
|
||||
|
||||
setUserPhotoToState = () => {
|
||||
const { profile } = this.props;
|
||||
|
||||
if (!profile) {
|
||||
this.setState({ pageIsLoaded: true });
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.getUserPhoto(profile.id).then((userPhotoData) => {
|
||||
if (userPhotoData.original) {
|
||||
let avatarDefaultSizes = /_(\d*)-(\d*)./g.exec(userPhotoData.original);
|
||||
if (avatarDefaultSizes !== null && avatarDefaultSizes.length > 2) {
|
||||
this.setState({
|
||||
avatar: {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
image: userPhotoData.original
|
||||
? userPhotoData.original.indexOf("default_user_photo") !== -1
|
||||
? null
|
||||
: userPhotoData.original
|
||||
: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ pageIsLoaded: true });
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, createdAvatar } = this.props;
|
||||
const { pageIsLoaded } = this.state;
|
||||
|
||||
return pageIsLoaded ? (
|
||||
<AvatarEditorBody>
|
||||
<AvatarEditor
|
||||
useModalDialog={false}
|
||||
image={createdAvatar.image}
|
||||
visible={true}
|
||||
onClose={this.onCloseAvatarEditor}
|
||||
onSave={this.onSaveAvatar}
|
||||
onCancel={this.onCancel}
|
||||
onLoadFile={this.onLoadFileAvatar}
|
||||
headerLabel={t("EditPhoto")}
|
||||
selectNewPhotoLabel={t("PeopleTranslations:selectNewPhotoLabel")}
|
||||
orDropFileHereLabel={t("PeopleTranslations:orDropFileHereLabel")}
|
||||
unknownTypeError={t("PeopleTranslations:ErrorUnknownFileImageType")}
|
||||
maxSizeFileError={t("PeopleTranslations:maxSizeFileError")}
|
||||
unknownError={t("Common:Error")}
|
||||
saveButtonLabel={
|
||||
this.state.isLoading ? t("UpdatingProcess") : t("Common:SaveButton")
|
||||
}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
saveButtonLoading={this.state.isLoading}
|
||||
maxSizeLabel={t("PeopleTranslations:MaxSizeLabel")}
|
||||
/>
|
||||
</AvatarEditorBody>
|
||||
) : (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
inject(({ auth, peopleStore }) => ({
|
||||
setDocumentTitle: auth.setDocumentTitle,
|
||||
setIsEditingForm: peopleStore.editingFormStore.setIsEditingForm,
|
||||
toggleAvatarEditor: peopleStore.avatarEditorStore.toggleAvatarEditor,
|
||||
resetProfile: peopleStore.targetUserStore.resetTargetUser,
|
||||
fetchProfile: peopleStore.targetUserStore.getTargetUser,
|
||||
profile: peopleStore.targetUserStore.targetUser,
|
||||
setCreatedAvatar: peopleStore.avatarEditorStore.setCreatedAvatar,
|
||||
setCroppedAvatar: peopleStore.avatarEditorStore.setCroppedAvatar,
|
||||
updateProfile: peopleStore.targetUserStore.updateProfile,
|
||||
updateCreatedAvatar: peopleStore.targetUserStore.updateCreatedAvatar,
|
||||
getUserPhoto: peopleStore.targetUserStore.getUserPhoto,
|
||||
createdAvatar: peopleStore.avatarEditorStore.createdAvatar,
|
||||
avatarMax: peopleStore.avatarEditorStore.avatarMax,
|
||||
croppedAvatar: peopleStore.avatarEditorStore.croppedAvatar,
|
||||
}))(
|
||||
observer(
|
||||
withTranslation(["ProfileAction", "Common", "PeopleTranslations"])(
|
||||
CreateAvatarEditorPage
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
@ -1,758 +0,0 @@
|
||||
import React from "react";
|
||||
import { withRouter } from "react-router";
|
||||
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import Button from "@docspace/components/button";
|
||||
import Textarea from "@docspace/components/textarea";
|
||||
import Text from "@docspace/components/text";
|
||||
import AvatarEditor from "@docspace/components/avatar-editor";
|
||||
import { isTablet } from "@docspace/components/utils/device";
|
||||
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import {
|
||||
MainContainer,
|
||||
AvatarContainer,
|
||||
MainFieldsContainer,
|
||||
} from "./FormFields/Form";
|
||||
import TextField from "./FormFields/TextField";
|
||||
import PasswordField from "./FormFields/PasswordField";
|
||||
import EmailField from "./FormFields/EmailField";
|
||||
import DateField from "./FormFields/DateField";
|
||||
import RadioField from "./FormFields/RadioField";
|
||||
import DepartmentField from "./FormFields/DepartmentField";
|
||||
import ContactsField from "./FormFields/ContactsField";
|
||||
import InfoFieldContainer from "./FormFields/InfoFieldContainer";
|
||||
import { DataLossWarningDialog } from "../../../../components/dialogs";
|
||||
import {
|
||||
createThumbnailsAvatar,
|
||||
loadAvatar,
|
||||
} from "@docspace/common/api/people";
|
||||
import toastr from "client/toastr";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import {
|
||||
toEmployeeWrapper,
|
||||
getUserRole,
|
||||
getUserContactsPattern,
|
||||
getUserContacts,
|
||||
mapGroupsToGroupSelectorOptions,
|
||||
mapGroupSelectorOptionsToGroups,
|
||||
filterGroupSelectorOptions,
|
||||
} from "../../../../helpers/people-helpers";
|
||||
import config from "PACKAGE_FILE";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { AppServerConfig } from "@docspace/common/constants";
|
||||
|
||||
class CreateUserForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = this.mapPropsToState(props);
|
||||
this.mainFieldsContainerRef = React.createRef();
|
||||
}
|
||||
|
||||
createAvatar(userId, userName) {
|
||||
const { createdAvatar } = this.props;
|
||||
createThumbnailsAvatar(userId, {
|
||||
x: createdAvatar.x,
|
||||
y: createdAvatar.y,
|
||||
width: createdAvatar.width,
|
||||
height: createdAvatar.height,
|
||||
tmpFile: createdAvatar.tmpFile,
|
||||
})
|
||||
.then((res) => {
|
||||
this.props.updateCreatedAvatar(res);
|
||||
this.props.updateProfileInUsers();
|
||||
toastr.success(this.props.t("ChangesSavedSuccessfully"));
|
||||
this.props.history.push(
|
||||
combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
this.props.homepage,
|
||||
`/accounts/view/${userName}`
|
||||
)
|
||||
);
|
||||
})
|
||||
.catch((error) => toastr.error(error));
|
||||
}
|
||||
|
||||
openAvatarEditor = () => {
|
||||
let avatarDefault = this.state.avatar.image;
|
||||
let avatarDefaultSizes = /_orig_(\d*)-(\d*)./g.exec(
|
||||
this.state.avatar.image
|
||||
);
|
||||
if (
|
||||
avatarDefault !== null &&
|
||||
avatarDefaultSizes !== null &&
|
||||
avatarDefaultSizes.length > 2
|
||||
) {
|
||||
this.setState({
|
||||
avatar: {
|
||||
tmpFile: this.state.avatar.tmpFile,
|
||||
image: this.state.avatar.image,
|
||||
defaultWidth: avatarDefaultSizes[1],
|
||||
defaultHeight: avatarDefaultSizes[2],
|
||||
},
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
visibleAvatarEditor: true,
|
||||
});
|
||||
};
|
||||
|
||||
openAvatarEditorPage = () => {
|
||||
const { toggleAvatarEditor } = this.props;
|
||||
|
||||
toggleAvatarEditor(true);
|
||||
};
|
||||
|
||||
onLoadFileAvatar = (file, fileData) => {
|
||||
let data = new FormData();
|
||||
let _this = this;
|
||||
data.append("file", file);
|
||||
data.append("Autosave", false);
|
||||
|
||||
if (!file) {
|
||||
_this.onSaveAvatar(false);
|
||||
return;
|
||||
}
|
||||
|
||||
loadAvatar(0, data)
|
||||
.then((response) => {
|
||||
if (!response.success && response.message) {
|
||||
throw response.message;
|
||||
}
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
if (fileData) {
|
||||
fileData.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
|
||||
var stateCopy = Object.assign({}, _this.state);
|
||||
stateCopy.avatar = {
|
||||
tmpFile: response.data,
|
||||
image: response.data,
|
||||
defaultWidth: img.width,
|
||||
defaultHeight: img.height,
|
||||
};
|
||||
_this.setState(stateCopy);
|
||||
|
||||
if (fileData.existImage) {
|
||||
_this.onSaveAvatar(
|
||||
fileData.existImage,
|
||||
fileData.position,
|
||||
fileData.avatar,
|
||||
fileData.croppedImage
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
img.src = response.data;
|
||||
})
|
||||
.catch((error) => toastr.error(error));
|
||||
};
|
||||
|
||||
onSaveAvatar = (isUpdate, result, avatar, croppedImage) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
const { setCreatedAvatar, setCroppedAvatar, resetProfile } = this.props;
|
||||
|
||||
stateCopy.visibleAvatarEditor = false;
|
||||
stateCopy.croppedAvatarImage = croppedImage;
|
||||
if (isUpdate) {
|
||||
stateCopy.avatar.x = Math.round(
|
||||
result.x * avatar.defaultWidth - result.width / 2
|
||||
);
|
||||
stateCopy.avatar.y = Math.round(
|
||||
result.y * avatar.defaultHeight - result.height / 2
|
||||
);
|
||||
stateCopy.avatar.width = result.width;
|
||||
stateCopy.avatar.height = result.height;
|
||||
|
||||
setCreatedAvatar(stateCopy.avatar);
|
||||
setCroppedAvatar(croppedImage);
|
||||
} else {
|
||||
resetProfile();
|
||||
}
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onCloseAvatarEditor = () => {
|
||||
this.setState({
|
||||
visibleAvatarEditor: false,
|
||||
croppedAvatarImage: "",
|
||||
avatar: {
|
||||
tmpFile: "",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.props.match.params.type !== prevProps.match.params.type) {
|
||||
this.setState(this.mapPropsToState(this.props));
|
||||
}
|
||||
|
||||
const isMobileDevice = isMobile || isTablet();
|
||||
|
||||
if (prevState.isMobile !== isMobileDevice) {
|
||||
this.setState({ isMobile: isMobileDevice });
|
||||
}
|
||||
}
|
||||
|
||||
mapPropsToState = (props) => {
|
||||
var profile = toEmployeeWrapper({
|
||||
isVisitor: props.match.params.type === "guest",
|
||||
passwordType: "link",
|
||||
});
|
||||
var allOptions = mapGroupsToGroupSelectorOptions(props.groups);
|
||||
var selected = mapGroupsToGroupSelectorOptions(profile.groups);
|
||||
return {
|
||||
visibleAvatarEditor: false,
|
||||
croppedAvatarImage: "",
|
||||
isLoading: false,
|
||||
errors: {
|
||||
firstName: false,
|
||||
lastName: false,
|
||||
email: false,
|
||||
password: false,
|
||||
},
|
||||
profile: profile,
|
||||
selector: {
|
||||
visible: false,
|
||||
allOptions: allOptions,
|
||||
options: [...allOptions],
|
||||
selected: selected,
|
||||
},
|
||||
avatar: {
|
||||
tmpFile: "",
|
||||
image: null,
|
||||
defaultWidth: 0,
|
||||
defaultHeight: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
isMobile: isMobile || isTablet,
|
||||
};
|
||||
};
|
||||
setIsEdit() {
|
||||
const { isEdit, setIsEditingForm } = this.props;
|
||||
if (!isEdit) setIsEditingForm(true);
|
||||
}
|
||||
|
||||
onInputChange = (event) => {
|
||||
const { userFormValidation } = this.props;
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
const value = event.target.value;
|
||||
const title = event.target.name;
|
||||
|
||||
if (!value.match(userFormValidation)) {
|
||||
stateCopy.errors[title] = true;
|
||||
} else {
|
||||
if (this.state.errors[title]) stateCopy.errors[title] = false;
|
||||
}
|
||||
|
||||
stateCopy.profile[title] = value;
|
||||
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onBirthdayDateChange = (value) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.birthday = value ? value.toJSON() : null;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onWorkFromDateChange = (value) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.workFrom = value ? value.toJSON() : null;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
scrollToErrorForm = () => {
|
||||
const element = this.mainFieldsContainerRef.current;
|
||||
const parent = element.closest(".scroll-body");
|
||||
(parent || window).scrollTo(0, element.offsetTop);
|
||||
};
|
||||
|
||||
validate = () => {
|
||||
const { profile, errors: stateErrors } = this.state;
|
||||
|
||||
if (stateErrors.firstName || stateErrors.lastName) {
|
||||
this.scrollToErrorForm();
|
||||
return;
|
||||
}
|
||||
|
||||
const errors = {
|
||||
firstName: !profile.firstName.trim(),
|
||||
lastName: !profile.lastName.trim(),
|
||||
email: stateErrors.email || !profile.email.trim(),
|
||||
password: profile.passwordType === "temp" && !profile.password.trim(),
|
||||
};
|
||||
const hasError =
|
||||
errors.firstName || errors.lastName || errors.email || errors.password;
|
||||
|
||||
if (hasError) {
|
||||
this.scrollToErrorForm();
|
||||
}
|
||||
|
||||
this.setState({ errors: errors });
|
||||
return !hasError;
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
if (!this.validate()) return false;
|
||||
const {
|
||||
setIsEditingForm,
|
||||
homepage,
|
||||
createProfile,
|
||||
createdAvatar,
|
||||
t,
|
||||
history,
|
||||
} = this.props;
|
||||
const profile = this.state.profile;
|
||||
if (!profile.birthday) profile.birthday = new Date();
|
||||
|
||||
this.setState({ isLoading: true });
|
||||
createProfile(profile)
|
||||
.then((profile) => {
|
||||
if (createdAvatar.tmpFile !== "") {
|
||||
this.createAvatar(profile.id, profile.userName);
|
||||
} else {
|
||||
toastr.success(t("ChangesSavedSuccessfully"));
|
||||
history.push(
|
||||
combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
homepage,
|
||||
`/accounts/view/${profile.userName}`
|
||||
)
|
||||
);
|
||||
}
|
||||
setIsEditingForm(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
toastr.error(error);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
};
|
||||
|
||||
onCancelHandler = () => {
|
||||
const { isEdit, setIsVisibleDataLossDialog } = this.props;
|
||||
|
||||
if (isEdit) {
|
||||
setIsVisibleDataLossDialog(true);
|
||||
} else {
|
||||
this.onCancel();
|
||||
}
|
||||
};
|
||||
|
||||
onCancel = () => {
|
||||
const { filter, setFilter, history } = this.props;
|
||||
history.goBack();
|
||||
setFilter(filter);
|
||||
};
|
||||
|
||||
onContactsItemAdd = (item) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.push({
|
||||
id: new Date().getTime().toString(),
|
||||
type: item.value,
|
||||
value: "",
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onContactsItemTypeChange = (item) => {
|
||||
const id = item.key.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.forEach((element) => {
|
||||
if (element.id === id) element.type = item.value;
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onContactsItemTextChange = (event) => {
|
||||
const id = event.target.name.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.contacts.forEach((element) => {
|
||||
if (element.id === id) element.value = event.target.value;
|
||||
});
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onContactsItemRemove = (event) => {
|
||||
const id = event.target.closest(".remove_icon").dataset.for.split("_")[0];
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
const filteredArray = stateCopy.profile.contacts.filter((element) => {
|
||||
return element.id !== id;
|
||||
});
|
||||
stateCopy.profile.contacts = filteredArray;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onShowGroupSelector = () => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.selector.visible = true;
|
||||
this.setState(stateCopy);
|
||||
};
|
||||
|
||||
onCloseGroupSelector = () => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.selector.visible = false;
|
||||
this.setState(stateCopy);
|
||||
};
|
||||
|
||||
onSearchGroups = (template) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.selector.options = filterGroupSelectorOptions(
|
||||
stateCopy.selector.allOptions,
|
||||
template
|
||||
);
|
||||
this.setState(stateCopy);
|
||||
};
|
||||
|
||||
onSelectGroups = (selected) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.groups = mapGroupSelectorOptionsToGroups(selected);
|
||||
stateCopy.selector.selected = selected;
|
||||
stateCopy.selector.visible = false;
|
||||
this.setState(stateCopy);
|
||||
this.setIsEdit();
|
||||
};
|
||||
|
||||
onRemoveGroup = (id) => {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.profile.groups = stateCopy.profile.groups.filter(
|
||||
(group) => group.id !== id
|
||||
);
|
||||
stateCopy.selector.selected = stateCopy.selector.selected.filter(
|
||||
(option) => option.key !== id
|
||||
);
|
||||
this.setState(stateCopy);
|
||||
};
|
||||
|
||||
onValidateEmailField = (value) =>
|
||||
this.setState({ errors: { ...this.state.errors, email: !value.isValid } });
|
||||
|
||||
onSaveClick = () => this.setState({ isLoading: true });
|
||||
|
||||
render() {
|
||||
const { isLoading, errors, profile, selector, isMobile } = this.state;
|
||||
const {
|
||||
t,
|
||||
customNames,
|
||||
createdAvatar,
|
||||
croppedAvatar,
|
||||
passwordSettings,
|
||||
language,
|
||||
isTabletView,
|
||||
} = this.props;
|
||||
const { regDateCaption, userPostCaption, groupCaption } = customNames;
|
||||
|
||||
const pattern = getUserContactsPattern();
|
||||
const contacts = getUserContacts(profile.contacts);
|
||||
|
||||
const notEmptyFirstName = Boolean(profile.firstName.trim());
|
||||
const notEmptyLastName = Boolean(profile.lastName.trim());
|
||||
|
||||
return (
|
||||
<>
|
||||
<MainContainer>
|
||||
<DataLossWarningDialog onContinue={this.onCancel} />
|
||||
<AvatarContainer>
|
||||
<Avatar
|
||||
size="max"
|
||||
role={getUserRole(profile)}
|
||||
editing={true}
|
||||
source={croppedAvatar}
|
||||
editLabel={t("Common:AddButton")}
|
||||
editAction={
|
||||
isMobile ? this.openAvatarEditorPage : this.openAvatarEditor
|
||||
}
|
||||
/>
|
||||
<AvatarEditor
|
||||
image={createdAvatar.image}
|
||||
visible={this.state.visibleAvatarEditor}
|
||||
onClose={this.onCloseAvatarEditor}
|
||||
onSave={this.onSaveClick}
|
||||
onLoadFile={this.onLoadFileAvatar}
|
||||
headerLabel={t("AddPhoto")}
|
||||
selectNewPhotoLabel={t("PeopleTranslations:selectNewPhotoLabel")}
|
||||
orDropFileHereLabel={t("PeopleTranslations:orDropFileHereLabel")}
|
||||
unknownTypeError={t(
|
||||
"PeopleTranslations:ErrorUnknownFileImageType"
|
||||
)}
|
||||
maxSizeFileError={t("PeopleTranslations:maxSizeFileError")}
|
||||
unknownError={t("Common:Error")}
|
||||
saveButtonLabel={t("Common:SaveButton")}
|
||||
saveButtonLoading={this.state.isLoading}
|
||||
maxSizeLabel={t("PeopleTranslations:MaxSizeLabel")}
|
||||
/>
|
||||
</AvatarContainer>
|
||||
<MainFieldsContainer
|
||||
ref={this.mainFieldsContainerRef}
|
||||
{...(!isTabletView && { marginBottom: "32px" })}
|
||||
>
|
||||
<TextField
|
||||
isRequired={true}
|
||||
hasError={errors.firstName}
|
||||
{...(notEmptyFirstName && {
|
||||
errorMessage: t("ErrorInvalidUserFirstName"),
|
||||
})}
|
||||
labelText={`${t("FirstName")}:`}
|
||||
inputName="firstName"
|
||||
inputValue={profile.firstName}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onInputChange}
|
||||
inputAutoFocussed={true}
|
||||
inputTabIndex={1}
|
||||
/>
|
||||
<TextField
|
||||
isRequired={true}
|
||||
hasError={errors.lastName}
|
||||
{...(notEmptyLastName && {
|
||||
errorMessage: t("ErrorInvalidUserLastName"),
|
||||
})}
|
||||
labelText={`${t("Common:LastName")}:`}
|
||||
inputName="lastName"
|
||||
inputValue={profile.lastName}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onInputChange}
|
||||
inputTabIndex={2}
|
||||
/>
|
||||
<EmailField
|
||||
isRequired={true}
|
||||
hasError={errors.email}
|
||||
labelText={`${t("Common:Email")}:`}
|
||||
inputName="email"
|
||||
inputValue={profile.email}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onInputChange}
|
||||
inputTabIndex={3}
|
||||
helpButtonHeaderContent={t("Common:Mail")}
|
||||
tooltipContent={
|
||||
<Text fontSize="13px" as="div">
|
||||
<Trans t={t} i18nKey="EmailPopupHelper" ns="ProfileAction">
|
||||
The main e-mail is needed to restore access to the portal in
|
||||
case of loss of the password and send notifications.
|
||||
<p className="tooltip_email" style={{ margin: "1rem 0" }}>
|
||||
You can create a new mail on the domain as the primary. In
|
||||
this case, you must set a one-time password so that the
|
||||
user can log in to the portal for the first time.
|
||||
</p>
|
||||
The main e-mail can be used as a login when logging in to
|
||||
the portal.
|
||||
</Trans>
|
||||
</Text>
|
||||
}
|
||||
onValidateInput={this.onValidateEmailField}
|
||||
/>
|
||||
<PasswordField
|
||||
isRequired={true}
|
||||
hasError={errors.password}
|
||||
labelText={`${t("Common:Password")}:`}
|
||||
radioName="passwordType"
|
||||
radioValue={profile.passwordType}
|
||||
radioOptions={[
|
||||
{ value: "link", label: t("ActivationLink") },
|
||||
{ value: "temp", label: t("TemporaryPassword") },
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
inputName="password"
|
||||
emailInputName="email"
|
||||
inputValue={profile.password}
|
||||
inputIsDisabled={isLoading || profile.passwordType === "link"}
|
||||
inputOnChange={this.onInputChange}
|
||||
copyLinkText={t("Common:CopyEmailAndPassword")}
|
||||
copiedResourceText={t("CopiedResourceText")}
|
||||
inputTabIndex={4}
|
||||
passwordSettings={passwordSettings}
|
||||
t={t}
|
||||
/>
|
||||
<DateField
|
||||
calendarHeaderContent={`${t("CalendarSelectDate")}:`}
|
||||
labelText={`${t("PeopleTranslations:Birthdate")}:`}
|
||||
inputName="birthday"
|
||||
inputClassName="date-picker_input-birthday"
|
||||
inputValue={
|
||||
profile.birthday ? new Date(profile.birthday) : undefined
|
||||
}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onBirthdayDateChange}
|
||||
inputTabIndex={5}
|
||||
locale={language}
|
||||
/>
|
||||
<RadioField
|
||||
labelText={`${t("PeopleTranslations:Sex")}:`}
|
||||
radioName="sex"
|
||||
radioValue={profile.sex}
|
||||
radioOptions={[
|
||||
{ value: "male", label: t("PeopleTranslations:MaleSexStatus") },
|
||||
{
|
||||
value: "female",
|
||||
label: t("PeopleTranslations:FemaleSexStatus"),
|
||||
},
|
||||
]}
|
||||
radioIsDisabled={isLoading}
|
||||
radioOnChange={this.onInputChange}
|
||||
/>
|
||||
<DateField
|
||||
calendarHeaderContent={`${t("CalendarSelectDate")}:`}
|
||||
labelText={`${regDateCaption}:`}
|
||||
inputName="workFrom"
|
||||
inputClassName="date-picker_input-reg-date"
|
||||
inputValue={
|
||||
profile.workFrom ? new Date(profile.workFrom) : undefined
|
||||
}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onWorkFromDateChange}
|
||||
inputTabIndex={6}
|
||||
calendarMinDate={
|
||||
profile.birthday ? new Date(profile.birthday) : undefined
|
||||
}
|
||||
locale={language}
|
||||
/>
|
||||
<TextField
|
||||
labelText={`${t("Common:Location")}:`}
|
||||
inputName="location"
|
||||
inputValue={profile.location}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onInputChange}
|
||||
inputTabIndex={7}
|
||||
/>
|
||||
<TextField
|
||||
labelText={`${userPostCaption}:`}
|
||||
inputName="title"
|
||||
inputValue={profile.title}
|
||||
inputIsDisabled={isLoading}
|
||||
inputOnChange={this.onInputChange}
|
||||
inputTabIndex={8}
|
||||
/>
|
||||
<DepartmentField
|
||||
labelText={`${groupCaption}:`}
|
||||
isDisabled={isLoading}
|
||||
showGroupSelectorButtonTitle={t("Common:AddButton")}
|
||||
onShowGroupSelector={this.onShowGroupSelector}
|
||||
onCloseGroupSelector={this.onCloseGroupSelector}
|
||||
onRemoveGroup={this.onRemoveGroup}
|
||||
selectorIsVisible={selector.visible}
|
||||
selectorOptions={selector.options}
|
||||
selectorSelectedOptions={selector.selected}
|
||||
selectorSelectAllText={t("Common:SelectAll")}
|
||||
selectorOnSearchGroups={this.onSearchGroups}
|
||||
selectorOnSelectGroups={this.onSelectGroups}
|
||||
/>
|
||||
</MainFieldsContainer>
|
||||
</MainContainer>
|
||||
<InfoFieldContainer
|
||||
headerText={t("Common:Comments")}
|
||||
marginBottom={"42px"}
|
||||
>
|
||||
<Textarea
|
||||
placeholder={t("WriteComment")}
|
||||
name="notes"
|
||||
value={profile.notes}
|
||||
isDisabled={isLoading}
|
||||
onChange={this.onInputChange}
|
||||
tabIndex={9}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer
|
||||
headerText={t("ContactInformation")}
|
||||
marginBottom={"42px"}
|
||||
>
|
||||
<ContactsField
|
||||
pattern={pattern.contact}
|
||||
contacts={contacts.contact}
|
||||
isDisabled={isLoading}
|
||||
addItemText={t("AddContact")}
|
||||
onItemAdd={this.onContactsItemAdd}
|
||||
onItemTypeChange={this.onContactsItemTypeChange}
|
||||
onItemTextChange={this.onContactsItemTextChange}
|
||||
onItemRemove={this.onContactsItemRemove}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer
|
||||
headerText={t("PeopleTranslations:SocialProfiles")}
|
||||
{...(isTabletView && { marginBottom: "36px" })}
|
||||
>
|
||||
<ContactsField
|
||||
pattern={pattern.social}
|
||||
contacts={contacts.social}
|
||||
isDisabled={isLoading}
|
||||
addItemText={t("AddContact")}
|
||||
onItemAdd={this.onContactsItemAdd}
|
||||
onItemTypeChange={this.onContactsItemTypeChange}
|
||||
onItemTextChange={this.onContactsItemTextChange}
|
||||
onItemRemove={this.onContactsItemRemove}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<div>
|
||||
<Button
|
||||
label={t("Common:SaveButton")}
|
||||
onClick={this.handleSubmit}
|
||||
primary
|
||||
isDisabled={isLoading}
|
||||
size="normal"
|
||||
tabIndex={10}
|
||||
className="create-user_save-btn"
|
||||
/>
|
||||
<Button
|
||||
label={t("Common:CancelButton")}
|
||||
onClick={this.onCancelHandler}
|
||||
isDisabled={isLoading}
|
||||
size="normal"
|
||||
style={{ marginLeft: "8px" }}
|
||||
tabIndex={11}
|
||||
className="create-user_cancel-btn"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
inject(({ auth, peopleStore }) => ({
|
||||
passwordSettings: auth.settingsStore.passwordSettings,
|
||||
customNames: auth.settingsStore.customNames,
|
||||
language: auth.language,
|
||||
homepage: config.homepage,
|
||||
isEdit: peopleStore.editingFormStore.isEdit,
|
||||
groups: peopleStore.groupsStore.groups,
|
||||
setIsVisibleDataLossDialog:
|
||||
peopleStore.editingFormStore.setIsVisibleDataLossDialog,
|
||||
setIsEditingForm: peopleStore.editingFormStore.setIsEditingForm,
|
||||
filter: peopleStore.filterStore.filter,
|
||||
setFilter: peopleStore.filterStore.setFilterParams,
|
||||
toggleAvatarEditor: peopleStore.avatarEditorStore.toggleAvatarEditor,
|
||||
resetProfile: peopleStore.targetUserStore.resetTargetUser,
|
||||
createProfile: peopleStore.usersStore.createUser,
|
||||
createdAvatar: peopleStore.avatarEditorStore.createdAvatar,
|
||||
setCreatedAvatar: peopleStore.avatarEditorStore.setCreatedAvatar,
|
||||
croppedAvatar: peopleStore.avatarEditorStore.croppedAvatar,
|
||||
setCroppedAvatar: peopleStore.avatarEditorStore.setCroppedAvatar,
|
||||
updateProfileInUsers: peopleStore.usersStore.updateProfileInUsers,
|
||||
updateCreatedAvatar: peopleStore.targetUserStore.updateCreatedAvatar,
|
||||
userFormValidation: auth.settingsStore.userFormValidation,
|
||||
isTabletView: auth.settingsStore.isTabletView,
|
||||
}))(
|
||||
observer(
|
||||
withTranslation(["ProfileAction", "Common", "PeopleTranslations"])(
|
||||
CreateUserForm
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
@ -1,35 +0,0 @@
|
||||
import React from "react";
|
||||
import CreateAvatarEditorPage from "./createAvatarEditorPage";
|
||||
import AvatarEditorPage from "./avatarEditorPage";
|
||||
import CreateUserForm from "./createUserForm";
|
||||
import UpdateUserForm from "./updateUserForm";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withRouter } from "react-router";
|
||||
|
||||
import withPeopleLoader from "../../../../HOCs/withPeopleLoader";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
|
||||
const SectionUserBody = ({ avatarEditorIsOpen, match, isMy, loaded }) => {
|
||||
const { type } = match.params;
|
||||
return type ? (
|
||||
avatarEditorIsOpen ? (
|
||||
<CreateAvatarEditorPage />
|
||||
) : (
|
||||
<CreateUserForm />
|
||||
)
|
||||
) : avatarEditorIsOpen ? (
|
||||
<AvatarEditorPage />
|
||||
) : (
|
||||
<UpdateUserForm isMy={isMy} />
|
||||
);
|
||||
};
|
||||
|
||||
export default withRouter(
|
||||
inject(({ peopleStore }) => ({
|
||||
avatarEditorIsOpen: peopleStore.avatarEditorStore.visible,
|
||||
}))(
|
||||
withPeopleLoader(observer(SectionUserBody))(
|
||||
<Loaders.ProfileView isEdit={false} />
|
||||
)
|
||||
)
|
||||
);
|
File diff suppressed because it is too large
Load Diff
@ -1,146 +0,0 @@
|
||||
import React, { useCallback } from "react";
|
||||
import styled from "styled-components";
|
||||
import { withRouter } from "react-router";
|
||||
import IconButton from "@docspace/components/icon-button";
|
||||
import Headline from "@docspace/common/components/Headline";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
|
||||
import config from "PACKAGE_FILE";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { AppServerConfig } from "@docspace/common/constants";
|
||||
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import withPeopleLoader from "../../../../HOCs/withPeopleLoader";
|
||||
|
||||
const homepage = config.homepage;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto auto;
|
||||
align-items: center;
|
||||
|
||||
.arrow-button {
|
||||
@media (max-width: 1024px) {
|
||||
padding: 8px 0 8px 8px;
|
||||
margin-left: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-headline {
|
||||
margin-left: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const SectionHeaderContent = (props) => {
|
||||
const {
|
||||
profile,
|
||||
history,
|
||||
match,
|
||||
customNames,
|
||||
filter,
|
||||
isEdit,
|
||||
setFilter,
|
||||
setIsVisibleDataLossDialog,
|
||||
toggleAvatarEditor,
|
||||
avatarEditorIsOpen,
|
||||
isMy,
|
||||
isEditTargetUser,
|
||||
} = props;
|
||||
const { userCaption, guestCaption } = customNames;
|
||||
const { type } = match.params;
|
||||
const { t } = useTranslation("ProfileAction");
|
||||
|
||||
const headerText = avatarEditorIsOpen
|
||||
? t("EditPhoto")
|
||||
: type
|
||||
? type === "guest"
|
||||
? t("CustomCreation", { user: guestCaption })
|
||||
: t("CustomCreation", { user: userCaption })
|
||||
: profile
|
||||
? isMobileOnly
|
||||
? t("Common:Editing")
|
||||
: t("EditUserDialogTitle")
|
||||
: "";
|
||||
|
||||
const onClickBackHandler = () => {
|
||||
if (isEdit) {
|
||||
setIsVisibleDataLossDialog(true, onClickBack);
|
||||
} else {
|
||||
onClickBack();
|
||||
}
|
||||
};
|
||||
|
||||
const setFilterAndReset = useCallback(
|
||||
(filter) => {
|
||||
props.resetProfile();
|
||||
setFilter(filter);
|
||||
},
|
||||
[props, setFilter]
|
||||
);
|
||||
|
||||
const goBackAndReset = useCallback(() => {
|
||||
if (isMy) {
|
||||
return history.goBack();
|
||||
}
|
||||
|
||||
if (!isEditTargetUser && (!profile || !document.referrer)) {
|
||||
setFilterAndReset(filter);
|
||||
const urlFilter = filter.toUrlParams();
|
||||
return history.push(
|
||||
combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
homepage,
|
||||
`/accounts/filter?${urlFilter}`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
history.push(
|
||||
combineUrl(
|
||||
AppServerConfig.proxyURL,
|
||||
homepage,
|
||||
`/accounts/view/${profile.userName}`
|
||||
)
|
||||
);
|
||||
|
||||
return props.resetProfile();
|
||||
}, [history, props]);
|
||||
|
||||
const onClickBack = useCallback(() => {
|
||||
avatarEditorIsOpen ? toggleAvatarEditor(false) : goBackAndReset();
|
||||
}, [avatarEditorIsOpen, toggleAvatarEditor, profile, filter, goBackAndReset]);
|
||||
return (
|
||||
<Wrapper>
|
||||
<IconButton
|
||||
iconName="/static/images/arrow.path.react.svg"
|
||||
size="17"
|
||||
isFill={true}
|
||||
onClick={onClickBackHandler}
|
||||
className="arrow-button"
|
||||
/>
|
||||
<Headline className="header-headline" type="content" truncate={true}>
|
||||
{headerText}
|
||||
</Headline>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default withRouter(
|
||||
inject(({ auth, peopleStore }) => ({
|
||||
customNames: auth.settingsStore.customNames,
|
||||
isEdit: peopleStore.editingFormStore.isEdit,
|
||||
setIsVisibleDataLossDialog:
|
||||
peopleStore.editingFormStore.setIsVisibleDataLossDialog,
|
||||
filter: peopleStore.filterStore.filter,
|
||||
setFilter: peopleStore.filterStore.setFilterParams,
|
||||
toggleAvatarEditor: peopleStore.avatarEditorStore.toggleAvatarEditor,
|
||||
resetProfile: peopleStore.targetUserStore.resetTargetUser,
|
||||
profile: peopleStore.targetUserStore.targetUser,
|
||||
avatarEditorIsOpen: peopleStore.avatarEditorStore.visible,
|
||||
isEditTargetUser: peopleStore.targetUserStore.isEditTargetUser,
|
||||
}))(
|
||||
withPeopleLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />)
|
||||
)
|
||||
);
|
@ -1,5 +0,0 @@
|
||||
export { default as SectionHeaderContent } from "./Header";
|
||||
export { default as CreateUserForm } from "./Body/createUserForm";
|
||||
export { default as UpdateUserForm } from "./Body/updateUserForm";
|
||||
export { default as AvatarEditorPage } from "./Body/avatarEditorPage";
|
||||
export { default as CreateAvatarEditorPage } from "./Body/createAvatarEditorPage";
|
@ -1,142 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Section from "@docspace/common/components/Section";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import toastr from "client/toastr";
|
||||
import { linkOAuth } from "@docspace/common/api/people";
|
||||
import { getAuthProviders } from "@docspace/common/api/settings";
|
||||
|
||||
import SectionUserBody from "./Section/Body/index";
|
||||
import {
|
||||
SectionHeaderContent,
|
||||
// CreateUserForm,
|
||||
// UpdateUserForm,
|
||||
// AvatarEditorPage,
|
||||
// CreateAvatarEditorPage,
|
||||
} from "./Section";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import { withRouter } from "react-router";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
class ProfileAction extends React.Component {
|
||||
componentDidMount() {
|
||||
const {
|
||||
match,
|
||||
fetchProfile,
|
||||
isEdit,
|
||||
setIsEditingForm,
|
||||
t,
|
||||
setDocumentTitle,
|
||||
setFirstLoad,
|
||||
profile,
|
||||
setLoadedProfile,
|
||||
} = this.props;
|
||||
const { userId } = match.params;
|
||||
setFirstLoad(false);
|
||||
this.documentElement = document.getElementsByClassName("hidingHeader");
|
||||
setDocumentTitle(t("ProfileAction"));
|
||||
if (isEdit) {
|
||||
setIsEditingForm(false);
|
||||
}
|
||||
if ((userId && !profile) || (profile && userId !== profile.userName)) {
|
||||
setLoadedProfile(false);
|
||||
fetchProfile(userId).finally(() => setLoadedProfile(true));
|
||||
}
|
||||
|
||||
if (!this.loaded && this.documentElement) {
|
||||
for (var i = 0; i < this.documentElement.length; i++) {
|
||||
this.documentElement[i].style.transition = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { match, fetchProfile } = this.props;
|
||||
const { userId } = match.params;
|
||||
const prevUserId = prevProps.match.params.userId;
|
||||
|
||||
if (userId !== undefined && userId !== prevUserId) {
|
||||
fetchProfile(userId);
|
||||
}
|
||||
|
||||
if (this.loaded && this.documentElement) {
|
||||
for (var i = 0; i < this.documentElement.length; i++) {
|
||||
this.documentElement[i].style.transition = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.setIsEditTargetUser(false);
|
||||
}
|
||||
|
||||
render() {
|
||||
// console.log("ProfileAction render");
|
||||
|
||||
this.loaded = false;
|
||||
const { profile, match, isMy, tReady, showCatalog, isAdmin } = this.props;
|
||||
const { userId, type } = match.params;
|
||||
|
||||
if (type) {
|
||||
this.loaded = true;
|
||||
} else if (profile) {
|
||||
this.loaded = profile.userName === userId || profile.id === userId;
|
||||
}
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Section.SectionHeader>
|
||||
<SectionHeaderContent tReady={tReady} loaded={this.loaded} />
|
||||
</Section.SectionHeader>
|
||||
|
||||
<Section.SectionBody>
|
||||
<SectionUserBody isMy={isMy} tReady={tReady} loaded={this.loaded} />
|
||||
</Section.SectionBody>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ProfileAction.propTypes = {
|
||||
setDocumentTitle: PropTypes.func.isRequired,
|
||||
isEdit: PropTypes.bool,
|
||||
setIsEditingForm: PropTypes.func.isRequired,
|
||||
fetchProfile: PropTypes.func.isRequired,
|
||||
profile: PropTypes.object,
|
||||
match: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default withRouter(
|
||||
inject(({ auth, peopleStore }) => {
|
||||
const { setDocumentTitle } = auth;
|
||||
const {
|
||||
usersStore,
|
||||
editingFormStore,
|
||||
targetUserStore,
|
||||
loadingStore,
|
||||
} = peopleStore;
|
||||
const { setProviders } = usersStore;
|
||||
const { isEdit, setIsEditingForm } = editingFormStore;
|
||||
const {
|
||||
getTargetUser: fetchProfile,
|
||||
targetUser: profile,
|
||||
setIsEditTargetUser,
|
||||
} = targetUserStore;
|
||||
const { setFirstLoad, setLoadedProfile } = loadingStore;
|
||||
|
||||
return {
|
||||
setProviders,
|
||||
setDocumentTitle,
|
||||
isEdit,
|
||||
setIsEditingForm,
|
||||
fetchProfile,
|
||||
profile,
|
||||
setFirstLoad,
|
||||
setLoadedProfile,
|
||||
setIsEditTargetUser,
|
||||
isAdmin: auth.isAdmin,
|
||||
showCatalog: auth.settingsStore.showCatalog,
|
||||
};
|
||||
})(withTranslation(["ProfileAction", "Common"])(observer(ProfileAction)))
|
||||
);
|
@ -257,7 +257,6 @@ module.exports = (env, argv) => {
|
||||
"./PeopleSelector": "./src/components/PeopleSelector",
|
||||
"./PeopleSelector/UserTooltip":
|
||||
"./src/components/PeopleSelector/sub-components/UserTooltip.js",
|
||||
"./MyProfile": "./src/pages/My",
|
||||
},
|
||||
shared: {
|
||||
...deps,
|
||||
|
Loading…
Reference in New Issue
Block a user