- {`You're duplicating the workspace "${srcWorkspace.name}" to upgrade from`}{' '}
+ {`You're duplicating the workspace "${srcWorkspace.displayName}" to upgrade from`}{' '}
{fromCdrVersion} to {toCdrVersion}.
@@ -593,6 +593,7 @@ export const WorkspaceEdit = fp.flow(
createWorkspace(): Workspace {
return {
name: '',
+ displayName: '',
accessTierShortName: DEFAULT_ACCESS_TIER,
cdrVersionId: '',
researchPurpose: {
@@ -652,9 +653,10 @@ export const WorkspaceEdit = fp.flow(
}
if (this.isMode(WorkspaceEditMode.Duplicate)) {
- // This is the only field which is not automatically handled/differentiated
+ // name/displayName is the only field which is not automatically handled/differentiated
// on the API level.
workspace.name = 'Duplicate of ' + workspace.name;
+ workspace.displayName = 'Duplicate of ' + workspace.displayName;
// unselect to prevent unneeded re-review
workspace.researchPurpose.reviewRequested = undefined;
}
@@ -974,9 +976,9 @@ export const WorkspaceEdit = fp.flow(
case WorkspaceEditMode.Create:
return 'Create a new workspace';
case WorkspaceEditMode.Edit:
- return 'Edit workspace "' + workspace.name + '"';
+ return 'Edit workspace "' + workspace.displayName + '"';
case WorkspaceEditMode.Duplicate:
- return 'Duplicate workspace "' + workspace.name + '"';
+ return 'Duplicate workspace "' + workspace.displayName + '"';
}
}
@@ -1283,6 +1285,7 @@ export const WorkspaceEdit = fp.flow(
populationChecked,
workspace: {
name,
+ displayName,
billingAccountName,
researchPurpose: {
anticipatedFindings,
@@ -1303,6 +1306,7 @@ export const WorkspaceEdit = fp.flow(
} = this.state;
const values: object = {
name,
+ displayName,
billingAccountName,
anticipatedFindings,
intendedStudy,
@@ -1337,7 +1341,8 @@ export const WorkspaceEdit = fp.flow(
// surfaced directly. Currently these constraints are entirely separate
// from the user facing error strings we render.
const constraints: object = {
- name: requiredStringWithMaxLength(80, 'Name'),
+ // name is not included, in order to avoid duplicate error messages
+ displayName: requiredStringWithMaxLength(80, 'Name'),
// The prefix for these lengthMessages require HTML formatting
// The prefix string is omitted here and included in the React template below
billingAccountName: { presence: true },
@@ -1415,6 +1420,11 @@ export const WorkspaceEdit = fp.flow(
);
}
+ setWorkspaceName(name: string) {
+ this.setState(fp.set(['workspace', 'name'], name));
+ this.setState(fp.set(['workspace', 'displayName'], name));
+ }
+
render() {
const params = parseQueryParams(this.props.location.search);
const highlightBilling = !!params.get('highlightBilling');
@@ -1422,6 +1432,7 @@ export const WorkspaceEdit = fp.flow(
const {
workspace: {
name,
+ displayName,
billingAccountName,
cdrVersionId,
accessTierShortName,
@@ -1512,12 +1523,12 @@ export const WorkspaceEdit = fp.flow(
style={styles.textInput}
autoFocus
placeholder='Workspace Name'
- value={name}
- onBlur={(v) =>
- this.setState(fp.set(['workspace', 'name'], v.trim()))
- }
- onChange={(v) =>
- this.setState(fp.set(['workspace', 'name'], v))
+ value={displayName}
+ onBlur={(v: string) => this.setWorkspaceName(v.trim())}
+ onChange={(v: string) =>
+ // do not trim, because it would prevent inner spaces
+ // e.g. it would turn "My Workspace" into "MyWorkspace"
+ this.setWorkspaceName(v)
}
/>
@@ -2282,7 +2293,7 @@ export const WorkspaceEdit = fp.flow(
{this.props.workspaceEditMode === WorkspaceEditMode.Create
? 'You already have a workspace named ' +
- name +
+ displayName +
' Please choose another name'
: 'Another client has modified this workspace since the beginning of this editing ' +
'session. Please reload to avoid overwriting those changes.'}
diff --git a/ui/src/app/pages/workspace/workspace-list.spec.tsx b/ui/src/app/pages/workspace/workspace-list.spec.tsx
index 4812f4691cc..f5929450a73 100644
--- a/ui/src/app/pages/workspace/workspace-list.spec.tsx
+++ b/ui/src/app/pages/workspace/workspace-list.spec.tsx
@@ -23,7 +23,7 @@ import { WorkspacesApiStub } from 'testing/stubs/workspaces-api-stub';
import { WorkspaceList } from './workspace-list';
-describe('WorkspaceList', () => {
+describe(WorkspaceList.name, () => {
const profile = ProfileStubVariables.PROFILE_STUB;
let profileApi: ProfileApiStub;
let user;
@@ -81,7 +81,7 @@ describe('WorkspaceList', () => {
it('displays the correct number of workspaces', async () => {
component();
await waitForNoSpinner();
- expect(getCardNames()).toEqual(workspaceStubs.map((w) => w.name));
+ expect(getCardNames()).toEqual(workspaceStubs.map((w) => w.displayName));
});
it('has the correct permissions classes', async () => {
@@ -122,13 +122,13 @@ describe('WorkspaceList', () => {
);
await pickAccessLevel(accessLevelDropdown, 'Reader');
- expect(getCardNames()).toEqual([workspaceRead.name]);
+ expect(getCardNames()).toEqual([workspaceRead.displayName]);
await pickAccessLevel(accessLevelDropdown, 'Owner');
- expect(getCardNames()).toEqual([workspaceOwn.name]);
+ expect(getCardNames()).toEqual([workspaceOwn.displayName]);
await pickAccessLevel(accessLevelDropdown, 'Writer');
- expect(getCardNames()).toEqual([workspaceWrite.name]);
+ expect(getCardNames()).toEqual([workspaceWrite.displayName]);
await pickAccessLevel(accessLevelDropdown, 'All');
expect(getCardNames().length).toEqual(3);
diff --git a/ui/src/app/pages/workspace/workspace-list.tsx b/ui/src/app/pages/workspace/workspace-list.tsx
index 479a99db37e..9c3567497f6 100644
--- a/ui/src/app/pages/workspace/workspace-list.tsx
+++ b/ui/src/app/pages/workspace/workspace-list.tsx
@@ -74,7 +74,7 @@ export const WorkspaceList = fp.flow(withUserProfile())(
const workspacesReceived = (await workspacesApi().getWorkspaces())
.items;
workspacesReceived.sort((a, b) =>
- a.workspace.name.localeCompare(b.workspace.name)
+ a.workspace.displayName.localeCompare(b.workspace.displayName)
);
this.setState({
workspaceList: workspacesReceived.map(
diff --git a/ui/src/app/pages/workspace/workspace-share.spec.tsx b/ui/src/app/pages/workspace/workspace-share.spec.tsx
index 233cda33fd7..cf2da2ac2e9 100644
--- a/ui/src/app/pages/workspace/workspace-share.spec.tsx
+++ b/ui/src/app/pages/workspace/workspace-share.spec.tsx
@@ -78,7 +78,7 @@ describe(WorkspaceShare.name, () => {
const tomRiddleDiary: WorkspaceData = {
namespace: 'Horcrux',
- name: 'The Diary of Tom Marvolo Riddle',
+ displayName: 'The Diary of Tom Marvolo Riddle',
terraName: 'diary',
etag: '1',
accessLevel: WorkspaceAccessLevel.OWNER,
diff --git a/ui/src/app/pages/workspace/workspace-share.tsx b/ui/src/app/pages/workspace/workspace-share.tsx
index 44756f15f89..e710613d615 100644
--- a/ui/src/app/pages/workspace/workspace-share.tsx
+++ b/ui/src/app/pages/workspace/workspace-share.tsx
@@ -438,7 +438,7 @@ export const WorkspaceShare = fp.flow(withUserProfile())(
}}
>