Skip to content

Commit e96ea9a

Browse files
authored
Merge branch 'dev' into sps_fix_hsts_issue
2 parents 90f1dd2 + 20a8567 commit e96ea9a

40 files changed

+1081
-251
lines changed

.circleci/config.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ jobs:
211211
executor: node
212212
resource_class: large
213213
steps:
214-
- checkout
214+
- checkout:
215+
method: full
215216
- restore_cache:
216217
keys:
217218
- deps-{{ .Branch }}-{{ checksum ".pnp.cjs" }}

integration-tests/slack/slack-notify-channels.json

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -9,66 +9,6 @@
99
{
1010
"name": "dsde-qa",
1111
"id": "C53JYBV9A"
12-
},
13-
{
14-
"name": "dsp-analysis-non-prod-alerts",
15-
"id": "C07RX0CJV0D",
16-
"tests": [
17-
{
18-
"name": "run-analysis"
19-
},
20-
{
21-
"name": "run-rstudio"
22-
},
23-
{
24-
"name": "analysis-context-bar"
25-
},
26-
{
27-
"name": "run-analysis-azure"
28-
},
29-
{
30-
"name": "find-workflow"
31-
},
32-
{
33-
"name": "import-dockstore-workflow"
34-
},
35-
{
36-
"name": "run-workflow"
37-
}
38-
]
39-
},
40-
{
41-
"name": "dsp-tdr",
42-
"id": "CD4HBRFMG",
43-
"tests": [
44-
{
45-
"name": "preview-drs-uri"
46-
}
47-
]
48-
},
49-
{
50-
"name": "dsp-core-services-alerts",
51-
"id": "C07Q8H7F8LV",
52-
"tests": [
53-
{
54-
"name": "preview-drs-uri"
55-
},
56-
{
57-
"name": "import-tdr-snapshot"
58-
},
59-
{
60-
"name": "billing-projects"
61-
},
62-
{
63-
"name": "delete-orphaned-workspaces"
64-
},
65-
{
66-
"name": "register-user"
67-
},
68-
{
69-
"name": "request-access"
70-
}
71-
]
7212
}
7313
]
7414
}

