Merge pull request #491 from ONLYOFFICE/feature/redesign-tiles

Feature/redesign tiles
This commit is contained in:
Alexey Safronov 2022-01-27 12:06:52 +03:00 committed by GitHub
commit e010268e2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 479 additions and 584 deletions

View File

@ -1,85 +1,79 @@
import styled, { css } from "styled-components";
import { mobile, tablet } from "@appserver/components/utils/device";
import { smallTablet, tablet, size } from "@appserver/components/utils/device";
const StyledTile = styled.div`
position: relative;
display: grid;
//min-width: 250px;
width: 100%;
height: ${(props) => (props.isFolder ? "57px" : "240px")};
border: 1px solid #d0d5da;
border-radius: 3px;
height: ${(props) => (props.isFolder ? "32px" : "220px")};
${(props) =>
props.isFolder
? css`
&:before {
content: "";
position: absolute;
top: -5px;
left: -1px;
border-top: 1px solid #d0d5da;
border-top-left-radius: 3px;
border-left: 1px solid #d0d5da;
width: 38px;
height: 8px;
background-color: #fff;
border-bottom: transparent;
}
@media ${smallTablet} {
&:nth-of-type(n + 3) {
display: none;
}
&:after {
content: "";
position: absolute;
top: -4px;
left: 34px;
border-top: 1px solid #d0d5da;
background-color: #fff;
width: 7px;
height: 10px;
transform: rotateZ(35deg);
${(props) =>
props.isFolder &&
css`
&:nth-of-type(n + 2) {
display: none;
}
`}
}
@media ${tablet} {
left: 34px;
}
}
`
: null}
@media (min-width: ${size.smallTablet}px) and ${tablet} {
&:nth-of-type(n + 7) {
display: none;
}
}
`;
const StyledMainContent = styled.div`
padding: 12px 12px 4px 12px;
height: 175px;
clipPath > rect {
width: calc(100% + 20px);
}
height: 172px;
`;
const StyledBottom = styled.div`
display: grid;
grid-template-columns: 24px auto;
grid-gap: 8px;
padding: ${(props) => (props.isFolder ? "20px 12px" : "8px 12px 12px 12px")};
display: flex;
align-items: ${(props) => (props.isFolder ? "center" : "stretch")};
margin-top: ${(props) => (props.isFolder ? 0 : "10px")};
height: 38px;
.first-content {
display: inline-block;
${(props) =>
!props.isFolder
? css`
width: 24px;
height: 30px;
`
: css`
width: 16px;
height: 16px;
`}
height: 32px;
width: 32px;
min-width: 32px;
}
.second-content {
clipPath > rect {
width: calc(100% + 20px);
}
width: 100%;
height: ${(props) => (props.isFolder ? "16px" : "30px")};
height: ${(props) => (props.isFolder ? "32px" : "16px")};
margin-left: 8px;
}
.files-second-content {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
margin-left: 8px;
.second-content {
&:last-of-type {
height: 12px;
margin-right: auto;
margin-left: 0;
width: 50%;
border-radius: 3px;
}
}
}
.option-button {
height: 16px;
width: 16px;
min-width: 16px;
margin-left: 8px;
border-radius: 6px;
}
`;

View File

