diff --git a/src/components/WelcomeView.jsx b/src/components/WelcomeView.jsx
index 59e8bdc62..d3e92bc9f 100755
--- a/src/components/WelcomeView.jsx
+++ b/src/components/WelcomeView.jsx
@@ -34,6 +34,10 @@ const SubTitle = styled(Typography)({
fontSize: '16px',
});
+const SubTitleBox = styled(Box)({
+ fontSize: '16px',
+});
+
const MainContent = styled(Box)(({ theme }) => ({
display: 'inline-block',
color: theme.typography.color,
@@ -100,7 +104,7 @@ function WelcomeView({ terraUrl }) {
Terra Data Repository is a cloud-native platform that allows data owners to{' '}
govern and share biomedical research data.
-
+
-
+
Terra Data Repository requires a Terra account.
diff --git a/src/components/dataset/data/sidebar/panels/ShareSnapshot.jsx b/src/components/dataset/data/sidebar/panels/ShareSnapshot.jsx
index 24056b9e5..f10adeff0 100644
--- a/src/components/dataset/data/sidebar/panels/ShareSnapshot.jsx
+++ b/src/components/dataset/data/sidebar/panels/ShareSnapshot.jsx
@@ -16,8 +16,9 @@ import {
} from '@mui/material';
import { MoreVert } from '@mui/icons-material';
import { isEmail } from 'validator';
-import { createSnapshot } from 'actions/index';
+import { createSnapshot, snapshotCreateDetails } from 'actions/index';
import SnapshotAccess from 'components/snapshot/SnapshotAccess';
+import AuthDomain from 'src/components/snapshot/AuthDomain';
const drawerWidth = 600;
const sidebarWidth = 56;
@@ -95,6 +96,7 @@ export class ShareSnapshot extends React.PureComponent {
anchor: null,
hasError: false,
errorMsg: '',
+ authDomain: undefined,
};
}
@@ -107,8 +109,18 @@ export class ShareSnapshot extends React.PureComponent {
setIsSharing: PropTypes.func,
};
+ setAuthDomain = (domain) => {
+ this.setState({ authDomain: domain });
+ };
+
saveSnapshot = () => {
const { dispatch } = this.props;
+ const { authDomain } = this.state;
+ dispatch(
+ snapshotCreateDetails({
+ authDomain,
+ }),
+ );
dispatch(createSnapshot(undefined));
};
@@ -126,18 +138,21 @@ export class ShareSnapshot extends React.PureComponent {
{!isModal && (
-
-
-
+ <>
+
+
+
+
+ >
)}
{isModal && (
diff --git a/src/components/snapshot/AuthDomain.test.tsx b/src/components/snapshot/AuthDomain.test.tsx
new file mode 100644
index 000000000..9dac2224f
--- /dev/null
+++ b/src/components/snapshot/AuthDomain.test.tsx
@@ -0,0 +1,81 @@
+import { mount } from 'cypress/react';
+import { Router } from 'react-router-dom';
+import { ThemeProvider } from '@mui/material/styles';
+import { Provider } from 'react-redux';
+import React from 'react';
+import createMockStore from 'redux-mock-store';
+import { ManagedGroupMembershipEntry } from 'src/models/group';
+import history from '../../modules/hist';
+import AuthDomain from './AuthDomain';
+import globalTheme from '../../modules/theme';
+
+const mountAuthDomain = (userGroups: Array
) => {
+ const state = {
+ user: {
+ userGroups,
+ },
+ };
+
+ const mockStore = createMockStore([]);
+ const store = mockStore(state);
+
+ cy.intercept('GET', 'https://sam.dsde-dev.broadinstitute.org/api/groups/v1').as('getUserGroups');
+
+ mount(
+
+
+
+ {
+ /* no-op */
+ }}
+ />
+
+
+ ,
+ );
+};
+
+describe('Test AuthDomain component', () => {
+ it('Displays authorization domain section', () => {
+ mountAuthDomain([]);
+
+ cy.get('label[for="authorization-domain"]')
+ .should('contain.text', 'Authorization Domain')
+ .should('contain.text', '(optional)');
+ });
+
+ it('Shows authorization domain dropdown with options when user groups exist', () => {
+ const userGroups = [
+ { groupEmail: 'email1', groupName: 'group1', role: 'READER' },
+ { groupEmail: 'email2', groupName: 'group2', role: 'READER' },
+ ];
+ mountAuthDomain(userGroups);
+
+ cy.get('#authorization-domain-select')
+ .should('exist')
+ .should('not.be.disabled')
+ .should('have.value', '');
+
+ cy.get('#authorization-domain-select').parent().click();
+ cy.get('[data-cy^=menuItem]').should('have.length', userGroups.length);
+ });
+
+ it('Select an authorization domain when user groups exist', () => {
+ const userGroups = [
+ { groupEmail: 'email1', groupName: 'group1', role: 'READER' },
+ { groupEmail: 'email2', groupName: 'group2', role: 'READER' },
+ ];
+ mountAuthDomain(userGroups);
+
+ cy.get('#authorization-domain-select').parent().click();
+ cy.get('[data-cy=menuItem-group2]').click();
+ cy.get('#authorization-domain-select').should('have.value', 'group2');
+ });
+
+ it('Disables authorization domain dropdown when insufficient user groups', () => {
+ const userGroups = [{ groupEmail: 'default', groupName: 'default', role: 'READER' }];
+ mountAuthDomain(userGroups);
+ cy.get('#authorization-domain-select').should('be.disabled');
+ });
+});
diff --git a/src/components/snapshot/AuthDomain.tsx b/src/components/snapshot/AuthDomain.tsx
new file mode 100644
index 000000000..aab605bdc
--- /dev/null
+++ b/src/components/snapshot/AuthDomain.tsx
@@ -0,0 +1,77 @@
+import React from 'react';
+import { Box, FormLabel, Link, styled } from '@mui/material';
+import { withStyles } from '@mui/styles';
+import { ManagedGroupMembershipEntry } from 'src/models/group';
+import { AppDispatch } from 'src/store';
+import { TdrState } from 'src/reducers';
+import { useOnMount } from 'src/libs/utils';
+import { LaunchOutlined } from '@mui/icons-material';
+import { connect } from 'react-redux';
+import { getUserGroups } from 'src/actions';
+import JadeDropdown from '../dataset/data/JadeDropdown';
+
+const styles = () => ({
+ /* empty styles */
+});
+
+const JadeLink = styled('span')(({ theme }) => theme.mixins.jadeLink);
+
+type AuthDomainProps = {
+ dispatch: AppDispatch;
+ userGroups: Array;
+ setParentAuthDomain: (domain: string) => void;
+};
+
+function AuthDomain({ dispatch, userGroups, setParentAuthDomain }: AuthDomainProps) {
+ const [selectedAuthDomain, setSelectedAuthDomain] = React.useState(undefined);
+
+ useOnMount(() => {
+ dispatch(getUserGroups());
+ });
+
+ return (
+ <>
+
+ Authorization Domain
+ - (optional)
+
+
+ Authorization Domains restrict data access to only specified individuals in a group and are
+ intended to fulfill requirements you may have for data governed by a compliance standard,
+ such as federal controlled-access data or HIPAA protected data. They follow all snapshot
+ copies and cannot be removed. For more details, see{' '}
+
+
+ When to use an Authorization Domain
+
+
+
+ .
+
+ group.groupName) : []}
+ name="authorization-domain"
+ onSelectedItem={(event) => {
+ const authDomain = event.target.value;
+ setParentAuthDomain(authDomain);
+ setSelectedAuthDomain(authDomain);
+ }}
+ value={selectedAuthDomain || ''}
+ />
+ >
+ );
+}
+
+function mapStateToProps(state: TdrState) {
+ return {
+ userGroups: state.user.userGroups,
+ };
+}
+
+export default connect(mapStateToProps)(withStyles(styles)(AuthDomain));