Merge branch 'develop' of github.com:ONLYOFFICE/AppServer into feature/confirm-test
This commit is contained in:
commit
a3530a2e33
@ -14,7 +14,7 @@ using ASC.Web.Studio.Core.Notify;
|
||||
using Autofac;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
71
packages/asc-web-components/submenu/README.md
Normal file
71
packages/asc-web-components/submenu/README.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Submenu
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import Submenu from "@appserver/components/submenu";
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Submenu
|
||||
data={[
|
||||
{
|
||||
id: "FileInput",
|
||||
name: "File Input",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={function noRefCheck() {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "ToggleButton",
|
||||
name: "Toggle Button",
|
||||
content: (
|
||||
<ToggleButton
|
||||
className="toggle className"
|
||||
id="toggle id"
|
||||
label="label text"
|
||||
onChange={() => {}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
startSelect={1}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Data is an array of objects with following fields:
|
||||
|
||||
- id - unique id
|
||||
- name - header in submenu
|
||||
- content - HTML object that will be rendered under submenu
|
||||
|
||||
##### Example:
|
||||
|
||||
```jsx
|
||||
{
|
||||
id: "FileInput",
|
||||
name: "File Input",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={function noRefCheck() {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------- | :-------------: | :------: | :----: | :-----: | ----------------------------------------------------------------------------- |
|
||||
| `data` | `array` | ✅ | - | - | List of elements |
|
||||
| `startSelect` | `obj`, `number` | - | - | 0 | Object from data that will be chosen first **OR** Its index in **data** array |
|
126
packages/asc-web-components/submenu/autoOffset.js
Normal file
126
packages/asc-web-components/submenu/autoOffset.js
Normal file
@ -0,0 +1,126 @@
|
||||
import { tablet } from "../utils/device";
|
||||
import DomHelpers from "../utils/domHelpers";
|
||||
|
||||
const paddingGap = 14;
|
||||
const flexGap = 4;
|
||||
const offset = 32;
|
||||
const wrapperPadding = DomHelpers.getViewport() <= tablet ? 16 : 20;
|
||||
|
||||
export const countAutoOffset = (data, submenuItemsRef) => {
|
||||
const [marker, itemsAndGaps, itemOnMarker] = countParams(
|
||||
data,
|
||||
submenuItemsRef
|
||||
);
|
||||
|
||||
if (itemOnMarker === undefined) return 0;
|
||||
if (
|
||||
itemOnMarker.type === "gap" &&
|
||||
itemOnMarker !== itemsAndGaps[itemsAndGaps.length - 1]
|
||||
)
|
||||
return itemOnMarker.end - marker + offset - wrapperPadding;
|
||||
if (itemOnMarker.type === "item" && marker - itemOnMarker.start < 32) {
|
||||
return -(marker - itemOnMarker.start - offset) - wrapperPadding;
|
||||
}
|
||||
if (
|
||||
itemOnMarker.type === "item" &&
|
||||
itemOnMarker.end - marker < 7.5 &&
|
||||
itemOnMarker !== itemsAndGaps[itemsAndGaps.length - 2]
|
||||
) {
|
||||
return itemOnMarker.end - marker + offset * 2 - wrapperPadding;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
export const countAutoFocus = (itemId, data, submenuItemsRef) => {
|
||||
const [marker, itemsAndGaps, itemOnMarker] = countParams(
|
||||
data,
|
||||
submenuItemsRef
|
||||
);
|
||||
|
||||
const [focusedItem] = itemsAndGaps.filter((obj) => obj.id === itemId);
|
||||
const submenuWidth = submenuItemsRef.current.offsetWidth;
|
||||
|
||||
if (itemOnMarker.id && focusedItem.id === itemOnMarker.id)
|
||||
return focusedItem.end - marker;
|
||||
if (
|
||||
focusedItem.start < marker - submenuWidth ||
|
||||
focusedItem.start - offset < marker - submenuWidth
|
||||
)
|
||||
return focusedItem.start - marker + submenuWidth - wrapperPadding - offset;
|
||||
return 0;
|
||||
};
|
||||
|
||||
const countParams = (data, submenuItemsRef) => {
|
||||
const refCurrent = submenuItemsRef.current;
|
||||
|
||||
const texts = data.map((d) => countText(d.name));
|
||||
const itemsAndGaps = countItemsAndGaps(texts);
|
||||
|
||||
const submenuWidth = refCurrent.offsetWidth;
|
||||
const marker = refCurrent.scrollLeft + submenuWidth - wrapperPadding;
|
||||
|
||||
const [itemOnMarker] = itemsAndGaps.filter(
|
||||
(obj) => obj.start < marker && marker < obj.end
|
||||
);
|
||||
|
||||
return [marker, itemsAndGaps, itemOnMarker];
|
||||
};
|
||||
|
||||
const countText = (text) => {
|
||||
const inputText = text;
|
||||
const font = "600 13px open sans";
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext("2d");
|
||||
context.font = font;
|
||||
return { id: text, width: context.measureText(inputText).width };
|
||||
};
|
||||
|
||||
const countItemsAndGaps = (texts) => {
|
||||
const result = [];
|
||||
|
||||
texts.forEach(({ id, width }) => {
|
||||
if (!result.length)
|
||||
result.push(
|
||||
{
|
||||
type: "gap",
|
||||
length: paddingGap,
|
||||
start: 0,
|
||||
end: paddingGap + wrapperPadding,
|
||||
},
|
||||
{
|
||||
id: id,
|
||||
type: "item",
|
||||
length: width,
|
||||
start: paddingGap,
|
||||
end: paddingGap + width,
|
||||
}
|
||||
);
|
||||
else {
|
||||
const lastItem = result[result.length - 1];
|
||||
result.push(
|
||||
{
|
||||
type: "gap",
|
||||
length: paddingGap * 2 + flexGap,
|
||||
start: lastItem.end,
|
||||
end: lastItem.end + paddingGap * 2 + flexGap,
|
||||
},
|
||||
{
|
||||
id: id,
|
||||
type: "item",
|
||||
length: width,
|
||||
start: lastItem.end + paddingGap * 2 + flexGap,
|
||||
end: lastItem.end + paddingGap * 2 + flexGap + width,
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
result.push({
|
||||
type: "gap",
|
||||
length: paddingGap,
|
||||
start: result[result.length - 1].end,
|
||||
end: result[result.length - 1].end + paddingGap + wrapperPadding,
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
89
packages/asc-web-components/submenu/data.js
Normal file
89
packages/asc-web-components/submenu/data.js
Normal file
@ -0,0 +1,89 @@
|
||||
import React from "react";
|
||||
import FileInput from "@appserver/components/file-input";
|
||||
import Row from "@appserver/components/row";
|
||||
import Textarea from "@appserver/components/textarea";
|
||||
import Text from "../text";
|
||||
|
||||
export const data = [
|
||||
{
|
||||
id: "Overview",
|
||||
name: "Overview",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={() => {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "Documents",
|
||||
name: "Documents",
|
||||
content: (
|
||||
<Textarea
|
||||
onChange={() => {}}
|
||||
value="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "Milestones",
|
||||
name: "Milestones",
|
||||
content: (
|
||||
<Row
|
||||
key="1"
|
||||
checked
|
||||
contextOptions={[
|
||||
{
|
||||
key: "key1",
|
||||
label: "Edit",
|
||||
onClick: () => {},
|
||||
},
|
||||
{
|
||||
key: "key2",
|
||||
label: "Delete",
|
||||
onClick: function noRefCheck() {},
|
||||
},
|
||||
]}
|
||||
onRowClick={function noRefCheck() {}}
|
||||
onSelect={function noRefCheck() {}}
|
||||
>
|
||||
<Text truncate>Sample text</Text>
|
||||
</Row>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "Time tracking",
|
||||
name: "Time tracking",
|
||||
content: <p>Time tracking</p>,
|
||||
},
|
||||
{
|
||||
id: "Contacts",
|
||||
name: "Contacts",
|
||||
content: <p>Contacts</p>,
|
||||
},
|
||||
{
|
||||
id: "Team",
|
||||
name: "Team",
|
||||
content: <p>Team</p>,
|
||||
},
|
||||
];
|
||||
|
||||
export const startSelect = data[2];
|
||||
|
||||
export const testData = [
|
||||
{
|
||||
id: "Tab1",
|
||||
name: "Tab1",
|
||||
content: <p>1</p>,
|
||||
},
|
||||
{
|
||||
id: "Tab2",
|
||||
name: "Tab2",
|
||||
content: <p>2</p>,
|
||||
},
|
||||
];
|
||||
|
||||
export const testStartSelect = testData[1];
|
110
packages/asc-web-components/submenu/index.js
Normal file
110
packages/asc-web-components/submenu/index.js
Normal file
@ -0,0 +1,110 @@
|
||||
import PropTypes from "prop-types";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
|
||||
import Text from "../text";
|
||||
import { countAutoFocus, countAutoOffset } from "./autoOffset";
|
||||
import {
|
||||
StyledSubmenu,
|
||||
StyledSubmenuBottomLine,
|
||||
StyledSubmenuContentWrapper,
|
||||
StyledSubmenuItem,
|
||||
StyledSubmenuItemLabel,
|
||||
StyledSubmenuItems,
|
||||
StyledSubmenuItemText,
|
||||
} from "./styled-submenu";
|
||||
|
||||
const Submenu = ({ data, startSelect = 0, ...rest }) => {
|
||||
if (!data) return null;
|
||||
|
||||
const [currentItem, setCurrentItem] = useState(
|
||||
data[startSelect] || startSelect || null
|
||||
);
|
||||
|
||||
const submenuItemsRef = useRef();
|
||||
|
||||
const selectSubmenuItem = (e) => {
|
||||
const item = data.find((el) => el.id === e.currentTarget.id);
|
||||
if (item) setCurrentItem(item);
|
||||
const offset = countAutoFocus(item.name, data, submenuItemsRef);
|
||||
submenuItemsRef.current.scrollLeft += offset;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!submenuItemsRef.current) return;
|
||||
let isDown = false;
|
||||
let startX;
|
||||
let scrollLeft;
|
||||
|
||||
const mouseDown = (e) => {
|
||||
e.preventDefault();
|
||||
isDown = true;
|
||||
startX = e.pageX - submenuItemsRef.current.offsetLeft;
|
||||
scrollLeft = submenuItemsRef.current.scrollLeft;
|
||||
};
|
||||
|
||||
const mouseMove = (e) => {
|
||||
if (!isDown) return;
|
||||
e.preventDefault();
|
||||
const x = e.pageX - submenuItemsRef.current.offsetLeft;
|
||||
const walk = x - startX;
|
||||
submenuItemsRef.current.scrollLeft = scrollLeft - walk;
|
||||
};
|
||||
|
||||
const mouseUp = () => {
|
||||
const offset = countAutoOffset(data, submenuItemsRef);
|
||||
submenuItemsRef.current.scrollLeft += offset;
|
||||
isDown = false;
|
||||
};
|
||||
|
||||
const mouseLeave = () => (isDown = false);
|
||||
|
||||
submenuItemsRef.current.addEventListener("mousedown", mouseDown);
|
||||
submenuItemsRef.current.addEventListener("mousemove", mouseMove);
|
||||
submenuItemsRef.current.addEventListener("mouseup", mouseUp);
|
||||
submenuItemsRef.current.addEventListener("mouseleave", mouseLeave);
|
||||
|
||||
return () => {
|
||||
submenuItemsRef.current?.removeEventListener("mousedown", mouseDown);
|
||||
submenuItemsRef.current?.removeEventListener("mousemove", mouseMove);
|
||||
submenuItemsRef.current?.removeEventListener("mouseup", mouseUp);
|
||||
submenuItemsRef.current?.removeEventListener("mouseleave", mouseLeave);
|
||||
};
|
||||
}, [submenuItemsRef]);
|
||||
|
||||
return (
|
||||
<StyledSubmenu {...rest}>
|
||||
<StyledSubmenuItems ref={submenuItemsRef} role="list">
|
||||
{data.map((d) => {
|
||||
const isActive = d === currentItem;
|
||||
return (
|
||||
<StyledSubmenuItem key={d.id} id={d.id} onClick={selectSubmenuItem}>
|
||||
<StyledSubmenuItemText>
|
||||
<Text
|
||||
color={isActive ? "#316DAA" : "#657077"}
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
truncate="false"
|
||||
>
|
||||
{d.name}
|
||||
</Text>
|
||||
</StyledSubmenuItemText>
|
||||
<StyledSubmenuItemLabel color={isActive ? "#316DAA" : "none"} />
|
||||
</StyledSubmenuItem>
|
||||
);
|
||||
})}
|
||||
</StyledSubmenuItems>
|
||||
<StyledSubmenuBottomLine />
|
||||
|
||||
<StyledSubmenuContentWrapper>
|
||||
{currentItem.content}
|
||||
</StyledSubmenuContentWrapper>
|
||||
</StyledSubmenu>
|
||||
);
|
||||
};
|
||||
|
||||
Submenu.propTypes = {
|
||||
data: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,
|
||||
startSelect: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
|
||||
};
|
||||
|
||||
export default Submenu;
|
76
packages/asc-web-components/submenu/styled-submenu.js
Normal file
76
packages/asc-web-components/submenu/styled-submenu.js
Normal file
@ -0,0 +1,76 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
import { tablet } from "../utils/device";
|
||||
|
||||
export const StyledSubmenu = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.scrollbar {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledSubmenuBottomLine = styled.div`
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
margin: -1px 0 15px 0;
|
||||
background: #eceef1;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuContentWrapper = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItems = styled.div`
|
||||
overflow: scroll;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
padding: 0 20px;
|
||||
@media ${tablet} {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItem = styled.div.attrs((props) => ({
|
||||
id: props.id,
|
||||
}))`
|
||||
scroll-behavior: smooth;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-direction: column;
|
||||
padding: 4px 14px 0;
|
||||
line-height: 20px;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItemText = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItemLabel = styled.div`
|
||||
z-index: 1;
|
||||
width: calc(100% + 28px);
|
||||
margin-left: -14px;
|
||||
height: 4px;
|
||||
bottom: 0px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
background-color: ${(props) => props.color};
|
||||
`;
|
25
packages/asc-web-components/submenu/submenu.stories.js
Normal file
25
packages/asc-web-components/submenu/submenu.stories.js
Normal file
@ -0,0 +1,25 @@
|
||||
import Submenu from ".";
|
||||
import React from "react";
|
||||
import { data, startSelect } from "./data";
|
||||
|
||||
const Wrapper = (props) => (
|
||||
<div
|
||||
style={{
|
||||
height: "170px",
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Template = (args) => (
|
||||
<Wrapper>
|
||||
<Submenu {...args} />
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
data: data,
|
||||
startSelect: startSelect,
|
||||
};
|
64
packages/asc-web-components/submenu/submenu.stories.mdx
Normal file
64
packages/asc-web-components/submenu/submenu.stories.mdx
Normal file
@ -0,0 +1,64 @@
|
||||
import { Canvas, Meta, Story } from "@storybook/addon-docs/blocks";
|
||||
|
||||
import Submenu from "./";
|
||||
import * as stories from "./submenu.stories.js";
|
||||
|
||||
<Meta
|
||||
title="Components/Submenu"
|
||||
component={Submenu}
|
||||
argTypes={{
|
||||
data: { required: true },
|
||||
}}
|
||||
/>
|
||||
|
||||
# Submenu
|
||||
|
||||
<Canvas>
|
||||
<Story story={stories.Default} name="Default" />
|
||||
</Canvas>
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import Submenu from "@appserver/components/submenu";
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Submenu
|
||||
data={[
|
||||
{
|
||||
id: "FileInput",
|
||||
name: "File Input",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={function noRefCheck() {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "ToggleButton",
|
||||
name: "Toggle Button",
|
||||
content: (
|
||||
<ToggleButton
|
||||
className="toggle className"
|
||||
id="toggle id"
|
||||
label="label text"
|
||||
onChange={() => {}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
startSelect={1}
|
||||
/>
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------- | :-------------: | :------: | :----: | :-----: | ----------------------------------------------------------------------------------- |
|
||||
| `data` | `array` | ✅ | - | - | List of elements |
|
||||
| `startSelect` | `obj`, `number` | - | - | 0 | Object from **`data`** **OR** Its index in **`data`** that will be a default select |
|
44
packages/asc-web-components/submenu/submenu.test.js
Normal file
44
packages/asc-web-components/submenu/submenu.test.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { mount, shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import Submenu from "./";
|
||||
import { testData, testStartSelect } from "./data";
|
||||
|
||||
const props = {
|
||||
data: testData,
|
||||
startSelect: testStartSelect,
|
||||
};
|
||||
|
||||
const onlyData = {
|
||||
data: testData,
|
||||
};
|
||||
|
||||
describe("<Submenu />", () => {
|
||||
it("renders without error", () => {
|
||||
const wrapper = mount(<Submenu {...props} />);
|
||||
expect(wrapper).toExist(true);
|
||||
});
|
||||
|
||||
it("gets data prop", () => {
|
||||
const wrapper = mount(<Submenu {...onlyData} />);
|
||||
expect(wrapper.prop("data")).toEqual(testData);
|
||||
});
|
||||
|
||||
it("doesnt render without data prop", () => {
|
||||
const wrapper = mount(<Submenu />);
|
||||
expect(wrapper).toExist(false);
|
||||
});
|
||||
|
||||
it("gets startSelect prop", () => {
|
||||
const wrapper = mount(<Submenu {...props} />);
|
||||
expect(wrapper.prop("startSelect")).toEqual(testStartSelect);
|
||||
});
|
||||
|
||||
it("selects first data item as currentItem without startSelect prop", () => {
|
||||
const wrapper = shallow(<Submenu {...onlyData} />)
|
||||
.find("styled-submenu__StyledSubmenuContentWrapper")
|
||||
.childAt(0);
|
||||
const currentItemWrapper = shallow(testData[0].content);
|
||||
expect(wrapper.debug()).toEqual(currentItemWrapper.debug());
|
||||
});
|
||||
});
|
@ -5,7 +5,6 @@ import {
|
||||
AppServerConfig,
|
||||
FileStatus,
|
||||
} from "@appserver/common/constants";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
|
||||
import Badges from "../components/Badges";
|
||||
@ -36,18 +35,11 @@ export default function withBadges(WrappedComponent) {
|
||||
};
|
||||
|
||||
onBadgeClick = () => {
|
||||
const {
|
||||
item,
|
||||
selectedFolderPathParts,
|
||||
markAsRead,
|
||||
setNewFilesPanelVisible,
|
||||
} = this.props;
|
||||
const { item, markAsRead, setNewFilesPanelVisible } = this.props;
|
||||
if (item.fileExst) {
|
||||
markAsRead([], [item.id], item);
|
||||
} else {
|
||||
const newFolderIds = selectedFolderPathParts;
|
||||
newFolderIds.push(item.id);
|
||||
setNewFilesPanelVisible(true, newFolderIds, item);
|
||||
setNewFilesPanelVisible(true, null, item);
|
||||
}
|
||||
};
|
||||
|
||||
@ -115,7 +107,6 @@ export default function withBadges(WrappedComponent) {
|
||||
treeFoldersStore,
|
||||
filesActionsStore,
|
||||
versionHistoryStore,
|
||||
selectedFolderStore,
|
||||
dialogsStore,
|
||||
filesStore,
|
||||
settingsStore,
|
||||
@ -146,7 +137,6 @@ export default function withBadges(WrappedComponent) {
|
||||
isTabletView,
|
||||
setIsVerHistoryPanel,
|
||||
fetchFileVersions,
|
||||
selectedFolderPathParts: selectedFolderStore.pathParts,
|
||||
markAsRead,
|
||||
setNewFilesPanelVisible,
|
||||
setIsLoading,
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { Trans } from "react-i18next";
|
||||
|
||||
import toastr from "studio/toastr";
|
||||
import {
|
||||
AppServerConfig,
|
||||
@ -177,7 +175,6 @@ export default function withContent(WrappedContent) {
|
||||
createFolder,
|
||||
fileActionTemplateId,
|
||||
isDesktop,
|
||||
isLoading,
|
||||
isPrivacy,
|
||||
item,
|
||||
openDocEditor,
|
||||
@ -198,8 +195,6 @@ export default function withContent(WrappedContent) {
|
||||
|
||||
let title = itemTitle;
|
||||
|
||||
if (isLoading) return;
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const itemId = e.currentTarget.dataset.itemid;
|
||||
@ -461,7 +456,6 @@ export default function withContent(WrappedContent) {
|
||||
const {
|
||||
createFile,
|
||||
createFolder,
|
||||
isLoading,
|
||||
openDocEditor,
|
||||
renameFolder,
|
||||
setIsLoading,
|
||||
@ -511,7 +505,6 @@ export default function withContent(WrappedContent) {
|
||||
folderFormValidation,
|
||||
homepage: config.homepage,
|
||||
isDesktop: isDesktopClient,
|
||||
isLoading,
|
||||
isPrivacy: isPrivacyFolder,
|
||||
isTrashFolder: isRecycleBinFolder,
|
||||
openDocEditor,
|
||||
|
@ -66,7 +66,7 @@ class ArticleBodyContent extends React.Component {
|
||||
};
|
||||
|
||||
onShowNewFilesPanel = (folderId) => {
|
||||
this.props.setNewFilesPanelVisible(true, [folderId]);
|
||||
this.props.setNewFilesPanelVisible(true, folderId);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -113,8 +113,13 @@ class DialogsStore {
|
||||
this.destFolderId = destFolderId;
|
||||
};
|
||||
|
||||
setNewFilesPanelVisible = async (visible, newIds, item) => {
|
||||
const id = newIds && newIds[newIds.length - 1];
|
||||
setNewFilesPanelVisible = async (visible, newId, item) => {
|
||||
const { pathParts } = this.selectedFolderStore;
|
||||
|
||||
const id = visible && !newId ? item.id : newId;
|
||||
const newIds = newId ? [newId] : pathParts;
|
||||
item && pathParts.push(item.id);
|
||||
|
||||
let newFilesPanelVisible = visible;
|
||||
|
||||
if (visible) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { makeAutoObservable, runInAction } from "mobx";
|
||||
import api from "@appserver/common/api";
|
||||
import {
|
||||
FolderType,
|
||||
@ -519,8 +519,11 @@ class FilesStore {
|
||||
data.current.rootFolderType === FolderType.Privacy;
|
||||
|
||||
this.setFilesFilter(filterData, isPrefSettings); //TODO: FILTER
|
||||
this.setFolders(isPrivacyFolder && isMobile ? [] : data.folders);
|
||||
this.setFiles(isPrivacyFolder && isMobile ? [] : data.files);
|
||||
|
||||
runInAction(() => {
|
||||
this.setFolders(isPrivacyFolder && isMobile ? [] : data.folders);
|
||||
this.setFiles(isPrivacyFolder && isMobile ? [] : data.files);
|
||||
});
|
||||
|
||||
if (clearFilter) {
|
||||
this.fileActionStore.setAction({ type: null });
|
||||
@ -1314,6 +1317,14 @@ class FilesStore {
|
||||
}
|
||||
}
|
||||
|
||||
get filterType() {
|
||||
return this.filter.filterType;
|
||||
}
|
||||
|
||||
get filterSearch() {
|
||||
return this.filter.search;
|
||||
}
|
||||
|
||||
onCreateAddTempItem = (items) => {
|
||||
const { getFileIcon, getFolderIcon } = this.filesSettingsStore;
|
||||
const { extension, title } = this.fileActionStore;
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE für Business",
|
||||
"SubHeader": "Dokumente, Projekte, Kunden & E-Mails",
|
||||
"ButtonLabel": "Kostenlos testen",
|
||||
"Link": "https://www.onlyoffice.com/de/registration.aspx?utm_source=personal&utm_campaign=BannerPersonalCloud"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE für PC",
|
||||
"SubHeader": "Gratis Alternative zu MS Office",
|
||||
"ButtonLabel": "Herunterladen",
|
||||
"Link": "https://www.onlyoffice.com/de/download-desktop.aspx?utm_source=personal&utm_campaign=BannerPersonalDesktop"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE für Schulen",
|
||||
"SubHeader": "Endecken Sie alle Rabatte",
|
||||
"ButtonLabel": "Mehr erfahren",
|
||||
"Link": "https://www.onlyoffice.com/de/education.aspx?utm_source=personal&utm_campaign=BannerPersonalEducation"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE On-Premises",
|
||||
"SubHeader": "Schützen Sie Ihre Dokumente",
|
||||
"ButtonLabel": "Jetzt erhalten",
|
||||
"Link": "https://www.onlyoffice.com/de/download-workspace.aspx?utm_source=personal&utm_campaign=BannerPersonalEnterprise"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE Integration",
|
||||
"SubHeader": "Editoren für Ihre Plattform",
|
||||
"ButtonLabel": "Jetzt integrieren",
|
||||
"Link": "https://www.onlyoffice.com/de/connectors.aspx?utm_source=personal&utm_campaign=BannerPersonalIntegration"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE pour les entreprises",
|
||||
"SubHeader": "Documents, projets, clients et mails.",
|
||||
"ButtonLabel": "Commencer l’essai gratuit",
|
||||
"Link": "https://www.onlyoffice.com/fr/registration.aspx?utm_source=personal&utm_campaign=BannerPersonalCloud"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE pour le PC",
|
||||
"SubHeader": "Alternative gratuite à MS Office",
|
||||
"ButtonLabel": "Télécharger",
|
||||
"Link": "https://www.onlyoffice.com/fr/download-desktop.aspx?utm_source=personal&utm_campaign=BannerPersonalDesktop"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE éducation",
|
||||
"SubHeader": "Voir toutes les offres",
|
||||
"ButtonLabel": "En savoir plus",
|
||||
"Link": "https://www.onlyoffice.com/fr/education.aspx?utm_source=personal&utm_campaign=BannerPersonalEducation"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "Solution auto-hébergée",
|
||||
"SubHeader": "Vos docs en toute sécurité",
|
||||
"ButtonLabel": "Obtenir maintenant",
|
||||
"Link": "https://www.onlyoffice.com/fr/download-workspace.aspx?utm_source=personal&utm_campaign=BannerPersonalEnterprise"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE intégration",
|
||||
"SubHeader": "Éditeurs pour votre plateforme",
|
||||
"ButtonLabel": "Intégrer maintenant",
|
||||
"Link": "https://www.onlyoffice.com/fr/connectors.aspx?utm_source=personal&utm_campaign=BannerPersonalIntegration"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE per business",
|
||||
"SubHeader": "Documenti, progetti, clienti ed e-mail",
|
||||
"ButtonLabel": "Inizia la prova gratuita",
|
||||
"Link": "https://www.onlyoffice.com/it/registration.aspx?utm_source=personal&utm_campaign=BannerPersonalCloud"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE per PC",
|
||||
"SubHeader": "Alternativa gratuita a MS Office",
|
||||
"ButtonLabel": "Scarica",
|
||||
"Link": "https://www.onlyoffice.com/it/download-desktop.aspx?utm_source=personal&utm_campaign=BannerPersonalDesktop"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE per scuole",
|
||||
"SubHeader": "Informazioni sugli sconti",
|
||||
"ButtonLabel": "Per saperne di più",
|
||||
"Link": "https://www.onlyoffice.com/it/education.aspx?utm_source=personal&utm_campaign=BannerPersonalEducation"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE sul server",
|
||||
"SubHeader": "Mantieni documenti al sicuro",
|
||||
"ButtonLabel": "Scaricalo ora",
|
||||
"Link": "https://www.onlyoffice.com/it/download-workspace.aspx?utm_source=personal&utm_campaign=BannerPersonalEnterprise"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE integrazioni",
|
||||
"SubHeader": "Editor per la tua piattaforma",
|
||||
"ButtonLabel": "Connetti ora",
|
||||
"Link": "https://www.onlyoffice.com/it/connectors.aspx?utm_source=personal&utm_campaign=BannerPersonalIntegration"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE for business",
|
||||
"SubHeader": "Docs, projects, clients & emails",
|
||||
"ButtonLabel": "Start free trial",
|
||||
"Link": "https://www.onlyoffice.com/pt/registration.aspx?utm_source=personal&utm_campaign=BannerPersonalCloud"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE for PC",
|
||||
"SubHeader": "Get a free alternative to MS Office",
|
||||
"ButtonLabel": "Download",
|
||||
"Link": "https://www.onlyoffice.com/pt/download-desktop.aspx?utm_source=personal&utm_campaign=BannerPersonalDesktop"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE for schools",
|
||||
"SubHeader": "Learn about education discounts",
|
||||
"ButtonLabel": "Learn more",
|
||||
"Link": "https://www.onlyoffice.com/pt/education.aspx?utm_source=personal&utm_campaign=BannerPersonalEducation"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE on-premises",
|
||||
"SubHeader": "Keep your docs and projects safe",
|
||||
"ButtonLabel": "Get it now",
|
||||
"Link": "https://www.onlyoffice.com/pt/download-workspace.aspx?utm_source=personal&utm_campaign=BannerPersonalEnterprise"
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE for integration",
|
||||
"SubHeader": "Use online editors with your platform",
|
||||
"ButtonLabel": "Integrate now",
|
||||
"Link": "https://www.onlyoffice.com/pt/connectors.aspx?utm_source=personal&utm_campaign=BannerPersonalIntegration"
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE локально",
|
||||
"SubHeader": "Обеспечьте сохранность документов и проектов",
|
||||
"ButtonLabel": "Получить сейчас",
|
||||
"Link": "https://www.onlyoffice.com/ru/download-commercial.aspx?utm_source=personal&utm_campaign=BannerPersonalEnterprise"
|
||||
"Header": "ONLYOFFICE локально",
|
||||
"SubHeader": "Обеспечьте сохранность документов и проектов",
|
||||
"ButtonLabel": "Получить сейчас",
|
||||
"Link": "https://www.onlyoffice.com/ru/download-workspace.aspx?utm_source=personal&utm_campaign=BannerPersonalEnterprise"
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"Header": "ONLYOFFICE для интеграции",
|
||||
"SubHeader": "Используйте онлайн-редакторы с вашей платформой",
|
||||
"ButtonLabel": "Интегрировать сейчас",
|
||||
"Link": "https://www.onlyoffice.com/ru/connectors.aspx?utm_source=personal&utm_campaign=BannerPersonalIntegration"
|
||||
"Header": "ONLYOFFICE для интеграции",
|
||||
"SubHeader": "Используйте онлайн-редакторы с вашей платформой",
|
||||
"ButtonLabel": "Интегрировать сейчас",
|
||||
"Link": "https://www.onlyoffice.com/ru/connectors.aspx?utm_source=personal&utm_campaign=BannerPersonalIntegration"
|
||||
}
|
||||
|
4480
web/ASC.Web.Campaigns/yarn.lock
Normal file
4480
web/ASC.Web.Campaigns/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user