Merge pull request #601 from ONLYOFFICE/feature/catalog-item-link
Feature/catalog item link
This commit is contained in:
commit
db6c6f95de
@ -39,6 +39,7 @@ const PureAccountsItem = ({
|
||||
onClick,
|
||||
t,
|
||||
currentColorScheme,
|
||||
getLinkData,
|
||||
}) => {
|
||||
const onClickAction = React.useCallback(
|
||||
(e, id) => {
|
||||
@ -51,10 +52,13 @@ const PureAccountsItem = ({
|
||||
|
||||
const title = t("Accounts");
|
||||
|
||||
const linkData = getLinkData("accounts");
|
||||
|
||||
return (
|
||||
<ArticleItem
|
||||
key="accounts"
|
||||
text={title}
|
||||
linkData={linkData}
|
||||
title={title}
|
||||
icon={icon}
|
||||
showText={showText}
|
||||
|
@ -75,6 +75,7 @@ const Item = ({
|
||||
iconBadge,
|
||||
folderId,
|
||||
currentColorScheme,
|
||||
getLinkData,
|
||||
}) => {
|
||||
const [isDragActive, setIsDragActive] = useState(false);
|
||||
|
||||
@ -126,18 +127,24 @@ const Item = ({
|
||||
(e, folderId) => {
|
||||
setBufferSelection(null);
|
||||
|
||||
onClick &&
|
||||
onClick(
|
||||
e,
|
||||
folderId,
|
||||
item.title,
|
||||
item.rootFolderType,
|
||||
item.security.Create,
|
||||
);
|
||||
onClick?.(
|
||||
e,
|
||||
folderId,
|
||||
item.title,
|
||||
item.rootFolderType,
|
||||
item.security.Create,
|
||||
);
|
||||
},
|
||||
[onClick, item.title, item.rootFolderType],
|
||||
);
|
||||
|
||||
const linkData = getLinkData(
|
||||
item.id,
|
||||
item.title,
|
||||
item.rootFolderType,
|
||||
item.security.Create,
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledDragAndDrop
|
||||
key={item.id}
|
||||
@ -170,6 +177,7 @@ const Item = ({
|
||||
onClickBadge={onBadgeClick}
|
||||
iconBadge={iconBadge}
|
||||
badgeTitle={labelBadge ? "" : t("EmptyRecycleBin")}
|
||||
linkData={linkData}
|
||||
$currentColorScheme={currentColorScheme}
|
||||
/>
|
||||
</StyledDragAndDrop>
|
||||
@ -215,6 +223,8 @@ const Items = ({
|
||||
currentDeviceType,
|
||||
folderAccess,
|
||||
currentColorScheme,
|
||||
|
||||
getLinkData,
|
||||
}) => {
|
||||
const getEndOfBlock = React.useCallback((item) => {
|
||||
switch (item.key) {
|
||||
@ -329,6 +339,7 @@ const Items = ({
|
||||
getEndOfBlock={getEndOfBlock}
|
||||
showText={showText}
|
||||
onClick={onClick}
|
||||
getLinkData={getLinkData}
|
||||
onMoveTo={isTrash ? onRemove : onMoveTo}
|
||||
onBadgeClick={isTrash ? onEmptyTrashAction : onBadgeClick}
|
||||
showDragItems={showDragItems}
|
||||
@ -341,16 +352,6 @@ const Items = ({
|
||||
);
|
||||
});
|
||||
|
||||
/*if (!firstLoad && !isVisitor)
|
||||
items.splice(
|
||||
3,
|
||||
0,
|
||||
<SettingsItem
|
||||
key="settings-item"
|
||||
onClick={onClick}
|
||||
isActive={activeItemId === "settings"}
|
||||
/>
|
||||
);*/
|
||||
if (!isVisitor && !isCollaborator)
|
||||
items.splice(
|
||||
3,
|
||||
@ -358,6 +359,7 @@ const Items = ({
|
||||
<AccountsItem
|
||||
key="accounts-item"
|
||||
onClick={onClick}
|
||||
getLinkData={getLinkData}
|
||||
isActive={activeItemId === "accounts"}
|
||||
/>,
|
||||
);
|
||||
@ -375,6 +377,7 @@ const Items = ({
|
||||
dragging,
|
||||
getFolderIcon,
|
||||
onClick,
|
||||
getLinkData,
|
||||
onMoveTo,
|
||||
getEndOfBlock,
|
||||
onBadgeClick,
|
||||
|
@ -1,72 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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 from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import { ArticleItem } from "@docspace/shared/components/article-item";
|
||||
|
||||
import CatalogSettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url";
|
||||
|
||||
const PureSettingsItem = ({
|
||||
t,
|
||||
showText,
|
||||
isActive,
|
||||
onClick,
|
||||
currentColorScheme,
|
||||
}) => {
|
||||
const onClickAction = React.useCallback(() => {
|
||||
onClick && onClick("settings");
|
||||
}, [onClick]);
|
||||
|
||||
const title = t("Common:Settings");
|
||||
|
||||
return (
|
||||
<ArticleItem
|
||||
key="settings"
|
||||
text={title}
|
||||
title={title}
|
||||
icon={CatalogSettingsReactSvgUrl}
|
||||
showText={showText}
|
||||
onClick={onClickAction}
|
||||
isActive={isActive}
|
||||
folderId="document_catalog-settings"
|
||||
$currentColorScheme={currentColorScheme}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const SettingsItem = withTranslation(["FilesSettings", "Common"])(
|
||||
PureSettingsItem,
|
||||
);
|
||||
|
||||
export default inject(({ settingsStore }) => {
|
||||
return {
|
||||
showText: settingsStore.showText,
|
||||
currentColorScheme: settingsStore.currentColorScheme,
|
||||
};
|
||||
})(observer(SettingsItem));
|
@ -28,7 +28,7 @@ import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
import { DeviceType, RoomSearchArea } from "@docspace/shared/enums";
|
||||
import Items from "./Items";
|
||||
@ -43,9 +43,7 @@ import { getCategoryUrl } from "SRC_DIR/helpers/utils";
|
||||
import { CategoryType } from "SRC_DIR/helpers/constants";
|
||||
import { ArticleFolderLoader } from "@docspace/shared/skeletons/article";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { showProgress } from "@docspace/shared/utils/common";
|
||||
import { openingNewTab } from "@docspace/shared/utils/openingNewTab";
|
||||
|
||||
const ArticleBodyContent = (props) => {
|
||||
const {
|
||||
@ -77,18 +75,13 @@ const ArticleBodyContent = (props) => {
|
||||
isFrame,
|
||||
} = props;
|
||||
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const [disableBadgeClick, setDisableBadgeClick] = React.useState(false);
|
||||
const [activeItemId, setActiveItemId] = React.useState(null);
|
||||
|
||||
const isAccounts = location.pathname.includes("accounts/filter");
|
||||
|
||||
const onClick = React.useCallback(
|
||||
(e, folderId, title, rootFolderType, canCreate) => {
|
||||
const { toggleArticleOpen } = props;
|
||||
|
||||
const getLinkData = React.useCallback(
|
||||
(folderId, title, rootFolderType, canCreate) => {
|
||||
let params = null;
|
||||
let path = ``;
|
||||
|
||||
@ -100,8 +93,6 @@ const ArticleBodyContent = (props) => {
|
||||
canCreate,
|
||||
};
|
||||
|
||||
let withTimer = !!selectedFolderId;
|
||||
|
||||
switch (folderId) {
|
||||
case myFolderId:
|
||||
const myFilter = FilesFilter.getDefault();
|
||||
@ -155,17 +146,7 @@ const ArticleBodyContent = (props) => {
|
||||
params = accountsFilter.toUrlParams();
|
||||
path = getCategoryUrl(CategoryType.Accounts);
|
||||
|
||||
withTimer = false;
|
||||
|
||||
break;
|
||||
case "settings":
|
||||
path = getCategoryUrl(CategoryType.Settings);
|
||||
navigate(path);
|
||||
|
||||
if (currentDeviceType === DeviceType.mobile) {
|
||||
toggleArticleOpen();
|
||||
}
|
||||
return;
|
||||
case roomsFolderId:
|
||||
default:
|
||||
const roomsFilter = RoomsFilter.getDefault(
|
||||
@ -181,16 +162,33 @@ const ArticleBodyContent = (props) => {
|
||||
|
||||
path += `?${params}&date=${new Date().getTime()}`;
|
||||
|
||||
if (openingNewTab(path, e)) return;
|
||||
return { path, state };
|
||||
},
|
||||
[
|
||||
roomsFolderId,
|
||||
archiveFolderId,
|
||||
myFolderId,
|
||||
recycleBinFolderId,
|
||||
activeItemId,
|
||||
],
|
||||
);
|
||||
|
||||
if (folderId === "accounts" || folderId === "settings") clearFiles();
|
||||
const onClick = React.useCallback(
|
||||
(e, folderId) => {
|
||||
if (e?.ctrlKey || e?.metaKey || e?.shiftKey || e?.button) return;
|
||||
|
||||
setSelection && setSelection([]);
|
||||
const { toggleArticleOpen } = props;
|
||||
|
||||
const isAccountsClick = folderId === "accounts";
|
||||
|
||||
let withTimer = isAccountsClick ? false : !!selectedFolderId;
|
||||
|
||||
if (isAccountsClick) clearFiles();
|
||||
|
||||
setSelection?.([]);
|
||||
|
||||
setIsLoading(true, withTimer);
|
||||
|
||||
navigate(path, { state });
|
||||
|
||||
if (currentDeviceType === DeviceType.mobile) {
|
||||
toggleArticleOpen();
|
||||
}
|
||||
@ -202,7 +200,7 @@ const ArticleBodyContent = (props) => {
|
||||
recycleBinFolderId,
|
||||
activeItemId,
|
||||
selectedFolderId,
|
||||
isAccounts,
|
||||
|
||||
setSelection,
|
||||
],
|
||||
);
|
||||
@ -281,6 +279,7 @@ const ArticleBodyContent = (props) => {
|
||||
<Items
|
||||
onClick={onClick}
|
||||
onBadgeClick={onShowNewFilesPanel}
|
||||
getLinkData={getLinkData}
|
||||
showText={showText}
|
||||
onHide={toggleArticleOpen}
|
||||
activeItemId={activeItemId}
|
||||
|
@ -173,26 +173,19 @@ const ArticleBodyContent = (props) => {
|
||||
selectedKeys,
|
||||
]);
|
||||
|
||||
const onSelect = (value, e) => {
|
||||
if (isArrayEqual([value], selectedKeys)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const settingsPath = `/portal-settings${getSelectedLinkByKey(
|
||||
const getLinkData = (value) => {
|
||||
const path = `/portal-settings${getSelectedLinkByKey(
|
||||
value + "-0",
|
||||
settingsTree,
|
||||
)}`;
|
||||
|
||||
if (openingNewTab(settingsPath, e)) return;
|
||||
// setSelectedKeys([value + "-0"]);
|
||||
return { path, state: {} };
|
||||
};
|
||||
|
||||
const onSelect = (value, e) => {
|
||||
if (currentDeviceType === DeviceType.mobile) {
|
||||
toggleArticleOpen();
|
||||
}
|
||||
|
||||
if (settingsPath === location.pathname) return;
|
||||
|
||||
navigate(`${settingsPath}`);
|
||||
};
|
||||
|
||||
const mapKeys = (tKey) => {
|
||||
@ -303,6 +296,7 @@ const ArticleBodyContent = (props) => {
|
||||
const patternSearching = selectedKeys[0].split("-");
|
||||
const selectedKey = patternSearching[0];
|
||||
const title = mapKeys(item.tKey);
|
||||
const linkData = getLinkData(item.key);
|
||||
|
||||
items.push(
|
||||
<ArticleItem
|
||||
@ -315,6 +309,7 @@ const ArticleBodyContent = (props) => {
|
||||
value={item.link}
|
||||
isActive={item.key === selectedKey}
|
||||
onClick={(e) => onSelect(item.key, e)}
|
||||
linkData={linkData}
|
||||
folderId={item.id}
|
||||
style={{
|
||||
marginTop: `${item.key.includes(9) ? "16px" : "0"}`,
|
||||
|
@ -68,18 +68,11 @@ const ArticleBodyContent = () => {
|
||||
}, []);
|
||||
|
||||
const onClickItem = (item: TSettingsTreeItem, e: React.MouseEvent) => {
|
||||
const path = item.link;
|
||||
const url = combineUrl(PROXY_BASE_URL, path);
|
||||
|
||||
if (openingNewTab(url, e)) return;
|
||||
|
||||
setSelectedKey(item?.key);
|
||||
|
||||
if (isMobileOnly || isMobile()) {
|
||||
toggleArticleOpen();
|
||||
}
|
||||
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
const catalogItems = () => {
|
||||
@ -108,6 +101,7 @@ const ArticleBodyContent = () => {
|
||||
onClick={(e) => onClickItem(item, e)}
|
||||
folderId={item.id}
|
||||
$currentColorScheme={currentColorScheme}
|
||||
linkData={{ path: item.link, state: {} }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
import React from "react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { Text } from "../text";
|
||||
|
||||
@ -69,6 +70,7 @@ export const ArticleItemPure = (props: ArticleItemProps) => {
|
||||
badgeTitle,
|
||||
$currentColorScheme,
|
||||
title,
|
||||
linkData,
|
||||
} = props;
|
||||
|
||||
const onClickAction = (e: React.MouseEvent) => {
|
||||
@ -105,62 +107,68 @@ export const ArticleItemPure = (props: ArticleItemProps) => {
|
||||
|
||||
const renderItem = () => {
|
||||
return (
|
||||
<StyledArticleItemTheme
|
||||
className={className}
|
||||
style={style}
|
||||
showText={showText}
|
||||
isEndOfBlock={isEndOfBlock}
|
||||
isActive={isActive}
|
||||
data-testid="article-item"
|
||||
$currentColorScheme={$currentColorScheme}
|
||||
title={tooltipTitle}
|
||||
<Link
|
||||
style={{ textDecoration: "none" }}
|
||||
to={linkData?.path}
|
||||
state={linkData?.state}
|
||||
>
|
||||
<StyledArticleItemSibling
|
||||
id={folderId}
|
||||
<StyledArticleItemTheme
|
||||
className={className}
|
||||
style={style}
|
||||
showText={showText}
|
||||
isEndOfBlock={isEndOfBlock}
|
||||
isActive={isActive}
|
||||
isDragging={isDragging}
|
||||
isDragActive={isDragActive}
|
||||
onClick={onClickAction}
|
||||
onMouseUp={onMouseUpAction}
|
||||
onMouseDown={onMouseDown}
|
||||
/>
|
||||
<StyledArticleItemImg isActive={isActive}>
|
||||
<ReactSVG className="icon" src={icon} />
|
||||
{!showText && (
|
||||
<>
|
||||
{showInitial && (
|
||||
<StyledArticleItemInitialText>
|
||||
{getInitial(text)}
|
||||
</StyledArticleItemInitialText>
|
||||
)}
|
||||
{showBadge && !iconBadge && (
|
||||
<StyledArticleItemBadgeWrapper
|
||||
onClick={onClickBadgeAction}
|
||||
showText={showText}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledArticleItemImg>
|
||||
{showText && (
|
||||
<StyledArticleItemText isActive={isActive} noSelect>
|
||||
{text}
|
||||
</StyledArticleItemText>
|
||||
)}
|
||||
{showBadge && showText && (
|
||||
<StyledArticleItemBadgeWrapper
|
||||
showText={showText}
|
||||
onClick={onClickBadgeAction}
|
||||
title={badgeTitle}
|
||||
>
|
||||
{!iconBadge ? (
|
||||
<Badge className="catalog-item__badge" label={labelBadge} />
|
||||
) : (
|
||||
<ReactSVG className="catalog-item__icon" src={iconBadge} />
|
||||
data-testid="article-item"
|
||||
$currentColorScheme={$currentColorScheme}
|
||||
title={tooltipTitle}
|
||||
>
|
||||
<StyledArticleItemSibling
|
||||
id={folderId}
|
||||
isActive={isActive}
|
||||
isDragging={isDragging}
|
||||
isDragActive={isDragActive}
|
||||
onClick={onClickAction}
|
||||
onMouseUp={onMouseUpAction}
|
||||
onMouseDown={onMouseDown}
|
||||
/>
|
||||
<StyledArticleItemImg isActive={isActive}>
|
||||
<ReactSVG className="icon" src={icon} />
|
||||
{!showText && (
|
||||
<>
|
||||
{showInitial && (
|
||||
<StyledArticleItemInitialText>
|
||||
{getInitial(text)}
|
||||
</StyledArticleItemInitialText>
|
||||
)}
|
||||
{showBadge && !iconBadge && (
|
||||
<StyledArticleItemBadgeWrapper
|
||||
onClick={onClickBadgeAction}
|
||||
showText={showText}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledArticleItemBadgeWrapper>
|
||||
)}
|
||||
</StyledArticleItemTheme>
|
||||
</StyledArticleItemImg>
|
||||
{showText && (
|
||||
<StyledArticleItemText isActive={isActive} noSelect>
|
||||
{text}
|
||||
</StyledArticleItemText>
|
||||
)}
|
||||
{showBadge && showText && (
|
||||
<StyledArticleItemBadgeWrapper
|
||||
showText={showText}
|
||||
onClick={onClickBadgeAction}
|
||||
title={badgeTitle}
|
||||
>
|
||||
{!iconBadge ? (
|
||||
<Badge className="catalog-item__badge" label={labelBadge} />
|
||||
) : (
|
||||
<ReactSVG className="catalog-item__icon" src={iconBadge} />
|
||||
)}
|
||||
</StyledArticleItemBadgeWrapper>
|
||||
)}
|
||||
</StyledArticleItemTheme>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,21 @@
|
||||
|
||||
import { TColorScheme } from "../../themes";
|
||||
|
||||
export type TArticleLinkDataState =
|
||||
| {
|
||||
title: string;
|
||||
isRoot: boolean;
|
||||
isPublicRoomType: boolean;
|
||||
rootFolderType: number;
|
||||
canCreate: boolean;
|
||||
}
|
||||
| {};
|
||||
|
||||
export type TArticleLinkData = {
|
||||
path: string;
|
||||
state: TArticleLinkDataState;
|
||||
};
|
||||
|
||||
export interface ArticleItemProps {
|
||||
/** Accepts className */
|
||||
className?: string;
|
||||
@ -70,4 +85,5 @@ export interface ArticleItemProps {
|
||||
badgeTitle?: string;
|
||||
$currentColorScheme?: TColorScheme;
|
||||
title?: string;
|
||||
linkData: TArticleLinkData;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user