Merge branch 'master' into feature/jenkins-file

This commit is contained in:
pavelbannov 2020-01-15 12:34:25 +03:00
commit cc3a58430f
52 changed files with 576 additions and 350 deletions

View File

@ -1,13 +1,11 @@
{
"InviteLinkTitle": "Invitation link",
"HelpAnswerLinkInviteSettings": "Share the link to invite your colleagues to your portal.",
"InviteLinkValidInterval": "This link is valid for {{ count }} day only.",
"InviteLinkValidInterval": "This link is valid for {{ count }} days only.",
"CopyToClipboard": "Copy the link",
"CloseButton": "Close",
"LinkCopySuccess": "Link has been copied to the clipboard",
"GetShortenLink": "Get shortened link",
"InviteUsersAsCollaborators": "Add users as {{typeGuests, lowercase}}",
"LoadingProcessing": "Loading...",
"InviteLinkValidInterval_plural": "This link is valid for {{ count }} days only."
"LoadingProcessing": "Loading..."
}

View File

@ -1,13 +1,11 @@
{
"InviteLinkTitle": "Пригласительная ссылка",
"HelpAnswerLinkInviteSettings": "Поделитесь ссылкой, чтобы пригласить коллег на портал.",
"InviteLinkValidInterval": "Эта ссылка действительна только в течение {{ count }} дня.",
"InviteLinkValidInterval": "Эта ссылка действительна только в течение {{ count }} дней.",
"CopyToClipboard": "Копировать ссылку",
"CloseButton": "Закрыть",
"LinkCopySuccess": "Ссылка скопирована в буфер обмена",
"GetShortenLink": "Получить сокращенную ссылку",
"InviteUsersAsCollaborators": "Добавить со статусом {{typeGuests, lowercase}}",
"LoadingProcessing": "Загрузка...",
"InviteLinkValidInterval_plural": "Эта ссылка действительна только в течение {{ count }} дней."
"LoadingProcessing": "Загрузка..."
}

View File

