Skip to content

Commit 3da875a

Browse files
committed
hide hidden projects
1 parent facc403 commit 3da875a

File tree

10 files changed

+111
-105
lines changed

10 files changed

+111
-105
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import type { LeanWebConfig } from './types'
1+
import { LeanWebConfig } from "./src/api/config-types";
22

33
export const lean4webConfig: LeanWebConfig = {
44
serverCountry: null,
55
contactDetails: null,
66
impressum: null,
7-
}
7+
};

client/src/App.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { Menu } from './navigation/Navigation'
1717
import { mobileAtom, settingsAtom } from './settings/settings-atoms'
1818
import { lightThemes } from './settings/settings-types'
1919
import { freshlyImportedCodeAtom } from './store/import-atoms'
20-
import { projectAtom } from './store/project-atoms'
20+
import { currentProjectAtom } from './store/project-atoms'
2121
import { screenWidthAtom } from './store/window-atoms'
2222
import { save } from './utils/SaveToFile'
2323

@@ -35,7 +35,7 @@ function App() {
3535
const [settings] = useAtom(settingsAtom)
3636
const [mobile] = useAtom(mobileAtom)
3737
const [, setScreenWidth] = useAtom(screenWidthAtom)
38-
const [project] = useAtom(projectAtom)
38+
const [project] = useAtom(currentProjectAtom)
3939
const [code, setCode] = useAtom(codeAtom)
4040
const [freshlyImportedCode] = useAtom(freshlyImportedCodeAtom)
4141

@@ -76,7 +76,7 @@ function App() {
7676
(window.location.protocol === 'https:' ? 'wss://' : 'ws://') +
7777
window.location.host +
7878
'/websocket/' +
79-
project
79+
project.folder
8080
console.log(`[Lean4web] Socket url is ${socketUrl}`)
8181
var _options: LeanMonacoOptions = {
8282
websocket: { url: socketUrl },
@@ -108,7 +108,7 @@ function App() {
108108

109109
// Setting up the editor and infoview
110110
useEffect(() => {
111-
if (project === undefined) return
111+
if (!project) return
112112
console.debug('[Lean4web] Restarting editor')
113113
var _leanMonaco = new LeanMonaco()
114114
var leanMonacoEditor = new LeanMonacoEditor()
@@ -118,7 +118,7 @@ function App() {
118118
await _leanMonaco.start(options)
119119
await leanMonacoEditor.start(
120120
editorRef.current!,
121-
path.join(project, `${project}.lean`),
121+
path.join(project.folder, `${project.folder}.lean`),
122122
code ?? '',
123123
)
124124

client/src/Popups/Impressum.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { lean4webConfig } from '../config/config'
1+
import { lean4webConfig } from '../../config'
22
import { Popup } from '../navigation/Popup'
33

44
/** The popup with the privacy policy. */

client/src/Popups/PrivacyPolicy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { lean4webConfig } from '../config/config'
1+
import { lean4webConfig } from '../../config'
22
import { Popup } from '../navigation/Popup'
33

44
/** The popup with the privacy policy. */

client/src/api/config-types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { JSX } from 'react'
2+
3+
export type LeanWebConfig = {
4+
/** Where the server is located. Use `null` to not display this information. */
5+
serverCountry: string | null
6+
/** Contact details of the server maintainer. Used in Privacy Policy and Impressum.
7+
* Use `null` to not display this information.
8+
* Note: This will be embedded inside a `<p>` tag! (example: `<>Hans Muster<br />hans@nowhere.com</>`)
9+
*/
10+
contactDetails: JSX.Element | null
11+
/** Additional legal information shown in impressum alongside the contact details.
12+
* Use `null` to not display this information.
13+
* (example: `<><p>vat number: 000</p><>`)
14+
*/
15+
impressum: JSX.Element | null
16+
}

client/src/api/project-types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/** An example can be any Lean file which belongs to the project.
2+
* The editor just reads the file content, but it makes sense for maintainability
3+
* that you ensure the Lean project actually builds the file. */
4+
export type LeanWebExample = {
5+
/** File to load; relative path in `lean4web/Projects/<project_folder>/` */
6+
file: string
7+
/** Display name used in the `Examples` menu */
8+
name: string
9+
}
10+
11+
/** Configuration from a project's `leanweb-config.json` file. */
12+
export type LeanWebProjectConfig = {
13+
/** Display name; shown in selection menu */
14+
name: string
15+
/** Hidden projects do not appear in the dropdown and are only accessible through the direct link */
16+
hidden: boolean
17+
/** The default project. There must be exactly one project marked as default */
18+
default: boolean
19+
/** A list of examples which are added under the menu `Examples` */
20+
examples: LeanWebExample[]
21+
}
22+
23+
/* A project */
24+
export type LeanWebProject = {
25+
/* The folder name of the project. */
26+
folder: string
27+
config: LeanWebProjectConfig
28+
}

client/src/config/types.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

client/src/navigation/Navigation.tsx

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
1818
import { useAtom } from 'jotai'
1919
import { ChangeEvent, Dispatch, SetStateAction, useState } from 'react'
2020

21+
import { lean4webConfig } from '../../config'
2122
import ZulipIcon from '../assets/zulip.svg'
22-
import { lean4webConfig } from '../config/config'
2323
import { codeAtom } from '../editor/code-atoms'
2424
import ImpressumPopup from '../Popups/Impressum'
2525
import LoadUrlPopup from '../Popups/LoadUrl'
@@ -29,7 +29,7 @@ import ToolsPopup from '../Popups/Tools'
2929
import { mobileAtom } from '../settings/settings-atoms'
3030
import { SettingsPopup } from '../settings/SettingsPopup'
3131
import { setImportUrlAndProjectAtom } from '../store/import-atoms'
32-
import { projectAtom, projectsAtom } from '../store/project-atoms'
32+
import { currentProjectAtom, projectsAtom, visibleProjectsAtom } from '../store/project-atoms'
3333
import { save } from '../utils/SaveToFile'
3434
import { Dropdown } from './Dropdown'
3535
import { NavButton } from './NavButton'
@@ -155,8 +155,8 @@ export function Menu({
155155
codeMirror: boolean
156156
setCodeMirror: Dispatch<SetStateAction<boolean>>
157157
}) {
158-
const [{ data: projects }] = useAtom(projectsAtom)
159-
const [project, setProject] = useAtom(projectAtom)
158+
const [visibleProjects] = useAtom(visibleProjectsAtom)
159+
const [project, setProject] = useAtom(currentProjectAtom)
160160
const [code] = useAtom(codeAtom)
161161

162162
// state for handling the dropdown menus
@@ -178,20 +178,23 @@ export function Menu({
178178

179179
return (
180180
<div className="menu">
181-
<select
182-
name="leanVersion"
183-
value={project}
184-
onChange={(ev) => {
185-
setProject(ev.target.value)
186-
console.log(`set Lean project to: ${ev.target.value}`)
187-
}}
188-
>
189-
{projects.map((proj) => (
190-
<option key={proj.folder} value={proj.folder}>
191-
{proj.config.name}
192-
</option>
193-
))}
194-
</select>
181+
{project && (
182+
<select
183+
name="leanVersion"
184+
value={project.folder}
185+
onChange={(ev) => {
186+
setProject(ev.target.value)
187+
console.log(`set Lean project to: ${ev.target.value}`)
188+
}}
189+
>
190+
{project.folder}
191+
{visibleProjects.map((proj) => (
192+
<option key={proj.folder} value={proj.folder}>
193+
{proj.config.name}
194+
</option>
195+
))}
196+
</select>
197+
)}
195198
{mobile && (
196199
<NavButton
197200
icon={faCode}
@@ -288,7 +291,13 @@ export function Menu({
288291
{hasImpressum && (
289292
<ImpressumPopup open={impressumOpen} handleClose={() => setImpressumOpen(false)} />
290293
)}
291-
<ToolsPopup open={toolsOpen} handleClose={() => setToolsOpen(false)} project={project} />
294+
{project && (
295+
<ToolsPopup
296+
open={toolsOpen}
297+
handleClose={() => setToolsOpen(false)}
298+
project={project.folder}
299+
/>
300+
)}
292301
<SettingsPopup
293302
open={settingsOpen}
294303
handleClose={() => setSettingsOpen(false)}

client/src/store/project-atoms.ts

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,10 @@
11
import { atom } from 'jotai'
22
import { atomWithQuery } from 'jotai-tanstack-query'
33

4+
import { LeanWebProject } from '../api/project-types'
45
import { 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+
})

client/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@
2424
/* Performance */
2525
"skipLibCheck": true
2626
},
27-
"include": ["src"],
27+
"include": ["src", "config.ts"],
2828
"exclude": ["node_modules"]
2929
}

0 commit comments

Comments
 (0)