Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
bf048cc
feat: implement entity caching mechanism to optimize API calls
bencap Feb 17, 2026
6fddc9e
feat: unify inline collection item management with reusable table + a…
bencap Feb 17, 2026
c98f703
chore: refresh types for collections
bencap Feb 17, 2026
e287d3d
feat(calibrations): migrate class variants to lazy endpoints and upda…
bencap Feb 19, 2026
4b32818
feat: broaden calibration creation access and rename evidenceSources
bencap Feb 24, 2026
1eb996c
docs: update documentation for email requirements and clarify calibra…
bencap Feb 24, 2026
2de0b8d
chore: initialize agent instructions for MaveDB UI
bencap Feb 24, 2026
886187a
chore: Add issue number to TODO for #628
bencap Feb 24, 2026
ba29992
feat: add margin to calibration button for improved layout
bencap Feb 24, 2026
e05040a
fix: update calibration source order and fix error handling in calibr…
bencap Feb 24, 2026
b49053e
refactor: implement saveCalibration function to centralize calibratio…
bencap Feb 24, 2026
3bbef47
Merge pull request #620 from VariantEffect/feature/bencap/sortable-co…
bencap Feb 25, 2026
0061436
chore: update copilot instructions to include maintenance guidelines
bencap Feb 25, 2026
49b1ff6
Merge pull request #623 from VariantEffect/feature/bencap/calibration…
bencap Mar 2, 2026
5cfe2fc
Merge pull request #625 from VariantEffect/feature/bencap/calibration…
bencap Mar 2, 2026
06ea284
Merge pull request #627 from VariantEffect/chore/bencap/agent-instruc…
bencap Mar 2, 2026
c4d0f34
chore: bump dependencies for security updates
bencap Mar 2, 2026
3972a0c
chore: bump version to 2026.1.1
bencap Mar 2, 2026
de16178
fix: add sass-embedded and modern compiler API for pdbe-molstar 3.10.x
bencap Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions .github/instructions/api-and-data.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# API and Data Fetching

## HTTP Client

All API communication uses **Axios**, wrapped by the `rest-client-vue` library. The REST client is initialized in `src/main.js`:

```ts
import {initRestClient} from 'rest-client-vue'
initRestClient({apiBaseUrl: config.apiBaseUrl})
```

## API Base URL

Configured per environment via `VITE_API_URL` in `.env.*` files:

- Local dev: `https://127.0.0.1:8002/api/v1`
- Production: `https://api.mavedb.org/api/v1`

## Authorization Headers

Two Axios interceptors are installed at startup in `src/lib/auth.ts`:

1. **Request interceptor** — Automatically adds `Authorization: Bearer <token>` and `X-Active-Roles` headers to all requests targeting the MaveDB API.
2. **Response interceptor** — Catches 401/403 responses, verifies the session against `/users/me`, signs the user out if the session is expired, and optionally redirects to login.

This means components do not need to manually attach auth headers; they are injected globally.

## Item Types Configuration

`src/lib/item-types.js` defines a registry of REST resource types. Each entry maps a logical name to its REST collection endpoint and optional HTTP overrides:

```js
{
'scoreSet': {
name: 'scoreSet',
restCollectionName: 'score-sets',
// Optional HTTP overrides:
httpOptions: {
list: { method: 'get', url: `${config.apiBaseUrl}/some/custom/endpoint` }
}
}
}
```

Resource types include: experiment sets, experiments, score sets, collections, controlled keywords, users, access keys, and more.

## Data Fetching Patterns

### 1. Composition-based (primary pattern)

The `useItem()` composable from `src/composition/item.js` manages loading a single resource:

```ts
import useItem from '@/composition/item'

// In a component's setup function:
setup: (props) => useItem({itemTypeName: 'scoreSet'})

// The composable returns reactive properties:
// - item: the loaded resource
// - setItemId(id): triggers fetching by ID/URN
```

Similarly, `useItems()` from `src/composition/items.js` manages loading collections.

Both composables dynamically register Vuex modules with UUID namespaces for isolated state.

### 2. Direct Axios calls

For custom or one-off API interactions, components use Axios directly:

```ts
import axios from 'axios'
import config from '@/config'

const response = await axios.get(`${config.apiBaseUrl}/score-sets/${urn}`)
```

Auth headers are automatically included by the interceptor.

### 3. REST client (rest-client-vue)

The `rest-client-vue` wrapper provides reactive REST collection management with built-in caching and pagination. Used in some components for list/search scenarios.

## OpenAPI Type Generation

TypeScript types for API responses are auto-generated from the backend's OpenAPI spec:

```bash
npx openapi-typescript https://api.mavedb.org/openapi.json -o src/schema/openapi.d.ts
```

The generated types live in `src/schema/openapi.d.ts` and provide full type safety for API request/response shapes. Use these types when working with API data to ensure correctness.

## Key API Endpoints

