Edition via drag & drop des items

This commit is contained in:
2015-09-11 16:25:45 +02:00
parent 06c809a114
commit 1136b693fd
26 changed files with 665 additions and 67 deletions

49
js/store/actions/edit.js Normal file
View File

@ -0,0 +1,49 @@
var Util = require('../../util');
var path = require('path');
// Action types
var LOAD_DESKTOP_APPS = exports.LOAD_PROFILE = 'LOAD_DESKTOP_APPS';
var LOAD_DESKTOP_APPS_SUCCESS = exports.LOAD_DESKTOP_APPS_SUCCESS = 'LOAD_DESKTOP_APPS_SUCCESS';
var LOAD_DESKTOP_APPS_FAILED = exports.LOAD_DESKTOP_APPS_FAILED = 'LOAD_DESKTOP_APPS_FAILED';
var MOVE_PROFILE_ITEM = exports.MOVE_PROFILE_ITEM = 'MOVE_PROFILE_ITEM';
var ADD_PROFILE_ITEM = exports.ADD_PROFILE_ITEM = 'ADD_PROFILE_ITEM';
// Actions creators
exports.loadDesktopApps = function() {
return function(dispatch, getState) {
var baseDirs = global.process.env.XDG_DATA_DIRS.split(':').map(function(baseDir){
return path.join(baseDir, 'applications');
});
dispatch({ type: LOAD_DESKTOP_APPS });
return Util.DesktopApps.loadAllDesktopFiles(baseDirs)
.then(function(desktopApps) {
dispatch({ type: LOAD_DESKTOP_APPS_SUCCESS, desktopApps: desktopApps });
})
.catch(function(err) {
dispatch({ type: LOAD_DESKTOP_APPS_FAILED, error: err });
})
;
};
};
exports.moveProfileItem = function(movedItem, targetItem) {
return {
type: 'MOVE_PROFILE_ITEM',
movedItem: movedItem,
targetItem: targetItem
};
};
exports.addProfileItem = function(newItem, targetItem) {
return {
type: 'ADD_PROFILE_ITEM',
newItem: newItem,
targetItem: targetItem
};
};

View File

@ -0,0 +1,2 @@
exports.launcher = require('./launcher');
exports.edit = require('./edit');

View File

@ -0,0 +1,51 @@
var Util = require('../../util');
var LOAD_PROFILE = exports.LOAD_PROFILE = 'LOAD_PROFILE';
var LOAD_PROFILE_SUCCESS = exports.LOAD_PROFILE_SUCCESS = 'LOAD_PROFILE_SUCCESS';
var LOAD_PROFILE_FAILED = exports.LOAD_PROFILE_FAILED = 'LOAD_PROFILE_FAILED';
var RUN_APP = exports.RUN_APP = 'RUN_APP';
var RUN_APP_SUCCESS = exports.RUN_APP_SUCCESS = 'RUN_APP_SUCCESS';
var RUN_APP_FAILED = exports.RUN_APP_FAILED = 'RUN_APP_FAILED';
exports.loadProfile = function(profilePath) {
return function(dispatch, getState) {
dispatch({ type: LOAD_PROFILE, profilePath: profilePath });
return Util.System.loadJSONFile(profilePath)
.then(function(profile) {
dispatch({ type: LOAD_PROFILE_SUCCESS, profile: profile });
return profile;
})
.catch(function(err) {
dispatch({ type: LOAD_PROFILE_FAILED, error: err });
return err;
})
;
};
};
exports.runApp = function(execPath) {
return function(dispatch, getState) {
dispatch({ type: RUN_APP, execPath: execPath });
return Util.System.runApp(execPath)
.then(function() {
dispatch({ type: RUN_APP_SUCCESS, execPath: execPath });
return execPath;
})
.catch(function(err) {
dispatch({ type: RUN_APP_FAILED, error: err });
return err;
})
;
};
};

View File

@ -2,9 +2,11 @@ var redux = require('redux');
var thunkMiddleware = require('redux-thunk');
var loggerMiddleware = require('redux-logger');
var reducers = require('./reducers');
var loggerMiddleware = require('./middlewares/logger');
var createStore = redux.applyMiddleware(
thunkMiddleware
thunkMiddleware,
loggerMiddleware
)(redux.createStore);
var appReducer = redux.combineReducers({

View File

@ -0,0 +1,15 @@
var debug = require('../../util/debug')('store:logger');
module.exports = function loggerMiddleware(store) {
return function(next) {
return function(action) {
debug('Action %j', action);
debug('Store current state %j', store.getState());
next(action);
debug('Store new state %j', store.getState());
if(action.error) {
console.error(action.error.stack || action.error);
}
};
};
};

View File

@ -1,8 +1,8 @@
var actions = require('../../actions');
var actions = require('../actions');
module.exports = function(state, action) {
var desktopApps = [];
var desktopApps = state || [];
if( action.type === actions.edit.LOAD_DESKTOP_APPS_SUCCESS ) {
desktopApps = action.desktopApps;

View File

@ -1,17 +1,72 @@
var actions = require('../../actions');
var _ = require('lodash');
var actions = require('../actions');
module.exports = function(oldProfile, action) {
var newProfile = oldProfile || null;
switch(action.type) {
case actions.launcher.LOAD_PROFILE_SUCCESS:
newProfile = action.profile;
break;
return _.cloneDeep(action.profile);
case actions.edit.MOVE_PROFILE_ITEM:
return moveProfileItem(oldProfile, action.movedItem, action.targetItem);
case actions.edit.ADD_PROFILE_ITEM:
return addProfileItem(oldProfile, action.newItem, action.targetItem);
default:
return oldProfile || null;
}
};
function moveProfileItem(oldProfile, movedItem, targetItem) {
var newProfile = _.cloneDeep(oldProfile);
var previousParent = treeFind(newProfile, movedItem).parent;
var newParent = treeFind(newProfile, targetItem).item;
previousParent.items = _.reject(previousParent.items, function(item) {
return _.isEqual(item, movedItem);
});
newParent.items = newParent.items || [];
newParent.items.push(_.cloneDeep(movedItem));
return newProfile;
};
}
function addProfileItem(oldProfile, newItem, targetItem) {
var newProfile = _.cloneDeep(oldProfile);
var newParent = treeFind(newProfile, targetItem).item;
newParent.items = newParent.items || [];
newParent.items.push(_.cloneDeep(newItem));
return newProfile;
}
function treeFind(branch, obj) {
var items = branch.items;
if(!items) return;
for( var i = 0, item = items[i]; (item = items[i]); i++ ) {
if( _.isEqual(item, obj) ) {
return {item: item, parent: branch};
}
if(item.items) {
var result = treeFind(item, obj);
if(result) return result;
}
}
}