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:
parent
e11cbc19fe
commit
fd3eb41179
@ -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
|
||||||
|
|||||||
@ -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", () => {
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user