PromucFlow_constructor/app/client/src/pages/Applications/ApplicationCard.tsx

299 lines
7.9 KiB
TypeScript
Raw Normal View History

2020-08-18 06:40:11 +00:00
import React, { useState } from "react";
2019-11-21 10:52:49 +00:00
import styled from "styled-components";
import {
getApplicationViewerPageURL,
BUILDER_PAGE_URL,
} from "constants/routes";
2020-08-18 06:40:11 +00:00
import { Card, Classes } from "@blueprintjs/core";
2019-11-21 10:52:49 +00:00
import { ApplicationPayload } from "constants/ReduxActionConstants";
import Button from "components/editorComponents/Button";
2020-08-18 06:40:11 +00:00
import { theme, getColorWithOpacity } from "constants/DefaultTheme";
2019-11-21 10:52:49 +00:00
import ContextDropdown, {
ContextDropdownOption,
} from "components/editorComponents/ContextDropdown";
2020-04-03 11:08:38 +00:00
import { Colors } from "constants/Colors";
import {
isPermitted,
PERMISSION_TYPE,
} from "pages/Applications/permissionHelpers";
2020-08-18 06:40:11 +00:00
import { getInitialsAndColorCode, getColorCode } from "utils/AppsmithUtils";
import { ControlIcons } from "icons/ControlIcons";
import history from "utils/history";
const NameWrapper = styled.div<{
hasReadPermission: boolean;
showOverlay: boolean;
}>`
${props =>
props.showOverlay &&
`
{
background-color: white;
.overlay {
${props.hasReadPermission &&
`text-decoration: none;
&:after {
left: 0;
top: 0;
content: "";
position: absolute;
height: 100%;
width: 100%;
}
& .control {
display: block;
z-index: 1;
}`}
& div.image-container {
background: ${
props.hasReadPermission
? getColorWithOpacity(
props.theme.card.hoverBG,
props.theme.card.hoverBGOpacity,
)
: null
}
}
}
}
`}
border-radius: ${props => props.theme.radii[1]}px;
width: ${props => props.theme.card.minWidth + props.theme.spaces[5] * 2}px;
margin: ${props => props.theme.spaces[5]}px
${props => props.theme.spaces[5]}px;
overflow: hidden;
`;
const Name = styled.div`
padding-left: ${props => props.theme.spaces[5]}px;
padding-right: ${props => props.theme.spaces[5]}px;
padding-bottom: ${props => props.theme.spaces[5]}px;
height: 45px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 16px;
font-weight: 500;
color: ${Colors.OXFORD_BLUE};
line-height: 21px;
letter-spacing: 0.1px;
`;
2019-11-21 10:52:49 +00:00
2020-08-18 06:40:11 +00:00
const Wrapper = styled(Card)<{
hasReadPermission?: boolean;
backgroundColor: string;
}>`
2019-11-21 10:52:49 +00:00
display: flex;
flex-direction: column;
justify-content: center;
width: ${props => props.theme.card.minWidth}px;
height: ${props => props.theme.card.minHeight}px;
position: relative;
border-radius: ${props => props.theme.radii[1]}px;
2020-08-18 06:40:11 +00:00
background-color: ${props => props.backgroundColor};
2019-11-21 10:52:49 +00:00
margin: ${props => props.theme.spaces[5]}px
${props => props.theme.spaces[5]}px;
2020-08-18 06:40:11 +00:00
.overlay {
display: block;
position: absolute;
left: 0;
top: 0;
2020-08-18 06:40:11 +00:00
height: 100%;
width: 100%;
${props => !props.hasReadPermission && `pointer-events: none;`}
}
2019-11-21 10:52:49 +00:00
`;
2020-08-18 06:40:11 +00:00
2019-11-21 10:52:49 +00:00
const ApplicationImage = styled.div`
2020-01-28 08:21:22 +00:00
&& {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
& {
.control {
button {
span {
font-weight: ${props => props.theme.fontWeights[3]};
2020-08-18 06:40:11 +00:00
color: white;
2020-01-28 08:21:22 +00:00
}
}
}
2019-11-21 10:52:49 +00:00
}
}
`;
2020-05-05 12:16:51 +00:00
const Control = styled.div<{ fixed?: boolean }>`
2019-11-21 10:52:49 +00:00
outline: none;
border: none;
cursor: pointer;
2020-08-18 06:40:11 +00:00
.${Classes.BUTTON} {
margin-top: 7px;
div {
width: auto;
height: auto;
}
}
.${Classes.BUTTON_TEXT} {
font-size: 12px;
}
.more {
position: absolute;
right: ${props => props.theme.spaces[6]}px;
top: ${props => props.theme.spaces[4]}px;
}
2019-11-21 10:52:49 +00:00
`;
2020-08-18 06:40:11 +00:00
const Initials = styled.span`
font-size: 40px;
font-weight: bold;
color: #ffffff;
margin: auto;
`;
const APPLICATION_CONTROL_FONTSIZE_INDEX = 5;
2019-11-21 10:52:49 +00:00
type ApplicationCardProps = {
application: ApplicationPayload;
2020-01-27 08:24:58 +00:00
duplicate?: (applicationId: string) => void;
share?: (applicationId: string) => void;
delete?: (applicationId: string) => void;
2019-11-21 10:52:49 +00:00
};
export const ApplicationCard = (props: ApplicationCardProps) => {
2020-08-18 06:40:11 +00:00
const [showOverlay, setShowOverlay] = useState(false);
const hasEditPermission = isPermitted(
props.application?.userPermissions ?? [],
PERMISSION_TYPE.MANAGE_APPLICATION,
);
const hasReadPermission = isPermitted(
props.application?.userPermissions ?? [],
PERMISSION_TYPE.READ_APPLICATION,
);
2019-11-21 10:52:49 +00:00
const duplicateApp = () => {
2020-01-27 08:24:58 +00:00
props.duplicate && props.duplicate(props.application.id);
2019-11-21 10:52:49 +00:00
};
const shareApp = () => {
2020-01-27 08:24:58 +00:00
props.share && props.share(props.application.id);
2019-11-21 10:52:49 +00:00
};
const deleteApp = () => {
2020-01-27 08:24:58 +00:00
props.delete && props.delete(props.application.id);
2019-11-21 10:52:49 +00:00
};
2020-01-27 08:24:58 +00:00
const moreActionItems: ContextDropdownOption[] = [];
if (props.share) {
moreActionItems.push({
2019-11-21 10:52:49 +00:00
value: "share",
onSelect: shareApp,
label: "Share",
2020-01-27 08:24:58 +00:00
});
}
if (props.duplicate) {
moreActionItems.push({
value: "duplicate",
onSelect: duplicateApp,
label: "Duplicate",
});
}
if (props.delete && hasEditPermission) {
2020-01-27 08:24:58 +00:00
moreActionItems.push({
2019-11-21 10:52:49 +00:00
value: "delete",
onSelect: deleteApp,
label: "Delete",
intent: "danger",
2020-01-27 08:24:58 +00:00
});
}
2020-08-18 06:40:11 +00:00
let initials = getInitialsAndColorCode(props.application.name)[0];
if (initials.length < 2 && props.application.name.length > 1) {
initials += props.application.name[1].toUpperCase() || "";
}
const colorCode = getColorCode(props.application.id);
2020-01-27 08:24:58 +00:00
const viewApplicationURL = getApplicationViewerPageURL(
props.application.id,
props.application.defaultPageId,
);
const editApplicationURL = BUILDER_PAGE_URL(
props.application.id,
props.application.defaultPageId,
);
2019-11-21 10:52:49 +00:00
return (
2020-08-18 06:40:11 +00:00
<NameWrapper
showOverlay={showOverlay}
onMouseEnter={() => setShowOverlay(true)}
onMouseLeave={() => setShowOverlay(false)}
hasReadPermission={hasReadPermission}
className="t--application-card"
>
<Wrapper
key={props.application.id}
hasReadPermission={hasReadPermission}
backgroundColor={colorCode}
>
<Initials>{initials}</Initials>
{showOverlay && (
<div className="overlay">
<ApplicationImage className="image-container">
<Control className="control">
{!!moreActionItems.length && (
<ContextDropdown
options={moreActionItems}
toggle={{
type: "icon",
icon: "MORE_HORIZONTAL_CONTROL",
iconSize:
theme.fontSizes[APPLICATION_CONTROL_FONTSIZE_INDEX],
}}
className="more"
/>
)}
{hasEditPermission && (
<Button
onClick={() => history.push(editApplicationURL)}
filled
text="EDIT"
intent="primary"
icon={
<ControlIcons.EDIT_WHITE
color={Colors.WHITE}
width={9}
height={9}
/>
}
className="t--application-edit-link"
fluid
/>
)}
<Button
onClick={() => history.push(viewApplicationURL)}
intent="none"
outline
fluid
text="LAUNCH"
icon={<ControlIcons.LAUNCH_CONTROL width={9} height={9} />}
size="small"
className="t--application-view-link"
/>
</Control>
</ApplicationImage>
</div>
)}
2020-08-18 06:40:11 +00:00
</Wrapper>
<Name>{props.application.name}</Name>
</NameWrapper>
2019-11-21 10:52:49 +00:00
);
};
export default ApplicationCard;