Allow for renaming of a protofile (#2763)

This commit is contained in:
Opender Singh 2020-10-23 11:06:37 +13:00 committed by GitHub
parent b2bf1146f9
commit f2737ff706
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 10 deletions

View File

@ -0,0 +1,19 @@
import { shouldSave } from '../editable';
describe('shouldSave', () => {
it('should save if new and old are not the same', () => {
expect(shouldSave('old', 'new')).toBe(true);
});
it('should not save if new and old are the same', () => {
expect(shouldSave('old', 'old')).toBe(false);
});
it('should save if new is empty and we are not preventing blank', () => {
expect(shouldSave('old', '', false)).toBe(true);
});
it('should not save if new is empty and we are preventing blank', () => {
expect(shouldSave('old', '', true)).toBe(false);
});
});

View File

@ -3,6 +3,21 @@ import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import KeydownBinder from '../keydown-binder';
export const shouldSave = (oldValue, newValue, preventBlank) => {
// Should not save if length = 0 and we want to prevent blank
if (preventBlank && !newValue.length) {
return false;
}
// Should not save if old value and new value is the same
if (oldValue === newValue) {
return false;
}
// Should save
return true;
};
@autobind
class Editable extends PureComponent {
constructor(props) {
@ -36,11 +51,12 @@ class Editable extends PureComponent {
}
_handleEditEnd() {
const value = this._input.value.trim();
const originalValue = this.props.value;
const newValue = this._input.value.trim();
if (value !== this.props.value) {
// Don't run onSubmit for values that haven't been changed.
this.props.onSubmit(value);
if (shouldSave(originalValue, newValue, this.props.preventBlank)) {
// Don't run onSubmit for values that haven't been changed
this.props.onSubmit(newValue);
}
// This timeout prevents the UI from showing the old value after submit.
@ -73,6 +89,7 @@ class Editable extends PureComponent {
blankValue,
singleClick,
onEditStart, // eslint-disable-line no-unused-vars
preventBlank, // eslint-disable-line no-unused-vars
className,
renderReadView,
...extra
@ -124,6 +141,7 @@ Editable.propTypes = {
singleClick: PropTypes.bool,
onEditStart: PropTypes.func,
className: PropTypes.string,
preventBlank: PropTypes.bool,
};
export default Editable;

View File

@ -100,6 +100,11 @@ class ProtoFilesModal extends React.PureComponent<Props, State> {
}
}
async _handleRename(protoFile: ProtoFile, name: string): Promise<void> {
await models.protoFile.update(protoFile, { name });
await this._refresh();
}
render() {
const { protoFiles, selectedProtoFileId } = this.state;
@ -122,6 +127,7 @@ class ProtoFilesModal extends React.PureComponent<Props, State> {
selectedId={selectedProtoFileId}
handleSelect={this._handleSelect}
handleDelete={this._handleDelete}
handleRename={this._handleRename}
/>
</ModalBody>
<ModalFooter>

View File

@ -1,16 +1,22 @@
// @flow
import React from 'react';
import * as React from 'react';
import styled from 'styled-components';
import type { ProtoFile } from '../../../models/proto-file';
import PromptButton from '../base/prompt-button';
import type { DeleteProtoFileHandler, SelectProtoFileHandler } from './proto-file-list';
import type {
DeleteProtoFileHandler,
RenameProtoFileHandler,
SelectProtoFileHandler,
} from './proto-file-list';
import { ListGroupItem } from '../../../../../insomnia-components';
import Editable from '../base/editable';
type Props = {
protoFile: ProtoFile,
isSelected?: boolean,
handleSelect: SelectProtoFileHandler,
handleDelete: DeleteProtoFileHandler,
handleRename: RenameProtoFileHandler,
};
const SelectableListItem: React.PureComponent<{ isSelected?: boolean }> = styled(ListGroupItem)`
@ -21,7 +27,13 @@ const SelectableListItem: React.PureComponent<{ isSelected?: boolean }> = styled
background-color: ${({ isSelected }) => isSelected && 'var(--hl-sm) !important'};
`;
const ProtoFileListItem = ({ protoFile, isSelected, handleSelect, handleDelete }: Props) => {
const ProtoFileListItem = ({
protoFile,
isSelected,
handleSelect,
handleDelete,
handleRename,
}: Props) => {
const { name, _id } = protoFile;
// Don't re-instantiate the callbacks if the dependencies have not changed
@ -33,11 +45,17 @@ const ProtoFileListItem = ({ protoFile, isSelected, handleSelect, handleDelete }
},
[handleDelete, protoFile],
);
const handleRenameCallback = React.useCallback(
async (newName: string) => {
await handleRename(protoFile, newName);
},
[handleRename, protoFile],
);
return (
<SelectableListItem isSelected={isSelected} onClick={handleSelectCallback}>
<div className="row-spaced">
{name}
<Editable onSubmit={handleRenameCallback} value={name} preventBlank />
<PromptButton
className="btn btn--super-compact btn--outlined"
addIcon

View File

@ -1,20 +1,28 @@
// @flow
import React from 'react';
import * as React from 'react';
import type { ProtoFile } from '../../../models/proto-file';
import { ListGroup, ListGroupItem } from 'insomnia-components';
import ProtoFileListItem from './proto-file-list-item';
export type SelectProtoFileHandler = (id: string) => void;
export type DeleteProtoFileHandler = (protofile: ProtoFile) => Promise<void>;
export type RenameProtoFileHandler = (protoFile: ProtoFile, name: string) => Promise<void>;
type Props = {
protoFiles: Array<ProtoFile>,
selectedId?: string,
handleSelect: SelectProtoFileHandler,
handleDelete: DeleteProtoFileHandler,
handleRename: RenameProtoFileHandler,
};
const ProtoFileList = ({ protoFiles, selectedId, handleSelect, handleDelete }: Props) => (
const ProtoFileList = ({
protoFiles,
selectedId,
handleSelect,
handleDelete,
handleRename,
}: Props) => (
<ListGroup>
{!protoFiles.length && <ListGroupItem>No proto files exist for this workspace</ListGroupItem>}
{protoFiles.map(p => (
@ -24,6 +32,7 @@ const ProtoFileList = ({ protoFiles, selectedId, handleSelect, handleDelete }: P
isSelected={p._id === selectedId}
handleSelect={handleSelect}
handleDelete={handleDelete}
handleRename={handleRename}
/>
))}
</ListGroup>