Skip to content

Commit 9828592

Browse files
feat: added anvil data dictionary #4131 (#4382)
1 parent 95368c5 commit 9828592

File tree

10 files changed

+196
-31
lines changed

10 files changed

+196
-31
lines changed

e2e/testFunctions.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,16 @@ export async function testUrl(
8989
// Go to the selected tab
9090
await page.goto(tab.url);
9191
// Check that the selected tab appears selected and the other tabs appear deselected
92-
await expect(
93-
page.getByRole("tab").getByText(tab.tabName, { exact: true })
94-
).toHaveAttribute("aria-selected", "true");
92+
await expect(getTabByText(page, tab.tabName)).toHaveAttribute(
93+
"aria-selected",
94+
"true"
95+
);
9596
for (const otherTab of otherTabs) {
9697
if (otherTab.tabName !== tab.tabName) {
97-
await expect(
98-
page.getByRole("tab").getByText(otherTab.tabName)
99-
).toHaveAttribute("aria-selected", "false");
98+
await expect(getTabByText(page, otherTab.tabName)).toHaveAttribute(
99+
"aria-selected",
100+
"false"
101+
);
100102
}
101103
}
102104
}
@@ -115,12 +117,9 @@ export async function testTab(
115117
// Run the "Expect each tab to become selected, to go to the correct url, and to show all of its columns when selected" test
116118
await page.goto(startTab.url);
117119
await expect(getFirstRowNthColumnCellLocator(page, 1)).toBeVisible();
118-
await page
119-
.getByRole("tab")
120-
.getByText(endTab.tabName, { exact: true })
121-
.click();
120+
await getTabByText(page, endTab.tabName).click();
122121
await expect(page).toHaveURL(endTab.url);
123-
await expect(page.getByRole("tab").getByText(endTab.tabName)).toHaveAttribute(
122+
await expect(getTabByText(page, endTab.tabName)).toHaveAttribute(
124123
"aria-selected",
125124
"true"
126125
);
@@ -392,7 +391,7 @@ export async function testFilterPresence(
392391
): Promise<void> {
393392
// Goto the selected tab
394393
await page.goto(tab.url);
395-
await expect(page.getByRole("tab").getByText(tab.tabName)).toBeVisible();
394+
await expect(getTabByText(page, tab.tabName)).toBeVisible();
396395
for (const filterName of filterNames) {
397396
// Check that each filter is visible and clickable
398397
await expect(page.getByText(filterRegex(filterName))).toBeVisible();
@@ -524,10 +523,7 @@ export async function testFilterPersistence(
524523
await expect(getFirstRowNthColumnCellLocator(page, 0)).toBeVisible();
525524
// For each tab, check that the selected filter is still checked
526525
for (const tab of tabOrder.slice(1)) {
527-
await page
528-
.getByRole("tab")
529-
.getByText(tab.tabName, { exact: true })
530-
.dispatchEvent("click");
526+
await getTabByText(page, tab.tabName).dispatchEvent("click");
531527
await expect(page.getByText(filterRegex(testFilterName))).toBeVisible();
532528
await page.getByText(filterRegex(testFilterName)).dispatchEvent("click");
533529
await page.waitForLoadState("load");
@@ -538,10 +534,7 @@ export async function testFilterPersistence(
538534
}
539535
// Return to the start tab and confirm that the filter stays checked and that some content is visible
540536
// (dispatchevent necessary because the filter menu sometimes interrupts the click event)
541-
await page
542-
.getByRole("tab")
543-
.getByText(tabOrder[0].tabName, { exact: true })
544-
.dispatchEvent("click");
537+
await getTabByText(page, tabOrder[0].tabName).dispatchEvent("click");
545538
await expect(getFirstRowNthColumnCellLocator(page, 0)).toBeVisible();
546539
await page.getByText(filterRegex(testFilterName)).dispatchEvent("click");
547540
const previouslySelected = getNthFilterOptionLocator(page, filterIndex);
@@ -1147,9 +1140,10 @@ export async function testPaginationContent(
11471140
): Promise<void> {
11481141
// Navigate to the correct tab
11491142
await page.goto(tab.url);
1150-
await expect(
1151-
page.getByRole("tab").getByText(tab.tabName, { exact: true })
1152-
).toHaveAttribute("aria-selected", "true");
1143+
await expect(getTabByText(page, tab.tabName)).toHaveAttribute(
1144+
"aria-selected",
1145+
"true"
1146+
);
11531147

11541148
const firstElementTextLocator = getFirstRowNthColumnCellLocator(page, 0);
11551149

@@ -1212,4 +1206,16 @@ export async function testPaginationContent(
12121206
}
12131207
}
12141208

1209+
/**
1210+
* Return the tab with the specified text.
1211+
* @param page - a Playwright page object.
1212+
* @param tabText - the tab text to search for.
1213+
* @returns - a Playwright locator object for the tab with the specified text.
1214+
*/
1215+
export const getTabByText = (page: Page, tabText: string): Locator => {
1216+
return page.locator("[role='tab']", {
1217+
has: page.locator(`text="${tabText}"`),
1218+
});
1219+
};
1220+
12151221
/* eslint-enable sonarjs/no-duplicate-string -- Checking duplicate strings again*/

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"check-system-status:anvil-cmg": "esrun e2e/anvil/anvil-check-system-status.ts"
3333
},
3434
"dependencies": {
35-
"@databiosphere/findable-ui": "21.1.0",
35+
"@databiosphere/findable-ui": "21.3.0",
3636
"@emotion/react": "^11.13.3",
3737
"@emotion/styled": "^11.13.0",
3838
"@mdx-js/loader": "^3.0.1",

site-config/anvil-cmg/dev/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { donorsEntityConfig } from "./index/donorsEntityConfig";
1818
import { filesEntityConfig } from "./index/filesEntityConfig";
1919
import { summary } from "./index/summary";
2020
import { floating } from "./layout/floating";
21+
import dataDictionary from "./dataDictionary/data-dictionary.json";
2122

2223
// Template constants
2324
const APP_TITLE = "AnVIL Data Explorer";
@@ -129,6 +130,7 @@ export function makeConfig(
129130
key: "anvil-cmg",
130131
},
131132
contentDir: "anvil-cmg",
133+
dataDictionary,
132134
dataSource: {
133135
defaultListParams: {
134136
size: "25",
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
{
2+
"classes": [
3+
{
4+
"name": "Activity",
5+
"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.).",
6+
"key": "activities",
7+
"label": "Activity",
8+
"attributes": [
9+
{
10+
"key": "activities.activity_type",
11+
"label": "Activity Type",
12+
"description": "A reference to the type of activity, preferably using an identifier in a recommended standard ontology."
13+
},
14+
{
15+
"key": "activities.data_modality",
16+
"label": "Data Modality",
17+
"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.)."
18+
}
19+
]
20+
},
21+
{
22+
"name": "BioSample",
23+
"description": "Contains information about the sample(s) included in the dataset.",
24+
"key": "biosamples",
25+
"label": "BioSample",
26+
"attributes": [
27+
{
28+
"key": "biosamples.anatomical_site",
29+
"label": "Anatomical Site",
30+
"description": "A human-readable reference to the site within the organism from which the biosample was taken."
31+
},
32+
{
33+
"key": "biosamples.biosample_id",
34+
"label": "BioSample Id",
35+
"description": "A unique identifier for the biosample."
36+
},
37+
{
38+
"key": "biosamples.biosample_type",
39+
"label": "BioSample Type",
40+
"description": "A human-readable reference to the type of biosample represented by the record."
41+
}
42+
]
43+
},
44+
{
45+
"name": "Dataset",
46+
"description": "A dataset is a collection of related files and associated metadata that share the same consent and access permissions.",
47+
"key": "datasets",
48+
"label": "Dataset",
49+
"attributes": [
50+
{
51+
"key": "accessible",
52+
"label": "Access",
53+
"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."
54+
},
55+
{
56+
"key": "datasets.accessible",
57+
"label": "Access",
58+
"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."
59+
},
60+
{
61+
"key": "datasets.consent_group",
62+
"label": "Consent Group",
63+
"description": "Consent group or consent groups related to a dataset."
64+
},
65+
{
66+
"key": "datasets.registered_identifier",
67+
"label": "Registered Identifier",
68+
"description": "Unique ID used to identify this dataset in an external database. For example, the DUOS identifier for datasets registered in DUOS."
69+
},
70+
{
71+
"key": "datasets.title",
72+
"label": "Title",
73+
"description": "A human-readable property that identifies the dataset which the dataset belongs to."
74+
},
75+
{
76+
"key": "diagnoses.disease",
77+
"label": "Diagnosis",
78+
"description": "A human-readable property that identifies a disease or condition has been reported in this entity."
79+
}
80+
]
81+
},
82+
{
83+
"name": "Diagnosis",
84+
"description": "Contains information about conditions or diagnoses related to the donor of a biosample.",
85+
"key": "diagnoses",
86+
"label": "Diagnosis",
87+
"attributes": [
88+
{
89+
"key": "diagnoses.disease",
90+
"label": "Diagnosis",
91+
"description": "A human-readable property that identifies a disease or condition has been reported in this entity."
92+
}
93+
]
94+
},
95+
{
96+
"name": "Donor",
97+
"description": "Demographic and phenotypic information about the donor.",
98+
"key": "donors",
99+
"label": "Donor",
100+
"attributes": [
101+
{
102+
"key": "donors.donor_id",
103+
"label": "Donor Id",
104+
"description": "A unique identifier for the donor."
105+
},
106+
{
107+
"key": "donors.organism_type",
108+
"label": "Organism Type",
109+
"description": "A human-readable reference to the organism type."
110+
},
111+
{
112+
"key": "donors.phenotypic_sex",
113+
"label": "Phenotypic Sex",
114+
"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]"
115+
},
116+
{
117+
"key": "donors.reported_ethnicity",
118+
"label": "Reported Ethnicity",
119+
"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"
120+
}
121+
]
122+
},
123+
{
124+
"name": "File",
125+
"description": "Information for files associated with the dataset.",
126+
"key": "files",
127+
"label": "File",
128+
"attributes": [
129+
{
130+
"key": "drs_uri",
131+
"label": "DRS URI",
132+
"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."
133+
},
134+
{
135+
"key": "files.file_format",
136+
"label": "File Format",
137+
"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.)"
138+
},
139+
{
140+
"key": "files.file_name",
141+
"label": "File Name",
142+
"description": "The name of the file."
143+
},
144+
{
145+
"key": "files.file_size",
146+
"label": "File Size",
147+
"description": "Size of file in megabytes."
148+
}
149+
]
150+
}
151+
]
152+
}

site-config/anvil-cmg/dev/index/activitiesEntityConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const activitiesEntityConfig: EntityConfig<ActivitiesResponse> = {
2727
top: [],
2828
},
2929
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
30+
key: "activities",
3031
label: "Activities",
3132
list: {
3233
columns: [

site-config/anvil-cmg/dev/index/biosamplesEntityConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const biosamplesEntityConfig: EntityConfig<BioSamplesResponse> = {
2727
top: [],
2828
},
2929
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
30+
key: "biosamples",
3031
label: "BioSamples",
3132
list: {
3233
columns: [

site-config/anvil-cmg/dev/index/datasetsEntityConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const datasetsEntityConfig: EntityConfig<DatasetsResponse> = {
4444
getId: getDatasetEntryId,
4545
getTitle: getTitle,
4646
hideTabs: true,
47+
key: "datasets",
4748
label: "Datasets",
4849
list: {
4950
columns: [

site-config/anvil-cmg/dev/index/donorsEntityConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const donorsEntityConfig: EntityConfig<DonorsResponse> = {
2727
top: [],
2828
},
2929
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
30+
key: "donors",
3031
label: "Donors",
3132
list: {
3233
columns: [

site-config/anvil-cmg/dev/index/filesEntityConfig.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const filesEntityConfig: EntityConfig<FilesResponse> = {
4040
top: [],
4141
},
4242
exploreMode: EXPLORE_MODE.SS_FETCH_SS_FILTERING,
43+
key: "files",
4344
label: "Files",
4445
list: {
4546
columns: [

0 commit comments

Comments
 (0)