src/import-data/ImportDataOverview.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,25 @@ export interface ImportDataOverviewProps {
4747
export const ImportDataOverview = (props: ImportDataOverviewProps): ReactNode => {
4848
const { importRequest } = props;
4949

50+
const getDisplayUrl = (url: string) => url.replace(/^https?:\/\//, '').split('?')[0];
51+
5052
return div({ style: styles.card }, [
5153
h2({ style: styles.title }, [getTitleForImportRequest(importRequest)]),
5254
'url' in importRequest &&
5355
h(Fragment, [
54-
h3({ style: { fontSize: 16 } }, ['Dataset source:']),
55-
div({ style: { marginTop: '1rem' } }, [`${importRequest.url.href.split('?')[0]}`]),
56+
h3({ style: { fontSize: 16, marginBottom: 2 } }, ['Dataset source:']),
57+
div(
58+
{
59+
style: {
60+
fontSize: 13,
61+
color: colors.dark(0.7),
62+
marginBottom: 8,
63+
marginTop: 0,
64+
},
65+
},
66+
['(For reference only — not a direct link)']
67+
),
68+
div({ style: { marginTop: '1rem', marginBottom: '0.5rem' } }, [getDisplayUrl(importRequest.url.href)]),
5669
]),
5770
h(ImportRequirements, { importRequest }),
5871
]);

src/libs/ajax/teaspoons/Teaspoons.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
StartPipelineResponse,
1313
UserPipelineQuotaDetails,
1414
} from 'src/libs/ajax/teaspoons/teaspoons-models';
15+
import { FilterValues } from 'src/pages/scientificServices/pipelines/tabs/history/controls/TableFilters';
1516

1617
export const Teaspoons = (signal?: AbortSignal) => ({
1718
/* Lists all pipelines available to the user */
@@ -40,17 +41,25 @@ export const Teaspoons = (signal?: AbortSignal) => ({
4041
pageSize: number,
4142
pageNumber: number,
4243
sortProperty?: string,
43-
sortDirection?: string
44+
sortDirection?: string,
45+
filters?: FilterValues
4446
): Promise<GetPipelineRunsResponse> => {
47+
const { status, description, jobId, pipelineName } = filters || {};
48+
4549
const queryString = qs.stringify(
4650
{
4751
pageSize,
4852
pageNumber,
4953
...(sortProperty ? { sortProperty } : {}),
5054
...(sortDirection ? { sortDirection } : {}),
55+
...(status ? { status } : {}),
56+
...(description ? { description } : {}),
57+
...(jobId ? { jobId } : {}),
58+
...(pipelineName ? { pipelineName } : {}),
5159
},
5260
{ addQueryPrefix: true }
5361
);
62+
5463
const res = await fetchTeaspoons(`pipelineruns/v2/pipelineruns${queryString}`, _.merge(authOpts(), { signal }));
5564
return res.json();
5665
},

src/libs/ajax/teaspoons/teaspoons-models.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface Pipeline {
77

88
export interface PipelineInput {
99
name: string;
10-
type: 'FILE' | 'STRING' | 'FLOAT';
10+
type: 'FILE' | 'STRING' | 'FLOAT' | 'BOOLEAN';
1111
isRequired: boolean;
1212
displayName?: string;
1313
description?: string;
@@ -71,6 +71,7 @@ export interface PipelineRun {
7171

7272
export interface GetPipelineRunsResponse {
7373
totalResults: number;
74+
totalFilteredResults: number;
7475
pageToken: string;
7576
results: PipelineRun[];
7677
}

src/pages/scientificServices/NavPaths.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CliAuth } from 'src/pages/scientificServices/cli-auth/CliAuth';
2-
import { About } from 'src/pages/scientificServices/pipelines/views/About';
3-
import { JobHistory } from 'src/pages/scientificServices/pipelines/views/JobHistory';
4-
import { RunJob } from 'src/pages/scientificServices/pipelines/views/RunJob';
2+
import { About } from 'src/pages/scientificServices/pipelines/tabs/about/About';
3+
import { JobHistory } from 'src/pages/scientificServices/pipelines/tabs/history/JobHistory';
4+
import { RunJob } from 'src/pages/scientificServices/pipelines/tabs/run/RunJob';
55

66
export const navPaths = [
77
// For now, redirect /pipelines to the Imputation home page
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { render } from '@testing-library/react';
2+
import React from 'react';
3+
import { DocsKey, ZendeskLink, zendeskUrl } from 'src/pages/scientificServices/pipelines/common/zendeskUtils';
4+
5+
describe('zendeskUtils', () => {
6+
describe('zendeskUrl', () => {
7+
it('returns the correct URL for INPUT_REQ', () => {
8+
expect(zendeskUrl(DocsKey.INPUT_REQ)).toBe(
9+
'https://broadscientificservices.zendesk.com/hc/en-us/articles/40161675448859'
10+
);
11+
});
12+
13+
it('returns the default URL for an unknown DocsKey', () => {
14+
// @ts-expect-error Testing invalid key
15+
expect(zendeskUrl('UNKNOWN_KEY')).toBe(
16+
'https://broadscientificservices.zendesk.com/hc/en-us/sections/39901025462171' // Getting Started URL
17+
);
18+
});
19+
});
20+
21+
describe('ZendeskLink', () => {
22+
it('renders correctly with given children and href', () => {
23+
const { getByText } = render(
24+
<ZendeskLink docsKey={DocsKey.QUOTA_DETAILS} additionalStyle={{ fontWeight: 'italics' }}>
25+
Link to my excellent documentation
26+
</ZendeskLink>
27+
);
28+
29+
const linkElement = getByText('Link to my excellent documentation');
30+
expect(linkElement).toBeInTheDocument();
31+
expect(linkElement).toHaveAttribute(
32+
'href',
33+
'https://broadscientificservices.zendesk.com/hc/en-us/articles/39903092619035'
34+
);
35+
expect(linkElement).toHaveStyle('font-weight: italics');
36+
});
37+
});
38+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Enum representing different documentation keys
2+
import React from 'react';
3+
4+
export enum DocsKey {
5+
GETTING_STARTED = 'GETTING_STARTED',
6+
ABOUT_SERVICE = 'ABOUT_SERVICE',
7+
INPUT_REQ = 'INPUT_REQ',
8+
QUOTA_DETAILS = 'QUOTA_DETAILS',
9+
}
10+
11+
// Mapping of documentation keys to their respective Zendesk URLs
12+
const ZENDESK_PAGES: Record<DocsKey, string> = {
13+
GETTING_STARTED: 'https://broadscientificservices.zendesk.com/hc/en-us/sections/39901025462171',
14+
ABOUT_SERVICE: 'https://broadscientificservices.zendesk.com/hc/en-us/articles/39901941351323',
15+
INPUT_REQ: 'https://broadscientificservices.zendesk.com/hc/en-us/articles/40161675448859',
16+
QUOTA_DETAILS: 'https://broadscientificservices.zendesk.com/hc/en-us/articles/39903092619035',
17+
};
18+
19+
// Retrieve the Zendesk URL based on the provided documentation key
20+
export const zendeskUrl = (key: DocsKey): string => {
21+
// typescript should make sure all keys are valid, but just in case, default to the home page
22+
return ZENDESK_PAGES[key] ?? ZENDESK_PAGES.GETTING_STARTED;
23+
};
24+
25+
// Renders a component with link to the specified Zendesk documentation page
26+
export const ZendeskLink = ({
27+
docsKey,
28+
additionalStyle,
29+
children,
30+
}: {
31+
docsKey: DocsKey;
32+
additionalStyle?;
33+
children: React.ReactNode;
34+
}) => {
35+
return (
36+
<a
37+
href={zendeskUrl(docsKey)}
38+
target='_blank'
39+
style={{ color: '#46A3E9', textDecoration: 'underline', ...additionalStyle }}
40+
rel='noreferrer'
41+
>
42+
{children}
43+
</a>
44+
);
45+
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { useEffect, useState } from 'react';
2+
import { Teaspoons } from 'src/libs/ajax/teaspoons/Teaspoons';
3+
import { Pipeline } from 'src/libs/ajax/teaspoons/teaspoons-models';
4+
import { notify } from 'src/libs/notifications';
5+
import { useCancellation } from 'src/libs/react-utils';
6+
7+
export interface UsePipelinesListResult {
8+
pipelines: Pipeline[];
9+
isLoading: boolean;
10+
error: Error | undefined;
11+
}
12+
13+
export const usePipelinesList = (): UsePipelinesListResult => {
14+
const signal = useCancellation();
15+
const [pipelines, setPipelines] = useState<Pipeline[]>([]);
16+
const [isLoading, setIsLoading] = useState<boolean>(true);
17+
const [error, setError] = useState<Error | undefined>(undefined);
18+
19+
const fetchPipelines = async () => {
20+
setIsLoading(true);
21+
setError(undefined);
22+
23+
try {
24+
const response = await Teaspoons(signal).getPipelines();
25+
setPipelines(response.results);
26+
} catch (err) {
27+
const error = err instanceof Error ? err : new Error('Failed to fetch pipelines');
28+
setError(error);
29+
notify('error', error.message);
30+
setPipelines([]);
31+
} finally {
32+
setIsLoading(false);
33+
}
34+
};
35+
36+
useEffect(() => {
37+
fetchPipelines();
38+
}, [signal]); // eslint-disable-line react-hooks/exhaustive-deps
39+
40+
return {
41+
pipelines,
42+
isLoading,
43+
error,
44+
};
45+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Spinner } from '@terra-ui-packages/components';
2+
import React from 'react';
3+
import FooterWrapper from 'src/components/FooterWrapper';
4+
import { pipelinesTopBar } from 'src/pages/scientificServices/pipelines/common/scientific-services-common';
5+
import { DocsKey, ZendeskLink } from 'src/pages/scientificServices/pipelines/common/zendeskUtils';
6+
import { usePipelinesList } from 'src/pages/scientificServices/pipelines/hooks/usePipelinesList';
7+
import { AoUStylizedString } from 'src/pages/scientificServices/pipelines/utils/AoUStylizedString';
8+
9+
export const About = () => {
10+
const { isLoading, error, pipelines } = usePipelinesList();
11+
12+
return (
13+
<FooterWrapper alwaysShow>
14+
{pipelinesTopBar('about')}
15+
<div style={{ marginLeft: '2rem', marginTop: '1rem' }}>
16+
<h1>Scientific Services from the Broad Data Sciences Platform</h1>
17+
<h2 style={{ marginTop: '2rem' }}>Pipelines</h2>
18+
19+
{isLoading && <Spinner />}
20+
21+
{error && <div style={{ color: 'red' }}>{error.message}</div>}
22+
23+
{pipelines?.map((pipeline) => (
24+
<div key={pipeline.pipelineName}>
25+
<h3>
26+
<AoUStylizedString text={pipeline.displayName} />
27+
</h3>
28+
<div style={{ width: '50%' }}>
29+
{pipeline.description ? (
30+
<AoUStylizedString text={pipeline.description} />
31+
) : (
32+
<em>No description available</em>
33+
)}
34+
</div>
35+
</div>
36+
))}
37+
38+
<h2 style={{ marginTop: '2rem' }}>User Documentation</h2>
39+
<div style={{ marginTop: '1rem' }}>
40+
<ZendeskLink docsKey={DocsKey.GETTING_STARTED} additionalStyle={{ fontWeight: 'bold' }}>
41+
Get Started
42+
</ZendeskLink>
43+
</div>
44+
<div style={{ marginTop: '1rem' }}>
45+
<ZendeskLink docsKey={DocsKey.ABOUT_SERVICE} additionalStyle={{ fontWeight: 'bold' }}>
46+
About this Service
47+
</ZendeskLink>
48+
</div>
49+
</div>
50+
</FooterWrapper>
51+
);
52+
};

0 commit comments

Comments
 (0)