Skip to content

Commit 3490964

Browse files
ruggiRheeseyb
andauthored
Projects page: categories for public/private/shared (#5082)
* categories for public/private/shared * fix switch * no separator after all * share -> sharing * Update utopia-remix/app/routes/projects.tsx Co-authored-by: RheeseyB <1044774+Rheeseyb@users.noreply.github.com> --------- Co-authored-by: RheeseyB <1044774+Rheeseyb@users.noreply.github.com>
1 parent 793d1d2 commit 3490964

File tree

3 files changed

+106
-68
lines changed

3 files changed

+106
-68
lines changed

utopia-remix/app/components/projectActionContextMenu.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ export const ProjectActionsMenu = React.memo(
9393
const menuEntries = React.useMemo((): ContextMenuEntry[] => {
9494
switch (selectedCategory) {
9595
case 'allProjects':
96+
case 'public':
97+
case 'shared':
98+
case 'private':
9699
return [
97100
{
98101
text: 'Open',
@@ -189,7 +192,7 @@ export const ProjectActionsMenu = React.memo(
189192
onSelect={onOpenShareDialog}
190193
>
191194
<Flex justify={'between'} align={'center'} width={'100%'}>
192-
<Text>Share</Text>
195+
<Text>Sharing…</Text>
193196
{when(
194197
pendingAccessRequests.length > 0,
195198
<DotFilledIcon color='red' height={22} width={22} />,

utopia-remix/app/routes/projects.tsx

+99-67
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ import {
33
ArrowUpIcon,
44
CubeIcon,
55
DashboardIcon,
6+
GlobeIcon,
67
HamburgerMenuIcon,
8+
LockClosedIcon,
79
MagnifyingGlassIcon,
10+
PersonIcon,
811
TrashIcon,
912
} from '@radix-ui/react-icons'
1013
import { Badge, Button, ContextMenu, DropdownMenu, Flex, Text, TextField } from '@radix-ui/themes'
@@ -55,7 +58,7 @@ import { SharingDialogWrapper } from '../components/sharingDialog'
5558
const SortOptions = ['title', 'dateCreated', 'dateModified'] as const
5659
export type SortCriteria = (typeof SortOptions)[number]
5760

58-
const Categories = ['allProjects', 'trash'] as const
61+
const Categories = ['allProjects', 'trash', 'private', 'public', 'shared'] as const
5962

6063
function isCategory(category: unknown): category is Category {
6164
return Categories.includes(category as Category)
@@ -65,6 +68,9 @@ export type Category = (typeof Categories)[number]
6568

6669
const categories: { [key in Category]: { name: string; icon: React.ReactNode } } = {
6770
allProjects: { name: 'All My Projects', icon: <CubeIcon width='16' height='16' /> },
71+
private: { name: 'Private', icon: <LockClosedIcon width='16' height='16' /> },
72+
shared: { name: 'Sharing', icon: <PersonIcon width='16' height='16' /> },
73+
public: { name: 'Public', icon: <GlobeIcon width='16' height='16' /> },
6874
trash: { name: 'Trash', icon: <TrashIcon width='16' height='16' /> },
6975
}
7076

@@ -104,6 +110,16 @@ const ProjectsPage = React.memo(() => {
104110
switch (selectedCategory) {
105111
case 'allProjects':
106112
return data.projects
113+
case 'public':
114+
return data.projects.filter((p) => p.ProjectAccess?.access_level === AccessLevel.PUBLIC)
115+
case 'private':
116+
return data.projects.filter(
117+
(p) => (p.ProjectAccess?.access_level ?? AccessLevel.PRIVATE) === AccessLevel.PRIVATE,
118+
)
119+
case 'shared':
120+
return data.projects.filter(
121+
(p) => p.ProjectAccess?.access_level === AccessLevel.COLLABORATIVE,
122+
)
107123
case 'trash':
108124
return data.deletedProjects
109125
default:
@@ -454,6 +470,9 @@ const CategoryActions = React.memo(({ projects }: { projects: ProjectWithoutCont
454470

455471
switch (selectedCategory) {
456472
case 'allProjects':
473+
case 'public':
474+
case 'private':
475+
case 'shared':
457476
return null
458477
case 'trash':
459478
return <CategoryTrashActions projects={projects} />
@@ -557,6 +576,12 @@ const NoProjectsMessage = React.memo(() => {
557576
return 'Projects you create or open will show up here.'
558577
case 'trash':
559578
return 'Deleted projects are kept here until you destroy them for good.'
579+
case 'public':
580+
return 'Public projects you own.'
581+
case 'private':
582+
return 'Projects you create that are private to you.'
583+
case 'shared':
584+
return 'Projects that you have shared with other collaborators.'
560585
default:
561586
assertNever(cat)
562587
}
@@ -643,39 +668,42 @@ const ProjectCard = React.memo(
643668
onMouseDown={onSelect}
644669
onDoubleClick={openProject}
645670
>
646-
<div style={{ position: 'absolute', right: 6, bottom: 6, display: 'flex', gap: 2 }}>
647-
{collaborators.map((collaborator) => {
648-
return (
649-
<div
650-
key={`collaborator-${project.id}-${collaborator.id}`}
651-
style={{
652-
borderRadius: '100%',
653-
width: 24,
654-
height: 24,
655-
backgroundImage: `url("${collaborator.avatar}")`,
656-
backgroundSize: 'cover',
657-
display: 'flex',
658-
justifyContent: 'center',
659-
alignItems: 'center',
660-
fontSize: '.9em',
661-
fontWeight: 700,
662-
filter: project.deleted === true ? 'grayscale(1)' : undefined,
663-
}}
664-
title={collaborator.name ?? UnknownPlayerName}
665-
className={sprinkles({
666-
boxShadow: 'shadow',
667-
color: 'white',
668-
backgroundColor: 'primary',
669-
})}
670-
>
671-
{when(
672-
collaborator.avatar === '',
673-
multiplayerInitialsFromName(collaborator.name),
674-
)}
675-
</div>
676-
)
677-
})}
678-
</div>
671+
{when(
672+
project.ProjectAccess?.access_level === AccessLevel.COLLABORATIVE,
673+
<div style={{ position: 'absolute', right: 6, bottom: 6, display: 'flex', gap: 2 }}>
674+
{collaborators.map((collaborator) => {
675+
return (
676+
<div
677+
key={`collaborator-${project.id}-${collaborator.id}`}
678+
style={{
679+
borderRadius: '100%',
680+
width: 24,
681+
height: 24,
682+
backgroundImage: `url("${collaborator.avatar}")`,
683+
backgroundSize: 'cover',
684+
display: 'flex',
685+
justifyContent: 'center',
686+
alignItems: 'center',
687+
fontSize: '.9em',
688+
fontWeight: 700,
689+
filter: project.deleted === true ? 'grayscale(1)' : undefined,
690+
}}
691+
title={collaborator.name ?? UnknownPlayerName}
692+
className={sprinkles({
693+
boxShadow: 'shadow',
694+
color: 'white',
695+
backgroundColor: 'primary',
696+
})}
697+
>
698+
{when(
699+
collaborator.avatar === '',
700+
multiplayerInitialsFromName(collaborator.name),
701+
)}
702+
</div>
703+
)
704+
})}
705+
</div>,
706+
)}
679707
{when(
680708
activeOperations.length > 0,
681709
<div
@@ -841,39 +869,42 @@ const ProjectRow = React.memo(
841869
gap: 6,
842870
}}
843871
>
844-
{collaborators.map((collaborator) => {
845-
return (
846-
<div
847-
key={`collaborator-${project.id}-${collaborator.id}`}
848-
style={{
849-
borderRadius: '100%',
850-
width: 24,
851-
height: 24,
852-
backgroundColor: '#0075F9',
853-
backgroundImage: `url("${collaborator.avatar}")`,
854-
backgroundSize: 'cover',
855-
color: 'white',
856-
display: 'flex',
857-
justifyContent: 'center',
858-
alignItems: 'center',
859-
fontSize: '.9em',
860-
fontWeight: 700,
861-
filter: project.deleted === true ? 'grayscale(1)' : undefined,
862-
}}
863-
title={collaborator.name ?? UnknownPlayerName}
864-
className={sprinkles({
865-
boxShadow: 'shadow',
866-
color: 'white',
867-
backgroundColor: 'primary',
868-
})}
869-
>
870-
{when(
871-
collaborator.avatar === '',
872-
multiplayerInitialsFromName(collaborator.name),
873-
)}
874-
</div>
875-
)
876-
})}
872+
{when(
873+
project.ProjectAccess?.access_level === AccessLevel.COLLABORATIVE,
874+
collaborators.map((collaborator) => {
875+
return (
876+
<div
877+
key={`collaborator-${project.id}-${collaborator.id}`}
878+
style={{
879+
borderRadius: '100%',
880+
width: 24,
881+
height: 24,
882+
backgroundColor: '#0075F9',
883+
backgroundImage: `url("${collaborator.avatar}")`,
884+
backgroundSize: 'cover',
885+
color: 'white',
886+
display: 'flex',
887+
justifyContent: 'center',
888+
alignItems: 'center',
889+
fontSize: '.9em',
890+
fontWeight: 700,
891+
filter: project.deleted === true ? 'grayscale(1)' : undefined,
892+
}}
893+
title={collaborator.name ?? UnknownPlayerName}
894+
className={sprinkles({
895+
boxShadow: 'shadow',
896+
color: 'white',
897+
backgroundColor: 'primary',
898+
})}
899+
>
900+
{when(
901+
collaborator.avatar === '',
902+
multiplayerInitialsFromName(collaborator.name),
903+
)}
904+
</div>
905+
)
906+
}),
907+
)}
877908
</div>
878909
<ProjectBadge
879910
accessLevel={
@@ -885,6 +916,7 @@ const ProjectRow = React.memo(
885916
</div>
886917
</ContextMenu.Trigger>
887918
<ProjectActionsMenu project={project} accessRequests={accessRequests} />
919+
<SharingDialogWrapper project={project} accessRequests={accessRequests} />
888920
</ContextMenu.Root>
889921
)
890922
},

utopia-remix/app/util/use-sort-compare-project.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ export function useProjectIsOnActiveOperation() {
5353
return !activeOperations.some((op) => {
5454
switch (selectedCategory) {
5555
case 'allProjects':
56+
case 'public':
57+
case 'private':
58+
case 'shared':
5659
return op.type === 'delete' && op.projectId === project.proj_id
5760
case 'trash':
5861
return (

0 commit comments

Comments
 (0)