diff --git a/app/assets/javascripts/application.js.erb b/app/assets/javascripts/application.js.erb index 48d14fdfa..040f57363 100644 --- a/app/assets/javascripts/application.js.erb +++ b/app/assets/javascripts/application.js.erb @@ -38,6 +38,7 @@ //= require users/settings/teams/invite_users_modal //= require select2.min //= require select2_customization +//= require shared/inline_editing //= require turbolinks diff --git a/app/assets/javascripts/shared/inline_editing.js b/app/assets/javascripts/shared/inline_editing.js new file mode 100644 index 000000000..72d46a1d2 --- /dev/null +++ b/app/assets/javascripts/shared/inline_editing.js @@ -0,0 +1,63 @@ +function initInlineEditing(title) { + var editBlock = $('.' + title + '-editable-field'); + var inputString = editBlock.find('input'); + + function updateField() { + var params = {}; + + if (inputString[0].value === editBlock[0].dataset.originalName) { + inputString[0].disabled = true; + return false; + } + params[editBlock[0].dataset.paramsGroup] = {}; + params[editBlock[0].dataset.paramsGroup][editBlock[0].dataset.fieldToUpdate] = inputString[0].value; + $.ajax({ + url: editBlock[0].dataset.pathToUpdate, + type: 'PUT', + dataType: 'json', + data: params, + success: function() { + editBlock[0].dataset.originalName = inputString[0].value; + editBlock[0].dataset.error = false; + inputString[0].disabled = true; + }, + error: function(response) { + var errors = response.responseJSON; + editBlock[0].dataset.error = true; + if (response.responseJSON.errors === undefined) { + errors = errors[editBlock[0].dataset.fieldToUpdate][0]; + } else { + errors = errors.errors[editBlock[0].dataset.fieldToUpdate][0]; + } + editBlock.find('.error-block')[0].innerHTML = errors; + inputString.focus(); + } + }); + } + + editBlock.click(e => { + if (inputString[0].disabled) { + inputString[0].disabled = false; + inputString.focus(); + } + e.stopPropagation(); + }); + + $(window).click(() => { + if (inputString[0].disabled === false) { + updateField(); + } + }); + + $(editBlock.find('.save-button')).click(e => { + updateField(); + e.stopPropagation(); + }); + + $(editBlock.find('.cancel-button')).click(e => { + inputString[0].disabled = true; + editBlock[0].dataset.error = false; + inputString[0].value = editBlock[0].dataset.originalName; + e.stopPropagation(); + }); +} diff --git a/app/assets/stylesheets/partials/_inline_editing.scss b/app/assets/stylesheets/partials/_inline_editing.scss new file mode 100644 index 000000000..835a5867f --- /dev/null +++ b/app/assets/stylesheets/partials/_inline_editing.scss @@ -0,0 +1,94 @@ +@import "constants"; +@import "mixins"; + + +.inline-editing-container { + position: relative; + + .button-container { + height: 44px; + line-height: 44px; + overflow: hidden; + position: absolute; + right: 0; + top: 0; + width: 72px; + + span { + color: $color-silver; + cursor: pointer; + display: inline-block; + position: absolute; + text-align: center; + width: 36px; + + &:nth-child(1) {left: 0;} + + &:nth-child(2) {right: 0;} + } + } + + .error-block { + bottom: 3px; + color: $brand-danger; + display: none; + font-size: $font-size-small; + left: 5px; + line-height: 12px; + position: absolute; + + } + + &[data-error="true"] { + + .error-block { + display: block; + } + + input { + padding-bottom: 16px; + padding-top: 0; + } + } + + input { + border: 1px solid $color-silver; + border-radius: $border-radius-small; + cursor: pointer; + line-height: 20px; + padding: 8px 5px; + padding-right: 36px; + width: calc(100% - 36px); + + &:focus { + outline: 0; + } + + &:disabled { + background: transparent; + border: 1px solid transparent; + cursor: pointer; + user-select: none; + + + .button-container { + display: none; + + } + + &:hover { + border: 1px solid $color-gainsboro; + } + } + } +} + +.nav-name.editable { + margin: 0; + + .inline-editing-container { + + input { + line-height: 26px; + } + } +} diff --git a/app/controllers/experiments_controller.rb b/app/controllers/experiments_controller.rb index e3b4a4b00..140b7b76c 100644 --- a/app/controllers/experiments_controller.rb +++ b/app/controllers/experiments_controller.rb @@ -119,24 +119,24 @@ class ExperimentsController < ApplicationController ) ) @experiment.touch(:workflowimg_updated_at) - flash[:success] = t('experiments.update.success_flash', - experiment: @experiment.name) respond_to do |format| format.json do render json: {}, status: :ok end format.html do + flash[:success] = t('experiments.update.success_flash', + experiment: @experiment.name) redirect_to project_path(@experiment.project) end end else - flash[:alert] = t('experiments.update.error_flash') respond_to do |format| format.json do render json: @experiment.errors, status: :unprocessable_entity end format.html do + flash[:alert] = t('experiments.update.error_flash') redirect_back(fallback_location: root_path) end end diff --git a/app/views/experiments/canvas.html.erb b/app/views/experiments/canvas.html.erb index 2769de66f..ae85ee762 100644 --- a/app/views/experiments/canvas.html.erb +++ b/app/views/experiments/canvas.html.erb @@ -1,6 +1,15 @@ <% provide(:head_title, t("experiments.canvas.head_title", project: h(@project.name)).html_safe) %> <%= render partial: "shared/sidebar", locals: { current_experiment: @experiment, page: 'canvas' } %> -<%= render partial: "shared/secondary_navigation" %> +<%= render partial: "shared/secondary_navigation" , locals: { + editable: { + name: 'title', + active: true, + width: 'calc(100% - 500px)', + params_group: 'experiment', + field_to_udpate: 'name', + path_to_update: experiment_path(@experiment) + } +}%>