From e7bb41f38d0fb6729b5ab6bba3ef3b91a682ce97 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 24 Sep 2019 12:21:19 +0200 Subject: [PATCH] [ongoing] import users from csv file: admin inteface --- .../controllers/admin/members.js.erb | 26 +++ app/assets/javascripts/router.js.erb | 14 ++ app/assets/stylesheets/app.utilities.scss | 13 ++ .../templates/admin/members/import.html.erb | 165 ++++++++++++++++++ .../templates/admin/members/index.html.erb | 9 +- app/views/api/plans/_plan.json.jbuilder | 31 ++-- app/views/api/plans/index.json.jbuilder | 7 +- config/locales/app.admin.en.yml | 21 +++ config/locales/app.admin.es.yml | 21 +++ config/locales/app.admin.fr.yml | 21 +++ config/locales/app.admin.pt.yml | 21 +++ public/example.csv | 3 + 12 files changed, 337 insertions(+), 15 deletions(-) create mode 100644 app/assets/templates/admin/members/import.html.erb create mode 100644 public/example.csv diff --git a/app/assets/javascripts/controllers/admin/members.js.erb b/app/assets/javascripts/controllers/admin/members.js.erb index 6253fedfe..2166d1c80 100644 --- a/app/assets/javascripts/controllers/admin/members.js.erb +++ b/app/assets/javascripts/controllers/admin/members.js.erb @@ -609,6 +609,32 @@ Application.Controllers.controller('NewMemberController', ['$scope', '$state', ' } ]); +/** + * Controller used in the member's import page: import from CSV (admin view) + */ +Application.Controllers.controller('ImportMembersController', ['$scope', '$state', 'Group', 'Training', 'CSRF', 'plans', 'tags', + function($scope, $state, Group, Training, CSRF, plans, tags) { + CSRF.setMetaTags(); + + /* PUBLIC SCOPE */ + + // API URL where the form will be posted + $scope.actionUrl = '/api/members/import'; + + // Form action on the above URL + $scope.method = 'post'; + + // List of all plans + $scope.plans = plans; + + // List of all tags + $scope.tags = tags + + // Using the MembersController + return new MembersController($scope, $state, Group, Training); + } +]); + /** * Controller used in the admin's creation page (admin view) */ diff --git a/app/assets/javascripts/router.js.erb b/app/assets/javascripts/router.js.erb index 0c40c4d7f..0bfc95e37 100644 --- a/app/assets/javascripts/router.js.erb +++ b/app/assets/javascripts/router.js.erb @@ -959,6 +959,20 @@ angular.module('application.router', ['ui.router']) translations: ['Translations', function (Translations) { return Translations.query(['app.admin.members_new', 'app.shared.user', 'app.shared.user_admin']).$promise; }] } }) + .state('app.admin.members_import', { + url: '/admin/members/import', + views: { + 'main@': { + templateUrl: '<%= asset_path "admin/members/import.html" %>', + controller: 'ImportMembersController' + } + }, + resolve: { + translations: ['Translations', function (Translations) { return Translations.query(['app.admin.members_import', 'app.shared.user', 'app.shared.user_admin']).$promise; }], + plans: ['Plan', function(Plan) { return Plan.query().$promise }], + tags: ['Tag', function(Tag) { return Tag.query().$promise }] + } + }) .state('app.admin.members_edit', { url: '/admin/members/:id/edit', views: { diff --git a/app/assets/stylesheets/app.utilities.scss b/app/assets/stylesheets/app.utilities.scss index 0d940d69f..d7ee4d420 100644 --- a/app/assets/stylesheets/app.utilities.scss +++ b/app/assets/stylesheets/app.utilities.scss @@ -180,6 +180,11 @@ p, .widget p { .p-lg { padding: 30px; } .p-l { padding: 16px; } +.p-h-xs { padding-left: 5px; padding-right: 5px; } +.p-h-s { padding-left: 10px; padding-right: 10px; } +.p-h-l { padding-left: 16px; padding-right: 16px; } +.p-h-lg { padding-left: 30px; padding-right: 30px; } + .m-xxs{margin: 2px 4px} .m-xs{margin: 5px;} .m-sm{margin: 10px;} @@ -256,6 +261,14 @@ p, .widget p { .m-b-n-lg{margin-bottom: -30px} .m-b-n-xl{margin-bottom: -40px} +.m-h-none{margin-left: 0; margin-right: 0;} +.m-h-xs{margin-left: 5px; margin-right: 5px;} +.m-h-sm{margin-left: 10px; margin-right: 10px;} +.m-h{margin-left: 15px; margin-right: 15px;} +.m-h-md{margin-left: 20px; margin-right: 20px;} +.m-h-lg{margin-left: 30px; margin-right: 30px;} +.m-h-xl{margin-left: 40px; margin-right: 40px;} + .media-xs{min-width: 50px} .media-sm{min-width: 80px} .media-md{min-width: 90px} diff --git a/app/assets/templates/admin/members/import.html.erb b/app/assets/templates/admin/members/import.html.erb new file mode 100644 index 000000000..8520119ad --- /dev/null +++ b/app/assets/templates/admin/members/import.html.erb @@ -0,0 +1,165 @@ +
+ +
+
+ + + +
+
+

{{ 'members_import.import_members' }}

+
+
+ + + +
+
+ +
+
+

+ {{ 'members_import.info' }} +

+

+ {{ 'members_import.required_fields' }} +

+
+
+ +
+ +
+

{{ 'members_import.groups' }}

+ + + + + + + + + + + + + +
{{ 'members_import.group_name' }}{{ 'members_import.group_identifier' }}
+ {{ group.name }} + + {{ group.slug }} +
+
+ +
+

{{ 'members_import.trainings' }}

+ + + + + + + + + + + + + +
{{ 'members_import.training_name' }}{{ 'members_import.training_identifier' }}
+ {{ training.name }} + + {{ training.id }} +
+
+ +
+ + +
+ +
+

{{ 'members_import.plans' }}

+ + + + + + + + + + + + + +
{{ 'members_import.plan_name' }}{{ 'members_import.plan_identifier' }}
+ {{ plan.name }} + + {{ plan.slug }} +
+
+ +
+

{{ 'members_import.tags' }}

+ + + + + + + + + + + + + +
{{ 'members_import.tag_name' }}{{ 'members_import.tag_identifier' }}
+ {{ tag.name }} + + {{ tag.id }} +
+
+ +
+ +
+
+ +
+
+ +
+
+
+
+ Lorem ipsum dolor sit amet consectetur adipiscing elit +
+
+
+ +
+ + + + +
+
+ +
+
+ +
diff --git a/app/assets/templates/admin/members/index.html.erb b/app/assets/templates/admin/members/index.html.erb index 1137646e2..d3141103f 100644 --- a/app/assets/templates/admin/members/index.html.erb +++ b/app/assets/templates/admin/members/index.html.erb @@ -5,11 +5,18 @@ -
+

{{ 'users_management' }}

+
+
+ + + +
+
diff --git a/app/views/api/plans/_plan.json.jbuilder b/app/views/api/plans/_plan.json.jbuilder index 062a538f1..04fcd4e86 100644 --- a/app/views/api/plans/_plan.json.jbuilder +++ b/app/views/api/plans/_plan.json.jbuilder @@ -1,13 +1,20 @@ -json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :is_rolling, :description, :type, :ui_weight, :disabled -json.amount (plan.amount / 100.00) -json.prices plan.prices, partial: 'api/prices/price', as: :price -json.plan_file_attributes do - json.id plan.plan_file.id - json.attachment_identifier plan.plan_file.attachment_identifier -end if plan.plan_file +# frozen_string_literal: true -json.partners plan.partners do |partner| - json.first_name partner.first_name - json.last_name partner.last_name - json.email partner.email -end if plan.respond_to?(:partners) +json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :is_rolling, :description, :type, + :ui_weight, :disabled +json.amount plan.amount / 100.00 +json.prices plan.prices, partial: 'api/prices/price', as: :price +if plan.plan_file + json.plan_file_attributes do + json.id plan.plan_file.id + json.attachment_identifier plan.plan_file.attachment_identifier + end +end + +if plan.respond_to?(:partners) + json.partners plan.partners do |partner| + json.first_name partner.first_name + json.last_name partner.last_name + json.email partner.email + end +end \ No newline at end of file diff --git a/app/views/api/plans/index.json.jbuilder b/app/views/api/plans/index.json.jbuilder index 1e7e634fe..e2cbb90fc 100644 --- a/app/views/api/plans/index.json.jbuilder +++ b/app/views/api/plans/index.json.jbuilder @@ -1,5 +1,8 @@ +# frozen_string_literal: true + json.array!(@plans) do |plan| - json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :description, :type, :ui_weight, :disabled - json.amount (plan.amount / 100.00) + json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :description, :type, :ui_weight, + :slug, :disabled + json.amount plan.amount / 100.00 json.plan_file_url plan.plan_file.attachment_url if plan.plan_file end diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index a0273d529..a4f7221d1 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -569,6 +569,27 @@ en: add_a_member: "Add a member" user_is_an_organization: "User is an organization" + members_import: + # members bulk import + members_import: + import_members: "Import members" + info: "you can upload a CSV file to create new members or update existing ones. Your file must user the identifiers below to specify the group, trainings, suscription and tags of the members." + required_fields: "Your file must contain, at least, the following information for each user to create: email, name, first name and group." + groups: "Groups" + group_name: "Group name" + group_identifier: "Identifier to use" + trainings: "Trainings" + training_name: "Training name" + training_identifier: "Identifier to use" + plans: "Plans" + plan_name: "Plan name" + plan_identifier: "Identifier to use" + tags: "Tags" + tag_name: "Tag name" + tag_identifier: "Identifier to use" + download_example: "Download the exemple file" + select_file: "Choose a file" + members_edit: # edit a member duration: "Duration:" diff --git a/config/locales/app.admin.es.yml b/config/locales/app.admin.es.yml index 71a9d7e5d..66630137a 100644 --- a/config/locales/app.admin.es.yml +++ b/config/locales/app.admin.es.yml @@ -569,6 +569,27 @@ es: add_a_member: "Agregar un miembro" user_is_an_organization: "El usuario es una organización" + members_import: + # members bulk import + members_import: + import_members: "Import members" # translation_missing + info: "you can upload a CSV file to create new members or update existing ones. Your file must user the identifiers below to specify the group, trainings, suscription and tags of the members." # translation_missing + required_fields: "Your file must contain, at least, the following information for each user to create: email, name, first name and group." # translation_missing + groups: "Groups" # translation_missing + group_name: "Group name" # translation_missing + group_identifier: "Identifier to use" # translation_missing + trainings: "Trainings" # translation_missing + training_name: "Training name" # translation_missing + training_identifier: "Identifier to use" # translation_missing + plans: "Plans" # translation_missing + plan_name: "Plan name" # translation_missing + plan_identifier: "Identifier to use" # translation_missing + tags: "Tags" # translation_missing + tag_name: "Tag name" # translation_missing + tag_identifier: "Identifier to use" # translation_missing + download_example: "Download the exemple file" # translation_missing + select_file: "Choose a file" # translation_missing + members_edit: # edit a member duration: "Duración:" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 5f9ab3d65..b61bd0557 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -569,6 +569,27 @@ fr: add_a_member: "Ajouter un membre" user_is_an_organization: "L'utilisateur est une structure" + members_import: + # import massif de members + members_import: + import_members: "Importer des membres" + info: "Vous pouvez téléverser un fichier CVS afin de créer des nouveaux membres ou de mettre à jour les existants. Votre fichier doit utiliser les identifiants ci-dessous pour spécifier les groupe, formations, abonnement et étiquettes des membres." + required_fields: "Votre fichier doit obligatoirement comporter, au minimum, les informations suivantes pour chaque utilisateur à créer : courriel, nom, prénom et groupe." + groups: "Groupes" + group_name: "Nom du groupe" + group_identifier: "Identifiant à utiliser" + trainings: "Formations" + training_name: "Nom de la formation" + training_identifier: "Identifiant à utiliser" + plans: "Abonnements" + plan_name: "Nom de l'abonnement" + plan_identifier: "Identifiant à utiliser" + tags: "Étiquettes" + tag_name: "Nom de l'étiquette" + tag_identifier: "Identifiant à utiliser" + download_example: "Télécharger le fichier d'exemple" + select_file: "Choisissez un fichier" + members_edit: # modifier un membre duration: "Durée :" diff --git a/config/locales/app.admin.pt.yml b/config/locales/app.admin.pt.yml index be77652d3..70c5ebcb2 100755 --- a/config/locales/app.admin.pt.yml +++ b/config/locales/app.admin.pt.yml @@ -569,6 +569,27 @@ pt: add_a_member: "Adicionar membro" user_is_an_organization: "Usuário é uma organização" + members_import: + # members bulk import + members_import: + import_members: "Import members" # translation_missing + info: "you can upload a CSV file to create new members or update existing ones. Your file must user the identifiers below to specify the group, trainings, suscription and tags of the members." # translation_missing + required_fields: "Your file must contain, at least, the following information for each user to create: email, name, first name and group." # translation_missing + groups: "Groups" # translation_missing + group_name: "Group name" # translation_missing + group_identifier: "Identifier to use" # translation_missing + trainings: "Trainings" # translation_missing + training_name: "Training name" # translation_missing + training_identifier: "Identifier to use" # translation_missing + plans: "Plans" # translation_missing + plan_name: "Plan name" # translation_missing + plan_identifier: "Identifier to use" # translation_missing + tags: "Tags" # translation_missing + tag_name: "Tag name" # translation_missing + tag_identifier: "Identifier to use" # translation_missing + download_example: "Download the exemple file" # translation_missing + select_file: "Choose a file" # translation_missing + members_edit: # edit a member duration: "Duração:" diff --git a/public/example.csv b/public/example.csv new file mode 100644 index 000000000..da7f9d1b9 --- /dev/null +++ b/public/example.csv @@ -0,0 +1,3 @@ +id;gender;first_name;last_name;username;email;password;birthdate;address;phone;group;subscription;tags;trainings;website;job;interests;softwares;allow_contact;allow_newsletter;facebook;twitter;googleplus;viadeo;linkedin;instagram;youtube;vimeo;dailymotion;github;echosciences;pinterest;lastfm;flickr +;male;jean;dupont;jdupont;jean.dupont@gmail.com;;1970-01-01;12 bvd Libération - 75000 Paris;0123456789;standard;;1,2;1;http://www.example.com;Charpentier;Ping-pong;AutoCAD;yes;no;http://www.facebook.com/jdupont;;;;;;;;;http://github.com/example;;;; +43;;;;;;newpassword