Skip to content

Commit

Permalink
feat: added anvil data dictionary #4131 (#4382)
Browse files Browse the repository at this point in the history
  • Loading branch information
MillenniumFalconMechanic authored Feb 19, 2025
1 parent 95368c5 commit 9828592
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 31 deletions.
52 changes: 29 additions & 23 deletions e2e/testFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,16 @@ export async function testUrl(
// Go to the selected tab
await page.goto(tab.url);
// Check that the selected tab appears selected and the other tabs appear deselected
await expect(
page.getByRole("tab").getByText(tab.tabName, { exact: true })
).toHaveAttribute("aria-selected", "true");
await expect(getTabByText(page, tab.tabName)).toHaveAttribute(
"aria-selected",
"true"
);
for (const otherTab of otherTabs) {
if (otherTab.tabName !== tab.tabName) {
await expect(
page.getByRole("tab").getByText(otherTab.tabName)
).toHaveAttribute("aria-selected", "false");
await expect(getTabByText(page, otherTab.tabName)).toHaveAttribute(
"aria-selected",
"false"
);
}
}
}
Expand All @@ -115,12 +117,9 @@ export async function testTab(
// Run the "Expect each tab to become selected, to go to the correct url, and to show all of its columns when selected" test
await page.goto(startTab.url);
await expect(getFirstRowNthColumnCellLocator(page, 1)).toBeVisible();
await page
.getByRole("tab")
.getByText(endTab.tabName, { exact: true })
.click();
await getTabByText(page, endTab.tabName).click();
await expect(page).toHaveURL(endTab.url);
await expect(page.getByRole("tab").getByText(endTab.tabName)).toHaveAttribute(
await expect(getTabByText(page, endTab.tabName)).toHaveAttribute(
"aria-selected",
"true"
);
Expand Down Expand Up @@ -392,7 +391,7 @@ export async function testFilterPresence(
): Promise<void> {
// Goto the selected tab
await page.goto(tab.url);
await expect(page.getByRole("tab").getByText(tab.tabName)).toBeVisible();
await expect(getTabByText(page, tab.tabName)).toBeVisible();
for (const filterName of filterNames) {
// Check that each filter is visible and clickable
await expect(page.getByText(filterRegex(filterName))).toBeVisible();
Expand Down Expand Up @@ -524,10 +523,7 @@ export async function testFilterPersistence(
await expect(getFirstRowNthColumnCellLocator(page, 0)).toBeVisible();
// For each tab, check that the selected filter is still checked
for (const tab of tabOrder.slice(1)) {
await page
.getByRole("tab")
.getByText(tab.tabName, { exact: true })
.dispatchEvent("click");
await getTabByText(page, tab.tabName).dispatchEvent("click");
await expect(page.getByText(filterRegex(testFilterName))).toBeVisible();
await page.getByText(filterRegex(testFilterName)).dispatchEvent("click");
await page.waitForLoadState("load");
Expand All @@ -538,10 +534,7 @@ export async function testFilterPersistence(
}
// Return to the start tab and confirm that the filter stays checked and that some content is visible
// (dispatchevent necessary because the filter menu sometimes interrupts the click event)
await page
.getByRole("tab")
.getByText(tabOrder[0].tabName, { exact: true })
.dispatchEvent("click");
await getTabByText(page, tabOrder[0].tabName).dispatchEvent("click");
await expect(getFirstRowNthColumnCellLocator(page, 0)).toBeVisible();
await page.getByText(filterRegex(testFilterName)).dispatchEvent("click");
const previouslySelected = getNthFilterOptionLocator(page, filterIndex);
Expand Down Expand Up @@ -1147,9 +1140,10 @@ export async function testPaginationContent(
): Promise<void> {
// Navigate to the correct tab
await page.goto(tab.url);
await expect(
page.getByRole("tab").getByText(tab.tabName, { exact: true })
).toHaveAttribute("aria-selected", "true");
await expect(getTabByText(page, tab.tabName)).toHaveAttribute(
"aria-selected",
"true"
);

const firstElementTextLocator = getFirstRowNthColumnCellLocator(page, 0);

Expand Down Expand Up @@ -1212,4 +1206,16 @@ export async function testPaginationContent(
}
}

/**
* Return the tab with the specified text.
* @param page - a Playwright page object.
* @param tabText - the tab text to search for.
* @returns - a Playwright locator object for the tab with the specified text.
*/
export const getTabByText = (page: Page, tabText: string): Locator => {
return page.locator("[role='tab']", {
has: page.locator(`text="${tabText}"`),
});
};

/* eslint-enable sonarjs/no-duplicate-string -- Checking duplicate strings again*/
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"check-system-status:anvil-cmg": "esrun e2e/anvil/anvil-check-system-status.ts"
},
"dependencies": {
"@databiosphere/findable-ui": "21.1.0",
"@databiosphere/findable-ui": "21.3.0",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@mdx-js/loader": "^3.0.1",
Expand Down
2 changes: 2 additions & 0 deletions site-config/anvil-cmg/dev/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { donorsEntityConfig } from "./index/donorsEntityConfig";
import { filesEntityConfig } from "./index/filesEntityConfig";
import { summary } from "./index/summary";
import { floating } from "./layout/floating";
import dataDictionary from "./dataDictionary/data-dictionary.json";

// Template constants
const APP_TITLE = "AnVIL Data Explorer";
Expand Down Expand Up @@ -129,6 +130,7 @@ export function makeConfig(
key: "anvil-cmg",
},
contentDir: "anvil-cmg",
dataDictionary,
dataSource: {
defaultListParams: {
size: "25",
Expand Down
152 changes: 152 additions & 0 deletions site-config/anvil-cmg/dev/dataDictionary/data-dictionary.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
{
"classes": [
{
"name": "Activity",
"description": "A table describing the activities performed on biosamples or files that resulted in the generation of additional files. The anvil_activity table is used to capture activity provenance that does not fit into the other activity tables described in the schema (such as file indexing, file checksums, etc.).",
"key": "activities",
"label": "Activity",
"attributes": [
{
"key": "activities.activity_type",
"label": "Activity Type",
"description": "A reference to the type of activity, preferably using an identifier in a recommended standard ontology."
},
{
"key": "activities.data_modality",
"label": "Data Modality",
"description": "A table describing the activities performed on biosamples or files that resulted in the generation of additional files. The anvil_activity table is used to capture activity provenance that does not fit into the other activity tables described in the schema (such as file indexing, file checksums, etc.)."
}
]
},
{
"name": "BioSample",
"description": "Contains information about the sample(s) included in the dataset.",
"key": "biosamples",
"label": "BioSample",
"attributes": [
{
"key": "biosamples.anatomical_site",
"label": "Anatomical Site",
"description": "A human-readable reference to the site within the organism from which the biosample was taken."
},
{
"key": "biosamples.biosample_id",
"label": "BioSample Id",
"description": "A unique identifier for the biosample."
},
{
"key": "biosamples.biosample_type",
"label": "BioSample Type",
"description": "A human-readable reference to the type of biosample represented by the record."
}
]
},
{
"name": "Dataset",
"description": "A dataset is a collection of related files and associated metadata that share the same consent and access permissions.",
"key": "datasets",
"label": "Dataset",
"attributes": [
{
"key": "accessible",
"label": "Access",
"description": "Indicates whether the user has permission to access the given dataset. For open-access datasets, this value will always be \"Granted\". For controlled-access datasets, it will be \"Required\" if the user is not logged in. If the user is logged in, the value will reflect their specific access permissions for the dataset."
},
{
"key": "datasets.accessible",
"label": "Access",
"description": "Indicates whether the user has permission to access the given dataset. For open-access datasets, this value will always be \"Granted\". For controlled-access datasets, it will be \"Required\" if the user is not logged in. If the user is logged in, the value will reflect their specific access permissions for the dataset."
},
{
"key": "datasets.consent_group",
"label": "Consent Group",
"description": "Consent group or consent groups related to a dataset."
},
{
"key": "datasets.registered_identifier",
"label": "Registered Identifier",
"description": "Unique ID used to identify this dataset in an external database. For example, the DUOS identifier for datasets registered in DUOS."
},
{
"key": "datasets.title",
"label": "Title",
"description": "A human-readable property that identifies the dataset which the dataset belongs to."
},
{
"key": "diagnoses.disease",
"label": "Diagnosis",
"description": "A human-readable property that identifies a disease or condition has been reported in this entity."
}
]
},
{
"name": "Diagnosis",
"description": "Contains information about conditions or diagnoses related to the donor of a biosample.",
"key": "diagnoses",
"label": "Diagnosis",
"attributes": [
{
"key": "diagnoses.disease",
"label": "Diagnosis",
"description": "A human-readable property that identifies a disease or condition has been reported in this entity."
}
]
},
{
"name": "Donor",
"description": "Demographic and phenotypic information about the donor.",
"key": "donors",
"label": "Donor",
"attributes": [
{
"key": "donors.donor_id",
"label": "Donor Id",
"description": "A unique identifier for the donor."
},
{
"key": "donors.organism_type",
"label": "Organism Type",
"description": "A human-readable reference to the organism type."
},
{
"key": "donors.phenotypic_sex",
"label": "Phenotypic Sex",
"description": "A reference to the BiologicalSex of the Donor organism. \"An organismal quality inhering in a bearer by virtue of the bearer's physical expression of sexual characteristics. [PATO_0001894]"
},
{
"key": "donors.reported_ethnicity",
"label": "Reported Ethnicity",
"description": "A property that relects a Human Donor's reported ethnic origins. Note this may contain both Race and Ethnicity information as define by the US Department of Interior (DOI) https://www.doi.gov/pmb/eeo/directives/race-data"
}
]
},
{
"name": "File",
"description": "Information for files associated with the dataset.",
"key": "files",
"label": "File",
"attributes": [
{
"key": "drs_uri",
"label": "DRS URI",
"description": "A Uniform Resource Identifier (URI) that follows the GA4GH Data Repository Service (DRS) specification. It provides a standardized way to reference and access digital objects, such as files, within compliant data repositories. The DRS URI enables interoperability across systems by allowing authorized users and tools to retrieve dataset contents through a consistent interface."
},
{
"key": "files.file_format",
"label": "File Format",
"description": "An indication of the format of an electronic file; include the full file extension including compression extensions. Usually aligns with file extension (e.g. bam, sam, text, csv, etc.)"
},
{
"key": "files.file_name",
"label": "File Name",
"description": "The name of the file."
},
{
"key": "files.file_size",
"label": "File Size",
"description": "Size of file in megabytes."
}
]
}
]
}
1 change: 1 addition & 0 deletions site-config/anvil-cmg/dev/index/activitiesEntityConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const activitiesEntityConfig: EntityConfig<ActivitiesResponse> = {
top: [],
},
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
key: "activities",
label: "Activities",
list: {
columns: [
Expand Down
1 change: 1 addition & 0 deletions site-config/anvil-cmg/dev/index/biosamplesEntityConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const biosamplesEntityConfig: EntityConfig<BioSamplesResponse> = {
top: [],
},
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
key: "biosamples",
label: "BioSamples",
list: {
columns: [
Expand Down
1 change: 1 addition & 0 deletions site-config/anvil-cmg/dev/index/datasetsEntityConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const datasetsEntityConfig: EntityConfig<DatasetsResponse> = {
getId: getDatasetEntryId,
getTitle: getTitle,
hideTabs: true,
key: "datasets",
label: "Datasets",
list: {
columns: [
Expand Down
1 change: 1 addition & 0 deletions site-config/anvil-cmg/dev/index/donorsEntityConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const donorsEntityConfig: EntityConfig<DonorsResponse> = {
top: [],
},
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
key: "donors",
label: "Donors",
list: {
columns: [
Expand Down
1 change: 1 addition & 0 deletions site-config/anvil-cmg/dev/index/filesEntityConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const filesEntityConfig: EntityConfig<FilesResponse> = {
top: [],
},
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
key: "files",
label: "Files",
list: {
columns: [
Expand Down

0 comments on commit 9828592

Please sign in to comment.