Skip to content

Commit

Permalink
Merge pull request #180 from CanDIG/stable-candidate-v4.0.0
Browse files Browse the repository at this point in the history
v4.0.0: MoH Data Model v3
  • Loading branch information
daisieh authored Oct 4, 2024
2 parents d6b3c9e + a0edc7f commit 4398b13
Show file tree
Hide file tree
Showing 39 changed files with 4,283 additions and 3,445 deletions.
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ REACT_APP_BASE_NAME=''
REACT_APP_SITE_LOCATION = ''
REACT_APP_HTSGET_SERVER = ''
REACT_APP_INGEST_SERVER = ''
DISABLE_ESLINT_PLUGIN=false
GENERATE_SOURCEMAP=false
4 changes: 3 additions & 1 deletion .env.docker
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ REACT_APP_BASE_NAME=${REACT_APP_BASE_NAME}
REACT_APP_SITE_LOCATION = '${REACT_APP_SITE_LOCATION}'
REACT_APP_HTSGET_SERVER ='${REACT_APP_HTSGET_SERVER}'
REACT_APP_CANDIG_VERSION='${REACT_APP_CANDIG_VERSION}'
GENERATE_SOURCEMAP=false
REACT_APP_AGGREGATE_COUNT_THRESHOLD='${AGGREGATE_COUNT_THRESHOLD}'
DISABLE_ESLINT_PLUGIN='${DISABLE_ESLINT}'
GENERATE_SOURCEMAP=false
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ REACT_APP_FEDERATION_API_SERVER=''
REACT_APP_BASE_NAME=''
REACT_APP_SITE_LOCATION = ''
GENERATE_SOURCEMAP=false
DISABLE_ESLINT_PLUGIN=true
REACT_APP_HTSGET_SERVER = ''
31 changes: 17 additions & 14 deletions .github/workflows/candig-dispatch.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: Submodule PR
on:
push:
pull_request:
branches: [develop]
types: [closed]
jobs:
CanDIG-dispatch:
runs-on: ubuntu-latest
Expand All @@ -10,21 +11,23 @@ jobs:
CHECKOUT_BRANCH: 'develop'
PR_AGAINST_BRANCH: 'develop'
OWNER: 'CanDIG'
if: github.event.pull_request.merged == true
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: get PR data
uses: actions/github-script@v7
id: get_pr_data
with:
script: |
return (
await github.rest.repos.listPullRequestsAssociatedWithCommit({
commit_sha: context.sha,
owner: context.repo.owner,
repo: context.repo.repo,
})
).data[0];
shell: python
run: |
import json
import os
with open('${{ github.event_path }}') as fh:
event = json.load(fh)
escaped = event['pull_request']['title'].replace("'", '"')
pr_number = event["number"]
print(escaped)
with open(os.environ['GITHUB_ENV'], 'a') as fh:
print(f'PR_TITLE={escaped}', file=fh)
print(f'PR_NUMBER={pr_number}', file=fh)
- name: Create PR in CanDIGv2
id: make_pr
uses: CanDIG/github-action-pr-expanded@v4
Expand All @@ -33,7 +36,7 @@ jobs:
parent_repository: ${{ env.PARENT_REPOSITORY }}
checkout_branch: ${{ env.CHECKOUT_BRANCH}}
pr_against_branch: ${{ env.PR_AGAINST_BRANCH }}
pr_title: '${{ github.repository }} merging: ${{ fromJson(steps.get_pr_data.outputs.result).title }}'
pr_description: "PR triggered by update to develop branch on ${{ github.repository }}. Commit hash: `${{ github.sha }}`. PR link: [#${{ fromJson(steps.get_pr_data.outputs.result).number }}](https://github.com/${{ github.repository }}/pull/${{ fromJson(steps.get_pr_data.outputs.result).number }})"
pr_title: "${{ github.repository }} merging: ${{ env.PR_TITLE }}"
pr_description: "PR triggered by update to develop branch on ${{ github.repository }}. Commit hash: `${{ github.sha }}`. PR link: [#${{ env.PR_NUMBER }}](https://github.com/${{ github.repository }}/pull/${{ env.PR_NUMBER }})"
owner: ${{ env.OWNER }}
submodule_path: lib/candig-data-portal/candig-data-portal
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ RUN apk update && apk add gettext

RUN apk add --no-cache git curl vim bash

RUN npm install -g [email protected]

RUN addgroup -S candig && adduser -S candig -G candig

COPY --chown=candig:candig . /app/candig-data-portal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ A data analytics and visualization portal for CanDIG Services. Is built off the
## Setup Development Server

- Node: v21.7.0
- npm: 10.5.0
- npm: 10.8.0
- MUI: V5

