Merge branch 'feature/workspaces' of https://github.com/ONLYOFFICE/AppServer into feature/workspaces
This commit is contained in:
commit
7cec3df259
@ -12,8 +12,9 @@
|
||||
"scripts": {
|
||||
"wipe": "rimraf node_modules yarn.lock web/**/node_modules products/**/node_modules",
|
||||
"build": "yarn workspaces run build",
|
||||
"start": "concurrently \"wsrun --parallel start\"",
|
||||
"test": "yarn workspace @appserver/components test"
|
||||
"start": "concurrently \"wsrun --parallel start\"",
|
||||
"test": "yarn workspace @appserver/components test",
|
||||
"sb-components": "yarn workspace @appserver/components storybook"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lerna": "^3.22.1",
|
||||
|
@ -15,7 +15,7 @@ import AdvancedSelector2 from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import Button from "@appserver/components/button";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import UserTooltip from "../PeopleSelector/sub-components/UserTooltip";
|
||||
import UserTooltip from "studio/PeopleSelector/UserTooltip";
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
|
@ -10,8 +10,8 @@ import {
|
||||
StyledFilterItemContent,
|
||||
StyledCloseButtonBlock,
|
||||
} from "../StyledFilterInput";
|
||||
import GroupSelector from "people/GroupSelector"; //TODO: Move GroupSelector out of FilterItem
|
||||
import PeopleSelector from "../../PeopleSelector";
|
||||
import GroupSelector from "people/GroupSelector"; //TODO: Move out GroupSelector of FilterItem
|
||||
import PeopleSelector from "studio/PeopleSelector"; //TODO: Move out PeopleSelector of FilterItem
|
||||
|
||||
class FilterItem extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -1,11 +1,10 @@
|
||||
import React, { useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Backdrop from "@appserver/components/backdrop";
|
||||
import ProgressBar from "@appserver/components/progress-bar";
|
||||
//import ProgressBar from "@appserver/components/progress-bar";
|
||||
import { size } from "@appserver/components/utils/device";
|
||||
import { Provider } from "@appserver/components/utils/context";
|
||||
|
||||
import store from "../../store";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import i18n from "./i18n";
|
||||
|
@ -1,82 +0,0 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { withKnobs, boolean } from "@storybook/addon-knobs/react";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import PeopleSelector from ".";
|
||||
|
||||
import Button from "@appserver/components/button";
|
||||
import { text } from "@storybook/addon-knobs";
|
||||
//import withReadme from "storybook-readme/with-readme";
|
||||
//import Readme from "./README.md";
|
||||
|
||||
class PeopleSelectorExample extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.buttonRef = React.createRef();
|
||||
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
this.setState({
|
||||
isOpen: !this.state.isOpen,
|
||||
});
|
||||
};
|
||||
|
||||
onCancel = (e) => {
|
||||
if (this.buttonRef.current.contains(e.target)) {
|
||||
console.log("onCancel skipped");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("onCancel");
|
||||
this.toggle();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ position: "relative" }}>
|
||||
<Button
|
||||
label="Toggle dropdown"
|
||||
onClick={this.toggle}
|
||||
ref={this.buttonRef}
|
||||
/>
|
||||
<PeopleSelector
|
||||
isOpen={this.state.isOpen}
|
||||
useFake={true}
|
||||
isMultiSelect={boolean("isMultiSelect", true)}
|
||||
onSelect={(data) => {
|
||||
console.log("onSelect", data);
|
||||
this.toggle();
|
||||
}}
|
||||
onCancel={this.onCancel}
|
||||
defaultOption={{
|
||||
id: "777",
|
||||
groups: [],
|
||||
displayName: "Boris Johnson",
|
||||
avatar: "",
|
||||
title: "Prime Minister of the United Kingdom",
|
||||
email: "boris.johnson@example.com",
|
||||
}}
|
||||
defaultOptionLabel={text("defaultOptionLabel", "Me")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf("Components|PeopleSelector", module)
|
||||
.addDecorator(withKnobs)
|
||||
//.addDecorator(withReadme(Readme))
|
||||
.addParameters({ options: { addonPanelInRight: false } })
|
||||
.add("base", () => {
|
||||
return (
|
||||
<Section>
|
||||
<PeopleSelectorExample />
|
||||
</Section>
|
||||
);
|
||||
});
|
@ -1,19 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import en from "./locales/en/translation.json";
|
||||
import ru from "./locales/ru/translation.json";
|
||||
import { i18nBaseSettings } from "../../constants";
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: en,
|
||||
},
|
||||
ru: {
|
||||
translation: ru,
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({ ...i18nBaseSettings, resources });
|
||||
|
||||
export default newInstance;
|
@ -1,2 +0,0 @@
|
||||
import PeopleSelector from "./PeopleSelector.js";
|
||||
export default PeopleSelector;
|
@ -1,19 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import en from "./locales/en/translation.json";
|
||||
import ru from "./locales/ru/translation.json";
|
||||
import { i18nBaseSettings } from "../../constants";
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: en,
|
||||
},
|
||||
ru: {
|
||||
translation: ru,
|
||||
},
|
||||
};
|
||||
|
||||
newInstance.init({ ...i18nBaseSettings, resources });
|
||||
|
||||
export default newInstance;
|
@ -1 +0,0 @@
|
||||
export default from "./toastr";
|
@ -2,7 +2,6 @@ export { default as PrivateRoute } from "./PrivateRoute";
|
||||
export { default as PublicRoute } from "./PublicRoute";
|
||||
export { default as ExternalRedirect } from "./ExternalRedirect";
|
||||
export { default as Headline } from "./Headline";
|
||||
export { default as PeopleSelector } from "./PeopleSelector";
|
||||
export { default as AdvancedSelector } from "./AdvancedSelector";
|
||||
export { default as PageLayout } from "./PageLayout";
|
||||
export { default as ErrorContainer } from "./ErrorContainer";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import toastr from "../components/Toast";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import omit from "lodash/omit";
|
||||
|
||||
|
@ -137,15 +137,15 @@ class AuthStore {
|
||||
try {
|
||||
const response = await api.user.login(user, hash);
|
||||
|
||||
console.log("Login response", response);
|
||||
if (!response || !response.token) throw "Empty API response";
|
||||
|
||||
setWithCredentialsStatus(true);
|
||||
|
||||
await this.init();
|
||||
|
||||
return true;
|
||||
return Promise.resolve(true);
|
||||
} catch (e) {
|
||||
return false;
|
||||
return Promise.reject(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -118,6 +118,8 @@ class SettingsStore {
|
||||
getPortalTimezones: action,
|
||||
setHeaderVisible: action,
|
||||
setIsTabletView: action,
|
||||
setValue: action,
|
||||
setArticlePinned: action,
|
||||
});
|
||||
}
|
||||
|
||||
@ -127,18 +129,21 @@ class SettingsStore {
|
||||
return `https://helpcenter.onlyoffice.com/${lang}/installation/groups-authorization-keys.aspx`;
|
||||
}
|
||||
|
||||
setValue = (key, value) => {
|
||||
this[key] = value;
|
||||
};
|
||||
getSettings = async () => {
|
||||
const newSettings = await api.settings.getSettings();
|
||||
|
||||
Object.keys(newSettings).map((key) => {
|
||||
if (key in this) {
|
||||
this[key] = newSettings[key];
|
||||
this.setValue(key, newSettings[key]);
|
||||
|
||||
if (key === "culture" && !localStorage.getItem(LANGUAGE)) {
|
||||
localStorage.setItem(LANGUAGE, newSettings[key]);
|
||||
}
|
||||
} else if (key === "passwordHash") {
|
||||
this.hashSettings = newSettings[key];
|
||||
this.setValue("hashSettings", newSettings[key]);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -96,20 +96,37 @@ export function updateTempContent(isAuth = false) {
|
||||
export function hideLoader() {
|
||||
if (isMobile) return;
|
||||
|
||||
if (window.loadingTimeout) {
|
||||
clearTimeout(window.loadingTimeout);
|
||||
window.loadingTimeout = null;
|
||||
}
|
||||
// if (window.loadingTimeout) {
|
||||
// clearTimeout(window.loadingTimeout);
|
||||
// window.loadingTimeout = null;
|
||||
// }
|
||||
|
||||
document.body.classList.remove("loading");
|
||||
// document.body.classList.remove("loading");
|
||||
|
||||
const ele = document.getElementById("ipl-progress-indicator");
|
||||
if (ele) {
|
||||
// fade out
|
||||
ele.classList.add("available");
|
||||
ele.style.display = "";
|
||||
// setTimeout(() => {
|
||||
// // remove from DOM
|
||||
// ele.outerHTML = "";
|
||||
// }, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
export function showLoader() {
|
||||
if (isMobile) return;
|
||||
|
||||
window.loadingTimeout = setTimeout(() => {
|
||||
document.body.classList.add("loading");
|
||||
}, 1000);
|
||||
// window.loadingTimeout = setTimeout(() => {
|
||||
// document.body.classList.add("loading");
|
||||
// }, 1000);
|
||||
|
||||
const ele = document.getElementById("ipl-progress-indicator");
|
||||
if (ele) {
|
||||
ele.classList.remove("available");
|
||||
ele.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
export { withLayoutSize } from "./withLayoutSize";
|
||||
|
31
packages/asc-web-components/.storybook/main.js
Normal file
31
packages/asc-web-components/.storybook/main.js
Normal file
@ -0,0 +1,31 @@
|
||||
module.exports = {
|
||||
stories: [
|
||||
"../backdrop/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../button/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../avatar/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../badge/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../box/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../avatar-editor/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../calendar/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../checkbox/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../combobox/*.stories.@(js|mdx)",
|
||||
"../context-menu/*.stories.@(js|mdx)",
|
||||
"../context-menu-button/*.stories.@(js|mdx)",
|
||||
"../date-picker/*.stories.@(js|mdx)",
|
||||
"../drag-and-drop/*.stories.@(js|mdx)",
|
||||
"../drop-down/*.stories.@(js|mdx)",
|
||||
"../drop-down-item/*.stories.@(js|mdx)",
|
||||
"../email-input/*.stories.@(js|mdx)",
|
||||
"../empty-screen-container/*.stories.@(js|mdx)",
|
||||
"../field-container/*.stories.@(js|mdx)",
|
||||
"../file-input/*.stories.@(js|mdx)",
|
||||
"../grid/*.stories.@(js|mdx)",
|
||||
],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-docs",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-actions",
|
||||
"@storybook/addon-controls",
|
||||
],
|
||||
};
|
17
packages/asc-web-components/.storybook/preview.js
Normal file
17
packages/asc-web-components/.storybook/preview.js
Normal file
@ -0,0 +1,17 @@
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
controls: { expanded: true },
|
||||
};
|
||||
|
||||
export const globalTypes = {
|
||||
theme: {
|
||||
name: "Theme",
|
||||
description: "Global theme for components",
|
||||
defaultValue: "light",
|
||||
toolbar: {
|
||||
icon: "circlehollow",
|
||||
// array of plain string values or MenuItem shape (see below)
|
||||
items: ["light", "dark"],
|
||||
},
|
||||
},
|
||||
};
|
22
packages/asc-web-components/.storybook/webpack.config.js
Normal file
22
packages/asc-web-components/.storybook/webpack.config.js
Normal file
@ -0,0 +1,22 @@
|
||||
module.exports = ({ config }) => {
|
||||
const rules = config.module.rules;
|
||||
|
||||
const fileLoaderRule = rules.find((rule) => rule.test.test(".svg"));
|
||||
fileLoaderRule.exclude = /\.react.svg$/;
|
||||
|
||||
rules.push({
|
||||
test: /\.react.svg$/,
|
||||
use: [
|
||||
{
|
||||
loader: "@svgr/webpack",
|
||||
options: {
|
||||
svgoConfig: {
|
||||
plugins: [{ removeViewBox: false }],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return config;
|
||||
};
|
@ -1,16 +1,87 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { withKnobs, text, select } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import AvatarEditor from ".";
|
||||
import AvatarEditor from "./";
|
||||
import Avatar from "../avatar";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import { boolean } from "@storybook/addon-knobs";
|
||||
|
||||
const displayType = ["auto", "modal", "aside"];
|
||||
class AvatarEditorStory extends React.Component {
|
||||
export default {
|
||||
title: "Components/AvatarEditor",
|
||||
component: AvatarEditor,
|
||||
argTypes: {
|
||||
visible: { description: "Display avatar editor" },
|
||||
image: { description: "Display avatar editor" },
|
||||
accept: { description: "Accepted file types" },
|
||||
displayType: { description: "Display type" },
|
||||
useModalDialog: {
|
||||
description: "Use for the view of the modal dialog or not",
|
||||
},
|
||||
selectNewPhotoLabel: {
|
||||
description: "Translation string for file selection",
|
||||
},
|
||||
orDropFileHereLabel: {
|
||||
description:
|
||||
"Translation string for file dropping (concat with selectNewPhotoLabel prop)",
|
||||
},
|
||||
headerLabel: { description: "Translation string for title" },
|
||||
saveButtonLabel: { description: "Translation string for save button" },
|
||||
saveButtonLoading: {
|
||||
description: "Tells when the button should show loader icon",
|
||||
},
|
||||
cancelButtonLabel: { description: "Translation string for cancel button" },
|
||||
maxSizeFileError: { description: "Translation string for size warning" },
|
||||
unknownTypeError: {
|
||||
description: "Translation string for file type warning",
|
||||
},
|
||||
onLoadFileError: {
|
||||
description: "Translation string for load file warning",
|
||||
},
|
||||
unknownError: { description: "Translation string for warning" },
|
||||
maxSize: { description: "Max size of image" },
|
||||
onSave: { description: "Save event" },
|
||||
onClose: { description: "Closing event " },
|
||||
onDeleteImage: { description: "Image deletion event" },
|
||||
onLoadFile: { description: "Image upload event" },
|
||||
onImageChange: { description: "Image change event" },
|
||||
className: { description: "Accepts class" },
|
||||
id: { description: "Accepts id" },
|
||||
style: { description: "Accepts css style" },
|
||||
openEditor: { action: "onOpen", table: { disable: true } },
|
||||
closeEditor: { action: "onClose", table: { disable: true } },
|
||||
onSave: { action: "onSave", table: { disable: true } },
|
||||
onLoadFile: { action: "onLoadFile", table: { disable: true } },
|
||||
onImageChange: { action: "onImageChange", table: { disable: true } },
|
||||
onDeleteImage: { action: "onDeleteImage", table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Used to display user avatar editor on page.",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import AvatarEditor from "@appserver/components/avatar-editor";
|
||||
|
||||
<AvatarEditor
|
||||
visible={true}
|
||||
onClose={() => {}}
|
||||
onSave={() => {})}
|
||||
onDeleteImage={() => {})}
|
||||
onImageChange={() => {})}
|
||||
onLoadFile={() => {}}
|
||||
headerLabel="Edit Photo"
|
||||
selectNewPhotoLabel="Select new photo"
|
||||
orDropFileHereLabel="or drop file here"
|
||||
saveButtonLabel="Save"
|
||||
maxSizeFileError="Maximum file size exceeded"
|
||||
unknownTypeError="Unknown image file type"
|
||||
unknownError="Error"
|
||||
displayType="auto"
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
class Wrapper extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -25,40 +96,47 @@ class AvatarEditorStory extends React.Component {
|
||||
this.onLoadFile = this.onLoadFile.bind(this);
|
||||
this.onImageChange = this.onImageChange.bind(this);
|
||||
this.onDeleteImage = this.onDeleteImage.bind(this);
|
||||
this.onLoadFile = this.onLoadFile.bind(this);
|
||||
}
|
||||
|
||||
onDeleteImage() {
|
||||
action("onDeleteImage");
|
||||
this.props.onDeleteImage();
|
||||
}
|
||||
onImageChange(img) {
|
||||
action("onLoadFile");
|
||||
this.props.onImageChange(img);
|
||||
this.setState({
|
||||
userImage: img,
|
||||
});
|
||||
}
|
||||
onLoadFile(file) {
|
||||
action("onLoadFile")(file);
|
||||
this.props.onLoadFile(file);
|
||||
}
|
||||
onSave(isUpdate, data) {
|
||||
action("onSave")(isUpdate, data);
|
||||
this.props.onSave(isUpdate, data);
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
});
|
||||
}
|
||||
openEditor() {
|
||||
openEditor(e) {
|
||||
this.props.openEditor(e);
|
||||
this.setState({
|
||||
isOpen: true,
|
||||
});
|
||||
}
|
||||
onClose() {
|
||||
action("onClose");
|
||||
this.props.closeEditor();
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
unknownError,
|
||||
unknownTypeError,
|
||||
saveButtonLoading,
|
||||
maxSizeFileError,
|
||||
} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Avatar
|
||||
size="max"
|
||||
role="user"
|
||||
@ -66,44 +144,27 @@ class AvatarEditorStory extends React.Component {
|
||||
editing={true}
|
||||
editAction={this.openEditor}
|
||||
/>
|
||||
{this.props.children}
|
||||
<AvatarEditor
|
||||
visible={this.state.isOpen}
|
||||
{...this.props}
|
||||
visible={this.state.isOpen || this.props.visible}
|
||||
onClose={this.onClose}
|
||||
onSave={this.onSave}
|
||||
onDeleteImage={this.onDeleteImage}
|
||||
onImageChange={this.onImageChange}
|
||||
onLoadFile={this.onLoadFile}
|
||||
headerLabel={text("headerLabel", "Edit Photo")}
|
||||
chooseFileLabel={text(
|
||||
"chooseFileLabel",
|
||||
"Drop files here, or click to select files"
|
||||
)}
|
||||
chooseMobileFileLabel={text(
|
||||
"chooseMobileFileLabel",
|
||||
"Click to select files"
|
||||
)}
|
||||
saveButtonLabel={text("saveButtonLabel", "Save")}
|
||||
saveButtonLoading={boolean("saveButtonLoading", false)}
|
||||
maxSizeFileError={text(
|
||||
"maxSizeFileError",
|
||||
"Maximum file size exceeded"
|
||||
)}
|
||||
unknownTypeError={text("unknownTypeError", "Unknown image file type")}
|
||||
unknownError={text("unknownError", "Error")}
|
||||
displayType={select("displayType", displayType, "auto")}
|
||||
chooseFileLabel={"Drop files here, or click to select files"}
|
||||
chooseMobileFileLabel={"Click to select files"}
|
||||
saveButtonLoading={saveButtonLoading}
|
||||
maxSizeFileError={maxSizeFileError || "Maximum file size exceeded"}
|
||||
unknownTypeError={unknownTypeError || "Unknown image file type"}
|
||||
unknownError={unknownError || "Error"}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
storiesOf("Components|AvatarEditor", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => {
|
||||
return (
|
||||
<Section>
|
||||
<AvatarEditorStory />
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
const Template = (args) => {
|
||||
return <Wrapper {...args} />;
|
||||
};
|
||||
export const Default = Template.bind({});
|
||||
|
@ -57,7 +57,7 @@ const Slider = styled.input.attrs({
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
-webkit-box-shadow: ${(props) =>
|
||||
props.theme.avatarEditorBody.sliderThumb.boxShadow};
|
||||
props.theme.avatarEditorBody.slider.sliderThumb.boxShadow};
|
||||
box-shadow: ${(props) =>
|
||||
props.theme.avatarEditorBody.slider.sliderThumb.boxShadow};
|
||||
}
|
||||
|
@ -1,4 +1,44 @@
|
||||
import React from "react";
|
||||
import Avatar from "./";
|
||||
|
||||
const roleOptions = ["owner", "admin", "guest", "user"];
|
||||
const sizeOptions = ["max", "big", "medium", "small", "min"];
|
||||
|
||||
const editAction = () => console.log("Edit action");
|
||||
|
||||
export default {
|
||||
title: "Components/Avatar",
|
||||
component: Avatar,
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Used to display an avatar or brand.",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import Avatar from "@appserver/components/avatar";
|
||||
|
||||
<Avatar
|
||||
size="max"
|
||||
role="admin"
|
||||
source=""
|
||||
userName=""
|
||||
editing={false}
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => <Avatar {...args} />;
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
role: 'admin'
|
||||
}
|
||||
|
||||
/*import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { withKnobs, boolean, text, select } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
@ -32,4 +72,4 @@ storiesOf("Components|Avatar", module)
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
});*/
|
||||
|
@ -1,40 +1,64 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { BooleanValue } from "react-values";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import { withKnobs, number } from "@storybook/addon-knobs/react";
|
||||
import Readme from "./README.md";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import Backdrop from ".";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import Backdrop from "./";
|
||||
import Button from "../button";
|
||||
|
||||
storiesOf("Components|Backdrop", module)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.addDecorator(withKnobs)
|
||||
.add("base", () => (
|
||||
<Section>
|
||||
<BooleanValue>
|
||||
{({ value, toggle }) => (
|
||||
<div>
|
||||
<Button
|
||||
label="Show Backdrop"
|
||||
primary={true}
|
||||
onClick={(e) => {
|
||||
action("onShow")(e);
|
||||
toggle(true);
|
||||
}}
|
||||
/>
|
||||
<Backdrop
|
||||
visible={value}
|
||||
zIndex={number("zIndex", 1)}
|
||||
onClick={(e) => {
|
||||
action("onHide")(e);
|
||||
toggle(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</BooleanValue>
|
||||
</Section>
|
||||
));
|
||||
export default {
|
||||
title: "Components/Backdrop",
|
||||
component: Backdrop,
|
||||
argTypes: {
|
||||
visible: {
|
||||
description: "Display or not",
|
||||
},
|
||||
zIndex: {
|
||||
description: "CSS z-index",
|
||||
},
|
||||
className: { description: "Accepts class" },
|
||||
id: { description: "Accepts id" },
|
||||
style: { description: "Accepts CSS style" },
|
||||
withBackground: {
|
||||
description:
|
||||
"The background is not displayed if the viewport width is less than 1024, set it to true for display",
|
||||
},
|
||||
isAside: { description: "Must be true if used with Aside component" },
|
||||
onClick: { action: "On Hide", table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Backdrop for displaying modal dialogs or other components",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import Backdrop from "@appserver/components/backdrop";
|
||||
|
||||
<Backdrop visible={true} zIndex={200}/>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
const [isVisible, setIsVisible] = useState(args.visible);
|
||||
const toggleVisible = () => setIsVisible(!isVisible);
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
label="Show Backdrop"
|
||||
primary
|
||||
size="medium"
|
||||
onClick={toggleVisible}
|
||||
/>
|
||||
<Backdrop
|
||||
{...args}
|
||||
visible={isVisible}
|
||||
onClick={(e) => {
|
||||
args.onClick(e);
|
||||
toggleVisible(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
@ -1,66 +1,77 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import { withKnobs, number, color, text } from "@storybook/addon-knobs/react";
|
||||
import Readme from "./README.md";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import Badge from ".";
|
||||
|
||||
storiesOf("Components|Badge", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => (
|
||||
<Section>
|
||||
<Badge
|
||||
label={text("label", "10")}
|
||||
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="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>
|
||||
));
|
||||
import Badge from "./";
|
||||
|
||||
export default {
|
||||
title: "Components/Badge",
|
||||
component: Badge,
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Used for buttons, numbers or status markers next to icons.",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import Badge from "@appserver/components/badge";
|
||||
|
||||
<Badge
|
||||
label="10"
|
||||
backgroundColor="#ED7309"
|
||||
color="#FFFFFF"
|
||||
fontSize="11px"
|
||||
fontWeight={800}
|
||||
borderRadius="11px"
|
||||
padding="0 5px"
|
||||
maxWidth="50px"
|
||||
onClick={() => {}}
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
backgroundColor: { control: "color", description: "CSS background-color" },
|
||||
color: { control: "color", description: "CSS color" },
|
||||
label: { control: "text", description: "Value" },
|
||||
borderRadius: { description: "CSS border-radius" },
|
||||
className: { description: "Accepts class" },
|
||||
fontSize: { description: "CSS font-size" },
|
||||
fontWeight: { description: "CSS font-weight" },
|
||||
id: { description: "Accepts id" },
|
||||
maxWidth: { description: "CSS max-width" },
|
||||
onClick: { description: "onClick event" },
|
||||
padding: { description: "CSS padding" },
|
||||
style: { description: "Accepts css style" },
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => <Badge {...args} />;
|
||||
const NumberTemplate = (args) => <Badge {...args} />;
|
||||
const TextTemplate = (args) => <Badge {...args} />;
|
||||
const MixedTemplate = (args) => <Badge {...args} />;
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
label: 24,
|
||||
};
|
||||
export const NumberBadge = NumberTemplate.bind({});
|
||||
NumberBadge.argTypes = {
|
||||
label: { control: "number" },
|
||||
};
|
||||
NumberBadge.args = {
|
||||
label: 3,
|
||||
};
|
||||
export const TextBadge = TextTemplate.bind({});
|
||||
TextBadge.argTypes = {
|
||||
label: { control: "text" },
|
||||
};
|
||||
TextBadge.args = {
|
||||
label: "New",
|
||||
};
|
||||
export const MixedBadge = MixedTemplate.bind({});
|
||||
MixedBadge.argTypes = {
|
||||
label: { control: "text" },
|
||||
};
|
||||
MixedBadge.args = {
|
||||
label: "Ver.2",
|
||||
};
|
||||
|
@ -1,4 +1,219 @@
|
||||
import React from "react";
|
||||
|
||||
//import { Box } from "./";
|
||||
import Box from "./";
|
||||
|
||||
const containerProps = {
|
||||
widthProp: "100%",
|
||||
paddingProp: "10px",
|
||||
displayProp: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
};
|
||||
|
||||
const rowProps = {
|
||||
displayProp: "flex",
|
||||
flexDirection: "row",
|
||||
};
|
||||
|
||||
const commonBoxProps = {
|
||||
textAlign: "center",
|
||||
marginProp: "10px",
|
||||
paddingProp: "10px",
|
||||
};
|
||||
|
||||
export default {
|
||||
title: "Components/Box",
|
||||
component: Box,
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A container that lays out its contents in one direction. Box provides general CSS capabilities like flexbox layout, paddings, background color, border, and animation.",
|
||||
},
|
||||
source: {
|
||||
code: `import Box from "@appserver/components/box";
|
||||
|
||||
<Box />`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => (
|
||||
<Box {...containerProps}>
|
||||
<Box {...rowProps}>
|
||||
<Box {...commonBoxProps} backgroundProp="gray">
|
||||
color background
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
backgroundProp="linear-gradient(90deg, white, gray)"
|
||||
>
|
||||
linear gradient background
|
||||
</Box>
|
||||
<Box {...commonBoxProps} backgroundProp="radial-gradient(white, gray)">
|
||||
radial gradient background
|
||||
</Box>
|
||||
</Box>
|
||||
<Box {...rowProps}>
|
||||
<Box {...commonBoxProps} borderProp="4px solid gray">
|
||||
solid border
|
||||
</Box>
|
||||
<Box {...commonBoxProps} borderProp="4px dashed gray">
|
||||
dashed border
|
||||
</Box>
|
||||
<Box {...commonBoxProps} borderProp="4px dotted gray">
|
||||
dotted border
|
||||
</Box>
|
||||
<Box {...commonBoxProps} borderProp="4px double gray">
|
||||
double border
|
||||
</Box>
|
||||
</Box>
|
||||
<Box {...rowProps}>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{ style: "solid", width: "1px 0", color: "gray" }}
|
||||
>
|
||||
Horizontal border
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "0 1px",
|
||||
color: "gray",
|
||||
}}
|
||||
>
|
||||
vertical border
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "0 0 0 1px",
|
||||
color: "gray",
|
||||
}}
|
||||
>
|
||||
left border
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px 0 0 0",
|
||||
color: "gray",
|
||||
}}
|
||||
>
|
||||
top border
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "0 1px 0 0",
|
||||
color: "gray",
|
||||
}}
|
||||
>
|
||||
right border
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "0 0 1px 0",
|
||||
color: "gray",
|
||||
}}
|
||||
>
|
||||
bottom border
|
||||
</Box>
|
||||
</Box>
|
||||
<Box {...rowProps}>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px",
|
||||
color: "gray",
|
||||
radius: "100%",
|
||||
}}
|
||||
>
|
||||
full round
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px",
|
||||
color: "gray",
|
||||
radius: "5px",
|
||||
}}
|
||||
>
|
||||
round
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px",
|
||||
color: "gray",
|
||||
radius: "5px 0 0 5px",
|
||||
}}
|
||||
>
|
||||
left round
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px",
|
||||
color: "gray",
|
||||
radius: "5px 5px 0 0",
|
||||
}}
|
||||
>
|
||||
top round
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px",
|
||||
color: "gray",
|
||||
radius: "0 5px 5px 0",
|
||||
}}
|
||||
>
|
||||
right round
|
||||
</Box>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "solid",
|
||||
width: "1px",
|
||||
color: "gray",
|
||||
radius: "0 0 5px 5px",
|
||||
}}
|
||||
>
|
||||
bottom round
|
||||
</Box>
|
||||
</Box>
|
||||
<Box {...rowProps}>
|
||||
<Box
|
||||
{...commonBoxProps}
|
||||
borderProp={{
|
||||
style: "dashed solid double dotted",
|
||||
width: "2em 1rem 1px 2%",
|
||||
color: "red yellow green blue",
|
||||
radius: "10% 30% 50% 70%",
|
||||
}}
|
||||
>
|
||||
Mix border
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export const Default = Template.bind({});
|
||||
/*import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
@ -196,3 +411,4 @@ storiesOf("Components|Box", module)
|
||||
</Box>
|
||||
</Box>
|
||||
));
|
||||
*/
|
||||
|
@ -1,113 +0,0 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Button from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
|
||||
function onClick(e) {
|
||||
e = e || window.event;
|
||||
var target = e.target || e.srcElement,
|
||||
text = target.textContent || target.innerText;
|
||||
console.log("onClick", text);
|
||||
}
|
||||
|
||||
const getButtons = (primary) => {
|
||||
const sizes = ["large", "big", "medium", "base"];
|
||||
const states = ["isActivated", "isHovered", "isClicked", "isDisabled"];
|
||||
|
||||
const baseButton = {
|
||||
size: "base",
|
||||
primary: true,
|
||||
isActivated: false,
|
||||
isHovered: false,
|
||||
isClicked: false,
|
||||
isDisabled: false,
|
||||
isLoading: false,
|
||||
onClick: onClick,
|
||||
label: "base button",
|
||||
};
|
||||
|
||||
let buttons = [];
|
||||
baseButton.primary = primary;
|
||||
|
||||
sizes.forEach((size) => {
|
||||
let sizeButtons = [];
|
||||
states.forEach((state) => {
|
||||
let btn = {
|
||||
...baseButton,
|
||||
size: size,
|
||||
label: primary ? (size === "base" ? "Save" : "Publish") : "Cancel",
|
||||
};
|
||||
btn[state] = true;
|
||||
sizeButtons.push(btn);
|
||||
});
|
||||
buttons.push({
|
||||
size: size,
|
||||
buttons: sizeButtons,
|
||||
});
|
||||
});
|
||||
|
||||
console.log("buttons", buttons);
|
||||
|
||||
return buttons;
|
||||
};
|
||||
|
||||
storiesOf("Components|Buttons", module)
|
||||
.addParameters({ options: { showAddonPanel: false } })
|
||||
.add("all", () => (
|
||||
<Section>
|
||||
<div>
|
||||
<h1>Main buttons (primary action)</h1>
|
||||
<table style={{ width: 584, borderCollapse: "separate" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Active</th>
|
||||
<th>Hover</th>
|
||||
<th>Click</th>
|
||||
<th>Disable</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.values(getButtons(true)).map((btnSize, i) => {
|
||||
console.log(btnSize);
|
||||
return (
|
||||
<tr key={`row${i}`}>
|
||||
{Object.values(btnSize.buttons).map((btn, j) => (
|
||||
<td key={`col${i}${j}`} style={{ paddingBottom: 20 }}>
|
||||
<Button key={`btn${i}${j}`} {...btn} />
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div style={{ marginTop: 47 }}>
|
||||
<h1>Main buttons (secondary action)</h1>
|
||||
<table style={{ width: 584, borderCollapse: "separate" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Active</th>
|
||||
<th>Hover</th>
|
||||
<th>Click</th>
|
||||
<th>Disable</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.values(getButtons(false)).map((btnSize, i) => {
|
||||
console.log(btnSize);
|
||||
return (
|
||||
<tr key={`row${i}`}>
|
||||
{Object.values(btnSize.buttons).map((btn, j) => (
|
||||
<td key={`col${i}${j}`} style={{ paddingBottom: 20 }}>
|
||||
<Button key={`btn${i}${j}`} {...btn} />
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</Section>
|
||||
));
|
@ -1,45 +1,276 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { withKnobs, boolean, text, select } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import Button from ".";
|
||||
import { Icons } from "../icons";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import { orderBy } from "lodash";
|
||||
|
||||
storiesOf("Components|Buttons", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => {
|
||||
const sizeOptions = ["base", "medium", "big", "large"];
|
||||
const iconNames = orderBy(
|
||||
Object.keys(Icons),
|
||||
[(name) => name.toLowerCase()],
|
||||
["asc"]
|
||||
);
|
||||
import Icon from "../../../public/images/button.alert.react.svg";
|
||||
import Button from "./";
|
||||
|
||||
const iconName = select("icon", ["", ...iconNames], "");
|
||||
const hintIcon = iconName
|
||||
? React.createElement(Icons[iconName])
|
||||
: undefined;
|
||||
export default {
|
||||
title: "Components/Button",
|
||||
component: Button,
|
||||
argTypes: {
|
||||
label: { description: "Button text" },
|
||||
size: { description: "Size of button" },
|
||||
primary: { description: "Tells when the button should be primary" },
|
||||
scale: { description: "Scale width of button to 100%" },
|
||||
isClicked: {
|
||||
description: "Tells when the button should present a clicked state",
|
||||
},
|
||||
isDisabled: {
|
||||
description: "Tells when the button should present a disabled state",
|
||||
},
|
||||
isHovered: {
|
||||
description: "Tells when the button should present a hovered state",
|
||||
},
|
||||
isLoading: { description: "Tells when the button should show loader icon" },
|
||||
disableHover: { description: "Disable hover effect" },
|
||||
icon: { description: "Icon node element" },
|
||||
onClick: { description: "What the button will trigger when clicked " },
|
||||
className: { description: "Accepts class" },
|
||||
id: { description: "Accepts id" },
|
||||
style: { description: "Accepts CSS style" },
|
||||
tabIndex: { description: "Button tab index" },
|
||||
minwidth: { description: "Sets the nim width of the button" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Button is used for a action on a page.",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import Button from "@appserver/components/button";
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Button
|
||||
size="base"
|
||||
isDisabled={false}
|
||||
onClick={() => alert("Button clicked")}
|
||||
label="OK"
|
||||
/>
|
||||
`
|
||||
}
|
||||
},
|
||||
},
|
||||
args: {
|
||||
size: "base",
|
||||
label: "Base Button",
|
||||
},
|
||||
};
|
||||
|
||||
const sizes = ["base", "medium", "big", "large"];
|
||||
|
||||
const Wrapper = (props) => (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: props.isScale
|
||||
? "1fr"
|
||||
: "repeat( auto-fill, minmax(180px, 1fr) )",
|
||||
gridGap: "16px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Template = (args) => <Button {...args} />;
|
||||
const PrimaryTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
label={text("label", "Base button")}
|
||||
primary={boolean("primary", true)}
|
||||
size={select("size", sizeOptions, "big")}
|
||||
scale={boolean("scale", false)}
|
||||
isLoading={boolean("isLoading", false)}
|
||||
isHovered={boolean("isHovered", false)}
|
||||
isClicked={boolean("isClicked", false)}
|
||||
isDisabled={boolean("isDisabled", false)}
|
||||
minWidth={text("minWidth", "")}
|
||||
onClick={action("clicked")}
|
||||
icon={hintIcon}
|
||||
key={`all-primary-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
scale={false}
|
||||
size={size}
|
||||
label={`Primary ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const SecondaryTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-secondary-${size}`}
|
||||
{...args}
|
||||
scale={false}
|
||||
size={size}
|
||||
label={`Secondary ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const WithIconTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-icon-prim-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
size={size}
|
||||
icon={<Icon />}
|
||||
label={`With Icon ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-icon-sec-${size}`}
|
||||
{...args}
|
||||
size={size}
|
||||
icon={<Icon />}
|
||||
label={`With Icon ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const IsLoadingTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-load-prim-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
size={size}
|
||||
isLoading={true}
|
||||
label={`Loading ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-load-sec-${size}`}
|
||||
{...args}
|
||||
size={size}
|
||||
isLoading={true}
|
||||
label={`Loading ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const ScaleTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper isScale>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-scale-prim-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
size={size}
|
||||
isLoading={true}
|
||||
label={`Scale ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-scale-sec-${size}`}
|
||||
{...args}
|
||||
size={size}
|
||||
isLoading={true}
|
||||
label={`Scale ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const DisabledTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-disabled-prim-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
size={size}
|
||||
isDisabled={true}
|
||||
label={`Disabled ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-disabled-sec-${size}`}
|
||||
{...args}
|
||||
size={size}
|
||||
isDisabled={true}
|
||||
label={`Disabled ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const ClickedTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-clicked-prim-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
size={size}
|
||||
isClicked={true}
|
||||
label={`Disabled ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-clicked-sec-${size}`}
|
||||
{...args}
|
||||
size={size}
|
||||
isClicked={true}
|
||||
label={`Clicked ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const HoveredTemplate = (args) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-hovered-prim-${size}`}
|
||||
{...args}
|
||||
primary
|
||||
size={size}
|
||||
isHovered={true}
|
||||
label={`Disabled ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
{sizes.map((size) => (
|
||||
<Button
|
||||
key={`all-hovered-sec-${size}`}
|
||||
{...args}
|
||||
size={size}
|
||||
isHovered={true}
|
||||
label={`Clicked ${size[0].toUpperCase()}${size.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
export const PrimaryButtons = PrimaryTemplate.bind({});
|
||||
export const SecondaryButtons = SecondaryTemplate.bind({});
|
||||
export const WithIconButtons = WithIconTemplate.bind({});
|
||||
export const IsLoadingButtons = IsLoadingTemplate.bind({});
|
||||
export const ScaleButtons = ScaleTemplate.bind({});
|
||||
export const DisabledButtons = DisabledTemplate.bind({});
|
||||
export const ClickedButtons = ClickedTemplate.bind({});
|
||||
export const HoveredButtons = HoveredTemplate.bind({});
|
||||
HoveredButtons.argTypes = {
|
||||
isHovered: { table: { disable: true } },
|
||||
};
|
||||
|
@ -1,66 +1,111 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { withKnobs, color, select, date } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import Calendar from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import Calendar from "./";
|
||||
|
||||
function myDateKnob(name, defaultValue) {
|
||||
const stringTimestamp = date(name, defaultValue);
|
||||
return new Date(stringTimestamp);
|
||||
}
|
||||
export default {
|
||||
title: "Components/Calendar",
|
||||
component: Calendar,
|
||||
argTypes: {
|
||||
themeColor: { control: "color", description: "Color of the selected day" },
|
||||
maxDate: {
|
||||
control: "date",
|
||||
description: "Maximum date that the user can select",
|
||||
},
|
||||
selectedDate: { control: "date", description: "Selected date value" },
|
||||
openToDate: {
|
||||
control: "date",
|
||||
description:
|
||||
"The beginning of a period that shall be displayed by default",
|
||||
},
|
||||
minDate: {
|
||||
control: "date",
|
||||
description: "Minimum date that the user can select.",
|
||||
},
|
||||
locale: {
|
||||
description: "Browser locale",
|
||||
control: {
|
||||
type: "select",
|
||||
options: [
|
||||
"az",
|
||||
"zh-cn",
|
||||
"cs",
|
||||
"nl",
|
||||
"en-gb",
|
||||
"en",
|
||||
"fi",
|
||||
"fr",
|
||||
"de",
|
||||
"de-ch",
|
||||
"el",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"lv",
|
||||
"pl",
|
||||
"pt",
|
||||
"pt-br",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"es",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
],
|
||||
},
|
||||
},
|
||||
onChange: {
|
||||
description: "Function called when the user select a day",
|
||||
action: "onChange",
|
||||
},
|
||||
size: { description: "Calendar size" },
|
||||
className: { description: "Accepts class" },
|
||||
id: { description: "Accepts id" },
|
||||
style: { description: "Accepts css style" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Used to display custom calendar",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import Calendar from "@appserver/components/calendar";
|
||||
|
||||
const locales = [
|
||||
"az",
|
||||
"zh-cn",
|
||||
"cs",
|
||||
"nl",
|
||||
"en-gb",
|
||||
"en",
|
||||
"fi",
|
||||
"fr",
|
||||
"de",
|
||||
"de-ch",
|
||||
"el",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"lv",
|
||||
"pl",
|
||||
"pt",
|
||||
"pt-br",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"es",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
];
|
||||
<Calendar
|
||||
onChange={(date) => {
|
||||
console.log("Selected date:", date);
|
||||
}}
|
||||
disabled={false}
|
||||
themeColor="#ED7309"
|
||||
selectedDate={new Date()}
|
||||
openToDate={new Date()}
|
||||
minDate={new Date("1970/01/01")}
|
||||
maxDate={new Date("3000/01/01")}
|
||||
locale="ru"
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const arraySize = ["base", "big"];
|
||||
const Template = (args) => {
|
||||
return (
|
||||
<Calendar
|
||||
{...args}
|
||||
maxDate={new Date(args.maxDate)}
|
||||
selectedDate={new Date(args.selectedDate)}
|
||||
openToDate={new Date(args.openToDate)}
|
||||
minDate={new Date(args.minDate)}
|
||||
locale="en"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf("Components|Calendar", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => (
|
||||
<Section>
|
||||
<Calendar
|
||||
onChange={(date) => {
|
||||
action("Selected date")(date);
|
||||
}}
|
||||
themeColor={color("themeColor", "#ED7309")}
|
||||
selectedDate={myDateKnob("selectedDate", new Date())}
|
||||
openToDate={myDateKnob("openToDate", new Date())}
|
||||
minDate={myDateKnob("minDate", new Date("1970/01/01"))}
|
||||
maxDate={myDateKnob(
|
||||
"maxDate",
|
||||
new Date(new Date().getFullYear() + 1 + "/01/01")
|
||||
)}
|
||||
locale={select("locale", locales, "en")}
|
||||
size={select("size", arraySize, "base")}
|
||||
/>
|
||||
</Section>
|
||||
));
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
maxDate: new Date(new Date().getFullYear() + 1 + "/01/01"),
|
||||
minDate: new Date("1970/01/01"),
|
||||
selectedDate: new Date(),
|
||||
openToDate: new Date(),
|
||||
};
|
||||
|
@ -77,7 +77,9 @@ const CalendarStyle = styled.div`
|
||||
|
||||
.calendar-month_selected-day {
|
||||
background-color: ${(props) =>
|
||||
props.theme.calendar.selectedDay.backgroundColor};
|
||||
props.color
|
||||
? props.color
|
||||
: props.theme.calendar.selectedDay.backgroundColor};
|
||||
border-radius: ${(props) => props.theme.calendar.selectedDay.borderRadius};
|
||||
cursor: ${(props) => props.theme.calendar.selectedDay.cursor};
|
||||
color: ${(props) => props.theme.calendar.selectedDay.color};
|
||||
@ -152,6 +154,8 @@ const StyledWeekday = styled.div`
|
||||
`;
|
||||
StyledWeekday.defaultProps = { theme: Base };
|
||||
|
||||
StyledWeekday.defaultProps = { theme: Base };
|
||||
|
||||
export {
|
||||
Month,
|
||||
CalendarStyle,
|
||||
|
@ -1,34 +1,104 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { BooleanValue } from "react-values";
|
||||
import { withKnobs, boolean, text } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import Checkbox from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
|
||||
storiesOf("Components|Input", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("checkbox", () => (
|
||||
<Section>
|
||||
<BooleanValue>
|
||||
{({ value, toggle }) => (
|
||||
<Checkbox
|
||||
id={text("id", "id")}
|
||||
name={text("name", "name")}
|
||||
value={text("value", "value")}
|
||||
label={text("label", "label")}
|
||||
isChecked={value}
|
||||
isIndeterminate={boolean("isIndeterminate", false)}
|
||||
isDisabled={boolean("isDisabled", false)}
|
||||
onChange={(e) => {
|
||||
action("onChange")(e);
|
||||
toggle(e.target.checked);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</BooleanValue>
|
||||
</Section>
|
||||
));
|
||||
import Checkbox from "./";
|
||||
|
||||
export default {
|
||||
title: "Components/Checkbox",
|
||||
component: Checkbox,
|
||||
parameters: {
|
||||
docs: {
|
||||
description: { component: "Custom checkbox input" },
|
||||
source: {
|
||||
code: `
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
|
||||
<Checkbox
|
||||
id="id"
|
||||
name="name"
|
||||
value="value"
|
||||
label="label"
|
||||
isChecked={false}
|
||||
isIndeterminate={false}
|
||||
isDisabled={false}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
className: { description: "Accepts class" },
|
||||
id: { description: "Used as HTML id property" },
|
||||
isChecked: {
|
||||
description: "The checked property sets the checked state of a checkbox",
|
||||
},
|
||||
isDisabled: { description: "Disables the Checkbox input " },
|
||||
isIndeterminate: {
|
||||
description:
|
||||
"If true, this state is shown as a rectangle in the checkbox",
|
||||
},
|
||||
label: { description: "Label of the input" },
|
||||
name: { description: "Used as HTML `name` property" },
|
||||
onChange: {
|
||||
description: "Will be triggered whenever an CheckboxInput is clicked ",
|
||||
action: "onChange",
|
||||
},
|
||||
style: { description: "Accepts css style " },
|
||||
value: { description: "Value of the input" },
|
||||
title: { description: "Title " },
|
||||
truncate: { description: "Disables word wrapping" },
|
||||
},
|
||||
};
|
||||
|
||||
class Wrapper extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isChecked: false,
|
||||
};
|
||||
}
|
||||
|
||||
onChange = (e) => {
|
||||
this.props.onChange(e);
|
||||
this.setState({ isChecked: !this.state.isChecked });
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Checkbox
|
||||
{...this.props}
|
||||
isChecked={this.props.isChecked || this.state.isChecked}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
const Template = (args) => {
|
||||
return <Wrapper {...args} />;
|
||||
};
|
||||
|
||||
const AllCheckboxesTemplate = (args) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat( auto-fill, minmax(120px, 1fr) )",
|
||||
gridGap: "16px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Checkbox />
|
||||
<Checkbox isChecked={true} />
|
||||
<Checkbox isDisabled={true} />
|
||||
<Checkbox isIndeterminate={true} />
|
||||
<Checkbox label="Some label" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
label: "Checkbox label",
|
||||
};
|
||||
export const AllCheckboxStates = AllCheckboxesTemplate.bind({});
|
||||
|
@ -1,174 +1,278 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import {
|
||||
withKnobs,
|
||||
boolean,
|
||||
select,
|
||||
number,
|
||||
} from "@storybook/addon-knobs/react";
|
||||
import { optionsKnob as options } from "@storybook/addon-knobs";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import ComboBox from ".";
|
||||
import { Icons } from "../icons";
|
||||
import Button from "../button";
|
||||
|
||||
import ComboBox from "./";
|
||||
import RadioButton from "../radio-button";
|
||||
import DropDownItem from "../drop-down-item";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import NavLogoIcon from "../../../public/images/nav.logo.opened.react.svg";
|
||||
|
||||
export default {
|
||||
title: "Components/ComboBox",
|
||||
component: ComboBox,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ height: "230px" }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
|
||||
argTypes: {
|
||||
advancedOptions: {
|
||||
description: "If you need display options not basic options",
|
||||
},
|
||||
className: { description: "Accepts class" },
|
||||
displayType: { description: "Component Display Type" },
|
||||
dropDownMaxHeight: { description: "Height of Dropdown" },
|
||||
id: { description: "Accepts id" },
|
||||
isDisabled: { description: "Indicates that component is disabled" },
|
||||
noBorder: {
|
||||
description: "Indicates that component is displayed without borders",
|
||||
},
|
||||
onSelect: {
|
||||
description: "Will be triggered whenever an ComboBox is selected option",
|
||||
action: "onSelect",
|
||||
},
|
||||
options: { description: "Combo box options" },
|
||||
scaledOptions: {
|
||||
description:
|
||||
"Indicates that component`s options is scaled by ComboButton",
|
||||
},
|
||||
scaled: { description: "Indicates that component is scaled by parent" },
|
||||
selectedOption: { description: "Selected option" },
|
||||
size: { description: "Select component width, one of default" },
|
||||
style: { description: "Accepts css style" },
|
||||
toggleAction: {
|
||||
description:
|
||||
"The event will be raised when using `displayType: toggle` when clicking on a component",
|
||||
},
|
||||
showDisabledItems: {
|
||||
description: "Display disabled items or not when displayType !== toggle ",
|
||||
},
|
||||
children: { description: "Children element" },
|
||||
directionX: { description: "X direction selection" },
|
||||
directionY: { description: "Y direction selection" },
|
||||
opened: { description: "Tells when a component is open" },
|
||||
textOverflow: { description: "Accepts css text-overflow" },
|
||||
disableIconClick: { description: "Вisables clicking on the icon" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: { component: "Custom combo box input" },
|
||||
source: {
|
||||
code: `
|
||||
### Usage
|
||||
|
||||
import ComboBox from "@appserver/components/combobox";
|
||||
import NavLogoIcon from "../../../../../public/images/nav.logo.react.svg";
|
||||
const iconNames = Object.keys(Icons);
|
||||
const sizeOptions = ["base", "middle", "big", "huge", "content"];
|
||||
|
||||
iconNames.push("NONE");
|
||||
const options = [
|
||||
{
|
||||
key: 1,
|
||||
icon: "static/images/catalog.employee.react.svg", // optional item
|
||||
label: "Option 1",
|
||||
disabled: false, // optional item
|
||||
onClick: clickFunction, // optional item
|
||||
},
|
||||
];
|
||||
|
||||
storiesOf("Components|Input", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("combo box", () => {
|
||||
const comboOptions = [
|
||||
{
|
||||
key: 1,
|
||||
icon: "static/images/catalog.employee.react.svg",
|
||||
label: "Option 1",
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
icon: "CatalogGuestIcon",
|
||||
label: "Option 2",
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
disabled: true,
|
||||
label: "Option 3",
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
label: "Option 4",
|
||||
},
|
||||
{
|
||||
key: 5,
|
||||
icon: "static/images/copy.react.svg",
|
||||
label: "Option 5",
|
||||
},
|
||||
{
|
||||
key: 6,
|
||||
label: "Option 6",
|
||||
},
|
||||
{
|
||||
key: 7,
|
||||
label: "Option 7",
|
||||
},
|
||||
];
|
||||
#### Options have options:
|
||||
|
||||
const needScrollDropDown = boolean("Need scroll dropdown", false);
|
||||
const dropDownMaxHeight = needScrollDropDown
|
||||
? number("dropDownMaxHeight", 200)
|
||||
: null;
|
||||
const optionsMultiSelect = options(
|
||||
"children",
|
||||
{
|
||||
button: "button",
|
||||
icon: "icon",
|
||||
- key - Item key, may be a string or a number
|
||||
- label - Display text
|
||||
- icon - Optional name of icon that will be displayed before label
|
||||
- disabled - Make option disabled
|
||||
- onClick - On click function
|
||||
|
||||
ComboBox perceives all property's for positioning from DropDown!
|
||||
|
||||
If you need to display a custom list of options, you must use advancedOptions property. Like this:
|
||||
|
||||
const advancedOptions = (
|
||||
<Meta>
|
||||
<DropDownItem>
|
||||
<RadioButton value="asc" name="first" label="A-Z" isChecked={true} />
|
||||
</DropDownItem>
|
||||
<DropDownItem>
|
||||
<RadioButton value="desc" name="first" label="Z-A" />
|
||||
</DropDownItem>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem>
|
||||
<RadioButton value="first" name="second" label="First name" />
|
||||
</DropDownItem>
|
||||
<DropDownItem>
|
||||
<RadioButton
|
||||
value="last"
|
||||
name="second"
|
||||
label="Last name"
|
||||
isChecked={true}
|
||||
/>
|
||||
</DropDownItem>
|
||||
</Meta>
|
||||
);
|
||||
|
||||
<ComboBox
|
||||
options={[]} // An empty array will enable advancedOptions
|
||||
advancedOptions={advancedOptions}
|
||||
onSelect={(option) => console.log("Selected option", option)}
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Select",
|
||||
}}
|
||||
isDisabled={false}
|
||||
scaled={false}
|
||||
size="content"
|
||||
directionX="right"
|
||||
>
|
||||
<NavLogoIcon size="medium" key="comboIcon" />
|
||||
</ComboBox>
|
||||
|
||||
To use Combobox as a toggle button, you must declare it according to the parameters:
|
||||
|
||||
<ComboBox
|
||||
options={[]} // Required to display correctly
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Selected option",
|
||||
}}
|
||||
scaled={false}
|
||||
size="content"
|
||||
displayType="toggle"
|
||||
toggleAction={alert("action")}
|
||||
>
|
||||
<NavLogoIcon size="medium" key="comboIcon" />
|
||||
</ComboBox>
|
||||
`,
|
||||
},
|
||||
[],
|
||||
{
|
||||
display: "multi-select",
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let children = [];
|
||||
optionsMultiSelect.forEach(function (item, i) {
|
||||
switch (item) {
|
||||
case "button":
|
||||
children.push(<Button label="button" key={i} />);
|
||||
break;
|
||||
case "icon":
|
||||
children.push(<NavLogoIcon size="medium" key={i} />);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
const comboOptions = [
|
||||
{
|
||||
key: 1,
|
||||
icon: "static/images/catalog.employee.react.svg",
|
||||
label: "Option 1",
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
icon: "CatalogGuestIcon",
|
||||
label: "Option 2",
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
disabled: true,
|
||||
label: "Option 3",
|
||||
},
|
||||
{
|
||||
key: 4,
|
||||
label: "Option 4",
|
||||
},
|
||||
{
|
||||
key: 5,
|
||||
icon: "static/images/copy.react.svg",
|
||||
label: "Option 5",
|
||||
},
|
||||
{
|
||||
key: 6,
|
||||
label: "Option 6",
|
||||
},
|
||||
{
|
||||
key: 7,
|
||||
label: "Option 7",
|
||||
},
|
||||
];
|
||||
|
||||
const advancedOptions = (
|
||||
<>
|
||||
<DropDownItem key="1" noHover>
|
||||
<RadioButton value="asc" name="first" label="A-Z" isChecked={true} />
|
||||
</DropDownItem>
|
||||
<DropDownItem key="2" noHover>
|
||||
<RadioButton value="desc" name="first" label="Z-A" />
|
||||
</DropDownItem>
|
||||
<DropDownItem key="3" isSeparator />
|
||||
<DropDownItem key="4" noHover>
|
||||
<RadioButton value="first" name="second" label="First name" />
|
||||
</DropDownItem>
|
||||
<DropDownItem key="5" noHover>
|
||||
<RadioButton
|
||||
value="last"
|
||||
name="second"
|
||||
label="Last name"
|
||||
isChecked={true}
|
||||
/>
|
||||
</DropDownItem>
|
||||
</>
|
||||
);
|
||||
let children = [];
|
||||
|
||||
const childrenItems = children.length > 0 ? children : null;
|
||||
const advancedOptions = (
|
||||
<>
|
||||
<DropDownItem key="1" noHover>
|
||||
<RadioButton value="asc" name="first" label="A-Z" isChecked={true} />
|
||||
</DropDownItem>
|
||||
<DropDownItem key="2" noHover>
|
||||
<RadioButton value="desc" name="first" label="Z-A" />
|
||||
</DropDownItem>
|
||||
<DropDownItem key="3" isSeparator />
|
||||
<DropDownItem key="4" noHover>
|
||||
<RadioButton value="first" name="second" label="First name" />
|
||||
</DropDownItem>
|
||||
<DropDownItem key="5" noHover>
|
||||
<RadioButton
|
||||
value="last"
|
||||
name="second"
|
||||
label="Last name"
|
||||
isChecked={true}
|
||||
/>
|
||||
</DropDownItem>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<table
|
||||
style={{ width: 584, borderCollapse: "separate", textAlign: "left" }}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Default</th>
|
||||
<th>Advanced</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ paddingBottom: 20 }}>
|
||||
<ComboBox
|
||||
options={comboOptions}
|
||||
onSelect={(option) => action("Selected option")(option)}
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Select",
|
||||
default: true,
|
||||
}}
|
||||
isDisabled={boolean("isDisabled", false)}
|
||||
noBorder={boolean("noBorder", false)}
|
||||
dropDownMaxHeight={dropDownMaxHeight}
|
||||
scaled={boolean("scaled", false)}
|
||||
scaledOptions={boolean("scaledOptions", false)}
|
||||
size={select("size", sizeOptions, "content")}
|
||||
>
|
||||
{childrenItems}
|
||||
</ComboBox>
|
||||
</td>
|
||||
<td style={{ paddingBottom: 20 }}>
|
||||
<ComboBox
|
||||
options={[]}
|
||||
advancedOptions={advancedOptions}
|
||||
onSelect={(option) => action("Selected option")(option)}
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Select",
|
||||
default: true,
|
||||
}}
|
||||
isDisabled={boolean("isDisabled", false)}
|
||||
scaled={false}
|
||||
size="content"
|
||||
directionX="right"
|
||||
>
|
||||
<NavLogoIcon size="medium" key="comboIcon" />
|
||||
</ComboBox>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
const childrenItems = children.length > 0 ? children : null;
|
||||
|
||||
const Template = (args) => (
|
||||
<ComboBox
|
||||
{...args}
|
||||
options={[
|
||||
{ key: 1, label: "Option 1" },
|
||||
{ key: 2, label: "Option 2" },
|
||||
]}
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Select",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const BaseOptionsTemplate = (args) => (
|
||||
<ComboBox
|
||||
{...args}
|
||||
options={comboOptions}
|
||||
onSelect={(option) => args.onSelect(option)}
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Select",
|
||||
default: true,
|
||||
}}
|
||||
>
|
||||
{childrenItems}
|
||||
</ComboBox>
|
||||
);
|
||||
|
||||
const AdvancedOptionsTemplate = (args) => (
|
||||
<ComboBox
|
||||
{...args}
|
||||
options={[]}
|
||||
advancedOptions={advancedOptions}
|
||||
onSelect={(option) => args.onSelect(option)}
|
||||
selectedOption={{
|
||||
key: 0,
|
||||
label: "Select",
|
||||
default: true,
|
||||
}}
|
||||
>
|
||||
<NavLogoIcon size="medium" key="comboIcon" />
|
||||
</ComboBox>
|
||||
);
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
opened: true,
|
||||
scaled: false
|
||||
};
|
||||
export const BaseOptions = BaseOptionsTemplate.bind({});
|
||||
BaseOptions.args = {
|
||||
scaledOptions: false,
|
||||
scaled: false,
|
||||
noBorder: false,
|
||||
isDisabled: false,
|
||||
opened: true,
|
||||
};
|
||||
export const AdvancedOptions = AdvancedOptionsTemplate.bind({});
|
||||
AdvancedOptions.args = {
|
||||
opened: true,
|
||||
isDisabled: false,
|
||||
scaled: false,
|
||||
size: "content",
|
||||
directionX: "right",
|
||||
directionY: "bottom",
|
||||
};
|
||||
|
@ -0,0 +1,117 @@
|
||||
import React from "react";
|
||||
|
||||
import ContextMenuButton from "./";
|
||||
|
||||
export default {
|
||||
title: "Components/ContextMenuButton",
|
||||
component: ContextMenuButton,
|
||||
argTypes: {
|
||||
className: { description: "Accepts class" },
|
||||
clickColor: {
|
||||
description: "Specifies the icon click color",
|
||||
control: "color",
|
||||
},
|
||||
color: { description: "Specifies the icon color", control: "color" },
|
||||
data: { description: "Array of options for display " },
|
||||
directionX: {
|
||||
description: "What the button will trigger when mouse out of button",
|
||||
},
|
||||
getData: { description: "Function for converting to inner data " },
|
||||
hoverColor: {
|
||||
description: "Specifies the icon hover color",
|
||||
control: "color",
|
||||
},
|
||||
iconClickName: { description: "Specifies the icon click name" },
|
||||
iconHoverName: { description: "Specifies the icon hover name" },
|
||||
iconName: { description: "Specifies the icon name" },
|
||||
id: { description: "Accepts id" },
|
||||
isDisabled: {
|
||||
description: "Tells when the button should present a disabled state",
|
||||
},
|
||||
onMouseEnter: {
|
||||
description: "What the button will trigger when mouse hovered",
|
||||
action: "onMouseEnter",
|
||||
},
|
||||
onMouseLeave: {
|
||||
description: "What the button will trigger when mouse leave",
|
||||
action: "onMouseLeave",
|
||||
},
|
||||
onMouseOut: {
|
||||
description: "What the button will trigger when mouse out of button",
|
||||
action: "onMouseOut",
|
||||
},
|
||||
onMouseOver: {
|
||||
description: "What the button will trigger when mouse over button",
|
||||
action: "onMouseOver",
|
||||
},
|
||||
opened: {
|
||||
description: "Tells when the button should present a opened state",
|
||||
},
|
||||
size: { description: "Specifies the icon size" },
|
||||
style: { description: "Accepts css style" },
|
||||
title: { description: "Specifies the icon title" },
|
||||
iconOpenName: { description: "Specifies the icon open name" },
|
||||
directionY: { description: "Direction Y" },
|
||||
columnCount: { description: "Set the number of columns" },
|
||||
displayType: { description: "Set the display type" },
|
||||
onClickLabel: { action: "onClickLabel", table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `ContextMenuButton is used for displaying context menu actions on a list's item`,
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import ContextMenuButton from "@appserver/components/context-menu-button";
|
||||
|
||||
<ContextMenuButton
|
||||
iconName="static/images/vertical-dots.react.svg"
|
||||
size={16}
|
||||
color="#A3A9AE"
|
||||
isDisabled={false}
|
||||
title="Actions"
|
||||
getData={() => [
|
||||
{
|
||||
key: "key",
|
||||
label: "label",
|
||||
onClick: () => alert("label"),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
function getData() {
|
||||
console.log("getData");
|
||||
return [
|
||||
{
|
||||
key: "key1",
|
||||
label: "label1",
|
||||
onClick: () => args.onClickLabel("label1"),
|
||||
},
|
||||
{
|
||||
key: "key2",
|
||||
label: "label2",
|
||||
onClick: () => args.onClickLabel("label2"),
|
||||
},
|
||||
];
|
||||
}
|
||||
return (
|
||||
<ContextMenuButton
|
||||
{...args}
|
||||
title={"Actions"}
|
||||
iconName={"/static/images/vertical-dots.react.svg"}
|
||||
size={16}
|
||||
color={"#A3A9AE"}
|
||||
getData={getData}
|
||||
isDisabled={false}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
@ -1,41 +0,0 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import {
|
||||
withKnobs,
|
||||
text,
|
||||
select,
|
||||
number,
|
||||
color,
|
||||
boolean,
|
||||
} from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import ContextMenuButton from ".";
|
||||
import { Icons } from "../icons";
|
||||
|
||||
const iconNames = Object.keys(Icons);
|
||||
|
||||
function getData() {
|
||||
console.log("getData");
|
||||
return [
|
||||
{ key: "key1", label: "label1", onClick: () => console.log("label1") },
|
||||
{ key: "key2", label: "label2", onClick: () => console.log("label2") },
|
||||
];
|
||||
}
|
||||
|
||||
storiesOf("Components|ContextMenuButton", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => (
|
||||
<Section>
|
||||
<ContextMenuButton
|
||||
title={text("title", "Actions")}
|
||||
iconName={select("iconName", iconNames, "VerticalDotsIcon")}
|
||||
size={number("size", 16)}
|
||||
color={color("loaderColor", "#A3A9AE")}
|
||||
getData={getData}
|
||||
isDisabled={boolean("isDisabled", false)}
|
||||
/>
|
||||
</Section>
|
||||
));
|
@ -1,48 +1,74 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
|
||||
import RowContainer from "../row-container";
|
||||
import RowContent from "../row-content";
|
||||
import Row from "../row";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import Readme from "./README.md";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import ContextMenu from "./index";
|
||||
|
||||
export default {
|
||||
title: "Components/ContextMenu",
|
||||
component: ContextMenu,
|
||||
argTypes: {
|
||||
className: { description: "Accepts class" },
|
||||
id: { description: "Accepts id" },
|
||||
options: { description: "DropDownItems collection" },
|
||||
style: { description: "Accepts css style" },
|
||||
targetAreaId: { description: "Id of container apply to" },
|
||||
withBackdrop: { description: "Used to display backdrop" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `ContextMenu is used for a call context actions on a page.
|
||||
Implemented as part of RowContainer component.
|
||||
|
||||
For use within separate component it is necessary to determine active zone and events for calling and transferring options in menu.
|
||||
|
||||
In particular case, state is created containing options for particular Row element and passed to component when called.
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import ContextMenu from "@appserver/components/context-menu";
|
||||
|
||||
<ContextMenu targetAreaId="rowContainer" options={[]} />
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const getRndString = (n) =>
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substring(2, n + 2);
|
||||
|
||||
storiesOf("Components|ContextMenu", module)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => {
|
||||
const array = Array.from(Array(10).keys());
|
||||
const array = Array.from(Array(10).keys());
|
||||
const Template = (args) => (
|
||||
<RowContainer {...args} manualHeight="300px">
|
||||
{array.map((item, index) => {
|
||||
return (
|
||||
<Row
|
||||
key={`${item + 1}`}
|
||||
contextOptions={
|
||||
index !== 3
|
||||
? [
|
||||
{ key: 1, label: getRndString(5) },
|
||||
{ key: 2, label: getRndString(5) },
|
||||
{ key: 3, label: getRndString(5) },
|
||||
{ key: 4, label: getRndString(5) },
|
||||
]
|
||||
: []
|
||||
}
|
||||
>
|
||||
<RowContent>
|
||||
<span>{getRndString(5)}</span>
|
||||
<></>
|
||||
</RowContent>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</RowContainer>
|
||||
);
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<RowContainer manualHeight="300px">
|
||||
{array.map((item, index) => {
|
||||
return (
|
||||
<Row
|
||||
key={`${item + 1}`}
|
||||
contextOptions={
|
||||
index !== 3
|
||||
? [
|
||||
{ key: 1, label: getRndString(5) },
|
||||
{ key: 2, label: getRndString(5) },
|
||||
{ key: 3, label: getRndString(5) },
|
||||
{ key: 4, label: getRndString(5) },
|
||||
]
|
||||
: []
|
||||
}
|
||||
>
|
||||
<RowContent>
|
||||
<span>{getRndString(5)}</span>
|
||||
<></>
|
||||
</RowContent>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</RowContainer>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
export const Default = Template.bind({});
|
||||
|
@ -1,80 +1,127 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import {
|
||||
withKnobs,
|
||||
boolean,
|
||||
color,
|
||||
select,
|
||||
date,
|
||||
number,
|
||||
text,
|
||||
} from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import DatePicker from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import DatePicker from "./";
|
||||
|
||||
function myDateKnob(name, defaultValue) {
|
||||
const stringTimestamp = date(name, defaultValue);
|
||||
return new Date(stringTimestamp);
|
||||
}
|
||||
export default {
|
||||
title: "Components/DatePicker",
|
||||
component: DatePicker,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ height: "380px" }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
themeColor: { description: "Color of the selected day", control: "color" },
|
||||
selectedDate: { description: "Selected date value", control: "date" },
|
||||
openToDate: { description: "Opened date value", control: "date" },
|
||||
minDate: {
|
||||
description: "Minimum date that the user can select.",
|
||||
control: "date",
|
||||
},
|
||||
maxDate: {
|
||||
description: "Maximum date that the user can select.",
|
||||
control: "date",
|
||||
},
|
||||
calendarHeaderContent: {
|
||||
description: "Calendar header content (calendar opened in aside)",
|
||||
},
|
||||
calendarSize: { description: "Calendar size" },
|
||||
className: { description: "Accepts class " },
|
||||
displayType: { description: "Calendar display type " },
|
||||
hasError: { description: "Set error date-input style" },
|
||||
id: { description: "Accepts id " },
|
||||
isDisabled: { description: "Disabled react-calendar" },
|
||||
isOpen: { description: "Opens calendar" },
|
||||
isReadOnly: { description: "Set input type is read only" },
|
||||
locale: { description: "Browser locale" },
|
||||
onChange: {
|
||||
description: "Function called when the user select a day ",
|
||||
action: "onChange",
|
||||
},
|
||||
scaled: { description: "Selected calendar size" },
|
||||
style: { description: "Accepts css style" },
|
||||
zIndex: { description: "Calendar css z-index" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: "Base DatePicker component",
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import DatePicker from "@appserver/components/date-picker";
|
||||
|
||||
const locales = [
|
||||
"az",
|
||||
"zh-cn",
|
||||
"cs",
|
||||
"nl",
|
||||
"en-gb",
|
||||
"en",
|
||||
"fi",
|
||||
"fr",
|
||||
"de",
|
||||
"de-ch",
|
||||
"el",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"lv",
|
||||
"pl",
|
||||
"pt",
|
||||
"pt-br",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"es",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
];
|
||||
<DatePicker
|
||||
onChange={(date) => {
|
||||
console.log("Selected date", date);
|
||||
}}
|
||||
selectedDate={new Date()}
|
||||
minDate={new Date("1970/01/01")}
|
||||
maxDate={new Date(new Date().getFullYear() + 1 + "/01/01")}
|
||||
isDisabled={false}
|
||||
isReadOnly={false}
|
||||
hasError={false}
|
||||
isOpen={false}
|
||||
themeColor="#ED7309"
|
||||
locale="en"
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const displayType = ["dropdown", "aside", "auto"];
|
||||
const Template = (args) => {
|
||||
const locales = [
|
||||
"az",
|
||||
"zh-cn",
|
||||
"cs",
|
||||
"nl",
|
||||
"en-gb",
|
||||
"en",
|
||||
"fi",
|
||||
"fr",
|
||||
"de",
|
||||
"de-ch",
|
||||
"el",
|
||||
"it",
|
||||
"ja",
|
||||
"ko",
|
||||
"lv",
|
||||
"pl",
|
||||
"pt",
|
||||
"pt-br",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"es",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
];
|
||||
return (
|
||||
<DatePicker
|
||||
{...args}
|
||||
onChange={(date) => {
|
||||
args.onChange(date);
|
||||
}}
|
||||
selectedDate={new Date(args.selectedDate)}
|
||||
minDate={new Date(args.minDate)}
|
||||
maxDate={new Date(args.maxDate)}
|
||||
openToDate={new Date(args.openToDate)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf("Components|DatePicker", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => (
|
||||
<Section>
|
||||
<DatePicker
|
||||
onChange={(date) => {
|
||||
action("Selected date")(date);
|
||||
}}
|
||||
selectedDate={myDateKnob("selectedDate", new Date())}
|
||||
minDate={myDateKnob("minDate", new Date("1970/01/01"))}
|
||||
maxDate={myDateKnob(
|
||||
"maxDate",
|
||||
new Date(new Date().getFullYear() + 1 + "/01/01")
|
||||
)}
|
||||
isDisabled={boolean("isDisabled", false)}
|
||||
isReadOnly={boolean("isReadOnly", false)}
|
||||
hasError={boolean("hasError", false)}
|
||||
isOpen={boolean("isOpen", false)}
|
||||
themeColor={color("themeColor", "#ED7309")}
|
||||
locale={select("locale", locales, "en")}
|
||||
displayType={select("displayType", displayType, "auto")}
|
||||
calendarSize={select("calendarSize", ["base", "big"], "base")}
|
||||
zIndex={number("zIndex", 310)}
|
||||
calendarHeaderContent={text("headerContent", "Select Date")}
|
||||
/>
|
||||
</Section>
|
||||
));
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
isOpen: true,
|
||||
calendarHeaderContent: "Select Date",
|
||||
themeColor: "#ED7309",
|
||||
minDate: new Date("1970/01/01"),
|
||||
selectedDate: new Date(),
|
||||
maxDate: new Date(new Date().getFullYear() + 1 + "/01/01"),
|
||||
openToDate: new Date(),
|
||||
calendarSize: "base",
|
||||
};
|
||||
|
@ -1,30 +1,69 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import DragAndDrop from "./";
|
||||
import Text from "../text";
|
||||
|
||||
storiesOf("Components| DragAndDrop", module)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => {
|
||||
const onDrop = (items) => {
|
||||
console.log("onDrop", items);
|
||||
for (let file of items) {
|
||||
if (file) {
|
||||
console.log("File:", file.name);
|
||||
}
|
||||
export default {
|
||||
title: "Components/DragAndDrop",
|
||||
component: DragAndDrop,
|
||||
argTypes: {
|
||||
dragging: { description: "Show that the item is being dragged now." },
|
||||
isDropZone: { description: "Sets the component as a dropzone" },
|
||||
onDrop: {
|
||||
action: "onDrop",
|
||||
description:
|
||||
"Occurs when the dragged element is dropped on the drop target",
|
||||
},
|
||||
targetFile: { action: "File: ", table: { disable: true } },
|
||||
className: { description: "Accepts class" },
|
||||
onMouseDown: {
|
||||
description: "Occurs when the mouse button is pressed",
|
||||
action: "onMouseDown",
|
||||
},
|
||||
children: { table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Drag And Drop component can be used as Dropzone
|
||||
See documentation: https://github.com/react-dropzone/react-dropzone
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import DragAndDrop from "@appserver/components/drag-and-drop";
|
||||
|
||||
<DragAndDrop onDrop={onDrop} style={width: 200, height: 200, border: "5px solid #999"}>
|
||||
<Text style={textStyles} color="#999" fontSize="20px">
|
||||
Drop items here
|
||||
</Text>
|
||||
</DragAndDrop>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
const onDrop = (items) => {
|
||||
args.onDrop(items);
|
||||
for (let file of items) {
|
||||
if (file) {
|
||||
args.targetFile(file.name);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const dropDownStyles = { margin: 16, width: 200, height: 200 };
|
||||
const textStyles = { textAlign: "center", lineHeight: "9.5em" };
|
||||
const dropDownStyles = { margin: 16, width: 200, height: 200 };
|
||||
const textStyles = { textAlign: "center", lineHeight: "9.5em" };
|
||||
|
||||
return (
|
||||
<DragAndDrop {...args} isDropZone onDrop={onDrop} style={dropDownStyles}>
|
||||
<Text style={textStyles} color="#999" fontSize="20px">
|
||||
Drop items here
|
||||
</Text>
|
||||
</DragAndDrop>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
return (
|
||||
<DragAndDrop isDropZone onDrop={onDrop} style={dropDownStyles}>
|
||||
<Text style={textStyles} color="#999" fontSize="20px">
|
||||
Drop items here
|
||||
</Text>
|
||||
</DragAndDrop>
|
||||
);
|
||||
});
|
||||
|
@ -1,66 +1,127 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { withKnobs, boolean, select } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import DropDown from "../drop-down";
|
||||
import DropDownItem from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
|
||||
storiesOf("Components | DropDown", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base item", () => {
|
||||
const isHeader = boolean("Show category`s", true);
|
||||
const isSeparator = boolean("Show separator", true);
|
||||
const useIcon = boolean("Show icons", true);
|
||||
const direction = select("direction", ["left", "right"], "left");
|
||||
export default {
|
||||
title: "Components/DropDownItem",
|
||||
component: DropDownItem,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ height: "200px", position: "relative" }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
isHeader: {
|
||||
description: "Tells when the dropdown item should display like header",
|
||||
},
|
||||
isSeparator: {
|
||||
description: "Tells when the dropdown item should display like separator",
|
||||
},
|
||||
noHover: { description: "Disable default style hover effect" },
|
||||
className: { description: "Accepts class" },
|
||||
disabled: {
|
||||
description: "Tells when the dropdown item should display like disabled",
|
||||
},
|
||||
icon: { description: "Dropdown item icon" },
|
||||
id: { description: "Accepts id" },
|
||||
label: { description: "Dropdown item text" },
|
||||
onClick: {
|
||||
description: "What the dropdown item will trigger when clicked",
|
||||
action: "onClick",
|
||||
},
|
||||
style: { description: "Accepts css style" },
|
||||
tabIndex: { table: { disable: true } },
|
||||
children: { table: { disable: true } },
|
||||
textOverflow: { table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Is a item of DropDown component
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<DropDown directionX={direction} manualY="1%" open={true}>
|
||||
<DropDownItem
|
||||
isHeader={isHeader}
|
||||
label={isHeader ? "Category" : ""}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={useIcon ? "WindowsMsnIcon" : ""}
|
||||
label="Button 1"
|
||||
onClick={() => console.log("Button 1 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={useIcon ? "PlaneIcon" : ""}
|
||||
label="Button 2"
|
||||
onClick={() => console.log("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
disabled
|
||||
icon={useIcon ? "static/images/copy.react.svg" : ""}
|
||||
label="Button 3"
|
||||
onClick={() => console.log("Button 3 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={useIcon ? "ActionsDocumentsIcon" : ""}
|
||||
label="Button 4"
|
||||
onClick={() => console.log("Button 4 clicked")}
|
||||
/>
|
||||
<DropDownItem isSeparator={isSeparator} />
|
||||
<DropDownItem
|
||||
isHeader={isHeader}
|
||||
label={isHeader ? "Category" : ""}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={useIcon ? "static/images/nav.logo.react.svg" : ""}
|
||||
label="Button 5"
|
||||
onClick={() => console.log("Button 5 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
disabled
|
||||
icon={useIcon ? "static/images/nav.logo.react.svg" : ""}
|
||||
label="Button 6"
|
||||
onClick={() => console.log("Button 6 clicked")}
|
||||
/>
|
||||
</DropDown>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
An item can act as separator, header, or container.
|
||||
|
||||
When used as container, it will retain all styling features and positioning. To disable hover effects in container mode, you can use _noHover_ property.`,
|
||||
},
|
||||
source: {
|
||||
code: `import DropDownItem from "@appserver/components/drop-down-item";
|
||||
|
||||
<DropDownItem
|
||||
isSeparator={false}
|
||||
isHeader={false}
|
||||
label="Button 1"
|
||||
icon="static/images/nav.logo.react.svg"
|
||||
onClick={() => console.log("Button 1 clicked")}
|
||||
/>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
const isHeader = args.isHeader;
|
||||
const isSeparator = args.isSeparator;
|
||||
const useIcon = args.useIcon;
|
||||
const direction = "left";
|
||||
const noHover = args.noHover;
|
||||
const disabled = args.disabled;
|
||||
const { onClick } = args;
|
||||
return (
|
||||
<DropDown directionX={direction} manualY="1%" open={true}>
|
||||
<DropDownItem
|
||||
isHeader={isHeader}
|
||||
label={isHeader ? "Category" : ""}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={"WindowsMsnIcon"}
|
||||
label="Button 1"
|
||||
disabled={disabled}
|
||||
onClick={() => onClick("Button 1 clicked")}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={"PlaneIcon"}
|
||||
label="Button 2"
|
||||
onClick={() => onClick("Button 2 clicked")}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem
|
||||
disabled
|
||||
icon={"static/images/copy.react.svg"}
|
||||
label={args.label || "Button 3"}
|
||||
disabled={disabled}
|
||||
onClick={() => onClick("Button 3 clicked")}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={"ActionsDocumentsIcon"}
|
||||
label="Button 4"
|
||||
onClick={() => onClick("Button 4 clicked")}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem isSeparator={isSeparator} />
|
||||
<DropDownItem
|
||||
isHeader={isHeader}
|
||||
label={isHeader ? "Category" : ""}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem
|
||||
icon={"static/images/nav.logo.react.svg"}
|
||||
label="Button 5"
|
||||
onClick={() => onClick("Button 5 clicked")}
|
||||
noHover={noHover}
|
||||
/>
|
||||
<DropDownItem
|
||||
disabled
|
||||
icon={"static/images/nav.logo.react.svg"}
|
||||
label="Button 6"
|
||||
onClick={() => console.log("Button 6 clicked")}
|
||||
noHover={noHover}
|
||||
/>
|
||||
</DropDown>
|
||||
);
|
||||
};
|
||||
export const Default = Template.bind({});
|
||||
|
@ -1,70 +1,209 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import DropDown from ".";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import DropDown from "./";
|
||||
import DropDownItem from "../drop-down-item";
|
||||
import GroupButton from "../group-button";
|
||||
|
||||
storiesOf("Components| DropDown", module)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => (
|
||||
<div
|
||||
style={{
|
||||
padding: "8px 0 0 60px",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
}}
|
||||
export default {
|
||||
title: "Components/DropDown",
|
||||
component: DropDown,
|
||||
subcomponents: { DropDownItem, GroupButton },
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ height: "200px", position: "relative" }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
open: { description: "Tells when the dropdown should be opened" },
|
||||
className: { description: " Accepts class" },
|
||||
clickOutsideAction: {
|
||||
description:
|
||||
"Required for determining a click outside DropDown with the withBackdrop parameter",
|
||||
},
|
||||
directionX: {
|
||||
description: "Sets the opening direction relative to the parent",
|
||||
},
|
||||
directionY: {
|
||||
description: "Sets the opening direction relative to the parent",
|
||||
},
|
||||
id: { description: "Accepts id " },
|
||||
manualWidth: {
|
||||
description:
|
||||
"Required if you need to specify the exact width of the component, for example 100%",
|
||||
},
|
||||
manualX: {
|
||||
description:
|
||||
"Required if you need to specify the exact distance from the parent component",
|
||||
},
|
||||
manualY: {
|
||||
description:
|
||||
"Required if you need to specify the exact distance from the parent component",
|
||||
},
|
||||
maxHeight: { description: "Required if the scrollbar is displayed" },
|
||||
style: { description: "Accepts css style" },
|
||||
withBackdrop: { description: "Used to display backdrop" },
|
||||
showDisabledItems: { description: "Display disabled items or not" },
|
||||
children: { table: { disable: true } },
|
||||
columnCount: { table: { disable: true } },
|
||||
disableOnClickOutside: { table: { disable: true } },
|
||||
enableOnClickOutside: { table: { disable: true } },
|
||||
onClick: { action: "onClickItem", table: { disable: true } },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Is a dropdown with any number of action
|
||||
By default, it is used with DropDownItem elements in role of children.
|
||||
|
||||
If you want to display something custom, you can put it in children, but take into account that all stylization is assigned to the implemented component.
|
||||
|
||||
When using component, it should be noted that parent must have CSS property _position: relative_. Otherwise, DropDown will appear outside parent's border.
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
const [isOpen, setIsOpen] = useState(args.open);
|
||||
|
||||
const clickOutsideAction = (e) => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<DropDown
|
||||
{...args}
|
||||
open={isOpen}
|
||||
clickOutsideAction={clickOutsideAction}
|
||||
style={{ top: 0, left: 0 }}
|
||||
onClick={() => {}}
|
||||
>
|
||||
<div style={{ position: "relative" }}>
|
||||
<div>Only dropdown</div>
|
||||
<div style={{ marginTop: 8 }}>Without active button</div>
|
||||
<DropDown open={true}>
|
||||
<DropDownItem isHeader label="Category 1" />
|
||||
<DropDownItem
|
||||
label="Button 1"
|
||||
onClick={() => console.log("Button 1 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 2"
|
||||
onClick={() => console.log("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 3"
|
||||
onClick={() => console.log("Button 3 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 4"
|
||||
onClick={() => console.log("Button 4 clicked")}
|
||||
disabled={true}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
label="Button 5"
|
||||
onClick={() => console.log("Button 5 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 6"
|
||||
onClick={() => console.log("Button 6 clicked")}
|
||||
/>
|
||||
</DropDown>
|
||||
</div>
|
||||
<div style={{ position: "relative" }}>
|
||||
<div style={{ marginLeft: 16 }}>With Button</div>
|
||||
<GroupButton label="Dropdown demo" isDropdown={true}>
|
||||
<DropDownItem
|
||||
label="Button 1"
|
||||
onClick={() => console.log("Button 1 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 2"
|
||||
onClick={() => console.log("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 3"
|
||||
onClick={() => console.log("Button 3 clicked")}
|
||||
/>
|
||||
</GroupButton>
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
<DropDownItem isHeader label="Category 1" />
|
||||
|
||||
<DropDownItem
|
||||
label="Button 1"
|
||||
onClick={() => args.onClick("Button 1 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 2"
|
||||
onClick={() => args.onClick("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 3"
|
||||
onClick={() => args.onClick("Button 3 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 4"
|
||||
onClick={() => args.onClick("Button 4 clicked")}
|
||||
disabled={true}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
label="Button 5"
|
||||
onClick={() => args.onClick("Button 5 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 6"
|
||||
onClick={() => args.onClick("Button 6 clicked")}
|
||||
/>
|
||||
</DropDown>
|
||||
);
|
||||
};
|
||||
|
||||
const WithButtonTemplate = (args) => {
|
||||
return (
|
||||
<GroupButton
|
||||
label="Dropdown demo"
|
||||
style={{ top: 0, left: 0 }}
|
||||
isDropdown={true}
|
||||
opened={args.open}
|
||||
>
|
||||
<DropDownItem
|
||||
label="Button 1"
|
||||
onClick={() => args.onClick("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 2"
|
||||
onClick={() => args.onClick("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 3"
|
||||
onClick={() => args.onClick("Button 3 clicked")}
|
||||
/>
|
||||
</GroupButton>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
export const WithButton = WithButtonTemplate.bind({});
|
||||
|
||||
Default.args = { open: true };
|
||||
Default.parameters = {
|
||||
docs: {
|
||||
source: {
|
||||
code: `import DropDown from "@appserver/components/drop-down";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
|
||||
<DropDown {...props}>
|
||||
<DropDownItem isHeader label="Category 1" />
|
||||
<DropDownItem
|
||||
label="Button 1"
|
||||
onClick={() => action("Button 1 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 2"
|
||||
onClick={() => action("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 3"
|
||||
onClick={() => action("Button 3 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 4"
|
||||
onClick={() => action("Button 4 clicked")}
|
||||
disabled={true}
|
||||
/>
|
||||
<DropDownItem isSeparator />
|
||||
<DropDownItem
|
||||
label="Button 5"
|
||||
onClick={() => action("Button 5 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 6"
|
||||
onClick={() => action("Button 6 clicked")}
|
||||
/>
|
||||
</DropDown>`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
WithButton.args = {
|
||||
open: true,
|
||||
};
|
||||
WithButton.parameters = {
|
||||
docs: {
|
||||
source: {
|
||||
code: `import GroupButton from "@appserver/components/group-button";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
|
||||
<GroupButton label="Dropdown demo" isDropdown={true}>
|
||||
<DropDownItem
|
||||
label="Button 1"
|
||||
onClick={() => console.log("Button 1 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 2"
|
||||
onClick={() => console.log("Button 2 clicked")}
|
||||
/>
|
||||
<DropDownItem
|
||||
label="Button 3"
|
||||
onClick={() => console.log("Button 3 clicked")}
|
||||
/>
|
||||
</GroupButton>`,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -171,33 +171,6 @@ class DropDown extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
DropDown.propTypes = {
|
||||
children: PropTypes.any,
|
||||
className: PropTypes.string,
|
||||
clickOutsideAction: PropTypes.func,
|
||||
directionX: PropTypes.oneOf(["left", "right"]), //TODO: make more informative
|
||||
directionY: PropTypes.oneOf(["bottom", "top"]),
|
||||
disableOnClickOutside: PropTypes.func,
|
||||
enableOnClickOutside: PropTypes.func,
|
||||
id: PropTypes.string,
|
||||
manualWidth: PropTypes.string,
|
||||
manualX: PropTypes.string,
|
||||
manualY: PropTypes.string,
|
||||
maxHeight: PropTypes.number,
|
||||
open: PropTypes.bool,
|
||||
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||
withBackdrop: PropTypes.bool,
|
||||
columnCount: PropTypes.number,
|
||||
showDisabledItems: PropTypes.bool,
|
||||
};
|
||||
|
||||
DropDown.defaultProps = {
|
||||
directionX: "left",
|
||||
directionY: "bottom",
|
||||
withBackdrop: false,
|
||||
showDisabledItems: false,
|
||||
};
|
||||
|
||||
const EnhancedComponent = onClickOutside(DropDown);
|
||||
|
||||
class DropDownContainer extends React.Component {
|
||||
@ -226,8 +199,30 @@ class DropDownContainer extends React.Component {
|
||||
}
|
||||
|
||||
DropDownContainer.propTypes = {
|
||||
children: PropTypes.any,
|
||||
className: PropTypes.string,
|
||||
clickOutsideAction: PropTypes.func,
|
||||
directionX: PropTypes.oneOf(["left", "right"]), //TODO: make more informative
|
||||
directionY: PropTypes.oneOf(["bottom", "top"]),
|
||||
disableOnClickOutside: PropTypes.func,
|
||||
enableOnClickOutside: PropTypes.func,
|
||||
id: PropTypes.string,
|
||||
manualWidth: PropTypes.string,
|
||||
manualX: PropTypes.string,
|
||||
manualY: PropTypes.string,
|
||||
maxHeight: PropTypes.number,
|
||||
open: PropTypes.bool,
|
||||
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||
withBackdrop: PropTypes.bool,
|
||||
columnCount: PropTypes.number,
|
||||
showDisabledItems: PropTypes.bool
|
||||
};
|
||||
|
||||
DropDownContainer.defaultProps = {
|
||||
directionX: "left",
|
||||
directionY: "bottom",
|
||||
withBackdrop: false,
|
||||
showDisabledItems: false,
|
||||
};
|
||||
|
||||
export default DropDownContainer;
|
||||
|
@ -1,67 +1,261 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import {
|
||||
text,
|
||||
boolean,
|
||||
withKnobs,
|
||||
select,
|
||||
number,
|
||||
} from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import EmailInput from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import React, { useState } from "react";
|
||||
import EmailInput from "./";
|
||||
|
||||
const sizeInput = ["base", "middle", "big", "huge", "large"];
|
||||
export default {
|
||||
title: "Components/EmailInput",
|
||||
component: EmailInput,
|
||||
argTypes: {
|
||||
allowDomainPunycode: { control: "boolean" },
|
||||
allowLocalPartPunycode: { control: "boolean" },
|
||||
allowDomainIp: { control: "boolean" },
|
||||
allowStrictLocalPart: { control: "boolean" },
|
||||
allowSpaces: { control: "boolean" },
|
||||
allowName: { control: "boolean" },
|
||||
allowLocalDomainName: { control: "boolean" },
|
||||
onValidateInput: { action: "onValidateInput" },
|
||||
onChange: { action: "onChange" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Email entry field with advanced capabilities for validation based on setting
|
||||
|
||||
storiesOf("Components|Input", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("email input", () => {
|
||||
const placeholder = text("placeholder", "Input email");
|
||||
const size = select("size", sizeInput, "base");
|
||||
const scale = boolean("scale", false);
|
||||
const isDisabled = boolean("isDisabled", false);
|
||||
const isReadOnly = boolean("isReadOnly", false);
|
||||
const maxLength = number("maxLength", 255);
|
||||
const id = text("id", "emailId");
|
||||
const name = text("name", "demoEmailInput");
|
||||
### Properties
|
||||
|
||||
const allowDomainPunycode = boolean("allowDomainPunycode", false);
|
||||
const allowLocalPartPunycode = boolean("allowLocalPartPunycode", false);
|
||||
const allowDomainIp = boolean("allowDomainIp", false);
|
||||
const allowStrictLocalPart = boolean("allowStrictLocalPart", true);
|
||||
const allowSpaces = boolean("allowSpaces", false);
|
||||
const allowName = boolean("allowName", false);
|
||||
const allowLocalDomainName = boolean("allowLocalDomainName", false);
|
||||
You can apply all properties of the 'TextInput' component to the component
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ----------------- | :-----------------------: | :------: | :-----------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| className | string | - | - | - | Accepts class |
|
||||
| customValidate | func | - | - | - | Function for your custom validation input value. Function must return object with following parameters: 'value': string value of input, 'isValid': boolean result of validating, 'errors'(optional): array of errors |
|
||||
| emailSettings | Object, EmailSettings | - | - | { allowDomainPunycode: false, allowLocalPartPunycode: false, allowDomainIp: false, allowStrictLocalPart: true, allowSpaces: false, allowName: false, allowLocalDomainName: false } | Settings for validating email |
|
||||
| hasError | bool | - | - | - | Used in your custom validation |
|
||||
| id | string | - | - | - | Accepts id |
|
||||
| onChange | func | - | - | - | Function for your custom handling changes in input |
|
||||
| onValidateInput | func | - | { isValid: bool, errors: array} | - | Will be validate our value, return object with following parameters: 'isValid': boolean result of validating, 'errors': array of errors |
|
||||
| style | obj, array | - | - | - | Accepts css style
|
||||
|
||||
### Validate email
|
||||
|
||||
Our validation algorithm based on [RFC 5322 email address parser](https://www.npmjs.com/package/email-addresses).
|
||||
|
||||
For email validating you should use plain Object or EmailSettings with following settings:
|
||||
|
||||
const settings = {
|
||||
|
||||
allowDomainPunycode,
|
||||
|
||||
allowLocalPartPunycode,
|
||||
|
||||
allowDomainIp,
|
||||
|
||||
allowStrictLocalPart,
|
||||
|
||||
allowSpaces,
|
||||
|
||||
allowName,
|
||||
|
||||
allowLocalDomainName,
|
||||
};
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<EmailInput
|
||||
placeholder={placeholder}
|
||||
size={size}
|
||||
scale={scale}
|
||||
isDisabled={isDisabled}
|
||||
isReadOnly={isReadOnly}
|
||||
maxLength={maxLength}
|
||||
id={id}
|
||||
name={name}
|
||||
emailSettings={settings}
|
||||
onValidateInput={(isEmailValid) =>
|
||||
action("onValidateInput")(isEmailValid)
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
});
|
||||
### emailSettings prop
|
||||
|
||||
Plain object:
|
||||
|
||||
const emailSettings = {
|
||||
|
||||
allowDomainPunycode: false,
|
||||
|
||||
allowLocalPartPunycode: false,
|
||||
|
||||
allowDomainIp: false,
|
||||
|
||||
allowStrictLocalPart: true,
|
||||
|
||||
allowSpaces: false,
|
||||
|
||||
allowName: false,
|
||||
|
||||
allowLocalDomainName: false,
|
||||
};
|
||||
|
||||
or instance of 'EmailSettings' class:
|
||||
|
||||
import { EmailInput, utils } from "@appserver/components";
|
||||
|
||||
const { EmailSettings } = utils.email;
|
||||
|
||||
const emailSettings = new EmailSettings();
|
||||
|
||||
emailSettings.toObject(); /* returned Object with default settings:
|
||||
|
||||
{
|
||||
allowDomainPunycode: false,
|
||||
|
||||
allowLocalPartPunycode: false,
|
||||
|
||||
allowDomainIp: false,
|
||||
|
||||
allowStrictLocalPart: true,
|
||||
|
||||
allowSpaces: false,
|
||||
|
||||
allowName: false,
|
||||
|
||||
allowLocalDomainName: false
|
||||
}
|
||||
*/
|
||||
|
||||
email.allowName = true; // set allowName setting to true
|
||||
|
||||
emailSettings.toObject(); /* returned Object with NEW settings:
|
||||
|
||||
{
|
||||
allowDomainPunycode: false,
|
||||
|
||||
allowLocalPartPunycode: false,
|
||||
|
||||
allowDomainIp: false,
|
||||
|
||||
allowStrictLocalPart: true,
|
||||
|
||||
allowSpaces: false,
|
||||
|
||||
allowName: true,
|
||||
|
||||
allowLocalDomainName: false
|
||||
}
|
||||
*/
|
||||
|
||||
### Custom validate email
|
||||
|
||||
You should use custom validation with the 'customValidate' prop. This prop contains function for your custom validation input value. Function must return object with following parameters: 'value': string value of input, 'isValid': boolean result of validating, 'errors'(optional): array of errors.
|
||||
|
||||
Base colors:
|
||||
|
||||
| Сomponent actions | isValid | border-color |
|
||||
| ----------------- | :-----: | :--------------------------------------------------------------: |
|
||||
| :focus | false | ![#c30](https://placehold.it/15/c30/000000?text=+) #c30 |
|
||||
| :focus | true | ![#2DA7DB](https://placehold.it/15/2DA7DB/000000?text=+) #2DA7DB |
|
||||
| :hover | false | ![#c30](https://placehold.it/15/c30/000000?text=+) #c30 |
|
||||
| :hover | true | ![#D0D5DA](https://placehold.it/15/D0D5DA/000000?text=+) #D0D5DA |
|
||||
| default | false | ![#c30](https://placehold.it/15/c30/000000?text=+) #c30 |
|
||||
| default | true | ![#D0D5DA](https://placehold.it/15/D0D5DA/000000?text=+) #D0D5DA |
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { EmailInput } from "@appserver/components";
|
||||
|
||||
|
||||
const onChange = (e) => {
|
||||
|
||||
// your event handling
|
||||
|
||||
customValidate(e.target.value);
|
||||
};
|
||||
|
||||
|
||||
const customValidate = (value) => {
|
||||
|
||||
const isValid = !!(value && value.length > 0);
|
||||
|
||||
return {
|
||||
|
||||
value,
|
||||
|
||||
isValid: isValid,
|
||||
|
||||
errors: isValid ? [] : ["incorrect email"],
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const onValidateInput = (result) => {
|
||||
|
||||
console.log("onValidateInput", result);
|
||||
};
|
||||
|
||||
|
||||
<EmailInput
|
||||
|
||||
customValidate={customValidate}
|
||||
|
||||
onChange={onChange}
|
||||
|
||||
onValidateInput={onValidateInput}
|
||||
/>
|
||||
|
||||
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `import EmailInput from "@appserver/components/email-input";
|
||||
import { EmailSettings } from "@appserver/components/utils/email";
|
||||
|
||||
const settings = new EmailSettings();
|
||||
settings.allowDomainPunycode = true;
|
||||
|
||||
<EmailInput
|
||||
name="email"
|
||||
placeholder="email"
|
||||
emailSettings={settings}
|
||||
onValidateInput={result =>
|
||||
console.log("onValidateInput", result.value, result.isValid, result.errors);
|
||||
}
|
||||
/>
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = ({
|
||||
allowDomainPunycode,
|
||||
allowLocalPartPunycode,
|
||||
allowDomainIp,
|
||||
allowStrictLocalPart,
|
||||
allowSpaces,
|
||||
allowName,
|
||||
allowLocalDomainName,
|
||||
...rest
|
||||
}) => {
|
||||
const [emailValue, setEmailValue] = useState("");
|
||||
|
||||
const onChangeHandler = (value) => {
|
||||
setEmailValue(value);
|
||||
};
|
||||
const settings = {
|
||||
allowDomainPunycode,
|
||||
allowLocalPartPunycode,
|
||||
allowDomainIp,
|
||||
allowStrictLocalPart,
|
||||
allowSpaces,
|
||||
allowName,
|
||||
allowLocalDomainName,
|
||||
};
|
||||
return (
|
||||
<EmailInput
|
||||
{...rest}
|
||||
value={emailValue}
|
||||
emailSettings={settings}
|
||||
onValidateInput={(isEmailValid) => rest.onValidateInput(isEmailValid)}
|
||||
onChange={(e) => {
|
||||
rest.onChange(e.target.value);
|
||||
onChangeHandler(e.target.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
allowDomainPunycode: false,
|
||||
allowLocalPartPunycode: false,
|
||||
allowDomainIp: false,
|
||||
allowSpaces: false,
|
||||
allowName: false,
|
||||
allowLocalDomainName: false,
|
||||
allowStrictLocalPart: true,
|
||||
placeholder: "Input email",
|
||||
size: "base",
|
||||
};
|
||||
|
@ -122,11 +122,20 @@ EmailInput.propTypes = {
|
||||
PropTypes.objectOf(PropTypes.bool),
|
||||
]),
|
||||
hasError: PropTypes.bool,
|
||||
size: PropTypes.oneOf(["base", "middle", "big", "huge", "large"]),
|
||||
id: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onValidateInput: PropTypes.func,
|
||||
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||
value: PropTypes.string,
|
||||
autoComplete: PropTypes.string,
|
||||
isDisabled: PropTypes.bool,
|
||||
isReadOnly: PropTypes.bool,
|
||||
name: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
scale: PropTypes.bool,
|
||||
size: "base",
|
||||
size: PropTypes.oneOf(["base", "middle", "big", "huge", "large"]),
|
||||
};
|
||||
|
||||
EmailInput.defaultProps = {
|
||||
|
@ -1,42 +1,72 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import { withKnobs, text } from "@storybook/addon-knobs/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import EmptyScreenContainer from ".";
|
||||
import EmptyScreenContainer from "./";
|
||||
import Link from "../link";
|
||||
import CrossIcon from "../../../../../public/images/cross.react.svg"
|
||||
storiesOf("Components| EmptyScreenContainer", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("base", () => (
|
||||
import CrossIcon from "../../../public/images/cross.react.svg";
|
||||
|
||||
export default {
|
||||
title: "Components/EmptyScreenContainer",
|
||||
component: EmptyScreenContainer,
|
||||
argTypes: { onClick: { action: "Reset filter clicked" } },
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Used to display empty screen page
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ----------------- | :------------: | :------: | :----: | :-----: | --------------------------------------- |
|
||||
| buttons | element | - | - | - | Content of EmptyContentButtonsContainer |
|
||||
| className | string | - | - | - | Accepts class |
|
||||
| descriptionText | string | - | - | - | Description text |
|
||||
| headerText | string | - | - | - | Header text |
|
||||
| subheadingText | string | - | - | - | Subheading text |
|
||||
| id | string | - | - | - | Accepts id |
|
||||
| imageAlt | string | - | - | - | Alternative image text |
|
||||
| imageSrc | string | - | - | - | Image url source |
|
||||
| style | obj, array | - | - | - | Accepts css style |
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `
|
||||
import EmptyScreenContainer from "@appserver/components/empty-screen-container";
|
||||
|
||||
<EmptyScreenContainer
|
||||
imageSrc="empty_screen_filter.png"
|
||||
imageAlt="Empty Screen Filter image"
|
||||
headerText="No results matching your search could be found"
|
||||
subheading="No files to be displayed in this section"
|
||||
descriptionText="No results matching your search could be found"
|
||||
buttons={<a href="/">Go to home</a>}
|
||||
/>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
return (
|
||||
<EmptyScreenContainer
|
||||
imageSrc={text("imageSrc", "empty_screen_filter.png")}
|
||||
imageAlt={text("imageAlt", "Empty Screen Filter image")}
|
||||
headerText={text(
|
||||
"headerText",
|
||||
"No results matching your search could be found"
|
||||
)}
|
||||
subheadingText={text(
|
||||
"subheaderText",
|
||||
"No files to be displayed in this section"
|
||||
)}
|
||||
descriptionText={text(
|
||||
"descriptionText",
|
||||
"No people matching your filter can be displayed in this section. Please select other filter options or clear filter to view all the people in this section."
|
||||
)}
|
||||
{...args}
|
||||
buttons={
|
||||
<>
|
||||
<CrossIcon size="small" style={{ marginRight: "4px" }} />
|
||||
<Link
|
||||
type="action"
|
||||
isHovered={true}
|
||||
onClick={(e) => action("Reset filter clicked")(e)}
|
||||
>
|
||||
<Link type="action" isHovered={true} onClick={(e) => args.onClick(e)}>
|
||||
Reset filter
|
||||
</Link>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
));
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
Default.args = {
|
||||
imageSrc: "empty_screen_filter.png",
|
||||
imageAlt: "Empty Screen Filter image",
|
||||
headerText: "No results matching your search could be found",
|
||||
subheadingText: "No files to be displayed in this section",
|
||||
descriptionText:
|
||||
"No people matching your filter can be displayed in this section. Please select other filter options or clear filter to view all the people in this section.",
|
||||
};
|
||||
|
@ -1,4 +1,91 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import FieldContainer from ".";
|
||||
import TextInput from "../text-input";
|
||||
|
||||
export default {
|
||||
title: "Components/FieldContainer",
|
||||
component: FieldContainer,
|
||||
argTypes: {
|
||||
errorColor: { control: "color" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `Responsive form field container
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------------------- | :---------------: | :------: | :----: | :-------: | ------------------------------------------------ |
|
||||
| className | string | - | - | - | Accepts class |
|
||||
| errorColor | string | - | - | ![#C96C27](https://placehold.it/15/C96C27/000000?text=+) #C96C27 | Error text color |
|
||||
| errorMessageWidth | string | - | - | 320px | Error text width |
|
||||
| errorMessage | string | - | - | - | Error message text |
|
||||
| hasError | bool | - | - | false | Indicates that the field is incorrect |
|
||||
| helpButtonHeaderContent | string | - | - | - | Tooltip header content (tooltip opened in aside) |
|
||||
| id | string | - | - | - | Accepts id |
|
||||
| isRequired | bool | - | - | false | Indicates that the field is required to fill |
|
||||
| isVertical | bool | - | - | false | Vertical or horizontal alignment |
|
||||
| labelText | string | - | - | - | Field label text |
|
||||
| labelVisible | bool | - | - | true | Sets visibility of field label section |
|
||||
| maxLabelWidth | string | - | - | 110px | Max label width in horizontal alignment |
|
||||
| style | obj, array | - | - | - | Accepts css style |
|
||||
| tooltipContent | object, string | - | - | - | Tooltip content |
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `import FieldContainer from "@appserver/components/field-container";
|
||||
|
||||
<FieldContainer labelText="Name:">
|
||||
<TextInput value="" onChange={(e) => console.log(e.target.value)} />
|
||||
</FieldContainer>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
const [value, setValue] = useState("");
|
||||
return (
|
||||
<FieldContainer {...args}>
|
||||
<TextInput
|
||||
value={value}
|
||||
hasError={args.hasError}
|
||||
className="field-input"
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</FieldContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
isVertical: false,
|
||||
isRequired: false,
|
||||
hasError: false,
|
||||
labelVisible: true,
|
||||
labelText: "Name:",
|
||||
maxLabelWidth: "110px",
|
||||
tooltipContent: "Paste you tooltip content here",
|
||||
helpButtonHeaderContent: "Tooltip header",
|
||||
place: "top",
|
||||
errorMessage:
|
||||
"Error text. Lorem ipsum dolor sit amet, consectetuer adipiscing elit",
|
||||
errorColor: "#C96C27",
|
||||
errorMessageWidth: "293px",
|
||||
};
|
||||
Default.parameters = {
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ marginTop: 100, marginLeft: 50 }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
};
|
||||
/*
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { StringValue } from "react-values";
|
||||
@ -58,3 +145,4 @@ storiesOf("Components|FieldContainer", module)
|
||||
)}
|
||||
</StringValue>
|
||||
));
|
||||
*/
|
||||
|
@ -1,49 +1,80 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { text, boolean, withKnobs, select } from "@storybook/addon-knobs/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
import FileInput from ".";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import FileInput from "./";
|
||||
|
||||
const sizeInput = ["base", "middle", "big", "huge", "large"];
|
||||
export default {
|
||||
title: "Components/FileInput",
|
||||
component: FileInput,
|
||||
argTypes: {
|
||||
onInput: { action: "onInput" },
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `File entry field
|
||||
|
||||
storiesOf("Components|Input", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("file input", () => {
|
||||
const placeholder = text("placeholder", "Input file");
|
||||
const size = select("size", sizeInput, "base");
|
||||
const scale = boolean("scale", false);
|
||||
const isDisabled = boolean("isDisabled", false);
|
||||
const id = text("id", "fileInputId");
|
||||
const name = text("name", "demoFileInputName");
|
||||
const hasError = boolean("hasError", false);
|
||||
const hasWarning = boolean("hasWarning", false);
|
||||
const accept = text("accept", ".doc, .docx");
|
||||
### Properties
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<FileInput
|
||||
id={id}
|
||||
name={name}
|
||||
placeholder={placeholder}
|
||||
size={size}
|
||||
scale={scale}
|
||||
isDisabled={isDisabled}
|
||||
hasError={hasError}
|
||||
hasWarning={hasWarning}
|
||||
accept={accept}
|
||||
onInput={(file) => {
|
||||
action("onInput")(file);
|
||||
console.log(
|
||||
`name: ${file.name}`,
|
||||
`lastModified: ${file.lastModifiedDate}`,
|
||||
`size: ${file.size}`
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------- | :------------: | :------: | :--------------------------------------: | :-----: | ---------------------------------------------------------------------------------- |
|
||||
| className | string | - | - | - | Accepts class |
|
||||
| hasError | bool | - | - | false | Indicates the input field has an error |
|
||||
| hasWarning | bool | - | - | false | Indicates the input field has a warning |
|
||||
| id | string | - | - | - | Used as HTML 'id' property |
|
||||
| isDisabled | bool | - | - | false | Indicates that the field cannot be used (e.g not authorised, or changes not saved) |
|
||||
| name | string | - | - | - | Used as HTML 'name' property |
|
||||
| onInput | func | - | - | - | Called when a file is selected |
|
||||
| placeholder | string | - | - | - | Placeholder text for the input |
|
||||
| scale | bool | - | - | false | Indicates the input field has scale |
|
||||
| size | string | - | base, middle, big, huge, large | base | Supported size of the input fields. |
|
||||
| style | obj, array | - | - | - | Accepts css style |
|
||||
| accept | string | - | - | - | Specifies files visible for upload |
|
||||
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `import FileInput from "@appserver/components/file-input";
|
||||
<FileInput
|
||||
placeholder="Input file"
|
||||
accept=".doc, .docx"
|
||||
onInput={(file) => {
|
||||
console.log(
|
||||
file,
|
||||
"name: ", file.name},
|
||||
"lastModified: ", file.lastModifiedDate},
|
||||
"size: ", file.size}
|
||||
);
|
||||
});
|
||||
}}
|
||||
/>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
return (
|
||||
<FileInput
|
||||
{...args}
|
||||
onInput={(file) => {
|
||||
args.onInput(
|
||||
`File: ${file},
|
||||
name: ${file.name},
|
||||
lastModified: ${file.lastModifiedDate},
|
||||
size: ${file.size}`
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
placeholder: "Input file",
|
||||
size: "base",
|
||||
scale: false,
|
||||
isDisabled: false,
|
||||
id: "file-input-id",
|
||||
name: "demoFileInputName",
|
||||
hasError: false,
|
||||
hasWarning: false,
|
||||
accept: ".doc, .docx",
|
||||
};
|
||||
|
@ -1,4 +1,229 @@
|
||||
import React from "react";
|
||||
|
||||
import Grid from "./";
|
||||
import Box from "../box";
|
||||
import Text from "../text";
|
||||
|
||||
export default {
|
||||
title: "Components/Grid",
|
||||
component: Grid,
|
||||
subcomponents: { Box },
|
||||
argTypes: {},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component: `A container that lays out its contents in a 2-dimensional grid system. Use Box components to define rows and columns.
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| :--------------: | :-----------------------: | :------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| alignContent | string | - | - | - | sets the distribution of space between and around content items along a flexbox's cross-axis or a grid's block axis |
|
||||
| alignItems | string | - | - | - | sets the align-self value on all direct children as a group. In Flexbox, it controls the alignment of items on the Cross Axis. In Grid Layout, it controls the alignment of items on the Block Axis within their grid area. |
|
||||
| alignSelf | string | - | - | - | overrides a grid or flex item's align-items value. In Grid, it aligns the item inside the grid area. In Flexbox, it aligns the item on the cross axis. |
|
||||
| areasProp | array | - | [["header","header"],["navbar","main"]], [{ name: "header", start: [0, 0], end: [1, 0] }, { name: "navbar", start: [0, 1], end: [0, 1] }, { name: "main", start: [1, 1], end: [1, 1] }] | - | specifies named grid areas. Takes value as array of string arrays that specify named grid areas. Or objects array, that contains names and coordinates of areas. |
|
||||
| columnsProp | string,array,object | - | "25%", ["200px", ["100px","1fr"], "auto"], { count: 3, size: "100px" } | - | defines the sizing of the grid columns. Specifying a single string will repeat several columns of this size. Specifying an object allows you to specify the number of repetitions and the size of the column. Or you can specify an array with column sizes. The column size can be specified as an array of minimum and maximum widths. |
|
||||
| gridArea | string | - | - | - | is a shorthand property for grid-row-start, grid-column-start, grid-row-end and grid-column-end, specifying a grid item’s size and location within the grid by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the edges of its grid area. |
|
||||
| gridColumnGap | string | - | - | - | sets the size of the gap (gutter) between an element's columns. |
|
||||
| gridGap | string | - | - | - | sets the gaps (gutters) between rows and columns. It is a shorthand for row-gap and column-gap. |
|
||||
| gridRowGap | string | - | - | - | sets the size of the gap (gutter) between an element's grid rows. |
|
||||
| heightProp | string | - | - | 100% | defines the height of the border of the element area. |
|
||||
| justifyContent | string | - | - | - | defines how the browser distributes space between and around content items along the main-axis of a flex container, and the inline axis of a grid container. |
|
||||
| justifyItems | string | - | - | - | defines the default justify-self for all items of the box, giving them all a default way of justifying each box along the appropriate axis. |
|
||||
| justifySelf | string | - | - | - | sets the way a box is justified inside its alignment container along the appropriate axis. |
|
||||
| marginProp | string | - | - | - | sets the margin area on all four sides of an element. It is a shorthand for margin-top, margin-right, margin-bottom, and margin-left. |
|
||||
| paddingProp | string | - | - | - | sets the padding area on all four sides of an element. It is a shorthand for padding-top, padding-right, padding-bottom, and padding-left |
|
||||
| rowsProp | string,array | - | "50px", ["100px", ["100px","1fr"], "auto"] | - | defines the sizing of the grid rows. Specifying a single string will repeat several rows of this size. Or you can specify an array with rows sizes. The row size can be specified as an array of minimum and maximum heights. |
|
||||
| widthProp | string | - | - | 100% | defines the width of the border of the element area. |
|
||||
|
||||
`,
|
||||
},
|
||||
source: {
|
||||
code: `import Grid from "@appserver/components/grid";
|
||||
|
||||
<Grid {...args} {...gridProps}>
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>200px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>auto</Text>
|
||||
</Box>
|
||||
</Grid>`,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const gridProps = {
|
||||
marginProp: "0 0 20px 0",
|
||||
};
|
||||
|
||||
const boxProps = {
|
||||
paddingProp: "10px",
|
||||
displayProp: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
return (
|
||||
<Grid {...args} {...gridProps}>
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>200px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>auto</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
const TemplateColumns = (args) => {
|
||||
return (
|
||||
<>
|
||||
<Grid
|
||||
{...args}
|
||||
{...gridProps}
|
||||
columnsProp={["200px", ["100px", "1fr"], "auto"]}
|
||||
>
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>200px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>auto</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid {...args} {...gridProps} columnsProp="25%">
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>25%</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>25%</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>25%</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid {...args} {...gridProps} columnsProp={{ count: 3, size: "100px" }}>
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>100px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>100px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>100px</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
{...args}
|
||||
{...gridProps}
|
||||
columnsProp={{ count: 3, size: ["100px", "1fr"] }}
|
||||
>
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const TemplateRows = (args) => {
|
||||
return (
|
||||
<>
|
||||
<Grid
|
||||
{...args}
|
||||
{...gridProps}
|
||||
rowsProp={["100px", ["100px", "1fr"], "auto"]}
|
||||
>
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>100px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>minmax(100px,1fr)</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>auto</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid {...args} {...gridProps} rowsProp="50px">
|
||||
<Box {...boxProps} backgroundProp="#F4991A">
|
||||
<Text>50px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F2EAD3">
|
||||
<Text>50px</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} backgroundProp="#F9F5F0">
|
||||
<Text>50px</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const TemplateLayout = (args) => {
|
||||
return (
|
||||
<Grid
|
||||
{...args}
|
||||
widthProp="100vw"
|
||||
heightProp="100vh"
|
||||
gridGap="10px"
|
||||
rowsProp={["auto", "1fr", "auto"]}
|
||||
columnsProp={[["100px", "1fr"], "3fr", ["100px", "1fr"]]}
|
||||
areasProp={[
|
||||
{ name: "header", start: [0, 0], end: [2, 0] },
|
||||
{ name: "navbar", start: [0, 1], end: [0, 1] },
|
||||
{ name: "main", start: [1, 1], end: [1, 1] },
|
||||
{ name: "sidebar", start: [2, 1], end: [2, 1] },
|
||||
{ name: "footer", start: [0, 2], end: [2, 2] },
|
||||
]}
|
||||
>
|
||||
<Box {...boxProps} gridArea="header" backgroundProp="#F4991A">
|
||||
<Text>header</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} gridArea="navbar" backgroundProp="#F2EAD3">
|
||||
<Text>navbar</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} gridArea="main" backgroundProp="#F9F5F0">
|
||||
<Text>main</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} gridArea="sidebar" backgroundProp="#F2EAD3">
|
||||
<Text>sidebar</Text>
|
||||
</Box>
|
||||
<Box {...boxProps} gridArea="footer" backgroundProp="#F4991A">
|
||||
<Text>footer</Text>
|
||||
</Box>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
columnsProp: ["200px", ["100px", "1fr"], "auto"],
|
||||
};
|
||||
export const Columns = TemplateColumns.bind({});
|
||||
export const Rows = TemplateRows.bind({});
|
||||
export const Layout = TemplateLayout.bind({});
|
||||
/*
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
@ -129,3 +354,4 @@ storiesOf("Components|Grid", module)
|
||||
</Box>
|
||||
</Grid>
|
||||
));
|
||||
*/
|
||||
|
@ -7,9 +7,18 @@
|
||||
"start": "echo 'skip it'",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage"
|
||||
"test:coverage": "jest --coverage",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "^6.1.20",
|
||||
"@storybook/addon-controls": "^6.1.20",
|
||||
"@storybook/addon-docs": "^6.1.20",
|
||||
"@storybook/addon-essentials": "^6.1.20",
|
||||
"@storybook/addon-links": "^6.1.20",
|
||||
"@storybook/react": "^6.1.20",
|
||||
"react-values": "^0.3.3",
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
@ -46,7 +55,6 @@
|
||||
"prettier": "2.1.2",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react-values": "^0.3.3",
|
||||
"rollup": "^1.32.1",
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-cleanup": "^3.2.1",
|
||||
@ -87,4 +95,4 @@
|
||||
"react-window-infinite-loader": "^1.0.5",
|
||||
"resize-image": "^0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ import {
|
||||
NewPasswordButton,
|
||||
PasswordProgress,
|
||||
StyledInput,
|
||||
TooltipStyle,
|
||||
StyledTooltipContainer,
|
||||
StyledTooltipItem,
|
||||
} from "./styled-password-input";
|
||||
|
||||
class PasswordInput extends React.Component {
|
||||
@ -40,12 +43,16 @@ class PasswordInput extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
hideTooltip = () => {
|
||||
this.hideTooltip && this.refTooltip.current.hideTooltip();
|
||||
};
|
||||
|
||||
onBlur = () => {
|
||||
this.refTooltip.current.hideTooltip();
|
||||
this.hideTooltip();
|
||||
};
|
||||
|
||||
changeInputType = () => {
|
||||
this.refTooltip.current.hideTooltip();
|
||||
this.hideTooltip();
|
||||
const newType = this.state.type === "text" ? "password" : "text";
|
||||
|
||||
this.setState({
|
||||
@ -229,25 +236,25 @@ class PasswordInput extends React.Component {
|
||||
return !equal(this.props, nextProps) || !equal(this.state, nextState);
|
||||
}
|
||||
|
||||
// renderTextTooltip = (settings, length, digits, capital, special) => {
|
||||
// return (
|
||||
// <>
|
||||
// <div className="break"></div>
|
||||
// <Text
|
||||
// className="text-tooltip"
|
||||
// fontSize="10px"
|
||||
// color="#A3A9AE"
|
||||
// as="span"
|
||||
// >
|
||||
// {settings.minLength ? length : null}{" "}
|
||||
// {settings.digits ? `, ${digits}` : null}{" "}
|
||||
// {settings.upperCase ? `, ${capital}` : null}{" "}
|
||||
// {settings.specSymbols ? `, ${special}` : null}
|
||||
// </Text>
|
||||
// <div className="break"></div>
|
||||
// </>
|
||||
// );
|
||||
// };
|
||||
renderTextTooltip = (settings, length, digits, capital, special) => {
|
||||
return (
|
||||
<>
|
||||
<div className="break"></div>
|
||||
<Text
|
||||
className="text-tooltip"
|
||||
fontSize="10px"
|
||||
color="#A3A9AE"
|
||||
as="span"
|
||||
>
|
||||
{settings.minLength ? length : null}{" "}
|
||||
{settings.digits ? `, ${digits}` : null}{" "}
|
||||
{settings.upperCase ? `, ${capital}` : null}{" "}
|
||||
{settings.specSymbols ? `, ${special}` : null}
|
||||
</Text>
|
||||
<div className="break"></div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
renderTextTooltip = () => {
|
||||
const {
|
||||
@ -277,46 +284,49 @@ class PasswordInput extends React.Component {
|
||||
) : null;
|
||||
};
|
||||
|
||||
// renderTooltipContent = () =>
|
||||
// !isDisableTooltip && !isDisabled ? (
|
||||
// <StyledTooltipContainer forwardedAs="div" title={tooltipPasswordTitle}>
|
||||
// {tooltipPasswordTitle}
|
||||
// <StyledTooltipItem
|
||||
// forwardedAs="div"
|
||||
// title={tooltipPasswordLength}
|
||||
// valid={validLength}
|
||||
// >
|
||||
// {tooltipPasswordLength}
|
||||
// </StyledTooltipItem>
|
||||
// {passwordSettings.digits && (
|
||||
// <StyledTooltipItem
|
||||
// forwardedAs="div"
|
||||
// title={tooltipPasswordDigits}
|
||||
// valid={validDigits}
|
||||
// >
|
||||
// {tooltipPasswordDigits}
|
||||
// </StyledTooltipItem>
|
||||
// )}
|
||||
// {passwordSettings.upperCase && (
|
||||
// <StyledTooltipItem
|
||||
// forwardedAs="div"
|
||||
// title={tooltipPasswordCapital}
|
||||
// valid={validCapital}
|
||||
// >
|
||||
// {tooltipPasswordCapital}
|
||||
// </StyledTooltipItem>
|
||||
// )}
|
||||
// {passwordSettings.specSymbols && (
|
||||
// <StyledTooltipItem
|
||||
// forwardedAs="div"
|
||||
// title={tooltipPasswordSpecial}
|
||||
// valid={validSpecial}
|
||||
// >
|
||||
// {tooltipPasswordSpecial}
|
||||
// </StyledTooltipItem>
|
||||
// )}
|
||||
// </StyledTooltipContainer>
|
||||
// ) : null;
|
||||
renderTooltipContent = () =>
|
||||
!this.props.isDisableTooltip && !this.props.isDisabled ? (
|
||||
<StyledTooltipContainer
|
||||
forwardedAs="div"
|
||||
title={this.props.tooltipPasswordTitle}
|
||||
>
|
||||
{this.props.tooltipPasswordTitle}
|
||||
<StyledTooltipItem
|
||||
forwardedAs="div"
|
||||
title={this.props.tooltipPasswordLength}
|
||||
valid={this.validLength}
|
||||
>
|
||||
{this.props.tooltipPasswordLength}
|
||||
</StyledTooltipItem>
|
||||
{this.props.passwordSettings.digits && (
|
||||
<StyledTooltipItem
|
||||
forwardedAs="div"
|
||||
title={this.props.tooltipPasswordDigits}
|
||||
valid={this.validDigits}
|
||||
>
|
||||
{this.props.tooltipPasswordDigits}
|
||||
</StyledTooltipItem>
|
||||
)}
|
||||
{this.props.passwordSettings.upperCase && (
|
||||
<StyledTooltipItem
|
||||
forwardedAs="div"
|
||||
title={this.props.tooltipPasswordCapital}
|
||||
valid={this.validCapital}
|
||||
>
|
||||
{this.props.tooltipPasswordCapital}
|
||||
</StyledTooltipItem>
|
||||
)}
|
||||
{this.props.passwordSettings.specSymbols && (
|
||||
<StyledTooltipItem
|
||||
forwardedAs="div"
|
||||
title={this.props.tooltipPasswordSpecial}
|
||||
valid={this.validSpecial}
|
||||
>
|
||||
{this.props.tooltipPasswordSpecial}
|
||||
</StyledTooltipItem>
|
||||
)}
|
||||
</StyledTooltipContainer>
|
||||
) : null;
|
||||
|
||||
renderInputGroup = () => {
|
||||
const {
|
||||
@ -366,17 +376,17 @@ class PasswordInput extends React.Component {
|
||||
autoComplete={autoComplete}
|
||||
theme={theme}
|
||||
></InputBlock>
|
||||
{/* <TooltipStyle>
|
||||
<Tooltip
|
||||
id="tooltipContent"
|
||||
effect="solid"
|
||||
place="top"
|
||||
offsetLeft={tooltipOffsetLeft}
|
||||
reference={this.refTooltip}
|
||||
>
|
||||
{this.renderTooltipContent()}
|
||||
</Tooltip>
|
||||
</TooltipStyle> */}
|
||||
<TooltipStyle>
|
||||
<Tooltip
|
||||
id="tooltipContent"
|
||||
effect="solid"
|
||||
place="top"
|
||||
offsetLeft={this.tooltipOffsetLeft}
|
||||
reference={this.refTooltip}
|
||||
>
|
||||
{this.renderTooltipContent()}
|
||||
</Tooltip>
|
||||
</TooltipStyle>
|
||||
<Progress
|
||||
progressColor={progressColor}
|
||||
progressWidth={progressWidth}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Text from "../text";
|
||||
import { tablet, mobile } from "../utils/device";
|
||||
import Base from "../themes/base";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -133,19 +133,28 @@ const Progress = styled.div`
|
||||
`;
|
||||
Progress.defaultProps = { theme: Base };
|
||||
|
||||
// const TooltipStyle = styled.div`
|
||||
// .__react_component_tooltip {
|
||||
// }
|
||||
// `;
|
||||
const TooltipStyle = styled.div`
|
||||
.__react_component_tooltip {
|
||||
}
|
||||
`;
|
||||
|
||||
// const StyledTooltipContainer = styled(Text)`
|
||||
// //margin: 8px 16px 16px 16px;
|
||||
// `;
|
||||
const StyledTooltipContainer = styled(Text)`
|
||||
//margin: 8px 16px 16px 16px;
|
||||
`;
|
||||
|
||||
// const StyledTooltipItem = styled(Text)`
|
||||
// margin-left: 8px;
|
||||
// height: 24px;
|
||||
// color: ${(props) => (props.valid ? "#44bb00" : "#B40404")};
|
||||
// `;
|
||||
const StyledTooltipItem = styled(Text)`
|
||||
margin-left: 8px;
|
||||
height: 24px;
|
||||
color: ${(props) => (props.valid ? "#44bb00" : "#B40404")};
|
||||
`;
|
||||
|
||||
export { Progress, CopyLink, NewPasswordButton, PasswordProgress, StyledInput };
|
||||
export {
|
||||
Progress,
|
||||
CopyLink,
|
||||
NewPasswordButton,
|
||||
PasswordProgress,
|
||||
StyledInput,
|
||||
TooltipStyle,
|
||||
StyledTooltipContainer,
|
||||
StyledTooltipItem,
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import styled from "styled-components";
|
||||
import commonInputStyles from "./common-input-styles";
|
||||
import Input from "./Input";
|
||||
import Input from "./input";
|
||||
import Base from "../themes/base";
|
||||
|
||||
/* eslint-enable react/prop-types, no-unused-vars */
|
||||
|
@ -94,6 +94,13 @@
|
||||
<body>
|
||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||
|
||||
<div class="ipl-progress-indicator" id="ipl-progress-indicator">
|
||||
<div class="ipl-progress-indicator-head">
|
||||
<div class="first-indicator"></div>
|
||||
<div class="second-indicator"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="temp-content" style="display: none">
|
||||
<header class="temp-header-container">
|
||||
<div id="burger-loader-svg" class="burger-loader-svg">
|
||||
|
@ -8,7 +8,7 @@ import Settings from "./components/pages/Settings";
|
||||
import VersionHistory from "./components/pages/VersionHistory";
|
||||
import config from "../package.json";
|
||||
import PrivateRoute from "@appserver/common/components/PrivateRoute";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import { updateTempContent } from "@appserver/common/utils";
|
||||
import initFilesStore from "./store/InitFilesStore";
|
||||
import filesStore from "./store/FilesStore";
|
||||
|
@ -5,7 +5,7 @@ import styled from "styled-components";
|
||||
//import equal from "fast-deep-equal/react";
|
||||
import { getFolder } from "@appserver/common/api/files";
|
||||
import { FolderType, ShareAccessRights } from "@appserver/common/constants";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
import { onConvertFiles } from "../../../helpers/files-converter";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import TreeFolders from "./TreeFolders";
|
||||
import TreeSettings from "./TreeSettings";
|
||||
@ -119,7 +119,7 @@ export default inject(
|
||||
const { treeFolders, setSelectedNode, setTreeFolders } = treeFoldersStore;
|
||||
const selectedTreeNode = [selectedFolderStore.id + ""];
|
||||
|
||||
return {
|
||||
return {
|
||||
selectedFolderTitle: selectedFolderStore.title,
|
||||
treeFolders,
|
||||
selectedTreeNode,
|
||||
@ -129,6 +129,6 @@ export default inject(
|
||||
fetchFiles,
|
||||
setSelectedNode,
|
||||
setTreeFolders,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
)(observer(ArticleBodyContent));
|
||||
|
@ -8,7 +8,7 @@ import Checkbox from "@appserver/components/checkbox";
|
||||
import Scrollbar from "@appserver/components/scrollbar";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { getProgress, removeFiles } from "@appserver/common/api/files";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { TIMEOUT } from "../../../helpers/constants";
|
||||
import { loopTreeFolders } from "../../../helpers/files-helpers";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
@ -4,7 +4,7 @@ import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import Button from "@appserver/components/button";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { getFolder } from "@appserver/common/api/files";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { loopTreeFolders } from "../../../helpers/files-helpers";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
|
@ -6,7 +6,7 @@ import Button from "@appserver/components/button";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { getProgress, emptyTrash } from "@appserver/common/api/files";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { TIMEOUT } from "../../../helpers/constants";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
} from "@appserver/common/api/files";
|
||||
import { checkIsAuthenticated } from "@appserver/common/api/user";
|
||||
import { getUser } from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
import { setDocumentTitle } from "../../../helpers/utils";
|
||||
import { changeTitle, setFavicon, isIPad } from "./utils";
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
} from "@appserver/common/api/files";
|
||||
import history from "@appserver/common/history";
|
||||
import { FileAction, ShareAccessRights } from "@appserver/common/constants";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg";
|
||||
import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg";
|
||||
import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg";
|
||||
|
@ -7,7 +7,7 @@ import Link from "@appserver/components/link";
|
||||
import Text from "@appserver/components/text";
|
||||
import { markAsRead } from "@appserver/common/api/files";
|
||||
import { FileAction } from "@appserver/common/constants";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { getTitleWithoutExst } from "../../../../../helpers/files-helpers";
|
||||
import { NewFilesPanel } from "../../../../panels";
|
||||
import EditingWrapperComponent from "./EditingWrapperComponent";
|
||||
|
@ -31,7 +31,7 @@ import {
|
||||
} from "@appserver/common/api/files";
|
||||
import { FileAction } from "@appserver/common/constants";
|
||||
import MediaViewer from "@appserver/common/components/MediaViewer";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import { TIMEOUT } from "../../../../../helpers/constants";
|
||||
import { loopTreeFolders } from "../../../../../helpers/files-helpers";
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import copy from "copy-to-clipboard";
|
||||
import styled, { css } from "styled-components";
|
||||
import { withRouter } from "react-router";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import Headline from "@appserver/common/components/Headline";
|
||||
import { FilterType, FileAction } from "@appserver/common/constants";
|
||||
|
@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
||||
import { withRouter } from "react-router";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import axios from "axios";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import PageLayout from "@appserver/common/components/PageLayout";
|
||||
import { showLoader, hideLoader } from "@appserver/common/utils";
|
||||
import FilesFilter from "@appserver/common/api/files/filter";
|
||||
|
@ -5,7 +5,7 @@ import Heading from "@appserver/components/heading";
|
||||
import Aside from "@appserver/components/aside";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
import PeopleSelector from "@appserver/common/components/PeopleSelector";
|
||||
import PeopleSelector from "studio/PeopleSelector";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import {
|
||||
StyledAddUsersPanelPanel,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import PeopleSelector from "@appserver/common/components/PeopleSelector";
|
||||
import PeopleSelector from "studio/PeopleSelector";
|
||||
import Aside from "@appserver/components/aside";
|
||||
import Backdrop from "@appserver/components/backdrop";
|
||||
import Heading from "@appserver/components/heading";
|
||||
|
@ -7,7 +7,7 @@ import Button from "@appserver/components/button";
|
||||
import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import OwnerSelector from "./OwnerSelector";
|
||||
import {
|
||||
StyledAsidePanel,
|
||||
|
@ -8,7 +8,7 @@ import Text from "@appserver/components/text";
|
||||
import Link from "@appserver/components/link";
|
||||
import TextInput from "@appserver/components/text-input";
|
||||
import Textarea from "@appserver/components/textarea";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import {
|
||||
StyledEmbeddingPanel,
|
||||
|
@ -11,7 +11,7 @@ import RowContainer from "@appserver/components/row-container";
|
||||
import Button from "@appserver/components/button";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { getNewFiles, markAsRead } from "@appserver/common/api/files";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import {
|
||||
StyledAsidePanel,
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { withRouter } from "react-router";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { StyledAsidePanel } from "../StyledPanels";
|
||||
import TreeFolders from "../../Article/Body/TreeFolders";
|
||||
import { ThirdPartyMoveDialog } from "../../dialogs";
|
||||
|
@ -4,7 +4,7 @@ import ComboBox from "@appserver/components/combobox";
|
||||
import Row from "@appserver/components/row";
|
||||
import Text from "@appserver/components/text";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import copy from "copy-to-clipboard";
|
||||
import LinkRow from "./linkRow";
|
||||
import AccessComboBox from "./AccessComboBox";
|
||||
|
@ -10,7 +10,7 @@ import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import Textarea from "@appserver/components/textarea";
|
||||
import { withRouter } from "react-router";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
import {
|
||||
StyledAsidePanel,
|
||||
|
@ -31,3 +31,144 @@ body.drag-cursor * {
|
||||
6 6,
|
||||
auto !important;
|
||||
}
|
||||
|
||||
.ipl-progress-indicator.available {
|
||||
opacity: 0;
|
||||
}
|
||||
.ipl-progress-indicator {
|
||||
background-color: #f5f5f5;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
opacity: 1;
|
||||
pointer-events: none;
|
||||
-webkit-transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 436ms;
|
||||
-moz-transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 436ms;
|
||||
transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 436ms;
|
||||
z-index: 9999;
|
||||
top: 56px;
|
||||
}
|
||||
.insp-logo-frame {
|
||||
display: -webkit-flex;
|
||||
display: -moz-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
-moz-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-justify-content: center;
|
||||
-moz-justify-content: center;
|
||||
justify-content: center;
|
||||
-webkit-animation: fadein 436ms;
|
||||
-moz-animation: fadein 436ms;
|
||||
animation: fadein 436ms;
|
||||
height: 98%;
|
||||
}
|
||||
.insp-logo-frame-img {
|
||||
width: 112px;
|
||||
height: 112px;
|
||||
-webkit-align-self: center;
|
||||
-moz-align-self: center;
|
||||
align-self: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.ipl-progress-indicator-head {
|
||||
background-color: #c6dafc;
|
||||
height: 2px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.ipl-progress-indicator .first-indicator,
|
||||
.ipl-progress-indicator .second-indicator {
|
||||
background-color: red;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
-webkit-transform-origin: left center;
|
||||
-moz-transform-origin: left center;
|
||||
transform-origin: left center;
|
||||
-webkit-transform: scaleX(0);
|
||||
-moz-transform: scaleX(0);
|
||||
transform: scaleX(0);
|
||||
}
|
||||
.ipl-progress-indicator .first-indicator {
|
||||
-webkit-animation: first-indicator 2s linear infinite;
|
||||
-moz-animation: first-indicator 2s linear infinite;
|
||||
animation: first-indicator 2s linear infinite;
|
||||
}
|
||||
.ipl-progress-indicator .second-indicator {
|
||||
-webkit-animation: second-indicator 2s linear infinite;
|
||||
-moz-animation: second-indicator 2s linear infinite;
|
||||
animation: second-indicator 2s linear infinite;
|
||||
}
|
||||
.ipl-progress-indicator .insp-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
border-radius: 50%;
|
||||
-webkit-align-self: center;
|
||||
-moz-align-self: center;
|
||||
align-self: center;
|
||||
}
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes first-indicator {
|
||||
0% {
|
||||
transform: translate(0) scaleX(0);
|
||||
}
|
||||
25% {
|
||||
transform: translate(0) scaleX(0.5);
|
||||
}
|
||||
50% {
|
||||
transform: translate(25%) scaleX(0.75);
|
||||
}
|
||||
75% {
|
||||
transform: translate(100%) scaleX(0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(100%) scaleX(0);
|
||||
}
|
||||
}
|
||||
@keyframes second-indicator {
|
||||
0% {
|
||||
transform: translate(0) scaleX(0);
|
||||
}
|
||||
60% {
|
||||
transform: translate(0) scaleX(0);
|
||||
}
|
||||
80% {
|
||||
transform: translate(0) scaleX(0.6);
|
||||
}
|
||||
100% {
|
||||
transform: translate(100%) scaleX(0.1);
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ module.exports = (env, argv) => {
|
||||
if (argv.mode === "production") {
|
||||
config.mode = "production";
|
||||
} else {
|
||||
config.devtool = "source-map";
|
||||
config.devtool = "cheap-module-source-map";
|
||||
}
|
||||
|
||||
return config;
|
||||
|
@ -4,7 +4,7 @@ import { Switch } from "react-router";
|
||||
import PeopleStore from "./store/PeopleStore";
|
||||
import Home from "./components/pages/Home";
|
||||
import Loader from "@appserver/components/loader";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import PrivateRoute from "@appserver/common/components/PrivateRoute";
|
||||
import { updateTempContent } from "@appserver/common/utils";
|
||||
const Profile = React.lazy(() => import("./components/pages/Profile"));
|
||||
|
@ -6,7 +6,7 @@ import MainButton from "@appserver/components/main-button";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import InviteDialog from "./../../dialogs/InviteDialog/index";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import config from "../../../../package.json";
|
||||
|
@ -8,7 +8,7 @@ import FieldContainer from "@appserver/components/field-container";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { sendInstructionsToChangeEmail } from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
class ChangeEmailDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -6,7 +6,7 @@ import Link from "@appserver/components/link";
|
||||
import Text from "@appserver/components/text";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import { sendInstructionsToChangePassword } from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
class ChangePasswordDialogComponent extends React.Component {
|
||||
constructor() {
|
||||
|
@ -4,7 +4,7 @@ import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import Button from "@appserver/components/button";
|
||||
import Text from "@appserver/components/text";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
class ChangePhoneDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -12,7 +12,7 @@ import CustomScrollbarsVirtualList from "@appserver/components/scrollbar/custom-
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { EmployeeStatus } from "@appserver/common/constants";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
@ -12,7 +12,7 @@ import CustomScrollbarsVirtualList from "@appserver/components/scrollbar/custom-
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { EmployeeType } from "@appserver/common/constants";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
|
@ -9,7 +9,7 @@ import history from "@appserver/common/history";
|
||||
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import api from "@appserver/common/api";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
|
@ -9,7 +9,7 @@ import Text from "@appserver/components/text";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { sendInstructionsToDelete } from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
|
||||
class DeleteSelfProfileDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -13,7 +13,7 @@ import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import Filter from "@appserver/common/api/people/filter";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
|
@ -13,7 +13,7 @@ import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { resendUserInvites } from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
|
@ -6,9 +6,9 @@ import SelectedItem from "@appserver/components/selected-item";
|
||||
import TextInput from "@appserver/components/text-input";
|
||||
import { tablet } from "@appserver/components/utils/device";
|
||||
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import PeopleSelector from "@appserver/common/components/PeopleSelector";
|
||||
import PeopleSelector from "studio/PeopleSelector";
|
||||
import { GUID_EMPTY } from "../../../../../helpers/constants";
|
||||
import PropTypes from "prop-types";
|
||||
import React from "react";
|
||||
|
@ -5,7 +5,7 @@ import UserContent from "./userContent";
|
||||
import history from "@appserver/common/history";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import { EmployeeStatus } from "@appserver/common/constants";
|
||||
import { resendUserInvites } from "@appserver/common/api/people"; //TODO: Move to store action
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import RowContainer from "@appserver/components/row-container";
|
||||
import { Consumer } from "@appserver/components/utils/context";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
|
||||
import EmptyScreen from "./EmptyScreen";
|
||||
|
@ -9,7 +9,7 @@ import { tablet, desktop } from "@appserver/components/utils/device";
|
||||
import { Consumer } from "@appserver/components/utils/context";
|
||||
|
||||
import Headline from "@appserver/common/components/Headline";
|
||||
import toastr from "@appserver/common/components/Toast/toastr";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import { EmployeeType, EmployeeStatus } from "@appserver/common/constants";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
@ -7,7 +7,7 @@ import ComboBox from "@appserver/components/combobox";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
import styled from "styled-components";
|
||||
import { resendUserInvites } from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
|
@ -3,7 +3,7 @@ import IconButton from "@appserver/components/icon-button";
|
||||
import ContextMenuButton from "@appserver/components/context-menu-button";
|
||||
import AvatarEditor from "@appserver/components/avatar-editor";
|
||||
import Headline from "@appserver/common/components/Headline";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { withRouter } from "react-router";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import PageLayout from "@appserver/common/components/PageLayout";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import {
|
||||
ArticleHeaderContent,
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
loadAvatar,
|
||||
deleteAvatar,
|
||||
} from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { toEmployeeWrapper } from "../../../../../helpers/people-helpers";
|
||||
|
@ -8,7 +8,7 @@ import { isTablet } from "@appserver/components/utils/device";
|
||||
import {
|
||||
/*createThumbnailsAvatar,*/ loadAvatar,
|
||||
} from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { toEmployeeWrapper } from "../../../../../helpers/people-helpers";
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
createThumbnailsAvatar,
|
||||
loadAvatar,
|
||||
} from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import {
|
||||
|
@ -0,0 +1,26 @@
|
||||
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";
|
||||
|
||||
const SectionUserBody = ({ avatarEditorIsOpen, match }) => {
|
||||
const { type } = match.params;
|
||||
return type ? (
|
||||
avatarEditorIsOpen ? (
|
||||
<CreateAvatarEditorPage />
|
||||
) : (
|
||||
<CreateUserForm />
|
||||
)
|
||||
) : avatarEditorIsOpen ? (
|
||||
<AvatarEditorPage />
|
||||
) : (
|
||||
<UpdateUserForm />
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ peopleStore }) => ({
|
||||
avatarEditorIsOpen: peopleStore.avatarEditorStore.visible,
|
||||
}))(withRouter(observer(SectionUserBody)));
|
@ -30,7 +30,7 @@ import {
|
||||
loadAvatar,
|
||||
deleteAvatar,
|
||||
} from "@appserver/common/api/people";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import {
|
||||
ChangeEmailDialog,
|
||||
ChangePasswordDialog,
|
||||
|
@ -7,12 +7,13 @@ import {
|
||||
ArticleMainButtonContent,
|
||||
ArticleBodyContent,
|
||||
} from "../../Article";
|
||||
import SectionUserBody from "./Section/Body/index";
|
||||
import {
|
||||
SectionHeaderContent,
|
||||
CreateUserForm,
|
||||
UpdateUserForm,
|
||||
AvatarEditorPage,
|
||||
CreateAvatarEditorPage,
|
||||
// CreateUserForm,
|
||||
// UpdateUserForm,
|
||||
// AvatarEditorPage,
|
||||
// CreateAvatarEditorPage,
|
||||
} from "./Section";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
@ -67,13 +68,7 @@ class ProfileAction extends React.Component {
|
||||
console.log("ProfileAction render");
|
||||
|
||||
this.loaded = false;
|
||||
const {
|
||||
profile,
|
||||
isVisitor,
|
||||
match,
|
||||
isAdmin,
|
||||
avatarEditorIsOpen,
|
||||
} = this.props;
|
||||
const { profile, match } = this.props;
|
||||
const { userId, type } = match.params;
|
||||
|
||||
if (type) {
|
||||
@ -84,21 +79,17 @@ class ProfileAction extends React.Component {
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
{!isVisitor && (
|
||||
<PageLayout.ArticleHeader>
|
||||
<ArticleHeaderContent />
|
||||
</PageLayout.ArticleHeader>
|
||||
)}
|
||||
{!isVisitor && isAdmin && (
|
||||
<PageLayout.ArticleMainButton>
|
||||
<ArticleMainButtonContent />
|
||||
</PageLayout.ArticleMainButton>
|
||||
)}
|
||||
{!isVisitor && (
|
||||
<PageLayout.ArticleBody>
|
||||
<ArticleBodyContent />
|
||||
</PageLayout.ArticleBody>
|
||||
)}
|
||||
<PageLayout.ArticleHeader>
|
||||
<ArticleHeaderContent />
|
||||
</PageLayout.ArticleHeader>
|
||||
|
||||
<PageLayout.ArticleMainButton>
|
||||
<ArticleMainButtonContent />
|
||||
</PageLayout.ArticleMainButton>
|
||||
|
||||
<PageLayout.ArticleBody>
|
||||
<ArticleBodyContent />
|
||||
</PageLayout.ArticleBody>
|
||||
|
||||
<PageLayout.SectionHeader>
|
||||
{this.loaded ? <SectionHeaderContent /> : <Loaders.SectionHeader />}
|
||||
@ -106,17 +97,7 @@ class ProfileAction extends React.Component {
|
||||
|
||||
<PageLayout.SectionBody>
|
||||
{this.loaded ? (
|
||||
type ? (
|
||||
avatarEditorIsOpen ? (
|
||||
<CreateAvatarEditorPage />
|
||||
) : (
|
||||
<CreateUserForm />
|
||||
)
|
||||
) : avatarEditorIsOpen ? (
|
||||
<AvatarEditorPage />
|
||||
) : (
|
||||
<UpdateUserForm />
|
||||
)
|
||||
<SectionUserBody />
|
||||
) : (
|
||||
<Loaders.ProfileView isEdit={false} />
|
||||
)}
|
||||
@ -127,19 +108,18 @@ class ProfileAction extends React.Component {
|
||||
}
|
||||
|
||||
ProfileAction.propTypes = {
|
||||
setDocumentTitle: PropTypes.func.isRequired,
|
||||
isEdit: PropTypes.bool,
|
||||
setIsEditingForm: PropTypes.func.isRequired,
|
||||
fetchProfile: PropTypes.func.isRequired,
|
||||
match: PropTypes.object.isRequired,
|
||||
profile: PropTypes.object,
|
||||
isAdmin: PropTypes.bool,
|
||||
match: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default inject(({ auth, peopleStore }) => ({
|
||||
setDocumentTitle: auth.setDocumentTitle,
|
||||
isAdmin: auth.isAdmin,
|
||||
isVisitor: auth.userStore.user.isVisitor,
|
||||
isEdit: peopleStore.editingFormStore.isEdit,
|
||||
setIsEditingForm: peopleStore.editingFormStore.setIsEditingForm,
|
||||
fetchProfile: peopleStore.targetUserStore.getTargetUser,
|
||||
profile: peopleStore.targetUserStore.targetUser,
|
||||
avatarEditorIsOpen: peopleStore.avatarEditorStore.visible,
|
||||
}))(withTranslation("ProfileAction")(withRouter(observer(ProfileAction))));
|
||||
|
@ -161,7 +161,7 @@ module.exports = (env, argv) => {
|
||||
if (argv.mode === "production") {
|
||||
config.mode = "production";
|
||||
} else {
|
||||
config.devtool = "source-map";
|
||||
config.devtool = "cheap-module-source-map";
|
||||
}
|
||||
|
||||
return config;
|
||||
|
@ -11,7 +11,7 @@ import ErrorBoundary from "@appserver/common/components/ErrorBoundary";
|
||||
import Layout from "./components/Layout";
|
||||
import ScrollToTop from "./components/Layout/ScrollToTop";
|
||||
import history from "@appserver/common/history";
|
||||
import toastr from "@appserver/common/components/Toast";
|
||||
import toastr from "studio/toastr";
|
||||
import RectangleLoader from "@appserver/common/components/Loaders/RectangleLoader";
|
||||
import { updateTempContent } from "@appserver/common/utils";
|
||||
import { Provider as MobxProvider } from "mobx-react";
|
||||
@ -166,7 +166,6 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
|
||||
}, [loadBaseInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("App render", isLoaded);
|
||||
if (isLoaded) updateTempContent();
|
||||
}, [isLoaded]);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user