Web: Files: added public-room editing
This commit is contained in:
parent
6c727811a0
commit
3a3c4a6d3c
@ -44,9 +44,6 @@ import { ComboBox, TOption } from "@docspace/shared/components/combobox";
|
||||
import { TData } from "@docspace/shared/components/toast/Toast.type";
|
||||
import { TTranslation } from "@docspace/shared/types";
|
||||
import { TColorScheme, TTheme } from "@docspace/shared/themes";
|
||||
|
||||
import { SettingsStore } from "@docspace/shared/store/SettingsStore";
|
||||
import { UserStore } from "@docspace/shared/store/UserStore";
|
||||
import {
|
||||
ModalDialog,
|
||||
ModalDialogType,
|
||||
@ -65,8 +62,6 @@ import { StyledModalDialog, StyledBody } from "./StyledEmbeddingPanel";
|
||||
|
||||
import { DisplayBlock } from "./sub-components/DisplayBlock";
|
||||
import { CheckboxElement } from "./sub-components/CheckboxElement";
|
||||
import PublicRoomStore from "../../../store/PublicRoomStore";
|
||||
import DialogsStore from "../../../store/DialogsStore";
|
||||
|
||||
type LinkParamsLinkShareToType = {
|
||||
denyDownload: boolean;
|
||||
|
@ -29,7 +29,7 @@ import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
import { RoomsType, ShareAccessRights } from "@docspace/shared/enums";
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
import { LINKS_LIMIT_COUNT } from "@docspace/shared/constants";
|
||||
import InfoPanelViewLoader from "@docspace/shared/skeletons/info-panel/body";
|
||||
import MembersHelper from "../../helpers/MembersHelper";
|
||||
@ -182,6 +182,7 @@ const Members = ({
|
||||
key="general-link"
|
||||
link={primaryLink}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
isShareLink
|
||||
/>,
|
||||
);
|
||||
}
|
||||
@ -193,6 +194,7 @@ const Members = ({
|
||||
link={link}
|
||||
key={link?.sharedTo?.id}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
isShareLink
|
||||
/>,
|
||||
);
|
||||
});
|
||||
@ -202,6 +204,7 @@ const Members = ({
|
||||
key="create-additional-link"
|
||||
className="additional-link"
|
||||
onClick={onAddNewLink}
|
||||
isShareLink
|
||||
>
|
||||
<div className="create-link-icon">
|
||||
<IconButton size={12} iconName={PlusIcon} isDisabled />
|
||||
|
@ -24,70 +24,75 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { ContextMenuButton } from "@docspace/shared/components/context-menu-button";
|
||||
import moment from "moment";
|
||||
import LinkRowComponent from "@docspace/shared/components/share/sub-components/LinkRow";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import CopyReactSvgUrl from "PUBLIC_DIR/images/copy.react.svg?url";
|
||||
import LinkReactSvgUrl from "PUBLIC_DIR/images/tablet-link.react.svg?url";
|
||||
import SettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url";
|
||||
import ShareReactSvgUrl from "PUBLIC_DIR/images/share.react.svg?url";
|
||||
import CodeReactSvgUrl from "PUBLIC_DIR/images/code.react.svg?url";
|
||||
import CopyToReactSvgUrl from "PUBLIC_DIR/images/copyTo.react.svg?url";
|
||||
import OutlineReactSvgUrl from "PUBLIC_DIR/images/outline-true.react.svg?url";
|
||||
import LockedReactSvgUrl from "PUBLIC_DIR/images/locked.react.svg?url";
|
||||
import LoadedReactSvgUrl from "PUBLIC_DIR/images/loaded.react.svg?url";
|
||||
import TrashReactSvgUrl from "PUBLIC_DIR/images/trash.react.svg?url";
|
||||
import ClockReactSvg from "PUBLIC_DIR/images/clock.react.svg";
|
||||
import moment from "moment-timezone";
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
import { TTranslation } from "@docspace/shared/types";
|
||||
import { TFileLink } from "@docspace/shared/api/files/types";
|
||||
import { useState } from "react";
|
||||
import { TOption } from "@docspace/shared/components/combobox";
|
||||
|
||||
import { StyledLinkRow } from "./Styled";
|
||||
type LinkRowProps = {
|
||||
t: TTranslation;
|
||||
link: TFileLink;
|
||||
roomId: string | number;
|
||||
setLinkParams: (linkParams: {
|
||||
roomId: number | string;
|
||||
isEdit?: boolean;
|
||||
link: TFileLink;
|
||||
isPublic?: boolean;
|
||||
isFormRoom?: boolean;
|
||||
}) => void;
|
||||
setEditLinkPanelIsVisible: (value: boolean) => void;
|
||||
setDeleteLinkDialogVisible: (value: boolean) => void;
|
||||
setEmbeddingPanelData: (value: {
|
||||
visible: boolean;
|
||||
itemId?: string | number;
|
||||
}) => void;
|
||||
|
||||
const LinkRow = (props) => {
|
||||
isArchiveFolder: boolean;
|
||||
setIsScrollLocked: (isScrollLocked: boolean) => void;
|
||||
isPublicRoomType: boolean;
|
||||
isFormRoom: boolean;
|
||||
};
|
||||
|
||||
const LinkRow = (props: LinkRowProps) => {
|
||||
const {
|
||||
t,
|
||||
link,
|
||||
roomId,
|
||||
setLinkParams,
|
||||
setExternalLink,
|
||||
editExternalLink,
|
||||
setEditLinkPanelIsVisible,
|
||||
setDeleteLinkDialogVisible,
|
||||
setEmbeddingPanelData,
|
||||
isArchiveFolder,
|
||||
theme,
|
||||
setIsScrollLocked,
|
||||
isPublicRoomType,
|
||||
isFormRoom,
|
||||
...rest
|
||||
editExternalLink,
|
||||
setExternalLink,
|
||||
} = props;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const {
|
||||
title,
|
||||
shareLink,
|
||||
password,
|
||||
disabled,
|
||||
expirationDate,
|
||||
isExpired,
|
||||
primary,
|
||||
} = link.sharedTo;
|
||||
const { title, shareLink, password, isExpired, primary } = link.sharedTo;
|
||||
|
||||
const isLocked = !!password;
|
||||
const expiryDate = !!expirationDate;
|
||||
const date = moment(expirationDate).tz(window.timezone).format("LLL");
|
||||
const isDisabled = isExpired;
|
||||
|
||||
const tooltipContent = isExpired
|
||||
? t("Translations:LinkHasExpiredAndHasBeenDisabled")
|
||||
: t("Translations:PublicRoomLinkValidTime", { date });
|
||||
const [loadingLinks, setLoadingLinks] = useState<(string | number)[]>([]);
|
||||
|
||||
const onCloseContextMenu = () => {
|
||||
setIsScrollLocked(false);
|
||||
};
|
||||
|
||||
const onEditLink = () => {
|
||||
setEditLinkPanelIsVisible(true);
|
||||
@ -101,33 +106,11 @@ const LinkRow = (props) => {
|
||||
onCloseContextMenu();
|
||||
};
|
||||
|
||||
// const onDisableLink = () => {
|
||||
// if (isExpired) {
|
||||
// setEditLinkPanelIsVisible(true);
|
||||
// setLinkParams({ isEdit: true, link, roomId, isPublic: isPublicRoomType, isFormRoom });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// setIsLoading(true);
|
||||
|
||||
// const newLink = JSON.parse(JSON.stringify(link));
|
||||
// newLink.sharedTo.disabled = !newLink.sharedTo.disabled;
|
||||
|
||||
// editExternalLink(roomId, newLink)
|
||||
// .then((link) => {
|
||||
// setExternalLink(link);
|
||||
|
||||
// disabled
|
||||
// ? toastr.success(t("Files:LinkEnabledSuccessfully"))
|
||||
// : toastr.success(t("Files:LinkDisabledSuccessfully"));
|
||||
// })
|
||||
// .catch((err) => toastr.error(err?.message))
|
||||
// .finally(() => setIsLoading(false));
|
||||
// };
|
||||
|
||||
const onCopyPassword = () => {
|
||||
if (password) {
|
||||
copy(password);
|
||||
toastr.success(t("Files:PasswordSuccessfullyCopied"));
|
||||
}
|
||||
};
|
||||
|
||||
const onEmbeddingClick = () => {
|
||||
@ -152,12 +135,6 @@ const LinkRow = (props) => {
|
||||
setIsScrollLocked(true);
|
||||
};
|
||||
|
||||
const onCloseContextMenu = () => {
|
||||
setIsScrollLocked(false);
|
||||
};
|
||||
|
||||
const isDisabled = disabled || isExpired;
|
||||
|
||||
const getData = () => {
|
||||
return [
|
||||
{
|
||||
@ -166,17 +143,6 @@ const LinkRow = (props) => {
|
||||
icon: SettingsReactSvgUrl,
|
||||
onClick: onEditLink,
|
||||
},
|
||||
// {
|
||||
// key: "edit-link-separator",
|
||||
// isSeparator: true,
|
||||
// },
|
||||
// {
|
||||
// key: "share-key",
|
||||
// label: t("Files:Share"),
|
||||
// icon: ShareReactSvgUrl,
|
||||
// // onClick: () => args.onClickLabel("label2"),
|
||||
// },
|
||||
|
||||
!isDisabled && {
|
||||
key: "copy-link-settings-key",
|
||||
label: t("Files:CopySharedLink"),
|
||||
@ -184,27 +150,21 @@ const LinkRow = (props) => {
|
||||
onClick: onCopyExternalLink,
|
||||
},
|
||||
|
||||
!isDisabled &&
|
||||
isLocked && {
|
||||
key: "copy-link-password-key",
|
||||
label: t("Files:CopyLinkPassword"),
|
||||
icon: LockedReactSvgUrl,
|
||||
onClick: onCopyPassword,
|
||||
},
|
||||
|
||||
!isDisabled && {
|
||||
key: "embedding-settings-key",
|
||||
label: t("Files:EmbeddingSettings"),
|
||||
label: t("Files:Embed"),
|
||||
icon: CodeReactSvgUrl,
|
||||
onClick: onEmbeddingClick,
|
||||
},
|
||||
|
||||
// disabled
|
||||
// ? {
|
||||
// key: "enable-link-key",
|
||||
// label: t("Files:EnableLink"),
|
||||
// icon: LoadedReactSvgUrl,
|
||||
// onClick: onDisableLink,
|
||||
// }
|
||||
// : {
|
||||
// key: "disable-link-key",
|
||||
// label: t("Files:DisableLink"),
|
||||
// icon: OutlineReactSvgUrl,
|
||||
// onClick: onDisableLink,
|
||||
// },
|
||||
|
||||
{
|
||||
key: "delete-link-separator",
|
||||
isSeparator: true,
|
||||
@ -222,91 +182,65 @@ const LinkRow = (props) => {
|
||||
];
|
||||
};
|
||||
|
||||
const textColor = disabled ? theme.text.disableColor : theme.text.color;
|
||||
const editExternalLinkAction = (newLink: TFileLink) => {
|
||||
setLoadingLinks([newLink.sharedTo.id]);
|
||||
|
||||
console.log("newLink", newLink);
|
||||
|
||||
editExternalLink(roomId, newLink)
|
||||
.then((linkData: TFileLink) => {
|
||||
setExternalLink(linkData);
|
||||
setLinkParams({
|
||||
link: linkData,
|
||||
roomId,
|
||||
isPublic: isPublicRoomType,
|
||||
isFormRoom,
|
||||
});
|
||||
|
||||
copy(link?.sharedTo?.shareLink);
|
||||
toastr.success(t("Files:LinkEditedSuccessfully"));
|
||||
})
|
||||
.catch((err: Error) => toastr.error(err?.message))
|
||||
.finally(() => setLoadingLinks([]));
|
||||
};
|
||||
|
||||
const onAccessRightsSelect = (opt: TOption) => {
|
||||
const newLink = { ...link };
|
||||
if (opt.access) newLink.access = opt.access;
|
||||
editExternalLinkAction(newLink);
|
||||
};
|
||||
|
||||
const changeExpirationOption = async (
|
||||
linkData: TFileLink,
|
||||
expirationDate: moment.Moment | null,
|
||||
) => {
|
||||
const newLink = { ...link };
|
||||
newLink.sharedTo.expirationDate = moment(expirationDate);
|
||||
editExternalLinkAction(newLink);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledLinkRow
|
||||
{...rest}
|
||||
isArchiveFolder={isArchiveFolder}
|
||||
isExpired={isExpired}
|
||||
>
|
||||
<Avatar
|
||||
size="min"
|
||||
source={LinkReactSvgUrl}
|
||||
roleIcon={
|
||||
expiryDate ? (
|
||||
<div className="clock-icon">
|
||||
<ClockReactSvg />
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
withTooltip={expiryDate}
|
||||
tooltipContent={tooltipContent}
|
||||
/>
|
||||
{isArchiveFolder ? (
|
||||
<Text fontSize="14px" fontWeight={600} className="external-row-link">
|
||||
{title}
|
||||
</Text>
|
||||
) : (
|
||||
<Link
|
||||
type="action"
|
||||
fontSize="14px"
|
||||
fontWeight={600}
|
||||
onClick={onEditLink}
|
||||
isDisabled={disabled}
|
||||
color={textColor}
|
||||
className="external-row-link"
|
||||
>
|
||||
{title}
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{disabled && <Text color={textColor}>{t("Settings:Disabled")}</Text>}
|
||||
|
||||
<div className="external-row-icons">
|
||||
{!disabled && !isExpired && !isArchiveFolder && (
|
||||
<>
|
||||
{isLocked && (
|
||||
<IconButton
|
||||
className="locked-icon"
|
||||
size={16}
|
||||
iconName={LockedReactSvgUrl}
|
||||
onClick={onCopyPassword}
|
||||
title={t("Files:CopyLinkPassword")}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
className="copy-icon"
|
||||
size={16}
|
||||
iconName={CopyReactSvgUrl}
|
||||
onClick={onCopyExternalLink}
|
||||
title={t("Files:CopySharedLink")}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!isArchiveFolder && (
|
||||
<ContextMenuButton
|
||||
<LinkRowComponent
|
||||
loadingLinks={loadingLinks}
|
||||
links={[link]}
|
||||
getData={getData}
|
||||
isDisabled={isLoading}
|
||||
title={t("Files:ShowLinkActions")}
|
||||
directionY="both"
|
||||
onClick={onOpenContextMenu}
|
||||
onClose={onCloseContextMenu}
|
||||
onOpenContextMenu={onOpenContextMenu}
|
||||
onCloseContextMenu={onCloseContextMenu}
|
||||
isRoom
|
||||
linkTitle={title}
|
||||
onAccessRightsSelect={onAccessRightsSelect}
|
||||
changeExpirationOption={changeExpirationOption}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</StyledLinkRow>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(
|
||||
export default inject<TStore>(
|
||||
({
|
||||
settingsStore,
|
||||
dialogsStore,
|
||||
publicRoomStore,
|
||||
treeFoldersStore,
|
||||
infoPanelStore,
|
||||
publicRoomStore,
|
||||
}) => {
|
||||
const { infoPanelSelection } = infoPanelStore;
|
||||
const { theme } = settingsStore;
|
||||
@ -317,23 +251,25 @@ export default inject(
|
||||
setEmbeddingPanelData,
|
||||
setLinkParams,
|
||||
} = dialogsStore;
|
||||
const { editExternalLink, setExternalLink } = publicRoomStore;
|
||||
const { isArchiveFolderRoot } = treeFoldersStore;
|
||||
|
||||
const { id, roomType } = infoPanelSelection!;
|
||||
|
||||
const { editExternalLink, setExternalLink } = publicRoomStore;
|
||||
|
||||
return {
|
||||
setLinkParams,
|
||||
editExternalLink,
|
||||
roomId: infoPanelSelection.id,
|
||||
setExternalLink,
|
||||
roomId: id,
|
||||
setEditLinkPanelIsVisible,
|
||||
setDeleteLinkDialogVisible,
|
||||
setEmbeddingPanelData,
|
||||
isArchiveFolder: isArchiveFolderRoot,
|
||||
theme,
|
||||
isPublicRoomType:
|
||||
infoPanelSelection.roomType === RoomsType.PublicRoom ||
|
||||
infoPanelSelection.roomType === RoomsType.FormRoom,
|
||||
isFormRoom: infoPanelSelection?.roomType === RoomsType.FormRoom,
|
||||
roomType === RoomsType.PublicRoom || roomType === RoomsType.FormRoom,
|
||||
isFormRoom: roomType === RoomsType.FormRoom,
|
||||
editExternalLink,
|
||||
setExternalLink,
|
||||
};
|
||||
},
|
||||
)(
|
@ -77,6 +77,7 @@ const StyledList = styled(List)`
|
||||
`;
|
||||
|
||||
const itemSize = 48;
|
||||
const shareLinkItemSize = 68;
|
||||
|
||||
const MembersList = (props) => {
|
||||
const {
|
||||
@ -150,6 +151,16 @@ const MembersList = (props) => {
|
||||
[isNextPageLoading, loadNextPage],
|
||||
);
|
||||
|
||||
const getItemSize = ({ index }) => {
|
||||
const elem = list[index];
|
||||
|
||||
if (elem?.props?.isShareLink) {
|
||||
return shareLinkItemSize;
|
||||
}
|
||||
|
||||
return itemSize;
|
||||
};
|
||||
|
||||
const onScroll = (e) => {
|
||||
const header = document.getElementById("members-list-header");
|
||||
|
||||
@ -220,7 +231,7 @@ const MembersList = (props) => {
|
||||
onRowsRendered={onRowsRendered}
|
||||
ref={registerChild}
|
||||
rowCount={itemsCount}
|
||||
rowHeight={itemSize}
|
||||
rowHeight={getItemSize}
|
||||
rowRenderer={renderRow}
|
||||
width={width}
|
||||
isScrolling={isScrolling}
|
||||
|
@ -24,6 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import moment from "moment";
|
||||
import { TCreatedBy, TPathParts } from "../../types";
|
||||
import { TUser } from "../people/types";
|
||||
import {
|
||||
@ -394,9 +395,11 @@ export type TFileLink = {
|
||||
requestToken: string;
|
||||
shareLink: string;
|
||||
title: string;
|
||||
expirationDate?: string;
|
||||
expirationDate?: moment.Moment | null;
|
||||
internal?: boolean;
|
||||
password?: string;
|
||||
};
|
||||
subjectType: number;
|
||||
};
|
||||
|
||||
export type TFilesUsedSpace = {
|
||||
|
@ -27,7 +27,7 @@
|
||||
/* eslint-disable @typescript-eslint/default-param-last */
|
||||
import { AxiosRequestConfig } from "axios";
|
||||
|
||||
import { FolderType, MembersSubjectType } from "../../enums";
|
||||
import { FolderType, MembersSubjectType, ShareAccessRights } from "../../enums";
|
||||
import { request } from "../client";
|
||||
import {
|
||||
checkFilterInstance,
|
||||
@ -36,6 +36,7 @@ import {
|
||||
} from "../../utils/common";
|
||||
import RoomsFilter from "./filter";
|
||||
import { TGetRooms } from "./types";
|
||||
import moment from "moment";
|
||||
|
||||
export async function getRooms(filter: RoomsFilter, signal?: AbortSignal) {
|
||||
let params;
|
||||
@ -394,15 +395,15 @@ export const acceptInvitationByLink = async () => {
|
||||
};
|
||||
|
||||
export function editExternalLink(
|
||||
roomId,
|
||||
linkId,
|
||||
title,
|
||||
access,
|
||||
expirationDate,
|
||||
linkType,
|
||||
password,
|
||||
disabled,
|
||||
denyDownload,
|
||||
roomId: number | string,
|
||||
linkId: number | string,
|
||||
title: string,
|
||||
access: ShareAccessRights,
|
||||
expirationDate: moment.Moment,
|
||||
linkType: number,
|
||||
password: string,
|
||||
disabled: boolean,
|
||||
denyDownload: boolean,
|
||||
) {
|
||||
return request({
|
||||
method: "put",
|
||||
|
@ -43,6 +43,25 @@ const StyledWrapper = styled(ComboBox)`
|
||||
`}
|
||||
}
|
||||
|
||||
${({ type, theme }) =>
|
||||
type === "onlyIcon" &&
|
||||
css`
|
||||
.combo-button {
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.combo-button_selected-icon-container {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.combo-buttons_arrow-icon,
|
||||
.combo-button_selected-icon-container {
|
||||
svg path {
|
||||
fill: ${theme.iconButton.color};
|
||||
}
|
||||
}
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
.backdrop-active {
|
||||
top: -64px;
|
||||
@ -84,8 +103,16 @@ const StyledItemDescription = styled.div`
|
||||
|
||||
StyledItemDescription.defaultProps = { theme: Base };
|
||||
|
||||
const StyledItemIcon = styled.img`
|
||||
margin-right: 8px;
|
||||
const StyledItemIcon = styled.img<{ isShortenIcon?: boolean }>`
|
||||
padding-inline-end: 8px;
|
||||
|
||||
${({ isShortenIcon }) =>
|
||||
isShortenIcon &&
|
||||
css`
|
||||
padding-top: 2px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledItemContent = styled.div`
|
||||
|
@ -46,6 +46,7 @@ export const AccessRightSelectPure = ({
|
||||
advancedOptions,
|
||||
selectedOption,
|
||||
className,
|
||||
type,
|
||||
...props
|
||||
}: AccessRightSelectProps) => {
|
||||
const [currentItem, setCurrentItem] = useState(selectedOption);
|
||||
@ -76,7 +77,12 @@ export const AccessRightSelectPure = ({
|
||||
onClick={() => onSelectCurrentItem(item)}
|
||||
>
|
||||
<StyledItem>
|
||||
{item.icon && <StyledItemIcon src={item.icon} />}
|
||||
{item.icon && (
|
||||
<StyledItemIcon
|
||||
src={item.icon}
|
||||
isShortenIcon={type === "onlyIcon"}
|
||||
/>
|
||||
)}
|
||||
<StyledItemContent>
|
||||
<StyledItemTitle>
|
||||
{item.label}
|
||||
@ -108,6 +114,7 @@ export const AccessRightSelectPure = ({
|
||||
return (
|
||||
<StyledWrapper
|
||||
className={className}
|
||||
type={type}
|
||||
advancedOptions={formattedOptions}
|
||||
onSelect={onSelectCurrentItem}
|
||||
options={[]}
|
||||
@ -116,7 +123,7 @@ export const AccessRightSelectPure = ({
|
||||
icon: currentItem?.icon,
|
||||
default: true,
|
||||
key: currentItem?.key,
|
||||
label: currentItem?.label,
|
||||
label: type === "onlyIcon" ? "" : currentItem?.label,
|
||||
} as TOption
|
||||
}
|
||||
forceCloseClickOutside
|
||||
|
@ -44,6 +44,8 @@ type PropsFromCombobox = Pick<
|
||||
| "withoutBackground"
|
||||
| "withBackground"
|
||||
| "withBlur"
|
||||
| "type"
|
||||
| "noBorder"
|
||||
>;
|
||||
|
||||
export type AccessRightSelectProps = PropsFromCombobox & {
|
||||
|
@ -77,7 +77,7 @@ export interface ContextMenuButtonProps {
|
||||
/** Sets the number of columns */
|
||||
columnCount?: number;
|
||||
/** Sets the display type */
|
||||
displayType: ContextMenuButtonDisplayType;
|
||||
displayType?: ContextMenuButtonDisplayType;
|
||||
/** Closing event */
|
||||
onClose?: () => void;
|
||||
/** Sets the drop down open with the portal */
|
||||
|
@ -115,6 +115,41 @@ export const getAccessOptions = (
|
||||
return items;
|
||||
};
|
||||
|
||||
export const getRoomAccessOptions = (t: TTranslation) => {
|
||||
return [
|
||||
{
|
||||
access: ShareAccessRights.Editing,
|
||||
description:
|
||||
"Operations with existing files: viewing, editing, form filling, reviewing, commenting.",
|
||||
key: "editing",
|
||||
label: t("Common:Editor"),
|
||||
icon: AccessEditReactSvgUrl,
|
||||
},
|
||||
{
|
||||
access: ShareAccessRights.Review,
|
||||
description:
|
||||
"Operations with existing files: viewing, reviewing, commenting.",
|
||||
key: "review",
|
||||
label: t("Translations:RoleReviewer"),
|
||||
icon: AccessReviewReactSvgUrl,
|
||||
},
|
||||
{
|
||||
access: ShareAccessRights.Comment,
|
||||
description: "Operations with existing files: viewing, commenting.",
|
||||
key: "commenting",
|
||||
label: t("Commentator"),
|
||||
icon: AccessCommentReactSvgUrl,
|
||||
},
|
||||
{
|
||||
access: ShareAccessRights.ReadOnly,
|
||||
description: "File viewing",
|
||||
key: "viewing",
|
||||
label: t("JavascriptSdk:Viewer"),
|
||||
icon: EyeReactSvgUrl,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const getExpiredOptions = (
|
||||
t: TTranslation,
|
||||
setTwelveHours: VoidFunction,
|
||||
|
@ -24,7 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import styled from "styled-components";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
const StyledLinks = styled.div`
|
||||
margin-top: 20px;
|
||||
@ -49,12 +49,29 @@ const StyledLinks = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledLinkRow = styled.div`
|
||||
const StyledLinkRow = styled.div<{ isExpired?: boolean }>`
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
|
||||
.avatar_role-wrapper {
|
||||
/* svg {
|
||||
path {
|
||||
fill: ${({ isExpired, theme }) =>
|
||||
isExpired
|
||||
? theme.infoPanel.links.iconErrorColor
|
||||
: theme.infoPanel.links.iconColor};
|
||||
}
|
||||
} */
|
||||
|
||||
svg {
|
||||
path:nth-child(3) {
|
||||
fill: ${({ theme }) => theme.backgroundColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.combo-box {
|
||||
padding: 0;
|
||||
}
|
||||
@ -71,14 +88,23 @@ const StyledLinkRow = styled.div`
|
||||
|
||||
.internal-combobox {
|
||||
padding: 0px;
|
||||
|
||||
.combo-button-label {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.internal-combobox_expiered {
|
||||
.link-options_title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
margin: 6px 8px;
|
||||
color: ${({ theme }) => theme.infoPanel.members.linkAccessComboboxExpired};
|
||||
|
||||
${({ theme, isExpired }) =>
|
||||
isExpired &&
|
||||
css`
|
||||
color: ${theme.infoPanel.members.linkAccessComboboxExpired};
|
||||
`};
|
||||
}
|
||||
|
||||
.expired-options {
|
||||
@ -91,6 +117,7 @@ const StyledLinkRow = styled.div`
|
||||
|
||||
.expire-text {
|
||||
margin-inline-start: 8px;
|
||||
color: ${({ theme }) => theme.infoPanel.links.primaryColor};
|
||||
}
|
||||
|
||||
.link-actions {
|
||||
@ -98,6 +125,11 @@ const StyledLinkRow = styled.div`
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
margin-inline-start: auto;
|
||||
|
||||
.link-row_copy-icon {
|
||||
min-width: 16px;
|
||||
min-height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
|
@ -150,7 +150,7 @@ const ExpiredComboBox = ({
|
||||
</Trans>
|
||||
);
|
||||
}
|
||||
const date = t("Common:Unlimited");
|
||||
const date = t("Common:Unlimited").toLowerCase();
|
||||
|
||||
return (
|
||||
<Trans t={t} i18nKey="LinkIsValid" ns="Common">
|
||||
|
@ -30,6 +30,7 @@ import PlusIcon from "PUBLIC_DIR/images/plus.react.svg?url";
|
||||
import UniverseIcon from "PUBLIC_DIR/images/universe.react.svg?url";
|
||||
import PeopleIcon from "PUBLIC_DIR/images/people.react.svg?url";
|
||||
import CopyIcon from "PUBLIC_DIR/images/copy.react.svg?url";
|
||||
import LockedReactSvg from "PUBLIC_DIR/images/icons/12/locked.react.svg";
|
||||
|
||||
import { RowSkeleton } from "../../../skeletons/share";
|
||||
import { TFileLink } from "../../../api/files/types";
|
||||
@ -43,11 +44,18 @@ import { Loader, LoaderTypes } from "../../loader";
|
||||
import { Text } from "../../text";
|
||||
|
||||
import { StyledLinkRow, StyledSquare } from "../Share.styled";
|
||||
import { getShareOptions, getAccessOptions } from "../Share.helpers";
|
||||
import {
|
||||
getShareOptions,
|
||||
getAccessOptions,
|
||||
getRoomAccessOptions,
|
||||
} from "../Share.helpers";
|
||||
import { LinkRowProps } from "../Share.types";
|
||||
|
||||
import ExpiredComboBox from "./ExpiredComboBox";
|
||||
|
||||
import { AccessRightSelect } from "../../access-right-select";
|
||||
import { ContextMenuButton } from "../../context-menu-button";
|
||||
|
||||
const LinkRow = ({
|
||||
onAddClick,
|
||||
links,
|
||||
@ -56,11 +64,22 @@ const LinkRow = ({
|
||||
changeExpirationOption,
|
||||
availableExternalRights,
|
||||
loadingLinks,
|
||||
|
||||
isRoom,
|
||||
linkTitle,
|
||||
getData,
|
||||
onOpenContextMenu,
|
||||
onCloseContextMenu,
|
||||
onAccessRightsSelect,
|
||||
}: LinkRowProps) => {
|
||||
const { t } = useTranslation(["Common"]);
|
||||
const { t } = useTranslation(["Common", "Translations"]);
|
||||
|
||||
const shareOptions = getShareOptions(t) as TOption[];
|
||||
const accessOptions = getAccessOptions(t, availableExternalRights);
|
||||
const accessOptions = availableExternalRights
|
||||
? getAccessOptions(t, availableExternalRights)
|
||||
: [];
|
||||
|
||||
const roomAccessOptions = isRoom ? getRoomAccessOptions(t) : [];
|
||||
|
||||
const onCopyLink = (link: TFileLink) => {
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
@ -88,14 +107,24 @@ const LinkRow = ({
|
||||
(option) =>
|
||||
option && "access" in option && option.access === link.access,
|
||||
);
|
||||
|
||||
const roomSelectedOptions = roomAccessOptions.find(
|
||||
(option) =>
|
||||
option && "access" in option && option.access === link.access,
|
||||
);
|
||||
|
||||
const avatar = shareOption?.key === "anyone" ? UniverseIcon : PeopleIcon;
|
||||
|
||||
const isExpiredLink = link.sharedTo.isExpired;
|
||||
const isLocked = !!link.sharedTo.password;
|
||||
|
||||
const isLoaded = loadingLinks.includes(link.sharedTo.id);
|
||||
|
||||
return (
|
||||
<StyledLinkRow key={`share-link-row-${index * 5}`}>
|
||||
<StyledLinkRow
|
||||
isExpired={isExpiredLink}
|
||||
key={`share-link-row-${index * 5}`}
|
||||
>
|
||||
{isLoaded ? (
|
||||
<Loader className="loader" size="20px" type={LoaderTypes.track} />
|
||||
) : (
|
||||
@ -103,10 +132,21 @@ const LinkRow = ({
|
||||
size={AvatarSize.min}
|
||||
role={AvatarRole.user}
|
||||
source={avatar}
|
||||
roleIcon={isLocked ? <LockedReactSvg /> : undefined}
|
||||
|
||||
// roleIcon={
|
||||
// expiryDate ? (
|
||||
// <div className="clock-icon">
|
||||
// <ClockReactSvg />
|
||||
// </div>
|
||||
// ) : null
|
||||
// }
|
||||
/>
|
||||
)}
|
||||
<div className="link-options">
|
||||
{!isExpiredLink ? (
|
||||
{isRoom ? (
|
||||
<Text className="link-options_title">{linkTitle}</Text>
|
||||
) : !isExpiredLink ? (
|
||||
<ComboBox
|
||||
className="internal-combobox"
|
||||
directionY="both"
|
||||
@ -122,9 +162,7 @@ const LinkRow = ({
|
||||
isDisabled={isLoaded}
|
||||
/>
|
||||
) : (
|
||||
<Text className="internal-combobox_expiered">
|
||||
{shareOption?.label}
|
||||
</Text>
|
||||
<Text className="link-options_title">{shareOption?.label}</Text>
|
||||
)}
|
||||
<ExpiredComboBox
|
||||
link={link}
|
||||
@ -135,11 +173,43 @@ const LinkRow = ({
|
||||
<div className="link-actions">
|
||||
<IconButton
|
||||
size={16}
|
||||
className="link-row_copy-icon"
|
||||
iconName={CopyIcon}
|
||||
onClick={() => onCopyLink(link)}
|
||||
title={t("Common:CreateAndCopy")}
|
||||
isDisabled={isExpiredLink || isLoaded}
|
||||
/>
|
||||
{isRoom ? (
|
||||
<>
|
||||
<AccessRightSelect
|
||||
// className={className}
|
||||
// selectedOption={selectedOption}
|
||||
// onSelect={onSelectAccess}
|
||||
selectedOption={roomSelectedOptions}
|
||||
onSelect={onAccessRightsSelect}
|
||||
accessOptions={roomAccessOptions}
|
||||
noBorder
|
||||
// directionX="right"
|
||||
// directionY="bottom"
|
||||
// fixedDirection={true}
|
||||
// manualWidth={width + "px"}
|
||||
// isDefaultMode={false}
|
||||
// isAside={false}
|
||||
// setIsOpenItemAccess={setIsOpenItemAccess}
|
||||
// hideMobileView={isMobileHorizontalOrientation}
|
||||
type="onlyIcon"
|
||||
manualWidth="448px"
|
||||
/>
|
||||
<ContextMenuButton
|
||||
getData={getData}
|
||||
// isDisabled={isLoading}
|
||||
title={t("Files:ShowLinkActions")}
|
||||
directionY="both"
|
||||
onClick={onOpenContextMenu}
|
||||
onClose={onCloseContextMenu}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<ComboBox
|
||||
directionY="both"
|
||||
options={accessOptions}
|
||||
@ -154,6 +224,7 @@ const LinkRow = ({
|
||||
type="onlyIcon"
|
||||
isDisabled={isExpiredLink || isLoaded}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</StyledLinkRow>
|
||||
);
|
||||
|
15
public/images/icons/12/locked.react.svg
Normal file
15
public/images/icons/12/locked.react.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<svg width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_622_21524)">
|
||||
<mask id="path-1-outside-1_622_21524" maskUnits="userSpaceOnUse" x="0" y="0" width="12" height="14" fill="black">
|
||||
<rect fill="white" width="12" height="14"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 4C3 2.34315 4.34315 1 6 1C7.65685 1 9 2.34315 9 4V5C10.1046 5 11 5.89543 11 7V11C11 12.1046 10.1046 13 9 13H3C1.89543 13 1 12.1046 1 11V7C1 5.89543 1.89543 5 3 5V4ZM7 4V5H5V4C5 3.44772 5.44772 3 6 3C6.55228 3 7 3.44772 7 4ZM3 7V11H9V7H3ZM6 10C6.55228 10 7 9.55229 7 9C7 8.44772 6.55228 8 6 8C5.44772 8 5 8.44772 5 9C5 9.55229 5.44772 10 6 10Z"/>
|
||||
</mask>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 4C3 2.34315 4.34315 1 6 1C7.65685 1 9 2.34315 9 4V5C10.1046 5 11 5.89543 11 7V11C11 12.1046 10.1046 13 9 13H3C1.89543 13 1 12.1046 1 11V7C1 5.89543 1.89543 5 3 5V4ZM7 4V5H5V4C5 3.44772 5.44772 3 6 3C6.55228 3 7 3.44772 7 4ZM3 7V11H9V7H3ZM6 10C6.55228 10 7 9.55229 7 9C7 8.44772 6.55228 8 6 8C5.44772 8 5 8.44772 5 9C5 9.55229 5.44772 10 6 10Z" fill="#4781D1"/>
|
||||
<path d="M9 5H8C8 5.55228 8.44772 6 9 6V5ZM3 5V6C3.55228 6 4 5.55228 4 5H3ZM7 5V6C7.55228 6 8 5.55228 8 5H7ZM5 5H4C4 5.55228 4.44772 6 5 6V5ZM3 11H2C2 11.5523 2.44772 12 3 12V11ZM3 7V6C2.44772 6 2 6.44772 2 7H3ZM9 11V12C9.55228 12 10 11.5523 10 11H9ZM9 7H10C10 6.44772 9.55228 6 9 6V7ZM6 0C3.79086 0 2 1.79086 2 4H4C4 2.89543 4.89543 2 6 2V0ZM10 4C10 1.79086 8.20914 0 6 0V2C7.10457 2 8 2.89543 8 4H10ZM10 5V4H8V5H10ZM12 7C12 5.34315 10.6569 4 9 4V6C9.55228 6 10 6.44772 10 7H12ZM12 11V7H10V11H12ZM9 14C10.6569 14 12 12.6569 12 11H10C10 11.5523 9.55228 12 9 12V14ZM3 14H9V12H3V14ZM0 11C0 12.6569 1.34315 14 3 14V12C2.44772 12 2 11.5523 2 11H0ZM0 7V11H2V7H0ZM3 4C1.34315 4 0 5.34315 0 7H2C2 6.44772 2.44772 6 3 6V4ZM2 4V5H4V4H2ZM8 5V4H6V5H8ZM5 6H7V4H5V6ZM4 4V5H6V4H4ZM6 2C4.89543 2 4 2.89543 4 4H6V2ZM8 4C8 2.89543 7.10457 2 6 2V4H8ZM4 11V7H2V11H4ZM9 10H3V12H9V10ZM8 7V11H10V7H8ZM3 8H9V6H3V8ZM6 9V11C7.10457 11 8 10.1046 8 9H6ZM6 9H8C8 7.89543 7.10457 7 6 7V9ZM6 9V7C4.89543 7 4 7.89543 4 9H6ZM6 9H4C4 10.1046 4.89543 11 6 11V9Z" fill="white" mask="url(#path-1-outside-1_622_21524)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_622_21524">
|
||||
<rect width="12" height="14" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
@ -143,6 +143,7 @@
|
||||
"EditButton": "Edit",
|
||||
"Editing": "Editing",
|
||||
"Editor": "Editor",
|
||||
"Commentator": "Commentator",
|
||||
"EditPDFForm": "Edit PDF form",
|
||||
"Email": "Email",
|
||||
"EmptyDescription": "The list of users previously invited to {{productName}} or separate rooms will appear here. You will be able to invite these users for collaboration at any time.",
|
||||
|
Loading…
Reference in New Issue
Block a user