There was a migration from V4 - V5 of MUI following https://mui.com/material-ui/guides/migration-v4/
Expand Down
1 change: 1 addition & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
set -Euo pipefail

if [[ -f "initial_setup" ]]; then
[[ $DEBUG_MODE = 1 ]] && export DISABLE_ESLINT="false" || export DISABLE_ESLINT="true"
envsubst < .env.docker > .env.development
envsubst < .env.docker > .env.production
rm initial_setup
Expand Down
5,508 changes: 2,890 additions & 2,618 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
"highcharts": "^11.2.0",
"highcharts-react-official": "^3.2.1",
"history": "^5.3.0",
"i": "^0.3.7",
"material-ui-popup-state": "^5.0.10",
"npm": "^10.2.5",
"npm": "^10.8.0",
"papaparse": "^5.4.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
Expand Down
Binary file added src/assets/images/users/siteLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const config = {
basename: process.env.REACT_APP_BASE_NAME,
defaultPath: process.env.REACT_APP_BASE_NAME,
candigVersion: process.env.REACT_APP_CANDIG_VERSION,
aggregateThreshold: process.env.REACT_APP_AGGREGATE_COUNT_THRESHOLD,
fontFamily: `'Roboto', sans-serif`,
borderRadius: 12
};
Expand Down
133 changes: 133 additions & 0 deletions src/layout/MainLayout/Header/ProfileSection/apiTokenbutton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useState } from 'react';
import PropTypes from 'prop-types';

import { Alert, ListItemButton, ListItemIcon, ListItemText, Tooltip, Typography } from '@mui/material';
import PasswordIcon from '@mui/icons-material/Password';

import { fetchRefreshToken } from 'store/api';

// JWT decoder taken from here: https://stackoverflow.com/a/38552302/2148998
// Then ran through prettier a bunch
function parseJwt(token) {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
window
.atob(base64)
.split('')
.map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)
.join('')
);

return JSON.parse(jsonPayload);
}

function APITokenButton(props) {
const { classes, customization } = props;
const [token, setToken] = useState(undefined);
const [tokenHidden, setTokenHidden] = useState(false);
const [error, setError] = useState(undefined);
const [tooltipOpen, setTooltipOpen] = useState(false);

const grabToken = () => {
setError(false);
fetchRefreshToken().then((data) => {
if ('error' in data) {
setError(data.error);
} else {
setToken(data.token);
setTokenHidden(false);
}
});
};

function openTooltip() {
setTooltipOpen(true);
setTimeout(() => {
setTooltipOpen(false);
}, 3000);
}

function fallbackCopyTextToClipboard(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();

try {
document.execCommand('copy');
openTooltip();
} catch (err) {
console.error('Fallback copy failed:', err);
} finally {
document.body.removeChild(textarea);
}
}

const copyToken = () => {
try {
setTokenHidden(true);
if (navigator.clipboard) {
navigator.clipboard
.writeText(token)
.then(() => openTooltip())
.catch(() => {
fallbackCopyTextToClipboard(token);
});
} else {
fallbackCopyTextToClipboard(token);
}
} catch (err) {
console.error('Error copying token:', err);
}
};

const getTimeout = (token) => new Date(parseJwt(token).exp * 1000).toTimeString();

return (
<>
<ListItemButton className={classes.listItem} sx={{ borderRadius: `${customization.borderRadius}px` }} onClick={grabToken}>
<ListItemIcon>
<PasswordIcon stroke={1.5} size="1.3rem" />
</ListItemIcon>
<ListItemText primary={<Typography variant="body2">Get API Token</Typography>} />
</ListItemButton>
{token ? (
<>
<Tooltip
title="Token Copied!"
placement="top-end"
PopperProps={{
disablePortal: true
}}
onClose={() => setTooltipOpen(false)}
open={tooltipOpen}
disableFocusListener
disableHoverListener
disableTouchListener
>
<Alert severity="success" onClick={copyToken}>
{tokenHidden ? token.replaceAll(/./g, '*') : token}
</Alert>
</Tooltip>
<Typography variant="body2" sx={{ marginLeft: '49px' }}>
Click to copy (token valid until {getTimeout(token)})
</Typography>
<Typography variant="body2" className={classes.errorText} sx={{ marginLeft: '49px' }}>
Keep this token secure, do not share it with anybody!
</Typography>
</>
) : (
' '
)}
{error ? <Alert severity="error">{error}</Alert> : ' '}
</>
);
}

APITokenButton.propTypes = {
classes: PropTypes.object,
customization: PropTypes.object
};

export default APITokenButton;
Loading

0 comments on commit 4398b13

Please sign in to comment.