Much better sidebar sorting (#308)

This commit is contained in:
Gregory Schier 2017-06-13 13:45:15 -07:00 committed by GitHub
parent 4e61c699ab
commit 8cf491a99d
8 changed files with 63 additions and 139 deletions

View File

@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "insomnia", "name": "insomnia",
"version": "5.3.0", "version": "5.3.1",
"productName": "Insomnia", "productName": "Insomnia",
"longName": "Insomnia REST Client", "longName": "Insomnia REST Client",
"description": "Debug APIs like a human, not a robot", "description": "Debug APIs like a human, not a robot",

View File

@ -11,8 +11,7 @@ class SidebarChildren extends PureComponent {
handleDuplicateRequest, handleDuplicateRequest,
handleDuplicateRequestGroup, handleDuplicateRequestGroup,
handleGenerateCode, handleGenerateCode,
moveRequest, moveDoc,
moveRequestGroup,
handleActivateRequest, handleActivateRequest,
activeRequest, activeRequest,
workspace workspace
@ -29,7 +28,7 @@ class SidebarChildren extends PureComponent {
return ( return (
<SidebarRequestRow <SidebarRequestRow
key={child.doc._id} key={child.doc._id}
moveRequest={moveRequest} moveDoc={moveDoc}
handleActivateRequest={handleActivateRequest} handleActivateRequest={handleActivateRequest}
handleDuplicateRequest={handleDuplicateRequest} handleDuplicateRequest={handleDuplicateRequest}
handleGenerateCode={handleGenerateCode} handleGenerateCode={handleGenerateCode}
@ -66,8 +65,7 @@ class SidebarChildren extends PureComponent {
handleActivateRequest={handleActivateRequest} handleActivateRequest={handleActivateRequest}
key={requestGroup._id} key={requestGroup._id}
isActive={isActive} isActive={isActive}
moveRequestGroup={moveRequestGroup} moveDoc={moveDoc}
moveRequest={moveRequest}
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed} handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
handleDuplicateRequestGroup={handleDuplicateRequestGroup} handleDuplicateRequestGroup={handleDuplicateRequestGroup}
isCollapsed={child.collapsed} isCollapsed={child.collapsed}
@ -102,8 +100,7 @@ SidebarChildren.propTypes = {
handleDuplicateRequest: PropTypes.func.isRequired, handleDuplicateRequest: PropTypes.func.isRequired,
handleDuplicateRequestGroup: PropTypes.func.isRequired, handleDuplicateRequestGroup: PropTypes.func.isRequired,
handleGenerateCode: PropTypes.func.isRequired, handleGenerateCode: PropTypes.func.isRequired,
moveRequest: PropTypes.func.isRequired, moveDoc: PropTypes.func.isRequired,
moveRequestGroup: PropTypes.func.isRequired,
childObjects: PropTypes.arrayOf(PropTypes.object).isRequired, childObjects: PropTypes.arrayOf(PropTypes.object).isRequired,
workspace: PropTypes.object.isRequired, workspace: PropTypes.object.isRequired,

View File

@ -42,7 +42,7 @@ class SidebarRequestGroupRow extends PureComponent {
const { const {
connectDragSource, connectDragSource,
connectDropTarget, connectDropTarget,
moveRequest, moveDoc,
children, children,
requestGroup, requestGroup,
isCollapsed, isCollapsed,
@ -104,7 +104,7 @@ class SidebarRequestGroupRow extends PureComponent {
handleActivateRequest={misc.nullFn} handleActivateRequest={misc.nullFn}
handleDuplicateRequest={misc.nullFn} handleDuplicateRequest={misc.nullFn}
handleGenerateCode={misc.nullFn} handleGenerateCode={misc.nullFn}
moveRequest={moveRequest} moveDoc={moveDoc}
isActive={false} isActive={false}
request={null} request={null}
requestGroup={requestGroup} requestGroup={requestGroup}
@ -122,8 +122,7 @@ SidebarRequestGroupRow.propTypes = {
// Functions // Functions
handleSetRequestGroupCollapsed: PropTypes.func.isRequired, handleSetRequestGroupCollapsed: PropTypes.func.isRequired,
handleDuplicateRequestGroup: PropTypes.func.isRequired, handleDuplicateRequestGroup: PropTypes.func.isRequired,
moveRequestGroup: PropTypes.func.isRequired, moveDoc: PropTypes.func.isRequired,
moveRequest: PropTypes.func.isRequired,
handleActivateRequest: PropTypes.func.isRequired, handleActivateRequest: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired, handleCreateRequest: PropTypes.func.isRequired,
handleCreateRequestGroup: PropTypes.func.isRequired, handleCreateRequestGroup: PropTypes.func.isRequired,
@ -167,10 +166,14 @@ function isAbove (monitor, component) {
const dragTarget = { const dragTarget = {
drop (props, monitor, component) { drop (props, monitor, component) {
const movingDoc = monitor.getItem().requestGroup || monitor.getItem().request;
const parentId = props.requestGroup.parentId;
const targetId = props.requestGroup._id;
if (isAbove(monitor, component)) { if (isAbove(monitor, component)) {
props.moveRequestGroup(monitor.getItem().requestGroup, props.requestGroup, 1); props.moveDoc(movingDoc, parentId, targetId, 1);
} else { } else {
props.moveRequestGroup(monitor.getItem().requestGroup, props.requestGroup, -1); props.moveDoc(movingDoc, parentId, targetId, -1);
} }
}, },
hover (props, monitor, component) { hover (props, monitor, component) {
@ -196,5 +199,5 @@ function targetCollect (connect, monitor) {
}; };
} }
const source = DragSource('SIDEBAR_REQUEST_GROUP_ROW', dragSource, sourceCollect)(SidebarRequestGroupRow); const source = DragSource('SIDEBAR_REQUEST_ROW', dragSource, sourceCollect)(SidebarRequestGroupRow);
export default DropTarget('SIDEBAR_REQUEST_GROUP_ROW', dragTarget, targetCollect)(source); export default DropTarget('SIDEBAR_REQUEST_ROW', dragTarget, targetCollect)(source);

View File

@ -163,7 +163,7 @@ SidebarRequestRow.propTypes = {
handleDuplicateRequest: PropTypes.func.isRequired, handleDuplicateRequest: PropTypes.func.isRequired,
handleGenerateCode: PropTypes.func.isRequired, handleGenerateCode: PropTypes.func.isRequired,
requestCreate: PropTypes.func.isRequired, requestCreate: PropTypes.func.isRequired,
moveRequest: PropTypes.func.isRequired, moveDoc: PropTypes.func.isRequired,
// Other // Other
isActive: PropTypes.bool.isRequired, isActive: PropTypes.bool.isRequired,
@ -197,18 +197,15 @@ function isAbove (monitor, component) {
const dragTarget = { const dragTarget = {
drop (props, monitor, component) { drop (props, monitor, component) {
const {request} = monitor.getItem(); const movingDoc = monitor.getItem().requestGroup || monitor.getItem().request;
const targetRequest = props.request;
const {requestGroup} = props; const parentId = props.requestGroup ? props.requestGroup._id : props.request.parentId;
const requestGroupId = requestGroup ? requestGroup._id : null; const targetId = props.request ? props.request._id : null;
const parentId = targetRequest ? targetRequest.parentId : requestGroupId;
const targetId = targetRequest ? targetRequest._id : null;
if (isAbove(monitor, component)) { if (isAbove(monitor, component)) {
props.moveRequest(request, parentId, targetId, 1); props.moveDoc(movingDoc, parentId, targetId, 1);
} else { } else {
props.moveRequest(request, parentId, targetId, -1); props.moveDoc(movingDoc, parentId, targetId, -1);
} }
}, },
hover (props, monitor, component) { hover (props, monitor, component) {

View File

@ -47,8 +47,7 @@ class Sidebar extends PureComponent {
handleGenerateCode, handleGenerateCode,
handleCreateRequestGroup, handleCreateRequestGroup,
handleSetRequestGroupCollapsed, handleSetRequestGroupCollapsed,
moveRequest, moveDoc,
moveRequestGroup,
handleActivateRequest, handleActivateRequest,
activeRequest activeRequest
} = this.props; } = this.props;
@ -99,8 +98,7 @@ class Sidebar extends PureComponent {
handleDuplicateRequest={handleDuplicateRequest} handleDuplicateRequest={handleDuplicateRequest}
handleDuplicateRequestGroup={handleDuplicateRequestGroup} handleDuplicateRequestGroup={handleDuplicateRequestGroup}
handleGenerateCode={handleGenerateCode} handleGenerateCode={handleGenerateCode}
moveRequest={moveRequest} moveDoc={moveDoc}
moveRequestGroup={moveRequestGroup}
workspace={workspace} workspace={workspace}
activeRequest={activeRequest} activeRequest={activeRequest}
/> />
@ -124,8 +122,7 @@ Sidebar.propTypes = {
handleExportFile: PropTypes.func.isRequired, handleExportFile: PropTypes.func.isRequired,
handleSetActiveWorkspace: PropTypes.func.isRequired, handleSetActiveWorkspace: PropTypes.func.isRequired,
handleSetActiveEnvironment: PropTypes.func.isRequired, handleSetActiveEnvironment: PropTypes.func.isRequired,
moveRequest: PropTypes.func.isRequired, moveDoc: PropTypes.func.isRequired,
moveRequestGroup: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired, handleCreateRequest: PropTypes.func.isRequired,
handleCreateRequestGroup: PropTypes.func.isRequired, handleCreateRequestGroup: PropTypes.func.isRequired,
handleDuplicateRequest: PropTypes.func.isRequired, handleDuplicateRequest: PropTypes.func.isRequired,

View File

@ -252,8 +252,7 @@ class Wrapper extends PureComponent {
handleDuplicateRequest, handleDuplicateRequest,
handleDuplicateRequestGroup, handleDuplicateRequestGroup,
handleExportFile, handleExportFile,
handleMoveRequest, handleMoveDoc,
handleMoveRequestGroup,
handleResetDragPaneHorizontal, handleResetDragPaneHorizontal,
handleResetDragPaneVertical, handleResetDragPaneVertical,
handleResetDragSidebar, handleResetDragSidebar,
@ -312,8 +311,7 @@ class Wrapper extends PureComponent {
handleGenerateCode={handleGenerateCode} handleGenerateCode={handleGenerateCode}
handleDuplicateRequestGroup={handleDuplicateRequestGroup} handleDuplicateRequestGroup={handleDuplicateRequestGroup}
handleSetActiveEnvironment={handleSetActiveEnvironment} handleSetActiveEnvironment={handleSetActiveEnvironment}
moveRequest={handleMoveRequest} moveDoc={handleMoveDoc}
moveRequestGroup={handleMoveRequestGroup}
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed} handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
activeRequest={activeRequest} activeRequest={activeRequest}
activeEnvironment={activeEnvironment} activeEnvironment={activeEnvironment}
@ -523,8 +521,7 @@ Wrapper.propTypes = {
handleExportFile: PropTypes.func.isRequired, handleExportFile: PropTypes.func.isRequired,
handleSetActiveWorkspace: PropTypes.func.isRequired, handleSetActiveWorkspace: PropTypes.func.isRequired,
handleSetActiveEnvironment: PropTypes.func.isRequired, handleSetActiveEnvironment: PropTypes.func.isRequired,
handleMoveRequest: PropTypes.func.isRequired, handleMoveDoc: PropTypes.func.isRequired,
handleMoveRequestGroup: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired, handleCreateRequest: PropTypes.func.isRequired,
handleDuplicateRequest: PropTypes.func.isRequired, handleDuplicateRequest: PropTypes.func.isRequired,
handleDuplicateRequestGroup: PropTypes.func.isRequired, handleDuplicateRequestGroup: PropTypes.func.isRequired,

View File

@ -928,104 +928,50 @@ function mapDispatchToProps (dispatch) {
handleImportUriToWorkspace: global.importUri, handleImportUriToWorkspace: global.importUri,
handleCommand: global.newCommand, handleCommand: global.newCommand,
handleExportFile: global.exportFile, handleExportFile: global.exportFile,
handleMoveRequest: _moveRequest, handleMoveDoc: _moveDoc
handleMoveRequestGroup: _moveRequestGroup
}; };
} }
async function _moveRequestGroup (requestGroupToMove, requestGroupToTarget, targetOffset) { async function _moveDoc (docToMove, parentId, targetId, targetOffset) {
// Oh God, this function is awful... if (docToMove._id === targetId) {
if (requestGroupToMove._id === requestGroupToTarget._id) {
// Nothing to do
return;
}
// NOTE: using requestToTarget's parentId so we can switch parents!
let requestGroups = await models.requestGroup.findByParentId(requestGroupToTarget.parentId);
requestGroups = requestGroups.sort((a, b) => a.metaSortKey < b.metaSortKey ? -1 : 1);
// Find the index of request B so we can re-order and save everything
for (let i = 0; i < requestGroups.length; i++) {
const request = requestGroups[i];
if (request._id === requestGroupToTarget._id) {
let before, after;
if (targetOffset < 0) {
// We're moving to below
before = requestGroups[i];
after = requestGroups[i + 1];
} else {
// We're moving to above
before = requestGroups[i - 1];
after = requestGroups[i];
}
const beforeKey = before ? before.metaSortKey : requestGroups[0].metaSortKey - 100;
const afterKey = after ? after.metaSortKey : requestGroups[requestGroups.length - 1].metaSortKey + 100;
if (Math.abs(afterKey - beforeKey) < 0.000001) {
// If sort keys get too close together, we need to redistribute the list. This is
// not performant at all (need to update all siblings in DB), but it is extremely rare
// anyway
console.log(`-- Recreating Sort Keys ${beforeKey} ${afterKey} --`);
db.bufferChanges(300);
requestGroups.map((r, i) => {
models.requestGroup.update(r, {
metaSortKey: i * 100,
parentId: requestGroupToTarget.parentId
});
});
} else {
const metaSortKey = afterKey - ((afterKey - beforeKey) / 2);
models.requestGroup.update(requestGroupToMove, {
metaSortKey,
parentId: requestGroupToTarget.parentId
});
}
break;
}
}
}
async function _moveRequest (requestToMove, parentId, targetId, targetOffset) {
// Oh God, this function is awful...
if (requestToMove._id === targetId) {
// Nothing to do. We are in the same spot as we started // Nothing to do. We are in the same spot as we started
return; return;
} }
function __updateDoc (doc, patch) {
models.getModel(docToMove.type).update(doc, patch);
}
if (targetId === null) { if (targetId === null) {
// We are moving to an empty area. No sorting required // We are moving to an empty area. No sorting required
models.request.update(requestToMove, {parentId}); await __updateDoc(docToMove, {parentId});
return; return;
} }
// NOTE: using requestToTarget's parentId so we can switch parents! // NOTE: using requestToTarget's parentId so we can switch parents!
let requests = await models.request.findByParentId(parentId); let docs = [
requests = requests.sort((a, b) => a.metaSortKey < b.metaSortKey ? -1 : 1); ...await models.request.findByParentId(parentId),
...await models.requestGroup.findByParentId(parentId)
].sort((a, b) => a.metaSortKey < b.metaSortKey ? -1 : 1);
// Find the index of request B so we can re-order and save everything // Find the index of doc B so we can re-order and save everything
for (let i = 0; i < requests.length; i++) { for (let i = 0; i < docs.length; i++) {
const request = requests[i]; const doc = docs[i];
if (request._id === targetId) { if (doc._id === targetId) {
let before, after; let before, after;
if (targetOffset < 0) { if (targetOffset < 0) {
// We're moving to below // We're moving to below
before = requests[i]; before = docs[i];
after = requests[i + 1]; after = docs[i + 1];
} else { } else {
// We're moving to above // We're moving to above
before = requests[i - 1]; before = docs[i - 1];
after = requests[i]; after = docs[i];
} }
const beforeKey = before ? before.metaSortKey : requests[0].metaSortKey - 100; const beforeKey = before ? before.metaSortKey : docs[0].metaSortKey - 100;
const afterKey = after ? after.metaSortKey : requests[requests.length - 1].metaSortKey + 100; const afterKey = after ? after.metaSortKey : docs[docs.length - 1].metaSortKey + 100;
if (Math.abs(afterKey - beforeKey) < 0.000001) { if (Math.abs(afterKey - beforeKey) < 0.000001) {
// If sort keys get too close together, we need to redistribute the list. This is // If sort keys get too close together, we need to redistribute the list. This is
@ -1034,12 +980,10 @@ async function _moveRequest (requestToMove, parentId, targetId, targetOffset) {
console.log(`-- Recreating Sort Keys ${beforeKey} ${afterKey} --`); console.log(`-- Recreating Sort Keys ${beforeKey} ${afterKey} --`);
db.bufferChanges(300); db.bufferChanges(300);
requests.map((r, i) => { docs.map((r, i) => __updateDoc(r, {metaSortKey: i * 100, parentId}));
models.request.update(r, {metaSortKey: i * 100, parentId});
});
} else { } else {
const metaSortKey = afterKey - ((afterKey - beforeKey) / 2); const metaSortKey = afterKey - ((afterKey - beforeKey) / 2);
models.request.update(requestToMove, {metaSortKey, parentId}); __updateDoc(docToMove, {metaSortKey, parentId});
} }
break; break;

View File

@ -1,5 +1,4 @@
import {createSelector} from 'reselect'; import {createSelector} from 'reselect';
import * as models from '../../models/index';
// ~~~~~~~~~ // // ~~~~~~~~~ //
// Selectors // // Selectors //
@ -67,16 +66,6 @@ export const selectSidebarChildren = createSelector(
const children = requestsAndRequestGroups const children = requestsAndRequestGroups
.filter(e => e.parentId === parentId) .filter(e => e.parentId === parentId)
.sort((a, b) => { .sort((a, b) => {
// Always sort folders above
if (a.type === models.requestGroup.type && b.type !== models.requestGroup.type) {
return -1;
}
// Always sort folders above
if (b.type === models.requestGroup.type && a.type !== models.requestGroup.type) {
return 1;
}
if (a.metaSortKey === b.metaSortKey) { if (a.metaSortKey === b.metaSortKey) {
return a._id > b._id ? -1 : 1; return a._id > b._id ? -1 : 1;
} else { } else {