Merge branch 'feature/files' of https://github.com/ONLYOFFICE/CommunityServer-AspNetCore into feature/files

This commit is contained in:
Nikita Gopienko 2020-09-15 14:47:03 +03:00
commit 584bee8198
47 changed files with 1455 additions and 1124 deletions

View File

@ -29,7 +29,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>ASC.Files</title>
<title>ONLYOFFICE</title>
</head>
<body>
<noscript>

View File

@ -1,5 +1,12 @@
import React from "react";
import { TreeMenu, TreeNode, Icons, toastr, utils, Badge } from "asc-web-components";
import {
TreeMenu,
TreeNode,
Icons,
toastr,
utils,
Badge
} from "asc-web-components";
import styled from "styled-components";
import { api, constants } from "asc-web-common";
const { files } = api;
@ -9,12 +16,18 @@ const backgroundDragColor = "#EFEFB2";
const backgroundDragEnterColor = "#F8F7BF";
const StyledTreeMenu = styled(TreeMenu)`
.rc-tree-node-content-wrapper{
.rc-tree-node-content-wrapper {
background: ${props => !props.dragging && "none !important"};
}
.rc-tree-node-selected {
background: #DFE2E3 !important;
background: #dfe2e3 !important;
}
.rc-tree-treenode-disabled > span:not(.rc-tree-switcher),
.rc-tree-treenode-disabled > a,
.rc-tree-treenode-disabled > a span {
cursor: wait;
}
`;
@ -29,11 +42,13 @@ class TreeFolders extends React.Component {
onBadgeClick = e => {
const id = e.currentTarget.dataset.id;
this.props.onBadgeClick && this.props.onBadgeClick(id);
}
};
getFolderIcon = item => {
const showItem = item.newItems ? item.newItems > 0 && this.props.needUpdate : false;
const style = { position: "absolute", right: 1, top: 2 }
const showItem = item.newItems
? item.newItems > 0 && this.props.needUpdate
: false;
const style = { position: "absolute", right: 1, top: 2 };
const badgeProps = {
label: item.newItems,
backgroundColor: "#ED7309",
@ -42,7 +57,7 @@ class TreeFolders extends React.Component {
fontWeight: 800,
borderRadius: "11px",
padding: "0 5px",
style,
style
};
switch (item.key) {
@ -53,7 +68,13 @@ class TreeFolders extends React.Component {
return (
<>
<Icons.CatalogSharedIcon size="scale" isfill color="#657077" />
{showItem && <Badge data-id={item.id} {...badgeProps} onClick={this.onBadgeClick} />}
{showItem && (
<Badge
data-id={item.id}
{...badgeProps}
onClick={this.onBadgeClick}
/>
)}
</>
);
@ -61,7 +82,13 @@ class TreeFolders extends React.Component {
return (
<>
<Icons.CatalogPortfolioIcon size="scale" isfill color="#657077" />
{showItem && <Badge data-id={item.id} {...badgeProps} onClick={this.onBadgeClick} />}
{showItem && (
<Badge
data-id={item.id}
{...badgeProps}
onClick={this.onBadgeClick}
/>
)}
</>
);
@ -73,8 +100,16 @@ class TreeFolders extends React.Component {
}
};
showDragItems = (item) => {
const { isAdmin, myId, commonId, isCommon, isMy, isShare, currentId } = this.props;
showDragItems = item => {
const {
isAdmin,
myId,
commonId,
isCommon,
isMy,
isShare,
currentId
} = this.props;
if (item.id === currentId) {
return false;
}
@ -230,7 +265,7 @@ class TreeFolders extends React.Component {
};
onLoadData = treeNode => {
this.props.setIsLoading(true);
this.props.setIsLoading && this.props.setIsLoading(true);
//console.log("load data...", treeNode);
return this.generateTreeNodes(treeNode)
@ -245,7 +280,7 @@ class TreeFolders extends React.Component {
this.setState({ treeData });
})
.catch(err => toastr.error(err))
.finally(() => this.props.setIsLoading(false));
.finally(() => this.props.setIsLoading && this.props.setIsLoading(false));
};
onExpand = (data, treeNode) => {
@ -278,7 +313,7 @@ class TreeFolders extends React.Component {
}
}
onMouseEnter = (data) => {
onMouseEnter = data => {
if (this.props.dragging) {
if (data.node.props.dragging) {
this.props.setDragItem(data.node.props.id);
@ -294,25 +329,29 @@ class TreeFolders extends React.Component {
onDragOver = data => {
const parentElement = data.event.target.parentElement;
const existElement = parentElement.classList.contains("rc-tree-node-content-wrapper");
const existElement = parentElement.classList.contains(
"rc-tree-node-content-wrapper"
);
if (existElement) {
if (data.node.props.dragging) {
parentElement.style.background = backgroundDragColor;
}
}
}
};
onDragLeave = data => {
const parentElement = data.event.target.parentElement;
const existElement = parentElement.classList.contains("rc-tree-node-content-wrapper");
const existElement = parentElement.classList.contains(
"rc-tree-node-content-wrapper"
);
if (existElement) {
if (data.node.props.dragging) {
parentElement.style.background = backgroundDragEnterColor;
}
}
}
};
onDrop = data => {
const { setDragging, onTreeDrop } = this.props;
@ -321,10 +360,16 @@ class TreeFolders extends React.Component {
if (dragging) {
onTreeDrop(data.event, id);
}
}
};
render() {
const { selectedKeys, isLoading, onSelect, needUpdate, dragging } = this.props;
const {
selectedKeys,
isLoading,
onSelect,
needUpdate,
dragging
} = this.props;
const { treeData, expandedKeys } = this.state;
const loadProp = needUpdate ? { loadData: this.onLoadData } : {};
@ -344,7 +389,6 @@ class TreeFolders extends React.Component {
onExpand={this.onExpand}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onDragOver={this.onDragOver}
onDragLeave={this.onDragLeave}
onDrop={this.onDrop}

View File

@ -29,15 +29,30 @@ const StyledTreeMenu = styled(TreeMenu)`
.settings-node {
margin-left: 8px !important;
}
.rc-tree-treenode-disabled > span:not(.rc-tree-switcher),
.rc-tree-treenode-disabled > a,
.rc-tree-treenode-disabled > a span {
cursor: wait;
}
`;
const PureTreeSettings = props => {
const PureTreeSettings = ({
match,
enableThirdParty,
isAdmin,
selectedTreeNode,
expandedSetting,
isLoading,
setSelectedNode,
setExpandSettingsTree,
t
}) => {
useEffect(() => {
const { match, setSelectedNode, setExpandSettingsTree } = props;
const { setting } = match.params;
setSelectedNode([setting]);
if (setting) setExpandSettingsTree(["settings"]);
}, [props.match.setting]);
}, [match]);
const switcherIcon = obj => {
if (obj.isLeaf) {
@ -51,7 +66,6 @@ const PureTreeSettings = props => {
};
const onSelect = section => {
const { setSelectedNode, setExpandSettingsTree } = props;
const path = section[0];
if (path === "settings") {
@ -65,12 +79,10 @@ const PureTreeSettings = props => {
};
const onExpand = data => {
const { setExpandSettingsTree } = props;
setExpandSettingsTree(data);
};
const renderTreeNode = () => {
const { t, enableThirdParty, isAdmin } = props;
return (
<TreeNode
id="settings"
@ -109,7 +121,6 @@ const PureTreeSettings = props => {
);
};
const { selectedTreeNode, expandedSetting, isLoading } = props;
const nodes = renderTreeNode();
return (

View File

@ -1,8 +1,9 @@
import React from "react";
import { connect } from "react-redux";
import { toastr, utils } from "asc-web-components";
import { store as initStore } from "asc-web-common";
import TreeFolders from "./TreeFolders";
import TreeSettings from './TreeSettings';
import TreeSettings from "./TreeSettings";
import {
setFilter,
fetchFiles,
@ -16,19 +17,30 @@ import {
import store from "../../../store/store";
import isEqual from "lodash/isEqual";
import { NewFilesPanel } from "../../panels";
const { getCurrentModule } = initStore.auth.selectors;
class ArticleBodyContent extends React.Component {
state = {
expandedKeys: this.props.filter.treeFolders,
data: this.props.data,
showNewFilesPanel: false
};
constructor(props) {
super(props);
const { organizationName, selectedFolderTitle, currentModuleName } = props;
document.title = selectedFolderTitle
? `${selectedFolderTitle} - ${currentModuleName}`
: `${currentModuleName} - ${organizationName}`;
this.state = {
expandedKeys: this.props.filter.treeFolders,
data: this.props.data,
showNewFilesPanel: false
};
}
componentDidUpdate(prevProps) {
const { filter, data } = this.props;
if (
filter.treeFolders.length !==
prevProps.filter.treeFolders.length ||
filter.treeFolders.length !== prevProps.filter.treeFolders.length ||
this.state.expandedKeys.length !== filter.treeFolders.length
) {
this.setState({ expandedKeys: filter.treeFolders });
@ -55,24 +67,42 @@ class ArticleBodyContent extends React.Component {
return false;
}
onSelect = data => {
const { filter, setIsLoading, selectedTreeNode, setSelectedNode } = this.props;
onSelect = (data, e) => {
const {
filter,
setIsLoading,
selectedTreeNode,
setSelectedNode,
currentModuleName,
organizationName
} = this.props;
if (selectedTreeNode[0] !== data[0]) {
setSelectedNode(data)
setSelectedNode(data);
setIsLoading(true);
const newFilter = filter.clone();
newFilter.page = 0;
newFilter.startIndex = 0;
const selectedFolderTitle =
(e.node && e.node.props && e.node.props.title) || null;
document.title = selectedFolderTitle
? `${selectedFolderTitle} - ${currentModuleName}`
: `${currentModuleName} - ${organizationName}`;
fetchFiles(data[0], newFilter, store.dispatch)
.catch(err => toastr.error(err))
.finally(() => setIsLoading(false));
}
};
onShowNewFilesPanel = (folderId) => {
onShowNewFilesPanel = folderId => {
const { showNewFilesPanel } = this.state;
this.setState({ showNewFilesPanel: !showNewFilesPanel, newFolderId: [folderId] });
this.setState({
showNewFilesPanel: !showNewFilesPanel,
newFolderId: [folderId]
});
};
setNewFilesCount = (folderPath, filesCount) => {
@ -80,7 +110,7 @@ class ArticleBodyContent extends React.Component {
const dataItem = data.find(x => x.id === folderPath[0]);
dataItem.newItems = filesCount ? filesCount : dataItem.newItems - 1;
this.setState({ data });
}
};
render() {
const {
@ -117,7 +147,7 @@ class ArticleBodyContent extends React.Component {
treeFolders={data}
setTreeFolders={setTreeFolders}
setIsLoading={setIsLoading}
//setNewItems={this.setNewItems}
//setNewItems={this.setNewItems}
/>
)}
<TreeFolders
@ -148,7 +178,21 @@ class ArticleBodyContent extends React.Component {
}
function mapStateToProps(state) {
const { treeFolders, selectedFolder, filter, selection, dragging, updateTreeNew, selectedTreeNode } = state.files;
const currentModule = getCurrentModule(
state.auth.modules,
state.auth.settings.currentProductId
);
const {
treeFolders,
selectedFolder,
filter,
selection,
dragging,
updateTreeNew,
selectedTreeNode
} = state.files;
const currentFolderId = selectedFolder.id.toString();
const myFolderIndex = 0;
const shareFolderIndex = 1;
@ -158,19 +202,25 @@ function mapStateToProps(state) {
const shareId = treeFolders.length && treeFolders[shareFolderIndex].id;
const commonId = treeFolders.length && treeFolders[commonFolderIndex].id;
const isMy = selectedFolder &&
const isMy =
selectedFolder &&
selectedFolder.pathParts &&
selectedFolder.pathParts[0] === myId;
const isShare = selectedFolder &&
const isShare =
selectedFolder &&
selectedFolder.pathParts &&
selectedFolder.pathParts[0] === shareId;
const isCommon = selectedFolder &&
const isCommon =
selectedFolder &&
selectedFolder.pathParts &&
selectedFolder.pathParts[0] === commonId;
const selected = selectedTreeNode.length > 0 ? selectedTreeNode : [selectedFolder.id.toString()];
const selected =
selectedTreeNode.length > 0
? selectedTreeNode
: [selectedFolder.id.toString()];
return {
data: treeFolders,
@ -186,10 +236,21 @@ function mapStateToProps(state) {
selection,
dragging,
updateTreeNew,
selectedTreeNode: selected
selectedTreeNode: selected,
currentModuleName: (currentModule && currentModule.title) || "",
selectedFolderTitle: (selectedFolder && selectedFolder.title) || ""
};
}
export default connect(mapStateToProps, { setFilter, setTreeFolders, setDragItem, setDragging, setNewTreeFilesBadge, setIsLoading, setSelectedNode })(
ArticleBodyContent
);
export default connect(
mapStateToProps,
{
setFilter,
setTreeFolders,
setDragItem,
setDragging,
setNewTreeFilesBadge,
setIsLoading,
setSelectedNode
}
)(ArticleBodyContent);

View File

@ -294,7 +294,7 @@ class FilesRowContent extends React.PureComponent {
}
render() {
const { t, item, fileAction, isTrashFolder, folders, widthProp, isLoading } = this.props;
const { t, item, fileAction, isTrashFolder, folders, widthProp, isLoading, isMobile } = this.props;
const { itemTitle, editingId, showNewFilesPanel, newItems, newFolderId, showConvertDialog } = this.state;
const {
contentLength,
@ -349,6 +349,7 @@ class FilesRowContent extends React.PureComponent {
)}
<SimpleFilesRowContent
widthProp={widthProp}
isMobile={isMobile}
sideColor="#333"
isFile={fileExst}
onClick={this.onMobileRowClick}

View File

@ -890,13 +890,13 @@ class SectionBodyContent extends React.Component {
item = selection.find(x => x.id === Number(splitValue[1]) && x.fileExst);
}
if (item) {
this.setState({isDrag: true});
this.setState({ isDrag: true });
}
}
onMouseUp = e => {
const { selection, dragging, setDragging, dragItem, setDragItem } = this.props;
this.state.isDrag && this.setState({isDrag: false});
this.state.isDrag && this.setState({ isDrag: false });
const mouseButton = e.which ? e.which !== 1 : e.button ? e.button !== 0 : false;
if (mouseButton || !this.tooltipRef.current || !dragging) { return; }
document.removeEventListener("mousemove", this.onMouseMove);
@ -1099,7 +1099,8 @@ class SectionBodyContent extends React.Component {
viewAs,
t,
loopFilesOperations,
widthProp
widthProp,
isMobile
} = this.props;
const { editingId, showSharingPanel, showMoveToPanel, showCopyPanel } = this.state;
@ -1278,6 +1279,7 @@ class SectionBodyContent extends React.Component {
>
<FilesRowContent
widthProp={widthProp}
isMobile={isMobile}
item={item}
viewer={viewer}
culture={settings.culture}

View File

@ -3,7 +3,7 @@ import { connect } from "react-redux";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
import { isMobile } from "react-device-detect";
import { RequestLoader, Checkbox, toastr } from "asc-web-components";
import { RequestLoader, toastr } from "asc-web-components";
import { PageLayout, utils } from "asc-web-common";
import { withTranslation, I18nextProvider } from "react-i18next";
import {
@ -307,10 +307,10 @@ class PureHome extends React.Component {
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
selected,
overwriteSetting,
uploadOriginalFormatSetting,
hideWindowSetting
selected
// overwriteSetting,
// uploadOriginalFormatSetting,
// hideWindowSetting
} = this.state;
const {
t,
@ -320,25 +320,25 @@ class PureHome extends React.Component {
convertDialogVisible
} = this.props;
const progressBarContent = (
<div>
<Checkbox
onChange={this.onChangeOverwrite}
isChecked={overwriteSetting}
label={t("OverwriteSetting")}
/>
<Checkbox
onChange={this.onChangeOriginalFormat}
isChecked={uploadOriginalFormatSetting}
label={t("UploadOriginalFormatSetting")}
/>
<Checkbox
onChange={this.onChangeWindowVisible}
isChecked={hideWindowSetting}
label={t("HideWindowSetting")}
/>
</div>
);
// const progressBarContent = (
// <div>
// <Checkbox
// onChange={this.onChangeOverwrite}
// isChecked={overwriteSetting}
// label={t("OverwriteSetting")}
// />
// <Checkbox
// onChange={this.onChangeOriginalFormat}
// isChecked={uploadOriginalFormatSetting}
// label={t("UploadOriginalFormatSetting")}
// />
// <Checkbox
// onChange={this.onChangeWindowVisible}
// isChecked={hideWindowSetting}
// label={t("HideWindowSetting")}
// />
// </div>
// );
return (
<>
@ -402,6 +402,7 @@ class PureHome extends React.Component {
<PageLayout.SectionBody>
<SectionBodyContent
isMobile={isMobile}
selected={selected}
onChange={this.onRowChange}
loopFilesOperations={this.loopFilesOperations}

View File

@ -1,20 +1,17 @@
import React, { useEffect } from 'react';
import styled from 'styled-components';
import { connect } from 'react-redux';
import {
Heading,
ToggleButton
} from 'asc-web-components';
import React, { useEffect } from "react";
import styled from "styled-components";
import { connect } from "react-redux";
import { Heading, ToggleButton } from "asc-web-components";
import {
setUpdateIfExist,
setStoreOriginal,
import {
setUpdateIfExist,
setStoreOriginal,
setEnableThirdParty,
setConfirmDelete,
setConfirmDelete,
setStoreForceSave,
setSelectedNode,
setForceSave
} from '../../../../../store/files/actions';
} from "../../../../../store/files/actions";
const StyledSettings = styled.div`
display: grid;
@ -30,158 +27,142 @@ const StyledSettings = styled.div`
}
`;
function SectionBodyContent(props) {
useEffect(() => {
const { setting, t } = props;
document.title = t(`${setting}`);
return function setTitle() {
document.title = 'ASC.Files';
}
}, [props.setting])
const SectionBodyContent = ({
setting,
selectedTreeNode, setSelectedNode,
storeForceSave, setStoreForceSave ,
enableThirdParty, setEnableThirdParty,
storeOriginalFiles, setStoreOriginal,
confirmDelete, setConfirmDelete,
updateIfExist, setUpdateIfExist,
forceSave, setForceSave,
isAdmin,
t
}) => {
useEffect(() => {
const { setting, selectedTreeNode, setSelectedNode } = props;
if( setting !== selectedTreeNode[0] ) {
setSelectedNode([ setting ])
document.title = t(`${setting}`);
}, [setting]);
useEffect(() => {
if (setting !== selectedTreeNode[0]) {
setSelectedNode([setting]);
}
}, [props.setting]);
}, [setting]);
const onChangeStoreForceSave = () => {
const { storeForceSave, setStoreForceSave } = props;
setStoreForceSave( !storeForceSave, "storeForceSave" );
}
setStoreForceSave(!storeForceSave, "storeForceSave");
};
const onChangeThirdParty = () => {
const { enableThirdParty, setEnableThirdParty } = props;
setEnableThirdParty(!enableThirdParty, "enableThirdParty");
}
};
const renderAdminSettings = () => {
const {
enableThirdParty,
storeForceSave,
t
} = props;
return (
<StyledSettings>
<ToggleButton
<ToggleButton
className="toggle-btn"
label={t('intermediateVersion')}
label={t("intermediateVersion")}
onChange={onChangeStoreForceSave}
isChecked={storeForceSave}
/>
<ToggleButton
className="toggle-btn"
label={t('thirdPartyBtn')}
label={t("thirdPartyBtn")}
onChange={onChangeThirdParty}
isChecked={enableThirdParty}
/>
</StyledSettings>
)
}
);
};
const onChangeOriginalCopy = () => {
const { storeOriginalFiles, setStoreOriginal } = props;
setStoreOriginal( !storeOriginalFiles, "storeOriginalFiles" );
}
setStoreOriginal(!storeOriginalFiles, "storeOriginalFiles");
};
const onChangeDeleteConfirm = () => {
const { confirmDelete, setConfirmDelete } = props;
setConfirmDelete( !confirmDelete, "confirmDelete" );
}
setConfirmDelete(!confirmDelete, "confirmDelete");
};
const onChangeUpdateIfExist = () => {
const { updateIfExist, setUpdateIfExist } = props;
setUpdateIfExist( !updateIfExist, "updateIfExist" );
}
setUpdateIfExist(!updateIfExist, "updateIfExist");
};
const onChangeForceSave = () => {
const { forceSave, setForceSave } = props;
setForceSave( !forceSave, "forceSave" );
}
setForceSave(!forceSave, "forceSave");
};
const renderCommonSettings = () => {
const {
updateIfExist,
confirmDelete,
storeOriginalFiles,
forceSave,
t
} = props;
return (
<StyledSettings>
<ToggleButton
className="toggle-btn"
label={t('originalCopy')}
label={t("originalCopy")}
onChange={onChangeOriginalCopy}
isChecked={storeOriginalFiles}
/>
<ToggleButton
className="toggle-btn"
label={t('displayNotification')}
label={t("displayNotification")}
onChange={onChangeDeleteConfirm}
isChecked={confirmDelete}
/>
<ToggleButton
isDisabled={true}
className="toggle-btn"
label={t('displayRecent')}
onChange={(e)=>console.log(e)}
label={t("displayRecent")}
onChange={e => console.log(e)}
isChecked={false}
/>
<ToggleButton
isDisabled={true}
className="toggle-btn"
label={t('displayFavorites')}
onChange={(e)=>console.log(e)}
label={t("displayFavorites")}
onChange={e => console.log(e)}
isChecked={false}
/>
<ToggleButton
isDisabled={true}
className="toggle-btn"
label={t('displayTemplates')}
onChange={(e)=>console.log(e)}
label={t("displayTemplates")}
onChange={e => console.log(e)}
isChecked={false}
/>
<Heading className="heading" level={2} size="small">{t('storingFileVersion')}</Heading>
<Heading className="heading" level={2} size="small">
{t("storingFileVersion")}
</Heading>
<ToggleButton
className="toggle-btn"
label={t('updateOrCreate')}
label={t("updateOrCreate")}
onChange={onChangeUpdateIfExist}
isChecked={updateIfExist}
/>
<ToggleButton
className="toggle-btn"
label={t('keepIntermediateVersion')}
label={t("keepIntermediateVersion")}
onChange={onChangeForceSave}
isChecked={forceSave}
/>
</StyledSettings>
);
}
};
const renderClouds = () => {
return (<></>)
}
return <></>;
};
const { setting, enableThirdParty, isAdmin } = props;
let content;
if(setting === 'admin' && isAdmin)
content = renderAdminSettings();
if(setting === 'common')
content = renderCommonSettings();
if(setting === 'thirdParty' && enableThirdParty )
content = renderClouds();
return content;
if (setting === "admin" && isAdmin) content = renderAdminSettings();
if (setting === "common") content = renderCommonSettings();
if (setting === "thirdParty" && enableThirdParty) content = renderClouds();
return content;
}
function mapStateToProps(state) {
const { settingsTree, selectedTreeNode } = state.files;
const { isAdmin } = state.auth.user;
const {
const {
storeOriginalFiles,
confirmDelete,
updateIfExist,
@ -190,7 +171,7 @@ function mapStateToProps(state) {
enableThirdParty
} = settingsTree;
return {
return {
isAdmin,
selectedTreeNode,
storeOriginalFiles,
@ -199,16 +180,18 @@ function mapStateToProps(state) {
forceSave,
storeForceSave,
enableThirdParty
}
};
}
export default connect(
mapStateToProps, {
setUpdateIfExist,
setStoreOriginal,
mapStateToProps,
{
setUpdateIfExist,
setStoreOriginal,
setEnableThirdParty,
setConfirmDelete,
setStoreForceSave,
setSelectedNode,
setForceSave
})(SectionBodyContent);
}
)(SectionBodyContent);

View File

@ -21,11 +21,18 @@ const i18n = createI18N({
const { changeLanguage } = utils;
const PureSettings = props => {
const PureSettings = ({
match,
t,
isLoading,
enableThirdParty,
isAdmin,
getFilesSettings,
setIsLoading
}) => {
const [errorLoading, setErrorLoading] = useState(false);
useEffect(() => {
const { getFilesSettings, setIsLoading } = props;
setIsLoading(true);
getFilesSettings()
.then(() => setIsLoading(false))
@ -35,14 +42,7 @@ const PureSettings = props => {
});
}, []);
console.log("Settings render()");
const {
match,
t,
isLoading,
enableThirdParty,
isAdmin
} = props;
//console.log("Settings render()");
const { setting } = match.params;
const settings = (

View File

@ -508,7 +508,6 @@ export function setEnableThirdParty(data, setting) {
}
export function setForceSave(data, setting) {
console.log( data , setting)
return dispatch => {
return files.forceSave(data)
.then( res => dispatch(setFilesSetting(setting, res)));

View File

@ -1627,9 +1627,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "14.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
version "14.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.1.tgz#cc323bad8e8a533d4822f45ce4e5326f36e42177"
integrity sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==
"@types/parse-json@^4.0.0":
version "4.0.0"
@ -1872,9 +1872,9 @@
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
abab@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
abbrev@1:
version "1.1.1"
@ -2196,7 +2196,7 @@ asap@~2.0.6:
screenfull "^5.0.2"
"asc-web-components@file:../../../packages/asc-web-components":
version "1.0.431"
version "1.0.436"
dependencies:
email-addresses "^3.1.0"
html-to-react "^1.4.2"
@ -4240,9 +4240,9 @@ ejs@^2.6.1:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.564:
version "1.3.564"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz#e9c319ae437b3eb8bbf3e3bae4bead5a21945961"
integrity sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==
version "1.3.566"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.566.tgz#e373876bb63e5c9bbcbe1b48cbb2db000f79bf88"
integrity sha512-V0fANdGN7waOE0tvCDhjf1vqPRevG3eo0asYm42c4t1qmZSunlnUuWQDxglUi9wDpbKQlGIttMJ+2DYpRwvYRA==
elliptic@^6.5.3:
version "6.5.3"
@ -5439,7 +5439,7 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-symbols@^1.0.0, has-symbols@^1.0.1:
has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
@ -6039,9 +6039,9 @@ is-buffer@^1.0.2, is-buffer@^1.1.5:
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.4, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d"
integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==
is-ci@^2.0.0:
version "2.0.0"
@ -7882,7 +7882,7 @@ object-is@^1.0.1:
define-properties "^1.1.3"
es-abstract "^1.17.5"
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@ -7900,14 +7900,14 @@ object-visit@^1.0.0:
isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
version "4.1.1"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.0"
has-symbols "^1.0.1"
object-keys "^1.1.1"
object.entries@^1.1.0, object.entries@^1.1.1:
version "1.1.2"

View File

@ -1,48 +1,76 @@
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { utils, TreeMenu, TreeNode, Icons, Link } from "asc-web-components";
import { history } from "asc-web-common";
import { selectGroup } from "../../../store/people/actions";
import { getSelectedGroup } from "../../../store/people/selectors";
import { withTranslation, I18nextProvider } from "react-i18next";
import { utils as commonUtils } from "asc-web-common";
import { history, utils as commonUtils, store as initStore } from "asc-web-common";
import { createI18N } from "../../../helpers/i18n";
const i18n = createI18N({
page: "Article",
localesPath: "Article"
});
const { changeLanguage } = commonUtils;
const { getCurrentModule, isAdmin } = initStore.auth.selectors;
const getItems = data => {
return data.map(item => {
if (item.children && item.children.length) {
if (item.children) {
return (
<TreeNode
className="root-folder"
title={item.title}
key={item.key}
icon={
item.root ? (
<Icons.CatalogDepartmentsIcon
<Icons.DepartmentsGroupIcon
size="scale"
isfill={true}
color="#657077"
/>
) : (
""
)
""
)
}
>
{getItems(item.children)}
</TreeNode>
);
}
return <TreeNode key={item.key} title={item.title} />;
return <TreeNode
className='inner-folder'
key={item.key}
title={item.title}
icon={
<Icons.CatalogFolderIcon
size="scale"
isfill={true}
color="#657077"
/>
}
/>;
});
};
class ArticleBodyContent extends React.Component {
constructor(props) {
super(props);
const {
organizationName,
groups,
selectedGroup,
currentModuleName
} = props;
const currentGroup = getSelectedGroup(groups, selectedGroup);
document.title = currentGroup
? `${currentGroup.name} ${currentModuleName}`
: `${currentModuleName} ${organizationName}`;
}
shouldComponentUpdate(nextProps) {
if (
!utils.array.isArrayEqual(nextProps.selectedKeys, this.props.selectedKeys)
@ -58,12 +86,18 @@ class ArticleBodyContent extends React.Component {
}
onSelect = data => {
const { selectGroup, groups, t } = this.props;
const {
currentModuleName,
selectGroup,
groups,
organizationName
} = this.props;
const currentGroup = getSelectedGroup(groups, data[0]);
document.title = currentGroup
? `${currentGroup.name} ${t("People")}`
: `${t("People")} ${t("OrganizationName")}`;
? `${currentGroup.name} ${currentModuleName}`
: `${currentModuleName} ${organizationName}`;
selectGroup(
data && data.length === 1 && data[0] !== "root" ? data[0] : null
);
@ -168,15 +202,24 @@ const BodyContent = props => {
};
function mapStateToProps(state) {
const currentModule = getCurrentModule(
state.auth.modules,
state.auth.settings.currentProductId
);
const groups = state.people.groups;
const { groupsCaption } = state.auth.settings.customNames;
const { customNames, organizationName } = state.auth.settings;
const { groupsCaption } = customNames;
return {
data: getTreeGroups(groups, groupsCaption),
selectedKeys: state.people.selectedGroup
? [state.people.selectedGroup]
: ["root"],
groups
groups,
organizationName,
currentModuleName: (currentModule && currentModule.title) || "",
isAdmin: isAdmin(state.auth.user)
};
}

View File

@ -5,7 +5,7 @@ import { withRouter } from "react-router";
import { MainButton, DropDownItem, toastr } from "asc-web-components";
import { InviteDialog } from "./../../dialogs";
import { withTranslation, I18nextProvider } from "react-i18next";
import { store, utils } from "asc-web-common";
import { utils } from "asc-web-common";
import { createI18N } from "../../../helpers/i18n";
const i18n = createI18N({
@ -14,7 +14,6 @@ const i18n = createI18N({
});
const { changeLanguage } = utils;
const { isAdmin } = store.auth.selectors;
class PureArticleMainButtonContent extends React.Component {
constructor(props) {
@ -52,10 +51,10 @@ class PureArticleMainButtonContent extends React.Component {
render() {
console.log("People ArticleMainButtonContent render");
const { isAdmin, settings, t } = this.props;
const { settings, t } = this.props;
const { userCaption, guestCaption, groupCaption } = settings.customNames;
const { dialogVisible } = this.state;
return isAdmin ? (
return (
<>
<MainButton isDisabled={false} isDropdown={true} text={t("Actions")}>
<DropDownItem
@ -103,8 +102,6 @@ class PureArticleMainButtonContent extends React.Component {
/>
)}
</>
) : (
<></>
);
}
}
@ -125,13 +122,11 @@ const ArticleMainButtonContent = props => {
};
ArticleMainButtonContent.propTypes = {
isAdmin: PropTypes.bool.isRequired,
history: PropTypes.object.isRequired
};
const mapStateToProps = state => {
return {
isAdmin: isAdmin(state.auth.user),
settings: state.auth.settings
};
};

View File

@ -4,6 +4,5 @@
"InviteLinkTitle": "Invitation link",
"ImportPeople": "Import people",
"Actions": "Actions",
"LblInviteAgain": "Invite again",
"OrganizationName": "ONLYOFFICE"
}
"LblInviteAgain": "Invite again"
}

View File

@ -4,6 +4,5 @@
"InviteLinkTitle": "Пригласительная ссылка",
"ImportPeople": "Импортировать людей",
"Actions": "Действия",
"LblInviteAgain": "Отправить приглашение ещё раз",
"OrganizationName": "ONLYOFFICE"
}
"LblInviteAgain": "Отправить приглашение ещё раз"
}

View File

@ -1,7 +1,7 @@
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { Loader } from "asc-web-components";
import { PageLayout, utils } from "asc-web-common";
import { PageLayout, utils, store } from "asc-web-common";
import {
ArticleHeaderContent,
ArticleMainButtonContent,
@ -16,6 +16,7 @@ const i18n = createI18N({
localesPath: "pages/GroupAction"
});
const { changeLanguage } = utils;
const { isAdmin } = store.auth.selectors;
class GroupAction extends React.Component {
componentDidMount() {
@ -44,7 +45,7 @@ class GroupAction extends React.Component {
render() {
console.log("GroupAction render");
const { group, match } = this.props;
const { group, match, isAdmin } = this.props;
return (
<I18nextProvider i18n={i18n}>
@ -54,9 +55,11 @@ class GroupAction extends React.Component {
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
{isAdmin && (
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
)}
<PageLayout.ArticleBody>
<ArticleBodyContent />
@ -71,24 +74,26 @@ class GroupAction extends React.Component {
</PageLayout.SectionBody>
</PageLayout>
) : (
<PageLayout>
<PageLayout.ArticleHeader>
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
<PageLayout>
<PageLayout.ArticleHeader>
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
{isAdmin && (
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
)}
<PageLayout.ArticleBody>
<ArticleBodyContent />
</PageLayout.ArticleBody>
<PageLayout.ArticleBody>
<ArticleBodyContent />
</PageLayout.ArticleBody>
<PageLayout.SectionBody>
<Loader className="pageLoader" type="rombs" size="40px" />
</PageLayout.SectionBody>
</PageLayout>
)}
<PageLayout.SectionBody>
<Loader className="pageLoader" type="rombs" size="40px" />
</PageLayout.SectionBody>
</PageLayout>
)}
</I18nextProvider>
);
}
@ -110,7 +115,8 @@ const GroupActionContainer = props => {
function mapStateToProps(state) {
return {
settings: state.auth.settings,
group: state.group.targetGroup
group: state.group.targetGroup,
isAdmin: isAdmin(state.auth.user)
};
}

View File

@ -210,11 +210,11 @@ class SectionBodyContent extends React.PureComponent {
onClick: this.onEmailSentClick.bind(this, user.email)
},
user.mobilePhone &&
isMobileOnly && {
key: "send-message",
label: t("LblSendMessage"),
onClick: this.onSendMessageClick.bind(this, user.mobilePhone)
},
isMobileOnly && {
key: "send-message",
label: t("LblSendMessage"),
onClick: this.onSendMessageClick.bind(this, user.mobilePhone)
},
{ key: "separator", isSeparator: true },
{
key: "edit",
@ -235,18 +235,18 @@ class SectionBodyContent extends React.PureComponent {
? viewer.isOwner
? null
: {
key: "delete-profile",
label: t("DeleteSelfProfile"),
onClick: this.toggleDeleteSelfProfileDialog.bind(
this,
user.email
)
}
: {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick.bind(this, user)
key: "delete-profile",
label: t("DeleteSelfProfile"),
onClick: this.toggleDeleteSelfProfileDialog.bind(
this,
user.email
)
}
: {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick.bind(this, user)
}
];
case "disabled":
return [
@ -284,17 +284,17 @@ class SectionBodyContent extends React.PureComponent {
onClick: this.onInviteAgainClick.bind(this, user)
},
!isSelf &&
(user.status === EmployeeStatus.Active
? {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick.bind(this, user)
}
: {
key: "enable",
label: t("EnableUserButton"),
onClick: this.onEnableClick.bind(this, user)
}),
(user.status === EmployeeStatus.Active
? {
key: "disable",
label: t("DisableUserButton"),
onClick: this.onDisableClick.bind(this, user)
}
: {
key: "enable",
label: t("EnableUserButton"),
onClick: this.onEnableClick.bind(this, user)
}),
isSelf && {
key: "delete-profile",
label: t("DeleteSelfProfile"),
@ -347,7 +347,8 @@ class SectionBodyContent extends React.PureComponent {
settings,
t,
filter,
widthProp
widthProp,
isMobile
} = this.props;
const { dialogsVisible, user } = this.state;
@ -388,6 +389,7 @@ class SectionBodyContent extends React.PureComponent {
widthProp={widthProp}
>
<UserContent
isMobile={isMobile}
widthProp={widthProp}
user={user}
history={history}
@ -434,22 +436,22 @@ class SectionBodyContent extends React.PureComponent {
)}
</>
) : (
<EmptyScreenContainer
imageSrc="images/empty_screen_filter.png"
imageAlt="Empty Screen Filter image"
headerText={t("NotFoundTitle")}
descriptionText={t("NotFoundDescription")}
widthProp={widthProp}
buttons={
<>
<Icons.CrossIcon size="small" style={{ marginRight: "4px" }} />
<Link type="action" isHovered={true} onClick={this.onResetFilter}>
{t("ClearButton")}
</Link>
</>
}
/>
);
<EmptyScreenContainer
imageSrc="images/empty_screen_filter.png"
imageAlt="Empty Screen Filter image"
headerText={t("NotFoundTitle")}
descriptionText={t("NotFoundDescription")}
widthProp={widthProp}
buttons={
<>
<Icons.CrossIcon size="small" style={{ marginRight: "4px" }} />
<Link type="action" isHovered={true} onClick={this.onResetFilter}>
{t("ClearButton")}
</Link>
</>
}
/>
);
}
}

View File

@ -53,7 +53,7 @@ const getFormatedGroups = (user, status, selectGroup) => {
}
};
const UserContent = ({ user, history, settings, selectGroup, widthProp }) => {
const UserContent = ({ user, history, settings, selectGroup, widthProp, isMobile }) => {
const { userName, displayName, title, mobilePhone, email } = user;
const status = getUserStatus(user);
const groups = getFormatedGroups(user, status, selectGroup);
@ -82,6 +82,7 @@ const UserContent = ({ user, history, settings, selectGroup, widthProp }) => {
return (
<RowContent
widthProp={widthProp}
isMobile={isMobile}
sideColor={sideInfoColor}
>
<Link
@ -115,15 +116,15 @@ const UserContent = ({ user, history, settings, selectGroup, widthProp }) => {
>
{title}
</Text>
: <Box
containerMinWidth='120px'
containerWidth='20%'
: <Box
containerMinWidth='120px'
containerWidth='20%'
></Box>
}
{groups}
<Link
containerMinWidth='60px'
containerWidth='15%'
containerMinWidth='60px'
containerWidth='15%'
type='page'
title={mobilePhone}
fontSize='12px'
@ -135,8 +136,8 @@ const UserContent = ({ user, history, settings, selectGroup, widthProp }) => {
{mobilePhone}
</Link>
<Link
containerMinWidth='140px'
containerWidth='15%'
containerMinWidth='140px'
containerWidth='15%'
type='page'
title={email}
fontSize='12px'

View File

@ -3,7 +3,7 @@ import { connect } from "react-redux";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
import { RequestLoader } from "asc-web-components";
import { PageLayout, utils } from "asc-web-common";
import { PageLayout, utils, store } from "asc-web-common";
import { withTranslation, I18nextProvider } from "react-i18next";
import {
ArticleHeaderContent,
@ -17,7 +17,6 @@ import {
SectionPagingContent
} from "./Section";
import { setSelected } from "../../../store/people/actions";
import { getSelectedGroup } from "../../../store/people/selectors";
import { createI18N } from "../../../helpers/i18n";
import { isMobile } from "react-device-detect";
const i18n = createI18N({
@ -25,16 +24,12 @@ const i18n = createI18N({
localesPath: "pages/Home"
});
const { changeLanguage } = utils;
const { isAdmin } = store.auth.selectors;
class PureHome extends React.Component {
constructor(props) {
super(props);
const currentGroup = getSelectedGroup(props.groups, props.selectedGroup);
document.title = currentGroup
? `${currentGroup.name} ${props.t("People")}`
: `${props.t("People")} ${props.t("OrganizationName")}`;
this.state = {
isHeaderVisible: false,
isHeaderIndeterminate: false,
@ -97,7 +92,7 @@ class PureHome extends React.Component {
isHeaderChecked,
selected
} = this.state;
const { t } = this.props;
const { t, isAdmin } = this.props;
return (
<>
<RequestLoader
@ -114,9 +109,11 @@ class PureHome extends React.Component {
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
{isAdmin && (
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
)}
<PageLayout.ArticleBody>
<ArticleBodyContent />
@ -140,6 +137,7 @@ class PureHome extends React.Component {
<PageLayout.SectionBody>
<SectionBodyContent
isMobile={isMobile}
selected={selected}
onLoading={this.onLoading}
onChange={this.onRowChange}
@ -172,17 +170,21 @@ const Home = props => {
Home.propTypes = {
users: PropTypes.array,
history: PropTypes.object.isRequired,
isLoaded: PropTypes.bool
isLoaded: PropTypes.bool,
isAdmin: PropTypes.bool
};
function mapStateToProps(state) {
const { users, selection, selected, selectedGroup, groups } = state.people;
return {
users: state.people.users,
selection: state.people.selection,
selected: state.people.selected,
users,
selection,
selected,
selectedGroup,
groups,
isLoaded: state.auth.isLoaded,
selectedGroup: state.people.selectedGroup,
groups: state.people.groups
organizationName: state.auth.settings.organizationName,
isAdmin: isAdmin(state.auth.user)
};
}

View File

@ -45,12 +45,11 @@
"LblInvited": "Invited",
"LblSetActive": "Set active",
"LblSetDisabled": "Set disabled",
"DirectionAscLabel":"A-Z",
"DirectionDescLabel":"Z-A",
"DirectionAscLabel": "A-Z",
"DirectionDescLabel": "Z-A",
"MakeInvitationLink": "Make invitation link",
"SuccessfullyRemovedUsers": "Users have been removed successfully",
"SendEmailAction": "Send e-mail action",
"SuccessfullyRemovedGroup": "Group has been removed successfully",
"OrganizationName": "ONLYOFFICE",
"AddFilter": "Add filter"
}
}

View File

@ -45,12 +45,11 @@
"LblInvited": "Приглашен",
"LblSetActive": "Разблокировать",
"LblSetDisabled": "Заблокировать",
"DirectionAscLabel":"А-Я",
"DirectionDescLabel":"Я-А",
"DirectionAscLabel": "А-Я",
"DirectionDescLabel": "Я-А",
"MakeInvitationLink": "Создать пригласительную ссылку",
"SuccessfullyRemovedUsers": "Пользователи были успешно удалены",
"SendEmailAction": "Действие отправки e-mail",
"SuccessfullyRemovedGroup": "Группа была успешно удалена",
"OrganizationName": "ONLYOFFICE",
"AddFilter": "Добавить фильтр"
}
}

View File

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { Loader, toastr } from "asc-web-components";
import { PageLayout, utils } from "asc-web-common";
import { PageLayout, utils, store } from "asc-web-common";
import {
ArticleHeaderContent,
ArticleMainButtonContent,
@ -17,6 +17,7 @@ const i18n = createI18N({
localesPath: "pages/Profile"
});
const { changeLanguage } = utils;
const { isAdmin } = store.auth.selectors;
class PureProfile extends React.Component {
constructor(props) {
@ -62,7 +63,7 @@ class PureProfile extends React.Component {
render() {
//console.log("Profile render")
const { profile, isVisitor } = this.props;
const { profile, isVisitor, isAdmin } = this.props;
return (
<PageLayout withBodyAutoFocus={true}>
@ -71,7 +72,7 @@ class PureProfile extends React.Component {
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
)}
{!isVisitor && (
{(!isVisitor && isAdmin) && (
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
@ -92,8 +93,8 @@ class PureProfile extends React.Component {
{profile ? (
<SectionBodyContent />
) : (
<Loader className="pageLoader" type="rombs" size="40px" />
)}
<Loader className="pageLoader" type="rombs" size="40px" />
)}
</PageLayout.SectionBody>
</PageLayout>
);
@ -119,13 +120,15 @@ Profile.propTypes = {
history: PropTypes.object.isRequired,
isLoaded: PropTypes.bool,
match: PropTypes.object.isRequired,
profile: PropTypes.object
profile: PropTypes.object,
isAdmin: PropTypes.bool
};
function mapStateToProps(state) {
return {
isVisitor: state.auth.user.isVisitor,
profile: state.profile.targetUser
profile: state.profile.targetUser,
isAdmin: isAdmin(state.auth.user)
};
}

View File

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { Loader } from "asc-web-components";
import { PageLayout, utils } from "asc-web-common";
import { PageLayout, utils, store } from "asc-web-common";
import {
ArticleHeaderContent,
ArticleMainButtonContent,
@ -21,6 +21,7 @@ const i18n = createI18N({
localesPath: "pages/ProfileAction"
});
const { changeLanguage } = utils;
const { isAdmin } = store.auth.selectors;
class ProfileAction extends React.Component {
componentDidMount() {
@ -50,7 +51,7 @@ class ProfileAction extends React.Component {
console.log("ProfileAction render");
let loaded = false;
const { profile, isVisitor, match } = this.props;
const { profile, isVisitor, match, isAdmin } = this.props;
const { userId, type } = match.params;
if (type) {
@ -67,7 +68,7 @@ class ProfileAction extends React.Component {
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
)}
{!isVisitor && (
{(!isVisitor && isAdmin) && (
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
@ -89,11 +90,11 @@ class ProfileAction extends React.Component {
type ? (
<CreateUserForm />
) : (
<UpdateUserForm />
)
<UpdateUserForm />
)
) : (
<Loader className="pageLoader" type="rombs" size="40px" />
)}
<Loader className="pageLoader" type="rombs" size="40px" />
)}
</PageLayout.SectionBody>
</PageLayout>
</I18nextProvider>
@ -104,7 +105,8 @@ class ProfileAction extends React.Component {
ProfileAction.propTypes = {
fetchProfile: PropTypes.func.isRequired,
match: PropTypes.object.isRequired,
profile: PropTypes.object
profile: PropTypes.object,
isAdmin: PropTypes.bool
};
const ProfileActionTranslate = withTranslation()(ProfileAction);
@ -124,7 +126,8 @@ const ProfileActionContainer = props => {
function mapStateToProps(state) {
return {
isVisitor: state.auth.user.isVisitor,
profile: state.profile.targetUser
profile: state.profile.targetUser,
isAdmin: isAdmin(state.auth.user)
};
}

View File

@ -1,7 +1,7 @@
import React from "react";
import { connect } from "react-redux";
// import PropTypes from "prop-types";
import { PageLayout } from "asc-web-common";
import { PageLayout, store } from "asc-web-common";
import {
ArticleHeaderContent,
ArticleMainButtonContent,
@ -16,6 +16,7 @@ const i18n = createI18N({
page: "Reassign",
localesPath: "pages/Reassign"
});
const { isAdmin } = store.auth.selectors;
class Reassign extends React.Component {
componentDidMount() {
@ -36,6 +37,7 @@ class Reassign extends React.Component {
}
render() {
const { isAdmin } = this.props;
console.log("Reassign render");
// let loaded = false;
@ -55,9 +57,11 @@ class Reassign extends React.Component {
<ArticleHeaderContent />
</PageLayout.ArticleHeader>
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
{isAdmin && (
<PageLayout.ArticleMainButton>
<ArticleMainButtonContent />
</PageLayout.ArticleMainButton>
)}
<PageLayout.ArticleBody>
<ArticleBodyContent />
@ -84,6 +88,7 @@ Reassign.propTypes = {
function mapStateToProps(state) {
return {
isAdmin: isAdmin(state.auth.user)
// profile: state.profile.targetUser
};
}

View File

@ -1627,9 +1627,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "14.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
version "14.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.1.tgz#cc323bad8e8a533d4822f45ce4e5326f36e42177"
integrity sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==
"@types/parse-json@^4.0.0":
version "4.0.0"
@ -1865,9 +1865,9 @@
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
abab@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
abbrev@1:
version "1.1.1"
@ -2189,7 +2189,7 @@ asap@~2.0.6:
screenfull "^5.0.2"
"asc-web-components@file:../../../packages/asc-web-components":
version "1.0.431"
version "1.0.436"
dependencies:
email-addresses "^3.1.0"
html-to-react "^1.4.2"
@ -4233,9 +4233,9 @@ ejs@^2.6.1:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.564:
version "1.3.564"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz#e9c319ae437b3eb8bbf3e3bae4bead5a21945961"
integrity sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==
version "1.3.566"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.566.tgz#e373876bb63e5c9bbcbe1b48cbb2db000f79bf88"
integrity sha512-V0fANdGN7waOE0tvCDhjf1vqPRevG3eo0asYm42c4t1qmZSunlnUuWQDxglUi9wDpbKQlGIttMJ+2DYpRwvYRA==
elliptic@^6.5.3:
version "6.5.3"
@ -5432,7 +5432,7 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-symbols@^1.0.0, has-symbols@^1.0.1:
has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
@ -6032,9 +6032,9 @@ is-buffer@^1.0.2, is-buffer@^1.1.5:
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.4, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d"
integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==
is-ci@^2.0.0:
version "2.0.0"
@ -7875,7 +7875,7 @@ object-is@^1.0.1:
define-properties "^1.1.3"
es-abstract "^1.17.5"
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@ -7893,14 +7893,14 @@ object-visit@^1.0.0:
isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
version "4.1.1"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.0"
has-symbols "^1.0.1"
object-keys "^1.1.1"
object.entries@^1.1.0, object.entries@^1.1.1:
version "1.1.2"

View File

@ -67,8 +67,8 @@ const Tiles = ({ modules, isPrimary }) => {
))}
</div>
) : (
<></>
);
<></>
);
};
Tiles.propTypes = {
@ -76,12 +76,12 @@ Tiles.propTypes = {
isPrimary: PropTypes.bool.isRequired
};
const Body = ({ modules, match, isLoaded, homepage }) => {
const Body = ({ modules, match, isLoaded, homepage, organizationName }) => {
const { t } = useTranslation("translation", { i18n });
const { error } = match.params;
document.title = `${t("OrganizationName")}`;
window.open(homepage, '_self')
document.title = `${organizationName}`;
window.open(homepage, "_self");
useEffect(() => error && toastr.error(error), [error]);
@ -92,17 +92,17 @@ const Body = ({ modules, match, isLoaded, homepage }) => {
return !isLoaded ? (
<Loader className="pageLoader" type="rombs" size="40px" />
) : (
<HomeContainer>
<Tiles modules={modules} isPrimary={true} />
<Tiles modules={modules} isPrimary={false} />
<HomeContainer>
<Tiles modules={modules} isPrimary={true} />
<Tiles modules={modules} isPrimary={false} />
{!modules || !modules.length ? (
<Text className="home-error-text" fontSize="14px" color="#c30">
{t("NoOneModulesAvailable")}
</Text>
) : null}
</HomeContainer>
);
{!modules || !modules.length ? (
<Text className="home-error-text" fontSize="14px" color="#c30">
{t("NoOneModulesAvailable")}
</Text>
) : null}
</HomeContainer>
);
};
const Home = props => (
@ -119,10 +119,13 @@ Home.propTypes = {
};
function mapStateToProps(state) {
const { modules, isLoaded, settings } = state.auth;
const { homepage, organizationName } = settings;
return {
modules: state.auth.modules,
isLoaded: state.auth.isLoaded,
homepage: state.auth.settings.homepage
modules,
isLoaded,
homepage,
organizationName
};
}

View File

@ -1,4 +1,3 @@
{
"NoOneModulesAvailable": "No one modules available",
"OrganizationName": "ONLYOFFICE"
}
"NoOneModulesAvailable": "No one modules available"
}

View File

@ -1,4 +1,3 @@
{
"NoOneModulesAvailable": "Ни один модуль не доступен",
"OrganizationName": "ONLYOFFICE"
}
"NoOneModulesAvailable": "Ни один модуль не доступен"
}

View File

@ -1,231 +1,261 @@
import React from "react";
import { connect } from "react-redux";
import { withTranslation } from 'react-i18next';
import { FieldContainer, Loader, toastr, TextInput, Link, SaveCancelButtons } from "asc-web-components";
import styled from 'styled-components';
import { setGreetingTitle, restoreGreetingTitle } from '../../../../../store/settings/actions';
import { saveToSessionStorage, getFromSessionStorage } from '../../utils';
import { withTranslation } from "react-i18next";
import {
FieldContainer,
Loader,
toastr,
TextInput,
Link,
SaveCancelButtons
} from "asc-web-components";
import styled from "styled-components";
import {
setGreetingTitle,
restoreGreetingTitle
} from "../../../../../store/settings/actions";
import { saveToSessionStorage, getFromSessionStorage } from "../../utils";
const StyledComponent = styled.div`
.margin-top {
margin-top: 20px;
}
.margin-top {
margin-top: 20px;
}
.margin-left {
margin-left: 20px;
}
.margin-left {
margin-left: 20px;
}
.settings-block {
margin-bottom: 70px;
}
.settings-block {
margin-bottom: 70px;
}
.field-container-width {
max-width: 500px;
}
.field-container-width {
max-width: 500px;
}
.combo-button-label {
max-width: 100%;
}
.link-wrapper{
margin-top: 8px;
}
.combo-button-label {
max-width: 100%;
}
.link-wrapper {
margin-top: 8px;
}
`;
let greetingTitleFromSessionStorage = "";
const settingNames = [
"greetingTitle"
];
const settingNames = ["greetingTitle"];
class CustomTitles extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
const { t, greetingSettings, organizationName } = props;
const { t, greetingSettings } = props;
greetingTitleFromSessionStorage = getFromSessionStorage("greetingTitle");
greetingTitleFromSessionStorage = getFromSessionStorage("greetingTitle");
document.title = `${t("Customization")} ${organizationName}`;
document.title = `${t("Customization")} ${t("OrganizationName")}`;
this.state = {
isLoadedData: false,
isLoading: false,
greetingTitle: greetingTitleFromSessionStorage || greetingSettings,
greetingTitleDefault: greetingSettings,
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
hasChanged: false,
showReminder: false
};
}
this.state = {
isLoadedData: false,
isLoading: false,
greetingTitle: greetingTitleFromSessionStorage || greetingSettings,
greetingTitleDefault: greetingSettings,
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
hasChanged: false,
showReminder: false
}
}
componentDidMount() {
const { showReminder } = this.state;
componentDidMount() {
const { showReminder } = this.state
if ((greetingTitleFromSessionStorage) && !showReminder) {
this.setState({
showReminder: true
})
}
if (greetingTitleFromSessionStorage && !showReminder) {
this.setState({
isLoadedData: true
})
}
componentDidUpdate(prevProps, prevState) {
if (prevState.isLoadedData !== true) {
this.setState({
isLoadedData: true
})
}
if (this.state.greetingTitleDefault) {
this.checkChanges()
}
}
onChangeGreetingTitle = (e) => {
this.setState({ greetingTitle: e.target.value })
if (this.settingIsEqualInitialValue("greetingTitle", e.target.value)) {
saveToSessionStorage("greetingTitle", "")
} else {
saveToSessionStorage("greetingTitle", e.target.value)
}
this.checkChanges()
};
onSaveGreetingSettings = () => {
const { setGreetingTitle, t } = this.props;
const { greetingTitle } = this.state
this.setState({ isLoadingGreetingSave: true }, function () {
setGreetingTitle(greetingTitle)
.then(() => toastr.success(t('SuccessfullySaveGreetingSettingsMessage')))
.catch((error) => toastr.error(error))
.finally(() => this.setState({ isLoadingGreetingSave: false }));
})
showReminder: true
});
}
this.setState({
isLoadedData: true
});
}
componentDidUpdate(prevProps, prevState) {
if (prevState.isLoadedData !== true) {
this.setState({
showReminder: false,
greetingTitle: greetingTitle,
greetingTitleDefault: greetingTitle,
})
}
isLoadedData: true
});
}
onRestoreGreetingSettings = () => {
const { restoreGreetingTitle, t } = this.props;
this.setState({ isLoadingGreetingRestore: true }, function () {
restoreGreetingTitle()
.then(() => {
this.setState({
greetingTitle: this.props.greetingSettings,
greetingTitleDefault: this.props.greetingSettings,
showReminder: false,
})
saveToSessionStorage("greetingTitle", "")
toastr.success(t('SuccessfullySaveGreetingSettingsMessage'));
})
.catch((error) => toastr.error(error))
.finally(() => this.setState({ isLoadingGreetingRestore: false }));
})
}
if (this.state.greetingTitleDefault) {
this.checkChanges();
}
}
onCancelClick = () => {
onChangeGreetingTitle = e => {
this.setState({ greetingTitle: e.target.value });
settingNames.forEach(currentSetting => {
const valueFromSessionStorage = getFromSessionStorage(currentSetting);
if (this.settingIsEqualInitialValue("greetingTitle", e.target.value)) {
saveToSessionStorage("greetingTitle", "");
} else {
saveToSessionStorage("greetingTitle", e.target.value);
}
if (valueFromSessionStorage && !this.settingIsEqualInitialValue(currentSetting, valueFromSessionStorage)) {
const defaultValue = this.state[currentSetting + "Default"];
this.checkChanges();
};
this.setState({ [currentSetting]: defaultValue })
saveToSessionStorage(currentSetting, "")
}
})
onSaveGreetingSettings = () => {
const { setGreetingTitle, t } = this.props;
const { greetingTitle } = this.state;
this.setState({ isLoadingGreetingSave: true }, function() {
setGreetingTitle(greetingTitle)
.then(() =>
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"))
)
.catch(error => toastr.error(error))
.finally(() => this.setState({ isLoadingGreetingSave: false }));
});
this.setState({
showReminder: false
})
this.setState({
showReminder: false,
greetingTitle: greetingTitle,
greetingTitleDefault: greetingTitle
});
};
this.checkChanges()
}
onRestoreGreetingSettings = () => {
const { restoreGreetingTitle, t } = this.props;
this.setState({ isLoadingGreetingRestore: true }, function() {
restoreGreetingTitle()
.then(() => {
this.setState({
greetingTitle: this.props.greetingSettings,
greetingTitleDefault: this.props.greetingSettings,
showReminder: false
});
saveToSessionStorage("greetingTitle", "");
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
})
.catch(error => toastr.error(error))
.finally(() => this.setState({ isLoadingGreetingRestore: false }));
});
};
settingIsEqualInitialValue = (stateName, value) => {
const defaultValue = JSON.stringify(this.state[stateName + "Default"])
const currentValue = JSON.stringify(value)
return defaultValue === currentValue
}
onCancelClick = () => {
settingNames.forEach(currentSetting => {
const valueFromSessionStorage = getFromSessionStorage(currentSetting);
checkChanges = () => {
let hasChanged = false;
if (
valueFromSessionStorage &&
!this.settingIsEqualInitialValue(
currentSetting,
valueFromSessionStorage
)
) {
const defaultValue = this.state[currentSetting + "Default"];
settingNames.forEach(settingName => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (valueFromSessionStorage && !this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)) hasChanged = true
})
if (hasChanged !== this.state.hasChanged) {
this.setState({
hasChanged: hasChanged,
})
this.setState({ [currentSetting]: defaultValue });
saveToSessionStorage(currentSetting, "");
}
}
});
render() {
const { t } = this.props;
const { isLoadedData, greetingTitle, isLoadingGreetingSave, isLoadingGreetingRestore, hasChanged, showReminder } = this.state;
this.setState({
showReminder: false
});
return (
!isLoadedData ?
<Loader className="pageLoader" type="rombs" size='40px' />
: <>
<StyledComponent>
<div className='settings-block'>
<FieldContainer
id='fieldContainerWelcomePage'
className='field-container-width'
labelText={`${t("WelcomePageTitle")}:`}
isVertical={true}>
<TextInput
scale={true}
value={greetingTitle}
onChange={this.onChangeGreetingTitle}
isDisabled={isLoadingGreetingSave || isLoadingGreetingRestore}
/>
<div className="link-wrapper">
<Link
onClick={this.onRestoreGreetingSettings}
type="action"
color="#A3A9AE"
>
{t('SetDefaultTitle')}
</Link>
</div>
this.checkChanges();
};
</FieldContainer>
</div>
{hasChanged &&
<SaveCancelButtons
onSaveClick={this.onSaveGreetingSettings}
onCancelClick={this.onCancelClick}
showReminder={showReminder}
reminderTest={t('YouHaveUnsavedChanges')}
saveButtonLabel={t('SaveButton')}
cancelButtonLabel={t('CancelButton')}
/>
}
</StyledComponent>
</>
);
}
};
settingIsEqualInitialValue = (stateName, value) => {
const defaultValue = JSON.stringify(this.state[stateName + "Default"]);
const currentValue = JSON.stringify(value);
return defaultValue === currentValue;
};
function mapStateToProps(state) {
return {
greetingSettings: state.auth.settings.greetingSettings,
};
checkChanges = () => {
let hasChanged = false;
settingNames.forEach(settingName => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (
valueFromSessionStorage &&
!this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)
)
hasChanged = true;
});
if (hasChanged !== this.state.hasChanged) {
this.setState({
hasChanged: hasChanged
});
}
};
render() {
const { t } = this.props;
const {
isLoadedData,
greetingTitle,
isLoadingGreetingSave,
isLoadingGreetingRestore,
hasChanged,
showReminder
} = this.state;
return !isLoadedData ? (
<Loader className="pageLoader" type="rombs" size="40px" />
) : (
<>
<StyledComponent>
<div className="settings-block">
<FieldContainer
id="fieldContainerWelcomePage"
className="field-container-width"
labelText={`${t("WelcomePageTitle")}:`}
isVertical={true}
>
<TextInput
scale={true}
value={greetingTitle}
onChange={this.onChangeGreetingTitle}
isDisabled={isLoadingGreetingSave || isLoadingGreetingRestore}
/>
<div className="link-wrapper">
<Link
onClick={this.onRestoreGreetingSettings}
type="action"
color="#A3A9AE"
>
{t("SetDefaultTitle")}
</Link>
</div>
</FieldContainer>
</div>
{hasChanged && (
<SaveCancelButtons
onSaveClick={this.onSaveGreetingSettings}
onCancelClick={this.onCancelClick}
showReminder={showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("SaveButton")}
cancelButtonLabel={t("CancelButton")}
/>
)}
</StyledComponent>
</>
);
}
}
export default connect(mapStateToProps, { setGreetingTitle, restoreGreetingTitle })(withTranslation()(CustomTitles));
function mapStateToProps(state) {
const { greetingSettings, organizationName } = state.auth.settings;
return {
greetingSettings,
organizationName
};
}
export default connect(
mapStateToProps,
{ setGreetingTitle, restoreGreetingTitle }
)(withTranslation()(CustomTitles));

View File

@ -95,12 +95,13 @@ class Customization extends React.Component {
portalTimeZoneId,
rawCultures,
rawTimezones,
organizationName,
t
} = props;
const languages = mapCulturesToArray(rawCultures, t);
const timezones = mapTimezonesToArray(rawTimezones);
document.title = `${t("Customization")} ${t("OrganizationName")}`;
document.title = `${t("Customization")} ${organizationName}`;
this.state = {
isLoadedData: false,
@ -268,14 +269,22 @@ class Customization extends React.Component {
}
function mapStateToProps(state) {
const {
culture,
timezone,
timezones,
cultures,
nameSchemaId,
organizationName
} = state.auth.settings;
return {
portalLanguage: state.auth.settings.culture,
portalTimeZoneId: state.auth.settings.timezone,
language:
state.auth.user.cultureName || state.auth.settings.culture || "en-US",
rawTimezones: state.auth.settings.timezones,
rawCultures: state.auth.settings.cultures,
nameSchemaId: state.auth.settings.nameSchemaId
portalLanguage: culture,
portalTimeZoneId: timezone,
language: state.auth.user.cultureName || culture || "en-US",
rawTimezones: timezones,
rawCultures: cultures,
nameSchemaId: nameSchemaId,
organizationName
};
}

View File

@ -1,333 +1,428 @@
import React from "react";
import { connect } from "react-redux";
import { withTranslation } from 'react-i18next';
import { FieldContainer, Text, ComboBox, Loader, toastr, Link, SaveCancelButtons } from "asc-web-components";
import styled from 'styled-components';
import { Trans } from 'react-i18next';
import { store, utils } from 'asc-web-common';
import { setLanguageAndTime, getPortalTimezones } from '../../../../../store/settings/actions';
import { saveToSessionStorage, getFromSessionStorage } from '../../utils';
import { default as clientStore } from '../../../../../store/store';
import { withTranslation } from "react-i18next";
import {
FieldContainer,
Text,
ComboBox,
Loader,
toastr,
Link,
SaveCancelButtons
} from "asc-web-components";
import styled from "styled-components";
import { Trans } from "react-i18next";
import { store, utils } from "asc-web-common";
import {
setLanguageAndTime,
getPortalTimezones
} from "../../../../../store/settings/actions";
import { saveToSessionStorage, getFromSessionStorage } from "../../utils";
import { default as clientStore } from "../../../../../store/store";
const { changeLanguage } = utils;
const { getPortalCultures, getModules, getCurrentCustomSchema } = store.auth.actions;
const {
getPortalCultures,
getModules,
getCurrentCustomSchema
} = store.auth.actions;
const mapCulturesToArray = (cultures, t) => {
return cultures.map((culture) => {
return { key: culture, label: t(`Culture_${culture}`) };
});
return cultures.map(culture => {
return { key: culture, label: t(`Culture_${culture}`) };
});
};
const mapTimezonesToArray = (timezones) => {
return timezones.map((timezone) => {
return { key: timezone.id, label: timezone.displayName };
});
const mapTimezonesToArray = timezones => {
return timezones.map(timezone => {
return { key: timezone.id, label: timezone.displayName };
});
};
const findSelectedItemByKey = (items, selectedItemKey) => {
return items.find(item => item.key === selectedItemKey);
}
return items.find(item => item.key === selectedItemKey);
};
const StyledComponent = styled.div`
.margin-top {
margin-top: 20px;
}
.margin-top {
margin-top: 20px;
}
.margin-left {
margin-left: 20px;
}
.margin-left {
margin-left: 20px;
}
.settings-block {
margin-bottom: 70px;
}
.settings-block {
margin-bottom: 70px;
}
.field-container-width {
max-width: 500px;
}
.field-container-width {
max-width: 500px;
}
.combo-button-label {
max-width: 100%;
}
.combo-button-label {
max-width: 100%;
}
`;
let languageFromSessionStorage = "";
let timezoneFromSessionStorage = "";
const settingNames = [
"language",
"timezone"
]
const settingNames = ["language", "timezone"];
class LanguageAndTimeZone extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
const {
portalLanguage,
portalTimeZoneId,
rawCultures,
rawTimezones,
organizationName,
t
} = props;
const languages = mapCulturesToArray(rawCultures, t);
const timezones = mapTimezonesToArray(rawTimezones);
const language = findSelectedItemByKey(
languages,
portalLanguage || languages[0]
);
const timezone = findSelectedItemByKey(
timezones,
portalTimeZoneId || timezones[0]
);
const { portalLanguage, portalTimeZoneId, rawCultures, rawTimezones, t } = props;
const languages = mapCulturesToArray(rawCultures, t);
const timezones = mapTimezonesToArray(rawTimezones);
const language = findSelectedItemByKey(languages, portalLanguage || languages[0]);
const timezone = findSelectedItemByKey(timezones, portalTimeZoneId || timezones[0]);
languageFromSessionStorage = getFromSessionStorage("language");
timezoneFromSessionStorage = getFromSessionStorage("timezone");
languageFromSessionStorage = getFromSessionStorage("language");
timezoneFromSessionStorage = getFromSessionStorage("timezone");
document.title = `${t("Customization")} ${organizationName}`;
document.title = `${t("Customization")} ${t("OrganizationName")}`;
this.state = {
isLoadedData: false,
isLoading: false,
timezones,
timezone: timezoneFromSessionStorage || timezone,
timezoneDefault: timezone,
languages,
language: languageFromSessionStorage || language,
languageDefault: language,
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
hasChanged: false,
showReminder: false
};
}
this.state = {
isLoadedData: false,
isLoading: false,
timezones,
timezone: timezoneFromSessionStorage || timezone,
timezoneDefault: timezone,
languages,
language: languageFromSessionStorage || language,
languageDefault: language,
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
hasChanged: false,
showReminder: false
}
}
componentDidMount() {
const {
getPortalCultures,
portalLanguage,
portalTimeZoneId,
t,
getPortalTimezones
} = this.props;
const { timezones, languages, isLoadedData, showReminder } = this.state;
componentDidMount() {
const { getPortalCultures, portalLanguage, portalTimeZoneId, t, getPortalTimezones } = this.props;
const { timezones, languages, isLoadedData, showReminder } = this.state;
if (
(languageFromSessionStorage || timezoneFromSessionStorage) &&
!showReminder
) {
this.setState({
showReminder: true
});
}
if ((languageFromSessionStorage || timezoneFromSessionStorage) && !showReminder) {
this.setState({
showReminder: true
})
}
if (!timezones.length && !languages.length) {
let languages;
getPortalCultures()
.then(() => {
languages = mapCulturesToArray(this.props.rawCultures, t);
})
.then(() => getPortalTimezones())
.then(() => {
const timezones = mapTimezonesToArray(this.props.rawTimezones);
if (!timezones.length && !languages.length) {
let languages;
getPortalCultures()
.then(() => {
languages = mapCulturesToArray(this.props.rawCultures, t);
})
.then(() => getPortalTimezones())
.then(() => {
const language =
languageFromSessionStorage ||
findSelectedItemByKey(languages, portalLanguage) ||
languages[0];
const timezone =
timezoneFromSessionStorage ||
findSelectedItemByKey(timezones, portalTimeZoneId) ||
timezones[0];
const timezones = mapTimezonesToArray(this.props.rawTimezones);
const languageDefault =
findSelectedItemByKey(languages, portalLanguage) || languages[0];
const timezoneDefault =
findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
const language = languageFromSessionStorage || findSelectedItemByKey(languages, portalLanguage) || languages[0];
const timezone = timezoneFromSessionStorage || findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
this.setState({
languages,
language,
timezones,
timezone,
languageDefault,
timezoneDefault
});
const languageDefault = findSelectedItemByKey(languages, portalLanguage) || languages[0];
const timezoneDefault = findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0]
this.setState({ languages, language, timezones, timezone, languageDefault, timezoneDefault });
if (!timezoneDefault) {
this.setState({
timezoneDefault: timezone
})
}
if (!languageDefault) {
this.setState({
languageDefault: language
})
}
if (!timezoneDefault) {
this.setState({
timezoneDefault: timezone
});
}
if (timezones.length && languages.length && !isLoadedData) {
this.setState({ isLoadedData: true });
}
}
}
if (!languageDefault) {
this.setState({
languageDefault: language
});
}
});
}
if (timezones.length && languages.length && !isLoadedData) {
this.setState({ isLoadedData: true });
}
}
componentDidUpdate(prevProps, prevState) {
const { timezones, languages, timezoneDefault, languageDefault } = this.state;
const { i18n, language, nameSchemaId } = this.props;
if (timezones.length && languages.length && !prevState.isLoadedData) {
this.setState({ isLoadedData: true });
}
if (language !== prevProps.language) {
changeLanguage(i18n)
.then((t) => {
const newLocaleLanguages = mapCulturesToArray(this.props.rawCultures, t);
const newLocaleSelectedLanguage = findSelectedItemByKey(newLocaleLanguages, this.state.language.key) || newLocaleLanguages[0];
this.setState({
languages: newLocaleLanguages,
language: languageFromSessionStorage || newLocaleSelectedLanguage
});
})
.then(() => getModules(clientStore.dispatch))
.then(() => getCurrentCustomSchema(clientStore.dispatch, nameSchemaId));
}
if (timezoneDefault && languageDefault) {
this.checkChanges()
}
}
componentDidUpdate(prevProps, prevState) {
const {
timezones,
languages,
timezoneDefault,
languageDefault
} = this.state;
const { i18n, language, nameSchemaId } = this.props;
if (timezones.length && languages.length && !prevState.isLoadedData) {
this.setState({ isLoadedData: true });
}
if (language !== prevProps.language) {
changeLanguage(i18n)
.then(t => {
const newLocaleLanguages = mapCulturesToArray(
this.props.rawCultures,
t
);
const newLocaleSelectedLanguage =
findSelectedItemByKey(
newLocaleLanguages,
this.state.language.key
) || newLocaleLanguages[0];
this.setState({
languages: newLocaleLanguages,
language: languageFromSessionStorage || newLocaleSelectedLanguage
});
})
.then(() => getModules(clientStore.dispatch))
.then(() => getCurrentCustomSchema(clientStore.dispatch, nameSchemaId));
}
if (timezoneDefault && languageDefault) {
this.checkChanges();
}
}
onLanguageSelect = (language) => {
this.setState({ language })
if (this.settingIsEqualInitialValue("language", language)) {
saveToSessionStorage("language", "")
} else {
saveToSessionStorage("language", language)
onLanguageSelect = language => {
this.setState({ language });
if (this.settingIsEqualInitialValue("language", language)) {
saveToSessionStorage("language", "");
} else {
saveToSessionStorage("language", language);
}
this.checkChanges();
};
onTimezoneSelect = timezone => {
this.setState({ timezone });
if (this.settingIsEqualInitialValue("timezone", timezone)) {
saveToSessionStorage("timezone", "");
} else {
saveToSessionStorage("timezone", timezone);
}
this.checkChanges();
};
onSaveLngTZSettings = () => {
const { setLanguageAndTime, i18n } = this.props;
this.setState({ isLoading: true }, function() {
setLanguageAndTime(this.state.language.key, this.state.timezone.key)
.then(() => changeLanguage(i18n))
.then(t => toastr.success(t("SuccessfullySaveSettingsMessage")))
.catch(error => toastr.error(error))
.finally(() => this.setState({ isLoading: false }));
});
this.setState({
showReminder: false,
timezoneDefault: this.state.timezone,
languageDefault: this.state.language
});
};
onCancelClick = () => {
settingNames.forEach(settingName => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (
valueFromSessionStorage &&
!this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)
) {
const defaultValue = this.state[settingName + "Default"];
this.setState({ [settingName]: defaultValue });
saveToSessionStorage(settingName, "");
}
this.checkChanges()
};
});
onTimezoneSelect = (timezone) => {
this.setState({ timezone })
if (this.settingIsEqualInitialValue("timezone", timezone)) {
saveToSessionStorage("timezone", "")
} else {
saveToSessionStorage("timezone", timezone)
}
this.setState({
showReminder: false
});
this.checkChanges()
};
this.checkChanges();
};
onSaveLngTZSettings = () => {
const { setLanguageAndTime, i18n } = this.props;
this.setState({ isLoading: true }, function () {
setLanguageAndTime(this.state.language.key, this.state.timezone.key)
.then(() => changeLanguage(i18n))
.then((t) => toastr.success(t("SuccessfullySaveSettingsMessage")))
.catch((error) => toastr.error(error))
.finally(() => this.setState({ isLoading: false }));
})
settingIsEqualInitialValue = (settingName, value) => {
const defaultValue = JSON.stringify(this.state[settingName + "Default"]);
const currentValue = JSON.stringify(value);
return defaultValue === currentValue;
};
checkChanges = () => {
let hasChanged = false;
settingNames.forEach(settingName => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (
valueFromSessionStorage &&
!this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)
)
hasChanged = true;
});
if (hasChanged !== this.state.hasChanged) {
this.setState({
showReminder: false,
timezoneDefault: this.state.timezone,
languageDefault: this.state.language,
})
}
hasChanged: hasChanged
});
}
};
onCancelClick = () => {
settingNames.forEach(settingName => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
render() {
const { t, i18n } = this.props;
const {
isLoadedData,
languages,
language,
isLoading,
timezones,
timezone,
hasChanged,
showReminder
} = this.state;
const supportEmail = "documentation@onlyoffice.com";
const tooltipLanguage = (
<Text fontSize="13px">
<Trans i18nKey="NotFoundLanguage" i18n={i18n}>
"In case you cannot find your language in the list of the available
ones, feel free to write to us at
<Link href={`mailto:${supportEmail}`} isHovered={true}>
{{ supportEmail }}
</Link>{" "}
to take part in the translation and get up to 1 year free of charge."
</Trans>{" "}
<Link
isHovered={true}
href="https://helpcenter.onlyoffice.com/ru/guides/become-translator.aspx"
>
{t("LearnMore")}
</Link>
</Text>
);
if (valueFromSessionStorage && !this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)) {
const defaultValue = this.state[settingName + "Default"];
return !isLoadedData ? (
<Loader className="pageLoader" type="rombs" size="40px" />
) : (
<>
<StyledComponent>
<div className="settings-block">
<FieldContainer
id="fieldContainerLanguage"
className="field-container-width"
labelText={`${t("Language")}:`}
tooltipContent={tooltipLanguage}
helpButtonHeaderContent={t("Language")}
isVertical={true}
>
<ComboBox
id="comboBoxLanguage"
options={languages}
selectedOption={language}
onSelect={this.onLanguageSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className="dropdown-item-width"
/>
</FieldContainer>
this.setState({ [settingName]: defaultValue })
saveToSessionStorage(settingName, "")
}
})
this.setState({
showReminder: false
})
this.checkChanges()
}
settingIsEqualInitialValue = (settingName, value) => {
const defaultValue = JSON.stringify(this.state[settingName + "Default"])
const currentValue = JSON.stringify(value)
return defaultValue === currentValue
}
checkChanges = () => {
let hasChanged = false;
settingNames.forEach(settingName => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (valueFromSessionStorage && !this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)) hasChanged = true
})
if (hasChanged !== this.state.hasChanged) {
this.setState({
hasChanged: hasChanged,
})
}
}
render() {
const { t, i18n } = this.props;
const { isLoadedData, languages, language, isLoading, timezones, timezone, hasChanged, showReminder } = this.state;
const supportEmail = "documentation@onlyoffice.com";
const tooltipLanguage =
<Text fontSize='13px'>
<Trans i18nKey="NotFoundLanguage" i18n={i18n}>
"In case you cannot find your language in the list of the
available ones, feel free to write to us at
<Link href={`mailto:${supportEmail}`} isHovered={true}>
{{ supportEmail }}
</Link> to take part in the translation and get up to 1 year free of
charge."
</Trans>
{" "}
<Link isHovered={true} href="https://helpcenter.onlyoffice.com/ru/guides/become-translator.aspx">{t("LearnMore")}</Link>
</Text>
return (
!isLoadedData ?
<Loader className="pageLoader" type="rombs" size='40px' />
: <>
<StyledComponent>
<div className='settings-block'>
<FieldContainer
id='fieldContainerLanguage'
className='field-container-width'
labelText={`${t("Language")}:`}
tooltipContent={tooltipLanguage}
helpButtonHeaderContent={t("Language")}
isVertical={true}>
<ComboBox
id='comboBoxLanguage'
options={languages}
selectedOption={language}
onSelect={this.onLanguageSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className='dropdown-item-width'
/>
</FieldContainer>
<FieldContainer
id='fieldContainerTimezone'
className='field-container-width'
labelText={`${t("TimeZone")}:`}
isVertical={true}>
<ComboBox
id='comboBoxTimezone'
options={timezones}
selectedOption={timezone}
onSelect={this.onTimezoneSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className='dropdown-item-width'
/>
</FieldContainer>
</div>
{hasChanged &&
<SaveCancelButtons
onSaveClick={this.onSaveLngTZSettings}
onCancelClick={this.onCancelClick}
showReminder={showReminder}
reminderTest={t('YouHaveUnsavedChanges')}
saveButtonLabel={t('SaveButton')}
cancelButtonLabel={t('CancelButton')}
/>
}
</StyledComponent>
</>
);
}
};
function mapStateToProps(state) {
return {
portalLanguage: state.auth.settings.culture,
portalTimeZoneId: state.auth.settings.timezone,
language: state.auth.user.cultureName || state.auth.settings.culture,
rawTimezones: state.auth.settings.timezones,
rawCultures: state.auth.settings.cultures,
greetingSettings: state.auth.settings.greetingSettings,
nameSchemaId: state.auth.settings.nameSchemaId
};
<FieldContainer
id="fieldContainerTimezone"
className="field-container-width"
labelText={`${t("TimeZone")}:`}
isVertical={true}
>
<ComboBox
id="comboBoxTimezone"
options={timezones}
selectedOption={timezone}
onSelect={this.onTimezoneSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className="dropdown-item-width"
/>
</FieldContainer>
</div>
{hasChanged && (
<SaveCancelButtons
onSaveClick={this.onSaveLngTZSettings}
onCancelClick={this.onCancelClick}
showReminder={showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("SaveButton")}
cancelButtonLabel={t("CancelButton")}
/>
)}
</StyledComponent>
</>
);
}
}
export default connect(mapStateToProps, { getPortalCultures, setLanguageAndTime, getPortalTimezones })(withTranslation()(LanguageAndTimeZone));
function mapStateToProps(state) {
const {
culture,
timezone,
timezones,
cultures,
greetingSettings,
nameSchemaId,
organizationName
} = state.auth.settings;
return {
portalLanguage: culture,
portalTimeZoneId: timezone,
language: state.auth.user.cultureName || culture,
rawTimezones: timezones,
rawCultures: cultures,
greetingSettings,
nameSchemaId,
organizationName
};
}
export default connect(
mapStateToProps,
{ getPortalCultures, setLanguageAndTime, getPortalTimezones }
)(withTranslation()(LanguageAndTimeZone));

View File

@ -1,5 +1,6 @@
import React, { Component, useEffect } from "react";
import { withRouter } from "react-router";
import { connect } from "react-redux";
//import i18n from "../../i18n";
import { I18nextProvider, withTranslation } from "react-i18next";
import styled from "styled-components";
@ -32,9 +33,9 @@ class PureAccessRights extends Component {
constructor(props) {
super(props);
document.title = `${props.t("ManagementCategorySecurity")} ${props.t(
"OrganizationName"
)}`;
const { t, organizationName } = props;
document.title = `${t("ManagementCategorySecurity")} ${organizationName}`;
const url = props.history.location.pathname;
const newUrl = url.split("/");
@ -118,7 +119,16 @@ class PureAccessRights extends Component {
}
}
const AccessRightsContainer = withTranslation()(PureAccessRights);
function mapStateToProps(state) {
const { organizationName } = state.auth.settings;
return {
organizationName
};
}
const AccessRightsContainer = connect(mapStateToProps)(
withTranslation()(PureAccessRights)
);
const AccessRights = props => {
useEffect(() => {

View File

@ -1,108 +1,105 @@
{
"PortalOwner": "Portal Owner",
"AccessRightsOwnerCan": "Portal owner can",
"AccessRightsOwnerOpportunities": "Do the same as module administrators|Appoint module administrators|Set modules access rights|Manage portal configuration|Manage user accounts|Change portal owner|Backup portal data|Deactivate or delete portal",
"AdminSettings": "Administrators",
"ProjectsProduct": "Projects",
"CrmProduct": "CRM",
"CommunityProduct": "Community",
"People": "People",
"Mail": "Mail",
"AccessRightsFullAccess": "Full access",
"DocumentsProduct": "Documents",
"AccessRightsAccessToProduct": "Access to {{product}} module is given to",
"AccessRightsProductUsersCan": "{{category}} users can",
"AccessRightsDisabledProduct": "{{module}} module is disabled and is not shown on the portal. To enable it, refer to the Modules &amp; Tools section of the Portal Settings",
"AccessRightsAllUsers": "All {{users}}",
"AccessRightsUsersFromList": "{{users}} from the list",
"Employees": "users",
"StudioTimeLanguageSettings": "Language and Time Zone Settings",
"Language": "Language",
"TimeZone": "Time Zone",
"SaveButton": "Save",
"CancelButton": "Cancel",
"SuccessfullySaveSettingsMessage": "Settings have been successfully updated",
"NotFoundLanguage": "In case you cannot find your language in the list of the available ones, feel free to write to us at <1>{{supportEmail}}</1> to take part in the translation and get up to 1 year free of charge.",
"Settings": "Settings",
"PreviousPage": "Previous",
"NextPage": "Next",
"ManagementCategoryCommon": "Common",
"Customization": "Customization",
"ProductsAndInstruments": "Modules & tools",
"WhiteLabel": "White label",
"ManagementCategorySecurity": "Security",
"PortalSecurity": "Portal Access",
"AccessRights": "Access Rights",
"LoginHistoryNav": "Login History",
"AuditTrailNav": "Audit Trail",
"DataManagement": "Data Management",
"Migration": "Migration",
"Backup": "Backup",
"DeactivationDeletionPortal": "Portal Deactivation/Deletion",
"ManagementCategoryIntegration": "Integration",
"ThirdPartyAuthorization": "Third Party Authorization",
"SmtpSettings": "SMTP Settings",
"ManagementCategoryStatistic": "Statistics",
"LoadingProcessing": "Loading...",
"LoadingDescription": "Please wait...",
"GreetingSettingsTitle": "Welcome Page Settings",
"WelcomePageTitle": "Welcome page title",
"GreetingTitle": "Title",
"SetDefaultTitle": "Set default title",
"RestoreDefaultButton": "Restore to Default",
"SuccessfullySaveGreetingSettingsMessage": "Welcome Page settings have been successfully saved",
"LogoSettings": "Portal Logo Settings",
"LogoUploadRecommendation": "We recommended that you use images in <1>PNG</1> format with transparent background",
"CompanyNameForCanvasLogo": "Company name",
"UseAsLogoButton": "Use as logo",
"LogoLightSmall": "Logo for the portal header",
"LogoDark": "Logo for the About/Login page",
"LogoFavicon": "Favicon",
"LogoDocsEditor": "Logo for the editors header",
"ChangeLogoButton": "Change Logo",
"BrowserNoCanvasSupport": "Your browser does not support the HTML5 canvas tag.",
"AccessRightsChangeOwnerText": "To change the Portal owner please choose the Name of the new Portal owner below.",
"ChooseOwner": "Choose owner",
"DnsChangeMsg": "A link to confirm the operation has been sent to {{email}} (the email address of the portal owner).",
"AccessRightsChangeOwnerConfirmText": "Changes will be applied after the confirmation via email.",
"NotFoundTitle": "No results matching your search could be found",
"NotFoundDescription": "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.",
"ClearButton": "Reset filter",
"ProductUserOpportunities": "View profiles and groups",
"LearnMore": "Learn more...",
"AccessRightsChangeOwnerButtonText": "Change portal owner",
"PortalOwner": "Portal Owner",
"AccessRightsOwnerCan": "Portal owner can",
"AccessRightsOwnerOpportunities": "Do the same as module administrators|Appoint module administrators|Set modules access rights|Manage portal configuration|Manage user accounts|Change portal owner|Backup portal data|Deactivate or delete portal",
"AdminSettings": "Administrators",
"ProjectsProduct": "Projects",
"CrmProduct": "CRM",
"CommunityProduct": "Community",
"People": "People",
"Mail": "Mail",
"AccessRightsFullAccess": "Full access",
"DocumentsProduct": "Documents",
"AccessRightsAccessToProduct": "Access to {{product}} module is given to",
"AccessRightsProductUsersCan": "{{category}} users can",
"AccessRightsDisabledProduct": "{{module}} module is disabled and is not shown on the portal. To enable it, refer to the Modules &amp; Tools section of the Portal Settings",
"AccessRightsAllUsers": "All {{users}}",
"AccessRightsUsersFromList": "{{users}} from the list",
"Employees": "users",
"StudioTimeLanguageSettings": "Language and Time Zone Settings",
"Language": "Language",
"TimeZone": "Time Zone",
"SaveButton": "Save",
"CancelButton": "Cancel",
"SuccessfullySaveSettingsMessage": "Settings have been successfully updated",
"NotFoundLanguage": "In case you cannot find your language in the list of the available ones, feel free to write to us at <1>{{supportEmail}}</1> to take part in the translation and get up to 1 year free of charge.",
"Settings": "Settings",
"PreviousPage": "Previous",
"NextPage": "Next",
"ManagementCategoryCommon": "Common",
"Customization": "Customization",
"ProductsAndInstruments": "Modules & tools",
"WhiteLabel": "White label",
"ManagementCategorySecurity": "Security",
"PortalSecurity": "Portal Access",
"AccessRights": "Access Rights",
"LoginHistoryNav": "Login History",
"AuditTrailNav": "Audit Trail",
"DataManagement": "Data Management",
"Migration": "Migration",
"Backup": "Backup",
"DeactivationDeletionPortal": "Portal Deactivation/Deletion",
"ManagementCategoryIntegration": "Integration",
"ThirdPartyAuthorization": "Third Party Authorization",
"SmtpSettings": "SMTP Settings",
"ManagementCategoryStatistic": "Statistics",
"LoadingProcessing": "Loading...",
"LoadingDescription": "Please wait...",
"GreetingSettingsTitle": "Welcome Page Settings",
"WelcomePageTitle": "Welcome page title",
"GreetingTitle": "Title",
"SetDefaultTitle": "Set default title",
"RestoreDefaultButton": "Restore to Default",
"SuccessfullySaveGreetingSettingsMessage": "Welcome Page settings have been successfully saved",
"LogoSettings": "Portal Logo Settings",
"LogoUploadRecommendation": "We recommended that you use images in <1>PNG</1> format with transparent background",
"CompanyNameForCanvasLogo": "Company name",
"UseAsLogoButton": "Use as logo",
"LogoLightSmall": "Logo for the portal header",
"LogoDark": "Logo for the About/Login page",
"LogoFavicon": "Favicon",
"LogoDocsEditor": "Logo for the editors header",
"ChangeLogoButton": "Change Logo",
"BrowserNoCanvasSupport": "Your browser does not support the HTML5 canvas tag.",
"AccessRightsChangeOwnerText": "To change the Portal owner please choose the Name of the new Portal owner below.",
"ChooseOwner": "Choose owner",
"DnsChangeMsg": "A link to confirm the operation has been sent to {{email}} (the email address of the portal owner).",
"AccessRightsChangeOwnerConfirmText": "Changes will be applied after the confirmation via email.",
"NotFoundTitle": "No results matching your search could be found",
"NotFoundDescription": "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.",
"ClearButton": "Reset filter",
"ProductUserOpportunities": "View profiles and groups",
"LearnMore": "Learn more...",
"AccessRightsChangeOwnerButtonText": "Change portal owner",
"ProjectsUserCapabilityView": "View projects and take part in discussions",
"ProjectsUserCapabilityCreate": "Create and edit milestones, tasks, discussions, documents",
"ProjectsUserCapabilityTrack": "Track time for tasks, generate reports",
"ProjectsUserCapabilityForm": "Form a project team and set access rights",
"CRMUserCapabilityCreate": "Create a contact, task, case, opportunity with a possibility to limit access to them",
"CRMUserCapabilityEdit": "Edit a contact, task, case, opportunity with the access rights set up",
"CommunityUserCapability": "Create and edit milestones, tasks, discussions, documents",
"Sample": "Sample",
"ManageOwnMailAccounts": "Manage own mail accounts, receive and send letters",
"ManageOwnMailSettings": "Manage own Mail settings",
"ManageTheTagsAndAddressBook": "Manage the tags and address book",
"Culture_en": "English (United Kingdom)",
"Culture_en-US": "English (United States)",
"Culture_ru-RU": "Russian (Russia)",
"CountPerPage": "{{count}} per page",
"PageOfTotalPage": "{{page}} of {{totalPage}}",
"ByFirstNameSorting": "By first name",
"ByLastNameSorting": "By last name",
"OwnerSettings": "Owner settings",
"AdminsSettings": "Admins settings",
"SetPeopleAdmin": "Set people admin",
"SetPortalAdmin": "Set portal admin",
"PeopleAdmin": "People module admin",
"DirectionAscLabel":"A-Z",
"DirectionDescLabel":"Z-A",
"MeLabel": "Me",
"OrganizationName": "ONLYOFFICE",
"YouHaveUnsavedChanges": "You have unsaved changes",
"CustomTitles": "Custom titles",
"LanguageAndTimeZoneSettingsDescription": "Language and time zone settings is a way to change the language of the whole portal for all portal users and to configure the time zone so that all the events of the portal will be shown with the correct date and time.",
"CustomTitlesSettingsDescription": "Custom welcome page title will be displayed on the welcome page of your portal. The same name is also used for the From field of your portal email notifications. Custom domain name is a way to set an alternative URL for your portal. Custom portal name will appear next to the onlyoffice.com/onlyoffice.eu portal address."
}
"ProjectsUserCapabilityView": "View projects and take part in discussions",
"ProjectsUserCapabilityCreate": "Create and edit milestones, tasks, discussions, documents",
"ProjectsUserCapabilityTrack": "Track time for tasks, generate reports",
"ProjectsUserCapabilityForm": "Form a project team and set access rights",
"CRMUserCapabilityCreate": "Create a contact, task, case, opportunity with a possibility to limit access to them",
"CRMUserCapabilityEdit": "Edit a contact, task, case, opportunity with the access rights set up",
"CommunityUserCapability": "Create and edit milestones, tasks, discussions, documents",
"Sample": "Sample",
"ManageOwnMailAccounts": "Manage own mail accounts, receive and send letters",
"ManageOwnMailSettings": "Manage own Mail settings",
"ManageTheTagsAndAddressBook": "Manage the tags and address book",
"Culture_en": "English (United Kingdom)",
"Culture_en-US": "English (United States)",
"Culture_ru-RU": "Russian (Russia)",
"CountPerPage": "{{count}} per page",
"PageOfTotalPage": "{{page}} of {{totalPage}}",
"ByFirstNameSorting": "By first name",
"ByLastNameSorting": "By last name",
"OwnerSettings": "Owner settings",
"AdminsSettings": "Admins settings",
"SetPeopleAdmin": "Set people admin",
"SetPortalAdmin": "Set portal admin",
"PeopleAdmin": "People module admin",
"DirectionAscLabel": "A-Z",
"DirectionDescLabel": "Z-A",
"MeLabel": "Me",
"YouHaveUnsavedChanges": "You have unsaved changes",
"CustomTitles": "Custom titles",
"LanguageAndTimeZoneSettingsDescription": "Language and time zone settings is a way to change the language of the whole portal for all portal users and to configure the time zone so that all the events of the portal will be shown with the correct date and time.",
"CustomTitlesSettingsDescription": "Custom welcome page title will be displayed on the welcome page of your portal. The same name is also used for the From field of your portal email notifications. Custom domain name is a way to set an alternative URL for your portal. Custom portal name will appear next to the onlyoffice.com/onlyoffice.eu portal address."
}

View File

@ -43,7 +43,7 @@
"SmtpSettings": "Настройки SMTP",
"ManagementCategoryStatistic": "Статистика",
"LoadingProcessing": "Загрузка...",
"LoadingDescription": "Пожалуйста подождите...",
"LoadingDescription": "Пожалуйста подождите...",
"GreetingSettingsTitle": "Настройки страницы приветствия",
"WelcomePageTitle": "Заголовок страницы приветствия",
"GreetingTitle": "Заголовок",
@ -67,10 +67,9 @@
"NotFoundTitle": "Результатов, соответствующих заданным критериям, не найдено",
"NotFoundDescription": "В данном разделе нет людей, соответствующих фильтру. Пожалуйста, выберите другие параметры или очистите фильтр, чтобы просмотреть всех людей в этом разделе.",
"ClearButton": "Сбросить фильтр",
"LearnMore": "Подробнее...",
"LearnMore": "Подробнее...",
"AccessRightsChangeOwnerButtonText": "Сменить владельца портала",
"ProductUserOpportunities": "Просматривать профили и группы",
"AccessRightsAccessToProduct": "Доступ к модулю {{product}} предоставлен для",
"ProjectsUserCapabilityView": "Просматривать проекты и участвовать в обсуждениях",
@ -96,12 +95,11 @@
"SetPeopleAdmin": "Установить администратора модуля Люди",
"SetPortalAdmin": "Установить администратора портала",
"PeopleAdmin": "Администратор модуля Люди",
"DirectionAscLabel":"А-Я",
"DirectionDescLabel":"Я-А",
"DirectionAscLabel": "А-Я",
"DirectionDescLabel": "Я-А",
"MeLabel": "Я",
"OrganizationName": "ONLYOFFICE",
"YouHaveUnsavedChanges": "Имеются несохраненные изменения",
"CustomTitles": "Пользовательские заголовки",
"LanguageAndTimeZoneSettingsDescription": "Настройки языка и часового пояса - это способ изменить язык всего портала для всех пользователей портала и настроить часовой пояс, чтобы все события портала отображались с правильной датой и временем.",
"CustomTitlesSettingsDescription": "Пользовательский заголовок страницы приветствия будет отображаться на странице приветствия вашего портала. Это же имя используется для поля 'От' вашего электронного уведомления портала. Пользовательское доменное имя - это способ установить альтернативный URL-адрес для вашего портала. Пользовательское имя портала будет отображаться рядом с адресом портала onlyoffice.com/onlyoffice.eu."
}
}

View File

@ -80,33 +80,35 @@ const SettingsContainer = ({
<Text fontSize="13px">{t('language')}</Text>
<ComboBox
className="drop-down"
options={languages}
selectedOption={{
key: selectLanguage.key,
label: selectLanguage.label
}}
noBorder={true}
scaled={false}
size='content'
dropDownMaxHeight={300}
onSelect={onSelectLanguageHandler}
/>
className="drop-down"
options={languages}
selectedOption={{
key: selectLanguage.key,
label: selectLanguage.label
}}
noBorder={true}
scaled={false}
size='content'
dropDownMaxHeight={300}
onSelect={onSelectLanguageHandler}
textOverflow={true}
/>
<Text className="title" fontSize="13px">{t('timezone')}</Text>
<ComboBox
className="drop-down"
options={timezones}
selectedOption={{
key: selectTimezone.key,
label: selectTimezone.label
}}
noBorder={true}
dropDownMaxHeight={300}
scaled={false}
size='content'
onSelect={onSelectTimezoneHandler}
/>
className="drop-down"
options={timezones}
selectedOption={{
key: selectTimezone.key,
label: selectTimezone.label
}}
noBorder={true}
dropDownMaxHeight={300}
scaled={false}
size='content'
onSelect={onSelectTimezoneHandler}
textOverflow={true}
/>
</StyledContainer>
);

View File

@ -1627,9 +1627,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "14.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
version "14.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.1.tgz#cc323bad8e8a533d4822f45ce4e5326f36e42177"
integrity sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==
"@types/parse-json@^4.0.0":
version "4.0.0"
@ -1865,9 +1865,9 @@
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
abab@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
abbrev@1:
version "1.1.1"
@ -2189,7 +2189,7 @@ asap@~2.0.6:
screenfull "^5.0.2"
"asc-web-components@file:../../packages/asc-web-components":
version "1.0.431"
version "1.0.436"
dependencies:
email-addresses "^3.1.0"
html-to-react "^1.4.2"
@ -4226,9 +4226,9 @@ ejs@^2.6.1:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.564:
version "1.3.564"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz#e9c319ae437b3eb8bbf3e3bae4bead5a21945961"
integrity sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==
version "1.3.566"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.566.tgz#e373876bb63e5c9bbcbe1b48cbb2db000f79bf88"
integrity sha512-V0fANdGN7waOE0tvCDhjf1vqPRevG3eo0asYm42c4t1qmZSunlnUuWQDxglUi9wDpbKQlGIttMJ+2DYpRwvYRA==
elliptic@^6.5.3:
version "6.5.3"
@ -5425,7 +5425,7 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-symbols@^1.0.0, has-symbols@^1.0.1:
has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
@ -6025,9 +6025,9 @@ is-buffer@^1.0.2, is-buffer@^1.1.5:
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.4, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d"
integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==
is-ci@^2.0.0:
version "2.0.0"
@ -7868,7 +7868,7 @@ object-is@^1.0.1:
define-properties "^1.1.3"
es-abstract "^1.17.5"
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@ -7886,14 +7886,14 @@ object-visit@^1.0.0:
isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
version "4.1.1"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.0"
has-symbols "^1.0.1"
object-keys "^1.1.1"
object.entries@^1.1.0, object.entries@^1.1.1:
version "1.1.2"

View File

@ -11,7 +11,8 @@ class SortComboBox extends React.Component {
const { sortDirection } = props;
this.state = {
sortDirection
sortDirection,
opened: false
}
this.combobox = React.createRef();
@ -28,6 +29,7 @@ class SortComboBox extends React.Component {
onChangeSortId = (e) => {
const { onChangeSortId } = this.props;
typeof onChangeSortId === 'function' && onChangeSortId(e.target.value);
this.setState({ opened: !this.state.opened });
}
onChangeView = (e) => {
@ -38,7 +40,7 @@ class SortComboBox extends React.Component {
onChangeSortDirection = (e) => {
const sortDirection = +e.target.value;
const { onChangeSortDirection } = this.props;
this.setState({ sortDirection });
this.setState({ sortDirection, opened: !this.state.opened });
typeof onChangeSortDirection === 'function' && onChangeSortDirection(sortDirection);
}
shouldComponentUpdate(nextProps, nextState) {
@ -58,10 +60,17 @@ class SortComboBox extends React.Component {
}
return (!isEqual(this.props, nextProps) || !isEqual(this.state, nextState));
}
onToggleAction = () => {
this.setState({
opened: !this.state.opened
});
}
render() {
const { options, directionAscLabel, directionDescLabel, isDisabled,
selectedOption, viewAs } = this.props;
const { sortDirection } = this.state;
const { sortDirection, opened } = this.state;
let settingsArray = options.filter(item => {
item.value = item.key
@ -126,6 +135,8 @@ class SortComboBox extends React.Component {
);
return (
<ComboBox
opened={opened}
toggleAction={this.onToggleAction}
advancedOptions={advancedOptions}
className='styled-sort-combobox'
directionX="right"

View File

@ -177,10 +177,7 @@ class Form extends Component {
} else {
this.setState({ isLoading: true });
sendInstructionsToChangePassword(this.state.email)
.then(
res => toastr.success(res),
message => toastr.error(message)
)
.then(res => toastr.success(res), message => toastr.error(message))
.finally(this.onDialogClose());
}
};
@ -197,7 +194,7 @@ class Form extends Component {
onSubmit = () => {
const { errorText, identifier, password } = this.state;
const { login, setIsLoaded, history, homepage } = this.props;
const { login, setIsLoaded, homepage } = this.props;
errorText && this.setState({ errorText: "" });
let hasError = false;
@ -222,7 +219,6 @@ class Form extends Component {
login(userName, pass)
.then(() => {
setIsLoaded(true);
//history.push(homepage);
window.open(homepage, "_self");
})
.catch(error => {
@ -231,10 +227,10 @@ class Form extends Component {
};
componentDidMount() {
const { match, t } = this.props;
const { match, t, organizationName } = this.props;
const { error, confirmedEmail } = match.params;
document.title = `${t("Authorization")} ${t("OrganizationName")}`;
document.title = `${t("Authorization")} ${organizationName}`;
error && this.setState({ errorText: error });
confirmedEmail && this.setState({ identifier: confirmedEmail });
@ -420,7 +416,9 @@ Form.propTypes = {
t: PropTypes.func.isRequired,
i18n: PropTypes.object.isRequired,
language: PropTypes.string.isRequired,
socialButtons: PropTypes.array
socialButtons: PropTypes.array,
organizationName: PropTypes.string,
homepage: PropTypes.string
};
Form.defaultProps = {
@ -464,15 +462,26 @@ LoginForm.propTypes = {
};
function mapStateToProps(state) {
const { isLoaded, user, settings } = state.auth;
const {
greetingSettings,
enabledJoin,
organizationName,
homepage,
culture
} = settings;
return {
isLoaded: state.auth.isLoaded,
language: state.auth.user.cultureName || state.auth.settings.culture,
greetingTitle: state.auth.settings.greetingSettings,
enabledJoin: state.auth.settings.enabledJoin,
homepage: state.auth.settings.homepage
isLoaded,
enabledJoin,
organizationName,
homepage,
language: user.cultureName || culture,
greetingTitle: greetingSettings
};
}
export default connect(mapStateToProps, { login, setIsLoaded })(
withRouter(LoginForm)
);
export default connect(
mapStateToProps,
{ login, setIsLoaded }
)(withRouter(LoginForm));

View File

@ -26,6 +26,5 @@
"CookieSettingsTitle": "Session Lifetime",
"Authorization": "Authorization",
"Or": "OR",
"Register": "Register",
"OrganizationName": "ONLYOFFICE"
}
"Register": "Register"
}

View File

@ -26,6 +26,5 @@
"CookieSettingsTitle": "Время жизни сессии",
"Authorization": "Авторизация",
"Or": "ИЛИ",
"Register": "Регистрация",
"OrganizationName": "ONLYOFFICE"
}
"Register": "Регистрация"
}

View File

@ -42,6 +42,7 @@ const initialState = {
dateTimePattern: "DD, mm dd, yy h:mm:ss tt",
timePattern: "h:mm tt"
},
organizationName: "ONLYOFFICE",
greetingSettings: "Web Office Applications",
enableAdmMess: false,
urlLicense: "https://gnu.org/licenses/gpl-3.0.html",

View File

@ -2427,9 +2427,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "14.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
version "14.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.1.tgz#cc323bad8e8a533d4822f45ce4e5326f36e42177"
integrity sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -2761,9 +2761,9 @@
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
abab@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
accepts@~1.3.7:
version "1.3.7"
@ -3121,7 +3121,7 @@ arrify@^1.0.1:
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
"asc-web-components@file:../../packages/asc-web-components":
version "1.0.431"
version "1.0.436"
dependencies:
email-addresses "^3.1.0"
html-to-react "^1.4.2"
@ -5372,9 +5372,9 @@ ejs@^2.7.4:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.564:
version "1.3.564"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz#e9c319ae437b3eb8bbf3e3bae4bead5a21945961"
integrity sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==
version "1.3.566"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.566.tgz#e373876bb63e5c9bbcbe1b48cbb2db000f79bf88"
integrity sha512-V0fANdGN7waOE0tvCDhjf1vqPRevG3eo0asYm42c4t1qmZSunlnUuWQDxglUi9wDpbKQlGIttMJ+2DYpRwvYRA==
element-resize-detector@^1.2.1:
version "1.2.1"
@ -6621,7 +6621,7 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-symbols@^1.0.0, has-symbols@^1.0.1:
has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
@ -7222,9 +7222,9 @@ is-buffer@^1.0.2, is-buffer@^1.1.5:
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d"
integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==
is-ci@^2.0.0:
version "2.0.0"
@ -9148,7 +9148,7 @@ object-is@^1.0.1, object-is@^1.0.2, object-is@^1.1.2:
define-properties "^1.1.3"
es-abstract "^1.17.5"
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@ -9161,14 +9161,14 @@ object-visit@^1.0.0:
isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
version "4.1.1"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.0"
has-symbols "^1.0.1"
object-keys "^1.1.1"
object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2:
version "1.1.2"

View File

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

View File

@ -97,7 +97,8 @@ class ComboBox extends React.Component {
noBorder,
scaledOptions,
displayType,
toggleAction } = this.props;
toggleAction,
textOverflow } = this.props;
const { isOpen, selectedOption } = this.state;
const dropDownMaxHeightProp = dropDownMaxHeight
@ -156,6 +157,7 @@ class ComboBox extends React.Component {
? advancedOptions
: options.map((option) =>
<DropDownItem {...option}
textOverflow={textOverflow}
key={option.key}
disabled={
option.disabled
@ -189,7 +191,8 @@ ComboBox.propTypes = {
selectedOption: PropTypes.object.isRequired,
size: PropTypes.oneOf(['base', 'middle', 'big', 'huge', 'content']),
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
toggleAction: PropTypes.func
toggleAction: PropTypes.func,
textOverflow: PropTypes.bool
}
ComboBox.defaultProps = {

View File

@ -25,7 +25,7 @@ const disabledAndHeaderStyle = css`
`;
const StyledDropdownItem = styled.div`
display: flex;
display:${props => props.textOverflow ? "block" : "flex"};
width: 100%;
max-width: 500px;
border: 0px;
@ -88,6 +88,7 @@ const StyledDropdownItem = styled.div`
`;
const IconWrapper = styled.div`
display:flex;
width: 16px;
margin-right: 8px;
line-height: 14px;
@ -126,7 +127,8 @@ DropDownItem.propTypes = {
children: PropTypes.any,
className: PropTypes.string,
id: PropTypes.string,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
textOverflow: PropTypes.bool
};
DropDownItem.defaultProps = {
@ -135,7 +137,8 @@ DropDownItem.defaultProps = {
tabIndex: -1,
label: '',
disabled: false,
noHover: false
noHover: false,
textOverflow: false
};
export default DropDownItem

View File

@ -50,7 +50,7 @@ const StyledRowContent = styled.div`
display: inline-flex;
${props => !props.disableSideInfo
&& (props.widthProp && (props.widthProp < size.tablet))
&& (props.widthProp && (props.widthProp < size.tablet)) || props.isMobile
? `${containerTabletStyle}`
: `
@media ${tablet} {
@ -70,7 +70,7 @@ const MainContainerWrapper = styled.div`
min-width: 140px;
${props => !props.disableSideInfo
&& (props.widthProp && (props.widthProp < size.tablet))
&& (props.widthProp && (props.widthProp < size.tablet)) || props.isMobile
? `${mainWrapperTabletStyle}`
: `
@media ${tablet} {
@ -84,7 +84,7 @@ const MainContainer = styled.div`
margin-right: 8px;
max-width: 86%;
${props => props.widthProp && (props.widthProp < size.tablet)
${props => props.widthProp && (props.widthProp < size.tablet) || props.isMobile
? `${mainContainerTabletStyle}`
: `
@media ${tablet} {
@ -101,7 +101,7 @@ const MainIcons = styled.div`
const SideContainerWrapper = styled.div`
${commonCss};
${props => props.widthProp && (props.widthProp < size.tablet)
${props => props.widthProp && (props.widthProp < size.tablet) || props.isMobile
? `${truncateCss}`
: `
@media ${tablet} {
@ -121,7 +121,7 @@ const SideContainerWrapper = styled.div`
color: ${props => props.color && props.color};
${props => !props.disableSideInfo
&& (props.widthProp && (props.widthProp < size.tablet))
&& (props.widthProp && (props.widthProp < size.tablet)) || props.isMobile
? `display: none;`
: `
@media ${tablet} {
@ -133,7 +133,7 @@ ${props => !props.disableSideInfo
const TabletSideInfo = styled.div`
display: none;
${props => props.widthProp && (props.widthProp < size.tablet)
${props => props.widthProp && (props.widthProp < size.tablet) || props.isMobile
? `${sideInfoTabletStyle}`
: `
@media ${tablet} {
@ -160,7 +160,7 @@ const getSideInfo = content => {
const RowContent = props => {
//console.log("RowContent render");
const { children, disableSideInfo, id, className, style, sideColor, onClick, widthProp } = props;
const { children, disableSideInfo, id, className, style, sideColor, onClick, widthProp, isMobile } = props;
const sideInfo = getSideInfo(children);
const mainContainerWidth = children[0].props && children[0].props.containerWidth;
@ -173,15 +173,18 @@ const RowContent = props => {
onClick={onClick}
style={style}
widthProp={widthProp}
isMobile={isMobile}
>
<MainContainerWrapper
disableSideInfo={disableSideInfo}
mainContainerWidth={mainContainerWidth}
widthProp={widthProp}
isMobile={isMobile}
>
<MainContainer
className="rowMainContainer"
widthProp={widthProp}
isMobile={isMobile}
>
{children[0]}
</MainContainer>
@ -200,6 +203,7 @@ const RowContent = props => {
containerWidth={element.props && element.props.containerWidth}
containerMinWidth={element.props && element.props.containerMinWidth}
widthProp={widthProp}
isMobile={isMobile}
>
{element}
</SideContainerWrapper>
@ -210,6 +214,7 @@ const RowContent = props => {
<TabletSideInfo
color={sideColor}
widthProp={widthProp}
isMobile={isMobile}
>
{sideInfo}
</TabletSideInfo>
@ -227,6 +232,7 @@ RowContent.propTypes = {
sideColor: PropTypes.string,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
widthProp: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
isMobile: PropTypes.bool
};
RowContent.defaultProps = {

View File

@ -2420,9 +2420,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node@*":
version "14.6.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
version "14.10.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.1.tgz#cc323bad8e8a533d4822f45ce4e5326f36e42177"
integrity sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -2754,9 +2754,9 @@
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
abab@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
version "2.0.5"
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
accepts@~1.3.7:
version "1.3.7"
@ -5335,9 +5335,9 @@ ejs@^2.7.4:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.564:
version "1.3.564"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz#e9c319ae437b3eb8bbf3e3bae4bead5a21945961"
integrity sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg==
version "1.3.566"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.566.tgz#e373876bb63e5c9bbcbe1b48cbb2db000f79bf88"
integrity sha512-V0fANdGN7waOE0tvCDhjf1vqPRevG3eo0asYm42c4t1qmZSunlnUuWQDxglUi9wDpbKQlGIttMJ+2DYpRwvYRA==
element-resize-detector@^1.2.1:
version "1.2.1"
@ -6567,7 +6567,7 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-symbols@^1.0.0, has-symbols@^1.0.1:
has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
@ -7142,9 +7142,9 @@ is-buffer@^1.0.2, is-buffer@^1.1.5:
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.1.tgz#4d1e21a4f437509d25ce55f8184350771421c96d"
integrity sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==
is-ci@^2.0.0:
version "2.0.0"
@ -9061,7 +9061,7 @@ object-is@^1.0.1, object-is@^1.0.2, object-is@^1.1.2:
define-properties "^1.1.3"
es-abstract "^1.17.5"
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@ -9074,14 +9074,14 @@ object-visit@^1.0.0:
isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
version "4.1.1"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd"
integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
define-properties "^1.1.3"
es-abstract "^1.18.0-next.0"
has-symbols "^1.0.1"
object-keys "^1.1.1"
object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2:
version "1.1.2"