1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Setting new workspace name restrictions (#832)

* Preventing to create empty and existent workspaces

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Autofocusing name input

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Save workspace when hitting Enter

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Refactoring of save workspace process

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2020-09-10 11:35:17 +03:00 committed by GitHub
parent e11cbc19fe
commit fd3eb41179
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 11 deletions

View File

@ -51,6 +51,10 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
return this.workspaces.get(id); return this.workspaces.get(id);
} }
getByName(name: string): Workspace {
return this.workspacesList.find(workspace => workspace.name === name);
}
@action @action
setActive(id = WorkspaceStore.defaultId, { redirectToLanding = true, resetActiveCluster = true } = {}) { setActive(id = WorkspaceStore.defaultId, { redirectToLanding = true, resetActiveCluster = true } = {}) {
if (id === this.currentWorkspaceId) return; if (id === this.currentWorkspaceId) return;
@ -68,13 +72,16 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
@action @action
saveWorkspace(workspace: Workspace) { saveWorkspace(workspace: Workspace) {
const id = workspace.id; const { id, name } = workspace;
const existingWorkspace = this.getById(id); const existingWorkspace = this.getById(id);
if (!name.trim() || this.getByName(name.trim())) {
return;
}
if (existingWorkspace) { if (existingWorkspace) {
Object.assign(existingWorkspace, workspace); Object.assign(existingWorkspace, workspace);
} else {
this.workspaces.set(id, workspace);
} }
this.workspaces.set(id, workspace);
return workspace;
} }
@action @action

View File

@ -92,6 +92,50 @@ describe("workspace store tests", () => {
expect(ws.workspaces.size).toBe(2); expect(ws.workspaces.size).toBe(2);
}) })
it("cannot create workspace with existent name", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "someid",
name: "default",
});
expect(ws.workspacesList.length).toBe(1); // default workspace only
})
it("cannot create workspace with empty name", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "random",
name: "",
});
expect(ws.workspacesList.length).toBe(1); // default workspace only
})
it("cannot create workspace with ' ' name", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "random",
name: " ",
});
expect(ws.workspacesList.length).toBe(1); // default workspace only
})
it("trim workspace name", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
ws.saveWorkspace({
id: "random",
name: "default ",
});
expect(ws.workspacesList.length).toBe(1); // default workspace only
})
}) })
describe("for a non-empty config", () => { describe("for a non-empty config", () => {

View File

@ -12,6 +12,7 @@ import { Icon } from "../icon";
import { Input } from "../input"; import { Input } from "../input";
import { cssNames, prevDefault } from "../../utils"; import { cssNames, prevDefault } from "../../utils";
import { Button } from "../button"; import { Button } from "../button";
import { isRequired, Validator } from "../input/input.validators";
@observer @observer
export class Workspaces extends React.Component { export class Workspaces extends React.Component {
@ -41,9 +42,9 @@ export class Workspaces extends React.Component {
saveWorkspace = (id: WorkspaceId) => { saveWorkspace = (id: WorkspaceId) => {
const draft = toJS(this.editingWorkspaces.get(id)); const draft = toJS(this.editingWorkspaces.get(id));
if (draft) { const workspace = workspaceStore.saveWorkspace(draft);
if (workspace) {
this.clearEditing(id); this.clearEditing(id);
workspaceStore.saveWorkspace(draft);
} }
} }
@ -90,6 +91,15 @@ export class Workspaces extends React.Component {
}) })
} }
onInputKeypress = (evt: React.KeyboardEvent<any>, workspaceId: WorkspaceId) => {
if (evt.key == 'Enter') {
// Trigget input validation
evt.currentTarget.blur();
evt.currentTarget.focus();
this.saveWorkspace(workspaceId);
}
}
render() { render() {
return ( return (
<WizardLayout className="Workspaces" infoPanel={this.renderInfo()}> <WizardLayout className="Workspaces" infoPanel={this.renderInfo()}>
@ -102,11 +112,15 @@ export class Workspaces extends React.Component {
const isDefault = workspaceStore.isDefault(workspaceId); const isDefault = workspaceStore.isDefault(workspaceId);
const isEditing = this.editingWorkspaces.has(workspaceId); const isEditing = this.editingWorkspaces.has(workspaceId);
const editingWorkspace = this.editingWorkspaces.get(workspaceId); const editingWorkspace = this.editingWorkspaces.get(workspaceId);
const className = cssNames("workspace flex gaps align-center", { const className = cssNames("workspace flex gaps", {
active: isActive, active: isActive,
editing: isEditing, editing: isEditing,
default: isDefault, default: isDefault,
}); });
const existenceValidator: Validator = {
message: () => `Workspace '${name}' already exists`,
validate: value => !workspaceStore.getByName(value.trim())
}
return ( return (
<div key={workspaceId} className={className}> <div key={workspaceId} className={className}>
{!isEditing && ( {!isEditing && (
@ -139,23 +153,27 @@ export class Workspaces extends React.Component {
placeholder={_i18n._(t`Name`)} placeholder={_i18n._(t`Name`)}
value={editingWorkspace.name} value={editingWorkspace.name}
onChange={v => editingWorkspace.name = v} onChange={v => editingWorkspace.name = v}
onKeyPress={(e) => this.onInputKeypress(e, workspaceId)}
validators={[isRequired, existenceValidator]}
autoFocus
/> />
<Input <Input
className="description" className="description"
placeholder={_i18n._(t`Description`)} placeholder={_i18n._(t`Description`)}
value={editingWorkspace.description} value={editingWorkspace.description}
onChange={v => editingWorkspace.description = v} onChange={v => editingWorkspace.description = v}
/> onKeyPress={(e) => this.onInputKeypress(e, workspaceId)}
<Icon
material="cancel"
tooltip={<Trans>Cancel</Trans>}
onClick={() => this.clearEditing(workspaceId)}
/> />
<Icon <Icon
material="save" material="save"
tooltip={<Trans>Save</Trans>} tooltip={<Trans>Save</Trans>}
onClick={() => this.saveWorkspace(workspaceId)} onClick={() => this.saveWorkspace(workspaceId)}
/> />
<Icon
material="cancel"
tooltip={<Trans>Cancel</Trans>}
onClick={() => this.clearEditing(workspaceId)}
/>
</Fragment> </Fragment>
)} )}
</div> </div>