diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..bf18a5c45 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,105 @@ +# AGENTS.md + +Instructions for automated coding agents working in this repository. + +## Scope + +These instructions apply to the whole repository. + +## Project Overview + +`bi-web` is a Vue 2.7 frontend for Breeding Insight. It uses Vue CLI 4, +TypeScript, Vuex, Vue Router, Buefy/Bulma, Vuelidate, CASL abilities, and an +axios wrapper for API calls. + +Important directories: + +- `src/views`: route-level pages. +- `src/components`: reusable Vue components and layout templates. +- `src/store`: Vuex root store and feature modules. +- `src/breeding-insight/model`: application domain models. +- `src/breeding-insight/dao`: raw API access using `src/util/api`. +- `src/breeding-insight/service`: business logic and response mapping. +- `src/breeding-insight/brapi/model`: generated BrAPI/OpenAPI models. +- `tests/unit`: Jest and Vue Test Utils unit tests. +- `tests/e2e`: Cypress end-to-end tests. +- `task`: Node task wrappers used by npm scripts. + +## Setup + +- Use npm and `package-lock.json`; do not introduce Yarn or pnpm. +- Use `npm install` for local setup, or `npm ci` for clean/install-in-CI style + runs. +- The Dockerfile uses Node 14 and npm 8.12.1. Avoid dependency or syntax changes + that require a newer runtime unless the runtime is intentionally updated. +- `npm run githooks` configures the repository's commit message hook. +- Local environment overrides belong in ignored `.env.local` or `.env.*.local` + files, not in tracked env files. + +## Common Commands + +- `npm run serve`: start the dev server. The default port is `8080`; `PORT` + overrides it. +- `npm run build`: production build. The task wrapper runs npm audit checks + before building. +- `npm run lint`: run Vue CLI ESLint. +- `npm run test:unit`: run existing Jest unit tests only when explicitly + requested. +- `npm run test:e2e`: run existing Cypress e2e tests only when explicitly + requested. +- `npm run test:accessibility`: run pa11y accessibility checks. This expects + the dev server to be running and `task/.pa11yTargets.json` to exist; use it + only when explicitly requested. + +This repository does not add or maintain tests as part of normal feature or bug +work. Do not create new tests, update existing tests, add test-only selectors, +or spend time repairing unrelated test failures unless the user explicitly asks +for test work. Prefer `npm run lint`, `npm run build`, or a focused manual smoke +check for verification when practical. + +## Coding Conventions + +- Preserve the existing Apache 2.0 notice header when editing files that have + it. Add the same header to new `.ts`, `.js`, and `.vue` source files. +- Keep TypeScript strictness in mind. Prefer explicit domain models and local + service/DAO patterns over loose `any` unless surrounding code already forces + it. +- Use the `@/` alias for imports from `src` when consistent with nearby files. +- Vue components commonly use class-style components with + `vue-property-decorator`; match the surrounding component style. +- ESLint requires long-form Vue directives: use `v-bind:` and `v-on:` instead + of shorthand in templates. +- Keep API calls centralized through `src/util/api`. DAOs should make HTTP + requests, while services should handle application mapping and user-facing + error logic. +- `src/breeding-insight/brapi/model` files are generated by Swagger/OpenAPI. + Do not hand-edit them unless the task explicitly calls for it. +- Reuse existing layouts in `src/components/layouts` and visual conventions + from the authenticated `/style-guide` page. Prefer existing Buefy/Bulma + patterns and the configured Feather icon pack. + +## Configuration Notes + +`vue.config.js` derives frontend runtime values from environment variables: + +- `VUE_APP_BI_API_ROOT` defaults to `http://localhost`. +- `VUE_APP_BI_API_V1_PATH` is computed as `${VUE_APP_BI_API_ROOT}/v1`. +- `VUE_APP_LOG_LEVEL` defaults to `error`. +- `VUE_APP_BRAPI_VENDOR_SUBMISSION_ENABLED` and + `VUE_APP_ALTERNATE_AUTHENTICATION_ENABLED` are enabled only when set to the + string `true`. + +`.env.development` maps these values from shell environment variables such as +`API_BASE_URL`, `SANDBOX_MODE`, and `WEB_LOG_LEVEL`. + +## Working Safely + +- Check `git status --short` before editing and do not overwrite unrelated + local changes. +- Do not commit generated output, `node_modules`, `dist`, local env files, IDE + files, Cypress screenshots/videos, or task logs. +- Do not change `package-lock.json` unless dependency changes are intentional. +- Keep changes scoped to the requested behavior. Avoid broad refactors unless + they are required to make the requested change safely. +- If backend behavior is relevant, make the frontend assumption explicit in the + code review or final notes; this repository only contains the web client. diff --git a/src/breeding-insight/dao/GenoDAO.ts b/src/breeding-insight/dao/GenoDAO.ts index 7df9fb97b..f4167ead6 100644 --- a/src/breeding-insight/dao/GenoDAO.ts +++ b/src/breeding-insight/dao/GenoDAO.ts @@ -17,6 +17,8 @@ import * as api from '@/util/api'; import { BiResponse, Response } from '@/breeding-insight/model/BiResponse'; +import { PaginationQuery } from '@/breeding-insight/model/PaginationQuery'; +import { GenotypeImportFilters, GenotypeImportSort } from '@/breeding-insight/model/Sort'; export class GenoDAO { @@ -42,4 +44,25 @@ export class GenoDAO { return new BiResponse(data); } -} \ No newline at end of file + + static async fetchGenotypeImports( + programId: string, + {page, pageSize}: PaginationQuery, + {field, order}: GenotypeImportSort, + filters: GenotypeImportFilters + ): Promise { + const {data} = await api.call({ + url: `${process.env.VUE_APP_BI_API_V1_PATH}/programs/${programId}/geno/imports`, + method: 'get', + params: { + ...filters, + page, + pageSize, + sortField: field, + sortOrder: order + } + }) as Response; + + return new BiResponse(data); + } +} diff --git a/src/breeding-insight/model/GenotypeImport.ts b/src/breeding-insight/model/GenotypeImport.ts new file mode 100644 index 000000000..02e2c8e9c --- /dev/null +++ b/src/breeding-insight/model/GenotypeImport.ts @@ -0,0 +1,41 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class GenotypeImport { + sampleSubmissionId?: string; + projectNameForSampleSubmission?: string; + sampleSubmissionCreatedBy?: string; + genotypingFileName?: string; + genotypingImportDate?: string; + genotypingImportBy?: string; + + constructor({ + sampleSubmissionId, + projectNameForSampleSubmission, + sampleSubmissionCreatedBy, + genotypingFileName, + genotypingImportDate, + genotypingImportBy + }: GenotypeImport = {}) { + this.sampleSubmissionId = sampleSubmissionId; + this.projectNameForSampleSubmission = projectNameForSampleSubmission; + this.sampleSubmissionCreatedBy = sampleSubmissionCreatedBy; + this.genotypingFileName = genotypingFileName; + this.genotypingImportDate = genotypingImportDate; + this.genotypingImportBy = genotypingImportBy; + } +} diff --git a/src/breeding-insight/model/Sort.ts b/src/breeding-insight/model/Sort.ts index f3ce72691..6c6652204 100644 --- a/src/breeding-insight/model/Sort.ts +++ b/src/breeding-insight/model/Sort.ts @@ -218,4 +218,24 @@ export class GermplasmListSort { this.field = field; this.order = order; } -} \ No newline at end of file +} + +export enum GenotypeImportSortField { + ProjectNameForSampleSubmission = 'projectNameForSampleSubmission', + SampleSubmissionCreatedBy = 'sampleSubmissionCreatedBy', + GenotypingFileName = 'genotypingFileName', + GenotypingImportDate = 'genotypingImportDate', + GenotypingImportBy = 'genotypingImportBy' +} + +export type GenotypeImportFilters = Partial>; + +export class GenotypeImportSort { + field: GenotypeImportSortField; + order: SortOrder; + + constructor(field: GenotypeImportSortField, order: SortOrder) { + this.field = field; + this.order = order; + } +} diff --git a/src/breeding-insight/service/GenoService.ts b/src/breeding-insight/service/GenoService.ts index 245569aac..25191a13a 100644 --- a/src/breeding-insight/service/GenoService.ts +++ b/src/breeding-insight/service/GenoService.ts @@ -16,9 +16,12 @@ */ import { GenoDAO } from '@/breeding-insight/dao/GenoDAO'; -import { BiResponse } from '@/breeding-insight/model/BiResponse'; +import { BiResponse, Metadata } from '@/breeding-insight/model/BiResponse'; import { ImportResponse } from '@/breeding-insight/model/import/ImportResponse'; import { GermplasmGenotype } from '@/breeding-insight/model/GermplasmGenotype'; +import { GenotypeImport } from '@/breeding-insight/model/GenotypeImport'; +import { PaginationQuery } from '@/breeding-insight/model/PaginationQuery'; +import { GenotypeImportFilters, GenotypeImportSort } from '@/breeding-insight/model/Sort'; export class GenoService { @@ -47,4 +50,26 @@ export class GenoService { return resp.result as GermplasmGenotype; } -} \ No newline at end of file + + static async fetchGenotypeImports( + programId: string, + paginationQuery: PaginationQuery, + sort: GenotypeImportSort, + filters: GenotypeImportFilters + ): Promise<[GenotypeImport[], Metadata]> { + if (!programId) { + throw 'Program ID not provided'; + } + + const response = await GenoDAO.fetchGenotypeImports(programId, paginationQuery, sort, filters); + const responseData = response.result && response.result.data ? response.result.data : response.result; + + if (!Array.isArray(responseData)) { + return [[], response.metadata]; + } + + const genotypeImports = responseData.map((record: GenotypeImport) => new GenotypeImport(record)); + + return [genotypeImports, response.metadata]; + } +} diff --git a/src/components/layouts/UserSideBarLayout.vue b/src/components/layouts/UserSideBarLayout.vue index 2498cf42c..9c7b9f5e7 100644 --- a/src/components/layouts/UserSideBarLayout.vue +++ b/src/components/layouts/UserSideBarLayout.vue @@ -140,6 +140,16 @@ Sample Management +
  • + + Genotyping + +
  • + + + + diff --git a/src/views/sample-mgmt/SampleManagement.vue b/src/views/sample-mgmt/SampleManagement.vue index fb720caa9..0a104cf2d 100644 --- a/src/views/sample-mgmt/SampleManagement.vue +++ b/src/views/sample-mgmt/SampleManagement.vue @@ -16,89 +16,83 @@ --> @@ -165,4 +159,4 @@ export default class SampleManagement extends Vue { } - \ No newline at end of file +