Web: Templates: Added room creation from a template

This commit is contained in:
Nikita Gopienko 2024-04-15 11:17:04 +03:00
parent 63f17aa4c8
commit 51dacad300
9 changed files with 206 additions and 46 deletions

View File

@ -34,6 +34,8 @@ import TagHandler from "./handlers/TagHandler";
import SetRoomParams from "./sub-components/SetRoomParams";
import RoomTypeList from "./sub-components/RoomTypeList";
import DialogHeader from "./sub-components/DialogHeader";
import TemplateBody from "./sub-components/TemplateBody";
import { RoomsType } from "@docspace/shared/enums";
const StyledModalDialog = styled(ModalDialog)`
.header-with-button {
@ -55,6 +57,19 @@ const StyledModalDialog = styled(ModalDialog)`
display: none;
}
`}
${({ isTemplate }) =>
isTemplate &&
css`
.selector_body,
.modal-body {
padding: 0;
}
.selector_body {
height: 100%;
}
`}
`;
const CreateRoomDialog = ({
@ -106,6 +121,7 @@ const CreateRoomDialog = ({
const [roomParams, setRoomParams] = useState({ ...startRoomParams });
const [isValidTitle, setIsValidTitle] = useState(true);
const [isTemplateSelected, setIsTemplateSelected] = useState(false);
const setRoomTags = (newTags) =>
setRoomParams({ ...roomParams, tags: newTags });
@ -143,6 +159,15 @@ const CreateRoomDialog = ({
const goBack = () => {
if (isLoading) return;
if (isTemplateSelected) {
setIsTemplateSelected(false);
setRoomParams((prev) => ({
...prev,
title: "",
type: RoomsType.TemplateRoom,
}));
return;
}
setRoomParams({ ...startRoomParams });
};
@ -160,29 +185,42 @@ const CreateRoomDialog = ({
onClose();
};
const isTemplate =
roomParams.type === RoomsType.TemplateRoom && !isTemplateSelected;
return (
<StyledModalDialog
displayType="aside"
withBodyScroll
withBodyScroll={!isTemplate}
visible={visible}
onClose={onCloseAndDisconnectThirdparty}
isScrollLocked={isScrollLocked}
withFooterBorder
isOauthWindowOpen={isOauthWindowOpen}
isTemplate={isTemplate}
>
<ModalDialog.Header>
<DialogHeader
isChooseRoomType={!roomParams.type}
onArrowClick={goBack}
isTemplate={isTemplate}
isTemplateSelected={isTemplateSelected}
/>
</ModalDialog.Header>
<ModalDialog.Body>
{!roomParams.type ? (
<RoomTypeList t={t} setRoomType={setRoomType} />
) : isTemplate ? (
<TemplateBody
t={t}
setIsTemplateSelected={setIsTemplateSelected}
setRoomParams={setRoomParams}
/>
) : (
<SetRoomParams
t={t}
isTemplateSelected={isTemplateSelected}
setIsOauthWindowOpen={setIsOauthWindowOpen}
tagHandler={tagHandler}
roomParams={roomParams}
@ -200,7 +238,7 @@ const CreateRoomDialog = ({
)}
</ModalDialog.Body>
{!!roomParams.type && (
{!!roomParams.type && !isTemplate && (
<ModalDialog.Footer>
<Button
id="shared_create-room-modal_submit"

View File

@ -38,45 +38,48 @@ const ChangeRoomOwner = ({
roomOwner,
onOwnerChange,
currentColorScheme,
isTemplate,
}) => {
const userName = roomOwner.displayName ?? roomOwner.label;
return (
<Styled.ChangeRoomOwner>
<Styled.ChangeRoomOwner isTemplate={isTemplate}>
<Text className="change-owner-label" fontWeight={600} fontSize="13px">
{t("Files:RoomOwner")}
{isTemplate ? `${t("Files:AccessToTemplate")}:` : t("Files:RoomOwner")}
</Text>
<div className="change-owner-display">
<Avatar
className={"change-owner-display-avatar"}
size="min"
role={""}
isDefaultSource={roomOwner.hasAvatar}
source={roomOwner.avatarSmall ?? roomOwner.avatar}
userName={userName}
/>
<div className="change-owner-display-name">
<Text fontWeight={600} fontSize="13px">
{userName}
</Text>
{roomOwner.id === currentUserId && (
<Text className="me-label">({t("Common:MeLabel")})</Text>
)}
<div className="change-owner-display-wrapper">
<div className="change-owner-display">
<Avatar
className={"change-owner-display-avatar"}
size="base"
role={""}
isDefaultSource={roomOwner.hasAvatar}
source={roomOwner.avatarSmall ?? roomOwner.avatar}
userName={userName}
/>
<div className="change-owner-display-name">
<Text fontWeight={600} fontSize="13px">
{userName}
</Text>
{roomOwner.id === currentUserId && (
<Text className="me-label">({t("Common:MeLabel")})</Text>
)}
</div>
</div>
</div>
<Link
className="change-owner-link"
isHovered
type="action"
fontWeight={600}
fontSize="13px"
color={currentColorScheme.main?.accent}
onClick={onOwnerChange}
>
{t("Common:ChangeButton")}
</Link>
<Link
className="change-owner-link"
isHovered
type="action"
fontWeight={600}
fontSize="13px"
color={isTemplate ? null : currentColorScheme.main?.accent}
onClick={onOwnerChange}
>
{isTemplate ? t("Files:AccessSettings") : t("Common:ChangeButton")}
</Link>
</div>
</Styled.ChangeRoomOwner>
);
};

View File

@ -44,6 +44,15 @@ export const ChangeRoomOwner = styled.div`
}
}
}
.change-owner-display-wrapper {
display: ${(props) => (props.isTemplate ? "flex" : "block")};
align-items: center;
.change-owner-link {
margin-left: auto;
}
}
`;
ChangeRoomOwner.defaultProps = { theme: Base };

View File

@ -32,7 +32,20 @@ import withLoader from "@docspace/client/src/HOCs/withLoader";
import { IconButton } from "@docspace/shared/components/icon-button";
import CreateEditRoomDilogHeaderLoader from "@docspace/shared/skeletons/create-edit-room/DilogHeader";
const DialogHeader = ({ t, isEdit, isChooseRoomType, onArrowClick }) => {
const DialogHeader = ({
t,
isEdit,
isChooseRoomType,
onArrowClick,
isTemplate,
isTemplateSelected,
}) => {
const title = isTemplateSelected
? t("Files:SaveAsTemplate")
: isTemplate
? t("Files:FromTemplate")
: t("Files:CreateRoom");
return (
<>
{isEdit ? (
@ -47,7 +60,7 @@ const DialogHeader = ({ t, isEdit, isChooseRoomType, onArrowClick }) => {
className="sharing_panel-arrow"
onClick={onArrowClick}
/>
<div>{t("Files:CreateRoom")}</div>
<div>{title}</div>
</div>
)}
</>

View File

@ -31,14 +31,23 @@ import { StyledParam } from "./StyledParam";
import { FieldContainer } from "@docspace/shared/components/field-container";
import { Label } from "@docspace/shared/components/label";
import { TextInput } from "@docspace/shared/components/text-input";
import { HelpButton } from "@docspace/shared/components/help-button";
import { Text } from "@docspace/shared/components/text";
const StyledInputParam = styled(StyledParam)`
flex-direction: column;
gap: 4px;
max-height: 54px;
.input-label {
cursor: pointer;
user-select: none;
.input-label-wrapper {
display: flex;
align-items: center;
gap: 4px;
.input-label {
cursor: pointer;
user-select: none;
}
}
`;
@ -59,18 +68,31 @@ const InputParam = React.forwardRef(
isAutoFocussed,
onKeyUp,
onKeyDown,
tooltipLabel,
},
ref,
) => {
return (
<StyledInputParam>
<Label
title={title}
className="input-label"
display="display"
htmlFor={id}
text={title}
/>
<div className="input-label-wrapper">
<Label
title={title}
className="input-label"
display="display"
htmlFor={id}
text={title}
/>
{tooltipLabel && (
<HelpButton
place="right"
tooltipContent={
<Text fontSize="12px" fontWeight={400}>
{tooltipLabel}
</Text>
}
/>
)}
</div>
<FieldContainer
isVertical={true}

View File

@ -37,6 +37,8 @@ import {
getRoomTypeDescriptionTranslation,
getRoomTypeTitleTranslation,
} from "./../data/index";
import { RoomsType } from "@docspace/shared/enums";
import { Badge } from "@docspace/shared/components/badge";
const StyledRoomType = styled.div`
cursor: pointer;
@ -185,6 +187,8 @@ const RoomType = ({
description: getRoomTypeDescriptionTranslation(roomType, t),
};
const isTemplate = roomType === RoomsType.TemplateRoom;
const arrowClassName =
type === "dropdownButton"
? "choose_room-forward_btn dropdown-button"
@ -203,6 +207,17 @@ const RoomType = ({
<Text noSelect className="choose_room-title-text">
{t(room.title)}
</Text>
{isTemplate && (
<Badge
label={t("New").toUpperCase()}
backgroundColor="#7757D9"
fontSize="9px"
fontWeight={700}
borderRadius="50px"
noHover
isHovered={false}
/>
)}
</div>
<Text noSelect className="choose_room-description">
{t(room.description)}

View File

@ -95,6 +95,7 @@ const SetRoomParams = ({
currentColorScheme,
setChangeRoomOwnerIsVisible,
folderFormValidation,
isTemplateSelected,
}) => {
const [previewIcon, setPreviewIcon] = useState(null);
const [createNewFolderIsChecked, setCreateNewFolderIsChecked] =
@ -147,7 +148,7 @@ const SetRoomParams = ({
return (
<StyledSetRoomParams disableImageRescaling={disableImageRescaling}>
{isEdit ? (
{isEdit || isTemplateSelected ? (
<RoomType t={t} roomType={roomParams.type} type="displayItem" />
) : (
<RoomTypeDropdown

View File

@ -54,9 +54,11 @@ const StyledTagInput = styled.div`
const TagInput = ({
t,
title,
tagHandler,
setIsScrollLocked,
isDisabled,
tooltipLabel,
onFocus,
onBlur,
}) => {
@ -119,7 +121,7 @@ const TagInput = ({
<InputParam
ref={inputRef}
id="shared_tags-input"
title={`${t("Common:Tags")}:`}
title={title ? `${title}:` : `${t("Common:Tags")}:`}
placeholder={t("TagsPlaceholder")}
value={tagInput}
onChange={onTagInputChange}
@ -127,6 +129,7 @@ const TagInput = ({
onBlur={handleBlur}
isDisabled={isDisabled}
onKeyDown={handleKeyDown}
tooltipLabel={tooltipLabel}
/>
<TagDropdown

View File

@ -0,0 +1,56 @@
// (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 RoomSelector from "@docspace/shared/selectors/Room";
import { RoomsType } from "@docspace/shared/enums";
const TemplateBody = ({ t, setIsTemplateSelected, setRoomParams }) => {
const onSubmit = (item) => {
console.log("onSubmit", item);
setIsTemplateSelected(item[0]);
setRoomParams((prev) => ({
...prev,
title: item[0]?.label,
type: item[0]?.roomType,
}));
};
return (
<RoomSelector
className="template-body_selector"
onSubmit={onSubmit}
roomType={RoomsType.TemplateRoom}
isMultiSelect={false}
withHeader={false}
withSearch
emptyScreenHeader={t("Common:EmptyTemplatesRoomsHeader")}
emptyScreenDescription={t("Common:EmptyTemplatesRoomsDescription")}
/>
);
};
export default TemplateBody;