From 2b1d1fc4dd692e7a86e10c3128ab41536b1b91ac Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 2 Jun 2016 12:49:00 +0200 Subject: [PATCH 1/2] [feature] basic ability manage steps order --- app/assets/javascripts/app.js.erb | 14 ++++++++++++++ .../controllers/projects.coffee.erb | 2 +- app/assets/templates/projects/_form.html.erb | 11 ++++++++++- app/assets/templates/projects/show.html.erb | 2 +- app/controllers/api/projects_controller.rb | 2 +- app/views/api/projects/show.json.jbuilder | 3 ++- ...60602075531_add_step_nb_to_project_step.rb | 19 +++++++++++++++++++ db/schema.rb | 3 ++- 8 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20160602075531_add_step_nb_to_project_step.rb diff --git a/app/assets/javascripts/app.js.erb b/app/assets/javascripts/app.js.erb index a40c034f4..dabc9e83e 100644 --- a/app/assets/javascripts/app.js.erb +++ b/app/assets/javascripts/app.js.erb @@ -125,6 +125,20 @@ config(['$httpProvider', 'AuthProvider', "growlProvider", "unsavedWarningsConfig // see https://github.com/revolunet/angular-google-analytics#automatic-page-view-tracking Analytics.pageView(); + + /** + * This helper method builds and return an array contaning every integers between + * the provided start and end. + * @param start {number} + * @param end {number} + * @return {Array} [start .. end] + */ + $rootScope.intArray = function(start, end) { + var arr = []; + for (var i = start; i < end; i++) { arr.push(i); } + return arr; + }; + }]).constant('angularMomentConfig', { timezone: Fablab.timezone }); diff --git a/app/assets/javascripts/controllers/projects.coffee.erb b/app/assets/javascripts/controllers/projects.coffee.erb index b9a2f2131..5b2953c3d 100644 --- a/app/assets/javascripts/controllers/projects.coffee.erb +++ b/app/assets/javascripts/controllers/projects.coffee.erb @@ -122,7 +122,7 @@ class ProjectsController # This will create a single new empty entry into the project's steps list. ## $scope.addStep = -> - $scope.project.project_steps_attributes.push {} + $scope.project.project_steps_attributes.push { step_nb: $scope.project.project_steps_attributes.length + 1 } diff --git a/app/assets/templates/projects/_form.html.erb b/app/assets/templates/projects/_form.html.erb index 4dbecba73..7e4d77e9f 100644 --- a/app/assets/templates/projects/_form.html.erb +++ b/app/assets/templates/projects/_form.html.erb @@ -74,9 +74,18 @@
- {{ 'step_N' | translate:{ INDEX:$index+1 } }}/{{project.project_steps_attributes.length}} +
+ + +
+ +
-

{{ 'step_N' | translate:{INDEX:$index+1} }} : {{step.title}}

+

{{ 'step_N' | translate:{INDEX:step.step_nb} }} : {{step.title}}

{{step.title}} diff --git a/app/controllers/api/projects_controller.rb b/app/controllers/api/projects_controller.rb index f78ffe555..2a6d4fffe 100644 --- a/app/controllers/api/projects_controller.rb +++ b/app/controllers/api/projects_controller.rb @@ -66,7 +66,7 @@ class API::ProjectsController < API::ApiController params.require(:project).permit(:name, :description, :tags, :machine_ids, :component_ids, :theme_ids, :licence_id, :author_id, :licence_id, :state, user_ids: [], machine_ids: [], component_ids: [], theme_ids: [], project_image_attributes: [:attachment], project_caos_attributes: [:id, :attachment, :_destroy], - project_steps_attributes: [:id, :description, :title, :_destroy, + project_steps_attributes: [:id, :description, :title, :_destroy, :step_nb, :project_step_image_attributes => :attachment]) end end diff --git a/app/views/api/projects/show.json.jbuilder b/app/views/api/projects/show.json.jbuilder index 495a9c42c..ab13940d7 100644 --- a/app/views/api/projects/show.json.jbuilder +++ b/app/views/api/projects/show.json.jbuilder @@ -46,12 +46,13 @@ json.project_users @project.project_users do |pu| json.slug pu.user.slug json.is_valid pu.is_valid end -json.project_steps_attributes @project.project_steps.order('project_steps.created_at ASC') do |s| +json.project_steps_attributes @project.project_steps.order('project_steps.step_nb ASC') do |s| json.id s.id json.description s.description json.title s.title json.project_step_image s.project_step_image.attachment_identifier if s.project_step_image json.project_step_image_url s.project_step_image.attachment.medium.url if s.project_step_image + json.step_nb s.step_nb end json.state @project.state json.licence do diff --git a/db/migrate/20160602075531_add_step_nb_to_project_step.rb b/db/migrate/20160602075531_add_step_nb_to_project_step.rb new file mode 100644 index 000000000..2f41200f8 --- /dev/null +++ b/db/migrate/20160602075531_add_step_nb_to_project_step.rb @@ -0,0 +1,19 @@ +class AddStepNbToProjectStep < ActiveRecord::Migration + def up + add_column :project_steps, :step_nb, :integer + execute 'UPDATE project_steps + SET step_nb = subquery.index + FROM ( + SELECT + id, project_id, created_at, + row_number() OVER (PARTITION BY project_id) AS index + FROM project_steps + ORDER BY created_at + ) AS subquery + WHERE project_steps.id = subquery.id;' + end + + def down + remove_column :project_steps, :step_nb + end +end diff --git a/db/schema.rb b/db/schema.rb index 1085aac04..bd88b76bb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160526102307) do +ActiveRecord::Schema.define(version: 20160602075531) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -337,6 +337,7 @@ ActiveRecord::Schema.define(version: 20160526102307) do t.datetime "created_at" t.datetime "updated_at" t.string "title", limit: 255 + t.integer "step_nb" end add_index "project_steps", ["project_id"], name: "index_project_steps_on_project_id", using: :btree From 48a90bb7b4d1071797b0250bf65898664b11416d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 2 Jun 2016 16:02:08 +0200 Subject: [PATCH 2/2] advanced project step modulation with automatic re-ordering --- .../controllers/projects.coffee.erb | 62 ++++++++++++++----- app/assets/templates/projects/_form.html.erb | 6 +- config/locales/app.shared.en.yml | 1 + config/locales/app.shared.fr.yml | 1 + 4 files changed, 53 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/controllers/projects.coffee.erb b/app/assets/javascripts/controllers/projects.coffee.erb index 5b2953c3d..f645cf09e 100644 --- a/app/assets/javascripts/controllers/projects.coffee.erb +++ b/app/assets/javascripts/controllers/projects.coffee.erb @@ -7,6 +7,7 @@ # in the various projects' admin controllers. # # Provides : +# - $scope.totalSteps # - $scope.machines = [{Machine}] # - $scope.components = [{Component}] # - $scope.themes = [{Theme}] @@ -17,6 +18,7 @@ # - $scope.deleteFile(file) # - $scope.addStep() # - $scope.deleteStep(step) +# - $scope.changeStepIndex(step, newIdx) # # Requires : # - $scope.project.project_caos_attributes = [] @@ -24,7 +26,7 @@ # - $state (Ui-Router) [ 'app.public.projects_show', 'app.public.projects_list' ] ## class ProjectsController - constructor: ($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document)-> + constructor: ($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, dialogs, _t)-> ## Retrieve the list of machines from the server Machine.query().$promise.then (data)-> @@ -50,6 +52,8 @@ class ProjectsController id: d.id name: d.name + $scope.totalSteps = $scope.project.project_steps_attributes.length + ## @@ -122,22 +126,52 @@ class ProjectsController # This will create a single new empty entry into the project's steps list. ## $scope.addStep = -> - $scope.project.project_steps_attributes.push { step_nb: $scope.project.project_steps_attributes.length + 1 } + $scope.totalSteps += 1 + $scope.project.project_steps_attributes.push { step_nb: $scope.totalSteps } + ## - # This will remove the given stip from the project's steps list. If the step was previously saved + # This will remove the given step from the project's steps list. If the step was previously saved # on the server, it will be marked for deletion for the next saving. Otherwise, it will be simply truncated from # the steps array. # @param file {Object} the file to delete ## $scope.deleteStep = (step) -> - index = $scope.project.project_steps_attributes.indexOf(step) - if step.id? - step._destroy = true - else - $scope.project.project_steps_attributes.splice(index, 1) + dialogs.confirm + resolve: + object: -> + title: _t('confirmation_required') + msg: _t('do_you_really_want_to_delete_this_step') + , -> # deletion confirmed + index = $scope.project.project_steps_attributes.indexOf(step) + if step.id? + step._destroy = true + else + $scope.project.project_steps_attributes.splice(index, 1) + + # update the new total number of steps + $scope.totalSteps -= 1 + # reindex the remaning steps + for s in $scope.project.project_steps_attributes + if s.step_nb > step.step_nb + s.step_nb -= 1 + + + + ## + # Change the step_nb property of the given step to the new value provided. The step that was previously at this + # index will be assigned to the old position of the provided step. + # @param step {Object} the project's step to reindex + # @param newIdx {number} the new index to assign to the step + ## + $scope.changeStepIndex = (step, newIdx) -> + for s in $scope.project.project_steps_attributes + if s.step_nb == newIdx + s.step_nb = step.step_nb + step.step_nb = newIdx + break @@ -275,8 +309,8 @@ Application.Controllers.controller "ProjectsController", ["$scope", "$state", 'P ## # Controller used in the project creation page ## -Application.Controllers.controller "NewProjectController", ["$scope", "$state", 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF' -, ($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, CSRF) -> +Application.Controllers.controller "NewProjectController", ["$scope", "$state", 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'dialogs', '_t' +, ($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, dialogs, _t) -> CSRF.setMetaTags() ## API URL where the form will be posted @@ -299,7 +333,7 @@ Application.Controllers.controller "NewProjectController", ["$scope", "$state", name: d.name ## Using the ProjectsController - new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document) + new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, dialogs, _t) ] @@ -307,8 +341,8 @@ Application.Controllers.controller "NewProjectController", ["$scope", "$state", ## # Controller used in the project edition page ## -Application.Controllers.controller "EditProjectController", ["$scope", "$state", '$stateParams', 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'projectPromise' -, ($scope, $state, $stateParams, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, projectPromise) -> +Application.Controllers.controller "EditProjectController", ["$scope", "$state", '$stateParams', 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'projectPromise', 'dialogs', '_t' +, ($scope, $state, $stateParams, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, projectPromise, dialogs, _t) -> CSRF.setMetaTags() ## API URL where the form will be posted @@ -329,7 +363,7 @@ Application.Controllers.controller "EditProjectController", ["$scope", "$state", name: d.name ## Using the ProjectsController - new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document) + new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, dialogs, _t) ] diff --git a/app/assets/templates/projects/_form.html.erb b/app/assets/templates/projects/_form.html.erb index 7e4d77e9f..fb9b9eac5 100644 --- a/app/assets/templates/projects/_form.html.erb +++ b/app/assets/templates/projects/_form.html.erb @@ -72,14 +72,14 @@
-
+
diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index c97ba5523..e54ab6ae0 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -120,6 +120,7 @@ en: add_a_picture: "Add a picture" change_the_picture: "Change the picture" delete_the_step: "Delete the step" + do_you_really_want_to_delete_this_step: "Do you really want to delete this step?" add_a_new_step: "Add a new step" publish_your_project: "Publish your project" employed_materials: "Employed materials" diff --git a/config/locales/app.shared.fr.yml b/config/locales/app.shared.fr.yml index 9f773f22e..c17557189 100644 --- a/config/locales/app.shared.fr.yml +++ b/config/locales/app.shared.fr.yml @@ -120,6 +120,7 @@ fr: add_a_picture: "Ajouter une image" change_the_picture: "Modifier l'image" delete_the_step: "Supprimer l'étape" + do_you_really_want_to_delete_this_step: "Êtes-vous sur de vouloir supprimer cette étape ?" add_a_new_step: "Ajouter une nouvelle étape" publish_your_project: "Publier votre projet" employed_materials: "Matériaux utilisés"