Update viewer with Study List and routing to Viewer
This commit is contained in:
parent
4fbc208b41
commit
5d6aad488e
@ -13,7 +13,7 @@
|
|||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"moment": "^2.22.2",
|
"moment": "^2.22.2",
|
||||||
"ohif-core": "^0.1.1",
|
"ohif-core": "^0.1.2",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"query-string": "^6.2.0",
|
"query-string": "^6.2.0",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
@ -23,7 +23,7 @@
|
|||||||
"react-router": "^4.3.1",
|
"react-router": "^4.3.1",
|
||||||
"react-router-dom": "^4.3.1",
|
"react-router-dom": "^4.3.1",
|
||||||
"react-scripts": "^2.1.1",
|
"react-scripts": "^2.1.1",
|
||||||
"react-viewerbase": "^0.1.5",
|
"react-viewerbase": "^0.1.6",
|
||||||
"redux": "^4.0.1"
|
"redux": "^4.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -2,13 +2,13 @@ import React, { Component } from 'react';
|
|||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { Route, Switch } from 'react-router-dom';
|
import { Route, Switch } from 'react-router-dom';
|
||||||
import ViewerRouting from "./ViewerRouting.js";
|
import ViewerRouting from "./ViewerRouting.js";
|
||||||
|
import StudyListRouting from './StudyListRouting.js';
|
||||||
import StandaloneRouting from './StandaloneRouting.js';
|
import StandaloneRouting from './StandaloneRouting.js';
|
||||||
import IHEInvokeImageDisplay from './IHEInvokeImageDisplay.js';
|
import IHEInvokeImageDisplay from './IHEInvokeImageDisplay.js';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import './variables.css';
|
import './variables.css';
|
||||||
// TODO: figure out how to change themes dynamically
|
// TODO: figure out how to change themes dynamically
|
||||||
import './theme-tide.css';
|
import './theme-tide.css';
|
||||||
import { StudyList } from 'react-viewerbase';
|
|
||||||
|
|
||||||
const reload = () => window.location.reload();
|
const reload = () => window.location.reload();
|
||||||
|
|
||||||
@ -43,14 +43,14 @@ class App extends Component {
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/studylist"
|
path="/studylist"
|
||||||
component={StudyList}
|
component={StudyListRouting}
|
||||||
/*auth={this.props.auth}*/
|
/*auth={this.props.auth}*/
|
||||||
store={this.props.store}
|
store={this.props.store}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/"
|
path="/"
|
||||||
component={StudyList}
|
component={StudyListRouting}
|
||||||
/*auth={this.props.auth}*/
|
/*auth={this.props.auth}*/
|
||||||
store={this.props.store}
|
store={this.props.store}
|
||||||
/>
|
/>
|
||||||
|
|||||||
21
OHIFViewer-react/src/ConnectedStudyList.js
Normal file
21
OHIFViewer-react/src/ConnectedStudyList.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import StudyListWithData from './StudyListWithData.js';
|
||||||
|
|
||||||
|
const isActive = (a) => a.active === true;
|
||||||
|
|
||||||
|
const mapStateToProps = (state, ownProps) => {
|
||||||
|
const activeServer = state.servers.servers.find(isActive);
|
||||||
|
|
||||||
|
return {
|
||||||
|
server: activeServer,
|
||||||
|
...ownProps
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConnectedStudyList = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
null
|
||||||
|
)(StudyListWithData);
|
||||||
|
|
||||||
|
export default ConnectedStudyList;
|
||||||
16
OHIFViewer-react/src/FlexboxLayout/ConnectedFlexboxLayout.js
Normal file
16
OHIFViewer-react/src/FlexboxLayout/ConnectedFlexboxLayout.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import FlexboxLayout from './FlexboxLayout';
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
leftSidebarOpen: state.ui.leftSidebarOpen,
|
||||||
|
rightSidebarOpen: state.ui.rightSidebarOpen
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConnectedFlexboxLayout = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
null
|
||||||
|
)(FlexboxLayout);
|
||||||
|
|
||||||
|
export default ConnectedFlexboxLayout;
|
||||||
29
OHIFViewer-react/src/FlexboxLayout/ConnectedToolbarRow.js
Normal file
29
OHIFViewer-react/src/FlexboxLayout/ConnectedToolbarRow.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { connect } from 'react-redux';
|
||||||
|
import ToolbarRow from './ToolbarRow';
|
||||||
|
import { setLeftSidebarOpen, setRightSidebarOpen } from '../redux/actions.js';
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
leftSidebarOpen: state.ui.leftSidebarOpen,
|
||||||
|
rightSidebarOpen: state.ui.rightSidebarOpen
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
setLeftSidebarOpen: state => {
|
||||||
|
dispatch(setLeftSidebarOpen(state))
|
||||||
|
},
|
||||||
|
setRightSidebarOpen: state => {
|
||||||
|
dispatch(setRightSidebarOpen(state))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConnectedToolbarRow = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ToolbarRow);
|
||||||
|
|
||||||
|
export default ConnectedToolbarRow;
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import OHIF from 'ohif-core';
|
|
||||||
import cornerstone from 'cornerstone-core';
|
import cornerstone from 'cornerstone-core';
|
||||||
import { StudyBrowser } from 'react-viewerbase';
|
import { StudyBrowser } from 'react-viewerbase';
|
||||||
import ViewerMain from './ViewerMain.js';
|
import ViewerMain from './ViewerMain.js';
|
||||||
@ -81,12 +80,12 @@ class FlexboxLayout extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getThumbnailsFromImageIds() {
|
getThumbnailsFromImageIds() {
|
||||||
const studyThumbnails = this.state.studiesForBrowser.forEach(function (study) {
|
this.state.studiesForBrowser.forEach(function (study) {
|
||||||
const { studyInstanceUid } = study;
|
const { studyInstanceUid } = study;
|
||||||
|
|
||||||
study.thumbnails.forEach(function (displaySet) {
|
study.thumbnails.forEach(function (displaySet) {
|
||||||
const imageId = displaySet.imageId;
|
const imageId = displaySet.imageId;
|
||||||
const {displaySetInstanceUid, seriesDescription, seriesNumber, instanceNumber, numImageFrames} = displaySet;
|
const { displaySetInstanceUid } = displaySet;
|
||||||
|
|
||||||
cornerstone.loadAndCacheImage(imageId).then((image) => {
|
cornerstone.loadAndCacheImage(imageId).then((image) => {
|
||||||
loadSuccess.call(this, image, studyInstanceUid, displaySetInstanceUid);
|
loadSuccess.call(this, image, studyInstanceUid, displaySetInstanceUid);
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import ViewerFromStudyData from "./ViewerFromStudyData.js";
|
|||||||
function IHEInvokeImageDisplay({ match }) {
|
function IHEInvokeImageDisplay({ match }) {
|
||||||
const requestType = match.params.query.requestType;
|
const requestType = match.params.query.requestType;
|
||||||
let studyInstanceUids;
|
let studyInstanceUids;
|
||||||
let patientUids;
|
//let patientUids;
|
||||||
let displayStudyList = false;
|
let displayStudyList = false;
|
||||||
|
|
||||||
if (requestType === "STUDY") {
|
if (requestType === "STUDY") {
|
||||||
@ -15,7 +15,7 @@ function IHEInvokeImageDisplay({ match }) {
|
|||||||
const decodedData = window.atob(uids);
|
const decodedData = window.atob(uids);
|
||||||
studyInstanceUids = decodedData.split(';');
|
studyInstanceUids = decodedData.split(';');
|
||||||
} else if (requestType === "PATIENT") {
|
} else if (requestType === "PATIENT") {
|
||||||
patientUids = this.params.query.patientID.split(';');
|
//patientUidspatientUids = this.params.query.patientID.split(';');
|
||||||
displayStudyList = true
|
displayStudyList = true
|
||||||
} else {
|
} else {
|
||||||
displayStudyList = true
|
displayStudyList = true
|
||||||
|
|||||||
24
OHIFViewer-react/src/StudyListRouting.js
Normal file
24
OHIFViewer-react/src/StudyListRouting.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import ConnectedStudyList from "./ConnectedStudyList";
|
||||||
|
|
||||||
|
// TODO: Move to react-viewerbase
|
||||||
|
|
||||||
|
function StudyListRouting({ match }) {
|
||||||
|
// TODO: Figure out which filters we want to pass in via a URL
|
||||||
|
//const { patientId } = match.params;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConnectedStudyList/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
StudyListRouting.propTypes = {
|
||||||
|
match: PropTypes.shape({
|
||||||
|
params: PropTypes.shape({
|
||||||
|
patientIds: PropTypes.string,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StudyListRouting;
|
||||||
120
OHIFViewer-react/src/StudyListWithData.js
Normal file
120
OHIFViewer-react/src/StudyListWithData.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import React, {Component} from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import OHIF from 'ohif-core';
|
||||||
|
import { withRouter } from 'react-router-dom';
|
||||||
|
import { StudyList } from "react-viewerbase";
|
||||||
|
import Header from "./Header";
|
||||||
|
|
||||||
|
class StudyListWithData extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
searchData: {},
|
||||||
|
studies: null,
|
||||||
|
error: null
|
||||||
|
};
|
||||||
|
|
||||||
|
this.pageSize = 5;
|
||||||
|
this.defaultSort = { field: 'patientName', order: 'desc' };
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
// TODO: Avoid using timepoints here
|
||||||
|
//const params = { studyInstanceUids, seriesInstanceUids, timepointId, timepointsFilter={} };
|
||||||
|
|
||||||
|
this.searchForStudies();
|
||||||
|
}
|
||||||
|
|
||||||
|
searchForStudies = (searchData = {
|
||||||
|
currentPage: 0,
|
||||||
|
pageSize: 5
|
||||||
|
}) => {
|
||||||
|
const { server } = this.props;
|
||||||
|
console.log(searchData);
|
||||||
|
const filter = {
|
||||||
|
patientId: searchData.patientId,
|
||||||
|
patientName: searchData.patientName,
|
||||||
|
accessionNumber: searchData.accessionNumber,
|
||||||
|
studyDescription: searchData.studyDescription,
|
||||||
|
modalitiesInStudy: searchData.modalitiesInStudy,
|
||||||
|
limit: searchData.currentPage * searchData.pageSize + searchData.pageSize,
|
||||||
|
offset: searchData.currentPage * searchData.pageSize
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: add sorting
|
||||||
|
const promise = OHIF.studies.searchStudies(server, filter)
|
||||||
|
|
||||||
|
// Render the viewer when the data is ready
|
||||||
|
promise.then(studies => {
|
||||||
|
if (!studies) {
|
||||||
|
studies = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Fix casing of this property!
|
||||||
|
const fixedStudies = studies.map(study => {
|
||||||
|
const fixedStudy = study;
|
||||||
|
fixedStudy.studyInstanceUID = study.studyInstanceUid;
|
||||||
|
|
||||||
|
return fixedStudy;
|
||||||
|
})
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
studies: fixedStudies,
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
this.setState({
|
||||||
|
error: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onImport = () => {
|
||||||
|
console.log('onImport');
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectItem = (studyInstanceUID) => {
|
||||||
|
console.log('onSelectItem');
|
||||||
|
|
||||||
|
console.log('studyInstanceUID');
|
||||||
|
|
||||||
|
this.props.history.push(`/viewer/${studyInstanceUID}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch = (searchData) => {
|
||||||
|
// TODO: Update search filters
|
||||||
|
this.searchForStudies(searchData);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.error) {
|
||||||
|
return (<div>Error: {JSON.stringify(this.state.error)}</div>);
|
||||||
|
} else if (this.state.studies === null) {
|
||||||
|
return (<div>Loading...</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
const studyCount = this.state.studies ? this.state.studies.length : 0;
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
<Header />
|
||||||
|
<StudyList studies={this.state.studies}
|
||||||
|
studyCount={studyCount}
|
||||||
|
studyListFunctionsEnabled={false}
|
||||||
|
onImport={this.onImport}
|
||||||
|
onSelectItem={this.onSelectItem}
|
||||||
|
pageSize={this.pageSize}
|
||||||
|
defaultSort={this.defaultSort}
|
||||||
|
onSearch={this.onSearch} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StudyListWithData.propTypes = {
|
||||||
|
patientId: PropTypes.string,
|
||||||
|
server: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(StudyListWithData);
|
||||||
@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
|||||||
import cornerstone from 'cornerstone-core';
|
import cornerstone from 'cornerstone-core';
|
||||||
import cornerstoneTools from 'cornerstone-tools';
|
import cornerstoneTools from 'cornerstone-tools';
|
||||||
import OHIF from 'ohif-core';
|
import OHIF from 'ohif-core';
|
||||||
import { CineDialog } from 'react-viewerbase';
|
//import { CineDialog } from 'react-viewerbase';
|
||||||
|
|
||||||
import Header from '../Header'
|
import Header from '../Header'
|
||||||
import ConnectedFlexboxLayout from '../FlexboxLayout/ConnectedFlexboxLayout.js';
|
import ConnectedFlexboxLayout from '../FlexboxLayout/ConnectedFlexboxLayout.js';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ class Dropdown extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderList = () => {
|
renderList = () => {
|
||||||
const { list, link, align } = this.props
|
const { list, align } = this.props
|
||||||
|
|
||||||
if (!this.state.open) {
|
if (!this.state.open) {
|
||||||
return null
|
return null
|
||||||
@ -80,8 +80,6 @@ class Dropdown extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { open } = this.state
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='dd-menu' ref={node => this.node = node}>
|
<div className='dd-menu' ref={node => this.node = node}>
|
||||||
<div className="dd-menu-toggle" onClick={this.toggleList}>
|
<div className="dd-menu-toggle" onClick={this.toggleList}>
|
||||||
|
|||||||
@ -18,9 +18,12 @@ const servers = {
|
|||||||
dicomWeb: [
|
dicomWeb: [
|
||||||
{
|
{
|
||||||
"name": "DCM4CHEE",
|
"name": "DCM4CHEE",
|
||||||
"wadoUriRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado",
|
//"wadoUriRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||||
"qidoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
//"qidoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||||
"wadoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
//"wadoRoot": "http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||||
|
"wadoUriRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/wado",
|
||||||
|
"qidoRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||||
|
"wadoRoot": "https://dcm4che.ohif.club/dcm4chee-arc/aets/DCM4CHEE/rs",
|
||||||
"qidoSupportsIncludeField": true,
|
"qidoSupportsIncludeField": true,
|
||||||
"imageRendering": "wadors",
|
"imageRendering": "wadors",
|
||||||
"thumbnailRendering": "wadors",
|
"thumbnailRendering": "wadors",
|
||||||
@ -29,7 +32,8 @@ const servers = {
|
|||||||
"logRequests": true,
|
"logRequests": true,
|
||||||
"logResponses": false,
|
"logResponses": false,
|
||||||
"logTiming": true,
|
"logTiming": true,
|
||||||
"auth": "admin:admin"
|
//"auth": "admin:admin"
|
||||||
|
"auth": "cloud:healthcare"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
16
OHIFViewer-react/src/redux/actions.js
Normal file
16
OHIFViewer-react/src/redux/actions.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const setLeftSidebarOpen = state => ({
|
||||||
|
type: 'SET_LEFT_SIDEBAR_OPEN',
|
||||||
|
state
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setRightSidebarOpen = state => ({
|
||||||
|
type: 'SET_RIGHT_SIDEBAR_OPEN',
|
||||||
|
state
|
||||||
|
});
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
setLeftSidebarOpen,
|
||||||
|
setRightSidebarOpen
|
||||||
|
};
|
||||||
|
|
||||||
|
export default actions;
|
||||||
@ -1 +1 @@
|
|||||||
export default 'c08d12cb36ad7b1ff310b4970a84bc7e6a14e6ed';
|
export default '4fbc208b41fcaa0f957a49409cb55e91c6397d03';
|
||||||
|
|||||||
@ -6832,10 +6832,10 @@ obuf@^1.0.0, obuf@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
|
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
|
||||||
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
|
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
|
||||||
|
|
||||||
ohif-core@^0.1.1:
|
ohif-core@^0.1.2:
|
||||||
version "0.1.1"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.1.1.tgz#594b5a7969c11e5d5eaa3890a384f39409543d3b"
|
resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.1.2.tgz#897c63b73de7a139567d0a6cfe98426aa25e1cb9"
|
||||||
integrity sha512-Ib/lI9fioMiqt5DXmZ8iXtiSne8Z2ubQoh/ePAwgZPljXfMvSY1cUpQK+O90pZqBh444KDolYX00OrJIIbSRgg==
|
integrity sha512-KkiN14ctO3Dp4fJkjndSyUH5suBVcMVxetZdOVGrSlxWbnpCg6Hd2FPZpP6PcYPE4yhWNvUyV5dfP4Qhg14oxw==
|
||||||
dependencies:
|
dependencies:
|
||||||
cornerstone-math "^0.1.7"
|
cornerstone-math "^0.1.7"
|
||||||
isomorphic-base64 "^1.0.2"
|
isomorphic-base64 "^1.0.2"
|
||||||
@ -8288,10 +8288,10 @@ react-scripts@^2.1.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "1.2.4"
|
fsevents "1.2.4"
|
||||||
|
|
||||||
react-viewerbase@^0.1.5:
|
react-viewerbase@^0.1.6:
|
||||||
version "0.1.5"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.1.5.tgz#a5ef7fd852ead91c74fb0068a7cb97c922a9c17a"
|
resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.1.6.tgz#09c775aed103d4382e7f24e5e0850c45327fa481"
|
||||||
integrity sha512-196Req5szlhpvQWivxZmQzF3dMj2vCJtjnyusullRd8isTdaK+cLaCuKBRiJ5Eo6zwM69uTXj7ar8BHQARRzeQ==
|
integrity sha512-msFND25X0uooifaPf8y/VA/2yHrz+M/6yiJwh/rJD8HiM2Bel4JExDOJw9hJmmOS4l7dHpooxAI9ackibvwFAQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.6"
|
classnames "^2.2.6"
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user