@ -248,6 +248,12 @@ class SectionBodyContent extends React.Component {
});
};
onKeyPress = event => {
if (event.key === "Enter") {
this.onSave();
}
}
render() {
const { t } = this.props;
const {
@ -279,6 +285,7 @@ class SectionBodyContent extends React.Component {
value={groupName}
onChange={this.onGroupChange}
isDisabled={inLoading}
onKeyUp={this.onKeyPress}
/>
</FieldContainer>
<FieldContainer
@ -292,7 +299,7 @@ class SectionBodyContent extends React.Component {
id="head-selector_button"
tabIndex={2}
options={[]}
isOpen={isHeadSelectorOpen}
opened={isHeadSelectorOpen}
selectedOption={groupManager}
scaled={true}
isDisabled={inLoading}
@ -319,7 +326,7 @@ class SectionBodyContent extends React.Component {
id="users-selector_button"
tabIndex={3}
options={[]}
isOpen={isUsersSelectorOpen}
opened={isUsersSelectorOpen}
isDisabled={inLoading}
selectedOption={{
key: 0,

View File

@ -3,7 +3,8 @@ import {
Button,
IconButton,
Text,
ToggleContent
ToggleContent,
Link
} from "asc-web-components";
import { getUserContacts, getUserRole } from "../../../../../store/people/selectors";
@ -39,13 +40,6 @@ const EditButtonWrapper = styled.div`
}
`;
const ContactTextTruncate = styled.div`
padding: 0 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const ToggleWrapper = styled.div`
width: 100%;
${props => props.isSelf && `margin-bottom: 24px;`}
@ -57,14 +51,28 @@ const ContactWrapper = styled.div`
display: inline-flex;
width: 300px;
margin-bottom: 12px;
.contact-link {
padding: 0 8px;
}
`;
const createContacts = contacts => {
const styledContacts = contacts.map((contact, index) => {
let url = null;
if (contact.link && contact.link.length > 0) {
url = stringFormat(contact.link, [contact.value]);
}
return (
<ContactWrapper key={index}>
<IconButton color="#333333" size={16} iconName={contact.icon} isFill={true} />
<ContactTextTruncate>{contact.value}</ContactTextTruncate>
<Link
className='contact-link'
isTextOverflow
href={url}
>
{contact.value}
</Link>
</ContactWrapper>
);
});
@ -72,6 +80,8 @@ const createContacts = contacts => {
return styledContacts;
};
const stringFormat = (string, data) => string.replace(/\{(\d+)\}/g, (m, n) => data[n] || m);
class SectionBodyContent extends React.PureComponent {
onEditSubscriptionsClick = () => console.log("Edit subscriptions onClick()");

View File

@ -29,7 +29,8 @@ class DepartmentField extends React.Component {
selectorIsVisible,
selectorSelectedOptions,
selectorOnSelectGroups
selectorOnSelectGroups,
searchPlaceHolderLabel
} = this.props;
return (
@ -50,6 +51,7 @@ class DepartmentField extends React.Component {
isMultiSelect={true}
onSelect={selectorOnSelectGroups}
onCancel={onCloseGroupSelector}
searchPlaceHolderLabel={searchPlaceHolderLabel}
/>
{selectorSelectedOptions.map(option => (
<SelectedItem

View File

@ -471,7 +471,7 @@ class CreateUserForm extends React.Component {
onCloseGroupSelector={this.onCloseGroupSelector}
onRemoveGroup={this.onRemoveGroup}
selectorIsVisible={selector.visible}
selectorSearchPlaceholder={t("Search")}
searchPlaceHolderLabel={t("SearchDepartments")}
selectorOptions={selector.options}
selectorSelectedOptions={selector.selected}
selectorAddButtonText={t("CustomAddDepartments", { departments })}

View File

@ -605,7 +605,7 @@ class UpdateUserForm extends React.Component {
onCloseGroupSelector={this.onCloseGroupSelector}
onRemoveGroup={this.onRemoveGroup}
selectorIsVisible={selector.visible}
selectorSearchPlaceholder={t("Search")}
searchPlaceHolderLabel={t("SearchDepartments")}
selectorOptions={selector.options}
selectorSelectedOptions={selector.selected}
selectorAddButtonText={t("CustomAddDepartments", { departments })}

View File

@ -16,7 +16,6 @@
"ContactInformation": "Contact information",
"AddContact": "Add contact",
"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.",
"ProfileTypePopupHelper": "Guests have limited access to some portal features and modules",
@ -41,6 +40,7 @@
"Phone": "Phone",
"ChangesSavedSuccessfully": "Changes saved successfully",
"EditProfile": "Edit profile",
"SearchDepartments": "Search departments",
"CustomEmployedSinceDate": "{{employedSinceDate}}",
"CustomPosition": "{{position}}",

View File

@ -16,7 +16,6 @@
"ContactInformation": "Контактные данные",
"AddContact": "Добавить новый контакт",
"SocialProfiles": "Социальные профили",
"Search": "Поиск",
"SelectAll": "Выбрать все",
"EmailPopupHelper": "Основной email нужен для восстановления доступа к порталу в случае потери пароля, а также для отправки оповещений. <1>Вы можете создать новый email на домене в качестве основного. В этом случае потребуется задать одноразовый пароль, чтобы пользователь смог войти на портал в первый раз.</1> Основной email можно использовать как логин при входе на портал.",
"ProfileTypePopupHelper": "Гости имеют ограниченный доступ к некоторым функциям и модулям портала",
@ -41,6 +40,7 @@
"Phone": "Телефон",
"ChangesSavedSuccessfully": "Изменения успешно сохранены",
"EditProfile": "Редактирование профиля",
"SearchDepartments": "Поиск группы",
"CustomEmployedSinceDate": "{{employedSinceDate}}",
"CustomPosition": "{{position}}",

View File

@ -50,23 +50,23 @@ export const getUserRole = user => {
export const getUserContactsPattern = () => {
return {
contact: [
{ type: "mail", icon: "MailIcon" },
{ type: "phone", icon: "PhoneIcon" },
{ type: "mobphone", icon: "MobileIcon" },
{ type: "gmail", icon: "GmailIcon" },
{ type: "skype", icon: "SkypeIcon" },
{ type: "mail", icon: "MailIcon", link: 'mailto:{0}' },
{ type: "phone", icon: "PhoneIcon", link: 'tel:{0}' },
{ type: "mobphone", icon: "MobileIcon", link: 'tel:{0}' },
{ type: "gmail", icon: "GmailIcon", link: 'mailto:{0}' },
{ type: "skype", icon: "SkypeIcon", link: 'skype:{0}?userinfo' },
{ type: "msn", icon: "WindowsMsnIcon" },
{ type: "icq", icon: "IcqIcon" },
{ type: "icq", icon: "IcqIcon", link: 'https://www.icq.com/people/{0}' },
{ type: "jabber", icon: "JabberIcon" },
{ type: "aim", icon: "AimIcon" }
],
social: [
{ type: "facebook", icon: "ShareFacebookIcon" },
{ type: "livejournal", icon: "LivejournalIcon" },
{ type: "myspace", icon: "MyspaceIcon" },
{ type: "twitter", icon: "ShareTwitterIcon" },
{ type: "blogger", icon: "BloggerIcon" },
{ type: "yahoo", icon: "YahooIcon" }
{ type: "facebook", icon: "ShareFacebookIcon", link: 'https://facebook.com/{0}' },
{ type: "livejournal", icon: "LivejournalIcon", link: 'https://{0}.livejournal.com' },
{ type: "myspace", icon: "MyspaceIcon", link: 'https://myspace.com/{0}' },
{ type: "twitter", icon: "ShareTwitterIcon", link: 'https://twitter.com/{0}' },
{ type: "blogger", icon: "BloggerIcon", link: 'https://{0}.blogspot.com' },
{ type: "yahoo", icon: "YahooIcon", link: 'mailto:{0}@yahoo.com' }
]
};
};

View File

@ -0,0 +1,6 @@
import { Provider } from "react-redux";
import store from "./store";
const withProvider = story => <Provider store={store}>{story()}</Provider>;
export default withProvider;

View File

@ -0,0 +1,8 @@
import { combineReducers } from 'redux';
import authReducer from "../../../src/store/auth/reducer";
const rootReducer = combineReducers({
auth: authReducer
});
export default rootReducer;

View File

@ -0,0 +1,14 @@
import { createStore } from 'redux';
import rootReducer from './rootReducer';
const configureStore = prelodedState => (
createStore(
rootReducer,
prelodedState
)
);
/* eslint-enable */
const store = configureStore({});
export default store;

View File

@ -1,6 +1,6 @@
{
"name": "asc-web-common",
"version": "1.0.34",
"version": "1.0.45",
"description": "Ascensio System SIA common components and solutions library",
"license": "AGPL-3.0",
"files": [

View File

@ -3,7 +3,6 @@ import PropTypes from "prop-types";
import Selector from "./sub-components/Selector";
import { utils, Backdrop, DropDown, Aside } from "asc-web-components";
import throttle from "lodash/throttle";
import onClickOutside from "react-onclickoutside";
const { desktop } = utils.device;
const displayTypes = ["dropdown", "aside", "auto"];
@ -22,15 +21,8 @@ class AdvancedSelector extends React.Component {
this.throttledResize = throttle(this.resize, 300);
}
handleClickOutside = e => {
// ..handling code goes here...
console.log(`ADSelector#${this.props.id} handleClickOutside`, e);
this.onClose(e);
};
componentDidMount() {
if(this.props.isOpen) {
this.props.enableOnClickOutside();
window.addEventListener("resize", this.throttledResize);
}
}
@ -57,12 +49,10 @@ class AdvancedSelector extends React.Component {
if(this.props.isOpen !== prevProps.isOpen) {
console.log(`ADSelector#${this.props.id} componentDidUpdate isOpen=${this.props.isOpen}`);
if(this.props.isOpen) {
this.props.enableOnClickOutside();
this.resize();
window.addEventListener("resize", this.throttledResize);
}
else {
this.props.disableOnClickOutside();
this.throttledResize.cancel();
window.removeEventListener("resize", this.throttledResize);
}
@ -80,7 +70,6 @@ class AdvancedSelector extends React.Component {
this.throttledResize && this.throttledResize.cancel();
window.removeEventListener("resize", this.throttledResize);
}
this.props.disableOnClickOutside();
}
getTypeByWidth = () => {
@ -103,7 +92,7 @@ class AdvancedSelector extends React.Component {
<div ref={this.ref} id={id} className={className} style={style}>
{displayType === "dropdown"
?
<DropDown open={isOpen} className="dropdown-container">
<DropDown open={isOpen} className="dropdown-container" clickOutsideAction={this.onClose}>
<Selector {...this.props} displayType={displayType} />
</DropDown>
:
@ -153,9 +142,7 @@ AdvancedSelector.propTypes = {
onGroupChange: PropTypes.func,
onCancel: PropTypes.func,
onAddNewClick: PropTypes.func,
loadNextPage: PropTypes.func,
enableOnClickOutside: PropTypes.func,
disableOnClickOutside: PropTypes.func
loadNextPage: PropTypes.func
};
AdvancedSelector.defaultProps = {
@ -169,17 +156,4 @@ AdvancedSelector.defaultProps = {
options: []
};
const EnhancedComponent = onClickOutside(AdvancedSelector);
class AdvancedSelectorContainer extends React.Component {
render() {
console.log(`AdvancedSelectorContainer isOpen=${this.props.isOpen} enableOnClickOutside=${this.props.isOpen}`);
return <EnhancedComponent disableOnClickOutside={true} {...this.props} />;
}
}
AdvancedSelectorContainer.propTypes = {
isOpen: PropTypes.bool
}
export default AdvancedSelectorContainer;
export default AdvancedSelector;

View File

@ -368,7 +368,7 @@ const Selector = props => {
}
return (
<div style={style} className="row-block" {...tooltipProps}>
<div style={style} className="row-option" {...tooltipProps}>
{content}
</div>
);
@ -466,7 +466,7 @@ const Selector = props => {
return (
<div
style={style}
className={`row-block${isSelected ? " selected" : ""}`}
className={`row-group${isSelected ? " selected" : ""}`}
>
{isMultiSelect && allowGroupSelection && (
<Checkbox
@ -608,7 +608,7 @@ const Selector = props => {
</AutoSizer>
{!hasNextPage && itemCount === 0 && (
<div className="row-block">
<div className="row-option">
<Text>
{!searchValue ? emptyOptionsLabel : emptySearchOptionsLabel}
</Text>
@ -626,7 +626,7 @@ const Selector = props => {
{displayType === "dropdown" && groups && groups.length > 0 && (
<Column className="column-groups" displayType={displayType} size={size}>
<Header className="header-groups">
<Text as="p" className="group_header" fontSize="15px" isBold={true}>
<Text as="p" className="group_header" fontSize="15px" fontWeight={600}>
{groupsHeaderLabel}
</Text>
</Header>

View File

@ -49,12 +49,26 @@ const dropdownStyles = css`
margin-left: -8px;
/* background-color: white; */
.row-block {
.row-group {
box-sizing: border-box;
height: 32px;
cursor: pointer;
padding-top: 8px;
padding-left: 8px;
.group_checkbox {
display: inline-block;
}
&:hover {
background-color: #f8f9f9;
border-radius: 3px;
}
}
.row-group.selected {
background-color: #eceef1;
border-radius: 3px;
}
}
}
@ -147,6 +161,24 @@ const StyledSelector = styled(Container)`
}
`}
`}
.options_searcher {
div:first-child {
:hover {
border-color: #D0D5DA;
}
:focus, :focus-within {
border-color: #2DA7DB;
}
& > input {
color: #A3A9AE;
}
}
}
}
.body-options {
@ -154,9 +186,12 @@ const StyledSelector = styled(Container)`
margin-left: -8px;
/* background-color: white; */
.row-block {
.row-option {
padding-left: 8px;
padding-top: 8px;
box-sizing: border-box;
height: 32px;
cursor: pointer;
.option-info {
position: absolute;
@ -167,21 +202,6 @@ const StyledSelector = styled(Container)`
}
}
.row-block {
box-sizing: border-box;
height: 32px;
cursor: pointer;
padding-top: 8px;
&:hover {
background-color: #f8f9f9;
}
}
.row-block.selected {
background-color: #eceef1;
}
.footer {
grid-area: footer;
}

View File

@ -92,7 +92,8 @@ class GroupSelector extends React.Component {
isDisabled,
onSelect,
onCancel,
t
t,
searchPlaceHolderLabel
} = this.props;
return (
@ -110,7 +111,7 @@ class GroupSelector extends React.Component {
isOpen={isOpen}
isMultiSelect={isMultiSelect}
isDisabled={isDisabled}
searchPlaceHolderLabel={t("SearchPlaceholder")}
searchPlaceHolderLabel={searchPlaceHolderLabel || t("SearchPlaceholder")}
selectButtonLabel={t("AddDepartmentsButtonLabel")}
selectAllLabel={t("SelectAllLabel")}
emptySearchOptionsLabel={t("EmptySearchOptionsLabel")}
@ -125,17 +126,18 @@ class GroupSelector extends React.Component {
}
GroupSelector.propTypes = {
id: PropTypes.string,
className: PropTypes.oneOf([PropTypes.string, PropTypes.array]),
style: PropTypes.object,
isOpen: PropTypes.bool,
onSelect: PropTypes.func,
onCancel: PropTypes.func,
useFake: PropTypes.bool,
isMultiSelect: PropTypes.bool,
id: PropTypes.string,
isDisabled: PropTypes.bool,
isMultiSelect: PropTypes.bool,
isOpen: PropTypes.bool,
language: PropTypes.string,
t: PropTypes.func
onCancel: PropTypes.func,
onSelect: PropTypes.func,
searchPlaceHolderLabel: PropTypes.string,
style: PropTypes.object,
t: PropTypes.func,
useFake: PropTypes.bool,
};
GroupSelector.defaultProps = {

View File

@ -7,14 +7,16 @@ import {
boolean
} from "@storybook/addon-knobs/react";
import Section from "../../../.storybook/decorators/section";
import withProvider from "../../../.storybook/decorators/redux";
import GroupSelector from ".";
import { BooleanValue } from "react-values";
import { Button } from "asc-web-components";
//import withReadme from "storybook-readme/with-readme";
//import Readme from "./README.md";
storiesOf("Components|GroupSelector", module)
.addDecorator(withProvider)
.addDecorator(withKnobs)
//.addDecorator(withReadme(Readme))
.addParameters({ options: { addonPanelInRight: false } })

View File

@ -117,9 +117,14 @@ class Layout extends React.Component {
});
};
clearNavTimeout = () => {
if (this.timeout == null) return;
clearTimeout(this.timeout);
this.timeout = null;
}
handleNavMouseEnter = () => {
if (!this.state.isNavHoverEnabled) return;
this.timeout = setTimeout(() => {
this.setState({
isBackdropVisible: false,
@ -131,12 +136,7 @@ class Layout extends React.Component {
handleNavMouseLeave = () => {
if (!this.state.isNavHoverEnabled) return;
if (this.timeout != null) {
clearTimeout(this.timeout);
this.timeout = null;
}
this.clearNavTimeout();
this.setState({
isBackdropVisible: false,
isNavOpened: false,
@ -145,6 +145,7 @@ class Layout extends React.Component {
};
toggleAside = () => {
this.clearNavTimeout();
this.setState({
isBackdropVisible: true,
isNavOpened: false,
@ -198,8 +199,8 @@ class Layout extends React.Component {
badgeNumber={item.notifications}
onClick={item.onClick}
onBadgeClick={e => {
item.onBadgeClick(e);
this.toggleAside();
item.onBadgeClick(e);
}}
url={item.url}
>

View File

@ -9,6 +9,7 @@ import {IconButton, ContextMenuButton, MainButton, SearchInput, Paging} from "as
import withReadme from 'storybook-readme/with-readme';
import { boolean, withKnobs } from '@storybook/addon-knobs/react';
import Readme from './README.md';
import withProvider from "../../../.storybook/decorators/redux";
const currentUser = {
id: '00000000-0000-0000-0000-000000000000',
@ -211,6 +212,7 @@ const sectionPagingContent = <Paging
/>
storiesOf('Components|Layout', module)
.addDecorator(withProvider)
.addDecorator(withKnobs)
.addDecorator(withReadme(Readme))
.add('base', () => (

View File

@ -37,6 +37,7 @@ const HeaderNav = React.memo(props => {
badgeNumber={module.notifications}
onClick={module.onClick}
onBadgeClick={module.onBadgeClick}
noHover={true}
/>
))}
{props.user && (

View File

@ -29,6 +29,7 @@ const HeaderComponent = React.memo(props => {
iconName="MenuIcon"
badgeNumber={props.badgeNumber}
onClick={props.onClick}
noHover={true}
/>
<Headline type="header" color="#FFFFFF">
{props.currentModule && props.currentModule.title}

View File

@ -22,8 +22,11 @@ const NavItemWrapper = styled(Link)`
position: relative;
box-sizing: border-box;
&:hover {
background: #0D3760;
${props => !props.noHover && css`
&:hover {
background: #0D3760;
text-decoration: none;
}`
}
`;
@ -34,8 +37,9 @@ const NavItemLabel = styled(Text)`
const badgeCss = css`
position: absolute;
top: 10px;
right: 10px;
top: 2px;
right: 4px;
overflow: inherit;
`;
const NavItemBadge = styled(Badge)`
@ -53,14 +57,16 @@ const NavItem = React.memo(props => {
badgeNumber,
onClick,
onBadgeClick,
url
url,
noHover
} = props;
const color = active ? activeColor : baseColor;
return separator ? (
<NavItemSeparator />
) : (
<NavItemWrapper
<NavItemWrapper
noHover={noHover}
href={url}
onClick={onClick}>
{React.createElement(Icons[iconName], {
@ -75,7 +81,7 @@ const NavItem = React.memo(props => {
)}
<NavItemBadge
opened={opened}
number={badgeNumber}
label={badgeNumber}
onClick={onBadgeClick}
/>
</NavItemWrapper>
@ -94,6 +100,7 @@ NavItem.propTypes = {
onClick: PropTypes.func,
opened: PropTypes.bool,
separator: PropTypes.bool,
noHover: PropTypes.bool
};
export default NavItem;

View File

@ -9,6 +9,7 @@ import {IconButton, ContextMenuButton, MainButton, SearchInput, Paging} from 'as
import withReadme from 'storybook-readme/with-readme';
import { boolean, withKnobs } from '@storybook/addon-knobs/react';
import Readme from './README.md';
import withProvider from "../../../.storybook/decorators/redux";
const HeaderContent = styled.div`
display: flex;
@ -114,6 +115,7 @@ const sectionPagingContent = <Paging
/>
storiesOf('Components|PageLayout', module)
.addDecorator(withProvider)
.addDecorator(withKnobs)
.addDecorator(withReadme(Readme))
.add('base', () => (

View File

@ -11,10 +11,12 @@ import Section from "../../../.storybook/decorators/section";
import PeopleSelector from ".";
import { BooleanValue } from "react-values";
import { Button } from "asc-web-components";
import withProvider from "../../../.storybook/decorators/redux";
//import withReadme from "storybook-readme/with-readme";
//import Readme from "./README.md";
storiesOf("Components|PeopleSelector", module)
.addDecorator(withProvider)
.addDecorator(withKnobs)
//.addDecorator(withReadme(Readme))
.addParameters({ options: { addonPanelInRight: false } })

View File

@ -1,6 +1,6 @@
{
"name": "asc-web-components",
"version": "1.0.297",
"version": "1.0.312",
"description": "Ascensio System SIA component library",
"license": "AGPL-3.0",
"main": "dist/asc-web-components.js",
@ -112,6 +112,7 @@
"react-custom-scrollbars": "^4.2.1",
"react-dropzone": "^10.2.1",
"react-lifecycles-compat": "^3.0.4",
"react-onclickoutside": "^6.9.0",
"react-text-mask": "^5.4.3",
"react-toastify": "^5.4.1",
"react-tooltip": "^3.11.1",

View File

@ -10,7 +10,7 @@ import { Badge } from "asc-web-components";
```jsx
<Badge
number={10}
label="10"
backgroundColor="#ED7309"
color="#FFFFFF"
fontSize="11px"
@ -34,7 +34,7 @@ import { Badge } from "asc-web-components";
| `fontWeight` | `number` | - | - | `800` | CSS font-weight |
| `id` | `string` | - | - | - | Accepts id |
| `maxWidth` | `string` | - | - | `50px` | CSS max-width |
| `number` | `number` | - | - | `0` | Number value |
| `label` | `string` | - | - | `0` | Value |
| `onClick` | `func` | - | - | - | onClick event |
| `padding` | `string` | - | - | `0 5px` | CSS padding |
| `style` | `obj`, `array` | - | - | - | Accepts css style |

View File

@ -13,7 +13,7 @@ storiesOf('Components|Badge', module)
.add('base', () => (
<Section>
<Badge
number={number('number', 10)}
label={text('label', '10')}
backgroundColor={color('backgroundColor', '#ED7309')}
color={color('color', '#FFFFFF')}
fontSize={text('fontSize', '11px')}
@ -21,9 +21,46 @@ storiesOf('Components|Badge', module)
borderRadius={text('borderRadius', '11px')}
padding={text('padding', '0 5px')}
maxWidth={text('maxWidth', '50px')}
onClick={(e)=>{
onClick={(e) => {
action('onClick')(e);
}}
/>
<br />
<Badge
label="New"
backgroundColor={color('backgroundColor', '#ED7309')}
color={color('color', '#FFFFFF')}
fontSize={text('fontSize', '11px')}
fontWeight={number('fontWeight', 800)}
borderRadius={text('borderRadius', '11px')}
padding={text('padding', '0 5px')}
maxWidth={text('maxWidth', '50px')}
onClick={(e) => {
action('onClick')(e);
}}
/>
<br />
<Badge
label="Ver.2"
backgroundColor="#A3A9AE"
color={color('color', '#FFFFFF')}
fontSize={text('fontSize', '11px')}
fontWeight={number('fontWeight', 800)}
borderRadius={text('borderRadius', '11px')}
padding={text('padding', '0 5px')}
maxWidth={text('maxWidth', '50px')}
onClick={(e) => {
action('onClick')(e);
}}
/>
<p>
Text with badge
<Badge
label="3"
onClick={(e) => {
action('onClick')(e);
}}
/>
</p>
</Section>
));

View File

@ -11,12 +11,12 @@ describe('<Badge />', () => {
expect(wrapper).toExist();
});
it('displays number', () => {
it('displays label', () => {
const wrapper = mount(
<Badge number={10} />
<Badge label='10' />
);
expect(wrapper.prop('number')).toBe(10);
expect(wrapper.prop('label')).toBe('10');
});
it('call onClick()', () => {

View File

@ -4,15 +4,26 @@ import styled from 'styled-components';
import Text from "../text";
const StyledBadge = styled.div`
display: ${props => (props.label.length > 0 || props.label != '0') ? 'inline-block' : 'none'};
border: 1px solid transparent;
border-radius: ${props => props.borderRadius};
width: fit-content;
padding: 2px;
line-height: 0.8;
cursor: pointer;
overflow: hidden;
:hover {
border-color: ${props => props.backgroundColor};
}
`;
const StyledInner = styled.div`
background-color: ${props => props.backgroundColor};
border-radius: ${props => props.borderRadius};
padding: ${props => props.padding};
max-width: ${props => props.maxWidth};
text-align: center;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
display: ${props => props.number > 0 ? 'inline-block' : 'none'};
user-select: none;
line-height: 1.5;
`;
@ -21,24 +32,47 @@ const Badge = props => {
//console.log("Badge render");
const onClick = e => {
if (props.onClick) {
e.stopPropagation();
props.onClick(e);
}
if (!props.onClick) return;
e.preventDefault();
e.stopPropagation();
props.onClick(e);
};
const { fontSize, color, fontWeight } = props;
const {
fontSize,
color,
fontWeight,
backgroundColor,
borderRadius,
padding,
maxWidth
} = props;
return (
<StyledBadge {...props} onClick={onClick}>
<Text fontWeight={fontWeight} color={color} fontSize={fontSize}>
{props.number}
</Text>
<StyledBadge
{...props}
onClick={onClick}
>
<StyledInner
backgroundColor={backgroundColor}
borderRadius={borderRadius}
padding={padding}
maxWidth={maxWidth}
>
<Text
fontWeight={fontWeight}
color={color}
fontSize={fontSize}>
{props.label}
</Text>
</StyledInner>
</StyledBadge>
);
};
Badge.propTypes = {
number: PropTypes.number,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
backgroundColor: PropTypes.string,
color: PropTypes.string,
fontSize: PropTypes.string,
@ -53,7 +87,7 @@ Badge.propTypes = {
};
Badge.defaultProps = {
number: 0,
label: 0,
backgroundColor: '#ED7309',
color: '#FFFFFF',
fontSize: "11px",

View File

@ -32,7 +32,8 @@ const baseProps = {
selectedOption: {
key: 0,
icon: 'CatalogFolderIcon',
label: "Select"
label: "Select",
default: true
},
options: baseOptions,
opened: false,
@ -41,6 +42,17 @@ const baseProps = {
scaled: true
};
const toggleDisplayProps = {
options: [],
selectedOption: {
key: 0,
label: "Selected option"
},
scaled: false,
size: "content",
displayType: "toggle"
};
describe('<ComboBox />', () => {
it('rendered without error', () => {
const wrapper = mount(
@ -76,6 +88,13 @@ describe('<ComboBox />', () => {
expect(wrapper.prop('opened')).toEqual(true);
});
it('opened without borders', () => {
const wrapper = mount(<ComboBox {...baseProps} opened={true} noBorder={true} />);
expect(wrapper.prop('opened')).toEqual(true);
expect(wrapper.prop('noBorder')).toEqual(true);
});
it('with DropDown max height', () => {
const wrapper = mount(<ComboBox {...baseProps} dropDownMaxHeight={200} />);
@ -188,24 +207,6 @@ describe('<ComboBox />', () => {
expect(wrapper.state('isOpen')).toBe(false);
});
it('causes function handleClick() with opened prop', () => {
const wrapper = mount(<ComboBox {...baseProps} opened={true} />);
const instance = wrapper.instance();
instance.handleClick(new Event('click'));
expect(wrapper.state('isOpen')).toBe(false);
});
it('causes function handleClick()', () => {
const wrapper = mount(<ComboBox {...baseProps} />);
const instance = wrapper.instance();
instance.handleClick(new Event('click'));
expect(wrapper.state('isOpen')).toBe(false);
});
it('causes function handleClick() with simulate', () => {
const wrapper = mount(<ComboBox {...baseProps} opened={true} />);
@ -222,38 +223,35 @@ describe('<ComboBox />', () => {
expect(wrapper.state('isOpen')).toBe(true);
});
it('componentDidUpdate() state lifecycle test', () => {
it('componentDidUpdate() lifecycle test', () => {
const wrapper = shallow(<ComboBox {...baseProps} />);
const instance = wrapper.instance();
const newSelected = { key: 1, label: "Select" };
wrapper.setState({ isOpen: false });
jest.spyOn(instance, 'setIsOpen');
instance.componentDidUpdate(wrapper.props(), wrapper.state());
wrapper.setProps({
opened: true
});
expect(wrapper.state()).toBe(wrapper.state());
});
expect(wrapper.props().opened).toBe(true);
it('componentDidUpdate() props lifecycle test', () => {
const wrapper = shallow(<ComboBox {...baseProps} />);
const instance = wrapper.instance();
wrapper.setProps({
opened: false
});
expect(wrapper.props().opened).toBe(false);
instance.componentDidUpdate({
opened: true,
selectedOption: {
key: 1,
label: "Select"
}
}, wrapper.state());
selectedOption: newSelected
}, {
isOpen: true
});
expect(wrapper.props()).toBe(wrapper.props());
});
instance.forceUpdate(); //Need for manual re-render, enzyme issue
it('componentWillUnmount() lifecycle test', () => {
const wrapper = mount(<ComboBox {...baseProps} opened={true} />);
const componentWillUnmount = jest.spyOn(wrapper.instance(), 'componentWillUnmount');
wrapper.unmount();
expect(componentWillUnmount).toHaveBeenCalled();
expect(instance.setIsOpen).toHaveBeenCalled();
});
it('accepts id', () => {
@ -279,4 +277,47 @@ describe('<ComboBox />', () => {
expect(wrapper.getDOMNode().style).toHaveProperty('color', 'red');
});
it('render like toggle displayType', () => {
const onToggleClick = jest.fn();
const wrapper = mount(
<ComboBox
{...toggleDisplayProps}
toggleAction={onToggleClick}
/>
);
expect(wrapper.prop('displayType')).toEqual('toggle');
});
it('click on toggle', () => {
const onToggleClick = jest.fn();
const wrapper = mount(
<ComboBox
{...toggleDisplayProps}
toggleAction={onToggleClick}
/>
);
jest.spyOn(wrapper.instance(), 'setIsOpen');
wrapper.simulate('click');
expect(onToggleClick).toHaveBeenCalled();
});
it('click outside', () => {
const onToggleClick = jest.fn();
const wrapper = mount(<ComboBox {...baseProps} opened toggleAction={onToggleClick} />);
const instance = wrapper.instance();
jest.spyOn(instance, 'handleClickOutside');
instance.handleClickOutside(); //TODO: rework with simulation
expect(wrapper.state('isOpen')).toBe(false);
expect(wrapper.prop('opened')).toBe(true);
expect(instance.handleClickOutside).toHaveBeenCalled();
expect(onToggleClick).toHaveBeenCalled();
});
});

View File

@ -3,7 +3,6 @@ import DropDown from '../drop-down'
import DropDownItem from '../drop-down-item'
import PropTypes from 'prop-types'
import React from 'react'
import { handleAnyClick } from '../../utils/event';
import isEqual from 'lodash/isEqual';
import styled from 'styled-components';
@ -31,26 +30,32 @@ class ComboBox extends React.Component {
isOpen: props.opened,
selectedOption: props.selectedOption
};
if (props.opened)
handleAnyClick(true, this.handleClick);
}
handleClick = (e) => {
if (this.state.isOpen && !this.ref.current.contains(e.target)) {
this.toggle(false);
this.props.toggleAction && this.props.toggleAction(e, true);
}
shouldComponentUpdate(nextProps, nextState) {
const needUpdate = !isEqual(this.props, nextProps) || !isEqual(this.state, nextState);
//console.log("shouldComponentUpdate", needUpdate);
return needUpdate;
}
stopAction = (e) => e.preventDefault();
toggle = (isOpen) => this.setState({ isOpen: isOpen });
setIsOpen = (isOpen) => this.setState({ isOpen: isOpen });
handleClickOutside = e => {
//console.log(`ComboBox handleClickOutside`, e);
this.setState({ isOpen: !this.state.isOpen }, () => {
this.props.toggleAction && this.props.toggleAction(e, this.state.isOpen);
})
};
comboBoxClick = (e) => {
if (this.props.isDisabled || e && e.target.closest('.optionalBlock')) return;
this.toggle(!this.state.isOpen);
this.props.toggleAction && this.props.toggleAction(e, this.state.isOpen);
this.setState({ isOpen: !this.state.isOpen }, () => {
this.props.toggleAction && this.props.toggleAction(e, this.state.isOpen);
})
};
optionClick = (option) => {
@ -62,21 +67,9 @@ class ComboBox extends React.Component {
this.props.onSelect && this.props.onSelect(option);
};
componentWillUnmount() {
handleAnyClick(false, this.handleClick);
}
shouldComponentUpdate(nextProps, nextState) {
return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState);
}
componentDidUpdate(prevProps, prevState) {
if (this.props.opened !== prevProps.opened) {
handleAnyClick(this.props.opened, this.handleClick);
}
if (this.state.isOpen !== prevState.isOpen) {
handleAnyClick(this.state.isOpen, this.handleClick);
if (this.props.opened !== prevProps.opened && this.state.isOpen !== prevState.isOpen) {
this.setIsOpen(this.state.isOpen);
}
if (this.props.selectedOption !== prevProps.selectedOption) {
@ -149,6 +142,7 @@ class ComboBox extends React.Component {
directionY={directionY}
manualY='102%'
open={isOpen}
clickOutsideAction={this.handleClickOutside}
{...dropDownMaxHeightProp}
{...dropDownManualWidthProp}
>

View File

@ -65,16 +65,16 @@ const StyledComboButton = styled.div`
max-width: 175px;
${props => props.noBorder && `
line-height: 15px;
border-bottom: 1px dashed transparent;
text-decoration: underline dashed transparent;
`}
${props => props.isOpen && props.noBorder && `
border-bottom: 1px dashed;
text-decoration: underline dashed;
`};
}
.combo-button-label:hover{
${props => props.noBorder && !props.isDisabled && `
border-bottom: 1px dashed;
text-decoration: underline dashed;
`}
}
`;

View File

@ -140,15 +140,6 @@ describe('<ContextMenuButton />', () => {
expect(wrapper.props()).toBe(wrapper.props());
});
it('componentWillUnmount() props lifecycle test', () => {
const wrapper = shallow(<ContextMenuButton {...baseProps} />);
const instance = wrapper.instance();
instance.componentWillUnmount();
expect(wrapper).toExist(false);
});
it('accepts id', () => {
const wrapper = mount(
<ContextMenuButton {...baseProps} id="testId" />

View File

@ -4,7 +4,6 @@ import PropTypes from 'prop-types'
import DropDownItem from '../drop-down-item'
import DropDown from '../drop-down'
import IconButton from '../icon-button'
import { handleAnyClick } from '../../utils/event';
const StyledOuter = styled.div`
display: inline-block;
@ -28,39 +27,35 @@ class ContextMenuButton extends React.Component {
this.toggle = this.toggle.bind(this);
this.onIconButtonClick = this.onIconButtonClick.bind(this);
this.onDropDownItemClick = this.onDropDownItemClick.bind(this);
if (props.opened)
handleAnyClick(true, this.handleClick);
}
handleClick = (e) => this.state.isOpen && !this.ref.current.contains(e.target) && this.toggle(false);
stopAction = (e) => e.preventDefault();
toggle = (isOpen) => this.setState({ isOpen: isOpen });
componentWillUnmount() {
handleAnyClick(false, this.handleClick);
}
componentDidUpdate(prevProps, prevState) {
if (this.props.opened !== prevProps.opened) {
this.toggle(this.props.opened);
}
if (this.state.isOpen !== prevState.isOpen) {
handleAnyClick(this.state.isOpen, this.handleClick);
}
}
onIconButtonClick = () => {
if (!this.props.isDisabled) {
this.setState({
data: this.props.getData(),
isOpen: !this.state.isOpen
});
}
else {
this.stopAction
if (this.props.isDisabled) {
this.stopAction;
return;
}
console.log("ContextMenuButton onIconButtonClick (isOpen)", this.state.isOpen);
this.setState({
data: this.props.getData(),
isOpen: !this.state.isOpen
});
}
clickOutsideAction = () => {
console.log("ContextMenuButton clickOutsideAction", );
this.onIconButtonClick();
}
onDropDownItemClick = (item) => {
@ -83,6 +78,7 @@ class ContextMenuButton extends React.Component {
clickColor,
size,
iconName,
iconOpenName,
iconHoverName,
iconClickName,
isDisabled,
@ -97,7 +93,7 @@ class ContextMenuButton extends React.Component {
} = this.props;
const { isOpen } = this.state;
const iconButtonName = isOpen && iconOpenName ? iconOpenName : iconName;
return (
<StyledOuter ref={this.ref} className={className} id={id} style={style}>
<IconButton
@ -105,7 +101,7 @@ class ContextMenuButton extends React.Component {
hoverColor={hoverColor}
clickColor={clickColor}
size={size}
iconName={iconName}
iconName={iconButtonName}
iconHoverName={iconHoverName}
iconClickName={iconClickName}
isFill={false}
@ -119,7 +115,7 @@ class ContextMenuButton extends React.Component {
<DropDown
directionX={directionX}
open={isOpen}
clickOutsideAction={this.onIconButtonClick}
clickOutsideAction={this.clickOutsideAction}
>
{
this.state.data.map((item, index) =>
@ -148,6 +144,7 @@ ContextMenuButton.propTypes = {
iconHoverName: PropTypes.string,
iconClickName: PropTypes.string,
iconOpenName: PropTypes.string,
onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func,

View File

@ -98,7 +98,8 @@ describe('<DropDown />', () => {
expect(wrapper.props.children).toEqual(child);
});
it('componentDidUpdate() state lifecycle test', () => {
//TODO: Fix final condition checks
/* it('componentDidUpdate() state lifecycle test', () => {
const wrapper = shallow(<DropDown {...baseProps} />);
const instance = wrapper.instance();
@ -107,16 +108,17 @@ describe('<DropDown />', () => {
instance.componentDidUpdate(wrapper.props(), wrapper.state());
expect(wrapper.state()).toBe(wrapper.state());
});
}); */
it('componentDidUpdate() props lifecycle test', () => {
//TODO: Fix final condition checks
/* it('componentDidUpdate() props lifecycle test', () => {
const wrapper = shallow(<DropDown {...baseProps} />);
const instance = wrapper.instance();
instance.componentDidUpdate({ open: true }, wrapper.state());
expect(wrapper.props()).toBe(wrapper.props());
});
}); */
it('accepts id', () => {
const wrapper = mount(

View File

@ -5,6 +5,7 @@ import CustomScrollbarsVirtualList from '../scrollbar/custom-scrollbars-virtual-
import DropDownItem from '../drop-down-item'
import Backdrop from '../backdrop'
import { FixedSizeList } from "react-window"
import onClickOutside from "react-onclickoutside";
const StyledDropdown = styled.div`
font-family: 'Open Sans',sans-serif,Arial;
@ -80,17 +81,41 @@ class DropDown extends React.PureComponent {
}
componentDidMount() {
this.checkPosition();
}
componentDidUpdate(prevProps) {
if (this.props.open !== prevProps.open) {
if(this.props.open) {
this.props.enableOnClickOutside();
this.checkPosition();
}
}
toggleDropDown = () => {
this.props.clickOutsideAction && this.props.clickOutsideAction(!this.props.open);
componentWillUnmount() {
this.props.disableOnClickOutside();
}
componentDidUpdate(prevProps) {
if (this.props.open !== prevProps.open) {
if(this.props.open) {
this.props.enableOnClickOutside();
this.checkPosition();
}
else {
this.props.disableOnClickOutside();
}
}
}
handleClickOutside = e => {
// ..handling code goes here...
console.log(`DropDown handleClickOutside`, e);
this.toggleDropDown(e);
//this.onClose(e);
//this.setIsOpen(!this.state.isOpen);
//this.props.toggleAction && this.props.toggleAction(e, this.state.isOpen);
};
toggleDropDown = (e) => {
this.props.clickOutsideAction && this.props.clickOutsideAction(e, !this.props.open);
}
checkPosition = () => {
@ -123,7 +148,6 @@ class DropDown extends React.PureComponent {
//console.log("DropDown render");
return (
<>
{(withBackdrop && open && isTablet) && <Backdrop visible zIndex={149} onClick={this.toggleDropDown} />}
<StyledDropdown
ref={this.dropDownRef}
{...this.props}
@ -145,6 +169,7 @@ class DropDown extends React.PureComponent {
</FixedSizeList>
: children}
</StyledDropdown>
{(withBackdrop && open && isTablet) && <Backdrop visible zIndex={149} onClick={this.toggleDropDown} />}
</>
);
}
@ -164,7 +189,9 @@ DropDown.propTypes = {
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
withArrow: PropTypes.bool,
withBackdrop: PropTypes.bool,
clickOutsideAction: PropTypes.func
clickOutsideAction: PropTypes.func,
enableOnClickOutside: PropTypes.func,
disableOnClickOutside: PropTypes.func
};
DropDown.defaultProps = {
@ -174,4 +201,14 @@ DropDown.defaultProps = {
withBackdrop: true
};
export default DropDown
const EnhancedComponent = onClickOutside(DropDown);
class DropDownContainer extends React.Component {
render() {
//console.log(`AdvancedSelectorContainer isOpen=${this.props.isOpen} enableOnClickOutside=${this.props.isOpen}`);
return <EnhancedComponent disableOnClickOutside={true} {...this.props} />;
}
}
export default DropDownContainer;

View File

@ -138,7 +138,7 @@ class FilterItem extends React.Component {
directionX='left'
toggleAction={(e,isOpen)=>{
this.setState({
isOpen: !isOpen
isOpen: isOpen
})
}}
></StyledComboBox>
@ -206,25 +206,28 @@ class FilterBlock extends React.Component {
});
}
if (this.state.hideFilterItems.length > 0) {
var open = false;
var hideFilterItemsList = this.state.hideFilterItems.map(function (item) {
open = item.key.indexOf('_-1') == -1 ? false : true
return <FilterItem
block={true}
isDisabled={_this.props.isDisabled}
key={item.key}
groupItems={_this.props.getFilterData().filter(function (t) {
return (t.group == item.group && t.group != t.key);
})}
onSelectFilterItem={_this.props.onClickFilterItem}
id={item.key}
groupLabel={item.groupLabel}
opened={item.key.indexOf('_-1') == -1 ? false : true}
label={item.label}
onClose={_this.onDeleteFilterItem}>
</FilterItem>
})
hideItems.push(
<HideFilter key="hide-filter" count={this.state.hideFilterItems.length} isDisabled={this.props.isDisabled}>
<HideFilter key="hide-filter" count={this.state.hideFilterItems.length} isDisabled={this.props.isDisabled} open={open}>
{
this.state.hideFilterItems.map(function (item) {
return <FilterItem
block={true}
isDisabled={_this.props.isDisabled}
key={item.key}
groupItems={_this.props.getFilterData().filter(function (t) {
return (t.group == item.group && t.group != t.key);
})}
onSelectFilterItem={_this.props.onClickFilterItem}
id={item.key}
groupLabel={item.groupLabel}
opened={false}
label={item.label}
onClose={_this.onDeleteFilterItem}>
</FilterItem>
})
hideFilterItemsList
}
</HideFilter>
);

View File

@ -10,12 +10,12 @@ class FilterButton extends React.PureComponent {
id={this.props.id}
title='Actions'
iconName='RectangleFilterIcon'
iconOpenName='RectangleFilterClickIcon'
color='#A3A9AE'
size={this.props.iconSize}
isDisabled={this.props.isDisabled}
getData={this.props.getData}
iconHoverName='RectangleFilterHoverIcon'
iconClickName='RectangleFilterClickIcon'
className='filter-button'
></ContextMenuButton>
)

View File

@ -3,6 +3,7 @@ import styled from "styled-components";
import { Icons } from "../icons";
import DropDown from "../drop-down";
import { handleAnyClick } from "../../utils/event";
import PropTypes from 'prop-types';
const Caret = styled.div`
width: 7px;
@ -54,7 +55,7 @@ class HideFilter extends React.Component {
this.ref = React.createRef();
this.dropDownRef = React.createRef();
this.state = {
popoverOpen: false
popoverOpen: this.props.open
};
}
@ -71,7 +72,7 @@ class HideFilter extends React.Component {
handleClick = e => {
this.state.popoverOpen &&
!this.ref.current.contains(e.target) &&
!this.dropDownRef.current.firstElementChild.contains(e.target) &&
this.onClick(false);
};
@ -120,5 +121,10 @@ class HideFilter extends React.Component {
);
}
}
HideFilter.propTypes = {
children: PropTypes.any,
open: PropTypes.bool,
isDisabled: PropTypes.bool,
count: PropTypes.number
}
export default HideFilter;

View File

@ -35,12 +35,15 @@ const StyledFilterBlock = styled.div`
.filter-button {
div:active {
svg path:first-child {
fill: #ECEEF1;
fill: #ECEEF1;
}
}
div:first-child:hover {
svg path:first-child {
stroke: #adb3b8;
}
svg path:not(:first-child) {
stroke: #555F65;
stroke: #555F65;
}
}
}

View File

@ -48,7 +48,7 @@ class IconButton extends React.PureComponent {
onMouseEnter && onMouseEnter(e);
}
onMouseLeave(e) {
const { isDisabled, iconName, color, onMouseDown } = this.props;
const { isDisabled, iconName, color, onMouseLeave } = this.props;
if (isDisabled) return;
@ -57,7 +57,7 @@ class IconButton extends React.PureComponent {
currentIconColor: color
});
onMouseDown && onMouseDown(e);
onMouseLeave && onMouseLeave(e);
}
onMouseDown(e) {
const {
@ -177,6 +177,7 @@ IconButton.propTypes = {
onMouseEnter: PropTypes.func,
onMouseDown: PropTypes.func,
onMouseUp: PropTypes.func,
onMouseLeave: PropTypes.func,
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
dataTip: PropTypes.string

View File

@ -0,0 +1,3 @@
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.9862 0.721877L16.2791 0.0147705L8.50091 7.79295L0.722732 0.0147736L0.015625 0.72188L7.7938 8.50006L0.0156276 16.2782L0.722734 16.9853L8.50091 9.20716L16.2791 16.9853L16.9862 16.2782L9.20801 8.50005L16.9862 0.721877Z" fill="#D0D5DA"/>
</svg>

After

Width:  |  Height:  |  Size: 390 B

View File

@ -117,6 +117,7 @@ import OrigRectangleFilterHoverIcon from './rectangle.filter.hover.react.svg';
import OrigRectangleFilterClickIcon from './rectangle.filter.click.react.svg';
import OrigCatalogButtonIcon from './catalog.button.react.svg';
import OrigCrossIcon from './cross.react.svg';
import OrigCrossSidebarIcon from './cross.sidebar.react.svg';
import OrigCheckboxIcon from './checkbox.react.svg';
import OrigCheckboxCheckedIcon from './checkbox.checked.react.svg';
import OrigCheckboxIndeterminateIcon from './checkbox.indeterminate.react.svg';
@ -373,6 +374,10 @@ export const CrossIcon = createStyledIcon(
OrigCrossIcon,
'CrossIcon'
);
export const CrossSidebarIcon = createStyledIcon(
OrigCrossSidebarIcon,
'CrossSidebarIcon'
);
export const DangerIcon = createStyledIcon(
OrigDangerIcon,
'DangerIcon'

View File

@ -1,5 +1,5 @@
<svg width="33" height="26" viewBox="0 0 33 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.5 3C0.5 1.61929 1.61929 0.5 3 0.5H21.1954C21.9785 0.5 22.7163 0.866919 23.1889 1.49134L31.2783 12.1803C31.6858 12.7188 31.6832 13.4633 31.2719 13.999L23.1913 24.5226C22.7182 25.1388 21.9854 25.5 21.2084 25.5H3C1.61929 25.5 0.5 24.3807 0.5 23V3Z" fill="#ECEEF1" stroke="#A3A9AE"/>
<rect x="13.5" y="6.5" width="13" height="1" transform="rotate(90 13.5 6.5)" fill="#D8D8D8" stroke="#979797"/>
<rect x="6.5" y="12.5" width="13" height="1" fill="#D8D8D8" stroke="#979797"/>
<rect x="13.5" y="6.5" width="13" height="1" transform="rotate(90 13.5 6.5)" fill="#D8D8D8" stroke="#555F65"/>
<rect x="6.5" y="12.5" width="13" height="1" fill="#D8D8D8" stroke="#555F65"/>
</svg>

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 585 B

View File

@ -166,7 +166,7 @@ class MainButton extends React.PureComponent {
return (
<GroupMainButton {...this.props} ref={this.ref}>
<StyledMainButton {...this.props} onClick={this.onMainButtonClick}>
<Text fontSize='16px' fontWeight={600} color="#fff">
<Text fontSize='16px' fontWeight='bold' color="#fff">
{this.props.text}
</Text>
</StyledMainButton>

View File

@ -6,6 +6,7 @@ import Aside from "../aside";
import Heading from "../heading";
import { desktop } from "../../utils/device";
import throttle from "lodash/throttle";
import { Icons } from "../icons";
const Dialog = styled.div`
position: relative;
@ -37,35 +38,22 @@ const StyledHeader = styled.div`
border-bottom: 1px solid #dee2e6;
`;
const CloseButton = styled.a`
cursor: pointer;
position: absolute;
right: 16px;
top: 20px;
width: 16px;
height: 16px;
const CloseButton = styled(Icons.CrossSidebarIcon)`
cursor: pointer;
position: absolute;
width: 17px;
height: 17px;
min-width: 17px;
min-height: 17px;
right: 16px;
top: 19px;
&:hover {
&:before,
&:after {
background-color: #657077;
}
}
&:before,
&:after {
position: absolute;
left: 8px;
content: " ";
height: 16px;
width: 1px;
background-color: #d8d8d8;
}
&:before {
transform: rotate(45deg);
}
&:after {
transform: rotate(-45deg);
path {
fill: #657077;
}
}
`;

View File

@ -6,6 +6,13 @@ import InputBlock from '../input-block';
const StyledSearchInput = styled.div`
font-family: Open Sans;
font-style: normal;
.search-input-block {
& > input {
font-size: 14px;
font-weight: 600;
}
}
`;
class SearchInput extends React.Component {
@ -74,6 +81,7 @@ class SearchInput extends React.Component {
return (
<StyledSearchInput className={this.props.className} style={this.props.style}>
<InputBlock
className='search-input-block'
ref={this.input}
id={this.props.id}
name={this.props.name}

View File

@ -8,7 +8,7 @@ const styleCss = css`
outline: 0 !important;
font-weight: ${props => props.fontWeight
? props.fontWeight
: props.isBold == true ? 700 : 500};
: props.isBold == true ? 700 : 'normal'};
${props => props.isItalic == true && css`font-style: italic;`}
${props => props.backgroundColor && css`background-color: ${props => props.backgroundColor};`}
${props => props.isInline

View File

@ -4,11 +4,29 @@ import { Icons } from '../icons'
import Heading from '../heading'
import PropTypes from 'prop-types'
const StyledContainer = styled.div`
.span-toggle-content {
cursor: pointer;
user-select: none;
}
.heading-toggle-content {
height: 24px;
line-height: 26px;
box-sizing: border-box;
font-style: normal;
&:hover {
border-bottom: 1px dashed;
}
}
`;
const StyledContent = styled.div`
color: #333;
display: ${props => props.isOpen ? 'block' : 'none'};
padding-top: 9px;
padding-top: 6px;
`;
// eslint-disable-next-line react/prop-types, no-unused-vars
@ -21,74 +39,69 @@ const Arrow = styled(IconArrow)`
transform: ${props => props.isOpen && 'rotate(180deg)'};
`;
const StyledSpan = styled.span`
cursor: pointer;
user-select: none;
`;
const StyledText = styled(Heading)`
height: 24px;
line-height: 26px;
box-sizing: border-box;
font-style: normal;
&:hover{
border-bottom: 1px dashed;
}
`;
class ToggleContent extends React.Component {
constructor(props) {
super(props);
const { isOpen } = props;
this.state = {
isOpen: this.props.isOpen
isOpen
};
}
toggleContent = (isOpen) => this.setState({ isOpen: isOpen });
toggleContent = () => this.setState({ isOpen: !this.state.isOpen });
componentDidUpdate(prevProps) {
if (this.props.isOpen !== prevProps.isOpen) {
this.setState({ isOpen: this.props.isOpen });
const { isOpen } = this.props;
if (isOpen !== prevProps.isOpen) {
this.setState({ isOpen });
}
}
render() {
//console.log("ToggleContent render");
// console.log("ToggleContent render");
const {
children,
className,
id,
label,
style
} = this.props;
const { isOpen } = this.state;
return (
<div
className={this.props.className}
id={this.props.id}
style={this.props.style}
<StyledContainer
className={className}
id={id}
style={style}
>
<StyledSpan onClick={() => {
this.toggleContent(!this.state.isOpen);
this.props.onChange && this.props.onChange(!this.state.isOpen);
}}>
<Arrow color="#333333" isfill={true} size='medium' isOpen={this.state.isOpen} />
<StyledText level={2} size='small' isInline={true}>{this.props.label}</StyledText>
</StyledSpan>
<StyledContent isOpen={this.state.isOpen}>{this.props.children}</StyledContent>
</div>
<span className='span-toggle-content' onClick={this.toggleContent}>
<Arrow color="#333" isfill={true} size='medium' isOpen={isOpen} />
<Heading className='heading-toggle-content' level={2} size='small' isInline={true}>{label}</Heading>
</span>
<StyledContent isOpen={isOpen}>{children}</StyledContent>
</StyledContainer>
)
}
}
ToggleContent.propTypes = {
label: PropTypes.string.isRequired,
isOpen: PropTypes.bool,
onChange: PropTypes.func,
className: PropTypes.string,
children: PropTypes.any,
className: PropTypes.string,
id: PropTypes.string,
isOpen: PropTypes.bool,
label: PropTypes.string.isRequired,
onChange: PropTypes.func,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
}
ToggleContent.defaultProps = {
isOpen: false,
label: "Some label"
label: ""
}
export default ToggleContent;

View File

@ -10678,6 +10678,11 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-onclickoutside@^6.9.0:
version "6.9.0"
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz#a54bc317ae8cf6131a5d78acea55a11067f37a1f"
integrity sha512-8ltIY3bC7oGhj2nPAvWOGi+xGFybPNhJM0V1H8hY/whNcXgmDeaeoCMPPd8VatrpTsUWjb/vGzrmu6SrXVty3A==
react-popper-tooltip@^2.8.3:
version "2.10.0"
resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.10.0.tgz#4d8383644d1002a50bd2bf74b2d1214d84ffc77c"