mirror of
https://github.com/xodio/xod.git
synced 2026-03-14 20:56:52 +01:00
feat(xod-client): show/hide deprecated patches in the ProjectBrowser by toggling filter option
This commit is contained in:
@@ -1,52 +0,0 @@
|
||||
.PanelToolbar {
|
||||
display: block;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
background-color: $chrome-title-bg;
|
||||
|
||||
button {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 1;
|
||||
|
||||
background: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
color: $sidebar-color-text;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: $sidebar-color-text-hover;
|
||||
}
|
||||
|
||||
&.addlib{
|
||||
@extend .icon-addlib;
|
||||
}
|
||||
&.newpatch{
|
||||
@extend .icon-newpatch;
|
||||
}
|
||||
&.contextmenu {
|
||||
@extend .icon-contextmenu;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: $font-size-m;
|
||||
color: $light-grey-bright;
|
||||
float: left;
|
||||
line-height: 18px;
|
||||
padding: 3px;
|
||||
}
|
||||
&-buttons {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,9 @@
|
||||
&.newpatch{
|
||||
@extend .icon-newpatch;
|
||||
}
|
||||
&.filter {
|
||||
@extend .icon-filter;
|
||||
}
|
||||
&.contextmenu {
|
||||
@extend .icon-contextmenu;
|
||||
opacity: 0.7;
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
'components/Modals',
|
||||
'components/Node',
|
||||
'components/NoPatch',
|
||||
'components/PanelToolbar',
|
||||
'components/PatchDocs',
|
||||
'components/PatchGroup',
|
||||
'components/PatchGroupItem',
|
||||
|
||||
@@ -4,3 +4,5 @@ export const PATCH_DELETE_REQUESTED = 'PATCH_DELETE_REQUESTED';
|
||||
|
||||
export const SET_SELECTION = 'SET_SELECTION';
|
||||
export const REMOVE_SELECTION = 'REMOVE_SELECTION';
|
||||
|
||||
export const TOGGLE_DEPRECATED_FILTER = 'TOGGLE_DEPRECATED_FILTER';
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
PATCH_DELETE_REQUESTED,
|
||||
SET_SELECTION,
|
||||
REMOVE_SELECTION,
|
||||
TOGGLE_DEPRECATED_FILTER,
|
||||
} from './actionTypes';
|
||||
|
||||
import { getSelectedPatchPath } from './selectors';
|
||||
@@ -49,3 +50,7 @@ export const setSelection = selectedPatchPath => ({
|
||||
export const removeSelection = () => ({
|
||||
type: REMOVE_SELECTION,
|
||||
});
|
||||
|
||||
export const toggleDeprecatedFilter = () => ({
|
||||
type: TOGGLE_DEPRECATED_FILTER,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Id of context menu to show it
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const PATCH_GROUP_CONTEXT_MENU_ID = 'PATCH_GROUP_CONTEXT_MENU_ID';
|
||||
export const FILTER_CONTEXT_MENU_ID = 'FILTER_CONTEXT_MENU_ID';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { Icon } from 'react-fa';
|
||||
import { HotKeys } from 'react-hotkeys';
|
||||
import { ContextMenuTrigger } from 'react-contextmenu';
|
||||
import { ContextMenuTrigger, ContextMenu, MenuItem } from 'react-contextmenu';
|
||||
|
||||
import $ from 'sanctuary-def';
|
||||
import {
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
isPathLocal,
|
||||
getBaseName,
|
||||
PatchPath,
|
||||
isDeprecatedPatch,
|
||||
} from 'xod-project';
|
||||
import { isAmong, notEquals, $Maybe, foldMaybe } from 'xod-func-tools';
|
||||
|
||||
@@ -36,16 +37,23 @@ import PatchGroupItem from '../components/PatchGroupItem';
|
||||
import ProjectBrowserPopups from '../components/ProjectBrowserPopups';
|
||||
import PatchGroupItemContextMenu from '../components/PatchGroupItemContextMenu';
|
||||
|
||||
import { PATCH_GROUP_CONTEXT_MENU_ID } from '../constants';
|
||||
import {
|
||||
PATCH_GROUP_CONTEXT_MENU_ID,
|
||||
FILTER_CONTEXT_MENU_ID,
|
||||
} from '../constants';
|
||||
import { PANEL_IDS, SIDEBAR_IDS } from '../../editor/constants';
|
||||
import { triggerUpdateHelpboxPositionViaProjectBrowser } from '../../editor/utils';
|
||||
|
||||
const pickPatchPartsForComparsion = R.map(R.pick(['dead', 'path']));
|
||||
const pickPatchPartsForComparsion = R.map(
|
||||
R.pick(['deprecated', 'dead', 'path'])
|
||||
);
|
||||
|
||||
const checkmark = active => (active ? <span className="state">✔</span> : null);
|
||||
|
||||
const pickPropsForComparsion = R.compose(
|
||||
R.evolve({
|
||||
localPatches: pickPatchPartsForComparsion,
|
||||
libs: pickPatchPartsForComparsion,
|
||||
libs: R.map(pickPatchPartsForComparsion),
|
||||
}),
|
||||
R.omit(['actions'])
|
||||
);
|
||||
@@ -178,9 +186,11 @@ class ProjectBrowser extends React.Component {
|
||||
|
||||
const collectPropsFn = this.getCollectPropsFn(path);
|
||||
|
||||
const key = `${path}${deprecated ? '_deprecated' : ''}`;
|
||||
|
||||
return (
|
||||
<PatchGroupItem
|
||||
key={path}
|
||||
key={key}
|
||||
patchPath={path}
|
||||
dead={dead}
|
||||
label={getBaseName(path)}
|
||||
@@ -235,6 +245,14 @@ class ProjectBrowser extends React.Component {
|
||||
);
|
||||
const installingLibNames = R.pluck('name', installingLibsComponents);
|
||||
|
||||
// Rejecting of deprecated patches is implemented in the
|
||||
// component for better performance.
|
||||
// :: { LibName: [Patch] } -> { LibName: [Patch] }
|
||||
const rejectDeprecatedPatches = R.unless(
|
||||
() => this.props.showDeprecated,
|
||||
R.map(R.reject(isDeprecatedPatch))
|
||||
);
|
||||
|
||||
const libComponents = R.compose(
|
||||
R.reject(R.compose(isAmong(installingLibNames), R.prop('name'))),
|
||||
R.map(([libName, libPatches]) => ({
|
||||
@@ -250,7 +268,8 @@ class ProjectBrowser extends React.Component {
|
||||
</PatchGroup>
|
||||
),
|
||||
})),
|
||||
R.toPairs
|
||||
R.toPairs,
|
||||
rejectDeprecatedPatches
|
||||
)(libs);
|
||||
|
||||
return R.compose(
|
||||
@@ -283,6 +302,17 @@ class ProjectBrowser extends React.Component {
|
||||
title="Add library"
|
||||
onClick={this.onClickAddLibrary}
|
||||
/>,
|
||||
<ContextMenuTrigger
|
||||
id={FILTER_CONTEXT_MENU_ID}
|
||||
key="contextMenuTrigger"
|
||||
renderTag="button"
|
||||
attributes={{
|
||||
className: 'filter',
|
||||
}}
|
||||
holdToDisplay={0}
|
||||
>
|
||||
<span />
|
||||
</ContextMenuTrigger>,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -323,6 +353,12 @@ class ProjectBrowser extends React.Component {
|
||||
onPatchRename={this.props.actions.requestRename}
|
||||
onPatchHelp={this.onPatchHelpClicked}
|
||||
/>
|
||||
<ContextMenu id={FILTER_CONTEXT_MENU_ID}>
|
||||
<MenuItem onClick={this.props.actions.toggleDeprecatedFilter}>
|
||||
{checkmark(this.props.showDeprecated)}
|
||||
Deprecated nodes
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</HotKeys>
|
||||
);
|
||||
}
|
||||
@@ -342,6 +378,7 @@ ProjectBrowser.propTypes = {
|
||||
defaultNodePosition: PropTypes.object.isRequired,
|
||||
sidebarId: PropTypes.oneOf(R.values(SIDEBAR_IDS)).isRequired,
|
||||
autohide: PropTypes.bool.isRequired,
|
||||
showDeprecated: PropTypes.bool.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
addNode: PropTypes.func.isRequired,
|
||||
switchPatch: PropTypes.func.isRequired,
|
||||
@@ -357,6 +394,7 @@ ProjectBrowser.propTypes = {
|
||||
closeAllPopups: PropTypes.func.isRequired,
|
||||
showLibSuggester: PropTypes.func.isRequired,
|
||||
showHelpbox: PropTypes.func.isRequired,
|
||||
toggleDeprecatedFilter: PropTypes.func.isRequired,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -370,6 +408,7 @@ const mapStateToProps = R.applySpec({
|
||||
libs: ProjectBrowserSelectors.getLibs,
|
||||
installingLibs: ProjectBrowserSelectors.getInstallingLibraries,
|
||||
defaultNodePosition: EditorSelectors.getDefaultNodePlacePosition,
|
||||
showDeprecated: ProjectBrowserSelectors.shouldShowDeprecatedPatches,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
@@ -395,6 +434,8 @@ const mapDispatchToProps = dispatch => ({
|
||||
addNotification: MessagesActions.addNotification,
|
||||
showLibSuggester: EditorActions.showLibSuggester,
|
||||
showHelpbox: EditorActions.showHelpbox,
|
||||
|
||||
toggleDeprecatedFilter: ProjectBrowserActions.toggleDeprecatedFilter,
|
||||
},
|
||||
dispatch
|
||||
),
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
PATCH_DELETE_REQUESTED,
|
||||
SET_SELECTION,
|
||||
REMOVE_SELECTION,
|
||||
TOGGLE_DEPRECATED_FILTER,
|
||||
} from './actionTypes';
|
||||
|
||||
import { PATCH_DELETE, PATCH_RENAME } from '../project/actionTypes';
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
INSTALL_LIBRARIES_FAILED,
|
||||
} from '../editor/actionTypes';
|
||||
|
||||
// Reducers
|
||||
const selectionReducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case SET_SELECTION:
|
||||
@@ -52,9 +54,19 @@ const installingLibrariesReducer = (state, action) => {
|
||||
}
|
||||
};
|
||||
|
||||
const filtersReducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case TOGGLE_DEPRECATED_FILTER:
|
||||
return R.over(R.lensProp('deprecated'), R.not, state);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default (state = initialState, action) =>
|
||||
R.merge(state, {
|
||||
selectedPatchPath: selectionReducer(state.selectedPatchPath, action),
|
||||
filters: filtersReducer(state.filters, action),
|
||||
installingLibraries: installingLibrariesReducer(
|
||||
state.installingLibraries,
|
||||
action
|
||||
|
||||
@@ -10,6 +10,11 @@ import { isPatchDeadTerminal } from '../project/utils';
|
||||
|
||||
export const getProjectBrowser = R.prop('projectBrowser');
|
||||
|
||||
export const shouldShowDeprecatedPatches = createSelector(
|
||||
getProjectBrowser,
|
||||
R.path(['filters', 'deprecated'])
|
||||
);
|
||||
|
||||
export const getSelectedPatchPath = createSelector(
|
||||
getProjectBrowser,
|
||||
R.prop('selectedPatchPath')
|
||||
@@ -29,14 +34,23 @@ const markDeadPatches = R.curry((project, patch) =>
|
||||
)(patch, project)
|
||||
);
|
||||
|
||||
export const getLocalPatches = createSelector(
|
||||
// :: Patch -> Patch
|
||||
const markDeprecatedPatches = patch =>
|
||||
R.assoc('deprecated', XP.isDeprecatedPatch(patch), patch);
|
||||
|
||||
const getLocalPatchesList = createSelector(
|
||||
ProjectSelectors.getProject,
|
||||
project =>
|
||||
XP.listLocalPatches
|
||||
);
|
||||
|
||||
export const getLocalPatches = createMemoizedSelector(
|
||||
[getLocalPatchesList, ProjectSelectors.getProject],
|
||||
[R.equals],
|
||||
(patches, project) =>
|
||||
R.compose(
|
||||
R.sortBy(XP.getPatchPath),
|
||||
R.map(markDeadPatches(project)),
|
||||
XP.listLocalPatches
|
||||
)(project)
|
||||
R.map(R.compose(markDeprecatedPatches, markDeadPatches(project)))
|
||||
)(patches)
|
||||
);
|
||||
|
||||
// TODO: this is not actually label anymore
|
||||
@@ -63,7 +77,7 @@ export const getLibs = createMemoizedSelector(
|
||||
R.map(R.sort(R.ascend(XP.getPatchPath))),
|
||||
R.groupBy(R.pipe(XP.getPatchPath, XP.getLibraryName)),
|
||||
R.reject(isPatchDeadTerminal),
|
||||
R.map(markDeadPatches(project))
|
||||
R.map(R.compose(markDeprecatedPatches, markDeadPatches(project)))
|
||||
)(patches)
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
export default {
|
||||
selectedPatchPath: null,
|
||||
filters: {
|
||||
deprecated: false,
|
||||
},
|
||||
installingLibraries: [],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user