Merge branch 'develop' into feature/11.0.2

This commit is contained in:
pavelbannov 2020-12-28 16:28:26 +03:00
commit e6943a4544
17 changed files with 779 additions and 801 deletions

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Backdrop, Heading, Aside, IconButton } from "asc-web-components"; import { Backdrop, Heading, Aside, IconButton } from "asc-web-components";
import { GroupSelector, utils } from "asc-web-common"; import { GroupSelector, utils, constants } from "asc-web-common";
import { withTranslation } from "react-i18next"; import { withTranslation } from "react-i18next";
import { import {
StyledAddGroupsPanel, StyledAddGroupsPanel,
@ -9,6 +9,7 @@ import {
StyledHeaderContent, StyledHeaderContent,
StyledBody, StyledBody,
} from "../StyledPanels"; } from "../StyledPanels";
import AccessComboBox from "../SharingPanel/AccessComboBox";
import { createI18N } from "../../../helpers/i18n"; import { createI18N } from "../../../helpers/i18n";
const i18n = createI18N({ const i18n = createI18N({
page: "AddGroupsPanel", page: "AddGroupsPanel",
@ -16,6 +17,7 @@ const i18n = createI18N({
}); });
const { changeLanguage } = utils; const { changeLanguage } = utils;
const { ShareAccessRights } = constants;
class AddGroupsPanelComponent extends React.Component { class AddGroupsPanelComponent extends React.Component {
constructor(props) { constructor(props) {
@ -23,7 +25,10 @@ class AddGroupsPanelComponent extends React.Component {
changeLanguage(i18n); changeLanguage(i18n);
this.state = { showActionPanel: false }; this.state = {
showActionPanel: false,
accessRight: ShareAccessRights.ReadOnly,
};
this.scrollRef = React.createRef(); this.scrollRef = React.createRef();
} }
@ -38,23 +43,22 @@ class AddGroupsPanelComponent extends React.Component {
}; };
onSelectGroups = (groups) => { onSelectGroups = (groups) => {
const { const { shareDataItems, setShareDataItems, onClose } = this.props;
accessRight,
shareDataItems,
setShareDataItems,
onClose,
} = this.props;
const items = shareDataItems; const items = shareDataItems;
for (let item of groups) { for (let item of groups) {
if (item.key) { if (item.key) {
item.id = item.key; item.id = item.key;
delete item.key;
} }
const currentItem = shareDataItems.find((x) => x.id === item.id); const currentItem = shareDataItems.find((x) => x.sharedTo.id === item.id);
if (!currentItem) { if (!currentItem) {
item.rights = accessRight; const newItem = {
items.push(item); access: this.state.accessRight,
isLocked: false,
isOwner: false,
sharedTo: item,
};
items.push(newItem);
} }
} }
@ -62,10 +66,19 @@ class AddGroupsPanelComponent extends React.Component {
onClose(); onClose();
}; };
onPLusClick = () => { onKeyPress = (event) => {
console.log("onPlusClick"); if (event.key === "Esc" || event.key === "Escape") {
this.props.onClose();
}
}; };
onAccessChange = (e) => {
const accessRight = +e.currentTarget.dataset.access;
this.setState({ accessRight });
};
//onPLusClick = () => console.log("onPlusClick");
componentDidMount() { componentDidMount() {
const scroll = this.scrollRef.current.getElementsByClassName("scroll-body"); const scroll = this.scrollRef.current.getElementsByClassName("scroll-body");
setTimeout(() => scroll[1] && scroll[1].focus(), 2000); setTimeout(() => scroll[1] && scroll[1].focus(), 2000);
@ -75,18 +88,11 @@ class AddGroupsPanelComponent extends React.Component {
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener("keyup", this.onKeyPress); window.removeEventListener("keyup", this.onKeyPress);
} }
onKeyPress = (event) => {
if (event.key === "Esc" || event.key === "Escape") {
this.props.onClose();
}
};
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { showActionPanel } = this.state; const { showActionPanel, accessRight } = this.state;
const { visible, accessRight } = this.props; const { visible } = this.props;
if (accessRight && accessRight.rights !== nextProps.accessRight.rights) { if (accessRight !== nextState.accessRight) {
return true; return true;
} }
@ -102,7 +108,8 @@ class AddGroupsPanelComponent extends React.Component {
} }
render() { render() {
const { visible, embeddedComponent, t } = this.props; const { t, visible, accessOptions } = this.props;
const { accessRight } = this.state;
const zIndex = 310; const zIndex = 310;
@ -146,8 +153,16 @@ class AddGroupsPanelComponent extends React.Component {
displayType="aside" displayType="aside"
withoutAside withoutAside
onSelect={this.onSelectGroups} onSelect={this.onSelectGroups}
embeddedComponent={embeddedComponent} embeddedComponent={
showCounter={true} <AccessComboBox
t={t}
access={accessRight}
directionX="right"
onAccessChange={this.onAccessChange}
accessOptions={accessOptions}
/>
}
showCounter
/> />
</StyledBody> </StyledBody>
</StyledContent> </StyledContent>

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Backdrop, Heading, Aside, IconButton } from "asc-web-components"; import { Backdrop, Heading, Aside, IconButton } from "asc-web-components";
import { PeopleSelector, utils } from "asc-web-common"; import { PeopleSelector, utils, constants } from "asc-web-common";
import { withTranslation } from "react-i18next"; import { withTranslation } from "react-i18next";
import { import {
StyledAddUsersPanelPanel, StyledAddUsersPanelPanel,
@ -9,6 +9,7 @@ import {
StyledHeaderContent, StyledHeaderContent,
StyledBody, StyledBody,
} from "../StyledPanels"; } from "../StyledPanels";
import AccessComboBox from "../SharingPanel/AccessComboBox";
import { createI18N } from "../../../helpers/i18n"; import { createI18N } from "../../../helpers/i18n";
const i18n = createI18N({ const i18n = createI18N({
page: "AddUsersPanel", page: "AddUsersPanel",
@ -16,6 +17,7 @@ const i18n = createI18N({
}); });
const { changeLanguage } = utils; const { changeLanguage } = utils;
const { ShareAccessRights } = constants;
class AddUsersPanelComponent extends React.Component { class AddUsersPanelComponent extends React.Component {
constructor(props) { constructor(props) {
@ -25,6 +27,7 @@ class AddUsersPanelComponent extends React.Component {
this.state = { this.state = {
showActionPanel: false, showActionPanel: false,
accessRight: ShareAccessRights.ReadOnly,
}; };
this.scrollRef = React.createRef(); this.scrollRef = React.createRef();
@ -35,28 +38,33 @@ class AddUsersPanelComponent extends React.Component {
onArrowClick = () => this.props.onClose(); onArrowClick = () => this.props.onClose();
onKeyPress = (event) => {
if (event.key === "Esc" || event.key === "Escape") {
this.props.onClose();
}
};
onClosePanels = () => { onClosePanels = () => {
this.props.onClose(); this.props.onClose();
this.props.onSharingPanelClose(); this.props.onSharingPanelClose();
}; };
onPeopleSelect = (users) => { onPeopleSelect = (users) => {
const { const { shareDataItems, setShareDataItems, onClose } = this.props;
accessRight,
shareDataItems,
setShareDataItems,
onClose,
} = this.props;
const items = shareDataItems; const items = shareDataItems;
for (let item of users) { for (let item of users) {
if (item.key) { if (item.key) {
item.id = item.key; item.id = item.key;
delete item.key;
} }
const currentItem = shareDataItems.find((x) => x.id === item.id); const currentItem = shareDataItems.find((x) => x.sharedTo.id === item.id);
if (!currentItem) { if (!currentItem) {
item.rights = accessRight; const newItem = {
items.push(item); access: this.state.accessRight,
isLocked: false,
isOwner: false,
sharedTo: item,
};
items.push(newItem);
} }
} }
@ -64,6 +72,19 @@ class AddUsersPanelComponent extends React.Component {
onClose(); onClose();
}; };
onOwnerSelect = (owner) => {
const { setShareDataItems, shareDataItems, onClose } = this.props;
const ownerItem = shareDataItems.find((x) => x.isOwner);
ownerItem.sharedTo = owner[0];
if (owner[0].key) {
owner[0].id = owner[0].key;
}
setShareDataItems(shareDataItems);
onClose();
};
componentDidMount() { componentDidMount() {
const scroll = this.scrollRef.current.getElementsByClassName("scroll-body"); const scroll = this.scrollRef.current.getElementsByClassName("scroll-body");
setTimeout(() => scroll[1] && scroll[1].focus(), 2000); setTimeout(() => scroll[1] && scroll[1].focus(), 2000);
@ -74,17 +95,11 @@ class AddUsersPanelComponent extends React.Component {
window.removeEventListener("keyup", this.onKeyPress); window.removeEventListener("keyup", this.onKeyPress);
} }
onKeyPress = (event) => {
if (event.key === "Esc" || event.key === "Escape") {
this.props.onClose();
}
};
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { showActionPanel } = this.state; const { showActionPanel, accessRight } = this.state;
const { visible, accessRight } = this.props; const { visible } = this.props;
if (accessRight && accessRight.rights !== nextProps.accessRight.rights) { if (accessRight !== nextState.accessRight) {
return true; return true;
} }
@ -99,11 +114,37 @@ class AddUsersPanelComponent extends React.Component {
return false; return false;
} }
onAccessChange = (e) => {
const accessRight = +e.currentTarget.dataset.access;
this.setState({ accessRight });
};
render() { render() {
const { visible, embeddedComponent, t, groupsCaption } = this.props; const {
t,
visible,
groupsCaption,
accessOptions,
isMultiSelect,
} = this.props;
const { accessRight } = this.state;
const zIndex = 310; const zIndex = 310;
const embeddedComponent = isMultiSelect
? {
embeddedComponent: (
<AccessComboBox
t={t}
access={accessRight}
directionX="right"
onAccessChange={this.onAccessChange}
accessOptions={accessOptions}
/>
),
}
: null;
//console.log("AddUsersPanel render"); //console.log("AddUsersPanel render");
return ( return (
<StyledAddUsersPanelPanel visible={visible}> <StyledAddUsersPanelPanel visible={visible}>
@ -127,7 +168,7 @@ class AddUsersPanelComponent extends React.Component {
size="medium" size="medium"
truncate truncate
> >
{t("LinkText")} {isMultiSelect ? t("LinkText") : t("OwnerChange")}
</Heading> </Heading>
{/*<IconButton {/*<IconButton
size="16" size="16"
@ -139,14 +180,18 @@ class AddUsersPanelComponent extends React.Component {
<StyledBody ref={this.scrollRef}> <StyledBody ref={this.scrollRef}>
<PeopleSelector <PeopleSelector
role={isMultiSelect ? null : "user"}
employeeStatus={1}
displayType="aside" displayType="aside"
withoutAside withoutAside
isOpen={visible} isOpen={visible}
isMultiSelect isMultiSelect={isMultiSelect}
onSelect={this.onPeopleSelect} onSelect={
embeddedComponent={embeddedComponent} isMultiSelect ? this.onPeopleSelect : this.onOwnerSelect
}
{...embeddedComponent}
groupsCaption={groupsCaption} groupsCaption={groupsCaption}
showCounter={true} showCounter
//onCancel={onClose} //onCancel={onClose}
/> />
</StyledBody> </StyledBody>

View File

@ -1,3 +1,4 @@
{ {
"LinkText": "Add users" "LinkText": "Add users",
"OwnerChange": "Change owner"
} }

View File

@ -1,3 +1,4 @@
{ {
"LinkText": "Добавить пользователей" "LinkText": "Добавить пользователей",
"OwnerChange": "Сменить владельца"
} }

View File

@ -0,0 +1,124 @@
import React from "react";
import { ComboBox, Icons, DropDownItem } from "asc-web-components";
import { constants } from "asc-web-common";
import { getAccessIcon } from "../../../store/files/selectors";
const { ShareAccessRights } = constants;
const AccessComboBox = (props) => {
const {
access,
accessOptions,
directionX,
isDisabled,
itemId,
onAccessChange,
t,
} = props;
const {
FullAccess,
CustomFilter,
Review,
FormFilling,
Comment,
ReadOnly,
DenyAccess,
} = ShareAccessRights;
const advancedOptions = (
<>
{accessOptions.includes("FullAccess") && (
<DropDownItem
label={t("FullAccess")}
icon="AccessEditIcon"
data-id={itemId}
data-access={FullAccess}
onClick={onAccessChange}
/>
)}
{accessOptions.includes("FilterEditing") && (
<DropDownItem
label={t("CustomFilter")}
icon="CustomFilterIcon"
data-id={itemId}
data-access={CustomFilter}
onClick={onAccessChange}
/>
)}
{accessOptions.includes("Review") && (
<DropDownItem
label={t("Review")}
icon="AccessReviewIcon"
data-id={itemId}
data-access={Review}
onClick={onAccessChange}
/>
)}
{accessOptions.includes("FormFilling") && (
<DropDownItem
label={t("FormFilling")}
icon="AccessFormIcon"
data-id={itemId}
data-access={FormFilling}
onClick={onAccessChange}
/>
)}
{accessOptions.includes("Comment") && (
<DropDownItem
label={t("Comment")}
icon="AccessCommentIcon"
data-id={itemId}
data-access={Comment}
onClick={onAccessChange}
/>
)}
{accessOptions.includes("ReadOnly") && (
<DropDownItem
label={t("ReadOnly")}
icon="EyeIcon"
data-id={itemId}
data-access={ReadOnly}
onClick={onAccessChange}
/>
)}
{accessOptions.includes("DenyAccess") && (
<DropDownItem
label={t("DenyAccess")}
icon="AccessNoneIcon"
data-id={itemId}
data-access={DenyAccess}
onClick={onAccessChange}
/>
)}
</>
);
const accessIcon = getAccessIcon(access);
return (
<ComboBox
advancedOptions={advancedOptions}
options={[]}
selectedOption={{ key: 0 }}
size="content"
className="panel_combo-box"
scaled={false}
directionX={directionX}
disableIconClick={false}
isDisabled={isDisabled}
>
{React.createElement(Icons[accessIcon], {
size: "medium",
className: "sharing-access-combo-box-icon",
})}
</ComboBox>
);
};
export default AccessComboBox;

View File

@ -1,273 +1,250 @@
import React from "react"; import React from "react";
import { import { IconButton, Row, Text, Icons, Link } from "asc-web-components";
IconButton,
ComboBox,
Row,
Text,
Icons,
DropDownItem,
} from "asc-web-components";
import { toastr } from "asc-web-common"; import { toastr } from "asc-web-common";
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import LinkRow from "./linkRow"; import LinkRow from "./linkRow";
import AccessComboBox from "./AccessComboBox";
import equal from "fast-deep-equal/react";
import { getAccessIcon } from "../../../store/files/selectors";
const SharingRow = (props) => { class SharingRow extends React.Component {
const { constructor(props) {
t, super(props);
selection,
item, this.state = {
index, access: props.item.access,
isMyId, };
accessOptions, }
onFullAccessClick,
onReadOnlyClick, componentDidUpdate() {
onReviewClick, const { access } = this.props.item;
onCommentClick, if (this.state.access !== access) {
onFormFillingClick, this.setState({ access });
onDenyAccessClick, }
onFilterEditingClick, }
onRemoveUserClick,
onShowEmbeddingPanel, shouldComponentUpdate(nextProps) {
onToggleLink, if (!equal(this.props, nextProps)) {
internalLink, return true;
} = props; }
const externalLinkVisible = if (this.state.access !== this.props.item.access) {
selection && selection.length === 1 && item.shareLink; return true;
const internalLinkVisible = index === 0 && internalLink; }
return true;
}
onCopyInternalLink = () => {
const { internalLink, t } = this.props;
const onCopyInternalLink = () => {
copy(internalLink); copy(internalLink);
toastr.success(t("LinkCopySuccess")); toastr.success(t("LinkCopySuccess"));
}; };
const advancedOptionsRender = (accessOptions) => ( onCopyClick = () => {
<> const { t, item } = this.props;
{accessOptions.includes("FullAccess") && ( const { shareLink } = item.sharedTo;
<DropDownItem
label="Full access"
icon="AccessEditIcon"
onClick={() => onFullAccessClick(item)}
/>
)}
{accessOptions.includes("ReadOnly") && (
<DropDownItem
label="Read only"
icon="EyeIcon"
onClick={() => onReadOnlyClick(item)}
/>
)}
{accessOptions.includes("Review") && (
<DropDownItem
label="Review"
icon="AccessReviewIcon"
onClick={() => onReviewClick(item)}
/>
)}
{accessOptions.includes("Comment") && (
<DropDownItem
label="Comment"
icon="AccessCommentIcon"
onClick={() => onCommentClick(item)}
/>
)}
{accessOptions.includes("FormFilling") && (
<DropDownItem
label="Form filling"
icon="AccessFormIcon"
onClick={() => onFormFillingClick(item)}
/>
)}
{accessOptions.includes("DenyAccess") && (
<DropDownItem
label="Deny access"
icon="AccessNoneIcon"
onClick={() => onDenyAccessClick(item)}
/>
)}
{accessOptions.includes("FilterEditing") && (
<DropDownItem
label="Custom filter"
icon="CustomFilterIcon"
onClick={() => onFilterEditingClick(item)}
/>
)}
</>
);
const embeddedComponentRender = (
accessOptions = this.props.accessOptions,
item,
isDisabled
) => (
<ComboBox
advancedOptions={advancedOptionsRender(accessOptions)}
options={[]}
selectedOption={{ key: 0 }}
size="content"
className="panel_combo-box"
scaled={false}
directionX="left"
disableIconClick={false}
isDisabled={isDisabled}
>
{React.createElement(Icons[item.rights.icon], {
size: "medium",
className: "sharing-access-combo-box-icon",
})}
</ComboBox>
);
const onCopyClick = () => {
toastr.success(t("LinkCopySuccess")); toastr.success(t("LinkCopySuccess"));
copy(item.shareLink); copy(shareLink);
}; };
const onShareEmail = () => { onShareEmail = () => {
const { selection, item, t } = this.props;
const { shareLink } = item.sharedTo;
const itemName = selection.title ? selection.title : selection[0].title; const itemName = selection.title ? selection.title : selection[0].title;
const subject = `You have been granted access to the ${itemName} document`; const subject = t("ShareEmailSubject", { itemName });
const body = `You have been granted access to the ${itemName} document. Click the link below to open the document right now: 111${item.shareLink}111`; const body = t("ShareEmailBody", { itemName, shareLink });
window.open(`mailto:?subject=${subject}&body=${body}`); window.open(`mailto:?subject=${subject}&body=${body}`);
}; };
const onShareTwitter = () => { onShareTwitter = () => {
const encodedLink = encodeURIComponent(item.shareLink); const encodedLink = encodeURIComponent(this.props.item.sharedTo.shareLink);
window.open(`https://twitter.com/intent/tweet?text=${encodedLink}`); window.open(`https://twitter.com/intent/tweet?text=${encodedLink}`);
}; };
const onShareFacebook = () => { onShareFacebook = () => {
window.open( window.open(
`https://www.facebook.com/sharer/sharer.php?u=${item.shareLink}` `https://www.facebook.com/sharer/sharer.php?u=${this.props.item.sharedTo.shareLink}`
); );
}; };
const internalLinkData = [ render() {
{ //console.log("SharingRow render");
key: "linkItem", const {
label: t("CopyInternalLink"), t,
onClick: onCopyInternalLink, selection,
}, item,
]; index,
isMyId,
accessOptions,
onChangeItemAccess,
onRemoveUserClick,
onShowEmbeddingPanel,
onToggleLink,
externalLinkData,
canShareOwnerChange,
onShowChangeOwnerPanel,
isLoading,
internalLink,
} = this.props;
const { access } = this.state;
const externalLinkOptions = [ const { isOwner, isLocked } = item;
{ const { label, displayName, name, shareLink, id } = item.sharedTo;
key: "linkItem_0", const userName = name
label: t("CopyExternalLink"), ? name === "Everyone"
onClick: onCopyClick, ? t("ShareEveryone")
}, : name
{ : "";
key: "linkItem_1",
isSeparator: true,
},
{
key: "linkItem_2",
label: `${t("ShareVia")} e-mail`,
onClick: onShareEmail,
},
{
key: "linkItem_3",
label: `${t("ShareVia")} Google Plus`,
onClick: () => toastr.warning("Share via Google Plus"),
},
{
key: "linkItem_4",
label: `${t("ShareVia")} Facebook`,
onClick: onShareFacebook,
},
{
key: "linkItem_5",
label: `${t("ShareVia")} Twitter`,
onClick: onShareTwitter,
},
{
key: "linkItem_6",
isSeparator: true,
},
{
key: "linkItem_7",
label: t("Embedding"),
onClick: () => onShowEmbeddingPanel(item.shareLink),
},
];
//console.log("SharingRow render"); const externalLinkVisible =
return ( selection && selection.length === 1 && shareLink;
<> const internalLinkVisible = index === 0 && internalLink;
{externalLinkVisible && (
<LinkRow
linkText="ExternalLink"
options={externalLinkOptions}
embeddedComponentRender={embeddedComponentRender}
onToggleLink={onToggleLink}
withToggle={true}
{...props}
/>
)}
{internalLinkVisible && (
<LinkRow
linkText="InternalLink"
options={internalLinkData}
embeddedComponentRender={embeddedComponentRender}
{...props}
/>
)}
{!item.shareLink && ( const internalLinkData = [
<Row {
className="sharing-row" key: "linkItem",
key={`internal-link-key_${index}`} label: t("CopyInternalLink"),
element={ onClick: this.onCopyInternalLink,
item.rights.isOwner || item.id === isMyId ? ( },
<Icons.AccessEditIcon ];
size="medium"
className="sharing_panel-owner-icon" const externalLinkOptions = [
/> {
) : ( key: "linkItem_0",
embeddedComponentRender(accessOptions, item) label: t("CopyExternalLink"),
) onClick: this.onCopyClick,
} },
contextButtonSpacerWidth="0px" {
> key: "linkItem_1",
<> isSeparator: true,
{!item.shareLink && ( },
<Text truncate className="sharing_panel-text"> {
{item.label key: "linkItem_2",
? item.label label: `${t("ShareVia")} e-mail`,
: item.name onClick: this.onShareEmail,
? item.name },
: item.displayName} {
</Text> key: "linkItem_3",
)} label: `${t("ShareVia")} Google Plus`,
{item.rights.isOwner ? ( onClick: () => toastr.warning("Share via Google Plus"),
<Text className="sharing_panel-remove-icon" color="#A3A9AE"> },
{t("Owner")} {
</Text> key: "linkItem_4",
) : item.id === isMyId ? ( label: `${t("ShareVia")} Facebook`,
<Text onClick: this.onShareFacebook,
className="sharing_panel-remove-icon" },
//color="#A3A9AE" {
> key: "linkItem_5",
{t("AccessRightsFullAccess")} label: `${t("ShareVia")} Twitter`,
</Text> onClick: this.onShareTwitter,
) : ( },
!item.shareLink && ( {
<IconButton key: "linkItem_6",
iconName="RemoveIcon" isSeparator: true,
onClick={() => onRemoveUserClick(item)} },
className="sharing_panel-remove-icon" {
color="#A3A9AE" key: "linkItem_7",
label: t("Embedding"),
onClick: () => onShowEmbeddingPanel(shareLink),
},
];
const onRemoveUserProp = !isLoading ? { onClick: onRemoveUserClick } : {};
const onShowChangeOwnerPanelProp = !isLoading
? { onClick: onShowChangeOwnerPanel }
: {};
const accessIcon = getAccessIcon(access);
return (
<>
{externalLinkVisible && (
<LinkRow
linkText="ExternalLink"
options={externalLinkOptions}
externalLinkData={externalLinkData}
onToggleLink={onToggleLink}
withToggle
{...this.props}
/>
)}
{internalLinkVisible && (
<LinkRow
linkText="InternalLink"
options={internalLinkData}
{...this.props}
/>
)}
{!shareLink && (
<Row
className="sharing-row"
key={`internal-link-key_${id}`}
element={
isOwner || isLocked ? (
React.createElement(Icons[accessIcon], {
size: "medium",
className: "sharing_panel-owner-icon",
isfill: true,
color: isLoading ? "#D0D5DA" : "#a3a9ae",
})
) : (
<AccessComboBox
t={t}
access={access}
directionX="left"
onAccessChange={onChangeItemAccess}
itemId={id}
accessOptions={accessOptions}
isDisabled={isLoading}
/> />
) )
)} }
</> contextButtonSpacerWidth="0px"
</Row> >
)} <>
</> {!shareLink &&
); (isOwner && canShareOwnerChange ? (
}; <Link isHovered type="action" {...onShowChangeOwnerPanelProp}>
{label ? label : userName ? userName : displayName}
</Link>
) : (
<Text truncate className="sharing_panel-text">
{label ? label : userName ? userName : displayName}
</Text>
))}
{isOwner ? (
<Text className="sharing_panel-remove-icon" color="#A3A9AE">
{t("Owner")}
</Text>
) : id === isMyId ? (
<Text
className="sharing_panel-remove-icon"
//color="#A3A9AE"
>
{t("AccessRightsFullAccess")}
</Text>
) : (
!shareLink &&
!isLocked && (
<IconButton
iconName="RemoveIcon"
id={id}
{...onRemoveUserProp}
className="sharing_panel-remove-icon"
color="#A3A9AE"
isDisabled={isLoading}
/>
)
)}
</>
</Row>
)}
</>
);
}
}
export default SharingRow; export default SharingRow;

View File

@ -9,8 +9,6 @@ import {
DropDown, DropDown,
DropDownItem, DropDownItem,
Textarea, Textarea,
ComboBox,
Icons,
} from "asc-web-components"; } from "asc-web-components";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { withRouter } from "react-router"; import { withRouter } from "react-router";
@ -20,12 +18,19 @@ import {
getShareUsers, getShareUsers,
setShareFiles, setShareFiles,
setSharingPanelVisible, setSharingPanelVisible,
setIsLoading,
setFiles,
setFolders,
} from "../../../store/files/actions"; } from "../../../store/files/actions";
import { import {
getAccessOption, getAccessOption,
getExternalAccessOption, getExternalAccessOption,
getSelection, getSelection,
getSharePanelVisible, getSharePanelVisible,
getCanShareOwnerChange,
getIsLoading,
getFiles,
getFolders,
} from "../../../store/files/selectors"; } from "../../../store/files/selectors";
import { import {
StyledAsidePanel, StyledAsidePanel,
@ -66,15 +71,12 @@ class SharingPanelComponent extends React.Component {
showAddUsersPanel: false, showAddUsersPanel: false,
showEmbeddingPanel: false, showEmbeddingPanel: false,
showAddGroupsPanel: false, showAddGroupsPanel: false,
accessRight: { showChangeOwnerPanel: false,
icon: "EyeIcon",
rights: "ReadOnly",
accessNumber: ShareAccessRights.ReadOnly,
},
shareLink: "", shareLink: "",
isLoadedShareData: false, isLoadedShareData: false,
showPanel: false, showPanel: false,
accessOptions: [], accessOptions: [],
filesOwnerId: null,
}; };
this.ref = React.createRef(); this.ref = React.createRef();
@ -91,27 +93,47 @@ class SharingPanelComponent extends React.Component {
onToggleLink = (item) => { onToggleLink = (item) => {
const { shareDataItems } = this.state; const { shareDataItems } = this.state;
const { DenyAccess, ReadOnly } = ShareAccessRights;
const rights = const rights = item.access !== DenyAccess ? DenyAccess : ReadOnly;
item.rights.accessNumber !== ShareAccessRights.DenyAccess
? this.getItemAccess(ShareAccessRights.DenyAccess)
: this.getItemAccess(ShareAccessRights.ReadOnly);
const newDataItems = JSON.parse(JSON.stringify(shareDataItems)); const newDataItems = JSON.parse(JSON.stringify(shareDataItems));
newDataItems[0].rights = { ...rights }; newDataItems[0].access = rights;
this.setState({ this.setState({
shareDataItems: newDataItems, shareDataItems: newDataItems,
}); });
}; };
updateRowData = (newRowData) => {
const { files, folders, setFiles, setFolders } = this.props;
for (let item of newRowData) {
if (!item.fileExst && item.foldersCount) {
let folderIndex = folders.findIndex((x) => x.id === item.id);
if (folderIndex !== -1) {
folders[folderIndex] = item;
}
} else {
let fileIndex = files.findIndex((x) => x.id === item.id);
if (fileIndex !== -1) {
files[fileIndex] = item;
}
}
}
setFiles(files);
setFolders(folders);
};
onSaveClick = () => { onSaveClick = () => {
const { const {
baseShareData, baseShareData,
isNotifyUsers, isNotifyUsers,
message, message,
shareDataItems, shareDataItems,
filesOwnerId,
} = this.state; } = this.state;
const { selectedItems } = this.props; const { selection, setIsLoading } = this.props;
const folderIds = []; const folderIds = [];
const fileIds = []; const fileIds = [];
@ -120,32 +142,37 @@ class SharingPanelComponent extends React.Component {
let externalAccess = null; let externalAccess = null;
for (let item of shareDataItems) { for (let item of shareDataItems) {
const baseItem = baseShareData.find((x) => x.id === item.id); const baseItem = baseShareData.find(
if ( (x) => x.sharedTo.id === item.sharedTo.id
(baseItem && );
baseItem.rights.rights !== item.rights.rights &&
!item.shareLink) ||
!baseItem
) {
share.push({ shareTo: item.id, access: item.rights.accessNumber });
}
if ( if (
item.shareLink && (baseItem &&
item.rights.accessNumber !== baseItem.rights.accessNumber baseItem.access !== item.access &&
!item.sharedTo.shareLink) ||
(!item.isOwner && !baseItem)
) { ) {
externalAccess = item.rights.accessNumber; share.push({ shareTo: item.sharedTo.id, access: item.access });
}
if (item.sharedTo.shareLink && item.access !== baseItem.access) {
externalAccess = item.access;
} }
} }
for (let item of baseShareData) { for (let item of baseShareData) {
const baseItem = shareDataItems.find((x) => x.id === item.id); const baseItem = shareDataItems.find(
(x) => x.sharedTo.id === item.sharedTo.id
);
if (!baseItem) { if (!baseItem) {
share.push({ shareTo: item.id, access: 0 }); share.push({
shareTo: item.sharedTo.id,
access: ShareAccessRights.None,
});
} }
} }
for (let item of selectedItems) { for (let item of selection) {
if (item.fileExst) { if (item.fileExst) {
fileIds.push(item.id); fileIds.push(item.id);
} else { } else {
@ -153,93 +180,28 @@ class SharingPanelComponent extends React.Component {
} }
} }
const owner = shareDataItems.find((x) => x.isOwner);
const ownerId =
filesOwnerId !== owner.sharedTo.id ? owner.sharedTo.id : null;
setIsLoading(true);
this.onClose();
setShareFiles( setShareFiles(
folderIds, folderIds,
fileIds, fileIds,
share, share,
isNotifyUsers, isNotifyUsers,
message, message,
externalAccess externalAccess,
ownerId
) )
.then((res) => {
if (ownerId) {
this.updateRowData(res[0]);
}
})
.catch((err) => toastr.error(err)) .catch((err) => toastr.error(err))
.finally(() => this.onClose()); .finally(() => setIsLoading(false));
};
onFullAccessClick = () => {
this.setState({
accessRight: {
icon: "AccessEditIcon",
rights: "FullAccess",
accessNumber: ShareAccessRights.FullAccess,
isOwner: false,
},
});
};
onReadOnlyClick = () => {
this.setState({
accessRight: {
icon: "EyeIcon",
rights: "ReadOnly",
accessNumber: ShareAccessRights.ReadOnly,
isOwner: false,
},
});
};
onReviewClick = () => {
this.setState({
accessRight: {
icon: "AccessReviewIcon",
rights: "Review",
accessNumber: ShareAccessRights.Review,
isOwner: false,
},
});
};
onCommentClick = () => {
this.setState({
accessRight: {
icon: "AccessCommentIcon",
rights: "Comment",
accessNumber: ShareAccessRights.Comment,
isOwner: false,
},
});
};
onFormFillingClick = () => {
this.setState({
accessRight: {
icon: "AccessFormIcon",
rights: "FormFilling",
accessNumber: ShareAccessRights.FormFilling,
isOwner: false,
},
});
};
onDenyAccessClick = () => {
this.setState({
accessRight: {
icon: "AccessNoneIcon",
rights: "DenyAccess",
accessNumber: ShareAccessRights.DenyAccess,
isOwner: false,
},
});
};
onFilterEditingClick = () => {
this.setState({
accessRight: {
icon: "CustomFilterIcon",
rights: "CustomFilter",
accessNumber: ShareAccessRights.CustomFilter,
isOwner: false,
},
});
}; };
onNotifyUsersChange = () => onNotifyUsersChange = () =>
@ -251,247 +213,35 @@ class SharingPanelComponent extends React.Component {
showActionPanel: false, showActionPanel: false,
}); });
onFullAccessItemClick = (item) => { onChangeItemAccess = (e) => {
const newUsers = this.state.shareDataItems; const id = e.currentTarget.dataset.id;
const elementIndex = newUsers.findIndex((x) => x.id === item.id); const access = e.currentTarget.dataset.access;
if (newUsers[elementIndex].rights.rights !== "FullAccess") { const shareDataItems = this.state.shareDataItems;
newUsers[elementIndex].rights = { const elem = shareDataItems.find((x) => x.sharedTo.id === id && !x.isOwner);
icon: "AccessEditIcon",
rights: "FullAccess", if (elem.access !== +access) {
accessNumber: ShareAccessRights.FullAccess, elem.access = +access;
}; this.setState({ shareDataItems });
this.setState({ shareDataItems: newUsers });
}
};
onReadOnlyItemClick = (item) => {
const newUsers = this.state.shareDataItems;
const elementIndex = newUsers.findIndex((x) => x.id === item.id);
if (newUsers[elementIndex].rights.rights !== "ReadOnly") {
newUsers[elementIndex].rights = {
icon: "EyeIcon",
rights: "ReadOnly",
accessNumber: ShareAccessRights.ReadOnly,
};
this.setState({ shareDataItems: newUsers });
}
};
onReviewItemClick = (item) => {
const newUsers = this.state.shareDataItems;
const elementIndex = newUsers.findIndex((x) => x.id === item.id);
if (newUsers[elementIndex].rights.rights !== "Review") {
newUsers[elementIndex].rights = {
icon: "AccessReviewIcon",
rights: "Review",
accessNumber: ShareAccessRights.Review,
};
this.setState({ shareDataItems: newUsers });
}
};
onCommentItemClick = (item) => {
const newUsers = this.state.shareDataItems;
const elementIndex = newUsers.findIndex((x) => x.id === item.id);
if (newUsers[elementIndex].rights.rights !== "Comment") {
newUsers[elementIndex].rights = {
icon: "AccessCommentIcon",
rights: "Comment",
accessNumber: ShareAccessRights.Comment,
};
this.setState({ shareDataItems: newUsers });
}
};
onFormFillingItemClick = (item) => {
const newUsers = this.state.shareDataItems;
const elementIndex = newUsers.findIndex((x) => x.id === item.id);
if (newUsers[elementIndex].rights.rights !== "FormFilling") {
newUsers[elementIndex].rights = {
icon: "AccessFormIcon",
rights: "FormFilling",
accessNumber: ShareAccessRights.FormFilling,
};
this.setState({ shareDataItems: newUsers });
}
};
onFilterEditingItemClick = (item) => {
const newUsers = this.state.shareDataItems;
const elementIndex = newUsers.findIndex((x) => x.id === item.id);
if (newUsers[elementIndex].rights.rights !== "CustomFilter") {
newUsers[elementIndex].rights = {
icon: "CustomFilterIcon",
rights: "CustomFilter",
accessNumber: ShareAccessRights.CustomFilter,
};
this.setState({ shareDataItems: newUsers });
}
};
onDenyAccessItemClick = (item) => {
const newUsers = this.state.shareDataItems;
const elementIndex = newUsers.findIndex((x) => x.id === item.id);
if (newUsers[elementIndex].rights.rights !== "DenyAccess") {
newUsers[elementIndex].rights = {
icon: "AccessNoneIcon",
rights: "DenyAccess",
accessNumber: ShareAccessRights.DenyAccess,
};
this.setState({ shareDataItems: newUsers });
} }
}; };
onRemoveUserItemClick = (item) => { onRemoveUserItemClick = (e) => {
const id = e.currentTarget.dataset.for;
const shareDataItems = this.state.shareDataItems.slice(0); const shareDataItems = this.state.shareDataItems.slice(0);
const index = shareDataItems.findIndex((x) => x.id === item.id); const index = shareDataItems.findIndex((x) => x.sharedTo.id === id);
if (index !== -1) { if (index !== -1) {
shareDataItems.splice(index, 1); shareDataItems.splice(index, 1);
this.setState({ shareDataItems }); this.setState({ shareDataItems });
} }
}; };
getItemAccess = (accessType, isOwner = false) => {
const fullAccessRights = {
icon: "AccessEditIcon",
rights: "FullAccess",
accessNumber: ShareAccessRights.FullAccess,
isOwner: isOwner,
};
switch (accessType) {
case 1:
return fullAccessRights;
case 2:
return {
icon: "EyeIcon",
rights: "ReadOnly",
accessNumber: ShareAccessRights.ReadOnly,
isOwner: false,
};
case 3:
return {
icon: "AccessNoneIcon",
rights: "DenyAccess",
accessNumber: ShareAccessRights.DenyAccess,
isOwner: false,
};
case 5:
return {
icon: "AccessReviewIcon",
rights: "Review",
accessNumber: ShareAccessRights.Review,
isOwner: false,
};
case 6:
return {
icon: "AccessCommentIcon",
rights: "Comment",
accessNumber: ShareAccessRights.Comment,
isOwner: false,
};
case 7:
return {
icon: "AccessFormIcon",
rights: "FormFilling",
accessNumber: ShareAccessRights.FormFilling,
isOwner: false,
};
case 8:
return {
icon: "CustomFilterIcon",
rights: "CustomFilter",
accessNumber: ShareAccessRights.CustomFilter,
isOwner: false,
};
default:
return;
}
};
getShareDataItems = (items) => {
const {
getAccessOption,
getExternalAccessOption,
selectedItems,
} = this.props;
let arrayItems = [];
const newItems = [];
let stash = [];
for (let array of items) {
for (let item of array) {
const rights = this.getItemAccess(item.access, item.isOwner);
if (rights) {
item.sharedTo = { ...item.sharedTo, ...{ rights } };
arrayItems.push(item.sharedTo);
stash.push(item.sharedTo);
}
}
newItems.push(stash);
stash = [];
}
stash = null;
for (let item of arrayItems) {
let length = newItems.length;
if (!item.shareLink) {
while (length !== 0) {
if (newItems[length - 1].length !== 0) {
stash = newItems[length - 1].find((x) => x.id === item.id);
if (stash === this.props.isMyId) {
const adminRights = {
icon: "AccessEditIcon",
rights: "FullAccess",
accessNumber: ShareAccessRights.FullAccess,
isOwner: item.isOwner,
};
item.rights = adminRights;
} else if (
!stash ||
item.rights.rights !== stash.rights.rights ||
item.rights.isOwner !== stash.rights.isOwner
) {
const variesRights = {
icon: "CatalogQuestionIcon",
rights: "Varies",
isOwner: false,
};
item.rights = variesRights;
}
}
length--;
}
} else {
const externalLinkAccess = items[0][0].access;
item.access = externalLinkAccess;
item.rights = this.getItemAccess(externalLinkAccess);
}
}
arrayItems = this.removeDuplicateShareData(arrayItems);
const baseShareData = JSON.parse(JSON.stringify(arrayItems));
const accessOptions = getAccessOption(selectedItems);
const externalAccessOptions = getExternalAccessOption(selectedItems);
return {
baseShareData,
shareDataItems: arrayItems,
accessOptions,
externalAccessOptions,
};
};
removeDuplicateShareData = (shareDataItems) => {
let obj = {};
return shareDataItems.filter((x) => {
if (obj[x.id]) return false;
obj[x.id] = true;
return true;
});
};
getData = () => { getData = () => {
const { selectedItems } = this.props; const { selection } = this.props;
const folderId = []; const folderId = [];
const fileId = []; const fileId = [];
for (let item of selectedItems) { for (let item of selection) {
if (item.access === 1 || item.access === 0) { if (item.access === 1 || item.access === 0) {
if (item.fileExst) { if (item.fileExst) {
fileId.push(item.id); fileId.push(item.id);
@ -508,31 +258,46 @@ class SharingPanelComponent extends React.Component {
const returnValue = this.getData(); const returnValue = this.getData();
const folderId = returnValue[0]; const folderId = returnValue[0];
const fileId = returnValue[1]; const fileId = returnValue[1];
let error = null; const {
let shareData = {}; getAccessOption,
getExternalAccessOption,
selection,
setIsLoading,
} = this.props;
if (folderId.length !== 0 || fileId.length !== 0) { if (folderId.length !== 0 || fileId.length !== 0) {
setIsLoading(true);
getShareUsers(folderId, fileId) getShareUsers(folderId, fileId)
.then((res) => { .then((shareDataItems) => {
shareData = this.getShareDataItems(res); const baseShareData = JSON.parse(JSON.stringify(shareDataItems));
const accessOptions = getAccessOption(selection);
const externalAccessOptions = getExternalAccessOption(selection);
const filesOwner = shareDataItems.find((x) => x.isOwner);
const filesOwnerId = filesOwner ? filesOwner.sharedTo.id : null;
this.setState({
baseShareData,
shareDataItems,
accessOptions,
externalAccessOptions,
showPanel: true,
filesOwnerId,
});
}) })
.catch((err) => { .catch((err) => {
error = err;
toastr.error(err); toastr.error(err);
this.onClose();
}) })
.finally( .finally(() => setIsLoading(false));
() =>
!error && this.setState({ ...shareData, ...{ showPanel: true } })
);
} }
}; };
getInternalLink = () => { getInternalLink = () => {
const { settings, selectedItems } = this.props; const { settings, selection } = this.props;
const item = selectedItems[0]; const item = selection[0];
const isFile = !!item.fileExst; const isFile = !!item.fileExst;
if (selectedItems.length !== 1) return null; if (selection.length !== 1) return null;
return isFile return isFile
? item.canOpenPlayer ? item.canOpenPlayer
@ -555,6 +320,12 @@ class SharingPanelComponent extends React.Component {
showActionPanel: false, showActionPanel: false,
}); });
onShowChangeOwnerPanel = () =>
this.setState({
showChangeOwnerPanel: !this.state.showChangeOwnerPanel,
showActionPanel: false,
});
onChangeMessage = (e) => this.setState({ message: e.target.value }); onChangeMessage = (e) => this.setState({ message: e.target.value });
setShareDataItems = (shareDataItems) => this.setState({ shareDataItems }); setShareDataItems = (shareDataItems) => this.setState({ shareDataItems });
@ -577,8 +348,15 @@ class SharingPanelComponent extends React.Component {
showAddUsersPanel, showAddUsersPanel,
showEmbeddingPanel, showEmbeddingPanel,
showAddGroupsPanel, showAddGroupsPanel,
showChangeOwnerPanel,
} = this.state; } = this.state;
if (showAddUsersPanel || showEmbeddingPanel || showAddGroupsPanel) return; if (
showAddUsersPanel ||
showEmbeddingPanel ||
showAddGroupsPanel ||
showChangeOwnerPanel
)
return;
if (event.key === "Esc" || event.key === "Escape") { if (event.key === "Esc" || event.key === "Escape") {
this.onClose(); this.onClose();
} }
@ -599,7 +377,14 @@ class SharingPanelComponent extends React.Component {
render() { render() {
//console.log("Sharing panel render"); //console.log("Sharing panel render");
const { t, isMyId, selectedItems, groupsCaption } = this.props; const {
t,
isMyId,
selection,
groupsCaption,
canShareOwnerChange,
isLoading,
} = this.props;
const { const {
showActionPanel, showActionPanel,
isNotifyUsers, isNotifyUsers,
@ -608,7 +393,7 @@ class SharingPanelComponent extends React.Component {
showAddUsersPanel, showAddUsersPanel,
showAddGroupsPanel, showAddGroupsPanel,
showEmbeddingPanel, showEmbeddingPanel,
accessRight, showChangeOwnerPanel,
shareLink, shareLink,
showPanel, showPanel,
accessOptions, accessOptions,
@ -617,85 +402,8 @@ class SharingPanelComponent extends React.Component {
const visible = showPanel; const visible = showPanel;
const zIndex = 310; const zIndex = 310;
const internalLink = selectedItems && this.getInternalLink(); const onPlusClickProp = !isLoading ? { onClick: this.onPlusClick } : {};
const internalLink = selection.length === 1 && this.getInternalLink();
const advancedOptions = (
<>
{accessOptions.includes("FullAccess") && (
<DropDownItem
label="Full access"
icon="AccessEditIcon"
onClick={this.onFullAccessClick}
/>
)}
{accessOptions.includes("ReadOnly") && (
<DropDownItem
label="Read only"
icon="EyeIcon"
onClick={this.onReadOnlyClick}
/>
)}
{accessOptions.includes("Review") && (
<DropDownItem
label="Review"
icon="AccessReviewIcon"
onClick={this.onReviewClick}
/>
)}
{accessOptions.includes("Comment") && (
<DropDownItem
label="Comment"
icon="AccessCommentIcon"
onClick={this.onCommentClick}
/>
)}
{accessOptions.includes("FormFilling") && (
<DropDownItem
label="Form filling"
icon="AccessFormIcon"
onClick={this.onFormFillingClick}
/>
)}
{accessOptions.includes("DenyAccess") && (
<DropDownItem
label="Deny access"
icon="AccessNoneIcon"
onClick={this.onDenyAccessClick}
/>
)}
{accessOptions.includes("FilterEditing") && (
<DropDownItem
label="Custom filter"
icon="CustomFilterIcon"
onClick={this.onFilterEditingClick}
/>
)}
</>
);
const accessOptionsComboBox = (
<ComboBox
advancedOptions={advancedOptions}
options={[]}
selectedOption={{ key: 0, arrowIconColor: "#333333" }}
size="content"
className="panel_combo-box add-groups"
scaled={false}
directionX="right"
disableIconClick={false}
//isDisabled={isDisabled}
>
{React.createElement(Icons[accessRight.icon], {
size: "medium",
//color: this.state.currentIconColor,
//isfill: isFill
})}
</ComboBox>
);
return ( return (
<StyledAsidePanel visible={visible}> <StyledAsidePanel visible={visible}>
@ -706,7 +414,7 @@ class SharingPanelComponent extends React.Component {
isAside={true} isAside={true}
/> />
<Aside className="header_aside-panel" visible={visible}> <Aside className="header_aside-panel" visible={visible}>
<StyledContent> <StyledContent isDisabled={isLoading}>
<StyledHeaderContent> <StyledHeaderContent>
<Heading className="sharing_panel-header" size="medium" truncate> <Heading className="sharing_panel-header" size="medium" truncate>
{t("SharingSettingsTitle")} {t("SharingSettingsTitle")}
@ -717,8 +425,9 @@ class SharingPanelComponent extends React.Component {
size="17" size="17"
iconName="PlusIcon" iconName="PlusIcon"
className="sharing_panel-plus-icon" className="sharing_panel-plus-icon"
onClick={this.onPlusClick} {...onPlusClickProp}
color="A3A9AE" color="A3A9AE"
isDisabled={isLoading}
/> />
<DropDown <DropDown
@ -751,28 +460,24 @@ class SharingPanelComponent extends React.Component {
stype="mediumBlack" stype="mediumBlack"
style={SharingBodyStyle} style={SharingBodyStyle}
> >
{" "}
{shareDataItems.map((item, index) => ( {shareDataItems.map((item, index) => (
<SharingRow <SharingRow
key={index}
t={t} t={t}
selection={selectedItems}
item={item}
index={index} index={index}
key={`${item.sharedTo.id}_${index}`}
selection={selection}
item={item}
isMyId={isMyId} isMyId={isMyId}
accessOptions={accessOptions} accessOptions={accessOptions}
externalAccessOptions={externalAccessOptions} externalAccessOptions={externalAccessOptions}
canShareOwnerChange={canShareOwnerChange}
onChangeItemAccess={this.onChangeItemAccess}
internalLink={internalLink} internalLink={internalLink}
onFullAccessClick={this.onFullAccessItemClick}
onReadOnlyClick={this.onReadOnlyItemClick}
onReviewClick={this.onReviewItemClick}
onCommentClick={this.onCommentItemClick}
onFormFillingClick={this.onFormFillingItemClick}
onFilterEditingClick={this.onFilterEditingItemClick}
onDenyAccessClick={this.onDenyAccessItemClick}
onRemoveUserClick={this.onRemoveUserItemClick} onRemoveUserClick={this.onRemoveUserItemClick}
onShowEmbeddingPanel={this.onShowEmbeddingPanel} onShowEmbeddingPanel={this.onShowEmbeddingPanel}
onToggleLink={this.onToggleLink} onToggleLink={this.onToggleLink}
onShowChangeOwnerPanel={this.onShowChangeOwnerPanel}
isLoading={isLoading}
/> />
))} ))}
{isNotifyUsers && ( {isNotifyUsers && (
@ -781,6 +486,7 @@ class SharingPanelComponent extends React.Component {
placeholder={t("AddShareMessage")} placeholder={t("AddShareMessage")}
onChange={this.onChangeMessage} onChange={this.onChangeMessage}
value={message} value={message}
isDisabled={isLoading}
/> />
</div> </div>
)} )}
@ -791,6 +497,7 @@ class SharingPanelComponent extends React.Component {
label={t("Notify users")} label={t("Notify users")}
onChange={this.onNotifyUsersChange} onChange={this.onNotifyUsersChange}
className="sharing_panel-checkbox" className="sharing_panel-checkbox"
isDisabled={isLoading}
/> />
<Button <Button
className="sharing_panel-button" className="sharing_panel-button"
@ -798,6 +505,7 @@ class SharingPanelComponent extends React.Component {
size="big" size="big"
primary primary
onClick={this.onSaveClick} onClick={this.onSaveClick}
isDisabled={isLoading}
/> />
</StyledFooter> </StyledFooter>
</StyledContent> </StyledContent>
@ -808,11 +516,11 @@ class SharingPanelComponent extends React.Component {
onSharingPanelClose={this.onClose} onSharingPanelClose={this.onClose}
onClose={this.onShowUsersPanel} onClose={this.onShowUsersPanel}
visible={showAddUsersPanel} visible={showAddUsersPanel}
embeddedComponent={accessOptionsComboBox}
accessRight={accessRight}
shareDataItems={shareDataItems} shareDataItems={shareDataItems}
setShareDataItems={this.setShareDataItems} setShareDataItems={this.setShareDataItems}
groupsCaption={groupsCaption} groupsCaption={groupsCaption}
accessOptions={accessOptions}
isMultiSelect
/> />
)} )}
@ -821,8 +529,18 @@ class SharingPanelComponent extends React.Component {
onSharingPanelClose={this.onClose} onSharingPanelClose={this.onClose}
onClose={this.onShowGroupsPanel} onClose={this.onShowGroupsPanel}
visible={showAddGroupsPanel} visible={showAddGroupsPanel}
embeddedComponent={accessOptionsComboBox} shareDataItems={shareDataItems}
accessRight={accessRight} setShareDataItems={this.setShareDataItems}
accessOptions={accessOptions}
isMultiSelect
/>
)}
{showChangeOwnerPanel && (
<AddUsersPanel
onSharingPanelClose={this.onClose}
onClose={this.onShowChangeOwnerPanel}
visible={showChangeOwnerPanel}
shareDataItems={shareDataItems} shareDataItems={shareDataItems}
setShareDataItems={this.setShareDataItems} setShareDataItems={this.setShareDataItems}
/> />
@ -851,17 +569,24 @@ const SharingPanel = (props) => (
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
getAccessOption: (selectedItems) => getAccessOption(state, selectedItems), getAccessOption: (selection) => getAccessOption(state, selection),
getExternalAccessOption: (selectedItems) => getExternalAccessOption: (selection) =>
getExternalAccessOption(state, selectedItems), getExternalAccessOption(state, selection),
isMyId: getCurrentUserId(state), isMyId: getCurrentUserId(state),
selectedItems: getSelection(state), selection: getSelection(state),
groupsCaption: getSettingsCustomNamesGroupsCaption(state), groupsCaption: getSettingsCustomNamesGroupsCaption(state),
sharingPanelVisible: getSharePanelVisible(state), sharingPanelVisible: getSharePanelVisible(state),
canShareOwnerChange: getCanShareOwnerChange(state),
isLoading: getIsLoading(state),
files: getFiles(state),
folders: getFolders(state),
settings: getSettings(state), settings: getSettings(state),
}; };
}; };
export default connect(mapStateToProps, { setSharingPanelVisible })( export default connect(mapStateToProps, {
withRouter(SharingPanel) setSharingPanelVisible,
); setIsLoading,
setFiles,
setFolders,
})(withRouter(SharingPanel));

View File

@ -1,12 +1,12 @@
import React from "react"; import React from "react";
import { Row, LinkWithDropdown, ToggleButton, Icons } from "asc-web-components"; import { Row, LinkWithDropdown, ToggleButton, Icons } from "asc-web-components";
import { StyledLinkRow } from "../StyledPanels"; import { StyledLinkRow } from "../StyledPanels";
import AccessComboBox from "./AccessComboBox";
import { constants } from "asc-web-common"; import { constants } from "asc-web-common";
const { ShareAccessRights } = constants; const { ShareAccessRights } = constants;
class LinkRow extends React.Component { class LinkRow extends React.Component {
onToggleButtonChange = () => { onToggleButtonChange = () => {
const { onToggleLink, item } = this.props; const { onToggleLink, item } = this.props;
@ -19,14 +19,16 @@ class LinkRow extends React.Component {
options, options,
index, index,
t, t,
embeddedComponentRender,
externalAccessOptions,
item, item,
withToggle, withToggle,
externalAccessOptions,
onChangeItemAccess,
isLoading,
} = this.props; } = this.props;
const isChecked = item.rights.accessNumber !== ShareAccessRights.DenyAccess; const isChecked = item.access !== ShareAccessRights.DenyAccess;
const isDisabled = withToggle ? !isChecked : false; const disableLink = withToggle ? !isChecked : false;
const isDisabled = isLoading || disableLink;
return ( return (
<StyledLinkRow withToggle={withToggle} isDisabled={isDisabled}> <StyledLinkRow withToggle={withToggle} isDisabled={isDisabled}>
@ -35,7 +37,15 @@ class LinkRow extends React.Component {
key={`${linkText}-key_${index}`} key={`${linkText}-key_${index}`}
element={ element={
withToggle ? ( withToggle ? (
embeddedComponentRender(externalAccessOptions, item, isDisabled) <AccessComboBox
t={t}
access={item.access}
directionX="left"
accessOptions={externalAccessOptions}
onAccessChange={onChangeItemAccess}
itemId={item.sharedTo.id}
isDisabled={isDisabled}
/>
) : ( ) : (
<Icons.AccessEditIcon <Icons.AccessEditIcon
size="medium" size="medium"
@ -48,7 +58,7 @@ class LinkRow extends React.Component {
<> <>
<LinkWithDropdown <LinkWithDropdown
className="sharing_panel-link" className="sharing_panel-link"
color="#333333" color="#333"
dropdownType="alwaysDashed" dropdownType="alwaysDashed"
data={options} data={options}
fontSize="14px" fontSize="14px"
@ -62,6 +72,7 @@ class LinkRow extends React.Component {
<ToggleButton <ToggleButton
isChecked={isChecked} isChecked={isChecked}
onChange={this.onToggleButtonChange} onChange={this.onToggleButtonChange}
isDisabled={isLoading}
/> />
</div> </div>
)} )}

View File

@ -14,5 +14,17 @@
"ShareVia": "Share via", "ShareVia": "Share via",
"Embedding": "Embedding", "Embedding": "Embedding",
"ExternalLink": "External link", "ExternalLink": "External link",
"InternalLink": "Internal link" "InternalLink": "Internal link",
}
"FullAccess": "Full access",
"ReadOnly": "Read only",
"Review": "Review",
"Comment": "Comment",
"FormFilling": "Form filling",
"DenyAccess": "Deny access",
"CustomFilter": "Custom filter",
"ShareEveryone": "Everyone",
"ShareEmailSubject": "You have been granted access to the {{itemName}} document",
"ShareEmailBody": "You have been granted access to the {{itemName}} document. Click the link below to open the document right now: {{shareLink}}"
}

View File

@ -14,5 +14,17 @@
"ShareVia": "Отправить по", "ShareVia": "Отправить по",
"Embedding": "Встраивание", "Embedding": "Встраивание",
"ExternalLink": "Внешняя ссылка", "ExternalLink": "Внешняя ссылка",
"InternalLink": "Внутренняя ссылка" "InternalLink": "Внутренняя ссылка",
"FullAccess": "Полный доступ",
"ReadOnly": "Только чтение",
"Review": "Рецензирование",
"Comment": "Комментирование",
"FormFilling": "Заполнение форм",
"DenyAccess": "Доступ запрещён",
"CustomFilter": "Пользовательский фильтр",
"ShareEveryone": "Все",
"ShareEmailSubject": "Вам предоставлен доступ к документу {{itemName}}",
"ShareEmailBody": "Вам предоставлен доступ к документу {{itemName}}. Нажмите на ссылку ниже, чтобы открыть документ прямо сейчас: {{shareLink}}"
} }

View File

@ -161,6 +161,12 @@ const StyledContent = styled.div`
.header_aside-panel-plus-icon { .header_aside-panel-plus-icon {
margin-left: auto; margin-left: auto;
} }
.sharing-access-combo-box-icon {
path {
fill: ${(props) => (props.isDisabled ? "#D0D5DA" : "#A3A9AE")};
}
}
`; `;
const StyledHeaderContent = styled.div` const StyledHeaderContent = styled.div`
@ -282,6 +288,12 @@ const StyledBody = styled.div`
margin: 8px; margin: 8px;
right: 16px; right: 16px;
} }
.sharing-access-combo-box-icon {
path {
fill: #333;
}
}
`; `;
const StyledSharingBody = styled(Scrollbar)` const StyledSharingBody = styled(Scrollbar)`
@ -339,12 +351,6 @@ const StyledSharingBody = styled(Scrollbar)`
} }
} }
.sharing-access-combo-box-icon {
path {
fill: #a3a9ae;
}
}
.sharing_panel-owner-icon { .sharing_panel-owner-icon {
padding-right: 19px; padding-right: 19px;
} }

View File

@ -574,40 +574,35 @@ export function setShareFiles(
share, share,
notify, notify,
sharingMessage, sharingMessage,
externalAccess externalAccess,
ownerId
) { ) {
const foldersRequests = folderIds.map((id) =>
files.setShareFolder(id, share, notify, sharingMessage)
);
const filesRequests = fileIds.map((id) =>
files.setShareFiles(id, share, notify, sharingMessage)
);
let externalAccessRequest = []; let externalAccessRequest = [];
if (fileIds.length === 1 && externalAccess !== null) { if (fileIds.length === 1 && externalAccess !== null) {
externalAccessRequest = fileIds.map((id) => externalAccessRequest = fileIds.map((id) =>
files.setExternalAccess(id, externalAccess) files.setExternalAccess(id, externalAccess)
); );
} }
const ownerChangeRequest = ownerId
? [files.setFileOwner(folderIds, fileIds, ownerId)]
: [];
const shareRequest = !!share.length
? [files.setShareFiles(fileIds, folderIds, share, notify, sharingMessage)]
: [];
const requests = [ const requests = [
...foldersRequests, ...ownerChangeRequest,
...filesRequests, ...shareRequest,
...externalAccessRequest, ...externalAccessRequest,
]; ];
return axios.all(requests); return axios.all(requests);
} }
export function getShareUsers(folderIds, fileIds) { export function getShareUsers(folderIds, fileIds) {
const foldersRequests = folderIds.map((folderId) => return files.getShareFiles(fileIds, folderIds);
files.getShareFolders(folderId)
);
const filesRequests = fileIds.map((fileId) => files.getShareFiles(fileId));
const requests = [...foldersRequests, ...filesRequests];
return axios.all(requests).then((res) => res);
} }
export function clearPrimaryProgressData() { export function clearPrimaryProgressData() {

View File

@ -10,6 +10,29 @@ const presentInArray = (array, search) => {
return result === -1 ? false : true; return result === -1 ? false : true;
}; };
export const getAccessIcon = (access) => {
switch (access) {
case 1:
return "AccessEditIcon";
case 2:
return "EyeIcon";
case 3:
return "AccessNoneIcon";
case 4:
return "CatalogQuestionIcon";
case 5:
return "AccessReviewIcon";
case 6:
return "AccessCommentIcon";
case 7:
return "AccessFormIcon";
case 8:
return "CustomFilterIcon";
default:
return;
}
};
export const getMediaViewerImageFormats = (state) => { export const getMediaViewerImageFormats = (state) => {
return state.files.mediaViewerFormats.images; return state.files.mediaViewerFormats.images;
}; };
@ -884,7 +907,8 @@ export const getFileActionId = (state) => {
export const getFilesList = (state) => { export const getFilesList = (state) => {
return createSelector( return createSelector(
[ [
getItemsList, getFolders,
getFiles,
getSelection, getSelection,
getIsRecycleBinFolder, getIsRecycleBinFolder,
getIsRecentFolder, getIsRecentFolder,
@ -893,7 +917,8 @@ export const getFilesList = (state) => {
isVisitor, isVisitor,
], ],
( (
items, folders,
files,
selection, selection,
isRecycleBin, isRecycleBin,
isRecent, isRecent,
@ -901,6 +926,14 @@ export const getFilesList = (state) => {
actionId, actionId,
isVisitor isVisitor
) => { ) => {
const items =
folders && files
? [...folders, ...files]
: folders
? folders
: files
? files
: [];
return items.map((item) => { return items.map((item) => {
const { const {
access, access,
@ -1257,6 +1290,15 @@ export const getSharePanelVisible = (state) => {
return state.files.sharingPanelVisible; return state.files.sharingPanelVisible;
}; };
export const getCanShareOwnerChange = createSelector(
isAdmin,
getPathParts,
getCommonFolderId,
(isAdmin, pathParts, commonId) => {
return isAdmin && commonId === pathParts[0];
}
);
export const isSecondaryProgressFinished = createSelector( export const isSecondaryProgressFinished = createSelector(
getSecondaryProgressData, getSecondaryProgressData,
(data) => { (data) => {

View File

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

View File

@ -382,17 +382,12 @@ export function removeFiles(folderIds, fileIds, deleteAfter, immediately) {
return request({ method: "put", url: "/files/fileops/delete", data }); return request({ method: "put", url: "/files/fileops/delete", data });
} }
export function getShareFolders(folderId) { export function getShareFiles(fileIds, folderIds) {
const data = { fileIds, folderIds };
return request({ return request({
method: "get", method: "post",
url: `/files/folder/${folderId}/share`, url: "/files/share",
}); data,
}
export function getShareFiles(fileId) {
return request({
method: "get",
url: `/files/file/${fileId}/share`,
}); });
} }
@ -405,18 +400,29 @@ export function setExternalAccess(fileId, accessType) {
}); });
} }
export function setShareFolder(folderId, share, notify, sharingMessage) { export function setShareFiles(
const data = { share, notify, sharingMessage }; fileIds,
folderIds,
share,
notify,
sharingMessage
) {
const data = { fileIds, folderIds, share, notify, sharingMessage };
return request({ return request({
method: "put", method: "put",
url: `/files/folder/${folderId}/share`, url: "/files/share",
data, data,
}); });
} }
export function setShareFiles(fileId, share, notify, sharingMessage) { export function setFileOwner(folderIds, fileIds, userId) {
const data = { share, notify, sharingMessage }; const data = { folderIds, fileIds, userId };
return request({ method: "put", url: `/files/file/${fileId}/share`, data }); return request({
method: "post",
url: "/files/owner",
data,
});
} }
export function startUploadSession(folderId, fileName, fileSize, relativePath) { export function startUploadSession(folderId, fileName, fileSize, relativePath) {

View File

@ -99,6 +99,9 @@ class PeopleSelector extends React.Component {
if (role) { if (role) {
filter.role = role; filter.role = role;
} }
if (employeeStatus) {
filter.employeeStatus = employeeStatus;
}
if (currentGroup && currentGroup !== "all") filter.group = currentGroup; if (currentGroup && currentGroup !== "all") filter.group = currentGroup;
@ -281,6 +284,7 @@ PeopleSelector.propTypes = {
groupsCaption: PropTypes.string, groupsCaption: PropTypes.string,
searchPlaceHolderLabel: PropTypes.string, searchPlaceHolderLabel: PropTypes.string,
role: PropTypes.oneOf(["admin", "user", "guest"]), role: PropTypes.oneOf(["admin", "user", "guest"]),
employeeStatus: PropTypes.any,
displayType: PropTypes.oneOf(["auto", "aside", "dropdown"]), displayType: PropTypes.oneOf(["auto", "aside", "dropdown"]),
withoutAside: PropTypes.bool, withoutAside: PropTypes.bool,
embeddedComponent: PropTypes.any, embeddedComponent: PropTypes.any,

View File

@ -92,9 +92,11 @@ export const FolderType = Object.freeze({
}); });
export const ShareAccessRights = Object.freeze({ export const ShareAccessRights = Object.freeze({
None: 0,
FullAccess: 1, FullAccess: 1,
ReadOnly: 2, ReadOnly: 2,
DenyAccess: 3, DenyAccess: 3,
Varies: 4,
Review: 5, Review: 5,
Comment: 6, Comment: 6,
FormFilling: 7, FormFilling: 7,