From 80e73bfb97b51caaa3a7d2133e14fb08e6890f87 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Mon, 24 Sep 2018 16:25:04 +0200 Subject: [PATCH] Implement Projects view - navigation bar (tabs) [SCI-2729] --- .../projects/{index.js.erb => index.js} | 484 +++++++++--------- app/assets/stylesheets/projects.scss | 16 + app/views/projects/index.html.erb | 2 +- .../projects/index/_team_projects.html.erb | 33 +- .../shared/_secondary_navigation.html.erb | 37 +- config/locales/en.yml | 5 +- 6 files changed, 302 insertions(+), 275 deletions(-) rename app/assets/javascripts/projects/{index.js.erb => index.js} (53%) diff --git a/app/assets/javascripts/projects/index.js.erb b/app/assets/javascripts/projects/index.js similarity index 53% rename from app/assets/javascripts/projects/index.js.erb rename to app/assets/javascripts/projects/index.js index dae8711a8..394b4c81c 100644 --- a/app/assets/javascripts/projects/index.js.erb +++ b/app/assets/javascripts/projects/index.js @@ -7,9 +7,10 @@ // - refresh project users tab after manage user modal is closed // - refactor view handling using library, ex. backbone.js -//= require comments -(function () { +/* global Comments CounterBadge animateSpinner */ +//= require comments +(function() { var newProjectModal = null; var newProjectModalForm = null; var newProjectModalBody = null; @@ -25,19 +26,235 @@ var projectActionsModalBody = null; var projectActionsModalFooter = null; + var projectsViewMode = 'cards'; + var projectsViewFilter = $('.projects-view-filter.active').data('filter'); + + function initProjectsViewFilter() { + $('.projects-view-filter').click(function(event) { + event.preventDefault(); + event.stopPropagation(); + $('.projects-view-filter').removeClass('active'); + $(this).addClass('active'); + if ($(this).data('filter') === projectsViewFilter) { + return; + } + projectsViewFilter = $(this).data('filter'); + }); + } + + function initProjectsViewModeSwitch() { + $('input[name=projects-view-mode-selector]').on('change', function() { + if ($(this).val() === projectsViewMode) { + return; + } + projectsViewMode = $(this).val(); + }); + } + /** - * Stupid Bootstrap btn-group bug hotfix - * @param btnGroup - The button group element. + * Initialize the JS for new project modal to work. */ - function activateBtnGroup(btnGroup) { - var btns = btnGroup.find(".btn"); - btns.find("input[type='radio']") - .removeAttr("checked") - .prop("checked", false); - btns.filter(".active") - .find("input[type='radio']") - .attr("checked", "checked") - .prop("checked", true); + function initNewProjectModal() { + newProjectModal.on('hidden.bs.modal', function() { + var teamSelect = newProjectModalForm.find('select#project_team_id'); + var teamHidden = newProjectModalForm.find('input#project_visibility_hidden'); + var teamVisible = newProjectModalForm.find('input#project_visibility_visible'); + // When closing the new project modal, clear its input vals + // and potential errors + newProjectModalForm.clearFormErrors(); + + // Clear input fields + newProjectModalForm.clearFormFields(); + teamSelect.val(0); + teamSelect.selectpicker('refresh'); + + teamHidden.prop('checked', true); + teamHidden.attr('checked', 'checked'); + teamHidden.parent().addClass('active'); + teamVisible.prop('checked', false); + teamVisible.parent().removeClass('active'); + }).on('show.bs.modal', function() { + var teamSelect = newProjectModalForm.find('select#project_team_id'); + teamSelect.selectpicker('refresh'); + }); + + newProjectModalForm + .on('ajax:beforeSend', function() { + animateSpinner(newProjectModalBody); + }) + .on('ajax:success', function(data, status) { + // Redirect to response page + $(location).attr('href', status.url); + }) + .on('ajax:error', function(jqxhr, status) { + $(this).renderFormErrors('project', status.responseJSON); + }) + .on('ajax:complete', function() { + animateSpinner(newProjectModalBody, false); + }); + + newProjectBtn.click(function() { + // Show the modal + newProjectModal.modal('show'); + return false; + }); + } + + /** + * Initialize the JS for edit project modal to work. + */ + function initEditProjectModal() { + // Edit button click handler + editProjectBtn.click(function() { + // Submit the modal body's form + editProjectModalBody.find('form').submit(); + }); + + // On hide modal handler + editProjectModal.on('hidden.bs.modal', function() { + editProjectModalBody.html(''); + }); + + $(".panel-project a[data-action='edit']") + .on('ajax:success', function(ev, data) { + // Update modal title + editProjectModalTitle.html(data.title); + + // Set modal body + editProjectModalBody.html(data.html); + + // Add modal body's submit handler + editProjectModal.find('form') + .on('ajax:beforeSend', function() { + animateSpinner(this); + }) + .on('ajax:success', function(ev2, data2) { + // Project saved, replace changed project's title + var responseHtml = $(data2.html); + var id = responseHtml.attr('data-id'); + var newTitle = responseHtml.find('.panel-title'); + var existingTitle = $(".panel-project[data-id='" + id + "'] .panel-title"); + + existingTitle.after(newTitle); + existingTitle.remove(); + + // Hide modal + editProjectModal.modal('hide'); + }) + .on('ajax:error', function(ev2, data2) { + $(this).renderFormErrors('project', data2.responseJSON); + }) + .on('ajax:complete', function() { + animateSpinner(this, false); + }); + + // Show the modal + editProjectModal.modal('show'); + }) + .on('ajax:error', function() { + // TODO + }); + } + + function initManageUsersModal() { + // Reload users tab HTML element when modal is closed + projectActionsModal.on('hide.bs.modal', function() { + var projectEl = $('#' + $(this).attr('data-project-id')); + + // Load HTML to refresh users list + $.ajax({ + url: projectEl.attr('data-project-users-tab-url'), + type: 'GET', + dataType: 'json', + success: function(data) { + projectEl.find('#users-' + projectEl.attr('id')).html(data.html); + CounterBadge.updateCounterBadge( + data.counter, data.project_id, 'users' + ); + initUsersEditLink(projectEl); + }, + error: function() { + // TODO + } + }); + }); + + // Remove modal content when modal window is closed. + projectActionsModal.on('hidden.bs.modal', function() { + projectActionsModalHeader.html(''); + projectActionsModalBody.html(''); + projectActionsModalFooter.html(''); + }); + } + + // Initialize users editing modal remote loading. + function initUsersEditLink($el) { + $el.find('.manage-users-link') + .on('ajax:before', function() { + var projectId = $(this).closest('.panel-default').attr('id'); + projectActionsModal.attr('data-project-id', projectId); + projectActionsModal.modal('show'); + }) + .on('ajax:success', function(e, data) { + $('#manage-users-modal-project').text(data.project.name); + initUsersModalBody(data); + }); + } + + // Initialize reloading manage user modal content after posting new + // user. + + function initAddUserForm() { + projectActionsModalBody.find('.add-user-form') + .on('ajax:success', function(e, data) { + var errorBlock; + initUsersModalBody(data); + if (data.status === 'error') { + $(this).addClass('has-error'); + errorBlock = $(this).find('span.help-block'); + if (errorBlock.length && errorBlock.length > 0) { + errorBlock.html(data.error); + } else { + $(this).append("" + data.error + ''); + } + } + }); + } + + // Initialize remove user from project links. + function initRemoveUserLinks() { + projectActionsModalBody.find('.remove-user-link') + .on('ajax:success', function(e, data) { + initUsersModalBody(data); + }); + } + + // + function initUserRoleForms() { + projectActionsModalBody.find('.update-user-form select') + .on('change', function() { + $(this).parents('form').submit(); + }); + + projectActionsModalBody.find('.update-user-form') + .on('ajax:success', function(e, data) { + initUsersModalBody(data); + }) + .on('ajax:error', function() { + // TODO + }); + } + + // Initialize ajax listeners and elements style on modal body. This + // function must be called when modal body is changed. + function initUsersModalBody(data) { + projectActionsModalHeader.html(data.html_header); + projectActionsModalBody.html(data.html_body); + projectActionsModalFooter.html(data.html_footer); + projectActionsModalBody.find('.selectpicker').selectpicker(); + initAddUserForm(); + initRemoveUserLinks(); + initUserRoleForms(); } /** @@ -59,6 +276,8 @@ projectActionsModalBody = projectActionsModal.find('.modal-body'); projectActionsModalFooter = projectActionsModal.find('.modal-footer'); + initProjectsViewFilter(); + initProjectsViewModeSwitch(); initNewProjectModal(); initEditProjectModal(); initManageUsersModal(); @@ -69,8 +288,7 @@ // initialize project tab remote loading $('.panel-project .active').removeClass('active'); $('.panel-project .panel-footer [role=tab]') - - .on('ajax:before', function(e) { + .on('ajax:before', function() { var $this = $(this); var parentNode = $this.parents('li'); var targetId = $this.attr('aria-controls'); @@ -81,9 +299,9 @@ $('#' + targetId).removeClass('active'); return false; } + return true; }) - - .on('ajax:success', function(e, data, status, xhr) { + .on('ajax:success', function(e, data) { var $this = $(this); var targetId = $this.attr('aria-controls'); var target = $('#' + targetId); @@ -101,242 +319,10 @@ Comments.scrollBottom(parentNode); }) - .on('ajax:error', function() { // TODO }); } - /** - * Initialize the JS for new project modal to work. - */ - function initNewProjectModal() { - newProjectModalForm.submit(function() { - // Stupid Bootstrap btn-group bug hotfix - activateBtnGroup( - newProjectModal - .find("form .btn-group[data-toggle='buttons']") - ); - }); - newProjectModal.on("hidden.bs.modal", function () { - // When closing the new project modal, clear its input vals - // and potential errors - newProjectModalForm.clearFormErrors(); - - // Clear input fields - newProjectModalForm.clearFormFields(); - var teamSelect = newProjectModalForm.find('select#project_team_id'); - teamSelect.val(0); - teamSelect.selectpicker('refresh'); - - var teamHidden = newProjectModalForm.find('input#project_visibility_hidden'); - var teamVisible = newProjectModalForm.find('input#project_visibility_visible'); - teamHidden.prop("checked", true); - teamHidden.attr("checked", "checked"); - teamHidden.parent().addClass("active"); - teamVisible.prop("checked", false); - teamVisible.parent().removeClass("active"); - }) - .on("show.bs.modal", function() { - var teamSelect = newProjectModalForm.find('select#project_team_id'); - teamSelect.selectpicker('refresh'); - }); - - newProjectModalForm - .on("ajax:beforeSend", function(){ - animateSpinner(newProjectModalBody); - }) - .on("ajax:success", function(data, status, jqxhr) { - // Redirect to response page - $(location).attr("href", status.url); - }) - .on("ajax:error", function(jqxhr, status, error) { - $(this).renderFormErrors("project", status.responseJSON); - }) - .on("ajax:complete", function(){ - animateSpinner(newProjectModalBody, false); - }); - - newProjectBtn.click(function(e) { - // Show the modal - newProjectModal.modal("show"); - return false; - }); - } - - /** - * Initialize the JS for edit project modal to work. - */ - function initEditProjectModal() { - // Edit button click handler - editProjectBtn.click(function() { - // Stupid Bootstrap btn-group bug hotfix - activateBtnGroup( - editProjectModalBody - .find("form .btn-group[data-toggle='buttons']") - ); - - // Submit the modal body's form - editProjectModalBody.find("form").submit(); - }); - - // On hide modal handler - editProjectModal.on("hidden.bs.modal", function() { - editProjectModalBody.html(""); - }); - - $(".panel-project a[data-action='edit']") - .on("ajax:success", function(ev, data, status) { - // Update modal title - editProjectModalTitle.html(data.title); - - // Set modal body - editProjectModalBody.html(data.html); - - // Add modal body's submit handler - editProjectModal.find("form") - .on("ajax:beforeSend", function(){ - animateSpinner(this); - }) - .on("ajax:success", function(ev2, data2, status2) { - // Project saved, replace changed project's title - var responseHtml = $(data2.html); - var id = responseHtml.attr("data-id"); - var newTitle = responseHtml.find(".panel-title"); - var existingTitle = - $(".panel-project[data-id='" + id + "'] .panel-title"); - - existingTitle.after(newTitle); - existingTitle.remove(); - - // Hide modal - editProjectModal.modal("hide"); - }) - .on("ajax:error", function(ev2, data2, status2) { - $(this).renderFormErrors("project", data2.responseJSON); - }) - .on("ajax:complete", function(){ - animateSpinner(this, false); - }); - - // Show the modal - editProjectModal.modal("show"); - }) - .on("ajax:error", function(ev, data, status) { - // TODO - }); - } - - function initManageUsersModal() { - // Reload users tab HTML element when modal is closed - projectActionsModal.on("hide.bs.modal", function () { - var projectEl = $("#" + $(this).attr("data-project-id")); - - // Load HTML to refresh users list - $.ajax({ - url: projectEl.attr("data-project-users-tab-url"), - type: "GET", - dataType: "json", - success: function (data) { - projectEl.find("#users-" + projectEl.attr("id")).html(data.html); - CounterBadge.updateCounterBadge(data.counter, - data.project_id, - 'users'); - initUsersEditLink(projectEl); - }, - error: function (data) { - // TODO - } - }); - }); - - // Remove modal content when modal window is closed. - projectActionsModal.on("hidden.bs.modal", function () { - projectActionsModalHeader.html(""); - projectActionsModalBody.html(""); - projectActionsModalFooter.html(""); - }); - } - - // Initialize users editing modal remote loading. - function initUsersEditLink($el) { - - $el.find(".manage-users-link") - - .on("ajax:before", function () { - var projectId = $(this).closest(".panel-default").attr("id"); - projectActionsModal.attr("data-project-id", projectId); - projectActionsModal.modal('show'); - }) - - .on("ajax:success", function (e, data) { - $("#manage-users-modal-project").text(data.project.name); - initUsersModalBody(data); - }); - } - - // Initialize reloading manage user modal content after posting new - // user. - - function initAddUserForm() { - - projectActionsModalBody.find(".add-user-form") - - .on("ajax:success", function (e, data) { - initUsersModalBody(data); - if (data.status === 'error') { - $(this).addClass("has-error"); - var errorBlock = $(this).find("span.help-block"); - if (errorBlock .length && errorBlock.length > 0) { - errorBlock.html(data.error); - } else { - $(this).append("" + data.error + ""); - } - } - }); - } - - // Initialize remove user from project links. - function initRemoveUserLinks() { - - projectActionsModalBody.find(".remove-user-link") - - .on("ajax:success", function (e, data) { - initUsersModalBody(data); - }); - } - - // - function initUserRoleForms() { - - projectActionsModalBody.find(".update-user-form select") - - .on("change", function () { - $(this).parents("form").submit(); - }); - - projectActionsModalBody.find(".update-user-form") - - .on("ajax:success", function (e, data) { - initUsersModalBody(data); - }) - - .on("ajax:error", function (e, xhr, status, error) { - // TODO - }); - } - - // Initialize ajax listeners and elements style on modal body. This - // function must be called when modal body is changed. - function initUsersModalBody(data) { - projectActionsModalHeader.html(data.html_header); - projectActionsModalBody.html(data.html_body); - projectActionsModalFooter.html(data.html_footer); - projectActionsModalBody.find(".selectpicker").selectpicker(); - initAddUserForm(); - initRemoveUserLinks(); - initUserRoleForms(); - } - init(); }()); diff --git a/app/assets/stylesheets/projects.scss b/app/assets/stylesheets/projects.scss index 111d16585..cfe1820cd 100644 --- a/app/assets/stylesheets/projects.scss +++ b/app/assets/stylesheets/projects.scss @@ -15,6 +15,22 @@ $color-module-hover: $brand-primary; } } +/* Secondary navigation */ + +.navbar-nav { + + .btn-group .btn-toggle:not(.active) { + background-color: $color-white; + border-color: $color-silver; + color: $color-emperor; + } + + .projects-view-mode-switch { + margin: 10px; + } + +} + /* Canvas index page */ #canvas-container:not(.canvas-container-edit-mode) { diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index 00ca229f3..577d4486f 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -85,7 +85,7 @@ <% if @teams.exists? && can_create_projects?(current_team) %> - + diff --git a/app/views/projects/index/_team_projects.html.erb b/app/views/projects/index/_team_projects.html.erb index 8ea5c437c..e6542a738 100644 --- a/app/views/projects/index/_team_projects.html.erb +++ b/app/views/projects/index/_team_projects.html.erb @@ -1,16 +1,21 @@ -
-<% projects.each_with_index do |project, i| %> -
- <%= render partial: "projects/index/project", locals: {project: project} %> +
+
+
+ <% projects.each_with_index do |project, i| %> +
+ <%= render partial: "projects/index/project", locals: {project: project} %> +
+ <% if (i+1) % 4 == 0 %> +
+ <% end %> + <% if (i+1) % 3 == 0 %> +
+ <% end %> + <% if (i+1) % 2 == 0 %> +
+ <% end %> + <% end %> +
- <% if (i+1) % 4 == 0 %> -
- <% end %> - <% if (i+1) % 3 == 0 %> -
- <% end %> - <% if (i+1) % 2 == 0 %> -
- <% end %> -<% end %> +
Table view
diff --git a/app/views/shared/_secondary_navigation.html.erb b/app/views/shared/_secondary_navigation.html.erb index c357b2dad..75bc3538f 100644 --- a/app/views/shared/_secondary_navigation.html.erb +++ b/app/views/shared/_secondary_navigation.html.erb @@ -18,19 +18,38 @@