added Routing, refactoring
This commit is contained in:
parent
b4d837320e
commit
1e6a2c37dc
@ -22,7 +22,7 @@ const App = ({ settings }) => {
|
|||||||
>
|
>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Redirect exact from="/" to={`${homepage}`} />
|
<Redirect exact from="/" to={`${homepage}`} />
|
||||||
<PrivateRoute exact path={[homepage, `${homepage}/filter`]} component={withStudioLayout(Home)} />
|
<PrivateRoute exact path={[homepage, `${homepage}/filter`, `${homepage}/settings/:setting`]} component={withStudioLayout(Home)} />
|
||||||
<PrivateRoute exact path={`${homepage}/doceditor`} component={DocEditor} />
|
<PrivateRoute exact path={`${homepage}/doceditor`} component={DocEditor} />
|
||||||
<PrivateRoute exact path={`${homepage}/:fileId/history`} component={withStudioLayout(VersionHistory)} />
|
<PrivateRoute exact path={`${homepage}/:fileId/history`} component={withStudioLayout(VersionHistory)} />
|
||||||
<PublicRoute exact path={["/login","/login/error=:error", "/login/confirmed-email=:confirmedEmail"]} component={Login} />
|
<PublicRoute exact path={["/login","/login/error=:error", "/login/confirmed-email=:confirmedEmail"]} component={Login} />
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { TreeMenu, TreeNode, Icons, toastr, utils, Badge } from "asc-web-components";
|
import { TreeMenu, TreeNode, Icons } from "asc-web-components";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { api, constants } from "asc-web-common";
|
import { history, utils } from "asc-web-common";
|
||||||
const { files } = api;
|
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||||
const { FolderType, ShareAccessRights } = constants;
|
import { createI18N } from "../../../helpers/i18n";
|
||||||
|
|
||||||
|
const i18n = createI18N({
|
||||||
|
page: "SettingsTree",
|
||||||
|
localesPath: "pages/Settings"
|
||||||
|
})
|
||||||
|
|
||||||
|
const { changeLanguage } = utils;
|
||||||
|
|
||||||
const StyledTreeMenu = styled(TreeMenu)`
|
const StyledTreeMenu = styled(TreeMenu)`
|
||||||
margin-top: 20px !important;
|
margin-top: 20px !important;
|
||||||
@ -17,16 +23,12 @@ const StyledTreeMenu = styled(TreeMenu)`
|
|||||||
background: #DFE2E3 !important;
|
background: #DFE2E3 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rc-tree-switcher.rc-tree-switcher-noop {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-node {
|
.settings-node {
|
||||||
margin-left: 9px !important;
|
margin-left: 8px !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
class TreeSettings extends React.Component {
|
class PureTreeSettings extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -36,6 +38,9 @@ class TreeSettings extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switcherIcon = (obj) => {
|
switcherIcon = (obj) => {
|
||||||
|
if (obj.isLeaf) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if(obj.expanded) {
|
if(obj.expanded) {
|
||||||
return <Icons.ExpanderDownIcon size="scale" isfill color="dimgray" />;
|
return <Icons.ExpanderDownIcon size="scale" isfill color="dimgray" />;
|
||||||
} else {
|
} else {
|
||||||
@ -43,8 +48,9 @@ class TreeSettings extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelect = (e, r) => {
|
onSelect = (section) => {
|
||||||
console.log(e, r)
|
const path = section[0];
|
||||||
|
return history.push(`/products/files/settings/${path}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTreeNode = () => {
|
renderTreeNode = () => {
|
||||||
@ -53,28 +59,31 @@ class TreeSettings extends React.Component {
|
|||||||
<TreeNode
|
<TreeNode
|
||||||
id="settings"
|
id="settings"
|
||||||
key="settings"
|
key="settings"
|
||||||
title={t('settingsMenuTitle')}
|
title={t('treeSettingsMenuTitle')}
|
||||||
|
isLeaf={false}
|
||||||
icon={<Icons.SettingsIcon size="scale" isfill color="dimgray" />}
|
icon={<Icons.SettingsIcon size="scale" isfill color="dimgray" />}
|
||||||
>
|
>
|
||||||
<TreeNode
|
<TreeNode
|
||||||
className="settings-node"
|
className="settings-node"
|
||||||
id='common-settings'
|
id='common-settings'
|
||||||
key='common-settings'
|
key='common-settings'
|
||||||
title={t('settingCommonSettings')}
|
isLeaf={true}
|
||||||
|
title={t('treeSettingsCommonSettings')}
|
||||||
></TreeNode>
|
/>
|
||||||
<TreeNode
|
<TreeNode
|
||||||
className="settings-node"
|
className="settings-node"
|
||||||
id='admin-settings'
|
id='admin-settings'
|
||||||
key='admin-settings'
|
key='admin-settings'
|
||||||
title={t('settingsAdminSettings')}
|
isLeaf={true}
|
||||||
></TreeNode>
|
title={t('treeSettingsAdminSettings')}
|
||||||
|
/>
|
||||||
<TreeNode
|
<TreeNode
|
||||||
className="settings-node"
|
className="settings-node"
|
||||||
id='connected-cloud'
|
id='connected-clouds'
|
||||||
key='connected-cloud'
|
key='connected-clouds'
|
||||||
title={t('settingsConnectedCloud')}
|
isLeaf={true}
|
||||||
></TreeNode>
|
title={t('treeSettingsConnectedCloud')}
|
||||||
|
/>
|
||||||
</TreeNode>
|
</TreeNode>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -86,11 +95,12 @@ class TreeSettings extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledTreeMenu
|
<StyledTreeMenu
|
||||||
|
defaultExpandParent={false}
|
||||||
className="settings-tree-menu"
|
className="settings-tree-menu"
|
||||||
switcherIcon={this.switcherIcon}
|
switcherIcon={this.switcherIcon}
|
||||||
onSelect={this.onSelect}
|
onSelect={this.onSelect}
|
||||||
onClick={()=>console.log('111')}
|
|
||||||
showIcon={true}
|
showIcon={true}
|
||||||
|
onExpand={() => console.log('expand')}
|
||||||
>
|
>
|
||||||
{nodes}
|
{nodes}
|
||||||
</StyledTreeMenu>
|
</StyledTreeMenu>
|
||||||
@ -98,4 +108,15 @@ class TreeSettings extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TreeSettingsContainer = withTranslation()(PureTreeSettings);
|
||||||
|
|
||||||
|
const TreeSettings = props => {
|
||||||
|
changeLanguage(i18n);
|
||||||
|
return (
|
||||||
|
<I18nextProvider i18n={i18n}>
|
||||||
|
<TreeSettingsContainer { ...props } />
|
||||||
|
</I18nextProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default TreeSettings;
|
export default TreeSettings;
|
@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { toastr, utils } from "asc-web-components";
|
import { toastr, utils } from "asc-web-components";
|
||||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
|
||||||
import TreeFolders from "./TreeFolders";
|
import TreeFolders from "./TreeFolders";
|
||||||
import TreeSettings from './TreeSettings';
|
import TreeSettings from './TreeSettings';
|
||||||
import {
|
import {
|
||||||
@ -15,12 +14,8 @@ import {
|
|||||||
import store from "../../../store/store";
|
import store from "../../../store/store";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import { NewFilesPanel } from "../../panels";
|
import { NewFilesPanel } from "../../panels";
|
||||||
import i18n from "../i18n";
|
|
||||||
import { utils as commonUtils } from 'asc-web-common';
|
|
||||||
|
|
||||||
const { changeLanguage } = commonUtils;
|
class ArticleBodyContent extends React.Component {
|
||||||
|
|
||||||
class PureArticleBodyContent extends React.Component {
|
|
||||||
state = {
|
state = {
|
||||||
expandedKeys: this.props.filter.treeFolders,
|
expandedKeys: this.props.filter.treeFolders,
|
||||||
data: this.props.data,
|
data: this.props.data,
|
||||||
@ -59,7 +54,7 @@ class PureArticleBodyContent extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSelect = data => {
|
onSelect = data => {
|
||||||
const { selectedKeys, filter, onLoading } = this.props;
|
const { selectedKeys, filter, onLoading, setSettingsPath } = this.props;
|
||||||
if (selectedKeys[0] !== data[0]) {
|
if (selectedKeys[0] !== data[0]) {
|
||||||
onLoading(true);
|
onLoading(true);
|
||||||
const newFilter = filter.clone();
|
const newFilter = filter.clone();
|
||||||
@ -104,7 +99,6 @@ class PureArticleBodyContent extends React.Component {
|
|||||||
isShare,
|
isShare,
|
||||||
setDragging,
|
setDragging,
|
||||||
onTreeDrop,
|
onTreeDrop,
|
||||||
t
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { showNewFilesPanel, expandedKeys, newFolderId } = this.state;
|
const { showNewFilesPanel, expandedKeys, newFolderId } = this.state;
|
||||||
@ -148,19 +142,12 @@ class PureArticleBodyContent extends React.Component {
|
|||||||
onBadgeClick={this.onShowNewFilesPanel}
|
onBadgeClick={this.onShowNewFilesPanel}
|
||||||
onTreeDrop={onTreeDrop}
|
onTreeDrop={onTreeDrop}
|
||||||
/>
|
/>
|
||||||
<TreeSettings t={t}/>
|
<TreeSettings/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArticleBodyContentContainer = withTranslation()(PureArticleBodyContent);
|
|
||||||
|
|
||||||
const ArticleBodyContent = (props) => {
|
|
||||||
changeLanguage(i18n);
|
|
||||||
return (<I18nextProvider i18n={i18n}><ArticleBodyContentContainer {...props} /></I18nextProvider>);
|
|
||||||
};
|
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
const { treeFolders, selectedFolder, filter, selection, dragging, updateTreeNew } = state.files;
|
const { treeFolders, selectedFolder, filter, selection, dragging, updateTreeNew } = state.files;
|
||||||
const currentFolderId = selectedFolder.id.toString();
|
const currentFolderId = selectedFolder.id.toString();
|
||||||
@ -203,4 +190,4 @@ function mapStateToProps(state) {
|
|||||||
|
|
||||||
export default connect(mapStateToProps, { setFilter, setTreeFolders, setDragItem, setDragging, setNewTreeFilesBadge })(
|
export default connect(mapStateToProps, { setFilter, setTreeFolders, setDragItem, setDragging, setNewTreeFilesBadge })(
|
||||||
ArticleBodyContent
|
ArticleBodyContent
|
||||||
);
|
);
|
@ -6,10 +6,5 @@
|
|||||||
"NewFolder": "New Folder",
|
"NewFolder": "New Folder",
|
||||||
"UploadFiles": "Upload files",
|
"UploadFiles": "Upload files",
|
||||||
"UploadFolder": "Upload folder",
|
"UploadFolder": "Upload folder",
|
||||||
"UploadingLabel": "Uploading files: {{file}} of {{totalFiles}}",
|
"UploadingLabel": "Uploading files: {{file}} of {{totalFiles}}"
|
||||||
|
|
||||||
"settingsMenuTitle": "Settings",
|
|
||||||
"settingCommonSettings": "Common Settings",
|
|
||||||
"settingsAdminSettings": "Admin Settings",
|
|
||||||
"settingsConnectedCloud": "Connected Clouds"
|
|
||||||
}
|
}
|
@ -6,10 +6,5 @@
|
|||||||
"NewFolder": "Новая папка",
|
"NewFolder": "Новая папка",
|
||||||
"UploadFiles": "Загрузить файлы",
|
"UploadFiles": "Загрузить файлы",
|
||||||
"UploadFolder": "Загрузить папку",
|
"UploadFolder": "Загрузить папку",
|
||||||
"UploadingLabel": "Загружено файлов: {{file}} из {{totalFiles}}",
|
"UploadingLabel": "Загружено файлов: {{file}} из {{totalFiles}}"
|
||||||
|
|
||||||
"settingsMenuTitle": "Настройки",
|
|
||||||
"settingCommonSettings": "Общие настройки",
|
|
||||||
"settingsAdminSettings": "Настройки администратора",
|
|
||||||
"settingsConnectedCloud": "Подключенные облака"
|
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { withRouter } from "react-router";
|
import { withRouter, Route, Switch } from "react-router";
|
||||||
import { RequestLoader, Checkbox, toastr } from "asc-web-components";
|
import { RequestLoader, Checkbox, toastr } from "asc-web-components";
|
||||||
import { PageLayout, utils } from "asc-web-common";
|
import { PageLayout, utils, history, PrivateRoute } from "asc-web-common";
|
||||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
ArticleBodyContent,
|
ArticleBodyContent,
|
||||||
@ -16,6 +16,7 @@ import {
|
|||||||
SectionHeaderContent,
|
SectionHeaderContent,
|
||||||
SectionPagingContent
|
SectionPagingContent
|
||||||
} from "./Section";
|
} from "./Section";
|
||||||
|
import Settings from '../Settings';
|
||||||
import {
|
import {
|
||||||
clearProgressData,
|
clearProgressData,
|
||||||
deselectFile,
|
deselectFile,
|
||||||
@ -399,6 +400,10 @@ class PureHome extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSelectSettings = (data) => {
|
||||||
|
console.log(data);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
isHeaderVisible,
|
isHeaderVisible,
|
||||||
@ -478,39 +483,51 @@ class PureHome extends React.Component {
|
|||||||
onTreeDrop={this.onDrop}
|
onTreeDrop={this.onDrop}
|
||||||
/>
|
/>
|
||||||
</PageLayout.ArticleBody>
|
</PageLayout.ArticleBody>
|
||||||
|
<PageLayout.SectionHeader>
|
||||||
|
<Switch>
|
||||||
|
<PrivateRoute path="/products/files/filter" component={() => (
|
||||||
|
<SectionHeaderContent
|
||||||
|
isHeaderVisible={isHeaderVisible}
|
||||||
|
isHeaderIndeterminate={isHeaderIndeterminate}
|
||||||
|
isHeaderChecked={isHeaderChecked}
|
||||||
|
onCheck={this.onSectionHeaderContentCheck}
|
||||||
|
onSelect={this.onSectionHeaderContentSelect}
|
||||||
|
onClose={this.onClose}
|
||||||
|
onLoading={this.onLoading}
|
||||||
|
isLoading={isLoading}
|
||||||
|
loopFilesOperations={this.loopFilesOperations}
|
||||||
|
/>
|
||||||
|
)} />
|
||||||
|
</Switch>
|
||||||
|
</PageLayout.SectionHeader>
|
||||||
|
|
||||||
|
<PageLayout.SectionFilter>
|
||||||
|
<Switch>
|
||||||
|
<PrivateRoute path="/products/files/filter" component={() => (
|
||||||
|
<SectionFilterContent onLoading={this.onLoading} />
|
||||||
|
)} />
|
||||||
|
</Switch>
|
||||||
|
</PageLayout.SectionFilter>
|
||||||
|
|
||||||
|
<PageLayout.SectionBody>
|
||||||
|
<Switch>
|
||||||
|
<PrivateRoute exact path="/products/files/settings/:setting" component={Settings} />
|
||||||
|
<PrivateRoute path="/products/files/filter" component={() => (
|
||||||
|
<SectionBodyContent
|
||||||
|
selected={selected}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onLoading={this.onLoading}
|
||||||
|
onChange={this.onRowChange}
|
||||||
|
loopFilesOperations={this.loopFilesOperations}
|
||||||
|
onDropZoneUpload={this.onDrop}
|
||||||
|
/>
|
||||||
|
)} />
|
||||||
|
</Switch>
|
||||||
|
</PageLayout.SectionBody>
|
||||||
|
|
||||||
<PageLayout.SectionHeader>
|
<PageLayout.SectionPaging>
|
||||||
<SectionHeaderContent
|
<SectionPagingContent onLoading={this.onLoading} />
|
||||||
isHeaderVisible={isHeaderVisible}
|
</PageLayout.SectionPaging>
|
||||||
isHeaderIndeterminate={isHeaderIndeterminate}
|
|
||||||
isHeaderChecked={isHeaderChecked}
|
|
||||||
onCheck={this.onSectionHeaderContentCheck}
|
|
||||||
onSelect={this.onSectionHeaderContentSelect}
|
|
||||||
onClose={this.onClose}
|
|
||||||
onLoading={this.onLoading}
|
|
||||||
isLoading={isLoading}
|
|
||||||
loopFilesOperations={this.loopFilesOperations}
|
|
||||||
/>
|
|
||||||
</PageLayout.SectionHeader>
|
|
||||||
|
|
||||||
<PageLayout.SectionFilter>
|
|
||||||
<SectionFilterContent onLoading={this.onLoading} />
|
|
||||||
</PageLayout.SectionFilter>
|
|
||||||
|
|
||||||
<PageLayout.SectionBody>
|
|
||||||
<SectionBodyContent
|
|
||||||
selected={selected}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onLoading={this.onLoading}
|
|
||||||
onChange={this.onRowChange}
|
|
||||||
loopFilesOperations={this.loopFilesOperations}
|
|
||||||
onDropZoneUpload={this.onDrop}
|
|
||||||
/>
|
|
||||||
</PageLayout.SectionBody>
|
|
||||||
|
|
||||||
<PageLayout.SectionPaging>
|
|
||||||
<SectionPagingContent onLoading={this.onLoading} />
|
|
||||||
</PageLayout.SectionPaging>
|
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
103
products/ASC.Files/Client/src/components/pages/Settings/index.js
Normal file
103
products/ASC.Files/Client/src/components/pages/Settings/index.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
ToggleButton
|
||||||
|
} from 'asc-web-components';
|
||||||
|
|
||||||
|
const StyledSettings = styled(Box)`
|
||||||
|
.toggle-btn-container {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
class Settings extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
intermediateVersion: false,
|
||||||
|
thirdParty: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isCheckedIntermediate = () => {
|
||||||
|
this.setState({
|
||||||
|
intermediateVersion: !this.state.intermediateVersion
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
isCheckedThirdParty = () => {
|
||||||
|
this.setState({
|
||||||
|
thirdParty: !this.state.thirdParty
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
renderAdminSettings = () => {
|
||||||
|
const {
|
||||||
|
intermediateVersion,
|
||||||
|
thirdParty
|
||||||
|
} = this.state;
|
||||||
|
return (
|
||||||
|
<StyledSettings>
|
||||||
|
<Box className="toggle-btn-container">
|
||||||
|
<ToggleButton
|
||||||
|
label="Keep all saved intermediate versions"
|
||||||
|
onChange={this.isCheckedIntermediate}
|
||||||
|
isChecked={intermediateVersion}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<br />
|
||||||
|
<Box className="toggle-btn-container">
|
||||||
|
<ToggleButton
|
||||||
|
label="Allow users to connect third-party storages"
|
||||||
|
onChange={this.isCheckedThirdParty}
|
||||||
|
isChecked={thirdParty}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</StyledSettings>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCommonSettings = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
renderClouds = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSettings = setting => {
|
||||||
|
switch (setting) {
|
||||||
|
case "common-settings":
|
||||||
|
return this.renderCommonSettings();
|
||||||
|
case "admin-settings":
|
||||||
|
return this.renderAdminSettings();
|
||||||
|
case "connected-clouds":
|
||||||
|
return this.renderClouds();
|
||||||
|
default:
|
||||||
|
return this.renderCommonSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { settingsPath, match } = this.props;
|
||||||
|
const { setting } = match.params;
|
||||||
|
const content = this.renderSettings(setting);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{content}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
const { settingsPath } = state.files;
|
||||||
|
return { settingsPath };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(Settings);
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"treeSettingsMenuTitle": "Settings",
|
||||||
|
"treeSettingsCommonSettings": "Common Settings",
|
||||||
|
"treeSettingsAdminSettings": "Admin Settings",
|
||||||
|
"treeSettingsConnectedCloud": "Connected Clouds"
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"treeSettingsMenuTitle": "Настройки",
|
||||||
|
"treeSettingsCommonSettings": "Общие настройки",
|
||||||
|
"treeSettingsAdminSettings": "Настройки администратора",
|
||||||
|
"treeSettingsConnectedCloud": "Подключенные облака"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user