Skip to content

Commit

Permalink
Merge branch 'main' into 190-advanced-map-marker-config
Browse files Browse the repository at this point in the history
  • Loading branch information
jernestmyers committed Jul 5, 2023
2 parents 87d8baa + 01a146f commit b95bc83
Show file tree
Hide file tree
Showing 34 changed files with 836 additions and 660 deletions.
2 changes: 1 addition & 1 deletion packages/libs/components/src/map/SemanticMarkers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ function constrainLongitudeToMainWorld({
// but we need to make sure that west is slightly greater than east
// so that they "wrap around" the whole globe
// (if west was slightly less than east, it would represent a very tiny sliver)
if (newWest === newEast) newWest = newWest + 1e-8;
if (Math.abs(newEast - newWest) < 1e-8) newWest = newEast + 1e-8;

return {
southWest: { lat: south, lng: newWest },
Expand Down
2 changes: 0 additions & 2 deletions packages/libs/eda/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import { wrapWdkDependencies } from '@veupathdb/study-data-access/lib/shared/wra
import {
disableRestriction,
enableRestriction,
reduxMiddleware,
} from '@veupathdb/study-data-access/lib/data-restriction/DataRestrictionUtils';

import { edaEndpoint, wdkEndpoint, rootElement, rootUrl } from './constants';
Expand Down Expand Up @@ -224,7 +223,6 @@ initialize({
},
}),
endpoint: wdkEndpoint,
additionalMiddleware: [reduxMiddleware],
} as any);

// If you want to start measuring performance in your app, pass a function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
font-weight: 500;
text-align: center;
font-size: 1.2em;
max-width: 200px;
}
}
&-FullScreenContainer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -651,14 +651,14 @@ function LineplotViz(props: VisualizationProps<Options>) {
[options, providedOverlayVariable, providedOverlayVariableDescriptor]
);

// define showMarginalHistogram
const showMarginalHistogram = options?.showMarginalHistogram ?? false;
// check banner condition
const showIndependentAxisBanner =
vizConfig.independentAxisLogScale && vizConfig.useBinning;
const showDependentAxisBanner =
vizConfig.dependentAxisLogScale && vizConfig.showErrorBars;

const showMarginalHistogram = options?.showMarginalHistogram ?? false;