| Resource | Endpoint pattern |
| ------------------- | ------------------------------------ |
| Score sets | `/api/v1/score-sets/{urn}` |
| Experiments | `/api/v1/experiments/{urn}` |
| Experiment sets | `/api/v1/experiment-sets/{urn}` |
| Collections | `/api/v1/collections/{urn}` |
| Users | `/api/v1/users/me` |
| Access keys | `/api/v1/users/me/access-keys` |
| Controlled keywords | `/api/v1/controlled-keywords/{type}` |
| Search | `/api/v1/score-sets/search` |
| Statistics | `/api/v1/statistics` |

## Data Visualization

Several libraries are used for rendering scientific data:

- **D3** — Heatmaps (`src/lib/heatmap.ts`) and histograms (`src/lib/histogram.ts`)
- **Chart.js** — Statistical charts via `chart.js` and its Vue wrapper
- **PDBe Molstar** — 3D protein structure visualization (`pdbe-molstar`)

## CSV and File Handling

- **PapaParse** — CSV parsing for score/variant data uploads and downloads
- **JSZip** — ZIP file creation for multi-file downloads
- **pdfmake** — PDF generation for chart exports
- **dom-to-image** — DOM-to-image conversion for chart export
109 changes: 109 additions & 0 deletions .github/instructions/code-style.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Code Style and Formatting

## Formatting (Prettier)

The project uses Prettier for code formatting, configured in `.prettierrc.ts`:

| Setting | Value |
| ----------------------- | -------- |
| Print width | 120 |
| Semicolons | No |
| Quotes | Single |
| Tab width | 2 spaces |
| Trailing commas | None |
| Arrow parens | Always |
| Bracket spacing | No |
| End of line | LF |
| Vue indent script/style | No |

### Practical examples

```ts
// Correct
import {computed, ref, watch} from 'vue'
const result = someFunction(arg1, arg2)
const arrow = (x) => x + 1

// Wrong
import {computed, ref, watch} from 'vue'
const result = someFunction(arg1, arg2)
const arrow = (x) => x + 1
```

Note: no spaces inside braces, no semicolons, single quotes, always parenthesize arrow function parameters.

## Linting (ESLint)

Configured in `eslint.config.mjs` with:

- `eslint-plugin-vue` — Vue recommended rules
- `@vue/eslint-config-typescript` — TypeScript integration
- `@vue/eslint-config-prettier/skip-formatting` — Disables ESLint rules that conflict with Prettier

### Custom rules

- **`vue/attributes-order`**: Template attributes must be in **alphabetical order** (error level). This is strictly enforced.

```html
<!-- Correct -->
<button :disabled="loading" label="Save" severity="primary" @click="save" />

<!-- Wrong (not alphabetical) -->
<button label="Save" @click="save" :disabled="loading" severity="primary" />
```

## TypeScript

- **Strict mode** is enabled in `tsconfig.json`.
- `noUnusedLocals` and `noUnusedParameters` are enforced — do not leave unused variables or parameters.
- `noFallthroughCasesInSwitch` is enforced.
- Prefer `.ts` for new files. Some legacy files use `.js`.
- Use `@ts-expect-error` (not `@ts-ignore`) when type suppression is unavoidable, and include a comment explaining why.

## Naming Conventions

| Kind | Convention | Examples |
| ----------------- | ------------------ | ----------------------------------------- |
| Vue components | PascalCase | `ScoreSetView.vue`, `EntityLink.vue` |
| Functions | camelCase | `beginAuthentication`, `parseVariant` |
| Variables/refs | camelCase | `userProfile`, `isAuthenticated` |
| Constants | UPPER_SNAKE_CASE | `PUBLIC_PATHS`, `ORCID_ID_REGEX` |
| Composables | `use` prefix | `useAuth`, `useItem` |
| Screen components | Descriptive suffix | `*View`, `*Screen`, `*Creator`, `*Editor` |

## Import Conventions

- Always use the `@/` path alias (maps to `src/`). Never use relative paths.
- Group imports: Vue/library imports first, then project imports.

```ts
// External libraries
import {computed, ref, watch} from 'vue'
import {useRouter} from 'vue-router'
import _ from 'lodash'
import axios from 'axios'

// Project imports
import DefaultLayout from '@/components/layout/DefaultLayout.vue'
import useAuth from '@/composition/auth'
import config from '@/config'
```

## File Organization

- **Components**: `.vue` single-file components, always with `<script lang="ts">`.
- **Libraries/utilities**: `.ts` files in `src/lib/`.
- **Composables**: `.ts` files in `src/composables/` (new) or `src/composition/` (legacy).
- **Store modules**: In `src/store/modules/`.
- **Types**: Auto-generated API types in `src/schema/openapi.d.ts`. Custom types co-located with their usage.

## General Guidelines

