From 5aba68383771114b62d8dfaff894fa7e9e12fdd2 Mon Sep 17 00:00:00 2001 From: Mingfei Shao <2475897+mfshao@users.noreply.github.com> Date: Mon, 12 Jul 2021 14:13:11 -0500 Subject: [PATCH] HP-269 Feat/button redirect (#884) * Quickly swap out access selector for column filter * Add Export to Workspace button * Studies are not selectable unless user has access * Restore border to study description * Add export buttons * Post to manifestservice when Export to Workspace button is clicked * Fix bug with config variable scope * Update mock config with file manifests * Implement 'Download Manifest' button * [WIP] Support content_type: link * Add content_type: link * Redirect to workspace page on Export to Workspace click * Configure whether Disco page is behind login * Revert breaking config change * Fix bug preventing multiple files from being selected - Steps to reproduce (heal preprod): - Search for 'jcoin' and select that study - See 1 study selected - Search for 'bacpac' and select that study - Expect 2 studies selected, get 1 study selected - Cause: table selection onChange handler sets selected resources to be whatever's currently selected in the table. If search or filtering has removed a selected row in the table, the onChange handler will happily drop it, as even though it was selected it's no longer in the table. - Fix: ~~Update table selection onChange handler to work by deselecting / selecting a single row at a time.~~ Actually it turns out there's a one-line config change that also fixes the issue :angry-haha: * Remove old code and fix errors * Fix tests * Fix style issues * Adv search open/close * Merge master * [WIP] Filter sliding animation and stick to viewport * [WIP] Filtering logic * Set filter state * Filter based on selections * Combine filters with AND * Hide locks if authz field is missing * Hide Adv Search Filters button if not enabled * Warn instead of crashing if adv search filters field is missing * Update style: search bar * Update font * Update style: adjust font sizes and margins to compress header * Update style: advanced search button * Update style: advanced search button and export to workspace button * Tweak header style to match prototype * [WIP] Update table style to match prototype * Warn instead of crash if malformed filterField * Fix eslint * Update table style to match prototype - Hide border between row and study desc row - Negative margin hack to move study desc row up - Fix bottom border - Remove hover state * Make table scrollable when advanced search filters are open * Enable search over fields not present in table * [WIP] Study description page pops in from right * [WIP] Improve study description page - [x] Study desc page pops in from right - [x] Field styles match prototype - [ ] Permalink button matches prototype - [ ] Tags match prototype - [ ] Study description is expandable - [ ] Close button matches prototype * [WIP] Improve study description page - [x] Study desc page pops in from right - [x] Field styles match prototype - [ ] Permalink button matches prototype - [ ] Tags match prototype - [ ] Study description is expandable - [ ] Close button matches prototype * [WIP] Improve study description page - [x] Study desc page pops in from right - [x] Field styles match prototype - [ ] Permalink button matches prototype - [x] Tags match prototype - [ ] Study description is expandable - [ ] Close button matches prototype * [WIP] Improve study description page - [x] Study desc page pops in from right - [x] Field styles match prototype - [ ] Permalink button matches prototype - [x] Tags match prototype - [ ] Study description is expandable - [ ] Close button matches prototype - [x] Handle display of long fields * Clean up unused code * New study description page - [x] Study desc page pops in from right - [x] Field styles match prototype - [x] Tags match prototype - [x] Close button matches prototype - [x] Permalink button matches prototype - [x] Handle display of long fields - TODO Study description is expandable * Fix table row highlight visual bug - Use a CSS hack (::after element behind the expanded row, which has a transparent background) * Fix visual bug: pagination not visible * Fix visual bug: top of third study description line visible in table * change label 'Unaccessible' to 'No Access' * change n/a logic * change label to 'Access Required' * fix unit test * remove bhc from testSchema * fix stylelint * heal bundle without home page * Delete portal_config.md * fix * fix * fix unit test * fix: adv filter overflow * Mitigate table row CSS bug in Safari - In Safari, table rows overhang the bottom. - Seems to be caused by absolutely positioned ::after element -- in Chrome, it seems that `bottom: -35px` puts the ::after element right below the element it's attached to, but on Safari, `bottom: -35px` puts the ::after element on the bottom of the *container* element (the `table body`!) - Mitigated by changing table background to the same gray as the rows, and hiding the ::after elements at the bottom of the element behind the pagination element. * fix: row color * fix: empty component * fix: css * fix: css * fix: more css * feat: tag scroll * fix lint * feat: scroll tag reset * feat: sort tag * chore: rebase * chore: pkg * chore: 8 tags * chore: no more beta * fix: search crash * fix: css * fix: checkbox * feat: button redirect to login * update * fix: tests * fix: travis * update lock Co-authored-by: Michael Ingram Co-authored-by: haraprasadj --- package-lock.json | 113 ++++++++++++++++++++-- package.json | 4 +- src/Discovery/Discovery.test.tsx | 135 +++++++++++++++++++-------- src/Discovery/Discovery.tsx | 4 +- src/Discovery/DiscoveryActionBar.tsx | 25 +++-- src/Discovery/DiscoveryConfig.d.ts | 6 +- src/Discovery/reduxer.js | 12 +++ 7 files changed, 242 insertions(+), 57 deletions(-) create mode 100644 src/Discovery/reduxer.js diff --git a/package-lock.json b/package-lock.json index a9ae940876..b6977ce4c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@gen3/ui-component": "^0.10.0", "@storybook/addon-actions": "^5.0.0", "@storybook/react": "^5.0.0", + "@types/redux-mock-store": "^1.0.3", "antd": "^4.10.0", "brace": "^0.10.0", "clipboard-plus": "^1.0.0", @@ -54,6 +55,7 @@ "less-loader": "^4.1.0", "lodash": "^4.17.11", "mapbox-gl": "^1.9.1", + "mock-local-storage": "^1.0.5", "moment": "^2.22.2", "node-fetch": "^2.6.1", "npm": "^6.14.7", @@ -106,6 +108,7 @@ "@types/core-js": "^2.5.4", "@types/enzyme": "^3.10.8", "@types/jest": "^26.0.20", + "@types/react-redux": "^7.1.18", "@types/regenerator-runtime": "^0.13.0", "@typescript-eslint/eslint-plugin": "^4.14.0", "@typescript-eslint/parser": "^4.14.0", @@ -129,7 +132,6 @@ "html-webpack-plugin": "^3.2.0", "jest": "^24.5.0", "jest-localstorage-mock": "^2.3.0", - "mock-local-storage": "^1.0.5", "prettier": "^1.4.4", "react-hot-loader": "^1.3.0", "react-test-renderer": "^16.8.6", @@ -5517,6 +5519,16 @@ "@types/unist": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "5.1.1", "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==" @@ -5690,6 +5702,27 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-redux": { + "version": "7.1.18", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.18.tgz", + "integrity": "sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ==", + "dev": true, + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "node_modules/@types/react-redux/node_modules/redux": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/@types/react-syntax-highlighter": { "version": "11.0.4", "integrity": "sha512-9GfTo3a0PHwQeTVoqs0g5bS28KkSY48pp5659wA+Dp4MqceDEa8EHBqrllJvvtyusszyJhViUEap0FDvlk/9Zg==", @@ -5715,6 +5748,22 @@ "version": "3.0.8", "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==" }, + "node_modules/@types/redux-mock-store": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/redux-mock-store/-/redux-mock-store-1.0.3.tgz", + "integrity": "sha512-Wqe3tJa6x9MxMN4DJnMfZoBRBRak1XTPklqj4qkVm5VBpZnC8PSADf4kLuFQ9NAdHaowfWoEeUMz7NWc2GMtnA==", + "dependencies": { + "redux": "^4.0.5" + } + }, + "node_modules/@types/redux-mock-store/node_modules/redux": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/@types/regenerator-runtime": { "version": "0.13.0", "integrity": "sha512-U5osy6qZU3lOPGQRHGDIAt/hC/jAE7zP4Aq258UMXnF8/htmZ+72ALrSsmWTtqML7lCztKkKaPz6Pb5XHJF0Vw==", @@ -6753,6 +6802,7 @@ "node_modules/apollo-cache-control": { "version": "0.14.0", "integrity": "sha512-qN4BCq90egQrgNnTRMUHikLZZAprf3gbm8rC5Vwmc6ZdLolQ7bFsa769Hqi6Tq/lS31KLsXBLTOsRbfPHph12w==", + "deprecated": "The functionality provided by the `apollo-cache-control` package is built in to `apollo-server-core` starting with Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#cachecontrol for details.", "dependencies": { "apollo-server-env": "^3.1.0", "apollo-server-plugin-base": "^0.13.0" @@ -6964,6 +7014,7 @@ "node_modules/apollo-tracing": { "version": "0.15.0", "integrity": "sha512-UP0fztFvaZPHDhIB/J+qGuy6hWO4If069MGC98qVs0I8FICIGu4/8ykpX3X3K6RtaQ56EDAWKykCxFv4ScxMeA==", + "deprecated": "The `apollo-tracing` package is no longer part of Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#tracing for details", "dependencies": { "apollo-server-env": "^3.1.0", "apollo-server-plugin-base": "^0.13.0" @@ -14103,6 +14154,7 @@ "node_modules/graphql-extensions": { "version": "0.15.0", "integrity": "sha512-bVddVO8YFJPwuACn+3pgmrEg6I8iBuYLuwvxiE+lcQQ7POotVZxm2rgGw0PvVYmWWf3DT7nTVDZ5ROh/ALp8mA==", + "deprecated": "The `graphql-extensions` API has been removed from Apollo Server 3. Use the plugin API instead: https://www.apollographql.com/docs/apollo-server/integrations/plugins/", "dependencies": { "@apollographql/apollo-tools": "^0.5.0", "apollo-server-env": "^3.1.0", @@ -20147,7 +20199,6 @@ "node_modules/mock-local-storage": { "version": "1.1.17", "integrity": "sha512-vF5571cY3N/XFw8Oxr+0HmY6PedvO6i2IZrpnDV35sh7alhrh1RYYFZzItuh5OhJrQoulNSruiw1KHk5QB/EQg==", - "dev": true, "dependencies": { "core-js": "^0.8.3", "global": "^4.3.2" @@ -20156,8 +20207,7 @@ "node_modules/mock-local-storage/node_modules/core-js": { "version": "0.8.4", "integrity": "sha1-wiZl8eDRucPF4bCNq9HxCGleT88=", - "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true + "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js." }, "node_modules/moment": { "version": "2.29.1", @@ -40377,6 +40427,16 @@ "@types/unist": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dev": true, + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "5.1.1", "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==" @@ -40556,6 +40616,29 @@ } } }, + "@types/react-redux": { + "version": "7.1.18", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.18.tgz", + "integrity": "sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ==", + "dev": true, + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + }, + "dependencies": { + "redux": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.9.2" + } + } + } + }, "@types/react-syntax-highlighter": { "version": "11.0.4", "integrity": "sha512-9GfTo3a0PHwQeTVoqs0g5bS28KkSY48pp5659wA+Dp4MqceDEa8EHBqrllJvvtyusszyJhViUEap0FDvlk/9Zg==", @@ -40577,6 +40660,24 @@ "@types/react": "*" } }, + "@types/redux-mock-store": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/redux-mock-store/-/redux-mock-store-1.0.3.tgz", + "integrity": "sha512-Wqe3tJa6x9MxMN4DJnMfZoBRBRak1XTPklqj4qkVm5VBpZnC8PSADf4kLuFQ9NAdHaowfWoEeUMz7NWc2GMtnA==", + "requires": { + "redux": "^4.0.5" + }, + "dependencies": { + "redux": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "requires": { + "@babel/runtime": "^7.9.2" + } + } + } + }, "@types/regenerator-runtime": { "version": "0.13.0", "integrity": "sha512-U5osy6qZU3lOPGQRHGDIAt/hC/jAE7zP4Aq258UMXnF8/htmZ+72ALrSsmWTtqML7lCztKkKaPz6Pb5XHJF0Vw==", @@ -51943,7 +52044,6 @@ "mock-local-storage": { "version": "1.1.17", "integrity": "sha512-vF5571cY3N/XFw8Oxr+0HmY6PedvO6i2IZrpnDV35sh7alhrh1RYYFZzItuh5OhJrQoulNSruiw1KHk5QB/EQg==", - "dev": true, "requires": { "core-js": "^0.8.3", "global": "^4.3.2" @@ -51951,8 +52051,7 @@ "dependencies": { "core-js": { "version": "0.8.4", - "integrity": "sha1-wiZl8eDRucPF4bCNq9HxCGleT88=", - "dev": true + "integrity": "sha1-wiZl8eDRucPF4bCNq9HxCGleT88=" } } }, diff --git a/package.json b/package.json index e744f067fa..099ea25454 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@gen3/ui-component": "^0.10.0", "@storybook/addon-actions": "^5.0.0", "@storybook/react": "^5.0.0", + "@types/redux-mock-store": "^1.0.3", "antd": "^4.10.0", "brace": "^0.10.0", "clipboard-plus": "^1.0.0", @@ -49,6 +50,7 @@ "less-loader": "^4.1.0", "lodash": "^4.17.11", "mapbox-gl": "^1.9.1", + "mock-local-storage": "^1.0.5", "moment": "^2.22.2", "node-fetch": "^2.6.1", "npm": "^6.14.7", @@ -101,6 +103,7 @@ "@types/core-js": "^2.5.4", "@types/enzyme": "^3.10.8", "@types/jest": "^26.0.20", + "@types/react-redux": "^7.1.18", "@types/regenerator-runtime": "^0.13.0", "@typescript-eslint/eslint-plugin": "^4.14.0", "@typescript-eslint/parser": "^4.14.0", @@ -124,7 +127,6 @@ "html-webpack-plugin": "^3.2.0", "jest": "^24.5.0", "jest-localstorage-mock": "^2.3.0", - "mock-local-storage": "^1.0.5", "prettier": "^1.4.4", "react-hot-loader": "^1.3.0", "react-test-renderer": "^16.8.6", diff --git a/src/Discovery/Discovery.test.tsx b/src/Discovery/Discovery.test.tsx index 2c46871194..216b2b26d8 100644 --- a/src/Discovery/Discovery.test.tsx +++ b/src/Discovery/Discovery.test.tsx @@ -1,5 +1,8 @@ import React from 'react'; import { mount } from 'enzyme'; +import { Provider } from 'react-redux'; +import { StaticRouter } from 'react-router-dom'; +import configureMockStore from 'redux-mock-store'; import Discovery from './Discovery'; import { DiscoveryConfig } from './DiscoveryConfig'; @@ -7,6 +10,12 @@ import { DiscoveryConfig } from './DiscoveryConfig'; import mockData from './__mocks__/mock_mds_studies.json'; import mockConfig from './__mocks__/mock_config.json'; +const mockStore = configureMockStore(); +const store = mockStore({ + user: { + username: 'mock_user', + }, +}); const testStudies = mockData.map((study, i) => ({ ...study, __accessible: i % 2 === 0 })); // This mock is required to avoid errors when rendering the Discovery page @@ -35,18 +44,29 @@ describe('Configuration', () => { test('Page header is configurable', () => { const titleText = 'test title text'; testConfig.features.pageTitle = { enabled: true, text: titleText }; - let wrapper = mount(); + let wrapper = mount( + + + + + , + ); expect(wrapper.find('.discovery-page-title').text()).toBe(titleText); wrapper.unmount(); testConfig.features.pageTitle = { enabled: false, text: titleText }; - wrapper = mount(); + wrapper = mount( + + + + + ); expect(wrapper.exists('.discovery-page-title')).toBe(false); wrapper.unmount(); }); @@ -54,10 +74,16 @@ describe('Configuration', () => { test('Search bar can be enabled/disabled', () => { [true, false].forEach((enabled) => { testConfig.features.search.searchBar.enabled = enabled; - const wrapper = mount(); + const wrapper = mount( + + + + + , + ); expect(wrapper.exists('.discovery-search')).toBe(enabled); wrapper.unmount(); @@ -67,10 +93,16 @@ describe('Configuration', () => { test('Authorization checking can be enabled/disabled', () => { [true, false].forEach((enabled) => { testConfig.features.authorization.enabled = enabled; - const wrapper = mount(); + const wrapper = mount( + + + + + , + ); // accessible column in table should be present/hidden expect(wrapper.exists('.discovery-table__access-icon')).toBe(enabled); // access info in modal should be present/hidden @@ -90,10 +122,16 @@ describe('Modal', () => { testConfig.studyPageFields.header = enabled ? { field: testConfig.minimalFieldMapping.uid } : undefined; - const wrapper = mount(); + const wrapper = mount( + + + + + , + ); wrapper.find('.discovery-table__row').at(modalDataIndex).simulate('click'); const modal = wrapper.find('.discovery-modal').first(); expect(modal.exists('.discovery-modal__header-text')).toBe(enabled); @@ -106,10 +144,15 @@ describe('Modal', () => { const modalDataIndex = 2; const headerField = testConfig.minimalFieldMapping.uid; testConfig.studyPageFields.header = { field: headerField }; - const wrapper = mount(); + const wrapper = mount( + + + + + ); wrapper.find('.discovery-table__row').at(modalDataIndex).simulate('click'); const modal = wrapper.find('.discovery-modal').first(); const modalData = testStudies[modalDataIndex]; @@ -120,10 +163,16 @@ describe('Modal', () => { test('Modal fields show selected study\'s data with correct configuration', () => { const modalDataIndex = 2; - const wrapper = mount(); + const wrapper = mount( + + + + + , + ); wrapper.find('.discovery-table__row').at(modalDataIndex).simulate('click'); const modal = wrapper.find('.discovery-modal').first(); const modalData = testStudies[modalDataIndex]; @@ -191,11 +240,17 @@ describe('Modal', () => { const permalinkStudyIndex = 5; const permalinkStudyData = testStudies[permalinkStudyIndex]; const permalinkStudyUID = permalinkStudyData[testConfig.minimalFieldMapping.uid]; - const wrapper = mount(); + const wrapper = mount( + + + + + , + ); testConfig.studyPageFields.header = { field: testConfig.minimalFieldMapping.uid }; const modal = wrapper.find('.discovery-modal').first(); @@ -210,10 +265,16 @@ describe('Modal', () => { describe('Table', () => { test('Table filters records by tags', () => { testConfig.features.authorization.enabled = true; - const wrapper = mount(); + const wrapper = mount( + + + + + , + ); // select the `COVID 19` tag const targetTagValue = 'COVID 19'; diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index c953d1d431..8b15865a3d 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -9,7 +9,7 @@ import DiscoveryTagViewer from './DiscoveryTagViewer'; import DiscoveryListView from './DiscoveryListView'; import DiscoveryDetails from './DiscoveryDetails'; import DiscoveryAdvancedSearchPanel from './DiscoveryAdvancedSearchPanel'; -import DiscoveryActionBar from './DiscoveryActionBar'; +import ReduxDiscoveryActionBar from './reduxer'; import DiscoveryMDSSearch from './DiscoveryMDSSearch'; import DiscoveryAccessibilityLinks from './DiscoveryAccessibilityLinks'; @@ -477,7 +477,7 @@ const Discovery: React.FunctionComponent = (props: Props) => { )} {/* Bar with actions, stats, around advanced search and data actions */} - void; filtersVisible: boolean; setFiltersVisible: (boolean) => void; + user: User, } const handleDownloadManifestClick = (config: DiscoveryConfig, selectedResources: []) => { @@ -87,6 +91,11 @@ const handleExportToWorkspaceClick = async ( const DiscoveryActionBar = (props: Props) => { const history = useHistory(); + const location = useLocation(); + + const handleRedirectToLoginClick = () => { + history.push('/login', { from: `${location.pathname}` }); + }; return (
@@ -132,14 +141,15 @@ const DiscoveryActionBar = (props: Props) => { )} > )} @@ -164,11 +174,12 @@ const DiscoveryActionBar = (props: Props) => { disabled={props.selectedResources.length === 0} loading={props.exportingToWorkspace} icon={} - onClick={() => { + onClick={(props.user.username) ? () => { handleExportToWorkspaceClick(props.config, props.selectedResources, props.setExportingToWorkspace, history); - }} + } + : () => { handleRedirectToLoginClick(); }} > - Open In Workspace + {(props.user.username) ? 'Open In Workspace' : 'Login to Open In Workspace'} diff --git a/src/Discovery/DiscoveryConfig.d.ts b/src/Discovery/DiscoveryConfig.d.ts index 687337b012..611ca275b0 100644 --- a/src/Discovery/DiscoveryConfig.d.ts +++ b/src/Discovery/DiscoveryConfig.d.ts @@ -42,7 +42,7 @@ export interface DiscoveryConfig { // } // } }, - advSearchFilters: { + advSearchFilters?: { enabled: boolean, field: string, filters: { @@ -60,7 +60,7 @@ export interface DiscoveryConfig { title?: string showTagCategoryNames?: boolean }, - tagColumnWidth: string, + tagColumnWidth?: string, studyColumns: { name: string field: string @@ -106,7 +106,7 @@ export interface DiscoveryConfig { tagsListFieldName: string, authzField: string, uid: string, - commons: string + commons?: string }, tagCategories: { name: string, diff --git a/src/Discovery/reduxer.js b/src/Discovery/reduxer.js new file mode 100644 index 0000000000..9b40f83adb --- /dev/null +++ b/src/Discovery/reduxer.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux'; +import DiscoveryActionBar from './DiscoveryActionBar'; + +const ReduxDiscoveryActionBar = (() => { + const mapStateToProps = (state) => ({ + user: state.user, + }); + + return connect(mapStateToProps)(DiscoveryActionBar); +})(); + +export default ReduxDiscoveryActionBar;