[WEB-1255] chore: public and unlocked views (#4932)
* chore private and public views required changes * fix slight alignment of view icons * add feedback for update View button * fix object reference sharing by using cloneDeep to replicate objects * addressing review comments
This commit is contained in:
parent
711494b72e
commit
635efeab7b
27 changed files with 524 additions and 240 deletions
|
|
@ -11,11 +11,12 @@ import { Button, EmojiIconPicker, EmojiIconPickerTypes, Input, PhotoFilterIcon,
|
|||
import { Logo } from "@/components/common";
|
||||
import { AppliedFiltersList, FilterSelection, FiltersDropdown } from "@/components/issues";
|
||||
// constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue";
|
||||
import { EIssueLayoutTypes, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue";
|
||||
// helpers
|
||||
import { convertHexEmojiToDecimal } from "@/helpers/emoji.helper";
|
||||
// hooks
|
||||
import { useLabel, useMember, useProject, useProjectState } from "@/hooks/store";
|
||||
import { LayoutDropDown } from "../dropdowns/layout";
|
||||
|
||||
type Props = {
|
||||
data?: IProjectView | null;
|
||||
|
|
@ -190,7 +191,7 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message}</span>
|
||||
<span className="text-xs text-red-500">{errors?.name?.message?.toString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -211,7 +212,17 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex gap-2">
|
||||
<Controller
|
||||
control={control}
|
||||
name="display_filters.layout"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<LayoutDropDown
|
||||
onChange={(selectedValue: EIssueLayoutTypes) => onChange(selectedValue)}
|
||||
value={value}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="filters"
|
||||
|
|
|
|||
70
web/core/components/views/update-view-component.tsx
Normal file
70
web/core/components/views/update-view-component.tsx
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { SetStateAction, useEffect, useState } from "react";
|
||||
import { Button } from "@plane/ui";
|
||||
import { LockedComponent } from "../icons/locked-component";
|
||||
|
||||
type Props = {
|
||||
isLocked: boolean;
|
||||
areFiltersEqual: boolean;
|
||||
isOwner: boolean;
|
||||
isAuthorizedUser: boolean;
|
||||
setIsModalOpen: (value: SetStateAction<boolean>) => void;
|
||||
handleUpdateView: () => void;
|
||||
lockedTooltipContent?: string;
|
||||
};
|
||||
|
||||
export const UpdateViewComponent = (props: Props) => {
|
||||
const {
|
||||
isLocked,
|
||||
areFiltersEqual,
|
||||
isOwner,
|
||||
isAuthorizedUser,
|
||||
setIsModalOpen,
|
||||
handleUpdateView,
|
||||
lockedTooltipContent,
|
||||
} = props;
|
||||
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (areFiltersEqual) {
|
||||
setIsUpdating(false);
|
||||
}
|
||||
}, [areFiltersEqual]);
|
||||
|
||||
// Change state while updating view to have a feedback
|
||||
const updateButton = isUpdating ? (
|
||||
<Button variant="primary" size="sm" className="flex-shrink-0">
|
||||
Updating...
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
className="flex-shrink-0"
|
||||
onClick={() => {
|
||||
setIsUpdating(true);
|
||||
handleUpdateView();
|
||||
}}
|
||||
>
|
||||
Update view
|
||||
</Button>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
{isLocked ? (
|
||||
<LockedComponent toolTipContent={lockedTooltipContent} />
|
||||
) : (
|
||||
!areFiltersEqual &&
|
||||
isAuthorizedUser && (
|
||||
<>
|
||||
<Button variant="outline-primary" size="sm" className="flex-shrink-0" onClick={() => setIsModalOpen(true)}>
|
||||
Save as
|
||||
</Button>
|
||||
{isOwner && <>{updateButton}</>}
|
||||
</>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,14 +1,16 @@
|
|||
import React, { FC, useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { Earth, Lock } from "lucide-react";
|
||||
// types
|
||||
import { IProjectView } from "@plane/types";
|
||||
// ui
|
||||
import { FavoriteStar } from "@plane/ui";
|
||||
import { Tooltip, FavoriteStar } from "@plane/ui";
|
||||
// components
|
||||
import { DeleteProjectViewModal, CreateUpdateProjectViewModal, ViewQuickActions } from "@/components/views";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "@/constants/project";
|
||||
import { EViewAccess } from "@/constants/views";
|
||||
// helpers
|
||||
import { calculateTotalFilters } from "@/helpers/filter.helper";
|
||||
// hooks
|
||||
|
|
@ -39,6 +41,8 @@ export const ViewListItemAction: FC<Props> = observer((props) => {
|
|||
|
||||
const totalFilters = calculateTotalFilters(view.filters ?? {});
|
||||
|
||||
const access = view.access;
|
||||
|
||||
// handlers
|
||||
const handleAddToFavorites = () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
|
@ -70,8 +74,14 @@ export const ViewListItemAction: FC<Props> = observer((props) => {
|
|||
{totalFilters} {totalFilters === 1 ? "filter" : "filters"}
|
||||
</p>
|
||||
|
||||
<div className="cursor-default text-custom-text-300">
|
||||
<Tooltip tooltipContent={access === EViewAccess.PUBLIC ? "Public" : "Private"}>
|
||||
{access === EViewAccess.PUBLIC ? <Earth className="h-4 w-4" /> : <Lock className="h-4 w-4" />}
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/* created by */}
|
||||
{createdByDetails && <ButtonAvatars showTooltip={false} userIds={createdByDetails?.id} />}
|
||||
{<ButtonAvatars showTooltip={false} userIds={createdByDetails?.id ?? []} />}
|
||||
|
||||
{isEditingAllowed && (
|
||||
<FavoriteStar
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue