Skip to content

Commit

Permalink
OpenConceptLab/ocl_issues#1457 | cascade params from url to operation…
Browse files Browse the repository at this point in the history
…s panel
  • Loading branch information
snyaggarwal committed Jan 4, 2023
1 parent 3146940 commit 96733f6
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 58 deletions.
9 changes: 9 additions & 0 deletions src/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -803,3 +803,12 @@ export const getSSOLogoutURL = () => {
if(redirectURL && idToken)
return `${getAPIURL()}/users/logout/?&post_logout_redirect_uri=${redirectURL}&id_token_hint=${idToken}`
}


export const urlSearchParamsToObject = urlSearchParams => {
const result = {}
for(const [key, value] of urlSearchParams.entries()) { // each 'entry' is a [key, value] tuple
result[key] = value;
}
return result;
}
44 changes: 38 additions & 6 deletions src/components/app/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,38 @@ const App = props => {
<AuthenticationRequiredRoute path="/imports" component={ImportHome} />

{ /* Concept Home */ }
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/$cascade"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/$cascade"
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/$cascade"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/$cascade"
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)"
component={SourceHome}
Expand All @@ -126,27 +158,27 @@ const App = props => {
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)"
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)/$cascade"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)"
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)/$cascade"
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)"
component={SourceHome}
/>
<Route
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
path="/users/:user([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)/$cascade"
component={SourceHome}
/>
<Route
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept"
path="/orgs/:org([a-zA-Z0-9\-\.\_\@]+)/sources/:source([a-zA-Z0-9\-\.\_\@]+)/:version([a-zA-Z0-9\-\.\_\@]+)/concepts/:concept/:conceptVersion([a-zA-Z0-9\-\.\_\@]+)/$cascade"
component={SourceHome}
/>

Expand Down
94 changes: 50 additions & 44 deletions src/components/collections/CollectionHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,36 +194,40 @@ class CollectionHome extends React.Component {
this.URLs = this.getResourceURLs()
const url = this.URLs.version ? this.URLs.version : this.URLs.collection
APIService.new()
.overrideURL(url)
.get(null, null, {includeSummary: true, includeClientConfigs: true})
.then(response => {
if(get(response, 'detail') === "Not found.")
this.setState({isLoading: false, notFound: true, collection: {}, accessDenied: false, permissionDenied: false})
else if(get(response, 'detail') === "Authentication credentials were not provided.")
this.setState({isLoading: false, notFound: false, collection: {}, accessDenied: true, permissionDenied: false})
else if(get(response, 'detail') === "You do not have permission to perform this action.")
this.setState({isLoading: false, notFound: false, collection: {}, accessDenied: false, permissionDenied: true})
else if(!isObject(response))
this.setState({isLoading: false}, () => {throw response})
else {
const collection = response.data;
const customConfigs = get(collection, 'client_configs', [])
const defaultCustomConfig = find(customConfigs, {is_default: true});
this.setState({
isLoading: false,
collection: collection,
selectedConfig: defaultCustomConfig || COLLECTION_DEFAULT_CONFIG,
customConfigs: customConfigs,
}, () => {
const expansionURL = this.URLs.expansion || collection.expansion_url
if(expansionURL)
this.fetchExpansion(expansionURL)
this.setTab()
this.getVersions()
this.getExpansions()
})
}
})
.overrideURL(url)
.get(null, null, {includeSummary: true, includeClientConfigs: true})
.then(response => {
if(get(response, 'detail') === "Not found.")
this.setState({isLoading: false, notFound: true, collection: {}, accessDenied: false, permissionDenied: false})
else if(get(response, 'detail') === "Authentication credentials were not provided.")
this.setState({isLoading: false, notFound: false, collection: {}, accessDenied: true, permissionDenied: false})
else if(get(response, 'detail') === "You do not have permission to perform this action.")
this.setState({isLoading: false, notFound: false, collection: {}, accessDenied: false, permissionDenied: true})
else if(!isObject(response))
this.setState({isLoading: false}, () => {throw response})
else {
const collection = response.data;
const customConfigs = get(collection, 'client_configs', [])
const defaultCustomConfig = find(customConfigs, {is_default: true});
this.setState({
isLoading: false,
collection: collection,
selectedConfig: defaultCustomConfig || COLLECTION_DEFAULT_CONFIG,
customConfigs: customConfigs,
}, () => {
const expansionURL = this.URLs.expansion || collection.expansion_url
if(expansionURL)
this.fetchExpansion(expansionURL)
this.setTab()
this.getVersions()
this.getExpansions()

const { setParentResource, setParentItem } = this.context
setParentItem(this.state.collection)
setParentResource('collection')
})
}
})
})
}

