@@ -3,8 +3,11 @@ import {
3
3
ArrowUpIcon ,
4
4
CubeIcon ,
5
5
DashboardIcon ,
6
+ GlobeIcon ,
6
7
HamburgerMenuIcon ,
8
+ LockClosedIcon ,
7
9
MagnifyingGlassIcon ,
10
+ PersonIcon ,
8
11
TrashIcon ,
9
12
} from '@radix-ui/react-icons'
10
13
import { Badge , Button , ContextMenu , DropdownMenu , Flex , Text , TextField } from '@radix-ui/themes'
@@ -55,7 +58,7 @@ import { SharingDialogWrapper } from '../components/sharingDialog'
55
58
const SortOptions = [ 'title' , 'dateCreated' , 'dateModified' ] as const
56
59
export type SortCriteria = ( typeof SortOptions ) [ number ]
57
60
58
- const Categories = [ 'allProjects' , 'trash' ] as const
61
+ const Categories = [ 'allProjects' , 'trash' , 'private' , 'public' , 'shared' ] as const
59
62
60
63
function isCategory ( category : unknown ) : category is Category {
61
64
return Categories . includes ( category as Category )
@@ -65,6 +68,9 @@ export type Category = (typeof Categories)[number]
65
68
66
69
const categories : { [ key in Category ] : { name : string ; icon : React . ReactNode } } = {
67
70
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' /> } ,
68
74
trash : { name : 'Trash' , icon : < TrashIcon width = '16' height = '16' /> } ,
69
75
}
70
76
@@ -104,6 +110,16 @@ const ProjectsPage = React.memo(() => {
104
110
switch ( selectedCategory ) {
105
111
case 'allProjects' :
106
112
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
+ )
107
123
case 'trash' :
108
124
return data . deletedProjects
109
125
default :
@@ -454,6 +470,9 @@ const CategoryActions = React.memo(({ projects }: { projects: ProjectWithoutCont
454
470
455
471
switch ( selectedCategory ) {
456
472
case 'allProjects' :
473
+ case 'public' :
474
+ case 'private' :
475
+ case 'shared' :
457
476
return null
458
477
case 'trash' :
459
478
return < CategoryTrashActions projects = { projects } />
@@ -557,6 +576,12 @@ const NoProjectsMessage = React.memo(() => {
557
576
return 'Projects you create or open will show up here.'
558
577
case 'trash' :
559
578
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.'
560
585
default :
561
586
assertNever ( cat )
562
587
}
@@ -643,39 +668,42 @@ const ProjectCard = React.memo(
643
668
onMouseDown = { onSelect }
644
669
onDoubleClick = { openProject }
645
670
>
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
+ ) }
679
707
{ when (
680
708
activeOperations . length > 0 ,
681
709
< div
@@ -841,39 +869,42 @@ const ProjectRow = React.memo(
841
869
gap : 6 ,
842
870
} }
843
871
>
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
+ ) }
877
908
</ div >
878
909
< ProjectBadge
879
910
accessLevel = {
@@ -885,6 +916,7 @@ const ProjectRow = React.memo(
885
916
</ div >
886
917
</ ContextMenu . Trigger >
887
918
< ProjectActionsMenu project = { project } accessRequests = { accessRequests } />
919
+ < SharingDialogWrapper project = { project } accessRequests = { accessRequests } />
888
920
</ ContextMenu . Root >
889
921
)
890
922
} ,
0 commit comments