Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sort options for sidebar rows #2738

Merged
merged 14 commits into from Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 31 additions & 0 deletions packages/insomnia-app/app/common/constants.js
Expand Up @@ -257,6 +257,37 @@ const authTypesMap = {
[AUTH_NETRC]: ['Netrc', 'Netrc File'],
};

// Sort Orders
export const SORT_CUSTOM = 'custom';
export const SORT_NAME_ASC = 'name-asc';
develohpanda marked this conversation as resolved.
Show resolved Hide resolved
export const SORT_NAME_DESC = 'name-desc';
export const SORT_CREATED_FIRST = 'created-first';
export const SORT_CREATED_LAST = 'created-last';
export const SORT_METHOD = 'method';
export const SORT_TYPE_ASC = 'type-asc';
export const SORT_TYPE_DESC = 'type-desc';

export function getSortOrderName(sortOrder) {
switch (sortOrder) {
case SORT_NAME_ASC:
return 'Name Ascending';
case SORT_NAME_DESC:
return 'Name Descending';
case SORT_CREATED_FIRST:
return 'Created First';
case SORT_CREATED_LAST:
return 'Created Last';
case SORT_METHOD:
return 'Method';
case SORT_TYPE_ASC:
return 'Folder First';
case SORT_TYPE_DESC:
return 'Folder Last';
default:
return '';
}
}
develohpanda marked this conversation as resolved.
Show resolved Hide resolved

