diff --git a/src/PBSlib.coffee b/src/PBSlib.coffee index f6a95c5..a4e1fb2 100644 --- a/src/PBSlib.coffee +++ b/src/PBSlib.coffee @@ -1,14 +1,17 @@ class PBS constructor: (obj, @verbose, @errListener) -> @days = [] + @resources = [] @criticalPaths = [] + @verbose = yes if obj.push # is a list @list = obj else if obj.activities @list = obj.activities + if obj.resources?.push? then @resources = obj.resources else @list = [] - @err 'data is not an array nor a object with "activities" array' + @err 'data is not an array nor a object with "activities" array' log: (x...) -> if @verbose @@ -21,6 +24,24 @@ class PBS else console.log "[ !Pert! ]", x... if @errListener?.call? then @errListener x + compileResources: => + @log 'compiling resources...' + if not @resources? then return + @resources.forEach (x) => + @log 'processing resource', x + if x.assignedTo?.push? then x.assignedTo.forEach (i) => + a = @toActivity i + a.assigned ?= [] + a.assigned.push x.name or x.id + @list.forEach (x) => + item = @toActivity x + if item.assigned?.push? then item.assigned.forEach (i) => + res = @toResource i + if res + @log 'found', res, 'assigned to', item + res.assignedTo ?= [] + res.assignedTo.push i + # Returns the highest number in an array of numbers maxa: (l) -> return Math.max.apply null, l @@ -32,6 +53,14 @@ class PBS if x.id is id then item = x return item + # Find the activity with given id + toResource: (id) => + unless @resources?.push? then return + item = {} + for i,x of @resources + if x.id is id or x.name is id then item = x + return item + # Compute the item's end day calculateEndDay: (item) => if !item.startDay? @@ -83,11 +112,14 @@ class PBS @log "calculating path from",path lastID = path[path.length - 1] last = @toActivity lastID - if last.dependant? and last.dependant.length > 0 + if last.permittedDelay > 0 + @log "dead end at", lastID, "because its delay is", last.permittedDelay + else if last.dependant? and last.dependant.length > 0 last.dependant.forEach (x) => ii = @toActivity x delay = ii.permittedDelay or 0 if delay is 0 + @log 'following path from', last.id, 'to', ii.id, 'because', ii, 'has', ii.permittedDelay, 'days of free delay' @calculateCriticalPaths path.concat x else @log "dead end at", lastID, "-->", x, "because delay is", delay @@ -124,13 +156,16 @@ class PBS for x,i in @list if !x.depends? or x.depends.length is 0 @calculateCriticalPaths [x.id] - results = activities: @list, days: @days, criticalPaths: @criticalPaths + @compileResources() + results = + activities: @list + days: @days + criticalPaths: @criticalPaths + resources: @resources || [] + @log 'Done', results if options?.json if cb? then cb(JSON.stringify results) JSON.stringify results else if cb? then cb(results) results - -# export module to node environment -if module?.exports? then module.exports = PBS diff --git a/src/app.coffee b/src/app.coffee index 46db041..b96e71e 100644 --- a/src/app.coffee +++ b/src/app.coffee @@ -33,13 +33,18 @@ pertApp.config ($stateProvider,$urlRouterProvider,$locationProvider) -> templateUrl: 'table.html' controller: pertController + $stateProvider.state 'resources', + url: '/resources' + templateUrl: 'resources.html' + controller: pertController + # "Main" Controller pertController = ($scope) -> $scope.toLocalStorage = (data,options) -> options ?= {} data ?= [] - if !data.push? - return swal 'Error', 'data is not a list', 'error' + if !data.push? and !data.activities?.push? + return swal 'Error', 'data is not a valid PBSlib object', 'error' try sdata = JSON.stringify data console.log "Saving: "+sdata @@ -54,22 +59,17 @@ pertController = ($scope) -> $scope.fromLocalStorage = (options) -> options = options || {} data = localStorage.getItem options.name || 'ganttpert' - if data is null then data = "[]" + if data is null then data = '{"activities":[], "resources":[]}' try jdata = JSON.parse data - if jdata is null then jdata = [] + if jdata is null then jdata = activities: [], resources: [] catch e unless options.silent swal 'JSON Error', e, 'error' - if options.raw - #console.log 'Loading: []' - return [] - else - #console.log 'Loading: {list: [], days: []}' - return list: [], days: [] + return activities: [], resources: [] if options.raw #console.log 'Loading: '+jdata return jdata else #console.log 'Loading: '+$scope.pbs - return $scope.pbs ?= new PBS(jdata).calculate() + return $scope.pbs = new PBS(jdata).calculate() diff --git a/src/controllers.coffee b/src/controllers.coffee index f50b620..11f88d3 100644 --- a/src/controllers.coffee +++ b/src/controllers.coffee @@ -1,12 +1,18 @@ -pertApp.controller 'tableController', ($scope) -> +tableController = ($scope,getList) -> $scope.list = [] $scope.refreshTable = -> - ls = $scope.fromLocalStorage() - if ls? - $scope.list = ls.activities + data = $scope.fromLocalStorage() + if data? + $scope.list = getList data $scope.$on 'dataChanged', $scope.refreshTable $scope.refreshTable() + +pertApp.controller 'tableController', ($scope) -> + tableController $scope, (data) -> data.activities or [] +pertApp.controller 'resourceTableController', ($scope) -> + tableController $scope, (data) -> data.resources or [] + pertApp.controller 'pertDiagController', ($scope) -> $scope.buildGraph = (data) -> if !data? then return @@ -31,7 +37,6 @@ pertApp.controller 'pertDiagController', ($scope) -> style: 'arrow' network = new vis.Network (document.getElementById 'pertDiagram'), { nodes: nodes, edges: connections }, options $scope.rebuild = -> - console.log 'rebuild' $scope.buildGraph $scope.fromLocalStorage() $scope.$on 'dataChanged', $scope.rebuild $scope.rebuild() @@ -52,7 +57,7 @@ pertApp.controller 'ganttDiagController', ($scope) -> pertApp.controller 'rawEditorController', ($scope) -> $scope.reset = -> - $scope.toLocalStorage [] + $scope.toLocalStorage { activities: [], resources: [] } $scope.saveData = -> try data = JSON.parse $scope.taData @@ -61,46 +66,55 @@ pertApp.controller 'rawEditorController', ($scope) -> $scope.toLocalStorage data $scope.reloadData = -> $scope.taData = JSON.stringify $scope.fromLocalStorage silent: yes, raw: yes - $scope.$on 'dataChanged', -> - $scope.reloadData() - #$('#ta').val JSON.stringify $scope.fromLocalStorage silent: yes, raw: yes + $scope.$on 'dataChanged', $scope.reloadData $scope.reloadData() pertApp.controller 'editorController', ($scope) -> - $scope.list = [] - $scope.clone = (id) -> - for i,j of $scope.fromLocalStorage({raw: yes, silent: yes}) + $scope.activities = [] + $scope.resources = [] + $scope.actID = ''; $scope.actDur = ''; $scope.actDeps = '' + $scope.resID = ''; $scope.resName = ''; $scope.resAss = '' + $scope.clone = (isResource, id) -> + data = $scope.fromLocalStorage({raw: yes, silent: yes}) + l = if isResource then data.resources else data.activities + for i,j of $scope.fromLocalStorage({raw: yes, silent: yes}).activities if j.id is id $scope.addNew j.id, j.duration, j.depends swal 'Ok', id+' has been cloned', 'success' return swal 'Ops', 'could not find '+id, 'warning' - $scope.delete = (index,id) -> + $scope.delete = (isResource, index,id) -> newdata = $scope.fromLocalStorage raw: yes + iter = if isResource then newdata.resources else newdata.activities l = [] - if id? then for i,j of newdata - if id isnt j.id + if id? then for i,j of iter + if id isnt j.id and id isnt j.name l.push j - else for i,j of newdata + else for i,j of iter if parseInt(i) isnt index l.push j - diff = newdata.length - l.length - $scope.toLocalStorage l, silent: yes + diff = iter.length - l.length + if isResource + newdata.resources = l + else newdata.activities = l + $scope.toLocalStorage newdata, silent: yes if diff isnt 1 swal 'Done', diff+' item(s) deleted', 'warning' - $scope.addNew = (id, dur, deps) -> - dur ?= $('#new-duration').val().trim() - id ?= $('#new-id').val().trim() + $scope.addNew = (isResource, id, dur, deps) -> + dur ?= if isResource then $scope.resName else $scope.actDur + id ?= if isResource then $scope.resID else $scope.actID if !deps? - deps = $('#new-deps').val().split(' ') + deps = if isResource then $scope.resAss else $scope.actDeps + deps = deps.split ' ' if deps.length is 1 and deps[0] is '' deps = [] - try - dur = parseInt dur - catch e - return swal 'Error', 'duration must be an integer', 'error' + if !isResource + try + dur = parseInt dur + catch e + return swal 'Error', 'duration must be an integer', 'error' try unless isNaN id id = parseInt id @@ -110,13 +124,22 @@ pertApp.controller 'editorController', ($scope) -> deps[i] = parseInt dep catch e newdata = $scope.fromLocalStorage silent: yes, raw: yes - if !newdata? or newdata is null or !newdata.push? - newdata = [] - newdata.push { id: id, duration: dur, depends: deps } - $scope.toLocalStorage newdata, silent: yes + if isResource + if newdata?.resources?.push? + console.log newdata.resources + newdata.resources.push { id: id, name: dur, assignedTo: deps } + $scope.toLocalStorage newdata, silent: yes + else console.log "wtf cant add, data broken" + else + if newdata?.activities?.push? + newdata.activities.push { id: id, duration: dur, depends: deps } + $scope.toLocalStorage newdata, silent: yes + else console.log "wtf cant add, data broken" + $scope.refreshEditor = -> data = $scope.fromLocalStorage { silent: yes, raw: yes } - $scope.list = data || [] + $scope.activities = data.activities || [] + $scope.resources = data.resources || [] $scope.$on 'dataChanged', $scope.refreshEditor $scope.refreshEditor() diff --git a/src/edit.html b/src/edit.html index 5d6d585..1704dab 100644 --- a/src/edit.html +++ b/src/edit.html @@ -4,7 +4,7 @@

Dependencies must be a list of IDs separated by space
the program does not check cyclic or invalid dependencies for you

- +
New Activity @@ -12,21 +12,21 @@
ID - +
Duration - +
Dependencies - +
-
- + @@ -35,11 +35,11 @@ - + - +
#Dependencies Commands
{{$index + 1}} {{item.id}} {{item.duration}}{{item.depends || []}}{{item.depends.join(', ') || "None"}}
+
+ +
+
+ New Resource +
+
+
+ ID + +
+
+ Name + +
+
+ Assigned To + +
+ +
+
+ + + + + + + + + + + + + + + + +
#IDNameAssignationsCommands
{{$index + 1}}{{item.id}}{{item.name}}{{item.assignedTo || []}} + + +
diff --git a/src/index.html b/src/index.html index 47df66a..feca4ed 100644 --- a/src/index.html +++ b/src/index.html @@ -37,7 +37,8 @@