mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-27 10:14:17 +08:00
Add task complete/uncomplete functionality [SCI-999]
This commit is contained in:
parent
c2a69982aa
commit
cf8566df33
26 changed files with 394 additions and 40 deletions
|
@ -58,7 +58,7 @@ function bindEditDueDateAjax() {
|
|||
|
||||
$(".due-date-link")
|
||||
.on("ajax:success", function (ev, data, status) {
|
||||
var dueDateLink = $(".due-date-refresh");
|
||||
var dueDateLink = $('.task-due-date');
|
||||
|
||||
// Load contents
|
||||
editDueDateModalBody.html(data.html);
|
||||
|
@ -217,6 +217,42 @@ function bindEditTagsAjax() {
|
|||
});
|
||||
}
|
||||
|
||||
// Sets callback for completing/uncompleting task
|
||||
function applyTaskCompletedCallBack() {
|
||||
// First, remove old event handlers, as we use turbolinks
|
||||
$("[data-action='complete-task'], [data-action='uncomplete-task']").off();
|
||||
|
||||
$("[data-action='complete-task'], [data-action='uncomplete-task']")
|
||||
.on('click', function() {
|
||||
var button = $(this);
|
||||
$.ajax({
|
||||
url: button.data('link-url'),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (data.completed === true) {
|
||||
button.attr('data-action', 'uncomplete-task');
|
||||
button.find('.btn')
|
||||
.removeClass('btn-primary').addClass('btn-default');
|
||||
} else {
|
||||
button.attr('data-action', 'complete-task');
|
||||
button.find('.btn')
|
||||
.removeClass('btn-default').addClass('btn-primary');
|
||||
}
|
||||
$('.task-due-date').html(data.module_header_due_date_label);
|
||||
$('.task-state-label').html(data.module_state_label);
|
||||
button.find('button').html(data.new_title);
|
||||
},
|
||||
error: function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
applyTaskCompletedCallBack();
|
||||
});
|
||||
|
||||
bindEditDueDateAjax();
|
||||
bindEditDescriptionAjax();
|
||||
bindEditTagsAjax();
|
||||
|
|
|
@ -75,7 +75,7 @@ function bindEditDueDateAjax() {
|
|||
|
||||
$(".due-date-link")
|
||||
.on("ajax:success", function(ev, data, status) {
|
||||
var dueDateLink = $(".due-date-refresh");
|
||||
var dueDateLink = $(".task-due-date");
|
||||
|
||||
// Load contents
|
||||
editDueDateModalBody.html(data.html);
|
||||
|
|
|
@ -26,6 +26,9 @@ function applyCheckboxCallBack() {
|
|||
|
||||
// Sets callback for completing/uncompleting step
|
||||
function applyStepCompletedCallBack() {
|
||||
// First, remove old event handlers, as we use turbolinks
|
||||
$("[data-action='complete-step'], [data-action='uncomplete-step']").off();
|
||||
|
||||
$("[data-action='complete-step'], [data-action='uncomplete-step']").on('click', function(e){
|
||||
var button = $(this);
|
||||
var step = $(this).parents(".step");
|
||||
|
@ -44,6 +47,15 @@ function applyStepCompletedCallBack() {
|
|||
button = step.find("[data-action='complete-step']");
|
||||
button.attr("data-action", "uncomplete-step");
|
||||
button.find(".btn").removeClass("btn-primary").addClass("btn-default");
|
||||
if (data.task_completed) {
|
||||
task_button = $("[data-action='complete-task']");
|
||||
task_button.attr('data-action', 'uncomplete-task');
|
||||
task_button.find('.btn')
|
||||
.removeClass('btn-primary').addClass('btn-default');
|
||||
$('.task-due-date').html(data.module_header_due_date_label);
|
||||
$('.task-state-label').html(data.module_state_label);
|
||||
task_button.find('button').html(data.task_button_title);
|
||||
}
|
||||
}
|
||||
else {
|
||||
step.addClass("not-completed").removeClass("completed");
|
||||
|
|
|
@ -30,6 +30,7 @@ $color-cloud: rgba(0, 0, 0, .1);
|
|||
// Miscelaneous colors
|
||||
$color-mystic: #eaeff2;
|
||||
$color-candlelight: #ffda23;
|
||||
$color-saturated-green: #008600;
|
||||
|
||||
// Red colors
|
||||
$color-mojo: #cf4b48;
|
||||
|
|
|
@ -4,6 +4,22 @@
|
|||
|
||||
@import 'constants';
|
||||
|
||||
// Protocols index page
|
||||
.task-due-date,
|
||||
.task-state-label {
|
||||
.alert-green {
|
||||
color: $color-saturated-green;
|
||||
}
|
||||
|
||||
.alert-yellow {
|
||||
color: $color-candlelight;
|
||||
}
|
||||
|
||||
.alert-red {
|
||||
color: $color-milano-red;
|
||||
}
|
||||
}
|
||||
|
||||
/* Results index page */
|
||||
|
||||
#results {
|
||||
|
|
|
@ -207,6 +207,10 @@ path, ._jsPlumb_endpoint {
|
|||
color: $color-emperor;
|
||||
}
|
||||
|
||||
.panel-body .due-date-label {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
z-index: 30;
|
||||
}
|
||||
|
@ -217,6 +221,16 @@ path, ._jsPlumb_endpoint {
|
|||
&.module-hover {
|
||||
@include box-shadow(0 0 0 5px $color-module-hover);
|
||||
}
|
||||
|
||||
&.alert-green .panel-body {
|
||||
color: $color-saturated-green;
|
||||
font-weight: bold;
|
||||
|
||||
.due-date-link {
|
||||
color: $color-saturated-green;
|
||||
}
|
||||
}
|
||||
|
||||
&.alert-yellow .panel-body {
|
||||
color: $color-candlelight;
|
||||
font-weight: bold;
|
||||
|
@ -249,6 +263,13 @@ path, ._jsPlumb_endpoint {
|
|||
&.module-hover {
|
||||
@include box-shadow(0 0 0 5px $color-module-hover);
|
||||
}
|
||||
|
||||
&.alert-green {
|
||||
border-color: $color-saturated-green;
|
||||
border-radius: 8px;
|
||||
border-width: 4px;
|
||||
}
|
||||
|
||||
&.alert-yellow {
|
||||
border-color: $color-candlelight;
|
||||
border-width: 4px;
|
||||
|
@ -321,6 +342,11 @@ path, ._jsPlumb_endpoint {
|
|||
&.module-hover {
|
||||
@include box-shadow(0 0 0 5px $color-module-hover);
|
||||
}
|
||||
|
||||
&.alert-green {
|
||||
border-color: $color-saturated-green;
|
||||
}
|
||||
|
||||
&.alert-yellow {
|
||||
border-color: $color-candlelight;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ class MyModulesController < ApplicationController
|
|||
:description, :due_date, :protocols, :results,
|
||||
:samples, :activities, :activities_tab,
|
||||
:assign_samples, :unassign_samples,
|
||||
:delete_samples,
|
||||
:delete_samples, :toggle_task_state,
|
||||
:samples_index, :archive]
|
||||
before_action :load_vars_nested, only: [:new, :create]
|
||||
before_action :check_edit_permissions, only: [
|
||||
|
@ -192,8 +192,13 @@ class MyModulesController < ApplicationController
|
|||
if saved
|
||||
format.json {
|
||||
alerts = []
|
||||
alerts << "alert-red" if @my_module.is_overdue?
|
||||
alerts << "alert-yellow" if @my_module.is_one_day_prior?
|
||||
if @my_module.is_overdue? && !@my_module.completed?
|
||||
alerts << 'alert-red'
|
||||
elsif @my_module.is_one_day_prior? && !@my_module.completed?
|
||||
alerts << 'alert-yellow'
|
||||
elsif @my_module.completed?
|
||||
alerts << 'alert-green'
|
||||
end
|
||||
render json: {
|
||||
status: :ok,
|
||||
due_date_label: render_to_string(
|
||||
|
@ -339,6 +344,82 @@ class MyModulesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Complete/uncomplete task
|
||||
def toggle_task_state
|
||||
respond_to do |format|
|
||||
if can_complete_module(@my_module)
|
||||
@my_module.completed? ? @my_module.uncomplete : @my_module.complete
|
||||
completed = @my_module.completed?
|
||||
if @my_module.save
|
||||
# Create activity
|
||||
str = if completed
|
||||
'activities.complete_module'
|
||||
else
|
||||
'activities.uncomplete_module'
|
||||
end
|
||||
message = t(str,
|
||||
user: current_user.full_name,
|
||||
module: @my_module.name)
|
||||
Activity.create(
|
||||
user: current_user,
|
||||
project: @project,
|
||||
my_module: @my_module,
|
||||
message: message,
|
||||
type_of: completed ? :complete_task : :uncomplete_task
|
||||
)
|
||||
|
||||
if completed
|
||||
title = I18n.t('notifications.types.recent_changes')
|
||||
message = I18n.t('notifications.task_completed',
|
||||
user: current_user.name,
|
||||
module: @my_module.name,
|
||||
date: l(@my_module.completed_on, format: :full),
|
||||
project: @project.name,
|
||||
experiment: @my_module.experiment.name)
|
||||
|
||||
notification = Notification.create(
|
||||
type_of: :recent_changes,
|
||||
title: title,
|
||||
message: sanitize_input(message),
|
||||
generator_user_id: current_user.id
|
||||
)
|
||||
if current_user.recent_notification
|
||||
UserNotification.create(
|
||||
notification: notification, user: current_user
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Create localized title for complete/uncomplete button
|
||||
button_title = if completed
|
||||
t('my_modules.buttons.uncomplete')
|
||||
else
|
||||
t('my_modules.buttons.complete')
|
||||
end
|
||||
|
||||
format.json do
|
||||
render json: {
|
||||
new_title: button_title,
|
||||
completed: completed,
|
||||
module_header_due_date_label: render_to_string(
|
||||
partial: 'my_modules/module_header_due_date_label.html.erb',
|
||||
locals: { my_module: @my_module }
|
||||
),
|
||||
module_state_label: render_to_string(
|
||||
partial: 'my_modules/module_state_label.html.erb',
|
||||
locals: { my_module: @my_module }
|
||||
)
|
||||
}
|
||||
end
|
||||
else
|
||||
format.json { render json: {}, status: :unprocessable_entity }
|
||||
end
|
||||
else
|
||||
format.json { render json: {}, status: :unauthorized }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_vars
|
||||
|
|
|
@ -302,6 +302,10 @@ class StepsController < ApplicationController
|
|||
end
|
||||
|
||||
if step.save
|
||||
if protocol.in_module?
|
||||
task_completed = protocol.my_module.check_completness
|
||||
end
|
||||
|
||||
# Create activity
|
||||
if changed
|
||||
completed_steps = protocol.steps.where(completed: true).count
|
||||
|
@ -336,10 +340,29 @@ class StepsController < ApplicationController
|
|||
localized_title = !completed ?
|
||||
t("protocols.steps.options.complete_title") :
|
||||
t("protocols.steps.options.uncomplete_title")
|
||||
|
||||
format.json {
|
||||
render json: {new_title: localized_title}, status: :accepted
|
||||
}
|
||||
task_button_title =
|
||||
t('my_modules.buttons.uncomplete') if task_completed
|
||||
format.json do
|
||||
if task_completed
|
||||
render json: {
|
||||
new_title: localized_title,
|
||||
task_completed: task_completed,
|
||||
task_button_title: task_button_title,
|
||||
module_header_due_date_label: render_to_string(
|
||||
partial: 'my_modules/module_header_due_date_label.html.erb',
|
||||
locals: { my_module: step.protocol.my_module }
|
||||
),
|
||||
module_state_label: render_to_string(
|
||||
partial: 'my_modules/module_state_label.html.erb',
|
||||
locals: { my_module: step.protocol.my_module }
|
||||
)
|
||||
},
|
||||
status: :accepted
|
||||
else
|
||||
render json: { new_title: localized_title },
|
||||
status: :accepted
|
||||
end
|
||||
end
|
||||
else
|
||||
format.json {
|
||||
render json: {}, status: :unprocessable_entity
|
||||
|
|
|
@ -530,6 +530,10 @@ module PermissionHelper
|
|||
is_user_or_higher_of_project(my_module.experiment.project)
|
||||
end
|
||||
|
||||
def can_complete_module(my_module)
|
||||
is_technician_or_higher_of_project(my_module.experiment.project)
|
||||
end
|
||||
|
||||
# ---- RESULTS PERMISSIONS ----
|
||||
|
||||
def can_view_results_in_module(my_module)
|
||||
|
|
|
@ -52,7 +52,9 @@ class Activity < ActiveRecord::Base
|
|||
:delete_report,
|
||||
:edit_report,
|
||||
:assign_sample,
|
||||
:unassign_sample
|
||||
:unassign_sample,
|
||||
:complete_task,
|
||||
:uncomplete_task
|
||||
]
|
||||
|
||||
validates :type_of, presence: true
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class MyModule < ActiveRecord::Base
|
||||
include ArchivableModel, SearchableModel
|
||||
|
||||
enum state: Extends::TASKS_STATES
|
||||
|
||||
before_create :create_blank_protocol
|
||||
|
||||
auto_strip_attributes :name, :description, nullify: false
|
||||
|
@ -375,6 +377,36 @@ class MyModule < ActiveRecord::Base
|
|||
{ x: 0, y: positions.last[1] + HEIGHT }
|
||||
end
|
||||
|
||||
def completed?
|
||||
state == 'completed'
|
||||
end
|
||||
|
||||
# Mark task completed if all steps become completed
|
||||
def check_completness
|
||||
if protocol && protocol.steps.count > 0
|
||||
completed = true
|
||||
protocol.steps.find_each do |step|
|
||||
completed = false unless step.completed
|
||||
end
|
||||
if completed
|
||||
complete
|
||||
save!
|
||||
return true
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def complete
|
||||
self.state = 'completed'
|
||||
self.completed_on = DateTime.now
|
||||
end
|
||||
|
||||
def uncomplete
|
||||
self.state = 'uncompleted'
|
||||
self.completed_on = nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_blank_protocol
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<div class="panel panel-default module-large<%= " alert-red" if my_module.is_overdue? %><%= " alert-yellow" if my_module.is_one_day_prior? %>"
|
||||
<div class="panel panel-default module-large
|
||||
<%= " alert-red" if my_module.is_overdue? && !my_module.completed? %>
|
||||
<%= " alert-yellow" if my_module.is_one_day_prior? && !my_module.completed? %>
|
||||
<%= " alert-green" if my_module.completed? %>"
|
||||
id="<%= my_module.id %>"
|
||||
data-module-id="<%= my_module.id %>"
|
||||
data-module-name="<%= my_module.name %>"
|
||||
|
@ -30,20 +33,13 @@
|
|||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<%= link_to_if can_edit_module(my_module) && can_edit_modules(my_module.experiment), t("experiments.canvas.full_zoom.due_date"), due_date_my_module_path(my_module, format: :json), remote: true, class: "due-date-link" %>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<% if can_edit_module(my_module) && can_edit_modules(my_module.experiment) %>
|
||||
<%= link_to due_date_my_module_path(my_module, format: :json), remote: true, class: "due-date-link due-date-refresh" do %>
|
||||
<%= render partial: "my_modules/due_date_label.html.erb", locals: { my_module: my_module } %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render partial: "my_modules/due_date_label.html.erb", locals: { my_module: my_module } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% if can_edit_module(my_module) && can_edit_modules(my_module.experiment) %>
|
||||
<%= link_to due_date_my_module_path(my_module, format: :json), remote: true, class: "due-date-link due-date-refresh" do %>
|
||||
<%= render partial: "my_modules/due_date_label.html.erb", locals: { my_module: my_module } %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render partial: "my_modules/due_date_label.html.erb", locals: { my_module: my_module } %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="panel-footer panel-footer-scinote buttons-container">
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<div class="panel panel-default module-medium<%= " alert-red" if my_module.is_overdue? %><%= " alert-yellow" if my_module.is_one_day_prior? %>"
|
||||
<div class="panel panel-default module-medium
|
||||
<%= " alert-red" if my_module.is_overdue? && !my_module.completed? %>
|
||||
<%= " alert-yellow" if my_module.is_one_day_prior? && !my_module.completed? %>
|
||||
<%= " alert-green" if my_module.completed? %>"
|
||||
id="<%= my_module.id %>"
|
||||
data-module-id="<%= my_module.id %>"
|
||||
data-module-name="<%= my_module.name %>"
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<div class="module-small<%= " alert-red" if my_module.is_overdue? %><%= " alert-yellow" if my_module.is_one_day_prior? %>"
|
||||
<div class="module-small
|
||||
<%= " alert-red" if my_module.is_overdue? && !my_module.completed? %>
|
||||
<%= " alert-yellow" if my_module.is_one_day_prior? && !my_module.completed? %>
|
||||
<%= " alert-green" if my_module.completed? %>"
|
||||
id="<%= my_module.id %>"
|
||||
data-module-id="<%= my_module.id %>"
|
||||
data-module-name="<%= my_module.name %>"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<%= bootstrap_form_for @my_module, url: my_module_path(@my_module, format: :json), remote: :true do |f| %>
|
||||
<%= f.datetime_picker :due_date, label: t("my_modules.due_date.label"), clear: true %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,8 +1,29 @@
|
|||
<% if my_module.due_date then %>
|
||||
<%=l my_module.due_date, format: :full_date %>
|
||||
<% if my_module.is_overdue? or my_module.is_one_day_prior? %>
|
||||
<% if my_module.completed? %>
|
||||
<%= t("my_modules.states.completed") %>
|
||||
<span class="due-date-label">
|
||||
<%= l(my_module.completed_on, format: :full_date) %>
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</span>
|
||||
<% elsif my_module.is_one_day_prior? %>
|
||||
<%= t("my_modules.states.due_soon") %>
|
||||
<span class="due-date-label">
|
||||
<%=l my_module.due_date, format: :full_date %>
|
||||
<span class="glyphicon glyphicon-alert"></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<% elsif my_module.is_overdue? %>
|
||||
<%= t("my_modules.states.overdue") %>
|
||||
<span class="due-date-label">
|
||||
<%=l my_module.due_date, format: :full_date %>
|
||||
<span class="glyphicon glyphicon-alert"></span>
|
||||
</span>
|
||||
<% elsif my_module.due_date %>
|
||||
<%= t("experiments.canvas.full_zoom.due_date") %>
|
||||
<span class="due-date-label">
|
||||
<%=l my_module.due_date, format: :full_date %>
|
||||
</span>
|
||||
<% else %>
|
||||
<em><%=t "experiments.canvas.full_zoom.no_due_date" %></em>
|
||||
<%= t("experiments.canvas.full_zoom.due_date") %>
|
||||
<span class="due-date-label">
|
||||
<em><%=t "experiments.canvas.full_zoom.no_due_date" %></em>
|
||||
</span>
|
||||
<% end %>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="row">
|
||||
<div class="col-xs-6 col-sm-6 col-md-3">
|
||||
<div class="col-xs-6 col-sm-6 col-md-4">
|
||||
<div class="badge-icon bg-primary">
|
||||
<span class="glyphicon glyphicon-calendar"></span>
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 col-sm-6 col-md-3">
|
||||
<div class="col-xs-6 col-sm-6 col-md-4">
|
||||
<div class="badge-icon bg-primary">
|
||||
<% if can_edit_module(@my_module) then %>
|
||||
<%= link_to due_date_my_module_path(@my_module, format: :json), remote: true, class: "due-date-link", style: "color: inherit" do %>
|
||||
|
@ -22,18 +22,35 @@
|
|||
<div class="well well-sm">
|
||||
<span class="hidden-xs hidden-sm hidden-md"><%=t "my_modules.module_header.due_date" %></span>
|
||||
<% if can_edit_module(@my_module) then %>
|
||||
<%= link_to due_date_my_module_path(@my_module, format: :json), remote: true, class: "due-date-link due-date-refresh", style: "color: inherit" do %>
|
||||
<%= link_to due_date_my_module_path(@my_module, format: :json), remote: true, class: "due-date-link", style: "color: inherit" do %>
|
||||
<span class="task-due-date">
|
||||
<%= render partial: "module_header_due_date_label.html.erb",
|
||||
locals: { my_module: @my_module } %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span class="task-due-date">
|
||||
<%= render partial: "module_header_due_date_label.html.erb",
|
||||
locals: { my_module: @my_module } %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-6" id="module-tags" data-module-tags-url="<%= my_module_my_module_tags_url(@my_module, format: :json) %>">
|
||||
<div class="col-xs-6 col-sm-6 col-md-4">
|
||||
<div class="badge-icon bg-primary">
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
</div>
|
||||
<div class="well well-sm">
|
||||
<span class="task-state-label">
|
||||
<%= render partial: "module_state_label.html.erb",
|
||||
locals: { my_module: @my_module } %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-12 col-md-12" id="module-tags" data-module-tags-url="<%= my_module_my_module_tags_url(@my_module, format: :json) %>">
|
||||
<div class="badge-icon bg-primary">
|
||||
<% if can_edit_tags_for_module(@my_module) %>
|
||||
<a class="edit-tags-link" data-remote="true" href="<%= my_module_tags_edit_url(@my_module, format: :json) %>" style="color: inherit">
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
<% if @my_module.due_date.blank? %>
|
||||
<% if my_module.due_date.blank? %>
|
||||
<em><%=t "experiments.canvas.full_zoom.no_due_date" %></em>
|
||||
<% else %>
|
||||
<strong><%= l(@my_module.due_date, format: :full) %></strong>
|
||||
<% end %>
|
||||
<strong>
|
||||
<% if my_module.completed? %>
|
||||
<span class="alert-green">
|
||||
<%= l(my_module.due_date, format: :full) %>
|
||||
</span>
|
||||
<% elsif my_module.is_one_day_prior? %>
|
||||
<span class="alert-yellow">
|
||||
<%= l(my_module.due_date, format: :full) %>
|
||||
(<%= t('my_modules.states.due_soon') %>)
|
||||
</span>
|
||||
<% elsif my_module.is_overdue? %>
|
||||
<span class="alert-red">
|
||||
<%= l(my_module.due_date, format: :full) %>
|
||||
(<%= t('my_modules.states.overdue') %>)
|
||||
</span>
|
||||
<% else %>
|
||||
<%= l(my_module.due_date, format: :full) %>
|
||||
<% end %>
|
||||
</strong>
|
||||
<% end %>
|
||||
|
|
8
app/views/my_modules/_module_state_label.html.erb
Normal file
8
app/views/my_modules/_module_state_label.html.erb
Normal file
|
@ -0,0 +1,8 @@
|
|||
<%= t('my_modules.states.state_label') %>
|
||||
<% if my_module.completed? %>
|
||||
<strong class="alert-green">
|
||||
<%= t('my_modules.states.completed_on', date: l(my_module.completed_on, format: :full_date)) %>
|
||||
</strong>
|
||||
<% else %>
|
||||
<strong><%= t('my_modules.states.in_progress') %></strong>
|
||||
<% end %>
|
15
app/views/my_modules/_state_buttons.html.erb
Normal file
15
app/views/my_modules/_state_buttons.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
|||
<div class="btn-group" style="margin-left: 15px;">
|
||||
<% if !@my_module.completed? %>
|
||||
<div data-action="complete-task" data-link-url="<%= toggle_task_state_my_module_path(@my_module) %>">
|
||||
<button class="btn btn-primary">
|
||||
<%= t("my_modules.buttons.complete") %>
|
||||
</button>
|
||||
</div>
|
||||
<% else @my_module.completed? %>
|
||||
<div data-action="uncomplete-task" data-link-url="<%= toggle_task_state_my_module_path(@my_module) %>">
|
||||
<button class="btn btn-default">
|
||||
<%= t("my_modules.buttons.uncomplete") %>
|
||||
</button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
|
@ -9,6 +9,7 @@
|
|||
<%= render partial: "my_modules/protocols/protocol_status_bar.html.erb" %>
|
||||
</div>
|
||||
<%= render partial: "my_modules/protocols/protocol_buttons.html.erb" %>
|
||||
<%= render partial: "my_modules/state_buttons.html.erb" %>
|
||||
</div>
|
||||
|
||||
<div data-role="steps-container">
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
<% else %>
|
||||
<em><%=t "projects.reports.elements.module.no_due_date" %></em>
|
||||
<% end %>
|
||||
<% if my_module.completed? %>
|
||||
<%= t("my_modules.states.completed") %>
|
||||
<%= l(my_module.completed_on, format: :full) %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
|
|
@ -14,4 +14,7 @@ class Extends
|
|||
NOTIFICATIONS_TYPES = { assignment: 0,
|
||||
recent_changes: 1,
|
||||
system_message: 2 }
|
||||
|
||||
TASKS_STATES = { uncompleted: 0,
|
||||
completed: 1 }
|
||||
end
|
||||
|
|
|
@ -430,12 +430,22 @@ en:
|
|||
add_user_generic_error: "An error occured. "
|
||||
|
||||
my_modules:
|
||||
buttons:
|
||||
complete: "Complete task"
|
||||
uncomplete: "Uncomplete task"
|
||||
description:
|
||||
title: "Edit task %{module} description"
|
||||
label: "Description"
|
||||
due_date:
|
||||
title: "Edit task %{module} due date"
|
||||
label: "Due date"
|
||||
states:
|
||||
state_label: "Status:"
|
||||
in_progress: "In progress"
|
||||
completed: "Completed on"
|
||||
completed_on: "Task completed (%{date})"
|
||||
due_soon: "due soon"
|
||||
overdue: "overdue"
|
||||
samples:
|
||||
head_title: "%{project} | %{module} | Sample library"
|
||||
module_archive:
|
||||
|
@ -979,6 +989,8 @@ en:
|
|||
archive_module: "<i>%{user}</i> moved task <strong>%{module}</strong> to archive."
|
||||
restore_module: "<i>%{user}</i> restored task <strong>%{module}</strong> from archive."
|
||||
change_module_description: "<i>%{user}</i> changed task <strong>%{module}</strong>'s description."
|
||||
complete_module: "<i>%{user}</i> completed task <strong>%{module}</strong>."
|
||||
uncomplete_module: "<i>%{user}</i> uncompleted task <strong>%{module}</strong>."
|
||||
create_step: "<i>%{user}</i> created Step %{step} <strong>%{step_name}</strong>."
|
||||
destroy_step: "<i>%{user}</i> deleted Step %{step} <strong>%{step_name}</strong>."
|
||||
add_comment_to_step: "<i>%{user}</i> commented on Step %{step} <strong>%{step_name}</strong>."
|
||||
|
@ -1455,6 +1467,7 @@ en:
|
|||
email_title: "You've received a sciNote notification!"
|
||||
assign_user_to_team: "<i>%{assigned_user}</i> was added as %{role} to team <strong>%{team}</strong> by <i>%{assigned_by_user}</i>."
|
||||
unassign_user_from_team: "<i>%{unassigned_user}</i> was removed from team <strong>%{team}</strong> by <i>%{unassigned_by_user}</i>."
|
||||
task_completed: "%{user} completed task %{module}. %{date} | Project: %{project} | Experiment: %{experiment}"
|
||||
|
||||
atwho:
|
||||
no_results: "No results found"
|
||||
|
|
|
@ -268,6 +268,7 @@ Rails.application.routes.draw do
|
|||
get 'results' # Results view for single module
|
||||
get 'samples' # Samples view for single module
|
||||
get 'archive' # Archive view for single module
|
||||
post 'toggle_task_state'
|
||||
# Renders sample datatable for single module (ajax action)
|
||||
post 'samples_index'
|
||||
post :assign_samples,
|
||||
|
|
18
db/migrate/20170207100731_add_state_to_tasks.rb
Normal file
18
db/migrate/20170207100731_add_state_to_tasks.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
class AddStateToTasks < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :my_modules,
|
||||
:state,
|
||||
:integer,
|
||||
limit: 1,
|
||||
default: 0
|
||||
add_column :my_modules,
|
||||
:completed_on,
|
||||
:datetime,
|
||||
null: true
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :my_modules, :state
|
||||
remove_column :my_modules, :completed_on
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue