mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-08 21:06:24 +08:00
Adding inline editing to experiment title, project title and task title [SCI-3059] (#1524)
* Adding inline editing to experiment title, project title and task title
This commit is contained in:
parent
3acf9b71f8
commit
b1df8c9aa7
11 changed files with 259 additions and 8 deletions
|
@ -38,6 +38,7 @@
|
||||||
//= require users/settings/teams/invite_users_modal
|
//= require users/settings/teams/invite_users_modal
|
||||||
//= require select2.min
|
//= require select2.min
|
||||||
//= require select2_customization
|
//= require select2_customization
|
||||||
|
//= require shared/inline_editing
|
||||||
//= require turbolinks
|
//= require turbolinks
|
||||||
|
|
||||||
|
|
||||||
|
|
63
app/assets/javascripts/shared/inline_editing.js
Normal file
63
app/assets/javascripts/shared/inline_editing.js
Normal file
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
94
app/assets/stylesheets/partials/_inline_editing.scss
Normal file
94
app/assets/stylesheets/partials/_inline_editing.scss
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,24 +119,24 @@ class ExperimentsController < ApplicationController
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@experiment.touch(:workflowimg_updated_at)
|
@experiment.touch(:workflowimg_updated_at)
|
||||||
flash[:success] = t('experiments.update.success_flash',
|
|
||||||
experiment: @experiment.name)
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
render json: {}, status: :ok
|
render json: {}, status: :ok
|
||||||
end
|
end
|
||||||
format.html do
|
format.html do
|
||||||
|
flash[:success] = t('experiments.update.success_flash',
|
||||||
|
experiment: @experiment.name)
|
||||||
redirect_to project_path(@experiment.project)
|
redirect_to project_path(@experiment.project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
flash[:alert] = t('experiments.update.error_flash')
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
render json: @experiment.errors, status: :unprocessable_entity
|
render json: @experiment.errors, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
format.html do
|
format.html do
|
||||||
|
flash[:alert] = t('experiments.update.error_flash')
|
||||||
redirect_back(fallback_location: root_path)
|
redirect_back(fallback_location: root_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
<% provide(:head_title, t("experiments.canvas.head_title", project: h(@project.name)).html_safe) %>
|
<% 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/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)
|
||||||
|
}
|
||||||
|
}%>
|
||||||
|
|
||||||
<div class="content-pane" id="experiment-canvas">
|
<div class="content-pane" id="experiment-canvas">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
4
app/views/global_activities/_team_selection.html.erb
Normal file
4
app/views/global_activities/_team_selection.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<h5>Team</h5>
|
||||||
|
<select name="team">
|
||||||
|
<%=options_for_select @teams %>
|
||||||
|
</select>
|
31
app/views/global_activities/index.html.erb
Normal file
31
app/views/global_activities/index.html.erb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<div class="global-activities__container">
|
||||||
|
<br>
|
||||||
|
<div class="global-activities__top">
|
||||||
|
<h2 class="global-activiteis__title">Global activities</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="global-activities__main">
|
||||||
|
<div class="global-activities__top-actions">
|
||||||
|
<span><i class="fas fa-caret-square-down"></i> Expand All</span>
|
||||||
|
|
||||||
|
<span><i class="fas fa-caret-square-up"></i> Colapse All</span>
|
||||||
|
</div>
|
||||||
|
<div class="global-activities__search-container">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" placeholder="Search..." aria-describedby="basic-addon1">
|
||||||
|
<span class="input-group-addon" id="basic-addon1">
|
||||||
|
<i class="fas fa-search"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="global-activities_activities-list">
|
||||||
|
<h2>list of activities</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="global-activities__side">
|
||||||
|
<%= render "team_selection" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
|
@ -2,7 +2,16 @@
|
||||||
|
|
||||||
<%= render partial: 'shared/drag_n_drop_overlay' %>
|
<%= render partial: 'shared/drag_n_drop_overlay' %>
|
||||||
<%= render partial: "shared/sidebar", locals: { current_task: @my_module, page: 'task' } %>
|
<%= render partial: "shared/sidebar", locals: { current_task: @my_module, page: 'task' } %>
|
||||||
<%= render partial: "shared/secondary_navigation" %>
|
<%= render partial: "shared/secondary_navigation", locals: {
|
||||||
|
editable: {
|
||||||
|
name: 'title',
|
||||||
|
active: true,
|
||||||
|
width: 'calc(100% - 580px)',
|
||||||
|
params_group: 'my_module',
|
||||||
|
field_to_udpate: 'name',
|
||||||
|
path_to_update: my_module_path(@my_module)
|
||||||
|
}
|
||||||
|
} %>
|
||||||
|
|
||||||
<div class="content-pane my-modules-protocols-index">
|
<div class="content-pane my-modules-protocols-index">
|
||||||
<%= render partial: "module_header" %>
|
<%= render partial: "module_header" %>
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
<% provide(:head_title, t("projects.show.head_title", project: h(@project.name)).html_safe) %>
|
<% provide(:head_title, t("projects.show.head_title", project: h(@project.name)).html_safe) %>
|
||||||
<%= render partial: "shared/sidebar", locals: { current_project: @project, page: 'project' } %>
|
<%= render partial: "shared/sidebar", locals: { current_project: @project, page: 'project' } %>
|
||||||
<%= render partial: "shared/secondary_navigation" %>
|
<%= render partial: "shared/secondary_navigation", locals: {
|
||||||
|
editable: {
|
||||||
|
name: 'title',
|
||||||
|
active: true,
|
||||||
|
width: 'calc(100% - 500px)',
|
||||||
|
params_group: 'project',
|
||||||
|
field_to_udpate: 'name',
|
||||||
|
path_to_update: project_path(@project)
|
||||||
|
}
|
||||||
|
}%>
|
||||||
|
|
||||||
<div class="content-pane" id="project-show">
|
<div class="content-pane" id="project-show">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
19
app/views/shared/_inline_editing.html.erb
Normal file
19
app/views/shared/_inline_editing.html.erb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<div
|
||||||
|
class="inline-editing-container <%= name %>-editable-field"
|
||||||
|
style="width:<%= (defined? width) ? width.html_safe : '100%' %>"
|
||||||
|
data-field-to-update="<%= field_to_udpate %>"
|
||||||
|
data-params-group="<%= params_group %>"
|
||||||
|
data-path-to-update="<%= path_to_update %>"
|
||||||
|
data-original-name="<%= initial_value %>"
|
||||||
|
error="false"
|
||||||
|
>
|
||||||
|
<input type="text" value="<%= initial_value %>" disabled/>
|
||||||
|
<div class="button-container">
|
||||||
|
<span class="save-button"><i class="fas fa-check"></i></span>
|
||||||
|
<span class="cancel-button"><i class="fas fa-times"></i></span>
|
||||||
|
</div>
|
||||||
|
<span class="error-block"></span>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
initInlineEditing('<%= name %>')
|
||||||
|
</script>
|
|
@ -149,9 +149,21 @@
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Secondary navigation title -->
|
<!-- Secondary navigation title -->
|
||||||
<h4 class="nav-name">
|
<% editable = false if local_assigns[:editable].nil? %>
|
||||||
|
<h4 class="nav-name <%= (editable && editable[:active]) ? 'editable' : '' %>">
|
||||||
|
<% if editable && editable[:active] %>
|
||||||
|
<%= render partial: "shared/inline_editing", locals: {
|
||||||
|
initial_value: truncate(title_element.name, length: Constants::MAX_EDGE_LENGTH),
|
||||||
|
width: editable[:width] || '100%',
|
||||||
|
name: editable[:name],
|
||||||
|
field_to_udpate: editable[:field_to_udpate],
|
||||||
|
path_to_update: editable[:path_to_update],
|
||||||
|
params_group: editable[:params_group]
|
||||||
|
} %>
|
||||||
|
<% else %>
|
||||||
<%= truncate(title_element.name,
|
<%= truncate(title_element.name,
|
||||||
length: Constants::MAX_EDGE_LENGTH) %>
|
length: Constants::MAX_EDGE_LENGTH) %>
|
||||||
|
<% end %>
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue