Skip to content

Commit

Permalink
KF-2019-Q2 A (#1601)
Browse files Browse the repository at this point in the history
* ✨ Cavatica action per file repo row (#1538)

* save state

* Facets: When sending in an empty array, disable button #1438 (#1529)

* Bug/#1473 menu dropdown (#1543)

* remove withDropdownState from withDropdownMultiPane

* change Category visibility to be based on state and active index

* add currentCategory state

* add currentCategory setters

* change index lookup to includes

* remove dup props

* remove unused props

* use setActiveCategory consistently

* clean up handleSearchField

* Facets: When sending in an empty array, disable button #1438 (#1544)

* fix style  button analyze file in cavatica

* wrap text inside cells

* make search all filter bigger

* Hide "Remove selected participants from cohort" #1557

* Facets: When sending in an empty array, disable button #1438

* adds arranger admin update

* no need to build arranger admin

* refactors to separate component

* removes unused code

* removes extra git diff

* updates version

* updates comments

* uses localStorage.getItem

* Add color to selected row of participant table (#1553)

* Feat/restyle explore data virtual study (#1573)

* Save/delete a virtual study: minor changes #1580 (#1583)

* fix columns width (#1579)

* Update @arranger/components to v.1.1.6 (#1584)

* Feat/upgrade arranger components 1.1.7 (#1589)

* updates arranger components to 1.1.7 with term filter bug fix (#1585)

* fix/1572 - disable sorting on Participant Table arrays fields

* Range (continuous) filters: should not need to click beside the number boxes in order to apply it #1576

* disable virtual study save button on empty sqon (#1593)

* ✨ Survival Charts now available!

* 🐛 Restoring dependencies that were removed

* fix participant table ui and add tooltip (#1577)

* fix participant table ui and add tooltip

* fix ui when there are multiple values in a cell

* Fix bugs

* Fix duplicate data

* fix bug

* fix total participant table export (#1567)

* 📈 Tracks Virtual Study operations

GA events for the virtualStudies service

* 📈 Cohort Builder Combined Queries tracking

This tracks all the multi-sqon changes (duplicate, remove, updated) that can be done to Combined Queries in the Cohort Builder. This tracking event overload the label property to track specific sqon and event details and could potentially cause the event not to be tracked for large complex queries

* 🔥 Removes all UserSnap code

Removes all instances of UserSnap code through views, modals, analytics, and globals

* remove leftover artifact

* ♻️ Gen3 and DCF flow tracking

Udpates the fenced auth flow tracking to properly fire GA events and set GA dimensions to track persmissions and projects per authed user

* 📈 updates Cavatica GA tracking code

* 🚨 fixes eslint warnings

* ran prettier (no functional change)

* track after action, to avoid issue with tracking preventing the action

* Update text on data repository integrations area (#1600)
  • Loading branch information
nyanofthemoon authored Apr 17, 2019
1 parent e8074d6 commit d0121f6
Show file tree
Hide file tree
Showing 52 changed files with 4,018 additions and 699 deletions.
3,270 changes: 3,005 additions & 265 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 @@ -3,7 +3,8 @@
"version": "1.0.0",
"private": true,
"dependencies": {
"@arranger/components": "1.0.34",
"@arranger/admin-ui": "1.1.7",
"@arranger/components": "1.1.7",
"@nivo/bar": "^0.51.0",
"@nivo/core": "^0.51.0",
"@nivo/pie": "^0.51.0",
Expand Down
32 changes: 29 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { compose } from 'recompose';
import { injectState } from 'freactal';
import { Route, Switch, Redirect } from 'react-router-dom';
import styled from 'react-emotion';
import { Dashboard as ArrangerDashboard } from '@arranger/components';
import { translate } from 'react-i18next';
import Toast from 'uikit/Toast';
import { withTheme } from 'emotion-theming';
import { Dashboard as ArrangerDashboardLegacy } from '@arranger/components';

import Modal from 'components/Modal';
import UserProfile from 'components/UserProfile';
Expand Down Expand Up @@ -35,6 +35,7 @@ import { requireLogin } from './common/injectGlobals';
import { withApi } from 'services/api';
import { initializeApi, ApiContext } from 'services/api';
import { DCF, GEN3, COHORT_BUILDER_PATH } from 'common/constants';
import ArrangerAdmin from 'components/ArrangerAdmin'

const forceSelectRole = ({ loggedInUser, isLoadingUser, WrapperPage = Page, ...props }) => {
if (!loggedInUser && requireLogin) {
Expand All @@ -60,6 +61,7 @@ const AppContainer = styled('div')`
}
`;


const App = compose(
injectState,
withApi,
Expand All @@ -70,19 +72,43 @@ const App = compose(
<AppContainer>
<Switch>
<Route
// TODO: we need a user role specific for this
path="/admin"
render={props =>
forceSelectRole({
api,
isLoadingUser,
WrapperPage: FixedFooterPage,
Component: ({ match, ...props }) => {
return !isAdminToken({
validatedPayload: validateJWT({ jwt: state.loggedInUserToken }),
}) ? (
<Redirect to="/dashboard" />
) : (
<ArrangerAdmin baseRoute={match.url} failRedirect={"/"} />
);
},
loggedInUser,
index: props.match.params.index,
graphqlField: props.match.params.index,
...props,
})
}
/>
<Route
// TODO: left here for convenience during roll out of the new admin
path="/admin_legacy"
render={props =>
forceSelectRole({
api,
isLoadingUser,
WrapperPage: FixedFooterPage,
Component: ({ match, ...props }) => {
return !isAdminToken({
validatedPayload: validateJWT({ jwt: state.loggedInUserToken }),
}) ? (
<Redirect to="/dashboard" />
) : (
<ArrangerDashboard basename={match.url} {...props} />
<ArrangerDashboardLegacy basename={match.url} {...props} />
);
},
loggedInUser,
Expand Down
5 changes: 2 additions & 3 deletions src/common/injectGlobals.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ export const facebookAppId = getApplicationEnvVar('FACEBOOK_APP_ID');
export const egoAppId = getApplicationEnvVar('EGO_APP_ID');
export const googleMapsKey = getApplicationEnvVar('GOOGLE_MAPS_KEY');

export const usersnapHost = getApplicationEnvVar('USERSNAP_HOST');
export const usersnapId = getApplicationEnvVar('USERSNAP_ID');

export const hotjarHost = getApplicationEnvVar('HOTJAR_HOST');
export const hotjarId = getApplicationEnvVar('HOTJAR_ID');

Expand Down Expand Up @@ -91,3 +88,5 @@ export const reactApiDataVersionFallback: string =

// Public Stats
export const publicStatsApiRoot = getApplicationEnvVar('PUBLIC_STATS_ROOT') || '';

export const arrangerAdminApiRoot = getApplicationEnvVar('ARRANGER_ADMIN_ROOT') || null;
30 changes: 30 additions & 0 deletions src/components/ArrangerAdmin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, {Suspense} from 'react';
import { arrangerAdminApiRoot } from 'common/injectGlobals';
import { EGO_JWT_KEY } from 'common/constants';
import { withRouter } from 'react-router-dom';

const LazyArrangerAdminUi = React.lazy(() => import('@arranger/admin-ui/dist'))

export default withRouter(({
baseRoute,
history,
failRedirect="/"
}) => (
<div style={{ minHeight: "100vh" }}>
<Suspense fallback={<div>Loading...</div>}>
<LazyArrangerAdminUi
basename={baseRoute}
apiRoot={arrangerAdminApiRoot}
fetcher={(url, config) =>
fetch(url, {
...config,
headers: {
...config.headers,
authorization: `Bearer ${localStorage.getItem(EGO_JWT_KEY)}`
}
})
.catch(() => history.replace(failRedirect))
}/>
</Suspense>
</div>
))
40 changes: 18 additions & 22 deletions src/components/CohortBuilder/Categories/Category.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { withApi } from 'services/api';
import Column from 'uikit/Column';
import Dropdown from 'uikit/Dropdown';
import { compose, lifecycle, withState, withProps } from 'recompose';
import { withDropdownMultiPane } from 'uikit/Dropdown';
import { withDropdownState } from 'uikit/Dropdown';
import Filter from './Filter';
import CategoryRowDisplay from './CategoryRowDisplay';
import { arrangerProjectId } from 'common/injectGlobals';
Expand Down Expand Up @@ -101,8 +101,8 @@ const CategoryButton = styled(Column)`
background-color: ${({ theme }) => theme.backgroundGrey};
}
${({ isDropdownVisible, theme }) =>
isDropdownVisible
${({ isOpen, theme }) =>
isOpen
? css`
background-color: ${theme.backgroundGrey};
box-shadow: 0 0 5.9px 0.1px ${theme.lighterShadow};
Expand Down Expand Up @@ -130,15 +130,11 @@ const CategoryRow = compose(withApi)(({ api, field, active }) => (
const noop = () => {};

const Category = compose(
withDropdownMultiPane,
withProps(({ fields, currentSearchField = '' }) => {
withDropdownState,
withProps(({ fields, currentSearchField = '', category, currentCategory }) => {
const index = fields.indexOf(currentSearchField);
return index > -1
? {
showExpanded: true,
activeIndex: index,
isDropdownVisible: true,
}
return index > -1 && category === currentCategory
? { showExpanded: true, activeIndex: index }
: {};
}),
)(
Expand All @@ -149,34 +145,36 @@ const Category = compose(
toggleDropdown,
isDropdownVisible,
setDropdownVisibility,
toggleExpanded,
toggleExpandedDropdown,
setActiveIndex,
activeIndex,
setExpanded,
setExpanded = noop,
showExpanded,
fields,
setActiveCategory,
sqon = {
op: 'and',
content: [],
},
onSqonUpdate = noop,
onClose = noop,
category = '',
}) => {
const isFieldInSqon = fieldId =>
sqon.content.some(({ content: { field } }) => field === fieldId);

const isOpen = isDropdownVisible || !!activeIndex;

return (
<Dropdown
{...{
multiLevel: true,
onOuterClick: () => {
setExpanded(false);
setActiveCategory({ category, fieldName: '' });
setDropdownVisibility(false);
onClose();
},
isOpen: isDropdownVisible,
isOpen,
onToggle: toggleDropdown,
setActiveIndex,
setActiveIndex: index => setActiveCategory({ fieldName: fields[index], category }),
activeIndex,
setExpanded,
showExpanded,
Expand All @@ -189,16 +187,14 @@ const Category = compose(
initialSqon={sqon}
onSubmit={sqon => {
onSqonUpdate(sqon);
toggleExpanded();
setDropdownVisibility(false);
onClose();
}}
onBack={() => {
toggleExpanded();
onClose();
}}
onCancel={() => {
toggleExpandedDropdown();
setDropdownVisibility(false);
onClose();
}}
field={field}
Expand All @@ -215,7 +211,7 @@ const Category = compose(
OptionsContainerComponent: OptionsWrapper,
}}
>
<CategoryButton isDropdownVisible={isDropdownVisible}>
<CategoryButton isOpen={isOpen}>
<Column alignItems="center">
{' '}
{children}
Expand Down
50 changes: 46 additions & 4 deletions src/components/CohortBuilder/Categories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ const CATEGORY_FIELDS = {
'biospecimens.source_text_tissue_type',
'biospecimens.ncit_id_tissue_type',
'biospecimens.source_text_tumor_descriptor',

],
availableData: [
'available_data_types',
Expand All @@ -114,11 +113,23 @@ const CATEGORY_FIELDS = {
],
};

const CATEGORY_NAMES = {
quickSearch: 'quickSearch',
study: 'study',
clinical: 'clinical',
biospecimen: 'biospecimen',
demographic: 'demographic',
availableData: 'availableData',
};

const excludedCategories = ['searchAll', 'quickSearch'];

class Categories extends React.Component {
constructor(props) {
super(props);
this.state = {
currentSearchField: '',
currentCategory: null,
};
autobind(this);
}
Expand All @@ -128,17 +139,28 @@ class Categories extends React.Component {
this.props.onSqonUpdate(...args);
}

// searching should not open quick filters
handleSearchField(fieldName) {
this.setState({ currentSearchField: fieldName });
const currentCategoryKey = Object.keys(CATEGORY_FIELDS)
.filter(key => !excludedCategories.includes(key))
.find(key => CATEGORY_FIELDS[key].includes(fieldName));
const currentCategory = CATEGORY_NAMES[currentCategoryKey];
this.setState({ currentSearchField: fieldName, currentCategory });
}

handleCategoryClose() {
this.setState({ currentSearchField: '' });
this.setActiveCategory({ fieldName: '', category: null });
}

setActiveCategory = ({ category, fieldName }) =>
this.setState({
currentCategory: category,
currentSearchField: fieldName,
});

render() {
const { theme, sqon } = this.props;
const { currentSearchField } = this.state;
const { currentSearchField, currentCategory } = this.state;

return (
<Container>
Expand All @@ -154,8 +176,13 @@ class Categories extends React.Component {
title="Quick Filters"
sqon={sqon}
onSqonUpdate={this.handleSqonUpdate}
onClose={this.handleCategoryClose}
fields={CATEGORY_FIELDS.quickSearch}
currentSearchField={currentSearchField}
color={theme.filterPurple}
setActiveCategory={this.setActiveCategory}
category={CATEGORY_NAMES.quickSearch}
currentCategory={currentCategory}
>
<QuickFilterIcon fill={theme.filterPurple} />
</Category>
Expand All @@ -167,6 +194,9 @@ class Categories extends React.Component {
fields={CATEGORY_FIELDS.study}
currentSearchField={currentSearchField}
color={theme.studyRed}
setActiveCategory={this.setActiveCategory}
category={CATEGORY_NAMES.study}
currentCategory={currentCategory}
>
<StudyIcon fill={theme.studyRed} />
</Category>
Expand All @@ -178,6 +208,9 @@ class Categories extends React.Component {
fields={CATEGORY_FIELDS.demographic}
currentSearchField={currentSearchField}
color={theme.demographicPurple}
setActiveCategory={this.setActiveCategory}
category={CATEGORY_NAMES.demographic}
currentCategory={currentCategory}
>
<DemographicIcon fill={theme.demographicPurple} />
</Category>
Expand All @@ -189,6 +222,9 @@ class Categories extends React.Component {
fields={CATEGORY_FIELDS.clinical}
currentSearchField={currentSearchField}
color={theme.clinicalBlue}
setActiveCategory={this.setActiveCategory}
category={CATEGORY_NAMES.clinical}
currentCategory={currentCategory}
>
<ClinicalIcon width={18} height={17} fill={theme.clinicalBlue} />
</Category>
Expand All @@ -200,6 +236,9 @@ class Categories extends React.Component {
fields={CATEGORY_FIELDS.biospecimen}
currentSearchField={currentSearchField}
color={theme.biospecimenOrange}
setActiveCategory={this.setActiveCategory}
category={CATEGORY_NAMES.biospecimen}
currentCategory={currentCategory}
>
<BiospecimenIcon fill={theme.biospecimenOrange} />
</Category>
Expand All @@ -211,6 +250,9 @@ class Categories extends React.Component {
fields={CATEGORY_FIELDS.availableData}
currentSearchField={currentSearchField}
color={theme.dataBlue}
setActiveCategory={this.setActiveCategory}
category={CATEGORY_NAMES.availableData}
currentCategory={currentCategory}
>
<FileIcon width={11} height={14} fill={theme.dataBlue} />
</Category>
Expand Down
Loading

0 comments on commit d0121f6

Please sign in to comment.