mirror of
https://github.com/Kong/insomnia
synced 2024-11-08 23:00:30 +00:00
c48daaea44
* Add pinning behavior * add fa-thumb-tack * Updated package-lock files * Allow only top level request and request group to be pinned * Prevent dnd for pinned request * Efficiency change * Reverted changes * Revert changes to selectors.js * Fixed pin and add thumbtack * Changes * Pin styling * Fix overflow bug * styling complete * Remove additional style * Updated package-lock.json * Mergie * Boolean to boolean * allow nested requests to be pinned * Remove unused arg * Remove folder pinning functionality * Remove comment * Revert change to open tag on group * Render separator with dsiplay: none so that sync menu is in correct place * Don't reset parent id on request pin * Remove extra checks * Move pin filter to selectors to prevent duplicate childTree traversal * Decouple pinned items from search results * Hide pin on hover * Pin keyboard shortcut via shift+ctrl+p * Typo fix * Update mac hotkey + activeRequest nullcheck * Disable drag and drop only for items in the pinned list * Filter to Find
299 lines
8.1 KiB
JavaScript
299 lines
8.1 KiB
JavaScript
import { createSelector } from 'reselect';
|
|
import { fuzzyMatchAll } from '../../common/misc';
|
|
import * as models from '../../models';
|
|
|
|
// ~~~~~~~~~ //
|
|
// Selectors //
|
|
// ~~~~~~~~~ //
|
|
|
|
export const selectEntitiesLists = createSelector(
|
|
state => state.entities,
|
|
entities => {
|
|
const entitiesLists = {};
|
|
|
|
for (const k of Object.keys(entities)) {
|
|
const entityMap = entities[k];
|
|
entitiesLists[k] = Object.keys(entityMap).map(id => entityMap[id]);
|
|
}
|
|
|
|
return entitiesLists;
|
|
},
|
|
);
|
|
|
|
export const selectEntitiesChildrenMap = createSelector(
|
|
selectEntitiesLists,
|
|
entities => {
|
|
const parentLookupMap = {};
|
|
for (const k of Object.keys(entities)) {
|
|
for (const e of entities[k]) {
|
|
if (!e.parentId) {
|
|
continue;
|
|
}
|
|
|
|
if (parentLookupMap[e.parentId]) {
|
|
parentLookupMap[e.parentId].push(e);
|
|
} else {
|
|
parentLookupMap[e.parentId] = [e];
|
|
}
|
|
}
|
|
}
|
|
|
|
return parentLookupMap;
|
|
},
|
|
);
|
|
|
|
export const selectActiveWorkspace = createSelector(
|
|
state => selectEntitiesLists(state).workspaces,
|
|
state => state.entities,
|
|
state => state.global.activeWorkspaceId,
|
|
(workspaces, entities, activeWorkspaceId) => {
|
|
return entities.workspaces[activeWorkspaceId] || workspaces[0];
|
|
},
|
|
);
|
|
|
|
export const selectActiveWorkspaceClientCertificates = createSelector(
|
|
selectEntitiesLists,
|
|
selectActiveWorkspace,
|
|
(entities, activeWorkspace) => {
|
|
return entities.clientCertificates.filter(c => c.parentId === activeWorkspace._id);
|
|
},
|
|
);
|
|
|
|
export const selectActiveWorkspaceMeta = createSelector(
|
|
selectActiveWorkspace,
|
|
selectEntitiesLists,
|
|
(activeWorkspace, entities) => {
|
|
const id = activeWorkspace ? activeWorkspace._id : 'n/a';
|
|
return entities.workspaceMetas.find(m => m.parentId === id);
|
|
},
|
|
);
|
|
|
|
export const selectCollapsedRequestGroups = createSelector(
|
|
selectEntitiesLists,
|
|
entities => {
|
|
const collapsed = {};
|
|
|
|
// Default all to collapsed
|
|
for (const requestGroup of entities.requestGroups) {
|
|
collapsed[requestGroup._id] = true;
|
|
}
|
|
|
|
// Update those that have metadata (not all do)
|
|
for (const meta of entities.requestGroupMetas) {
|
|
collapsed[meta.parentId] = meta.collapsed;
|
|
}
|
|
|
|
return collapsed;
|
|
},
|
|
);
|
|
|
|
export const selectActiveWorkspaceEntities = createSelector(
|
|
selectActiveWorkspace,
|
|
selectEntitiesChildrenMap,
|
|
(activeWorkspace, childrenMap) => {
|
|
const descendants = [activeWorkspace];
|
|
const addChildrenOf = parent => {
|
|
const children = childrenMap[parent._id] || [];
|
|
for (const child of children) {
|
|
descendants.push(child);
|
|
addChildrenOf(child);
|
|
}
|
|
};
|
|
|
|
// Kick off the recursion
|
|
addChildrenOf(activeWorkspace);
|
|
|
|
return descendants;
|
|
},
|
|
);
|
|
|
|
export const selectPinnedRequests = createSelector(
|
|
selectEntitiesLists,
|
|
entities => {
|
|
const pinned = {};
|
|
|
|
// Default all to unpinned
|
|
for (const request of entities.requests) {
|
|
pinned[request._id] = false;
|
|
}
|
|
|
|
// Update those that have metadata (not all do)
|
|
for (const meta of entities.requestMetas) {
|
|
pinned[meta.parentId] = meta.pinned;
|
|
}
|
|
|
|
return pinned;
|
|
},
|
|
);
|
|
|
|
export const selectSidebarChildren = createSelector(
|
|
selectCollapsedRequestGroups,
|
|
selectPinnedRequests,
|
|
selectActiveWorkspace,
|
|
selectActiveWorkspaceMeta,
|
|
selectEntitiesChildrenMap,
|
|
(collapsed, pinned, activeWorkspace, activeWorkspaceMeta, childrenMap) => {
|
|
const sidebarFilter = activeWorkspaceMeta ? activeWorkspaceMeta.sidebarFilter : '';
|
|
|
|
function next(parentId, pinnedChildren) {
|
|
const children = (childrenMap[parentId] || [])
|
|
.filter(doc => {
|
|
return doc.type === models.request.type || doc.type === models.requestGroup.type;
|
|
})
|
|
.sort((a, b) => {
|
|
if (a.metaSortKey === b.metaSortKey) {
|
|
return a._id > b._id ? -1 : 1;
|
|
} else {
|
|
return a.metaSortKey < b.metaSortKey ? -1 : 1;
|
|
}
|
|
});
|
|
|
|
if (children.length > 0) {
|
|
return children.map(c => {
|
|
const child = {
|
|
doc: c,
|
|
hidden: false,
|
|
collapsed: !!collapsed[c._id],
|
|
pinned: !!pinned[c._id],
|
|
};
|
|
|
|
if (child.pinned) {
|
|
pinnedChildren.push(child);
|
|
}
|
|
|
|
// Don't add children of requests
|
|
child.children = c.type === models.request.type ? [] : next(c._id, pinnedChildren);
|
|
|
|
return child;
|
|
});
|
|
} else {
|
|
return children;
|
|
}
|
|
}
|
|
|
|
function matchChildren(children, parentNames = []) {
|
|
// Bail early if no filter defined
|
|
if (!sidebarFilter) {
|
|
return children;
|
|
}
|
|
|
|
for (const child of children) {
|
|
// Gather all parents so we can match them too
|
|
matchChildren(child.children, [...parentNames, child.doc.name]);
|
|
|
|
const hasMatchedChildren = child.children.find(c => c.hidden === false);
|
|
|
|
// Try to match request attributes
|
|
const { name, method } = child.doc;
|
|
const match = fuzzyMatchAll(sidebarFilter, [name, method, ...parentNames], {
|
|
splitSpace: true,
|
|
});
|
|
|
|
// Update hidden state depending on whether it matched
|
|
const matched = hasMatchedChildren || match;
|
|
child.hidden = !matched;
|
|
}
|
|
|
|
return children;
|
|
}
|
|
|
|
let pinnedChildren = [];
|
|
const childrenTree = next(activeWorkspace._id, pinnedChildren);
|
|
const matchedChildren = matchChildren(childrenTree);
|
|
|
|
return { pinned: pinnedChildren, all: matchedChildren };
|
|
},
|
|
);
|
|
|
|
export const selectWorkspaceRequestsAndRequestGroups = createSelector(
|
|
selectActiveWorkspaceEntities,
|
|
entities => {
|
|
return entities.filter(
|
|
e => e.type === models.request.type || e.type === models.requestGroup.type,
|
|
);
|
|
},
|
|
);
|
|
|
|
export const selectActiveRequest = createSelector(
|
|
state => state.entities,
|
|
selectActiveWorkspaceMeta,
|
|
(entities, workspaceMeta) => {
|
|
const id = workspaceMeta ? workspaceMeta.activeRequestId : 'n/a';
|
|
return entities.requests[id] || null;
|
|
},
|
|
);
|
|
|
|
export const selectActiveCookieJar = createSelector(
|
|
selectEntitiesLists,
|
|
selectActiveWorkspace,
|
|
(entities, workspace) => {
|
|
const cookieJar = entities.cookieJars.find(cj => cj.parentId === workspace._id);
|
|
return cookieJar || null;
|
|
},
|
|
);
|
|
|
|
export const selectActiveOAuth2Token = createSelector(
|
|
selectEntitiesLists,
|
|
selectActiveWorkspaceMeta,
|
|
(entities, workspaceMeta) => {
|
|
const id = workspaceMeta ? workspaceMeta.activeRequestId : 'n/a';
|
|
return entities.oAuth2Tokens.find(t => t.parentId === id);
|
|
},
|
|
);
|
|
|
|
export const selectUnseenWorkspaces = createSelector(
|
|
selectEntitiesLists,
|
|
entities => {
|
|
const { workspaces, workspaceMetas } = entities;
|
|
return workspaces.filter(workspace => {
|
|
const meta = workspaceMetas.find(m => m.parentId === workspace._id);
|
|
return !!(meta && !meta.hasSeen);
|
|
});
|
|
},
|
|
);
|
|
|
|
export const selectActiveRequestMeta = createSelector(
|
|
selectActiveRequest,
|
|
selectEntitiesLists,
|
|
(activeRequest, entities) => {
|
|
const id = activeRequest ? activeRequest._id : 'n/a';
|
|
return entities.requestMetas.find(m => m.parentId === id);
|
|
},
|
|
);
|
|
|
|
export const selectActiveRequestResponses = createSelector(
|
|
selectActiveRequest,
|
|
selectEntitiesLists,
|
|
(activeRequest, entities) => {
|
|
const requestId = activeRequest ? activeRequest._id : 'n/a';
|
|
return entities.responses
|
|
.filter(response => requestId === response.parentId)
|
|
.sort((a, b) => (a.created > b.created ? -1 : 1));
|
|
},
|
|
);
|
|
|
|
export const selectActiveResponse = createSelector(
|
|
selectActiveRequestMeta,
|
|
selectActiveRequestResponses,
|
|
(activeRequestMeta, responses) => {
|
|
const activeResponseId = activeRequestMeta ? activeRequestMeta.activeResponseId : 'n/a';
|
|
const activeResponse = responses.find(response => response._id === activeResponseId);
|
|
|
|
if (activeResponse) {
|
|
return activeResponse;
|
|
}
|
|
|
|
return responses[0] || null;
|
|
},
|
|
);
|
|
|
|
export const selectSyncItems = createSelector(
|
|
selectActiveWorkspaceEntities,
|
|
workspaceEntities =>
|
|
workspaceEntities.filter(models.canSync).map(doc => ({
|
|
key: doc._id,
|
|
name: doc.name || '',
|
|
document: doc,
|
|
})),
|
|
);
|