const data = usePromise(
useCallback(async (): Promise<LinePlotDataWithCoverage | undefined> => {
if (
Expand Down
4 changes: 2 additions & 2 deletions packages/libs/eda/src/lib/core/hooks/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ export function useStudyEntities(filters?: Filter[]) {
min:
filter.type === 'numberRange'
? filter.min
: filter.min.split('T00:00:00Z')[0],
: filter.min.split(/T00:00:00(?:\.000)?Z?/)[0],
max:
filter.type === 'numberRange'
? filter.max
: filter.max.split('T00:00:00Z')[0],
: filter.max.split(/T00:00:00(?:\.000)?Z?/)[0],
}
: undefined;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { barplotRequest } from './plugins/barplot';
import { lineplotRequest } from './plugins/lineplot';
import { histogramRequest } from './plugins/histogram';
import { scatterplotRequest } from './plugins/scatterplot';
//TO DO import timeline SVGIcon
import LineSVG from '../../../core/components/visualizations/implementations/selectorIcons/LineSVG';

interface Props {
selectedOverlayConfig?: OverlayConfig;
Expand All @@ -40,10 +42,6 @@ export function useStandaloneVizPlugins({
return visualization.withOptions({
hideFacetInputs: true, // will also enable table-only mode for mosaic
hideShowMissingnessToggle: true,
// TODO: need to distinguish lineplot from lineplot with marginal histogram?
// perhaps need to make another function only for lineplot with marginal histogram
// or define xxx.withOptions({}) directly at corresponding visualizationPlugins below
showMarginalHistogram: false,
layoutComponent: FloatingLayout,
// why are we providing three functions to access the properties of
// one object? Because in the pre-SAM world, getOverlayVariable was already
Expand Down Expand Up @@ -108,6 +106,17 @@ export function useStandaloneVizPlugins({
vizWithOptions(lineplotVisualization),
lineplotRequest
),
// activate timeline Viz
timeseries: vizWithCustomizedGetRequest(
vizWithOptions(
lineplotVisualization
.withOptions({
showMarginalHistogram: true,
})
.withSelectorIcon(LineSVG)
),
lineplotRequest
),
},
},
'standalone-map-distributions': {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import { get, isPlainObject } from 'lodash';
import React from 'react';
import { BasketActions, ResultPanelActions, ResultTableSummaryViewActions } from '@veupathdb/wdk-client/lib/Actions';
import {getResultTypeDetails} from '@veupathdb/wdk-client/lib/Utils/WdkResult';

import { getStudyId, getStudyPolicyUrl, getStudyRequestNeedsApproval } from '../shared/studies';
import { isUserApprovedForAction, isUserFullyApprovedForStudy } from '../study-access/permission';

import { attemptAction } from './DataRestrictionActionCreators';
import {
Action,
strictActions,
} from './DataRestrictionUiActions';
getStudyId,
getStudyPolicyUrl,
getStudyRequestNeedsApproval,
} from '../shared/studies';
import {
isUserApprovedForAction,
isUserFullyApprovedForStudy,
} from '../study-access/permission';

import { Action, strictActions } from './DataRestrictionUiActions';

// Getters! =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

export function getPolicyUrl (study = {}) {
return !study
? null
: getStudyPolicyUrl(study);
export function getPolicyUrl(study = {}) {
return !study ? null : getStudyPolicyUrl(study);
}

export function getRequestNeedsApproval (study = {}) {
export function getRequestNeedsApproval(study = {}) {
return getStudyRequestNeedsApproval(study);
}

export function getActionVerb (action) {
export function getActionVerb(action) {
if (typeof action !== 'string') return null;
switch (action) {
case Action.search:
Expand All @@ -43,28 +41,33 @@ export function getActionVerb (action) {
case Action.download:
return 'download data';
case Action.basket:
return 'add to your basket'
default:
return 'add to your basket';
default:
return action;
}
}

export function getRequirement ({ action, permissions, study, user }) {
export function getRequirement({ action, permissions, study, user }) {
//if (actionRequiresLogin({ action, study })) return 'login or create an account';
if ( getRequestNeedsApproval(study)=="0" ) return 'submit an access request';
if (actionRequiresApproval({ action, permissions, study, user })) return 'acquire research approval';
if (getRequestNeedsApproval(study) == '0') return 'submit an access request';
if (actionRequiresApproval({ action, permissions, study, user }))
return 'acquire research approval';
return 'contact us';
}

export function getRestrictionMessage ({ action, permissions, study, user }) {
export function getRestrictionMessage({ action, permissions, study, user }) {
const intention = getActionVerb(action);
const requirement = getRequirement({ action, permissions, study, user });
return <span>Please <b>{requirement}</b> in order to {intention}.</span>;
return (
<span>
Please <b>{requirement}</b> in order to {intention}.
</span>
);
}

// CHECKERS! =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

export function isAllowedAccess ({ permissions, action, study }) {
export function isAllowedAccess({ permissions, action, study }) {
const id = getStudyId(study);
if (sessionStorage.getItem('restriction_override') === 'true') return true;
if (isUserApprovedForAction(permissions, id, action)) return true;
Expand All @@ -75,141 +78,42 @@ export function isAllowedAccess ({ permissions, action, study }) {
// the UI in (1) home page study card, (2) study menu, (3) study record page is different when
// - the study.access is prerelease
// - the user doesnt have access
export function isPrereleaseStudy (access, studyId, permissions) {
export function isPrereleaseStudy(access, studyId, permissions) {
return (
access === 'prerelease' &&
!isUserFullyApprovedForStudy(permissions, studyId)
);
}

// we will request the user to request approval if explicit approval needed (guest or not)
export function actionRequiresApproval ({ action, permissions, study, user }) {
export function actionRequiresApproval({ action, permissions, study, user }) {
const datasetId = getStudyId(study);

return isUserApprovedForAction(
permissions,
datasetId,
action
) === false;
return isUserApprovedForAction(permissions, datasetId, action) === false;
}

export function disableRestriction () {
export function disableRestriction() {
sessionStorage.setItem('restriction_override', true);
}
window._disableRestriction = disableRestriction;

export function enableRestriction () {
export function enableRestriction() {
sessionStorage.removeItem('restriction_override');
}
window._enableRestriction = enableRestriction;

export function isActionStrict (action) {
export function isActionStrict(action) {
return strictActions.has(action);
}

export function getIdFromRecordClassName (recordClassName) {
export function getIdFromRecordClassName(recordClassName) {
if (typeof recordClassName !== 'string') return null;
if (recordClassName.length > 13) recordClassName = recordClassName.slice(0, 13);
if (recordClassName.length > 13)
recordClassName = recordClassName.slice(0, 13);
const result = recordClassName.match(/^DS_[^_]+/g);
return result === null
? null
: result[0];
return result === null ? null : result[0];
}

export function isStudyRecordClass(recordClass) {
return recordClass == null || recordClass.fullName.startsWith('DS_');
}


// Redux Middleware
// ----------------

/**
* Redux middleware for applying restrictions to specific redux actions.
*/
export const reduxMiddleware = store => next => action => {
if (!isPlainObject(action) || action.type == null) return next(action);
const restrictedAction = getDataRestrictionActionAndRecordClass(
store.getState(),
action,
(dataRestrictionAction, recordClassName) =>
attemptAction(dataRestrictionAction,{
studyId: getIdFromRecordClassName(recordClassName),
onAllow: () => next(action)
})
);
return restrictedAction == null ? next(action) : store.dispatch(restrictedAction);
}

/**
* Checks if a redux action should be restricted, and if so, calls `callback`
* with the restriction Action, and the record class name associated with the
* action.
*
* Return null to indicate that the redux action does not need to be
* restricted.
*/
function getDataRestrictionActionAndRecordClass(state, action, callback) {
if (!isPlainObject(action)) return null;

switch(action.type || '') {
case ResultPanelActions.openTabListing.type:
return getRecordClassNameByResultType(action.payload.resultType, recordClassName =>
callback(Action.results, recordClassName));

case 'step-analysis/select-tab':
case 'step-analysis/create-new-tab': {
return getRecordClassNameByStepId(state.stepAnalysis.stepId, recordClassName =>
callback(Action.analysis, recordClassName));
}

case BasketActions.requestUpdateBasket.type:
return callback(Action.basket, action.payload.recordClassName);

case BasketActions.requestAddStepToBasket.type:
return getRecordClassNameByStepId(action.payload.stepId, recordClassName =>
callback(Action.basket, recordClassName));

case ResultTableSummaryViewActions.requestPageSizeUpdate.type:
case ResultTableSummaryViewActions.requestSortingUpdate.type:
return getRecordClassNameByResultType(getResultTypeByViewId(action.payload.viewId, state), recordClassName =>
callback(Action.paginate, recordClassName));

case ResultTableSummaryViewActions.viewPageNumber.type:
return action.payload.page === 1
? null
: getRecordClassNameByResultType(getResultTypeByViewId(action.payload.viewId, state), recordClassName =>
callback(Action.paginate, recordClassName));

default:
return null;
}
}

function getResultTypeByViewId(viewId, state) {
return get(state, ['resultTableSummaryView', viewId, 'resultType']);
}

function getRecordClassNameByStepId(stepId, callback) {
return async function run({ wdkService }) {
try {
const step = await wdkService.findStep(stepId);
return callback(step.recordClassName);
}
catch(error) {
return callback(null);
}
};
}

function getRecordClassNameByResultType(resultType, callback) {
return async function run({ wdkService }) {
try {
const { recordClassName } = await getResultTypeDetails(wdkService, resultType)
return callback(recordClassName);
}
catch(error) {
return callback(null);
}
};
}
2 changes: 1 addition & 1 deletion packages/libs/wdk-client/src/Actions/BasketActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const fulfillUpdateBasket = makeActionCreator(

export const requestAddStepToBasket = makeActionCreator(
'requestAddStepToBasket',
(stepId: number) => ({ stepId })
(stepId: number, clearFirst: boolean) => ({ stepId, clearFirst })
);

export const fulfillAddStepToBasket = makeActionCreator(
Expand Down
Loading

0 comments on commit b95bc83

Please sign in to comment.