Merge branch 'master' into feature/asc-web-common

This commit is contained in:
Alexey Safronov 2019-11-26 11:42:57 +03:00
commit 14f92deedb
19 changed files with 157 additions and 109 deletions

View File

@ -373,9 +373,16 @@ class CreateUserForm extends React.Component {
helpButtonHeaderContent={t("Mail")}
tooltipContent={
<Trans i18nKey="EmailPopupHelper" i18n={i18n}>
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={{marginTop: "1rem", marginBottom: "1rem"}} >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.Body fontSize={13}>
<Trans i18nKey="EmailPopupHelper" i18n={i18n}>
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={{marginTop: "1rem", marginBottom: "1rem"}} >
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.Body>
}
/>
<PasswordField

View File

@ -1,25 +1,29 @@
import React from "react";
import React, { lazy, Suspense } from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import CustomizationSettings from "./customization";
import WhiteLabel from "./whitelabel";
import { Loader } from "asc-web-components";
const CustomizationSettings = lazy(() => import("./customization"));
const WhiteLabel = lazy(() => import("./whitelabel"));
const Common = ({ match }) => {
const basePath = '/settings/common';
return (
<Switch>
<Route
exact
path={[`${basePath}/customization`, '/common', match.path]}
component={CustomizationSettings}
/>
<Route
exact
path={`${basePath}/whitelabel`}
component={WhiteLabel}
/>
</Switch>
<Suspense fallback={<Loader className="pageLoader" type="rombs" size={40} />}>
<Switch>
<Route
exact
path={[`${basePath}/customization`, '/common', match.path]}
component={CustomizationSettings}
/>
<Route
exact
path={`${basePath}/whitelabel`}
component={WhiteLabel}
/>
</Switch>
</Suspense>
);
};

View File

@ -1,6 +1,7 @@
import React, { lazy } from "react";
import React, { lazy, Suspense } from "react";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { Loader } from "asc-web-components";
const AccessRightsSettings = lazy(() => import("./accessRights"));
@ -8,26 +9,28 @@ const Security = () => {
const basePath = "/settings/security";
return (
<Switch>
<Route
exact
path={[`${basePath}/accessrights`, basePath, `${basePath}/accessrights/owner`]}
component={AccessRightsSettings}
selectedTab={0}
/>
<Route
exact
path={[`${basePath}/accessrights/admins`, basePath]}
component={AccessRightsSettings}
selectedTab={1}
/>
<Route
exact
path={[`${basePath}/accessrights/modules`, basePath]}
component={AccessRightsSettings}
selectedTab={2}
/>
</Switch>
<Suspense fallback={<Loader className="pageLoader" type="rombs" size={40} />}>
<Switch>
<Route
exact
path={[`${basePath}/accessrights`, basePath, `${basePath}/accessrights/owner`]}
component={AccessRightsSettings}
selectedTab={0}
/>
<Route
exact
path={[`${basePath}/accessrights/admins`, basePath]}
component={AccessRightsSettings}
selectedTab={1}
/>
<Route
exact
path={[`${basePath}/accessrights/modules`, basePath]}
component={AccessRightsSettings}
selectedTab={2}
/>
</Switch>
</Suspense>
);
};

View File

@ -1,30 +1,34 @@
import React from "react";
import React, { lazy,Suspense } from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import { withRouter } from "react-router";
import Layout from './Layout';
import CommonSettings from "./categories/common";
import SecuritySettings from "./categories/security";
import { Loader } from "asc-web-components";
const CommonSettings = lazy(() => import("./categories/common"));
const SecuritySettings = lazy(() => import("./categories/security"));
const Settings = () => {
const basePath = '/settings';
return (
<Layout key='1'>
<Switch>
<Route
path={`${basePath}/security`}
component={SecuritySettings}
/>
<Route
path={[`${basePath}/common`, basePath]}
component={CommonSettings}
/>
<Redirect
to={{
pathname: "/error/404",
}}
/>
</Switch>
<Suspense fallback={<Loader className="pageLoader" type="rombs" size={40} />}>
<Switch>
<Route
path={`${basePath}/security`}
component={SecuritySettings}
/>
<Route
path={[`${basePath}/common`, basePath]}
component={CommonSettings}
/>
<Redirect
to={{
pathname: "/error/404",
}}
/>
</Switch>
</Suspense>
</Layout>
);
};

View File

@ -1,6 +1,6 @@
{
"name": "asc-web-components",
"version": "1.0.190",
"version": "1.0.196",
"description": "Ascensio System SIA component library",
"license": "AGPL-3.0",
"main": "dist/asc-web-components.js",

View File

@ -229,7 +229,11 @@ class AvatarEditorBody extends React.Component {
handleScale = e => {
const scale = parseFloat(e.target.value);
this.setState({ scale })
this.setState({ scale });
this.props.onSizeChange({
width: this.setEditorRef.current.getImage().width,
height: this.setEditorRef.current.getImage().height
});
};
onImageReady() {
this.setState({

View File

@ -33,7 +33,7 @@ const ComboBoxMonthStyle = styled.div`
${props =>
props.size === "base"
? `width: 172px; max-width: 172px;`
: `width: 205px; max-width: 205px;`}
: `width: 205px; max-width: 196px;`}
`;
const ComboBoxDateStyle = styled.div`
@ -49,7 +49,7 @@ const CalendarContainer = styled.div`
`;
const CalendarStyle = styled.div`
${props => (props.size === "base" ? "width: 260px;" : `width: 294px;`)}
${props => (props.size === "base" ? "width: 265px;" : `width: 289px;`)}
box-sizing: content-box;
${props =>
@ -92,7 +92,7 @@ const CalendarStyle = styled.div`
`;
const Month = styled.div`
width: ${props => (props.size === "base" ? "267px" : "303px")};
width: ${props => (props.size === "base" ? "267px" : "295px")};
`;
class Calendar extends Component {
@ -202,19 +202,15 @@ class Calendar extends Component {
selectedDate: dateInNextMonth,
openToDate: dateInNextMonth
});
} else if (
this.compareDates(dateInCurrentMonth, this.state.selectedDate) !== 0
) {
} else {
newState = this.mapPropsToState({
...this.state,
selectedDate: dateInCurrentMonth
});
}
if (newState) {
this.setState(newState);
this.props.onChange && this.props.onChange(newState.selectedDate);
}
this.setState(newState);
this.props.onChange && this.props.onChange(newState.selectedDate);
};
getListMonth = (minDate, maxDate, openToDate, months) => {

View File

@ -7,7 +7,7 @@ import { isArrayEqual } from "../../../utils/array";
const StyledDays = styled.div`
display: flex;
flex-wrap: wrap;
${props => (props.size === "base" ? "width: 270px;" : "width: 310px;")}
${props => (props.size === "base" ? "width: 270px;" : "width: 294px;")}
`;
class Days extends React.Component {

View File

@ -6,7 +6,7 @@ import PropTypes from "prop-types";
import { isArrayEqual } from "../../../utils/array";
const StyledWeekdays = styled.div`
width: ${props => (props.size === "base" ? "265px" : "310px")};
width: ${props => (props.size === "base" ? "272px" : "295px")};
display: flex;
margin-bottom: -5px;

View File

@ -378,7 +378,7 @@ class DatePicker extends Component {
<Content>
<Header>
<HeaderText>
<Text.Body isBold={true} fontSize={21}>
<Text.Body isBold={true} fontSize={20}>
{calendarHeaderContent}
</Text.Body>
</HeaderText>

View File

@ -22,7 +22,7 @@ const StyledDropdown = styled.div`
${props => (props.directionY === 'bottom' && css`top: ${props => props.manualY ? props.manualY : '100%'};`)}
${props => (props.directionX === 'right' && css`right: ${props => props.manualX ? props.manualX : '0px'};`)}
${props => (props.directionX === 'left' && css`left: ${props => props.manualX ? props.manualX : '0px'};`)}
z-index: 1000;
z-index: 150;
margin-top: ${props => (props.isUserPreview ? '6px' : '0px')};
margin-right: ${props => (props.isUserPreview ? '6px' : '0px')};
display: ${props => (props.isOpen || props.opened ? 'block' : 'none')};

View File

@ -214,7 +214,7 @@ class FilterInput extends React.Component {
const filterArr = Array.from(Array.from(this.filterWrapper.current.children).find(x => x.id === 'filter-items-container').children);
const filterButton = Array.from(Array.from(this.filterWrapper.current.children).find(x => x.id != 'filter-items-container').children)[0];
if (fullWidth <= this.minWidth) {
if (fullWidth <= this.minWidth && fullWidth > 0) {
this.setState({
openFilterItems: [],
hideFilterItems: cloneObjectsArray(currentFilterItems)

View File

@ -17,7 +17,7 @@ const StyledGroupButtonsMenu = styled.div`
width: 100%;
white-space: nowrap;
display: ${props => props.visible ? 'block' : 'none'};
z-index: 290;
z-index: 195;
`;
const CloseButton = styled.div`

View File

@ -11,7 +11,7 @@ const StyledNav = styled.nav`
position: absolute;
right: 0;
height: 56px;
z-index: 300;
z-index: 190;
& > div {
margin: 0 0 0 16px;

View File

@ -11,7 +11,7 @@ const StyledHeader = styled.header`
align-items: center;
background-color: ${backgroundColor};
display: none;
z-index: 200;
z-index: 185;
position: absolute;
width: 100vw;

View File

@ -204,19 +204,15 @@ class TabContainer extends Component {
<>
<StyledScrollbar
autoHide={onScrollHide}
autoHideDuration={500}
autoHideTimeout={1000}
stype="preMediumBlack"
className="scrollbar"
ref={this.scrollRef}
>
<NavItem
onMouseMove={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
className="className_items"
>
<NavItem className="className_items">
{children.map((item, index) => (
<Label
onMouseMove={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
ref={this.arrayRefs[index]}
onClick={this.titleClick.bind(
this,

View File

@ -22,23 +22,25 @@ const mask = [/\d/, /\d/, "/", /\d/, /\d/, "/", /\d/, /\d/, /\d/, /\d/];
### Properties
| Props | Type | Required | Values | Default | Description |
| ---------------- | :------: | :------: | :-----------------------------: | :-----: | ------------------------------------------------------------------------------------------------------ |
| `id` | `string` | - | - | - | Used as HTML `id` property |
| `name` | `string` | - | - | - | Used as HTML `name` property |
| `value` | `string` | ✅ | - | - | Value of the input |
| `autoComplete` | `string` | - | - | - | Used as HTML `autocomplete` property |
| `onChange` | `func` | - | - | - | Called with the new value. Required when input is not read only. Parent should pass it back as `value` |
| `onBlur` | `func` | - | - | - | Called when field is blurred |
| `onFocus` | `func` | - | - | - | Called when field is focused |
| `isAutoFocussed` | `bool` | - | - | - | Focus the input field on initial render |
| `isDisabled` | `bool` | - | - | `false` | Indicates that the field cannot be used (e.g not authorised, or changes not saved) |
| `isReadOnly` | `bool` | - | - | `false` | Indicates that the field is displaying read-only content |
| `hasError` | `bool` | - | - | - | Indicates the input field has an error |
| `hasWarning` | `bool` | - | - | - | Indicates the input field has a warning |
| `placeholder` | `string` | - | - | - | Placeholder text for the input |
| `type` | `string` | | `text`, `password` | `text` | Supported type of the input fields. |
| `size` | `string` | | `base`, `middle`, `big`, `huge` | `base` | Supported size of the input fields. |
| `scale` | `bool` | - | - | - | Indicates the input field has scale |
| `withBorder` | `bool` | - | - | `true` | Indicates that component contain border |
| `mask` | `array` | - | - | - | input text mask |
| Props | Type | Required | Values | Default | Description |
| ---------------- | :------: | :------: | :-----------------------------: | :-------: | ------------------------------------------------------------------------------------------------------ |
| `id` | `string` | - | - | - | Used as HTML `id` property |
| `name` | `string` | - | - | - | Used as HTML `name` property |
| `value` | `string` | ✅ | - | - | Value of the input |
| `autoComplete` | `string` | - | - | - | Used as HTML `autocomplete` property |
| `onChange` | `func` | - | - | - | Called with the new value. Required when input is not read only. Parent should pass it back as `value` |
| `onBlur` | `func` | - | - | - | Called when field is blurred |
| `onFocus` | `func` | - | - | - | Called when field is focused |
| `isAutoFocussed` | `bool` | - | - | - | Focus the input field on initial render |
| `isDisabled` | `bool` | - | - | `false` | Indicates that the field cannot be used (e.g not authorised, or changes not saved) |
| `isReadOnly` | `bool` | - | - | `false` | Indicates that the field is displaying read-only content |
| `hasError` | `bool` | - | - | - | Indicates the input field has an error |
| `hasWarning` | `bool` | - | - | - | Indicates the input field has a warning |
| `placeholder` | `string` | - | - | - | Placeholder text for the input |
| `type` | `string` | | `text`, `password` | `text` | Supported type of the input fields. |
| `size` | `string` | | `base`, `middle`, `big`, `huge` | `base` | Supported size of the input fields. |
| `scale` | `bool` | - | - | - | Indicates the input field has scale |
| `withBorder` | `bool` | - | - | `true` | Indicates that component contain border |
| `mask` | `array` | - | - | - | input text mask |
| `errorMessage` | `string` | - | - | - | Error message text |
| `errorColor` | `string` | - | - | "#C96C27" | Error text color |

View File

@ -4,6 +4,7 @@ import styled from 'styled-components';
import commonInputStyle from '../text-input/common-input-styles';
import MaskedInput from 'react-text-mask'
import isEqual from "lodash/isEqual";
import { Text } from "../text";
/* eslint-disable no-unused-vars */
/* eslint-disable react/prop-types */
@ -80,6 +81,18 @@ const StyledInput = styled(Input).attrs((props) => ({
${props => !props.withBorder && `border: none;`}
`;
const ErrorLabel = styled.label`
word-wrap: break-word;
font-size: 10px;
max-width: ${props =>
(props.scale && '100%') ||
(props.size === 'base' && '173px') ||
(props.size === 'middle' && '300px') ||
(props.size === 'big' && '350px') ||
(props.size === 'huge' && '500px')
};
`;
class TextInput extends React.Component {
shouldComponentUpdate(nextProps) {
return !isEqual(this.props, nextProps);
@ -87,7 +100,21 @@ class TextInput extends React.Component {
render() {
// console.log(`TextInput render id=${this.props.id}`);
return (<StyledInput {...this.props} />);
const {scale, size, errorMessage, color, hasError} = this.props;
return (
<>
<StyledInput {...this.props} />
{hasError ?
<Text.Body fontSize={10} color={color}>
<ErrorLabel
scale={scale}
size={size}
>
{errorMessage}
</ErrorLabel>
</Text.Body>
: null}
</>);
}
}
@ -114,7 +141,9 @@ TextInput.propTypes = {
isReadOnly: PropTypes.bool,
hasError: PropTypes.bool,
hasWarning: PropTypes.bool,
autoComplete: PropTypes.string
autoComplete: PropTypes.string,
errorMessage: PropTypes.string,
color: PropTypes.string
}
TextInput.defaultProps = {
@ -128,7 +157,8 @@ TextInput.defaultProps = {
hasWarning: false,
autoComplete: 'off',
withBorder: true,
keepCharPositions: false
keepCharPositions: false,
color: "#C96C27"
}
export default TextInput

View File

@ -2,7 +2,7 @@ import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { StringValue } from 'react-values';
import { withKnobs, boolean, text, select, number } from '@storybook/addon-knobs/react';
import { withKnobs, boolean, text, select, number, color } from '@storybook/addon-knobs/react';
import withReadme from 'storybook-readme/with-readme';
import Readme from './README.md';
import TextInput from '.';
@ -42,6 +42,8 @@ storiesOf('Components|Input', module)
withBorder={boolean('withBorder', true)}
mask={text("mask", null)}
value={value}
errorMessage={text("errorMessage", "Error text. Lorem ipsum dolor sit amet, consectetuer adipiscing elit")}
errorColor={color('errorColor', "#C96C27")}
onChange={e => {
set(e.target.value);
}}