diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13e0326..e11836e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ jobs: webui: name: WebUI Lint & Typecheck runs-on: ubuntu-latest + if: github.event.pull_request.draft == false || github.event_name != 'pull_request' defaults: run: working-directory: webui diff --git a/.github/workflows/osv-scanner.yml b/.github/workflows/osv-scanner.yml index 4aa423f..5b26e1e 100644 --- a/.github/workflows/osv-scanner.yml +++ b/.github/workflows/osv-scanner.yml @@ -18,7 +18,7 @@ permissions: jobs: scan-pr: - if: github.event_name == 'pull_request' || github.event_name == 'merge_group' + if: (github.event_name == 'pull_request' && github.event.pull_request.draft == false) || github.event_name == 'merge_group' uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@v2.3.1 scan-scheduled: diff --git a/core/artefacts.json b/core/artefacts.json new file mode 100644 index 0000000..695670d --- /dev/null +++ b/core/artefacts.json @@ -0,0 +1,39 @@ +{ + "items": [ + { + "id": "backend", + "label": "SmartEM Backend", + "url": "https://github.com/DiamondLightSource/smartem-decisions/pkgs/container/smartem-decisions", + "description": "Docker container image of SmartEM Backend services for use in k8s deploys", + "command": "docker pull ghcr.io/diamondlightsource/smartem-decisions:latest" + }, + { + "id": "agent", + "label": "SmartEM Agent", + "url": "https://github.com/DiamondLightSource/smartem-decisions/actions/workflows/build_win_smartem_agent.yml", + "description": "SmartEM Agent packaged as a Windows 10 executable (download from workflow artifacts)", + "command": "" + }, + { + "id": "frontend", + "label": "SmartEM Frontend", + "url": "#", + "description": "SmartEM Web UI - deployed via backend container, no standalone bundle published", + "command": "" + }, + { + "id": "workspace", + "label": "SmartEM Dev Workspace", + "url": "https://pypi.org/project/smartem-workspace/", + "description": "CLI tool to scaffold and manage a local development environment", + "command": "uvx smartem-workspace --help" + }, + { + "id": "fsrecorder", + "label": "FSRecorder Util", + "url": "https://github.com/DiamondLightSource/smartem-devtools/actions/workflows/build_win_fsrecorder.yml", + "description": "FSRecorder Utility packaged as a Windows 10 executable (download from workflow artifacts)", + "command": "" + } + ] +} diff --git a/core/claude-code-config.ts b/core/claude-code-config.ts deleted file mode 100644 index e274d10..0000000 --- a/core/claude-code-config.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Claude Code integration configuration for SmartEM workspace. - * - * Source of truth: claude-code-config.json - * This file re-exports the JSON data with TypeScript types for type safety. - */ - -import claudeCodeConfig from './claude-code-config.json' - -export interface SkillDefinition { - name: string - path: string -} - -export interface DefaultPermissions { - allow: string[] -} - -export interface ClaudeConfig { - skills: SkillDefinition[] - defaultPermissions: DefaultPermissions -} - -export interface SerenaConfig { - languages: string[] - encoding: string - ignoreAllFilesInGitignore: boolean - projectName: string -} - -export interface McpServerConfig { - command: string - args: string[] -} - -export interface McpConfig { - serena: McpServerConfig -} - -export interface ClaudeCodeConfigFile { - version: string - description: string - claudeConfig: ClaudeConfig - serenaConfig: SerenaConfig - mcpConfig: McpConfig -} - -export const claudeCodeConfigData: ClaudeCodeConfigFile = claudeCodeConfig - -export default claudeCodeConfigData diff --git a/core/dev-requirements.ts b/core/dev-requirements.ts deleted file mode 100644 index 67c61d5..0000000 --- a/core/dev-requirements.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Developer requirements for SmartEM workspace local environment setup. - * - * Source of truth: dev-requirements.json - * This file re-exports the JSON data with TypeScript types for type safety. - */ - -import devRequirementsConfig from './dev-requirements.json' - -export interface ToolRequirement { - name: string - command: string - versionArgs: string[] - required: boolean - minVersion?: string - alternatives?: string[] - description: string -} - -export interface NetworkCheck { - checkUrl: string - timeout: number - required: boolean - description: string -} - -export interface DevRequirementsConfig { - version: string - description: string - tools: ToolRequirement[] - network: NetworkCheck -} - -export const devRequirements: DevRequirementsConfig = devRequirementsConfig - -export default devRequirements diff --git a/core/github-labels-config.ts b/core/github-labels-config.ts deleted file mode 100644 index 0cf0e13..0000000 --- a/core/github-labels-config.ts +++ /dev/null @@ -1,92 +0,0 @@ -/** - * GitHub labels configuration for SmartEM repositories. - * Used for issue/PR categorisation and project management. - * - * This file defines: - * - Label definitions (types of work, system components) - * - Per-repo label assignments - * - * Synced using: npx tsx tools/github/sync-labels.ts --sync - */ - -export interface GitHubLabel { - name: string - description: string - color: string // 6-char hex without # -} - -export interface RepoLabelConfig { - repo: string - labels: 'all' | 'types-only' -} - -export interface GitHubLabelsConfig { - owner: string - typesOfWork: GitHubLabel[] - systemComponents: GitHubLabel[] - repos: RepoLabelConfig[] -} - -/** - * Types of work labels - categorise the nature of the work being done. - * Colors: Distinct hues avoiding blue/pink families (reserved for components). - */ -const typesOfWork: GitHubLabel[] = [ - { name: 'documentation', description: 'Improvements or additions to project documentation', color: '0d6d6e' }, - { name: 'testing', description: 'Writing, updating, or fixing automated tests', color: '2da44e' }, - { name: 'bugfixing', description: 'Fixing defects or unexpected behavior in existing code', color: 'cf222e' }, - { name: 'development', description: 'New features or functionality implementation', color: '8250df' }, - { name: 'refactoring', description: 'Code restructuring without changing external behavior', color: 'bc4c00' }, - { name: 'research', description: 'Investigation, spikes, or proof-of-concept work', color: '0598bd' }, - { name: 'devops', description: 'CI/CD, deployment, infrastructure, or tooling work', color: '57606a' }, - { name: 'security', description: 'Security fixes, audits, or vulnerability remediation', color: 'a40e26' }, - { name: 'admin', description: 'Project maintenance, dependency updates, or housekeeping', color: '7c4a03' }, - { name: 'enhancement', description: 'Minor improvements to existing functionality', color: '1b7c83' }, -] - -/** - * System component labels - identify which part of the system is affected. - * Colors: Blue family for backend, pink family for devtools, unique colors for standalone. - */ -const systemComponents: GitHubLabel[] = [ - // smartem-backend family (ocean blue scale: #0a3069 -> #0550ae -> #218bff) - { name: 'smartem-backend', description: 'Core backend services, messaging, and persistence layer', color: '0a3069' }, - { name: 'smartem-backend:db', description: 'Database schema, migrations, and data layer changes', color: '0550ae' }, - { name: 'smartem-backend:api', description: 'REST API endpoints and HTTP interface changes', color: '218bff' }, - - // smartem-agent (gold - standalone) - { name: 'smartem-agent', description: 'EPU workstation agent for microscope integration', color: '9a6700' }, - - // smartem-frontend (green - standalone) - { name: 'smartem-frontend', description: 'User-facing web UI for acquisition sessions and ML decisions', color: '1a7f37' }, - - // smartem-aria-connector (purple - standalone) - { name: 'smartem-aria-connector', description: 'ARIA deposition integration via FandanGO plugin', color: '6639ba' }, - - // smartem-devtools family (warm pink scale: #99154b -> #bf3989 -> #db61a2 -> #f09bc8) - { name: 'smartem-devtools', description: 'Developer tooling, documentation, and workspace configuration', color: '99154b' }, - { name: 'smartem-devtools:webui', description: 'Developer dashboard web interface', color: 'bf3989' }, - { name: 'smartem-devtools:claude', description: 'Claude Code configuration, skills, and prompts', color: 'db61a2' }, - { name: 'smartem-devtools:e2e-test', description: 'End-to-end testing infrastructure and scenarios', color: 'f09bc8' }, -] - -/** - * Per-repo label configuration. - * - 'all': Types of work + system components - * - 'types-only': Only types of work labels - */ -const repos: RepoLabelConfig[] = [ - { repo: 'smartem-devtools', labels: 'all' }, - { repo: 'smartem-decisions', labels: 'types-only' }, - { repo: 'smartem-frontend', labels: 'types-only' }, - { repo: 'fandanGO-cryoem-dls', labels: 'types-only' }, -] - -export const githubLabelsConfig: GitHubLabelsConfig = { - owner: 'DiamondLightSource', - typesOfWork, - systemComponents, - repos, -} - -export default githubLabelsConfig diff --git a/core/github-labels.json b/core/github-labels.json new file mode 100644 index 0000000..f12de76 --- /dev/null +++ b/core/github-labels.json @@ -0,0 +1,33 @@ +{ + "owner": "DiamondLightSource", + "typesOfWork": [ + { "name": "documentation", "description": "Improvements or additions to project documentation", "color": "0d6d6e" }, + { "name": "testing", "description": "Writing, updating, or fixing automated tests", "color": "2da44e" }, + { "name": "bugfixing", "description": "Fixing defects or unexpected behavior in existing code", "color": "cf222e" }, + { "name": "development", "description": "New features or functionality implementation", "color": "8250df" }, + { "name": "refactoring", "description": "Code restructuring without changing external behavior", "color": "bc4c00" }, + { "name": "research", "description": "Investigation, spikes, or proof-of-concept work", "color": "0598bd" }, + { "name": "devops", "description": "CI/CD, deployment, infrastructure, or tooling work", "color": "57606a" }, + { "name": "security", "description": "Security fixes, audits, or vulnerability remediation", "color": "a40e26" }, + { "name": "admin", "description": "Project maintenance, dependency updates, or housekeeping", "color": "7c4a03" }, + { "name": "enhancement", "description": "Minor improvements to existing functionality", "color": "1b7c83" } + ], + "systemComponents": [ + { "name": "smartem-backend", "description": "Core backend services, messaging, and persistence layer", "color": "0a3069" }, + { "name": "smartem-backend:db", "description": "Database schema, migrations, and data layer changes", "color": "0550ae" }, + { "name": "smartem-backend:api", "description": "REST API endpoints and HTTP interface changes", "color": "218bff" }, + { "name": "smartem-agent", "description": "EPU workstation agent for microscope integration", "color": "9a6700" }, + { "name": "smartem-frontend", "description": "User-facing web UI for acquisition sessions and ML decisions", "color": "1a7f37" }, + { "name": "smartem-aria-connector", "description": "ARIA deposition integration via FandanGO plugin", "color": "6639ba" }, + { "name": "smartem-devtools", "description": "Developer tooling, documentation, and workspace configuration", "color": "99154b" }, + { "name": "smartem-devtools:webui", "description": "Developer dashboard web interface", "color": "bf3989" }, + { "name": "smartem-devtools:claude", "description": "Claude Code configuration, skills, and prompts", "color": "db61a2" }, + { "name": "smartem-devtools:e2e-test", "description": "End-to-end testing infrastructure and scenarios", "color": "f09bc8" } + ], + "repos": [ + { "repo": "smartem-devtools", "labels": "all" }, + { "repo": "smartem-decisions", "labels": "types-only" }, + { "repo": "smartem-frontend", "labels": "types-only" }, + { "repo": "fandanGO-cryoem-dls", "labels": "types-only" } + ] +} diff --git a/core/index.ts b/core/index.ts new file mode 100644 index 0000000..aa6b2b0 --- /dev/null +++ b/core/index.ts @@ -0,0 +1,195 @@ +/** + * Core configuration module for SmartEM devtools. + * + * This file provides TypeScript types and typed re-exports for all JSON config files. + * JSON files are the source of truth for data; this file is the source of truth for types. + * + * Usage: + * import { repos, githubLabels, webUiConfig } from '../core' + * + * @see docs/decision-records/decisions/0013-json-config-with-typescript-types.md + */ + +// ============================================================================= +// JSON Imports +// ============================================================================= + +import reposJson from './repos.json' +import artefactsJson from './artefacts.json' +import githubLabelsJson from './github-labels.json' +import webUiConfigJson from './webui-config.json' +import microscopeListJson from './microscope-list.json' + +// ============================================================================= +// Repository Types (repos.json) +// ============================================================================= + +export interface RepoUrls { + https: string + ssh: string +} + +export interface Repository { + name: string + description: string + urls: RepoUrls + tags?: string[] + ownership?: 'full' | 'reference-only' + required?: boolean +} + +export interface Organization { + name: string + displayName: string + url: string + provider: 'github' | 'gitlab' + repos: Repository[] +} + +export interface Preset { + description: string + repos: string[] +} + +export interface ExternalLinks { + docs: string + projectBoard: string +} + +export interface ReposConfig { + version: string + links: ExternalLinks + presets: Record + organizations: Organization[] +} + +// ============================================================================= +// Artefacts Types (artefacts.json) +// ============================================================================= + +export interface ArtefactItem { + id: string + label: string + url: string + description?: string + command?: string +} + +export interface ArtefactsConfig { + items: ArtefactItem[] +} + +// ============================================================================= +// GitHub Labels Types (github-labels.json) +// ============================================================================= + +/** GitHub label definition for issue/PR categorisation */ +export interface GitHubLabel { + name: string + description: string + /** 6-character hex color without # prefix */ + color: string +} + +export interface RepoLabelConfig { + repo: string + labels: 'all' | 'types-only' +} + +export interface GitHubLabelsConfig { + owner: string + /** Labels categorising the nature of work (documentation, testing, bugfixing, etc.) */ + typesOfWork: GitHubLabel[] + /** Labels identifying which system component is affected */ + systemComponents: GitHubLabel[] + /** Per-repo label assignment configuration */ + repos: RepoLabelConfig[] +} + +// ============================================================================= +// WebUI Config Types (webui-config.json) +// ============================================================================= + +export interface FeatureFlags { + /** Enable dynamic repo stats fetching in development mode */ + repoStatsInDev: boolean + /** Enable dynamic repo stats fetching in production mode */ + repoStatsInProd: boolean + /** Line style for dashboard connection overlay */ + connectionLineStyle: 'straight' | 'bezier' | 'orthogonal' +} + +export interface HeaderButtonConfig { + text?: string + tooltip: string +} + +export interface HeaderConfig { + homeButton: HeaderButtonConfig + docsButton: HeaderButtonConfig + boardButton: HeaderButtonConfig + artefactsButton: HeaderButtonConfig + menuButton: HeaderButtonConfig + omniboxPlaceholder: string + repoSelectorLabel: string +} + +export interface WebUiConfig { + appTitle: string + header: HeaderConfig +} + +export interface WebUiConfigFile { + appTitle: string + featureFlags: FeatureFlags + header: HeaderConfig +} + +// ============================================================================= +// Microscope Types (microscope-list.json) +// ============================================================================= + +/** CryoEM instrument definition for DLS eBIC facility */ +export interface CryoEMInstrument { + name: string + alias: string +} + +// ============================================================================= +// Typed Config Exports +// ============================================================================= + +export const repos: ReposConfig = reposJson as ReposConfig +export const artefacts: ArtefactsConfig = artefactsJson as ArtefactsConfig +export const githubLabels: GitHubLabelsConfig = githubLabelsJson as GitHubLabelsConfig +export const webUiConfigFile: WebUiConfigFile = webUiConfigJson as WebUiConfigFile +export const microscopes: CryoEMInstrument[] = microscopeListJson as CryoEMInstrument[] + +// Derived exports for webui compatibility +export const webUiConfig: WebUiConfig = { + appTitle: webUiConfigFile.appTitle, + header: webUiConfigFile.header, +} +export const featureFlags: FeatureFlags = webUiConfigFile.featureFlags + +// ============================================================================= +// Aggregated Export (for webui compatibility) +// ============================================================================= + +export interface CoreConfig { + repos: ReposConfig + artefacts: ArtefactsConfig + githubLabels: GitHubLabelsConfig + webUiConfig: WebUiConfig + microscopes: CryoEMInstrument[] +} + +export const coreConfig: CoreConfig = { + repos, + artefacts, + githubLabels, + webUiConfig, + microscopes, +} + +export default coreConfig diff --git a/core/microscope-list.json b/core/microscope-list.json new file mode 100644 index 0000000..6285a62 --- /dev/null +++ b/core/microscope-list.json @@ -0,0 +1,13 @@ +[ + { "name": "Krios 1", "alias": "m02" }, + { "name": "Krios 2", "alias": "m03" }, + { "name": "Krios 3", "alias": "m06" }, + { "name": "Krios 4", "alias": "m07" }, + { "name": "Krios 5", "alias": "m08" }, + { "name": "Talos", "alias": "m04" }, + { "name": "Scios", "alias": "m05" }, + { "name": "Glacios 1", "alias": "m10" }, + { "name": "Glacios 2", "alias": "m12" }, + { "name": "Aquilos", "alias": "m11" }, + { "name": "Leica cryoCLEM", "alias": "m14" } +] diff --git a/core/microscope-list.ts b/core/microscope-list.ts deleted file mode 100644 index 6a57252..0000000 --- a/core/microscope-list.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * CryoEM instrument definitions for DLS eBIC facility. - */ - -export interface CryoEMInstrument { - name: string - alias: string -} - -export const microscopeList: CryoEMInstrument[] = [ - { name: 'Krios 1', alias: 'm02' }, - { name: 'Krios 2', alias: 'm03' }, - { name: 'Krios 3', alias: 'm06' }, - { name: 'Krios 4', alias: 'm07' }, - { name: 'Krios 5', alias: 'm08' }, - { name: 'Talos', alias: 'm04' }, - { name: 'Scios', alias: 'm05' }, - { name: 'Glacios 1', alias: 'm10' }, - { name: 'Glacios 2', alias: 'm12' }, - { name: 'Aquilos', alias: 'm11' }, - { name: 'Leica cryoCLEM', alias: 'm14' }, -] - -export default microscopeList diff --git a/core/repos-and-refs.ts b/core/repos-and-refs.ts deleted file mode 100644 index bfe2736..0000000 --- a/core/repos-and-refs.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Repository definitions and external references for SmartEM ecosystem. - * - * Source of truth: repos.json - * This file re-exports the JSON data with TypeScript types for type safety. - */ - -import reposConfig from './repos.json' - -// Re-export types for consumers -export interface RepoUrls { - https: string - ssh: string -} - -export interface Repository { - name: string - description: string - urls: RepoUrls - tags?: string[] - ownership?: 'full' | 'reference-only' - required?: boolean -} - -export interface OrgRepos { - org: string - orgUrl: string - repos: Repository[] -} - -export interface ExternalLinks { - docs: string - projectBoard: string -} - -export interface ReposAndRefsConfig { - links: ExternalLinks - repositories: OrgRepos[] -} - -// Transform JSON structure to match existing interface for backward compatibility -const diamondLightSourceOrg = reposConfig.organizations.find( - (org) => org.name === 'DiamondLightSource', -) -const fragmentScreenOrg = reposConfig.organizations.find((org) => org.name === 'FragmentScreen') -const ariaPHPOrg = reposConfig.organizations.find((org) => org.name === 'aria-php') - -export const reposAndRefsConfig: ReposAndRefsConfig = { - links: { - docs: reposConfig.links.docs, - projectBoard: reposConfig.links.projectBoard, - }, - repositories: [ - { - org: 'DiamondLightSource', - orgUrl: diamondLightSourceOrg?.url ?? 'https://github.com/DiamondLightSource', - repos: (diamondLightSourceOrg?.repos ?? []).map((repo) => ({ - name: repo.name, - description: repo.description, - urls: repo.urls, - tags: repo.tags, - ownership: repo.ownership, - required: repo.required, - })), - }, - { - org: 'FragmentScreen', - orgUrl: fragmentScreenOrg?.url ?? 'https://github.com/FragmentScreen', - repos: (fragmentScreenOrg?.repos ?? []).map((repo) => ({ - name: repo.name, - description: repo.description, - urls: repo.urls, - tags: repo.tags, - ownership: repo.ownership, - })), - }, - { - org: 'aria-php', - orgUrl: ariaPHPOrg?.url ?? 'https://gitlab.com/aria-php', - repos: (ariaPHPOrg?.repos ?? []).map((repo) => ({ - name: repo.name, - description: repo.description, - urls: repo.urls, - tags: repo.tags, - ownership: repo.ownership, - })), - }, - ], -} - -// Export the full config for workspace setup tools -export { reposConfig } - -export default reposAndRefsConfig diff --git a/core/webui-config.json b/core/webui-config.json new file mode 100644 index 0000000..0c1ab4d --- /dev/null +++ b/core/webui-config.json @@ -0,0 +1,17 @@ +{ + "appTitle": "SmartEM Dev Dashboard", + "featureFlags": { + "repoStatsInDev": true, + "repoStatsInProd": true, + "connectionLineStyle": "bezier" + }, + "header": { + "homeButton": { "tooltip": "Navigate to dashboard home" }, + "docsButton": { "text": "docs", "tooltip": "Open project documentation" }, + "boardButton": { "text": "board", "tooltip": "Open GitHub project board" }, + "artefactsButton": { "text": "artefacts", "tooltip": "Download artefacts and releases" }, + "menuButton": { "tooltip": "Open settings menu" }, + "omniboxPlaceholder": "search..", + "repoSelectorLabel": "repos / codebases" + } +} diff --git a/core/webui-config.ts b/core/webui-config.ts deleted file mode 100644 index 7805eb9..0000000 --- a/core/webui-config.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Web UI configuration for SmartEM frontend. - * - * This file is intentionally minimal. Configuration is split across: - * - github-labels-config.ts - GitHub labels and per-repo configuration - * - repos-and-refs.ts - Repository definitions and external links - * - microscope-list.ts - CryoEM instrument definitions - * - * The prebuild script in webui/ aggregates these into webui-app-contents.ts - */ - -// ============================================================================= -// Feature Flags -// ============================================================================= - -export interface FeatureFlags { - /** Enable dynamic repo stats fetching in development mode */ - repoStatsInDev: boolean - /** Enable dynamic repo stats fetching in production mode */ - repoStatsInProd: boolean - /** Line style for dashboard connection overlay: 'straight' | 'bezier' | 'orthogonal' */ - connectionLineStyle: 'straight' | 'bezier' | 'orthogonal' -} - -export const featureFlags: FeatureFlags = { - repoStatsInDev: true, - repoStatsInProd: true, - connectionLineStyle: 'bezier', -} - -// ============================================================================= -// Header Configuration -// ============================================================================= - -export interface HeaderButtonConfig { - text?: string - tooltip: string -} - -export interface HeaderConfig { - homeButton: HeaderButtonConfig - docsButton: HeaderButtonConfig - boardButton: HeaderButtonConfig - menuButton: HeaderButtonConfig - omniboxPlaceholder: string - repoSelectorLabel: string -} - -export interface WebUiConfig { - appTitle: string - header: HeaderConfig -} - -export const webUiConfig: WebUiConfig = { - appTitle: 'SmartEM Dev Dashboard', - header: { - homeButton: { tooltip: 'Navigate to dashboard home' }, - docsButton: { text: 'docs', tooltip: 'Open project documentation' }, - boardButton: { text: 'board', tooltip: 'Open GitHub project board' }, - menuButton: { tooltip: 'Open settings menu' }, - omniboxPlaceholder: 'search..', - repoSelectorLabel: 'repos / codebases', - }, -} - -export default webUiConfig diff --git a/docs/decision-records/decisions/0013-json-config-with-typescript-types.md b/docs/decision-records/decisions/0013-json-config-with-typescript-types.md new file mode 100644 index 0000000..afc2835 --- /dev/null +++ b/docs/decision-records/decisions/0013-json-config-with-typescript-types.md @@ -0,0 +1,114 @@ +# 13. JSON Configuration with Centralised TypeScript Types + +Date: 2025-01-15 + +## Status + +Accepted + +## Context + +The `core/` directory contained configuration data in multiple formats with unclear conventions: + +- **JSON files** (`repos.json`, `artefacts.json`) - used by Python CLI and prebuild scripts +- **TypeScript files** (`github-labels-config.ts`, `webui-config.ts`, `microscope-list.ts`) - contained both data and types +- **TypeScript wrapper files** (`repos-and-refs.ts`, `claude-code-config.ts`, `dev-requirements.ts`) - imported JSON and added types, but were unused + +This led to several problems: + +1. **Inconsistent conventions** - some configs were JSON, some were TS, some had both +2. **Dead code** - TS wrapper files existed but were never imported +3. **Type duplication** - `webui/scripts/prebuild.ts` generated types from JSON at build time, duplicating type definitions +4. **Unclear data flow** - configuration passed through multiple transformations before reaching consumers + +## Decision + +Adopt a **JSON-first configuration architecture** with a single TypeScript module for types: + +### Structure + +``` +core/ +├── repos.json # Data +├── artefacts.json # Data +├── github-labels.json # Data +├── webui-config.json # Data +├── microscope-list.json # Data +├── claude-code-config.json # Data +├── dev-requirements.json # Data +└── index.ts # Types + typed re-exports +``` + +### Principles + +1. **JSON files are the source of truth for data** - machine-readable, language-agnostic +2. **`core/index.ts` is the source of truth for types** - single location for all TypeScript interfaces +3. **No type generation** - types are authored once in `index.ts`, not generated from JSON +4. **Direct imports** - consumers import from `core/index.ts`, not generated files + +### Data Flow + +``` +core/*.json (data) + ↓ +core/index.ts (types + typed re-exports) + ↓ +consumers (webui, tools, etc.) +``` + +For webui specifically: +``` +core/index.ts + ↓ +webui/src/config/index.ts (transforms to webUiAppContents format) + ↓ +React components +``` + +## Consequences + +### Positive + +- **Single source of truth** - JSON for data, `index.ts` for types +- **No dead code** - removed 6 unused TS files +- **Simpler prebuild** - only syncs docs, no config generation +- **Clear conventions** - all config is JSON, all types are in `index.ts` +- **Language-agnostic data** - Python, TypeScript, and other tools can read JSON directly +- **Type safety preserved** - TypeScript consumers get full typing via `index.ts` + +### Negative + +- **Python type duplication** - `smartem-workspace` still has separate Pydantic schemas that must be manually kept in sync with JSON structure +- **Transformation layer** - webui needs an adapter (`webui/src/config/index.ts`) to transform `repos.json` structure to the format components expect + +### Neutral + +- **Build dependency** - webui now has a build-time dependency on `core/index.ts` (Vite bundles it, so runtime bundle is still self-contained) + +## Files Changed + +### Created +- `core/index.ts` - centralised types and re-exports +- `core/github-labels.json` - converted from TS +- `core/webui-config.json` - converted from TS +- `core/microscope-list.json` - converted from TS + +### Modified +- `webui/src/config/index.ts` - now imports from `core/index.ts` and transforms +- `webui/scripts/prebuild.ts` - simplified to docs sync only +- `tools/github/sync-labels.ts` - updated import path + +### Deleted +- `core/github-labels-config.ts` +- `core/webui-config.ts` +- `core/microscope-list.ts` +- `core/repos-and-refs.ts` +- `core/claude-code-config.ts` +- `core/dev-requirements.ts` +- `webui/src/config/webui-app-contents.ts` + +## Future Considerations + +1. **JSON Schema validation** - could add `$schema` to JSON files for editor support and validation +2. **Python type generation** - could generate Pydantic models from JSON Schema to eliminate manual sync +3. **Shared validation** - could use JSON Schema as single source for both TS and Python types diff --git a/tools/github/sync-labels.ts b/tools/github/sync-labels.ts index e16ee89..9d55443 100644 --- a/tools/github/sync-labels.ts +++ b/tools/github/sync-labels.ts @@ -3,7 +3,7 @@ * GitHub Labels Sync Script * * Syncs GitHub labels across SmartEM repositories to match the configuration - * in core/github-labels-config.ts. + * in core/github-labels.json. * * Usage: * npx tsx tools/github/sync-labels.ts --check # Check conformity (default) @@ -16,12 +16,12 @@ */ import { $ } from 'zx' -import { githubLabelsConfig, type GitHubLabel } from '../../core/github-labels-config.js' +import { githubLabels, type GitHubLabel } from '../../core/index.js' // Suppress zx verbose output $.verbose = false -const { owner: OWNER, repos: REPO_CONFIGS, typesOfWork, systemComponents } = githubLabelsConfig +const { owner: OWNER, repos: REPO_CONFIGS, typesOfWork, systemComponents } = githubLabels interface ExistingLabel { name: string diff --git a/webui/scripts/prebuild.ts b/webui/scripts/prebuild.ts index 5d632a6..9afde0d 100644 --- a/webui/scripts/prebuild.ts +++ b/webui/scripts/prebuild.ts @@ -1,6 +1,9 @@ -import { existsSync, readFileSync, writeFileSync } from 'node:fs' -import { dirname, resolve } from 'node:path' -import { fileURLToPath } from 'node:url' +/** + * Prebuild script for webui. + * + * Syncs documentation from docs/ to webui/src/docs/ as MDX files. + * Configuration is now imported directly from core/index.ts at build time. + */ // Sync documentation from docs/ to webui/src/docs/ import { syncDocs } from './generate-mdx-docs.js' @@ -8,182 +11,3 @@ import { generateNavigation } from './generate-nav-from-docs.js' syncDocs() generateNavigation() - -const __dirname = dirname(fileURLToPath(import.meta.url)) -const projectRoot = resolve(__dirname, '..') -const coreDir = resolve(projectRoot, '..', 'core') -const destFile = resolve(projectRoot, 'src', 'config', 'webui-app-contents.ts') - -const configFiles = [ - 'github-labels-config.ts', - 'repos.json', - 'microscope-list.ts', - 'webui-config.ts', -] - -for (const file of configFiles) { - const path = resolve(coreDir, file) - if (!existsSync(path)) { - console.error(`Config file not found: ${path}`) - process.exit(1) - } -} - -const githubLabelsContent = readFileSync(resolve(coreDir, 'github-labels-config.ts'), 'utf-8') -const reposJsonContent = readFileSync(resolve(coreDir, 'repos.json'), 'utf-8') -const microscopeListContent = readFileSync(resolve(coreDir, 'microscope-list.ts'), 'utf-8') -const webuiConfigContent = readFileSync(resolve(coreDir, 'webui-config.ts'), 'utf-8') - -const reposJson = JSON.parse(reposJsonContent) - -function generateReposAndRefsFromJson(): string { - const diamondLightSourceOrg = reposJson.organizations.find( - (org: { name: string }) => org.name === 'DiamondLightSource' - ) - const fragmentScreenOrg = reposJson.organizations.find( - (org: { name: string }) => org.name === 'FragmentScreen' - ) - const ariaPHPOrg = reposJson.organizations.find( - (org: { name: string }) => org.name === 'aria-php' - ) - - const mapRepo = (repo: { - name: string - description: string - urls: { https: string; ssh: string } - tags?: string[] - ownership?: string - required?: boolean - }) => ({ - name: repo.name, - description: repo.description, - urls: repo.urls, - tags: repo.tags, - ownership: repo.ownership, - required: repo.required, - }) - - return `interface RepoUrls { - https: string - ssh: string -} - -interface Repository { - name: string - description: string - urls: RepoUrls - tags?: string[] - ownership?: 'full' | 'reference-only' - required?: boolean -} - -interface OrgRepos { - org: string - orgUrl: string - repos: Repository[] -} - -interface ExternalLinks { - docs: string - projectBoard: string -} - -interface ReposAndRefsConfig { - links: ExternalLinks - repositories: OrgRepos[] -} - -const reposAndRefsConfig: ReposAndRefsConfig = { - links: { - docs: ${JSON.stringify(reposJson.links.docs)}, - projectBoard: ${JSON.stringify(reposJson.links.projectBoard)}, - }, - repositories: [ - { - org: 'DiamondLightSource', - orgUrl: ${JSON.stringify(diamondLightSourceOrg?.url ?? 'https://github.com/DiamondLightSource')}, - repos: ${JSON.stringify((diamondLightSourceOrg?.repos ?? []).map(mapRepo), null, 8).replace(/\n/g, '\n ')}, - }, - { - org: 'FragmentScreen', - orgUrl: ${JSON.stringify(fragmentScreenOrg?.url ?? 'https://github.com/FragmentScreen')}, - repos: ${JSON.stringify((fragmentScreenOrg?.repos ?? []).map(mapRepo), null, 8).replace(/\n/g, '\n ')}, - }, - { - org: 'aria-php', - orgUrl: ${JSON.stringify(ariaPHPOrg?.url ?? 'https://gitlab.com/aria-php')}, - repos: ${JSON.stringify((ariaPHPOrg?.repos ?? []).map(mapRepo), null, 8).replace(/\n/g, '\n ')}, - }, - ], -}` -} - -const aggregatedContent = `/** - * AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY - * - * This file is generated by scripts/prebuild.ts from: - * - core/github-labels-config.ts - * - core/repos.json (source of truth for repository definitions) - * - core/microscope-list.ts - * - core/webui-config.ts - * - * Edit the source files in core/ and run 'npm run prebuild' to regenerate. - */ - -// ============================================================================= -// GitHub Labels Config -// ============================================================================= - -${stripExportsAndComments(githubLabelsContent, 'GitHubLabelsConfig', 'githubLabelsConfig')} - -// ============================================================================= -// Repos and Refs (generated from repos.json) -// ============================================================================= - -${generateReposAndRefsFromJson()} - -// ============================================================================= -// Microscope List -// ============================================================================= - -${stripExportsAndComments(microscopeListContent, 'CryoEMInstrument', 'microscopeList')} - -// ============================================================================= -// WebUI Config -// ============================================================================= - -${stripExportsAndComments(webuiConfigContent, 'WebUiConfig', 'webUiConfig')} - -// ============================================================================= -// Aggregated App Contents -// ============================================================================= - -export interface WebUiAppContents { - githubLabels: GitHubLabelsConfig - repos: ReposAndRefsConfig - microscopes: CryoEMInstrument[] - config: WebUiConfig - featureFlags: FeatureFlags -} - -export const webUiAppContents: WebUiAppContents = { - githubLabels: githubLabelsConfig, - repos: reposAndRefsConfig, - microscopes: microscopeList, - config: webUiConfig, - featureFlags: featureFlags, -} - -export default webUiAppContents -` - -function stripExportsAndComments(content: string, _mainType: string, _mainExport: string): string { - return content - .replace(/\/\*\*[\s\S]*?\*\/\n*/g, '') - .replace(/^export default.*\n?/gm, '') - .replace(/^export /gm, '') - .trim() -} - -writeFileSync(destFile, aggregatedContent) -console.log(`Generated ${destFile}`) diff --git a/webui/src/components/header/ArtefactsMenu.tsx b/webui/src/components/header/ArtefactsMenu.tsx new file mode 100644 index 0000000..1c9b07a --- /dev/null +++ b/webui/src/components/header/ArtefactsMenu.tsx @@ -0,0 +1,167 @@ +import { Box, Menu, MenuItem, Typography } from '@mui/material' +import { useState } from 'react' +import { AppTooltip, CopyCodeBox } from '~/components/common' +import { webUiAppContents } from '~/config' + +const ICON_DOWNLOAD = '\uf019' +const ICON_CHEVRON_DOWN = '\uf078' +const ICON_EXTERNAL_LINK = '\uf08e' + +export function ArtefactsMenu() { + const { text, tooltip } = webUiAppContents.config.header.artefactsButton + const { items } = webUiAppContents.artefacts + const [anchorEl, setAnchorEl] = useState(null) + const open = Boolean(anchorEl) + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget) + } + + const handleClose = () => { + setAnchorEl(null) + } + + return ( + <> + + + + {ICON_DOWNLOAD} + + + {text} + + + {ICON_CHEVRON_DOWN} + + + + + {items.map((item) => ( + + + + {ICON_EXTERNAL_LINK} + + + {item.label} + + + {item.description && ( + + {item.description} + + )} + {item.command && ( + e.stopPropagation()} + sx={{ mt: 1, opacity: 0.7 }} + > + + + )} + + ))} + + + ) +} diff --git a/webui/src/components/header/Header.tsx b/webui/src/components/header/Header.tsx index cad1e60..e409f13 100644 --- a/webui/src/components/header/Header.tsx +++ b/webui/src/components/header/Header.tsx @@ -1,4 +1,5 @@ import { AppBar, Box, Toolbar } from '@mui/material' +import { ArtefactsMenu } from './ArtefactsMenu' import { DocsButton } from './DocsButton' import { LogoHomeButton } from './LogoHomeButton' import { MenuButton } from './MenuButton' @@ -20,6 +21,7 @@ export function Header() { + diff --git a/webui/src/components/header/index.ts b/webui/src/components/header/index.ts index 437b609..e41ce6c 100644 --- a/webui/src/components/header/index.ts +++ b/webui/src/components/header/index.ts @@ -1,7 +1,8 @@ +export { ArtefactsMenu } from './ArtefactsMenu' +export { DocsButton } from './DocsButton' export { Header } from './Header' export { LogoHomeButton } from './LogoHomeButton' -export { DocsButton } from './DocsButton' +export { MenuButton } from './MenuButton' +export { OmniBoxBar } from './OmniBoxBar' export { ProjectBoardButton } from './ProjectBoardButton' export { RepoListBar } from './RepoListBar' -export { OmniBoxBar } from './OmniBoxBar' -export { MenuButton } from './MenuButton' diff --git a/webui/src/config/index.ts b/webui/src/config/index.ts index 82edac0..8ec3948 100644 --- a/webui/src/config/index.ts +++ b/webui/src/config/index.ts @@ -1,2 +1,105 @@ -export * from './webui-app-contents' -export { default as webUiAppContents } from './webui-app-contents' +/** + * WebUI configuration adapter. + * + * Imports from core/ and transforms to the webUiAppContents format expected by components. + * This keeps the transformation logic in one place and provides a stable interface. + */ + +import { + type ArtefactsConfig, + artefacts, + type CryoEMInstrument, + type FeatureFlags, + featureFlags, + type GitHubLabelsConfig, + githubLabels, + microscopes, + type ReposConfig, + type Repository, + repos, + type WebUiConfig, + webUiConfig, +} from '../../../core' + +// ============================================================================= +// Transformed Types for WebUI +// ============================================================================= + +export interface RepoUrls { + https: string + ssh: string +} + +export interface WebUiRepository { + name: string + description: string + urls: RepoUrls + tags?: string[] + ownership?: 'full' | 'reference-only' + required?: boolean +} + +export interface OrgRepos { + org: string + orgUrl: string + repos: WebUiRepository[] +} + +export interface ExternalLinks { + docs: string + projectBoard: string +} + +export interface ReposAndRefsConfig { + links: ExternalLinks + repositories: OrgRepos[] +} + +// ============================================================================= +// Transform repos.json to webui format +// ============================================================================= + +function transformRepos(config: ReposConfig): ReposAndRefsConfig { + return { + links: config.links, + repositories: config.organizations.map((org) => ({ + org: org.name, + orgUrl: org.url, + repos: org.repos.map((repo) => ({ + name: repo.name, + description: repo.description, + urls: repo.urls, + tags: repo.tags, + ownership: repo.ownership, + required: repo.required, + })), + })), + } +} + +// ============================================================================= +// Aggregated App Contents +// ============================================================================= + +export interface WebUiAppContents { + githubLabels: GitHubLabelsConfig + repos: ReposAndRefsConfig + microscopes: CryoEMInstrument[] + config: WebUiConfig + featureFlags: FeatureFlags + artefacts: ArtefactsConfig +} + +export const webUiAppContents: WebUiAppContents = { + githubLabels, + repos: transformRepos(repos), + microscopes, + config: webUiConfig, + featureFlags, + artefacts, +} + +// Re-export types that components might need +export type { GitHubLabelsConfig, ArtefactsConfig, FeatureFlags, CryoEMInstrument, Repository } + +export default webUiAppContents diff --git a/webui/src/config/webui-app-contents.ts b/webui/src/config/webui-app-contents.ts deleted file mode 100644 index b2b56eb..0000000 --- a/webui/src/config/webui-app-contents.ts +++ /dev/null @@ -1,657 +0,0 @@ -/** - * AUTO-GENERATED FILE - DO NOT EDIT DIRECTLY - * - * This file is generated by scripts/prebuild.ts from: - * - core/github-labels-config.ts - * - core/repos.json (source of truth for repository definitions) - * - core/microscope-list.ts - * - core/webui-config.ts - * - * Edit the source files in core/ and run 'npm run prebuild' to regenerate. - */ - -// ============================================================================= -// GitHub Labels Config -// ============================================================================= - -interface GitHubLabel { - name: string - description: string - color: string // 6-char hex without # -} - -interface RepoLabelConfig { - repo: string - labels: 'all' | 'types-only' -} - -interface GitHubLabelsConfig { - owner: string - typesOfWork: GitHubLabel[] - systemComponents: GitHubLabel[] - repos: RepoLabelConfig[] -} - -const typesOfWork: GitHubLabel[] = [ - { name: 'documentation', description: 'Improvements or additions to project documentation', color: '0d6d6e' }, - { name: 'testing', description: 'Writing, updating, or fixing automated tests', color: '2da44e' }, - { name: 'bugfixing', description: 'Fixing defects or unexpected behavior in existing code', color: 'cf222e' }, - { name: 'development', description: 'New features or functionality implementation', color: '8250df' }, - { name: 'refactoring', description: 'Code restructuring without changing external behavior', color: 'bc4c00' }, - { name: 'research', description: 'Investigation, spikes, or proof-of-concept work', color: '0598bd' }, - { name: 'devops', description: 'CI/CD, deployment, infrastructure, or tooling work', color: '57606a' }, - { name: 'security', description: 'Security fixes, audits, or vulnerability remediation', color: 'a40e26' }, - { name: 'admin', description: 'Project maintenance, dependency updates, or housekeeping', color: '7c4a03' }, - { name: 'enhancement', description: 'Minor improvements to existing functionality', color: '1b7c83' }, -] - -const systemComponents: GitHubLabel[] = [ - // smartem-backend family (ocean blue scale: #0a3069 -> #0550ae -> #218bff) - { name: 'smartem-backend', description: 'Core backend services, messaging, and persistence layer', color: '0a3069' }, - { name: 'smartem-backend:db', description: 'Database schema, migrations, and data layer changes', color: '0550ae' }, - { name: 'smartem-backend:api', description: 'REST API endpoints and HTTP interface changes', color: '218bff' }, - - // smartem-agent (gold - standalone) - { name: 'smartem-agent', description: 'EPU workstation agent for microscope integration', color: '9a6700' }, - - // smartem-frontend (green - standalone) - { name: 'smartem-frontend', description: 'User-facing web UI for acquisition sessions and ML decisions', color: '1a7f37' }, - - // smartem-aria-connector (purple - standalone) - { name: 'smartem-aria-connector', description: 'ARIA deposition integration via FandanGO plugin', color: '6639ba' }, - - // smartem-devtools family (warm pink scale: #99154b -> #bf3989 -> #db61a2 -> #f09bc8) - { name: 'smartem-devtools', description: 'Developer tooling, documentation, and workspace configuration', color: '99154b' }, - { name: 'smartem-devtools:webui', description: 'Developer dashboard web interface', color: 'bf3989' }, - { name: 'smartem-devtools:claude', description: 'Claude Code configuration, skills, and prompts', color: 'db61a2' }, - { name: 'smartem-devtools:e2e-test', description: 'End-to-end testing infrastructure and scenarios', color: 'f09bc8' }, -] - -const repos: RepoLabelConfig[] = [ - { repo: 'smartem-devtools', labels: 'all' }, - { repo: 'smartem-decisions', labels: 'types-only' }, - { repo: 'smartem-frontend', labels: 'types-only' }, - { repo: 'fandanGO-cryoem-dls', labels: 'types-only' }, -] - -const githubLabelsConfig: GitHubLabelsConfig = { - owner: 'DiamondLightSource', - typesOfWork, - systemComponents, - repos, -} - -// ============================================================================= -// Repos and Refs (generated from repos.json) -// ============================================================================= - -interface RepoUrls { - https: string - ssh: string -} - -interface Repository { - name: string - description: string - urls: RepoUrls - tags?: string[] - ownership?: 'full' | 'reference-only' - required?: boolean -} - -interface OrgRepos { - org: string - orgUrl: string - repos: Repository[] -} - -interface ExternalLinks { - docs: string - projectBoard: string -} - -interface ReposAndRefsConfig { - links: ExternalLinks - repositories: OrgRepos[] -} - -const reposAndRefsConfig: ReposAndRefsConfig = { - links: { - docs: "https://diamondlightsource.github.io/smartem-decisions/", - projectBoard: "https://github.com/orgs/DiamondLightSource/projects/51/views/1", - }, - repositories: [ - { - org: 'DiamondLightSource', - orgUrl: "https://github.com/DiamondLightSource", - repos: [ - { - "name": "smartem-decisions", - "description": "Central system controller - backbone, messaging router, persistence, auth", - "urls": { - "https": "https://github.com/DiamondLightSource/smartem-decisions.git", - "ssh": "git@github.com:DiamondLightSource/smartem-decisions.git" - }, - "tags": [ - "core", - "python", - "backend" - ], - "ownership": "full" - }, - { - "name": "smartem-frontend", - "description": "Web UI for SmartEM - user-facing view of acquisition sessions and ML decisions", - "urls": { - "https": "https://github.com/DiamondLightSource/smartem-frontend.git", - "ssh": "git@github.com:DiamondLightSource/smartem-frontend.git" - }, - "tags": [ - "core", - "typescript", - "frontend" - ], - "ownership": "full" - }, - { - "name": "smartem-devtools", - "description": "Developer tooling, documentation, and workspace configuration", - "urls": { - "https": "https://github.com/DiamondLightSource/smartem-devtools.git", - "ssh": "git@github.com:DiamondLightSource/smartem-devtools.git" - }, - "tags": [ - "core", - "tooling" - ], - "ownership": "full", - "required": true - }, - { - "name": "fandanGO-cryoem-dls", - "description": "DLS facility plugin for FandanGO - bridges SmartEM to ARIA", - "urls": { - "https": "https://github.com/DiamondLightSource/fandanGO-cryoem-dls.git", - "ssh": "git@github.com:DiamondLightSource/fandanGO-cryoem-dls.git" - }, - "tags": [ - "aria", - "python" - ], - "ownership": "full" - }, - { - "name": "cryoem-services", - "description": "Processing execution layer for cryo-EM data pipelines (reference-only)", - "urls": { - "https": "https://github.com/DiamondLightSource/cryoem-services.git", - "ssh": "git@github.com:DiamondLightSource/cryoem-services.git" - }, - "tags": [ - "reference", - "python" - ], - "ownership": "reference-only" - } - ], - }, - { - org: 'FragmentScreen', - orgUrl: "https://github.com/FragmentScreen", - repos: [ - { - "name": "fandanGO-core", - "description": "Plugin framework foundation", - "urls": { - "https": "https://github.com/FragmentScreen/fandanGO-core.git", - "ssh": "git@github.com:FragmentScreen/fandanGO-core.git" - }, - "tags": [ - "aria", - "python", - "framework" - ], - "ownership": "reference-only" - }, - { - "name": "fandanGO-aria", - "description": "ARIA integration - auth, token management, metadata submission", - "urls": { - "https": "https://github.com/FragmentScreen/fandanGO-aria.git", - "ssh": "git@github.com:FragmentScreen/fandanGO-aria.git" - }, - "tags": [ - "aria", - "python" - ], - "ownership": "reference-only" - }, - { - "name": "fandanGO-cryoem-cnb", - "description": "CNB-CSIC Madrid cryo-EM plugin (peer reference)", - "urls": { - "https": "https://github.com/FragmentScreen/fandanGO-cryoem-cnb.git", - "ssh": "git@github.com:FragmentScreen/fandanGO-cryoem-cnb.git" - }, - "tags": [ - "aria", - "python", - "peer" - ], - "ownership": "reference-only" - }, - { - "name": "fandanGO-nmr-cerm", - "description": "CERM Florence NMR plugin (peer reference)", - "urls": { - "https": "https://github.com/FragmentScreen/fandanGO-nmr-cerm.git", - "ssh": "git@github.com:FragmentScreen/fandanGO-nmr-cerm.git" - }, - "tags": [ - "aria", - "python", - "peer" - ], - "ownership": "reference-only" - }, - { - "name": "fandanGO-nmr-guf", - "description": "GUF Frankfurt NMR plugin (peer reference)", - "urls": { - "https": "https://github.com/FragmentScreen/fandanGO-nmr-guf.git", - "ssh": "git@github.com:FragmentScreen/fandanGO-nmr-guf.git" - }, - "tags": [ - "aria", - "python", - "peer" - ], - "ownership": "reference-only" - }, - { - "name": "Samples", - "description": "Sample metadata/datasets for community reference", - "urls": { - "https": "https://github.com/FragmentScreen/Samples.git", - "ssh": "git@github.com:FragmentScreen/Samples.git" - }, - "tags": [ - "aria", - "data" - ], - "ownership": "reference-only" - } - ], - }, - { - org: 'aria-php', - orgUrl: "https://gitlab.com/aria-php", - repos: [ - { - "name": "data-deposition-api", - "description": "ARIA GraphQL/REST API for metadata deposition (primary)", - "urls": { - "https": "https://gitlab.com/aria-php/data-deposition-api.git", - "ssh": "git@gitlab.com:aria-php/data-deposition-api.git" - }, - "tags": [ - "aria", - "php", - "api" - ], - "ownership": "reference-only" - }, - { - "name": "aria-graphql-client", - "description": "PHP library for communicating with ARIA GraphQL API", - "urls": { - "https": "https://gitlab.com/aria-php/aria-graphql-client.git", - "ssh": "git@gitlab.com:aria-php/aria-graphql-client.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-elasticsearch-client", - "description": "Elasticsearch client for ARIA search records", - "urls": { - "https": "https://gitlab.com/aria-php/aria-elasticsearch-client.git", - "ssh": "git@gitlab.com:aria-php/aria-elasticsearch-client.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-rest", - "description": "REST API framework for defining versioned APIs", - "urls": { - "https": "https://gitlab.com/aria-php/aria-rest.git", - "ssh": "git@gitlab.com:aria-php/aria-rest.git" - }, - "tags": [ - "aria", - "php", - "framework" - ], - "ownership": "reference-only" - }, - { - "name": "aria-storage-interface", - "description": "Storage provider interface", - "urls": { - "https": "https://gitlab.com/aria-php/aria-storage-interface.git", - "ssh": "git@gitlab.com:aria-php/aria-storage-interface.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-webhooks", - "description": "Standard webhook payload format for ARIA platform", - "urls": { - "https": "https://gitlab.com/aria-php/aria-webhooks.git", - "ssh": "git@gitlab.com:aria-php/aria-webhooks.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-incoming-email", - "description": "Incoming email message routing", - "urls": { - "https": "https://gitlab.com/aria-php/aria-incoming-email.git", - "ssh": "git@gitlab.com:aria-php/aria-incoming-email.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-mailer", - "description": "Email wrapper (PHPMailer + Swiftmailer)", - "urls": { - "https": "https://gitlab.com/aria-php/aria-mailer.git", - "ssh": "git@gitlab.com:aria-php/aria-mailer.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-mailgun-webhooks", - "description": "Mailgun webhook event parser", - "urls": { - "https": "https://gitlab.com/aria-php/aria-mailgun-webhooks.git", - "ssh": "git@gitlab.com:aria-php/aria-mailgun-webhooks.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-invite-users", - "description": "User invitation framework", - "urls": { - "https": "https://gitlab.com/aria-php/aria-invite-users.git", - "ssh": "git@gitlab.com:aria-php/aria-invite-users.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-data-subscription", - "description": "Data source subscription framework for feeds", - "urls": { - "https": "https://gitlab.com/aria-php/aria-data-subscription.git", - "ssh": "git@gitlab.com:aria-php/aria-data-subscription.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-stats", - "description": "Performance statistics monitoring", - "urls": { - "https": "https://gitlab.com/aria-php/aria-stats.git", - "ssh": "git@gitlab.com:aria-php/aria-stats.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-site-logger", - "description": "Monolog plugin for ARIA site logging", - "urls": { - "https": "https://gitlab.com/aria-php/aria-site-logger.git", - "ssh": "git@gitlab.com:aria-php/aria-site-logger.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "aria-service-ai", - "description": "Service AI library", - "urls": { - "https": "https://gitlab.com/aria-php/aria-service-ai.git", - "ssh": "git@gitlab.com:aria-php/aria-service-ai.git" - }, - "tags": [ - "aria", - "php", - "library" - ], - "ownership": "reference-only" - }, - { - "name": "keycloak-api", - "description": "PHP bindings for Keycloak Account API", - "urls": { - "https": "https://gitlab.com/aria-php/keycloak-api.git", - "ssh": "git@gitlab.com:aria-php/keycloak-api.git" - }, - "tags": [ - "aria", - "php", - "integration" - ], - "ownership": "reference-only" - }, - { - "name": "doi-package", - "description": "DOI microservice client", - "urls": { - "https": "https://gitlab.com/aria-php/doi-package.git", - "ssh": "git@gitlab.com:aria-php/doi-package.git" - }, - "tags": [ - "aria", - "php", - "integration" - ], - "ownership": "reference-only" - }, - { - "name": "molgenis-php-client", - "description": "PHP client for Molgenis database", - "urls": { - "https": "https://gitlab.com/aria-php/molgenis-php-client.git", - "ssh": "git@gitlab.com:aria-php/molgenis-php-client.git" - }, - "tags": [ - "aria", - "php", - "integration" - ], - "ownership": "reference-only" - }, - { - "name": "shibboleth-idp-dockerized", - "description": "Dockerized Shibboleth IdP (identity federation)", - "urls": { - "https": "https://gitlab.com/aria-php/shibboleth-idp-dockerized.git", - "ssh": "git@gitlab.com:aria-php/shibboleth-idp-dockerized.git" - }, - "tags": [ - "aria", - "infrastructure" - ], - "ownership": "reference-only" - }, - { - "name": "rtd-compiler", - "description": "ReadTheDocs compiler for ARIA documentation", - "urls": { - "https": "https://gitlab.com/aria-php/rtd-compiler.git", - "ssh": "git@gitlab.com:aria-php/rtd-compiler.git" - }, - "tags": [ - "aria", - "infrastructure" - ], - "ownership": "reference-only" - } - ], - }, - ], -} - -// ============================================================================= -// Microscope List -// ============================================================================= - -interface CryoEMInstrument { - name: string - alias: string -} - -const microscopeList: CryoEMInstrument[] = [ - { name: 'Krios 1', alias: 'm02' }, - { name: 'Krios 2', alias: 'm03' }, - { name: 'Krios 3', alias: 'm06' }, - { name: 'Krios 4', alias: 'm07' }, - { name: 'Krios 5', alias: 'm08' }, - { name: 'Talos', alias: 'm04' }, - { name: 'Scios', alias: 'm05' }, - { name: 'Glacios 1', alias: 'm10' }, - { name: 'Glacios 2', alias: 'm12' }, - { name: 'Aquilos', alias: 'm11' }, - { name: 'Leica cryoCLEM', alias: 'm14' }, -] - -// ============================================================================= -// WebUI Config -// ============================================================================= - -// ============================================================================= -// Feature Flags -// ============================================================================= - -interface FeatureFlags { - repoStatsInDev: boolean - repoStatsInProd: boolean - connectionLineStyle: 'straight' | 'bezier' | 'orthogonal' -} - -const featureFlags: FeatureFlags = { - repoStatsInDev: true, - repoStatsInProd: true, - connectionLineStyle: 'bezier', -} - -// ============================================================================= -// Header Configuration -// ============================================================================= - -interface HeaderButtonConfig { - text?: string - tooltip: string -} - -interface HeaderConfig { - homeButton: HeaderButtonConfig - docsButton: HeaderButtonConfig - boardButton: HeaderButtonConfig - menuButton: HeaderButtonConfig - omniboxPlaceholder: string - repoSelectorLabel: string -} - -interface WebUiConfig { - appTitle: string - header: HeaderConfig -} - -const webUiConfig: WebUiConfig = { - appTitle: 'SmartEM Dev Dashboard', - header: { - homeButton: { tooltip: 'Navigate to dashboard home' }, - docsButton: { text: 'docs', tooltip: 'Open project documentation' }, - boardButton: { text: 'board', tooltip: 'Open GitHub project board' }, - menuButton: { tooltip: 'Open settings menu' }, - omniboxPlaceholder: 'search..', - repoSelectorLabel: 'repos / codebases', - }, -} - -// ============================================================================= -// Aggregated App Contents -// ============================================================================= - -export interface WebUiAppContents { - githubLabels: GitHubLabelsConfig - repos: ReposAndRefsConfig - microscopes: CryoEMInstrument[] - config: WebUiConfig - featureFlags: FeatureFlags -} - -export const webUiAppContents: WebUiAppContents = { - githubLabels: githubLabelsConfig, - repos: reposAndRefsConfig, - microscopes: microscopeList, - config: webUiConfig, - featureFlags: featureFlags, -} - -export default webUiAppContents