Expand Down Expand Up @@ -264,10 +268,8 @@ class CollectionHome extends React.Component {
}

onResourceSelect = selected => this.setState({selected: selected, width: selected ? this.state.width : false}, () => {
const { setOperationItem, setParentResource, setParentItem } = this.context
const { setOperationItem } = this.context
setOperationItem({...selected, parentVersion: this.props.match.params.version})
setParentItem(this.state.collection)
setParentResource('collection')
})

getContainerWidth = () => {
Expand Down Expand Up @@ -395,24 +397,28 @@ class CollectionHome extends React.Component {
singleColumn
scoped='collection'
parent={collection}
parentURL={get(expansion, 'url') || collection.url || collection.version_url}
mapping={selected}
location={{pathname: selected.version_url || selected.url}}
parentURL={get(expansion, 'url') || collection.url || collection.version_url}
mapping={selected}
_location={this.props.location}
_match={this.props.match}
location={{pathname: selected.version_url || selected.url}}
match={{params: {mappingVersion: selected.version, version: this.props.match.params.version}}}
header={false}
noRedirect
header={false}
noRedirect
/> :
<ConceptHome
singleColumn
scoped='collection'
parent={collection}
parentURL={get(expansion, 'url') || collection.url || collection.version_url}
concept={selected}
location={{pathname: selected.version_url || selected.url}}
parentURL={get(expansion, 'url') || collection.url || collection.version_url}
concept={selected}
_location={this.props.location}
_match={this.props.match}
location={{pathname: selected.version_url || selected.url}}
match={{params: {conceptVersion: selected.version, version: this.props.match.params.version}}}
openHierarchy={false}
header={false}
noRedirect
openHierarchy={false}
header={false}
noRedirect
/>
}
</div>
Expand Down
27 changes: 23 additions & 4 deletions src/components/common/OperationsDrawer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {
OpenInNew as NewTabIcon,
FileCopy as CopyIcon,
} from '@mui/icons-material';
import { get, map, includes, uniq, filter, find, startCase, isString, isObject } from 'lodash';
import { get, map, includes, uniq, filter, find, startCase, isString, isObject, merge, forEach } from 'lodash';
import { OperationsContext } from '../app/LayoutContext';
import {
getFHIRServerConfigFromCurrentContext, getAppliedServerConfig, getServerConfigsForCurrentUser, copyURL
getFHIRServerConfigFromCurrentContext, getAppliedServerConfig, getServerConfigsForCurrentUser, copyURL, urlSearchParamsToObject
} from '../../common/utils';
import { FHIR_OPERATIONS, GREEN, ERROR_RED, BLACK, DEFAULT_CASCADE_PARAMS } from '../../common/constants';
import APIService from '../../services/APIService';
Expand Down Expand Up @@ -92,7 +92,6 @@ const OperationsDrawer = () => {
const fhirResourceDisplay = startCase(fhirResource).replace(' ', '')
const operations = uniq([...get(fhirServer, `operations.${fhirResource}`, []), ...get(currentServer, `operations.${containerResource}`, [])])
const [byURL, setByURL] = React.useState(false)

React.useEffect(
() => {
setItem(operationItem)
Expand All @@ -113,6 +112,11 @@ const OperationsDrawer = () => {
[parentItem]
)

React.useEffect(
() => setValuesFromURL(),
[]
)

const shouldGetParent = _item => {
_item ||= item
return _item && currentServer.type === 'ocl' && _item.concept_class && fhirServer
Expand Down Expand Up @@ -145,6 +149,21 @@ const OperationsDrawer = () => {
const [selectedFHIRServerId, setSelectedFHIRServerId] = React.useState(get(fhirServer, 'id', ''))
const [cascadeParams, setCascadeParams] = React.useState({...DEFAULT_CASCADE_PARAMS})
const onOperationChange = event => setOperation(event.target.value)
const setValuesFromURL = () => {
const [url, query] = window.location.hash.split('?')
if(url && url.includes('/$cascade'))
setOperation('$cascade')
if(query) {
const queryParams = new URLSearchParams(query)
let newParams = merge(cascadeParams, urlSearchParamsToObject(queryParams))
forEach(newParams, (value, key) => {
if(['true', 'false'].includes(value))
newParams[key] = value === 'true'
})
setCascadeParams(newParams)
}
}

const onExecute = event => {
setIsFetching(true)
setResponse(null)
Expand Down Expand Up @@ -338,7 +357,7 @@ const OperationsDrawer = () => {
<h4 style={{marginTop: '30px', marginBottom: '15px'}}>
Cascade Parameters
</h4>
<CascadeParametersForm onChange={setCascadeParams} />
<CascadeParametersForm onChange={setCascadeParams} defaultParams={cascadeParams} />
</div>
}
<div className='col-xs-12 no-side-padding' style={{textAlign: 'right', margin: '15px 0'}}>
Expand Down
4 changes: 3 additions & 1 deletion src/components/concepts/ConceptHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ class ConceptHome extends React.Component {
this.setState({isLoading: false}, () => {throw response})
else
this.setState({isLoading: false, concept: response.data}, () => {
const { setOperationItem } = this.context
const { setOperationItem, setOpenOperations } = this.context
setOperationItem({...response.data, parentVersion: this.props.match.params.version})
if(this.props._location?.pathname.includes('/$cascade'))
setOpenOperations(true)
this.getMappings()
this.fetchParent()
if(this.props.scoped !== 'collection') {
Expand Down
12 changes: 9 additions & 3 deletions src/components/sources/SourceHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ class SourceHome extends React.Component {
}, () => {
this.setTab()
this.getVersions()

const { setParentResource, setParentItem } = this.context
setParentItem(this.state.source)
setParentResource('source')
})
}
})
Expand Down Expand Up @@ -237,10 +241,8 @@ class SourceHome extends React.Component {
}

onResourceSelect = selected => this.setState({selected: selected, width: selected ? this.state.width : false}, () => {
const { setOperationItem, setParentResource, setParentItem } = this.context
const { setOperationItem } = this.context
setOperationItem({...selected, parentVersion: this.props.match.params.version})
setParentItem(this.state.source)
setParentResource('source')
})

currentTabConfig = () => get(this.state.selectedConfig, `config.tabs.${this.state.tab}`)
Expand Down Expand Up @@ -362,6 +364,8 @@ class SourceHome extends React.Component {
singleColumn
scoped
mapping={selected}
_location={this.props.location}
_match={this.props.match}
location={{pathname: selected.versioned_object_id.toString() === selected.uuid ? selected.url : selected.version_url}}
match={{params: {mappingVersion: selected.versioned_object_id.toString() === selected.uuid ? null : selected.version, version: this.props.match.params.version}}}
header={false}
Expand All @@ -373,6 +377,8 @@ class SourceHome extends React.Component {
scoped
concept={selected}
parent={source}
_location={this.props.location}
_match={this.props.match}
location={{pathname: selected.versioned_object_id.toString() === selected.uuid ? selected.url : selected.version_url}}
match={{params: {conceptVersion: selected.versioned_object_id.toString() === selected.uuid ? null : selected.version, version: this.props.match.params.version}}}
openHierarchy={false}
Expand Down

0 comments on commit 96733f6

Please sign in to comment.