- Do not add semicolons.
- Do not add trailing commas.
- Do not add spaces inside curly braces for imports or object literals.
- Keep lines under 120 characters.
- Prefer `const` over `let`. Never use `var`.
- Use template literals for string interpolation.
- Use `async`/`await` over raw promises.
- Use lodash utilities (`_.get`, `_.isString`, `_.isEmpty`, etc.) for data manipulation — the library is already a dependency.
92 changes: 92 additions & 0 deletions .github/instructions/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# MaveDB UI — General Codebase Instructions

## Project Overview

MaveDB UI is the frontend for [MaveDB](https://mavedb.org), a database for Multiplex Assays of Variant Effect (MAVE) data. It is a single-page application built with **Vue 3**, **TypeScript**, and **Vite**.

## Tech Stack

| Layer | Technology |
| ------------------ | ------------------------------------------------------- |
| Framework | Vue 3 (Composition API via `defineComponent` + `setup`) |
| Language | TypeScript (strict mode) with some legacy `.js` files |
| Build tool | Vite 5 |
| Package manager | npm |
| Component library | PrimeVue 4 (Aura theme) |
| CSS | Tailwind CSS 4 + PrimeFlex 3 grid utilities |
| State management | Vuex 4 (legacy, migrating to Pinia) |
| Routing | Vue Router 4 (history mode) |
| HTTP client | Axios (via rest-client-vue wrapper) |
| Authentication | ORCID OAuth2 (custom implementation) |
| Form validation | vee-validate + yup |
| Data visualization | D3, Chart.js, PDBe Molstar |
| API types | Auto-generated from OpenAPI spec via openapi-typescript |

## Directory Structure

```
src/
├── assets/ # Global CSS and static images
├── components/
│ ├── common/ # Reusable, generic UI components
│ ├── layout/ # App shell: DefaultLayout, Toolbar, Footer
│ └── screens/ # Top-level route/page components (*View, *Screen, *Creator, *Editor)
├── composables/ # Vue 3 composables (newer pattern)
├── composition/ # Composition functions (older pattern, similar purpose)
├── lib/ # Business logic, utilities, API helpers
├── router/ # Vue Router configuration
├── schema/ # Auto-generated OpenAPI TypeScript types
└── store/ # Vuex store and modules
└── modules/ # auth, toast, item, items, layout, remote-data
```

## Key Conventions

- **Path alias**: Always use `@/` (maps to `src/`) instead of relative imports.
- **Component naming**: PascalCase `.vue` files. Screens suffixed with `View`, `Screen`, `Creator`, or `Editor`.
- **TypeScript**: Prefer `.ts` for new files. Strict mode is enabled (`noUnusedLocals`, `noUnusedParameters`, `noFallthroughCasesInSwitch`).
- **No test framework**: There is currently no automated test suite in this project.
- **Node version**: 20.x is required.

## Build & Run

```bash
npm install # Install dependencies
npm run dev # Dev server on https://127.0.0.1:8081 (local API)
MODE=prodapi npm run dev # Dev server using the live API
npm run build # Production build to dist/
```

## Environment Configuration

Environment variables are defined in `.env.*` files and accessed via `import.meta.env.VITE_*`. The `src/config.js` module re-exports them for convenient use:

- `VITE_API_URL` — Backend API base URL
- `VITE_APP_URL` — Application base URL
- `VITE_SITE_TITLE` — Page title template
- `VITE_CLINICAL_FEATURES_ENABLED` — Feature flag for MaveMD clinical features
- `VITE_PREVIEW_SITE` — Preview mode flag

## Domain Context

MaveDB stores and serves data about **variant effects** measured through multiplex assays. Key domain concepts:

- **Experiment Set** — A collection of related experiments
- **Experiment** — A single experimental setup
- **Score Set** — A set of variant effect scores from an experiment, the core data unit
- **Variant** — A specific genetic variant with measured effects
- **Calibration** — Statistical calibrations applied to score sets
- **URN** — Unique resource names used as primary identifiers (e.g., `urn:mavedb:00000001-a-1`)
- **HGVS** — Human Genome Variation Society notation for describing variants
- **Target Gene** — The gene being studied in an experiment

## Important Architectural Notes

1. **State management is in transition**: Vuex 4 modules exist for auth, toast, and dynamic item state. Pinia is installed but not widely used yet. New state management should prefer Pinia.
2. **Dynamic Vuex modules**: The `composition/item.js` composable creates per-component Vuex modules dynamically using `store.registerModule()` with UUID-based namespaces.
3. **Feature flags**: Some routes and features are conditionally enabled based on `config.CLINICAL_FEATURES_ENABLED`.
4. **HTTPS required for dev**: The Vite dev server uses `@vitejs/plugin-basic-ssl` because ORCID OAuth requires HTTPS callbacks. Port 8081 must be available (strictPort).

## Maintaining This File

This instruction file and the project documentation (`docs/`) are **living documents**. When you make changes to the codebase that affect the information described here — such as removing a feature flag, changing the tech stack, restructuring directories, or updating conventions — update this file and any affected documentation pages to reflect the new state. Do not leave stale or obsolete instructions in place.
Loading