11import { atom } from 'jotai'
22import { atomWithQuery } from 'jotai-tanstack-query'
33
4+ import { LeanWebProject } from '../api/project-types'
45import { urlArgsAtom , urlArgsStableAtom } from './url-atoms'
56
6- /* An example a project provides */
7- export interface Example {
8- file : string
9- name : string
10- }
11-
12- /* A project's user configuration */
13- export type ProjectConfig = {
14- name : string
15- hidden : boolean
16- default : boolean
17- examples : Example [ ]
18- }
19-
20- /* A project */
21- export type Project = {
22- folder : string
23- config : ProjectConfig
24- }
25-
26- const projectsQueryAtom = atomWithQuery < Project [ ] > ( ( get ) => ( {
7+ const projectsQueryAtom = atomWithQuery < LeanWebProject [ ] > ( ( get ) => ( {
278 queryKey : [ 'projects' ] ,
289 queryFn : async ( ) => {
2910 const res = await fetch ( `/api/projects` )
@@ -32,7 +13,7 @@ const projectsQueryAtom = atomWithQuery<Project[]>((get) => ({
3213} ) )
3314
3415/** Sort alphabetically while the `default` project always comes first */
35- function sortProjects ( p : Project , q : Project ) : number {
16+ function sortProjects ( p : LeanWebProject , q : LeanWebProject ) : number {
3617 if ( p . config . default ) return - 1
3718 if ( q . config . default ) return 1
3819 return p . config . name . localeCompare ( q . config . name )
@@ -44,32 +25,50 @@ export const projectsAtom = atom((get) => {
4425 return { ...query , data : query . data ?. sort ( sortProjects ) ?? [ ] }
4526} )
4627
47- export const defaultProjectFolderAtom = atom ( ( get ) => {
28+ export const defaultProjectAtom = atom ( ( get ) => {
4829 const projects = get ( projectsAtom ) . data
49- if ( projects . length === 0 ) return 'MathlibDemo' // TODO: is this correct?
30+ if ( projects . length === 0 ) return null
5031 const defaultProjects = projects . filter ( ( it ) => it . config . default )
5132
5233 if ( defaultProjects . length === 0 ) {
5334 console . warn ( `Expected exactly one default project, but found none.` )
54- return projects [ 0 ] . folder
35+ return projects [ 0 ]
5536 }
5637 if ( defaultProjects . length > 1 ) {
5738 console . error ( `Expected exactly one default project, but found ${ defaultProjects . length } ` )
5839 }
59- return defaultProjects [ 0 ] . folder
40+ return defaultProjects [ 0 ]
6041} )
6142
6243/** The currently selected project */
63- export const projectAtom = atom (
44+ export const currentProjectAtom = atom (
6445 ( get ) => {
65- const urlArgs = get ( urlArgsStableAtom )
66- return urlArgs . project ?? get ( defaultProjectFolderAtom )
46+ const urlArgProject = get ( urlArgsStableAtom ) . project
47+ const defaultProject = get ( defaultProjectAtom )
48+ const allProjects = get ( projectsAtom ) . data
49+ if ( ! urlArgProject ) return defaultProject
50+ if ( ! urlArgProject ) return defaultProject
51+ return (
52+ allProjects . find ( ( it ) => it . folder . toLowerCase ( ) == urlArgProject . toLowerCase ( ) ) ??
53+ defaultProject
54+ )
6755 } ,
6856 ( get , set , project : string ) => {
6957 const urlArgs = get ( urlArgsStableAtom )
58+ const defaultProject = get ( defaultProjectAtom )
7059 set ( urlArgsAtom , {
7160 ...urlArgs ,
72- project : project !== get ( defaultProjectFolderAtom ) ? project : undefined ,
61+ project :
62+ defaultProject == undefined || project !== defaultProject . folder ? project : undefined ,
7363 } )
7464 } ,
7565)
66+
67+ /** Visible projects */
68+ export const visibleProjectsAtom = atom ( ( get ) => {
69+ const current = get ( currentProjectAtom )
70+ const visible = get ( projectsAtom ) . data . filter (
71+ ( it ) => ! it . config . hidden || ( current && it . folder == current . folder ) ,
72+ )
73+ return visible
74+ } )
0 commit comments