From 359e3e19000885aa847f703d29f796911eb95853 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Tue, 21 May 2024 17:49:40 +0100 Subject: [PATCH] Allow transferring roadmap between teams --- src/components/Navigation/AccountDropdown.tsx | 2 +- src/components/PageProgress.tsx | 2 +- .../ShareOptions/ShareOptionsModal.tsx | 88 ++++++++++--------- .../ShareOptions/ShareOptionsTab.tsx | 34 ++++--- src/components/ShareOptions/ShareSuccess.tsx | 33 ++++--- .../ShareOptions/TransferToTeamList.tsx | 11 ++- 6 files changed, 97 insertions(+), 73 deletions(-) diff --git a/src/components/Navigation/AccountDropdown.tsx b/src/components/Navigation/AccountDropdown.tsx index 56a8b76ef..07119ea99 100644 --- a/src/components/Navigation/AccountDropdown.tsx +++ b/src/components/Navigation/AccountDropdown.tsx @@ -93,7 +93,7 @@ export function AccountDropdown() { ).length; return ( -
+
{isOnboardingModalOpen && onboardingConfig && ( {/* Tailwind based spinner for full page */} -
+
([]); const [teams, setTeams] = useState([]); @@ -71,13 +72,12 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { ); const [selectedTeamId, setSelectedTeamId] = useState(null); - const canTransferRoadmap = visibility === 'team' && !teamId; let isUpdateDisabled = false; // Disable update button if there are no friends to share with if (visibility === 'friends' && sharedFriendIds.length === 0) { isUpdateDisabled = true; // Disable update button if there are no team to transfer - } else if (canTransferRoadmap && !selectedTeamId) { + } else if (isTransferringToTeam && !selectedTeamId) { isUpdateDisabled = true; // Disable update button if there are no members to share with } else if ( @@ -198,6 +198,8 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) {
- {visibility === 'public' && ( -
- -

- Anyone with the link can access. -

-
- )} - {visibility === 'me' && ( -
- -

- Only you will be able to access. -

-
- )} - - {/* For Personal Roadmap */} - {visibility === 'friends' && ( - - )} + {!isTransferringToTeam && ( + <> + {visibility === 'public' && ( +
+ +

+ Anyone with the link can access. +

+
+ )} + {visibility === 'me' && ( +
+ +

+ Only you will be able to access. +

+
+ )} + {/* For Personal Roadmap */} + {visibility === 'friends' && ( + + )} - {/* For Team Roadmap */} - {visibility === 'team' && teamId && ( - + {/* For Team Roadmap */} + {visibility === 'team' && teamId && ( + + )} + )} - {canTransferRoadmap && ( + {isTransferringToTeam && ( <> - {canTransferRoadmap && ( + {isTransferringToTeam && ( )} - {!canTransferRoadmap && ( + {!isTransferringToTeam && ( { diff --git a/src/components/ShareOptions/ShareOptionsTab.tsx b/src/components/ShareOptions/ShareOptionsTab.tsx index 20bacd10f..c5927d441 100644 --- a/src/components/ShareOptions/ShareOptionsTab.tsx +++ b/src/components/ShareOptions/ShareOptionsTab.tsx @@ -8,6 +8,8 @@ import { } from 'lucide-react'; import type { AllowedRoadmapVisibility } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal'; import { cn } from '../../lib/classname'; +import { $teamList } from '../../stores/team.ts'; +import { useStore } from '@nanostores/react'; export const allowedVisibilityLabels: { id: AllowedRoadmapVisibility; @@ -44,15 +46,29 @@ export const allowedVisibilityLabels: { type ShareOptionTabsProps = { visibility: AllowedRoadmapVisibility; setVisibility: (visibility: AllowedRoadmapVisibility) => void; + + isTransferringToTeam: boolean; + setIsTransferringToTeam: (isTransferringToTeam: boolean) => void; + teamId?: string; onChange: (visibility: AllowedRoadmapVisibility) => void; }; export function ShareOptionTabs(props: ShareOptionTabsProps) { - const { visibility, setVisibility, teamId, onChange } = props; + const { + isTransferringToTeam, + setIsTransferringToTeam, + visibility, + setVisibility, + teamId, + onChange, + } = props; - const handleClick = (visibility: AllowedRoadmapVisibility) => { + const teamList = useStore($teamList); + + const handleTabClick = (visibility: AllowedRoadmapVisibility) => { + setIsTransferringToTeam(false); setVisibility(visibility); onChange(visibility); }; @@ -63,11 +79,9 @@ export function ShareOptionTabs(props: ShareOptionTabsProps) { {allowedVisibilityLabels.map((v) => { if (v.id === 'friends' && teamId) { return null; - } else if (v.id === 'team' && !teamId) { - return null; } - const isActive = v.id === visibility; + const isActive = !isTransferringToTeam && v.id === visibility; return (
  • { - handleClick(v.id); + handleTabClick(v.id); }} />
  • ); })} - {!teamId && ( + {(!teamId || teamList.length > 1) && (
    { - handleClick('team'); + setIsTransferringToTeam(true); }} className='border-red-300 text-red-600 hover:border-red-200 hover:bg-red-50 data-[active="true"]:border-red-600 data-[active="true"]:bg-red-600 data-[active="true"]:text-white' /> @@ -115,7 +129,7 @@ function OptionTab(props: OptionTabProps) { className={cn( 'flex items-center justify-center gap-2 rounded-md border px-3 py-2 text-sm text-black hover:border-gray-300 hover:bg-gray-100', 'data-[active="true"]:border-gray-500 data-[active="true"]:bg-gray-200 data-[active="true"]:text-black', - className + className, )} data-active={isActive} disabled={isActive} diff --git a/src/components/ShareOptions/ShareSuccess.tsx b/src/components/ShareOptions/ShareSuccess.tsx index 1785bfbdb..20f9fa684 100644 --- a/src/components/ShareOptions/ShareSuccess.tsx +++ b/src/components/ShareOptions/ShareSuccess.tsx @@ -82,25 +82,24 @@ export function ShareSuccess(props: ShareSuccessProps) {

    )} -
    -

    - You can also embed this roadmap on your website. -

    -
    - { - e.currentTarget.select(); - copyText(embedHtml); - }} - readOnly={true} - className="w-full resize-none rounded-md border bg-gray-50 p-2 text-sm" - value={embedHtml} - /> -
    -
    - {visibility === 'public' && ( <> +
    +

    + You can also embed this roadmap on your website. +

    +
    + { + e.currentTarget.select(); + copyText(embedHtml); + }} + readOnly={true} + className="w-full resize-none rounded-md border bg-gray-50 p-2 text-sm" + value={embedHtml} + /> +
    +
    Or diff --git a/src/components/ShareOptions/TransferToTeamList.tsx b/src/components/ShareOptions/TransferToTeamList.tsx index 8b4877648..e703c2d7c 100644 --- a/src/components/ShareOptions/TransferToTeamList.tsx +++ b/src/components/ShareOptions/TransferToTeamList.tsx @@ -9,6 +9,7 @@ type TransferToTeamListProps = { teams: UserTeamItem[]; setTeams: (teams: UserTeamItem[]) => void; + currentTeamId?: string; selectedTeamId: string | null; setSelectedTeamId: (teamId: string | null) => void; @@ -24,6 +25,7 @@ export function TransferToTeamList(props: TransferToTeamListProps) { selectedTeamId, setSelectedTeamId, isTeamMembersLoading, + currentTeamId, setIsTeamMembersLoading, onTeamChange, } = props; @@ -38,7 +40,7 @@ export function TransferToTeamList(props: TransferToTeamListProps) { } const { response, error } = await httpGet( - `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams` + `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`, ); if (error || !response) { toast.error(error?.message || 'Something went wrong'); @@ -46,7 +48,7 @@ export function TransferToTeamList(props: TransferToTeamListProps) { } setTeams( - response.filter((team) => ['admin', 'manager'].includes(team.role)) + response.filter((team) => ['admin', 'manager'].includes(team.role)), ); } @@ -80,13 +82,16 @@ export function TransferToTeamList(props: TransferToTeamListProps) {
      {teams.map((team) => { const isSelected = team._id === selectedTeamId; + if (team._id === currentTeamId) { + return null; + } return (