@ -32,7 +32,7 @@ const TileLoader = ({
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={false}
animate={true}
/>
<RectangleLoader
className="second-content"
@ -43,7 +43,18 @@ const TileLoader = ({
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={false}
animate={true}
/>
<RectangleLoader
className="option-button"
title={title}
borderRadius={borderRadius}
backgroundColor={backgroundColor}
foregroundColor={foregroundColor}
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={true}
/>
</StyledBottom>
</StyledTile>
@ -53,7 +64,6 @@ const TileLoader = ({
<RectangleLoader
className="main-content"
height="100%"
//width="100%"
title={title}
borderRadius={borderRadius}
backgroundColor={backgroundColor}
@ -61,7 +71,7 @@ const TileLoader = ({
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={false}
animate={true}
/>
</StyledMainContent>
@ -75,20 +85,34 @@ const TileLoader = ({
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={false}
/>
<RectangleLoader
className="second-content"
title={title}
width="100%"
borderRadius={borderRadius}
backgroundColor={backgroundColor}
foregroundColor={foregroundColor}
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={false}
animate={true}
/>
<div className="files-second-content">
<RectangleLoader
className="second-content"
title={title}
width="100%"
borderRadius={borderRadius}
backgroundColor={backgroundColor}
foregroundColor={foregroundColor}
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={true}
/>
<RectangleLoader
className="second-content"
title={title}
width="100%"
borderRadius={borderRadius}
backgroundColor={backgroundColor}
foregroundColor={foregroundColor}
backgroundOpacity={backgroundOpacity}
foregroundOpacity={foregroundOpacity}
speed={speed}
animate={true}
/>
</div>
</StyledBottom>
</StyledTile>
);

View File

@ -4,10 +4,11 @@ import PropTypes from "prop-types";
import TileLoader from "../TileLoader";
import RectangleLoader from "../RectangleLoader";
import { tablet } from "@appserver/components/utils/device";
const StyledTilesLoader = styled.div`
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
width: 100%;
grid-gap: 16px;
`;
@ -18,18 +19,22 @@ const StyledWrapper = styled.div`
grid-gap: 16px;
.folders {
margin-bottom: -4px;
margin-top: -1px;
margin-bottom: 12px;
}
.files {
margin-top: 12px;
margin-top: 25px;
}
margin-right: 9px;
@media (max-width: 1024px) {
margin-right: 2px;
margin-right: 3px;
@media ${tablet} {
margin-right: -1px;
}
`;
const TilesLoader = ({ foldersCount, filesCount, ...rest }) => {
const TilesLoader = ({ foldersCount, filesCount, sectionWidth, ...rest }) => {
const folders = [];
const files = [];
@ -40,24 +45,26 @@ const TilesLoader = ({ foldersCount, filesCount, ...rest }) => {
for (let i = 0; i < filesCount; i++) {
files.push(<TileLoader key={`files-loader-${i}`} {...rest} />);
}
return (
<StyledWrapper>
{foldersCount > 0 ? (
<RectangleLoader
height="15px"
width="120px"
height="22px"
width="57px"
className="folders"
animate={false}
animate
{...rest}
/>
) : null}
<StyledTilesLoader>{folders}</StyledTilesLoader>
{filesCount > 0 ? (
<RectangleLoader
height="15px"
width="120px"
height="22px"
width="35px"
className="files"
animate={false}
animate
{...rest}
/>
) : null}
@ -72,8 +79,8 @@ TilesLoader.propTypes = {
};
TilesLoader.defaultProps = {
foldersCount: 3,
filesCount: 3,
foldersCount: 2,
filesCount: 8,
};
export default TilesLoader;

View File

@ -23,10 +23,12 @@ const Badge = (props) => {
padding,
maxWidth,
lineHeight,
isHovered,
label,
} = props;
return (
<StyledBadge {...props} onClick={onClick}>
<StyledBadge isHovered={isHovered} onClick={onClick} {...props}>
<StyledInner
backgroundColor={backgroundColor}
borderRadius={borderRadius}
@ -40,7 +42,7 @@ const Badge = (props) => {
color={color}
fontSize={fontSize}
>
{props.label}
{label}
</Text>
</StyledInner>
</StyledBadge>
@ -74,6 +76,10 @@ Badge.propTypes = {
id: PropTypes.string,
/** Accepts css style */
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
/** Set hovered state and effects of link */
isHovered: PropTypes.bool,
/** Disabled hover styles */
noHover: PropTypes.bool,
};
Badge.defaultProps = {
@ -86,6 +92,8 @@ Badge.defaultProps = {
padding: "0 5px",
maxWidth: "50px",
lineHeight: "1.78",
isHovered: false,
noHover: false,
};
export default Badge;

View File

@ -1,6 +1,10 @@
import styled from "styled-components";
import styled, { css } from "styled-components";
import Base from "../themes/base";
const hoveredCss = css`
border-color: ${(props) => props.backgroundColor};
`;
const StyledBadge = styled.div`
display: ${(props) =>
props.label.length > 0 || props.label != "0" ? "inline-block" : "none"};
@ -12,9 +16,11 @@ const StyledBadge = styled.div`
cursor: pointer;
overflow: ${(props) => props.theme.badge.overflow};
:hover {
border-color: ${(props) => props.backgroundColor};
&:hover {
${(props) => !props.noHover && hoveredCss};
}
${(props) => !props.noHover && props.isHovered && hoveredCss}
`;
StyledBadge.defaultProps = { theme: Base };

View File

@ -122,6 +122,7 @@ export default function withBadges(WrappedComponent) {
isAdmin,
isDesktopClient,
sectionWidth,
viewAs,
} = this.props;
const { fileStatus, access } = item;
@ -150,6 +151,7 @@ export default function withBadges(WrappedComponent) {
onBadgeClick={this.onBadgeClick}
setConvertDialogVisible={this.setConvertDialogVisible}
onFilesClick={onFilesClick}
viewAs={viewAs}
/>
);

View File

@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import styled from "styled-components";
import Badge from "@appserver/components/badge";
import IconButton from "@appserver/components/icon-button";
@ -9,6 +9,42 @@ export const StyledIcon = styled(IconButton)`
${commonIconsStyles}
`;
const StyledWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
background: white;
padding: 6px;
border-radius: 4px;
box-shadow: 0px 2px 4px rgba(4, 15, 27, 0.16);
`;
const BadgeWrapper = ({ onClick, isTile, children: badge }) => {
if (!isTile) return badge;
const [isHovered, setIsHovered] = useState(false);
const onMouseEnter = () => {
setIsHovered(true);
};
const onMouseLeave = () => {
setIsHovered(false);
};
const newBadge = React.cloneElement(badge, { isHovered: isHovered });
return (
<StyledWrapper
onClick={onClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{newBadge}
</StyledWrapper>
);
};
const Badges = ({
t,
newItems,
@ -25,6 +61,7 @@ const Badges = ({
onShowVersionHistory,
onBadgeClick,
setConvertDialogVisible,
viewAs,
}) => {
const { id, locked, fileStatus, version, versionGroup, fileExst } = item;
@ -34,6 +71,7 @@ const Badges = ({
const showEditBadge = !locked || item.access === 0;
const isPrivacy = isPrivacyFolder && isDesktopClient;
const isForm = fileExst === ".oform";
const isTile = viewAs === "tile";
const iconEdit = isForm
? "/static/images/access.edit.form.react.svg"
@ -48,15 +86,26 @@ const Badges = ({
const contentNewItems = newItems > 999 ? "999+" : newItems;
const tabletViewBadge =
(sectionWidth > 500 && sectionWidth <= 1024) || isTablet;
!isTile && ((sectionWidth > 500 && sectionWidth <= 1024) || isTablet);
const sizeBadge = tabletViewBadge ? "medium" : "small";
const sizeBadge = isTile || tabletViewBadge ? "medium" : "small";
const lineHeightBadge = tabletViewBadge ? "1.46" : "1.34";
const lineHeightBadge = isTile || tabletViewBadge ? "1.46" : "1.34";
const paddingBadge = tabletViewBadge ? "0 5px" : "0 3px";
const paddingBadge = isTile || tabletViewBadge ? "0 5px" : "0 3px";
const fontSizeBadge = tabletViewBadge ? "11px" : "9px";
const fontSizeBadge = isTile || tabletViewBadge ? "11px" : "9px";
const commonBadgeProps = {
borderRadius: "11px",
color: "#FFFFFF",
fontSize: fontSizeBadge,
fontWeight: 800,
maxWidth: "50px",
padding: paddingBadge,
lineHeight: lineHeightBadge,
"data-id": id,
};
return fileExst ? (
<div className="badges additional-badges">
@ -98,53 +147,36 @@ const Badges = ({
/>
)}
{version > 1 && (
<Badge
className="badge-version tablet-badge icons-group"
backgroundColor="#A3A9AE"
borderRadius="11px"
color="#FFFFFF"
fontSize={fontSizeBadge}
fontWeight={800}
label={t("VersionBadge:Version", { version: countVersions })}
maxWidth="50px"
onClick={onShowVersionHistory}
padding={paddingBadge}
lineHeight={lineHeightBadge}
data-id={id}
/>
<BadgeWrapper onClick={onShowVersionHistory} isTile={isTile}>
<Badge
{...commonBadgeProps}
className="badge-version badge-version-current tablet-badge icons-group"
backgroundColor="#A3A9AE"
label={t("VersionBadge:Version", { version: countVersions })}
onClick={onShowVersionHistory}
/>
</BadgeWrapper>
)}
{(showNew || isNewWithFav) && (
<Badge
className="badge-version badge-new-version tablet-badge icons-group"
backgroundColor="#ED7309"
borderRadius="11px"
color="#FFFFFF"
fontSize={fontSizeBadge}
fontWeight={800}
label={t("New")}
maxWidth="50px"
onClick={onBadgeClick}
padding={paddingBadge}
lineHeight={lineHeightBadge}
data-id={id}
/>
<BadgeWrapper onClick={onBadgeClick} isTile={isTile}>
<Badge
{...commonBadgeProps}
className="badge-version badge-new-version tablet-badge icons-group"
backgroundColor="#ED7309"
label={t("New")}
onClick={onBadgeClick}
/>
</BadgeWrapper>
)}
</div>
) : (
showNew && (
<Badge
{...commonBadgeProps}
className="new-items tablet-badge"
backgroundColor="#ED7309"
borderRadius="11px"
color="#FFFFFF"
fontSize={fontSizeBadge}
fontWeight={800}
label={contentNewItems}
maxWidth="50px"
onClick={onBadgeClick}
padding={paddingBadge}
lineHeight={lineHeightBadge}
data-id={id}
/>
)
);

View File

@ -6,6 +6,7 @@ import commonIconsStyles from "@appserver/components/utils/common-icons-style";
import CheckIcon from "../../public/images/check.react.svg";
import CrossIcon from "../../../../../public/images/cross.react.svg";
import { tablet } from "@appserver/components/utils/device";
const StyledCheckIcon = styled(CheckIcon)`
${commonIconsStyles}
@ -52,11 +53,13 @@ const EditingWrapper = styled.div`
${(props) =>
props.viewAs === "tile" &&
`margin-right: 12px !important; margin-left: -4px;`}
@media (max-width: 1024px) {
`margin-right: 10px !important; margin-left: 8px;`}
@media ${tablet} {
height: 56px;
}
.edit-text {
height: 32px;
font-size: ${(props) =>
@ -71,13 +74,34 @@ const EditingWrapper = styled.div`
font-family: "Open Sans", sans-serif, Arial;
text-align: left;
color: #333333;
margin-left: 6px;
${(props) =>
props.viewAs === "tile" &&
css`
margin-right: 2px;
border: none;
background: none;
`};
}
.edit-button {
margin-left: 8px;
height: 32px;
padding: 8px 7px 7px 7px;
${(props) =>
props.viewAs === "tile" &&
css`
background: none;
border: 1px solid transparent;
:hover {
border-color: #d0d5da;
}
&:last-child {
margin-left: 2px;
}
`};
${(props) =>
props.viewAs === "table" &&
css`
@ -90,10 +114,6 @@ const EditingWrapper = styled.div`
border: 1px solid #d0d5da;
}
`}
&:last-child {
margin-left: 4px;
}
}
.edit-ok-icon {
@ -139,11 +159,9 @@ const EditingWrapperComponent = (props) => {
if (!isLoading) setIsLoading(true);
return onClickUpdateItem(e);
}
//if (code === 27) return cancelUpdateItem(e);
};
const onEscapeKeyPress = (e) => {
if (e.keyCode === 27) return cancelUpdateItem(e);
return;
};
const setIsHoveredOkHandler = () => {

View File

@ -26,9 +26,11 @@ const QuickButtons = ({
const isEditingWithFav = fileStatus === 33;
const showFavorite = isFavorite || isNewWithFav || isEditingWithFav;
const colorSharedButton = shared ? "#3B72A7" : "#a3a9ae";
const isTile = viewAs === "tile";
const iconShare = "/static/images/catalog.share.react.svg";
const iconShare = shared
? "/static/images/file.actions.share.react.svg"
: "/static/images/catalog.share.react.svg";
const iconLock = locked
? "/static/images/file.actions.locked.react.svg"
@ -39,8 +41,8 @@ const QuickButtons = ({
: "/static/images/favorite.react.svg";
const tabletViewQuickButton =
(sectionWidth > 500 && sectionWidth <= 1024) || isTablet;
const sizeQuickButton = tabletViewQuickButton ? "medium" : "small";
!isTile && ((sectionWidth > 500 && sectionWidth <= 1024) || isTablet);
const sizeQuickButton = isTile || tabletViewQuickButton ? "medium" : "small";
const displayShare = viewAs === "row" && (isMobile || sectionWidth <= 500);
const displayLock = !locked && (isMobile || sectionWidth <= 500);
@ -48,27 +50,30 @@ const QuickButtons = ({
return (
<div className="badges additional-badges">
{item.canShare && showShare && !displayShare && (
{item.canShare && showShare && (!displayShare || isTile) && (
<StyledIcon
iconName={iconShare}
className="badge share-button-icon"
size={sizeQuickButton}
onClick={onClickShare}
color={colorSharedButton}
/>
)}
{fileExst && accessToEdit && !isTrashFolder && !displayLock && (
<StyledIcon
iconName={iconLock}
className="badge lock-file icons-group"
size={sizeQuickButton}
data-id={id}
data-locked={locked ? true : false}
onClick={onClickLock}
hoverColor="#3B72A7"
/>
)}
{fileExst && !isTrashFolder && !displayFavorite && (
{fileExst &&
accessToEdit &&
!isTrashFolder &&
(!displayLock || isTile) && (
<StyledIcon
iconName={iconLock}
className="badge lock-file icons-group"
size={sizeQuickButton}
data-id={id}
data-locked={locked ? true : false}
onClick={onClickLock}
hoverColor="#3B72A7"
/>
)}
{fileExst && !isTrashFolder && (!displayFavorite || isTile) && (
<StyledIcon
iconName={iconFavorite}
className="favorite badge icons-group"

View File

@ -71,12 +71,6 @@ const StyledSimpleFilesRow = styled(Row)`
}
`}
.share-button-icon:hover {
cursor: pointer;
path {
fill: #3b72a7;
}
}
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
.styled-element {

View File

@ -183,14 +183,6 @@ const StyledQuickButtonsContainer = styled.div`
.favorite {
margin-top: 1px;
}
.share-button-icon:hover {
cursor: pointer;
path {
fill: #3b72a7;
}
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
`;
const FilesTableRow = (props) => {

View File

@ -11,10 +11,10 @@ import withFileActions from "../../../../../HOCs/withFileActions";
import withContextOptions from "../../../../../HOCs/withContextOptions";
import withQuickButtons from "../../../../../HOCs/withQuickButtons";
import ItemIcon from "../../../../../components/ItemIcon";
import withBadges from "../../../../../HOCs/withBadges";
const FilesTile = (props) => {
const FileTile = (props) => {
const {
t,
item,
sectionWidth,
dragging,
@ -27,17 +27,16 @@ const FilesTile = (props) => {
value,
displayShareButton,
isPrivacy,
//sharedButton,
contextOptionsProps,
checkedProps,
//element,
getIcon,
onFilesClick,
onMouseClick,
showShare,
isActive,
isEdit,
quickButtonsComponent,
badgesComponent,
t,
} = props;
const temporaryExtension =
@ -97,6 +96,7 @@ const FilesTile = (props) => {
sectionWidth={sectionWidth}
onFilesClick={onFilesClick}
/>
{badgesComponent}
</Tile>
</DragAndDrop>
</div>
@ -107,9 +107,11 @@ export default inject(({ formatsStore }) => {
const { getIcon } = formatsStore.iconFormatsStore;
return { getIcon };
})(
withTranslation("Home")(
withTranslation(["Home", "VersionBadge"])(
withFileActions(
withContextOptions(withRouter(withQuickButtons(observer(FilesTile))))
withContextOptions(
withRouter(withBadges(withQuickButtons(observer(FileTile))))
)
)
)
);

View File

@ -4,33 +4,23 @@ import { withTranslation } from "react-i18next";
import styled from "styled-components";
import Link from "@appserver/components/link";
import Text from "@appserver/components/text";
import TileContent from "./sub-components/TileContent";
import withContent from "../../../../../HOCs/withContent";
import withBadges from "../../../../../HOCs/withBadges";
import { isMobile } from "react-device-detect";
import { isDesktop } from "react-device-detect";
const SimpleFilesTileContent = styled(TileContent)`
.row-main-container {
height: auto;
max-width: 100%;
align-self: flex-end;
a {
word-break: break-word;
}
}
.main-icons {
align-self: flex-end;
}
.badge-ext {
margin-left: -8px;
margin-right: 8px;
}
.badge {
margin-right: 8px;
cursor: pointer;
@ -54,11 +44,6 @@ const SimpleFilesTileContent = styled(TileContent)`
padding-right: 8px;
}
.title-link {
font-size: ${isMobile ? "15px" : "13px"};
margin-top: 2px;
}
.favorite,
.can-convert,
.edit {
@ -78,45 +63,26 @@ const SimpleFilesTileContent = styled(TileContent)`
}
`;
const FilesTileContent = ({
item,
titleWithoutExt,
linkStyles,
badgesComponent,
}) => {
const FilesTileContent = ({ item, titleWithoutExt, linkStyles }) => {
const { fileExst, title } = item;
return (
<>
<SimpleFilesTileContent sideColor="#333" isFile={fileExst}>
<Link
className="title-link item-file-name"
className="item-file-name"
containerWidth="100%"
type="page"
title={title}
fontWeight="600"
fontSize={isMobile ? "15px" : "13px"}
fontSize={isDesktop ? "13px" : "14px"}
target="_blank"
{...linkStyles}
color="#333"
isTextOverflow
>
{titleWithoutExt}
{fileExst ? (
<Text
className="badge-ext"
as="span"
color="#A3A9AE"
fontSize={isMobile ? "15px" : "13px"}
fontWeight={600}
truncate={true}
>
{fileExst}
</Text>
) : null}
</Link>
<div className="badges">{badgesComponent}</div>
</SimpleFilesTileContent>
</>
);

View File

@ -6,11 +6,12 @@ import { ReactSVG } from "react-svg";
import styled, { css } from "styled-components";
import ContextMenu from "@appserver/components/context-menu";
import { tablet } from "@appserver/components/utils/device";
import { isDesktop, isMobile } from "react-device-detect";
import { isDesktop } from "react-device-detect";
import Link from "@appserver/components/link";
import Loader from "@appserver/components/loader";
const svgLoader = () => <div style={{ width: "96px" }}></div>;
const svgLoader = () => <div style={{ width: "96px" }} />;
const FlexBoxStyles = css`
display: flex;
@ -23,89 +24,48 @@ const FlexBoxStyles = css`
`;
const FolderStyles = css`
padding-left: 13px;
padding-bottom: 2px;
box-sizing: border-box;
height: 64px;
`;
const draggingStyle = css`
background-color: #f8f7bf;
`;
const draggingHoverStyle = css`
background-color: #efefb2;
const FileStyles = css`
height: 220px;
`;
const checkedStyle = css`
background: #f3f4f4 !important;
`;
const bottomFileBorder = css`
border-top-color: #d0d5da;
border-radius: 0 0 6px 6px;
`;
const StyledTile = styled.div`
cursor: ${(props) => (!props.isRecycleBin ? "pointer" : "default")};
min-height: 57px;
${(props) =>
props.inProgress &&
css`
pointer-events: none;
/* cursor: wait; */
`}
box-sizing: border-box;
width: 100%;
border: 1px solid #d0d5da;
border-radius: 3px;
${(props) => props.isFolder && "border-top-left-radius: 0px;"}
border-radius: 6px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
${(props) => props.isFolder && FlexBoxStyles}
${(props) => props.isFolder && FolderStyles}
${(props) => (props.checked || props.isActive) && checkedStyle}
${(props) =>
${(props) => (props.isFolder ? FolderStyles : FileStyles)}
${(props) =>
!props.isEdit &&
props.isFolder &&
css`
&:before {
content: "";
position: absolute;
top: -5px;
left: 0px;
border-top: 1px solid #d0d5da;
border-top-left-radius: 3px;
border-left: 1px solid #d0d5da;
width: 38px;
height: 8px;
background-color: #fff;
border-bottom: transparent;
}
&:after {
content: "";
position: absolute;
top: -3.5px;
left: 36px;
border-top: 1px solid #d0d5da;
background-color: #fff;
width: 9px;
height: 10px;
transform: rotateZ(35deg);
@media ${tablet} {
left: 35px;
}
}
`}
&:before,
&:after {
${(props) => props.isFolder && props.dragging && draggingStyle};
}
&:before,
&:after {
${(props) => (props.checked || props.isActive) && checkedStyle};
}
&:hover:before,
&:hover:after {
${(props) => props.isFolder && props.dragging && draggingHoverStyle};
}
(props.checked || props.isActive) &&
checkedStyle}
.checkbox {
display: flex;
opacity: ${(props) => (props.checked ? 1 : 0)};
flex: 0 0 16px;
margin-right: 4px;
justify-content: center;
@media ${tablet} {
@ -116,68 +76,33 @@ const StyledTile = styled.div`
.file-checkbox {
display: ${(props) => (props.checked ? "flex" : "none")};
flex: 0 0 16px;
margin-top: 3px;
margin-left: ${(props) =>
isMobile
? css`
${props.isFolder ? "6px" : "12px"};
`
: css`
${props.isFolder ? "5px" : "8px"}
`};
@media ${tablet} {
margin-top: 2px;
}
margin-top: 8px;
margin-left: ${(props) => (props.isFolder ? "8px" : "7px")};
}
.file-icon {
display: ${(props) => (props.checked ? "none" : "flex")};
flex: 0 0 auto;
margin-right: 4px;
user-select: none;
margin-top: ${(props) => (props.isFolder ? "-8px" : "-6px")};
height: ${isMobile ? "32px" : "24px"};
width: ${isMobile ? "32px" : "24px"};
img {
height: ${isMobile ? "32px" : "24px"};
width: ${isMobile ? "32px" : "24px"};
}
margin-left: ${(props) =>
isMobile
? css`
${props.isFolder ? "2px" : "4px"};
`
: css`
${props.isFolder ? "2px" : "4px"}
`};
margin-top: ${(props) => (props.isFolder ? "0" : "-2px")};
}
.file-icon_container {
min-width: ${isMobile ? "36px" : "28px"};
width: 32px;
height: 32px;
margin-left: ${(props) => (props.isFolder ? "15px" : "16px")};
margin-right: ${(props) => (props.isFolder ? "7px" : "8px")};
}
.styled-content {
padding-left: 10px;
padding-left: ${(props) =>
isMobile
? css`
${props.isFolder ? "8px" : "12px"};
`
: css`
${props.isFolder ? "10px" : "13px"}
`};
.tile-folder-loader {
padding-top: 4px;
}
:hover {
${(props) =>
!props.dragging &&
props.isDesktop &&
!props.inProgress &&
css`
.checkbox {
opacity: 1;
@ -193,41 +118,40 @@ const StyledTile = styled.div`
`;
const StyledFileTileTop = styled.div`
${FlexBoxStyles}
${FlexBoxStyles};
justify-content: space-between;
align-items: baseline;
background-color: #f8f9f9;
padding-top: 21px;
height: ${(props) => (props.checked || props.isActive ? "156px" : "156px")};
height: 156px;
position: relative;
border-bottom: ${(props) =>
props.checked || props.isActive
? "1px solid #D0D5DA"
: "1px solid transparent"};
.thumbnail-image,
.temporary-icon > .injected-svg {
.thumbnail-image {
pointer-events: none;
position: absolute;
left: 0;
right: 0;
bottom: 0;
margin: auto;
height: 100%;
width: 100%;
object-fit: cover;
border-radius: 6px 6px 0 0;
z-index: 0;
min-width: 208px;
}
.temporary-icon > .injected-svg {
margin-bottom: 16px;
position: absolute;
width: 100%;
bottom: 16px;
}
`;
const StyledFileTileBottom = styled.div`
${FlexBoxStyles}
padding: 9px 10px;
padding-right: 0;
height: 56px;
${FlexBoxStyles};
${(props) =>
!props.isEdit && (props.checked || props.isActive) && checkedStyle}
border-top: 1px solid transparent;
${(props) =>
!props.isEdit && (props.checked || props.isActive) && bottomFileBorder}
padding: 9px 0;
height: 62px;
box-sizing: border-box;
`;
@ -241,13 +165,13 @@ const StyledContent = styled.div`
max-width: 400px;
height: auto;
margin: 0 auto;
font-size: 15px;
line-height: 19px;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
word-break: break-word;
}
@media (max-width: 1024px) {
@ -272,10 +196,60 @@ const StyledOptionButton = styled.div`
display: block;
.expandButton > div:first-child {
padding-top: 8px;
padding-bottom: 8px;
padding-left: 12px;
padding-right: 13px;
padding: 8px 21px 8px 12px;
}
`;
const badgesPosition = css`
left: 9px;
.badges {
display: grid;
grid-template-columns: repeat(3, fit-content(50px));
grid-template-rows: 32px;
grid-gap: 7px;
.badge-new-version {
order: 1;
}
.badge-version-current {
order: 2;
}
.is-editing,
.can-convert {
order: 3;
}
}
`;
const quickButtonsPosition = css`
right: 9px;
.badges {
display: grid;
grid-template-columns: 32px;
grid-template-rows: repeat(3, 32px);
grid-gap: 7px;
}
`;
const StyledIcons = styled.div`
position: absolute;
top: 8px;
${(props) => props.isBadges && badgesPosition}
${(props) => props.isQuickButtons && quickButtonsPosition}
.badge {
display: flex;
align-items: center;
justify-content: center;
padding: 8px;
background: rgb(255, 255, 255);
border-radius: 4px;
box-shadow: 0px 2px 4px rgba(4, 15, 27, 0.16);
}
`;
@ -344,21 +318,23 @@ class Tile extends React.PureComponent {
isRecycleBin,
item,
isActive,
inProgress,
isEdit,
contentElement,
title,
} = this.props;
const { isFolder, id, fileExst } = item;
const renderCheckbox = Object.prototype.hasOwnProperty.call(
this.props,
"checked"
);
const renderElement = Object.prototype.hasOwnProperty.call(
this.props,
"element"
);
const renderContentElement = Object.prototype.hasOwnProperty.call(
this.props,
"contentElement"
);
const renderContext =
Object.prototype.hasOwnProperty.call(this.props, "contextOptions") &&
contextOptions.length > 0;
@ -377,6 +353,8 @@ class Tile extends React.PureComponent {
};
const icon = this.getIconFile();
const [FilesTileContent, badges] = children;
const quickButtons = contentElement;
return (
<StyledTile
@ -388,31 +366,42 @@ class Tile extends React.PureComponent {
isRecycleBin={isRecycleBin}
checked={checked}
isActive={isActive}
inProgress={inProgress}
isDesktop={isDesktop}
>
{isFolder || (!fileExst && id === -1) ? (
<>
{renderElement && !(!fileExst && id === -1) && !isEdit && (
<div className="file-icon_container">
<StyledElement
className="file-icon"
onClick={this.onFileIconClick}
>
{element}
</StyledElement>
<Checkbox
className="checkbox file-checkbox"
isChecked={checked}
isIndeterminate={indeterminate}
onChange={this.changeCheckbox}
/>
</div>
<>
{!inProgress ? (
<div className="file-icon_container">
<StyledElement
className="file-icon"
onClick={this.onFileIconClick}
>
{element}
</StyledElement>
<Checkbox
className="file-checkbox"
isChecked={checked}
isIndeterminate={indeterminate}
onChange={this.changeCheckbox}
/>
</div>
) : (
<Loader
className="tile-folder-loader"
type="oval"
size="16px"
/>
)}
</>
)}
<StyledContent
className="styled-content"
isFolder={(isFolder && !fileExst) || (!fileExst && id === -1)}
>
{children}
{FilesTileContent}
</StyledContent>
<StyledOptionButton spacerWidth={contextButtonSpacerWidth}>
{renderContext ? (
@ -427,9 +416,9 @@ class Tile extends React.PureComponent {
title={title}
/>
) : (
<div className="expandButton"> </div>
<div className="expandButton" />
)}
<ContextMenu model={contextOptions} ref={this.cm}></ContextMenu>
<ContextMenu model={contextOptions} ref={this.cm} />
</StyledOptionButton>
</>
) : (
@ -437,25 +426,37 @@ class Tile extends React.PureComponent {
<StyledFileTileTop checked={checked} isActive={isActive}>
{icon}
</StyledFileTileTop>
<StyledFileTileBottom>
<StyledIcons isBadges>{badges}</StyledIcons>
{renderContentElement && (
<StyledIcons isQuickButtons>{quickButtons}</StyledIcons>
)}
<StyledFileTileBottom
checked={checked}
isActive={isActive}
isEdit={isEdit}
>
{id !== -1 && !isEdit && (
<div className="file-icon_container">
<div className="file-icon" onClick={this.onFileIconClick}>
{element}
<>
<div className="file-icon_container">
<div className="file-icon" onClick={this.onFileIconClick}>
{element}
</div>
<Checkbox
className="file-checkbox"
isChecked={checked}
isIndeterminate={indeterminate}
onChange={this.changeCheckbox}
/>
</div>
<Checkbox
className="file-checkbox"
isChecked={checked}
isIndeterminate={indeterminate}
onChange={this.changeCheckbox}
/>
</div>
</>
)}
<StyledContent
className="styled-content"
isFolder={(isFolder && !fileExst) || (!fileExst && id === -1)}
>
{children}
{FilesTileContent}
</StyledContent>
<StyledOptionButton spacerWidth={contextButtonSpacerWidth}>
{renderContext ? (
@ -470,9 +471,9 @@ class Tile extends React.PureComponent {
title={title}
/>
) : (
<div className="expandButton"> </div>
<div className="expandButton" />
)}
<ContextMenu model={contextOptions} ref={this.cm}></ContextMenu>
<ContextMenu model={contextOptions} ref={this.cm} />
</StyledOptionButton>
</StyledFileTileBottom>
</>
@ -484,7 +485,10 @@ class Tile extends React.PureComponent {
Tile.propTypes = {
checked: PropTypes.bool,
children: PropTypes.element,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element,
]),
className: PropTypes.string,
contextButtonSpacerWidth: PropTypes.string,
contextOptions: PropTypes.array,
@ -497,6 +501,7 @@ Tile.propTypes = {
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
viewAs: PropTypes.string,
tileContextClick: PropTypes.func,
contentElement: PropTypes.element,
};
Tile.defaultProps = {

View File

@ -20,33 +20,19 @@ const paddingCss = css`
}
`;
const foldersStyle = css`
grid-gap: 19px 16px;
${paddingCss}
@media ${tablet} {
grid-gap: 17px 12px;
}
`;
const filesStyle = css`
grid-gap: 14px 16px;
${paddingCss}
@media ${tablet} {
grid-gap: 12px;
}
`;
const StyledGridWrapper = styled.div`
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
width: 100%;
padding-bottom: 24px;
margin-bottom: ${(props) => (props.isFolders ? "23px" : 0)};
box-sizing: border-box;
${(props) => (props.isFolders ? foldersStyle : filesStyle)};
${paddingCss};
grid-gap: 14px 16px;
@media ${tablet} {
grid-gap: 14px;
}
`;
const StyledTileContainer = styled.div`
@ -66,12 +52,8 @@ const StyledTileContainer = styled.div`
.tile-items-heading {
margin: 0;
padding-bottom: 11px;
margin-bottom: 15px;
pointer-events: none;
&.files {
padding-top: 8px;
}
}
@media ${tablet} {
@ -105,11 +87,11 @@ class TileContainer extends React.PureComponent {
}
renderFolders = () => {
return <div></div>;
return <div />;
};
renderFiles = () => {
return <div></div>;
return <div />;
};
// eslint-disable-next-line react/prop-types
@ -209,9 +191,11 @@ class TileContainer extends React.PureComponent {
{Files.length > 0 && (
<>
<Heading size="xsmall" className="tile-items-heading">
{headingFiles}
</Heading>
{Folders.length > 0 && (
<Heading size="xsmall" className="tile-items-heading">
{headingFiles}
</Heading>
)}
{useReactWindow ? (
<AutoSizer>{renderList}</AutoSizer>
) : (

View File

@ -19,15 +19,6 @@ const commonCss = css`
const StyledTileContent = styled.div`
width: 100%;
display: inline-flex;
${(props) =>
!props.disableSideInfo &&
css`
@media (max-width: 1024px) {
display: block;
height: 56px;
}
`};
`;
const MainContainerWrapper = styled.div`
@ -36,161 +27,31 @@ const MainContainerWrapper = styled.div`
display: flex;
align-self: center;
margin-right: auto;
${(props) =>
!props.disableSideInfo &&
css`
@media (max-width: 1024px) {
margin-right: 8px;
margin-top: 8px;
}
`};
`;
const MainContainer = styled.div`
height: 20px;
.badge-ext {
margin: 0px !important;
}
@media (max-width: 1024px) {
${truncateCss};
}
`;
const MainIcons = styled.div`
align-self: center;
white-space: nowrap;
.badges {
margin-right: 4px;
}
.additional-badges {
position: absolute;
top: 1px;
right: 2px;
display: flex;
flex-direction: row;
.icons-group {
margin-top: 10px;
margin-right: 3px;
}
}
`;
const SideContainerWrapper = styled.div`
${commonCss};
@media (max-width: 1024px) {
${truncateCss};
}
align-self: center;
align-items: center;
> a {
vertical-align: middle;
}
color: ${(props) => props.color && props.color};
${(props) =>
!props.disableSideInfo &&
css`
@media (max-width: 1024px) {
display: none;
}
`};
`;
const TabletSideInfo = styled.div`
display: none;
@media (max-width: 1024px) {
display: block;
color: ${(props) => props.color && props.color};
${commonCss};
${truncateCss};
}
`;
const getSideInfo = (content) => {
let info = "";
const lastIndex = content.length - 1;
content.forEach((element, index) => {
if (element) {
const delimiter = index === lastIndex ? "" : " | ";
if (index > 1) {
info +=
element.props && element.props.children
? element.props.children + delimiter
: "";
}
}
});
return info;
};
const TileContent = (props) => {
//console.log("TileContent render");
const {
children,
disableSideInfo,
id,
className,
style,
sideColor,
onClick,
badges,
} = props;
const sideInfo = getSideInfo(children);
const { children, id, className, style, onClick } = props;
return (
<StyledTileContent
disableSideInfo={disableSideInfo}
id={id}
className={className}
style={style}
onClick={onClick}
>
{badges}
<MainContainerWrapper
disableSideInfo={disableSideInfo}
mainContainerWidth={
children[0].props && children[0].props.containerWidth
}
mainContainerWidth={children.props && children.props.containerWidth}
>
<MainContainer className="row-main-container">
{children[0]}
</MainContainer>
<MainIcons className="main-icons">{children[1]}</MainIcons>
<MainContainer className="row-main-container">{children}</MainContainer>
</MainContainerWrapper>
{children.map((element, index) => {
if (index > 1 && element) {
return (
<SideContainerWrapper
disableSideInfo={disableSideInfo}
key={"side-" + index}
containerWidth={element.props && element.props.containerWidth}
containerMinWidth={
element.props && element.props.containerMinWidth
}
>
{element}
</SideContainerWrapper>
);
}
return null;
})}
{!disableSideInfo && (
<TabletSideInfo color={sideColor}>{sideInfo}</TabletSideInfo>
)}
</StyledTileContent>
);
};
@ -198,15 +59,10 @@ const TileContent = (props) => {
TileContent.propTypes = {
children: PropTypes.node.isRequired,
className: PropTypes.string,
disableSideInfo: PropTypes.bool,
id: PropTypes.string,
onClick: PropTypes.func,
sideColor: PropTypes.string,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
};
TileContent.defaultProps = {
disableSideInfo: false,
};
export default TileContent;

View File

@ -230,8 +230,6 @@ export default inject(
fileActionId: fileActionStore.id,
isEmptyFilesList,
setDragging,
startDrag,
setStartDrag,
folderId: selectedFolderStore.id,
setTooltipPosition,
isRecycleBinFolder: treeFoldersStore.isRecycleBinFolder,

View File

@ -291,7 +291,6 @@ class PureHome extends React.Component {
isHeaderVisible={isHeaderVisible}
onOpenUploadPanel={this.showUploadPanel}
firstLoad={firstLoad}
dragging={dragging}
>
<PageLayout.ArticleHeader>
<ArticleHeaderContent />

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 0.999512V2.99951V4.99951C9.47715 4.99951 5 9.47666 5 14.9995H3H1C1 7.26753 7.26801 0.999512 15 0.999512ZM7 14.9995C7 10.5812 10.5817 6.99951 15 6.99951V12.9995C15 14.1041 14.1046 14.9995 13 14.9995H7Z" fill="#3B72A7"/>
</svg>

After

Width:  |  Height:  |  Size: 375 B