insomnia/app/ui/components/sidebar/Sidebar.js

229 lines
6.7 KiB
JavaScript
Raw Normal View History

import React, {Component, PropTypes} from 'react';
import classnames from 'classnames';
import EnvironmentsDropdown from '../dropdowns/EnvironmentsDropdown';
import SidebarRequestRow from './SidebarRequestRow';
import SidebarRequestGroupRow from './SidebarRequestGroupRow';
import SidebarFilter from './SidebarFilter';
2016-11-11 23:06:24 +00:00
import SyncButton from '../dropdowns/SyncDropdown';
import WorkspaceDropdown from '../dropdowns/WorkspaceDropdown';
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
import {
SIDEBAR_SKINNY_REMS,
COLLAPSE_SIDEBAR_REMS
2016-11-10 02:40:53 +00:00
} from '../../../common/constants';
2016-03-18 00:36:00 +00:00
2016-03-23 05:26:27 +00:00
class Sidebar extends Component {
_filterChildren (filter, children, extra = null) {
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
filter = filter || '';
return children.filter(child => {
if (child.doc.type !== 'Request') {
2016-04-05 05:35:21 +00:00
return true;
}
const request = child.doc;
2016-04-05 05:35:21 +00:00
const otherMatches = extra || '';
const toMatch = `${request.method}${request.name}${otherMatches}`.toLowerCase();
const matchTokens = filter.toLowerCase().split(' ');
2016-04-05 05:35:21 +00:00
for (let i = 0; i < matchTokens.length; i++) {
let token = `${matchTokens[i]}`;
if (toMatch.indexOf(token) === -1) {
// Filter failed. Don't render children
return false;
}
}
2016-04-07 01:11:16 +00:00
return true;
})
2016-03-24 10:20:11 +00:00
}
_renderChildren (children, requestGroup) {
2016-04-29 04:57:03 +00:00
const {
filter,
handleCreateRequest,
2016-11-23 20:44:46 +00:00
handleCreateRequestGroup,
handleSetRequestGroupCollapsed,
moveRequest,
moveRequestGroup,
handleActivateRequest,
activeRequest,
workspace,
2016-04-29 04:57:03 +00:00
} = this.props;
const filteredChildren = this._filterChildren(
filter,
children,
requestGroup && requestGroup.name
);
const activeRequestId = activeRequest ? activeRequest._id : 'n/a';
return filteredChildren.map(child => {
if (child.doc.type === 'Request') {
return (
<SidebarRequestRow
key={child.doc._id}
moveRequest={moveRequest}
handleActivateRequest={handleActivateRequest}
requestCreate={handleCreateRequest.bind(null, workspace._id)}
isActive={child.doc._id === activeRequestId}
request={child.doc}
workspace={workspace}
/>
)
2016-04-29 04:57:03 +00:00
}
2016-05-01 19:56:30 +00:00
2016-04-29 04:57:03 +00:00
// We have a RequestGroup!
2016-04-29 04:57:03 +00:00
const requestGroup = child.doc;
function hasActiveChild (children) {
for (const c of children) {
if (c.children.length) {
return hasActiveChild(c.children);
} else if (c.doc._id === activeRequestId) {
return true;
}
}
// Didn't find anything, so return
return false;
}
const isActive = hasActiveChild(child.children);
2016-04-29 04:57:03 +00:00
const children = this._renderChildren(child.children, requestGroup);
// Don't render the row if there are no children while filtering
if (filter && !children.length) {
return null;
}
2016-04-29 04:57:03 +00:00
return (
<SidebarRequestGroupRow
handleActivateRequest={handleActivateRequest}
2016-04-29 04:57:03 +00:00
key={requestGroup._id}
isActive={isActive}
moveRequestGroup={moveRequestGroup}
moveRequest={moveRequest}
handleSetRequestGroupCollapsed={handleSetRequestGroupCollapsed}
isCollapsed={child.collapsed}
handleCreateRequest={handleCreateRequest.bind(null, requestGroup._id)}
2016-11-23 20:44:46 +00:00
handleCreateRequestGroup={handleCreateRequestGroup.bind(null, requestGroup._id)}
2016-04-29 04:57:03 +00:00
numChildren={child.children.length}
workspace={workspace}
requestGroup={requestGroup}
children={children}
/>
2016-04-29 04:57:03 +00:00
)
})
2016-03-24 10:20:11 +00:00
}
2016-03-23 05:26:27 +00:00
render () {
const {
showCookiesModal,
filter,
children,
hidden,
handleCreateRequest,
handleCreateRequestGroup,
width,
workspace,
workspaces,
environments,
activeEnvironment,
handleSetActiveEnvironment,
handleSetActiveWorkspace,
handleImportFile,
handleExportFile,
handleChangeFilter,
isLoading,
} = this.props;
2016-03-23 05:26:27 +00:00
return (
<aside className={classnames('sidebar', {
'sidebar--hidden': hidden,
'sidebar--skinny': width < SIDEBAR_SKINNY_REMS,
'sidebar--collapsed': width < COLLAPSE_SIDEBAR_REMS
})}>
<WorkspaceDropdown
className="sidebar__header"
activeWorkspace={workspace}
workspaces={workspaces}
handleExportFile={handleExportFile}
handleImportFile={handleImportFile}
handleSetActiveWorkspace={handleSetActiveWorkspace}
isLoading={isLoading}
/>
<div className="sidebar__menu">
<EnvironmentsDropdown
handleChangeEnvironment={id => handleSetActiveEnvironment(workspace._id, id)}
activeEnvironment={activeEnvironment}
environments={environments}
workspace={workspace}
/>
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
<button className="btn btn--super-compact"
onClick={e => showCookiesModal()}>
<div className="sidebar__menu__thing">
<span>Cookies</span>
</div>
</button>
</div>
<SidebarFilter
onChange={filter => handleChangeFilter(filter)}
requestCreate={handleCreateRequest.bind(null, workspace._id)}
requestGroupCreate={handleCreateRequestGroup.bind(null, workspace._id)}
filter={filter}
/>
<ul className="sidebar__list sidebar__list-root">
2016-05-01 19:56:30 +00:00
{this._renderChildren(children)}
</ul>
<SyncButton
className="sidebar__footer"
key={workspace._id}
workspace={workspace}
/>
2016-05-01 19:56:30 +00:00
</aside>
2016-03-23 05:26:27 +00:00
)
}
}
2016-03-18 00:36:00 +00:00
2016-03-20 04:00:40 +00:00
Sidebar.propTypes = {
// Functions
handleActivateRequest: PropTypes.func.isRequired,
handleSetRequestGroupCollapsed: PropTypes.func.isRequired,
handleChangeFilter: PropTypes.func.isRequired,
handleImportFile: PropTypes.func.isRequired,
handleExportFile: PropTypes.func.isRequired,
handleSetActiveWorkspace: PropTypes.func.isRequired,
handleSetActiveEnvironment: PropTypes.func.isRequired,
moveRequest: PropTypes.func.isRequired,
moveRequestGroup: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired,
handleCreateRequestGroup: PropTypes.func.isRequired,
showEnvironmentsModal: PropTypes.func.isRequired,
showCookiesModal: PropTypes.func.isRequired,
// Other
hidden: PropTypes.bool.isRequired,
width: PropTypes.number.isRequired,
isLoading: PropTypes.bool.isRequired,
children: PropTypes.array.isRequired,
workspace: PropTypes.object.isRequired,
workspaces: PropTypes.arrayOf(PropTypes.object).isRequired,
environments: PropTypes.arrayOf(PropTypes.object).isRequired,
// Optional
filter: PropTypes.string,
activeRequest: PropTypes.object,
activeEnvironment: PropTypes.object,
2016-03-20 04:00:40 +00:00
};
2016-03-18 00:36:00 +00:00
export default Sidebar;