Merge branch 'master' of https://github.com/ONLYOFFICE/AppServer
This commit is contained in:
commit
c152d60950
@ -1,11 +1,15 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { ComboBox, TextInput } from "asc-web-components";
|
||||
import { ComboBox, TextInput, IconButton } from "asc-web-components";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
margin: 0 0 16px 0;
|
||||
|
||||
.remove_icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
class ContactField extends React.Component {
|
||||
@ -26,7 +30,10 @@ class ContactField extends React.Component {
|
||||
|
||||
inputName,
|
||||
inputValue,
|
||||
inputOnChange
|
||||
inputOnChange,
|
||||
|
||||
removeButtonName,
|
||||
removeButtonOnChange
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -46,6 +53,15 @@ class ContactField extends React.Component {
|
||||
isDisabled={isDisabled}
|
||||
onChange={inputOnChange}
|
||||
/>
|
||||
<IconButton
|
||||
id={removeButtonName}
|
||||
className="remove_icon"
|
||||
size="16"
|
||||
onClick={removeButtonOnChange}
|
||||
iconName={"CatalogTrashIcon"}
|
||||
isFill={true}
|
||||
isClickable={true}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
@ -12,6 +12,10 @@ const Container = styled.div`
|
||||
width: 120px;
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
|
||||
.field-select > div > div:first-child.combo-button-label {
|
||||
color: #A3A9AE;
|
||||
}
|
||||
`;
|
||||
|
||||
const getOptions = (patterns, keyPrefix) => {
|
||||
@ -30,6 +34,7 @@ const renderItems = (
|
||||
pattern,
|
||||
onTypeChange,
|
||||
onTextChange,
|
||||
onRemove,
|
||||
isDisabled
|
||||
) => {
|
||||
const items = contacts.map((contact, index) => {
|
||||
@ -50,6 +55,8 @@ const renderItems = (
|
||||
inputName={prefix + "value"}
|
||||
inputValue={contact.value}
|
||||
inputOnChange={onTextChange}
|
||||
removeButtonName={prefix + "remove"}
|
||||
removeButtonOnChange={onRemove}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -72,6 +79,7 @@ class ContactsField extends React.Component {
|
||||
onItemAdd,
|
||||
onItemTypeChange,
|
||||
onItemTextChange,
|
||||
onItemRemove,
|
||||
isDisabled
|
||||
} = this.props;
|
||||
|
||||
@ -80,6 +88,7 @@ class ContactsField extends React.Component {
|
||||
pattern,
|
||||
onItemTypeChange,
|
||||
onItemTextChange,
|
||||
onItemRemove,
|
||||
isDisabled
|
||||
);
|
||||
|
||||
|
@ -21,6 +21,7 @@ const MainContainer = styled.div`
|
||||
|
||||
.departments-field {
|
||||
position: relative;
|
||||
margin: 0 0 40px 0;
|
||||
|
||||
.department-add-btn {
|
||||
margin: 0 8px 8px 0;
|
||||
|
@ -1,12 +1,13 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { Headline } from 'asc-web-common';
|
||||
import { Heading } from "asc-web-components";
|
||||
|
||||
const Container = styled.div`
|
||||
margin: 0 0 40px 0;
|
||||
max-width: 1024px;
|
||||
`;
|
||||
|
||||
const StyledHeader = styled(Headline)`
|
||||
const StyledHeader = styled(Heading)`
|
||||
margin: 0 0 24px 0;
|
||||
line-height: unset;
|
||||
`;
|
||||
@ -16,7 +17,7 @@ const InfoFieldContainer = React.memo(props => {
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<StyledHeader type='content'>{headerText}</StyledHeader>
|
||||
<StyledHeader level={2} size='small'>{headerText}</StyledHeader>
|
||||
{children}
|
||||
</Container>
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { connect } from 'react-redux'
|
||||
import { Avatar, Button, Textarea, toastr, AvatarEditor, Text } from 'asc-web-components'
|
||||
import { withTranslation, Trans } from 'react-i18next';
|
||||
import { toEmployeeWrapper, getUserRole, getUserContactsPattern, getUserContacts, mapGroupsToGroupSelectorOptions, mapGroupSelectorOptionsToGroups, filterGroupSelectorOptions } from "../../../../../store/people/selectors";
|
||||
import { createProfile, getUserPhoto } from '../../../../../store/profile/actions';
|
||||
import { createProfile } from '../../../../../store/profile/actions';
|
||||
import { MainContainer, AvatarContainer, MainFieldsContainer } from './FormFields/Form'
|
||||
import TextField from './FormFields/TextField'
|
||||
import PasswordField from './FormFields/PasswordField'
|
||||
@ -38,6 +38,7 @@ class CreateUserForm extends React.Component {
|
||||
this.onContactsItemAdd = this.onContactsItemAdd.bind(this);
|
||||
this.onContactsItemTypeChange = this.onContactsItemTypeChange.bind(this);
|
||||
this.onContactsItemTextChange = this.onContactsItemTextChange.bind(this);
|
||||
this.onContactsItemRemove = this.onContactsItemRemove.bind(this);
|
||||
|
||||
this.onShowGroupSelector = this.onShowGroupSelector.bind(this);
|
||||
this.onCloseGroupSelector = this.onCloseGroupSelector.bind(this);
|
||||
@ -148,21 +149,6 @@ class CreateUserForm extends React.Component {
|
||||
});
|
||||
var allOptions = mapGroupsToGroupSelectorOptions(props.groups);
|
||||
var selected = mapGroupsToGroupSelectorOptions(profile.groups);
|
||||
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
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
visibleAvatarEditor: false,
|
||||
croppedAvatarImage: "",
|
||||
@ -286,6 +272,16 @@ class CreateUserForm extends React.Component {
|
||||
this.setState(stateCopy);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
onShowGroupSelector() {
|
||||
var stateCopy = Object.assign({}, this.state);
|
||||
stateCopy.selector.visible = true;
|
||||
@ -485,7 +481,7 @@ class CreateUserForm extends React.Component {
|
||||
</MainFieldsContainer>
|
||||
</MainContainer>
|
||||
<InfoFieldContainer headerText={t("Comments")}>
|
||||
<Textarea name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={9}/>
|
||||
<Textarea placeholder={t("AddСomment")} name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={9}/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer headerText={t("ContactInformation")}>
|
||||
<ContactsField
|
||||
@ -496,6 +492,7 @@ class CreateUserForm extends React.Component {
|
||||
onItemAdd={this.onContactsItemAdd}
|
||||
onItemTypeChange={this.onContactsItemTypeChange}
|
||||
onItemTextChange={this.onContactsItemTextChange}
|
||||
onItemRemove={this.onContactsItemRemove}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer headerText={t("SocialProfiles")}>
|
||||
@ -507,6 +504,7 @@ class CreateUserForm extends React.Component {
|
||||
onItemAdd={this.onContactsItemAdd}
|
||||
onItemTypeChange={this.onContactsItemTypeChange}
|
||||
onItemTextChange={this.onContactsItemTextChange}
|
||||
onItemRemove={this.onContactsItemRemove}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<div>
|
||||
|
@ -56,6 +56,7 @@ class UpdateUserForm extends React.Component {
|
||||
this.onContactsItemAdd = this.onContactsItemAdd.bind(this);
|
||||
this.onContactsItemTypeChange = this.onContactsItemTypeChange.bind(this);
|
||||
this.onContactsItemTextChange = this.onContactsItemTextChange.bind(this);
|
||||
this.onContactsItemRemove = this.onContactsItemRemove.bind(this);
|
||||
|
||||
this.openAvatarEditor = this.openAvatarEditor.bind(this);
|
||||
this.onSaveAvatar = this.onSaveAvatar.bind(this);
|
||||
@ -338,6 +339,16 @@ class UpdateUserForm extends React.Component {
|
||||
this.setState(stateCopy);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
openAvatarEditor(){
|
||||
let avatarDefault = this.state.avatar.image;
|
||||
let avatarDefaultSizes = /_orig_(\d*)-(\d*)./g.exec(this.state.avatar.image);
|
||||
@ -697,7 +708,7 @@ class UpdateUserForm extends React.Component {
|
||||
</MainFieldsContainer>
|
||||
</MainContainer>
|
||||
<InfoFieldContainer headerText={t("Comments")}>
|
||||
<Textarea name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={10}/>
|
||||
<Textarea placeholder={t("AddСomment")} name="notes" value={profile.notes} isDisabled={isLoading} onChange={this.onInputChange} tabIndex={10}/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer headerText={t("ContactInformation")}>
|
||||
<ContactsField
|
||||
@ -708,6 +719,7 @@ class UpdateUserForm extends React.Component {
|
||||
onItemAdd={this.onContactsItemAdd}
|
||||
onItemTypeChange={this.onContactsItemTypeChange}
|
||||
onItemTextChange={this.onContactsItemTextChange}
|
||||
onItemRemove={this.onContactsItemRemove}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<InfoFieldContainer headerText={t("SocialProfiles")}>
|
||||
@ -719,6 +731,7 @@ class UpdateUserForm extends React.Component {
|
||||
onItemAdd={this.onContactsItemAdd}
|
||||
onItemTypeChange={this.onContactsItemTypeChange}
|
||||
onItemTextChange={this.onContactsItemTextChange}
|
||||
onItemRemove={this.onContactsItemRemove}
|
||||
/>
|
||||
</InfoFieldContainer>
|
||||
<div>
|
||||
|
@ -13,9 +13,9 @@
|
||||
"CopyEmailAndPassword": "Copy e-mail & password",
|
||||
"UserType": "Type",
|
||||
"AddButton": "Add",
|
||||
"ContactInformation": "Contact Information",
|
||||
"ContactInformation": "Contact information",
|
||||
"AddContact": "Add contact",
|
||||
"SocialProfiles": "Social Profiles",
|
||||
"SocialProfiles": "Social profiles",
|
||||
"Search": "Search",
|
||||
"SelectAll": "Select all",
|
||||
"EmailPopupHelper": "The main e-mail is needed to restore access to the portal in case of loss of the password and send notifications. <1> 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.</1> The main e-mail can be used as a login when logging in to the portal.",
|
||||
@ -32,6 +32,7 @@
|
||||
|
||||
"ActivationLink": "Activation link",
|
||||
"AddPhoto": "Add photo",
|
||||
"AddСomment": "Add comment",
|
||||
"TemporaryPassword": "Temporary password",
|
||||
"SexMale": "Male",
|
||||
"SexFemale": "Female",
|
||||
|
@ -31,7 +31,8 @@
|
||||
"Message": "Чат",
|
||||
|
||||
"ActivationLink": "Activation link",
|
||||
"AddPhoto": "Add photo",
|
||||
"AddPhoto": "Добавить фотографию",
|
||||
"AddСomment": "Добавить комментарий",
|
||||
"TemporaryPassword": "Temporary password",
|
||||
"SexMale": "Мужской",
|
||||
"SexFemale": "Женский",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "asc-web-common",
|
||||
"version": "1.0.22",
|
||||
"version": "1.0.23",
|
||||
"description": "Ascensio System SIA common components and solutions library",
|
||||
"license": "AGPL-3.0",
|
||||
"files": [
|
||||
|
@ -5,7 +5,7 @@ import { withRouter } from "react-router";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import { logout } from "../../store/auth/actions";
|
||||
import PureStudioLayout from "./pureStudioLayout";
|
||||
import PureStudioLayout from "./PureStudioLayout";
|
||||
|
||||
const getSeparator = id => {
|
||||
return {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "asc-web-components",
|
||||
"version": "1.0.261",
|
||||
"version": "1.0.263",
|
||||
"description": "Ascensio System SIA component library",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/asc-web-components.js",
|
||||
|
@ -109,7 +109,7 @@ const EditContainer = styled.div`
|
||||
text-align: center;
|
||||
line-height: 19px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, rgba(6, 22, 38, 0) 24.48%, rgba(6, 22, 38, 0.75) 100%);
|
||||
background: ${props => props.gradient ? "linear-gradient(180deg, rgba(6, 22, 38, 0) 24.48%, rgba(6, 22, 38, 0.75) 100%)" : "transparent"};
|
||||
`;
|
||||
|
||||
const EmptyIcon = styled(Icons.CameraIcon)`
|
||||
@ -177,13 +177,15 @@ const Avatar = memo(props => {
|
||||
{avatarContent}
|
||||
</AvatarWrapper>
|
||||
{editing && (size === 'max') &&
|
||||
<EditContainer>
|
||||
<EditContainer gradient={!!source}>
|
||||
<EditLink>
|
||||
<Link
|
||||
type='action'
|
||||
title={editLabel}
|
||||
isTextOverflow={true}
|
||||
isHovered={true}
|
||||
fontSize='14px'
|
||||
fontWeight={600}
|
||||
color={whiteColor}
|
||||
onClick={editAction}
|
||||
>
|
||||
|
@ -21,6 +21,7 @@ const StyledIconBlock = styled.div`
|
||||
props.isDisabled || !props.isClickable ? "default" : "pointer"};
|
||||
height: 100%;
|
||||
padding-right: 7px;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
`;
|
||||
|
||||
const StyledChildrenBlock = styled.div`
|
||||
|
@ -14,12 +14,22 @@ const StyledPaging = styled.div`
|
||||
margin-right: 8px;
|
||||
max-width: 110px;
|
||||
}
|
||||
|
||||
.buttonCustomStyle {
|
||||
padding: 6px 8px 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledOnPage = styled.div`
|
||||
margin-left: auto;
|
||||
margin-right: 0px;
|
||||
|
||||
.hideDisabled {
|
||||
div[disabled] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 450px) {
|
||||
display: none;
|
||||
}
|
||||
@ -27,6 +37,13 @@ const StyledOnPage = styled.div`
|
||||
|
||||
const StyledPage = styled.div`
|
||||
margin-right: 8px;
|
||||
|
||||
.manualWidth {
|
||||
> div:last-of-type {
|
||||
width: 120%;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Paging = props => {
|
||||
@ -52,6 +69,7 @@ const Paging = props => {
|
||||
style={style}
|
||||
>
|
||||
<Button
|
||||
className="buttonCustomStyle"
|
||||
size='medium'
|
||||
scale={true}
|
||||
label={previousLabel}
|
||||
@ -60,6 +78,7 @@ const Paging = props => {
|
||||
{pageItems &&
|
||||
<StyledPage>
|
||||
<ComboBox
|
||||
className="manualWidth"
|
||||
directionY={openDirection}
|
||||
options={pageItems}
|
||||
onSelect={onSelectPageAction}
|
||||
@ -69,6 +88,7 @@ const Paging = props => {
|
||||
</StyledPage>
|
||||
}
|
||||
<Button
|
||||
className="buttonCustomStyle"
|
||||
size='medium'
|
||||
scale={true}
|
||||
label={nextLabel}
|
||||
@ -77,6 +97,7 @@ const Paging = props => {
|
||||
{countItems &&
|
||||
<StyledOnPage>
|
||||
<ComboBox
|
||||
className="hideDisabled"
|
||||
directionY={openDirection}
|
||||
directionX='right'
|
||||
options={countItems}
|
||||
|
@ -8,8 +8,6 @@ import InputBlock from '../input-block'
|
||||
import { Icons } from '../icons'
|
||||
import Link from '../link'
|
||||
import Text from '../text'
|
||||
//import DropDown from '../drop-down'
|
||||
|
||||
import Tooltip from "../tooltip";
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -53,6 +51,7 @@ const PasswordProgress = styled.div`
|
||||
|
||||
const NewPasswordButton = styled.div`
|
||||
margin-left: 16px;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
|
||||
svg {
|
||||
overflow: hidden;
|
||||
@ -123,20 +122,12 @@ class PasswordInput extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
/*onFocus = () => {
|
||||
this.setState({
|
||||
displayTooltip: true
|
||||
});
|
||||
}*/
|
||||
|
||||
onBlur = () => {
|
||||
/*this.setState({
|
||||
displayTooltip: false
|
||||
});*/
|
||||
this.refTooltip.current.hideTooltip();
|
||||
}
|
||||
|
||||
changeInputType = () => {
|
||||
this.refTooltip.current.hideTooltip();
|
||||
const newType = this.state.type === 'text' ? 'password' : 'text';
|
||||
|
||||
this.setState({
|
||||
@ -340,7 +331,6 @@ class PasswordInput extends React.Component {
|
||||
validCapital,
|
||||
validSpecial,
|
||||
disableCopyAction
|
||||
//displayTooltip
|
||||
} = this.state;
|
||||
|
||||
const iconsColor = isDisabled ? '#D0D5DA' : '#A3A9AE';
|
||||
@ -394,7 +384,6 @@ class PasswordInput extends React.Component {
|
||||
type={type}
|
||||
iconColor={`${iconsColor} !important`}
|
||||
isIconFill={true}
|
||||
//onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
hasWarning={hasWarning}
|
||||
placeholder={placeholder}
|
||||
@ -501,10 +490,3 @@ PasswordInput.defaultProps = {
|
||||
}
|
||||
|
||||
export default PasswordInput;
|
||||
/*
|
||||
{displayTooltip &&
|
||||
<DropDown directionY='top' manualY='150%' open={true}>
|
||||
{tooltipContent}
|
||||
</DropDown>
|
||||
}
|
||||
*/
|
@ -30,6 +30,7 @@ const StyledSpan = styled.span`
|
||||
const StyledText = styled(Heading)`
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
box-sizing: border-box;
|
||||
font-style: normal;
|
||||
&:hover{
|
||||
border-bottom: 1px dashed;
|
||||
@ -67,7 +68,7 @@ class ToggleContent extends React.Component {
|
||||
this.props.onChange && this.props.onChange(!this.state.isOpen);
|
||||
}}>
|
||||
<Arrow color="#333333" isfill={true} size='medium' isOpen={this.state.isOpen} />
|
||||
<StyledText level={2} size='medium' isInline={true}>{this.props.label}</StyledText>
|
||||
<StyledText level={2} size='small' isInline={true}>{this.props.label}</StyledText>
|
||||
</StyledSpan>
|
||||
<StyledContent isOpen={this.state.isOpen}>{this.props.children}</StyledContent>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user