export function getPreviewModeName(previewMode, useLong = false) {
if (previewModeMap.hasOwnProperty(previewMode)) {
return useLong ? previewModeMap[previewMode][1] : previewModeMap[previewMode][0];
Expand Down
Expand Up @@ -7,11 +7,14 @@ import type { HotKeyRegistry } from '../../../common/hotkeys';
import { hotKeyRefs } from '../../../common/hotkeys';
import { executeHotKey } from '../../../common/hotkeys-listener';
import SidebarCreateDropdown from './sidebar-create-dropdown';
import SidebarSortDropdown from './sidebar-sort-dropdown';

type Props = {
onChange: string => void,
requestCreate: () => void,
requestGroupCreate: () => void,
sidebarSort: Function,
sortOrder: string,
cobwebsonsale marked this conversation as resolved.
Show resolved Hide resolved
filter: string,
hotKeyRegistry: HotKeyRegistry,
};
Expand Down Expand Up @@ -57,7 +60,7 @@ class SidebarFilter extends React.PureComponent<Props> {
}

render() {
const { filter, hotKeyRegistry } = this.props;
const { filter, hotKeyRegistry, sidebarSort, sortOrder } = this.props;
return (
<KeydownBinder onKeydown={this._handleKeydown}>
<div className="sidebar__filter">
Expand All @@ -75,6 +78,7 @@ class SidebarFilter extends React.PureComponent<Props> {
</button>
)}
</div>
<SidebarSortDropdown handleSort={sidebarSort} sortOrder={sortOrder} />
<SidebarCreateDropdown
handleCreateRequest={this._handleRequestCreate}
handleCreateRequestGroup={this._handleRequestGroupCreate}
Expand Down
@@ -0,0 +1,59 @@
// @flow
import autobind from 'autobind-decorator';
import * as React from 'react';
import {
getSortOrderName,
SORT_CREATED_FIRST,
SORT_CREATED_LAST,
SORT_CUSTOM,
SORT_METHOD,
SORT_NAME_ASC,
SORT_NAME_DESC,
SORT_TYPE_ASC,
SORT_TYPE_DESC,
} from '../../../common/constants';
import { Dropdown, DropdownButton, DropdownItem } from '../base/dropdown';

type Props = {
handleSort: Function,
sortOrder: string,
};

@autobind
class SidebarSortDropdown extends React.PureComponent<Props> {
develohpanda marked this conversation as resolved.
Show resolved Hide resolved
_handleSort(order: string) {
if (order !== this.props.sortOrder) {
cobwebsonsale marked this conversation as resolved.
Show resolved Hide resolved
this.props.handleSort(order);
}
}

renderSortOrder(order: string) {
const currentSortOrder = this.props.sortOrder || SORT_CUSTOM;

return (
<DropdownItem onClick={this._handleSort} value={order}>
{currentSortOrder === order ? <i className="fa fa-check" /> : <i className="fa fa-empty" />}{' '}
{getSortOrderName(order)}
</DropdownItem>
);
}
develohpanda marked this conversation as resolved.
Show resolved Hide resolved

render() {
return (
<Dropdown>
<DropdownButton className="btn btn--compact">
<i className="fa fa-sort" />
</DropdownButton>
{this.renderSortOrder(SORT_NAME_ASC)}
{this.renderSortOrder(SORT_NAME_DESC)}
{this.renderSortOrder(SORT_CREATED_FIRST)}
{this.renderSortOrder(SORT_CREATED_LAST)}
{this.renderSortOrder(SORT_METHOD)}
{this.renderSortOrder(SORT_TYPE_ASC)}
{this.renderSortOrder(SORT_TYPE_DESC)}
</Dropdown>
);
}
}

export default SidebarSortDropdown;
5 changes: 5 additions & 0 deletions packages/insomnia-app/app/ui/components/wrapper-debug.js
Expand Up @@ -35,6 +35,7 @@ type Props = {
handleSetResponseFilter: Function,
handleShowCookiesModal: Function,
handleShowRequestSettingsModal: Function,
handleSidebarSort: Function,
handleUpdateRequestAuthentication: Function,
handleUpdateRequestBody: Function,
handleUpdateRequestHeaders: Function,
Expand Down Expand Up @@ -103,6 +104,7 @@ class WrapperDebug extends React.PureComponent<Props> {
handleSetResponseFilter,
handleShowCookiesModal,
handleShowRequestSettingsModal,
handleSidebarSort,
handleUpdateRequestAuthentication,
handleUpdateRequestBody,
handleUpdateRequestHeaders,
Expand Down Expand Up @@ -164,6 +166,7 @@ class WrapperDebug extends React.PureComponent<Props> {
sidebarFilter,
sidebarHidden,
sidebarWidth,
sortOrder,
unseenWorkspaces,
vcs,
workspaces,
Expand Down Expand Up @@ -213,6 +216,8 @@ class WrapperDebug extends React.PureComponent<Props> {
onChange={handleSetSidebarFilter}
requestCreate={handleRequestCreate}
requestGroupCreate={handleRequestGroupCreate}
sidebarSort={handleSidebarSort}
sortOrder={sortOrder}
filter={sidebarFilter || ''}
hotKeyRegistry={settings.hotKeyRegistry}
/>
Expand Down
4 changes: 4 additions & 0 deletions packages/insomnia-app/app/ui/components/wrapper.js
Expand Up @@ -137,6 +137,7 @@ export type WrapperProps = {
handleSetResponseFilter: Function,
handleSetActiveResponse: Function,
handleSetSidebarRef: Function,
handleSidebarSort: Function,
handleStartDragSidebar: Function,
handleResetDragSidebar: Function,
handleStartDragPaneHorizontal: Function,
Expand Down Expand Up @@ -191,6 +192,7 @@ export type WrapperProps = {
gitVCS: GitVCS | null,
gitRepositories: Array<GitRepository>,
syncItems: Array<StatusCandidate>,
sortOrder: string,

// Optional
oAuth2Token: OAuth2Token | null,
Expand Down Expand Up @@ -533,6 +535,7 @@ class Wrapper extends React.PureComponent<WrapperProps, State> {
handleRender,
handleSetActiveWorkspace,
handleShowExportRequestsModal,
handleSidebarSort,
handleToggleMenuBar,
isVariableUncovered,
requestMetas,
Expand Down Expand Up @@ -823,6 +826,7 @@ class Wrapper extends React.PureComponent<WrapperProps, State> {
handleSetResponseFilter={this._handleSetResponseFilter}
handleShowCookiesModal={this._handleShowCookiesModal}
handleShowRequestSettingsModal={this._handleShowRequestSettingsModal}
handleSidebarSort={handleSidebarSort}
handleUpdateRequestAuthentication={Wrapper._handleUpdateRequestAuthentication}
handleUpdateRequestBody={Wrapper._handleUpdateRequestBody}
handleUpdateRequestHeaders={Wrapper._handleUpdateRequestHeaders}
Expand Down
89 changes: 89 additions & 0 deletions packages/insomnia-app/app/ui/containers/app.js
Expand Up @@ -30,6 +30,15 @@ import {
PREVIEW_MODE_SOURCE,
getAppId,
getAppName,
SORT_NAME_ASC,
SORT_NAME_DESC,
SORT_TYPE_ASC,
SORT_TYPE_DESC,
SORT_METHOD,
SORT_CREATED_FIRST,
SORT_CREATED_LAST,
HTTP_METHODS,
SORT_CUSTOM,
} from '../../common/constants';
import * as globalActions from '../redux/modules/global';
import * as entitiesActions from '../redux/modules/entities';
Expand Down Expand Up @@ -115,6 +124,7 @@ class App extends PureComponent {
forceRefreshCounter: 0,
forceRefreshHeaderCounter: 0,
isMigratingChildren: false,
activeSortOrder: props.activeSortOrder || SORT_CUSTOM,
develohpanda marked this conversation as resolved.
Show resolved Hide resolved
};

this._getRenderContextPromiseCache = {};
Expand Down Expand Up @@ -335,6 +345,80 @@ class App extends PureComponent {
});
}

_getSortMethod(order) {
develohpanda marked this conversation as resolved.
Show resolved Hide resolved
switch (order) {
case SORT_NAME_ASC:
return (a, b) => (a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1);
case SORT_NAME_DESC:
return (a, b) => (a.name.toLowerCase() > b.name.toLowerCase() ? -1 : 1);
case SORT_CREATED_FIRST:
return (a, b) => (a.created < b.created ? -1 : 1);
case SORT_CREATED_LAST:
return (a, b) => (a.created > b.created ? -1 : 1);
case SORT_METHOD:
return (a, b) => {
if (a.type !== b.type) {
return a.type === models.request.type ? -1 : 1;
} else if (a.type === models.request.type) {
const aIndex = HTTP_METHODS.indexOf(a.method);
const bIndex = HTTP_METHODS.indexOf(b.method);
if (aIndex !== bIndex) {
return aIndex < bIndex ? -1 : 1;
} else {
return a.metaSortKey < b.metaSortKey ? -1 : 1;
}
} else {
return a.metaSortKey < b.metaSortKey ? -1 : 1;
}
};
case SORT_TYPE_ASC:
return (a, b) => {
if (a.type === b.type) {
return a.metaSortKey < b.metaSortKey ? -1 : 1;
} else {
return a.type === models.requestGroup.type ? -1 : 1;
}
};
case SORT_TYPE_DESC:
return (a, b) => {
if (a.type === b.type) {
return a.metaSortKey < b.metaSortKey ? -1 : 1;
} else {
return a.type === models.request.type ? -1 : 1;
}
};
default:
return (a, b) => (a.metaSortKey < b.metaSortKey ? -1 : 1);
}
}

async _recalculateMetaSortKey(docs) {
function __updateDoc(doc, metaSortKey) {
models.getModel(doc.type).update(doc, { metaSortKey });
}

await db.bufferChanges(300);
docs.map((doc, i) => __updateDoc(doc, i * 100));
cobwebsonsale marked this conversation as resolved.
Show resolved Hide resolved
}

async _sortSidebar(order, parentId) {
console.log('[sort called]', order, parentId);
if (!parentId) {
parentId = this.props.activeWorkspace._id;
this.state.activeSortOrder = order;
}

const docs = [
...(await models.requestGroup.findByParentId(parentId)),
...(await models.request.findByParentId(parentId)),
].sort(this._getSortMethod(order));

this._recalculateMetaSortKey(docs);

// sort RequestGroups recursively
docs.filter(d => d.type === models.requestGroup.type).map(g => this._sortSidebar(order, g._id));
develohpanda marked this conversation as resolved.
Show resolved Hide resolved
}

static async _requestGroupDuplicate(requestGroup) {
showPrompt({
title: 'Duplicate Folder',
Expand Down Expand Up @@ -1335,6 +1419,8 @@ class App extends PureComponent {
handleUpdateDownloadPath={this._handleUpdateDownloadPath}
isVariableUncovered={isVariableUncovered}
headerEditorKey={forceRefreshHeaderCounter + ''}
handleSidebarSort={this._sortSidebar}
sortOrder={this.state.activeSortOrder}
develohpanda marked this conversation as resolved.
Show resolved Hide resolved
vcs={vcs}
gitVCS={gitVCS}
/>
Expand Down Expand Up @@ -1533,6 +1619,9 @@ async function _moveDoc(docToMove, parentId, targetId, targetOffset) {
models.getModel(docToMove.type).update(doc, patch);
}

// Change sort order to CUSTOM so that sidebar can be sorted again
// this.state.activeSortOrder = SORT_CUSTOM;

if (targetId === null) {
// We are moving to an empty area. No sorting required
await __updateDoc(docToMove, { parentId });
Expand Down