mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-27 02:04:33 +08:00
Merge branch 'features/task-flows' into ml-sci-4984
This commit is contained in:
commit
3c30ee904e
12 changed files with 78 additions and 132 deletions
|
@ -24,38 +24,6 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Complete mymodule
|
||||
function complete_my_module_actions() {
|
||||
var modal = $('#completed-task-modal');
|
||||
|
||||
modal.find('[data-action="complete"]')
|
||||
.off().on().click(function(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
$.ajax({
|
||||
url: modal.data('url'),
|
||||
type: 'GET',
|
||||
success: function(data) {
|
||||
var task_button = $("[data-action='complete-task']");
|
||||
task_button.attr('data-action', 'uncomplete-task');
|
||||
task_button.find('.btn')
|
||||
.removeClass('btn-toggle').addClass('btn-default');
|
||||
$('.task-due-date').html(data.module_header_due_date);
|
||||
$('.task-state-label').html(data.module_state_label);
|
||||
task_button
|
||||
.find('button')
|
||||
.html('<span class="fas fa-times"></span> ' +
|
||||
data.task_button_title);
|
||||
modal.modal('hide');
|
||||
},
|
||||
error: function() {
|
||||
modal.modal('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Sets callback for completing/uncompleting step
|
||||
function applyStepCompletedCallBack() {
|
||||
// First, remove old event handlers, as we use turbolinks
|
||||
|
@ -79,11 +47,6 @@
|
|||
button.attr("data-action", "uncomplete-step");
|
||||
button.find(".btn").removeClass("btn-toggle").addClass("btn-default");
|
||||
button.find("button").html('<span class="fas fa-times"></span> ' + data.new_title);
|
||||
|
||||
if (data.task_ready_to_complete) {
|
||||
$('#completed-task-modal').modal('show');
|
||||
complete_my_module_actions();
|
||||
}
|
||||
}
|
||||
else {
|
||||
step.addClass("not-completed").removeClass("completed");
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
align-items: center;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, auto) 12px minmax(0, auto);
|
||||
padding: .5em 0;
|
||||
padding: .5em 0 0;
|
||||
|
||||
li {
|
||||
display: contents;
|
||||
|
@ -74,13 +74,23 @@
|
|||
grid-column: span 3;
|
||||
line-height: 1em;
|
||||
padding: 0em 1em .5em;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.permission-error {
|
||||
padding: .5em 1em;
|
||||
}
|
||||
}
|
||||
|
||||
#viewTaskFlow {
|
||||
border-top: $border-default;
|
||||
cursor: pointer;
|
||||
display: list-item;
|
||||
grid-column: span 3;
|
||||
line-height: 2em;
|
||||
margin-top: .5em;
|
||||
padding: .5em 1em;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,13 +60,13 @@ module Api
|
|||
def task_params_create
|
||||
raise TypeError unless params.require(:data).require(:type) == 'tasks'
|
||||
|
||||
params.require(:data).require(:attributes).permit(%i(name x y description state))
|
||||
params.require(:data).require(:attributes).permit(%i(name x y description))
|
||||
end
|
||||
|
||||
def task_params_update
|
||||
raise TypeError unless params.require(:data).require(:type) == 'tasks'
|
||||
|
||||
params.require(:data).require(:attributes).permit(%i(name x y description state my_module_status_id))
|
||||
params.require(:data).require(:attributes).permit(%i(name x y description my_module_status_id))
|
||||
end
|
||||
|
||||
def load_task_for_managing
|
||||
|
|
|
@ -321,10 +321,6 @@ class StepsController < ApplicationController
|
|||
@step.completed = completed
|
||||
|
||||
if @step.save
|
||||
if @protocol.in_module?
|
||||
ready_to_complete = @protocol.my_module.check_completness_status
|
||||
end
|
||||
|
||||
# Create activity
|
||||
if changed
|
||||
completed_steps = @protocol.steps.where(completed: true).count
|
||||
|
@ -350,14 +346,7 @@ class StepsController < ApplicationController
|
|||
t('protocols.steps.options.uncomplete_title')
|
||||
end
|
||||
format.json do
|
||||
if ready_to_complete && @protocol.my_module.uncompleted?
|
||||
render json: {
|
||||
task_ready_to_complete: true,
|
||||
new_title: localized_title
|
||||
}, status: :ok
|
||||
else
|
||||
render json: { new_title: localized_title }, status: :ok
|
||||
end
|
||||
render json: { new_title: localized_title }, status: :ok
|
||||
end
|
||||
else
|
||||
format.json { render json: {}, status: :unprocessable_entity }
|
||||
|
|
|
@ -9,8 +9,6 @@ class MyModule < ApplicationRecord
|
|||
before_create :create_blank_protocol
|
||||
before_create :assign_default_status_flow
|
||||
|
||||
before_validation :set_completed, if: :my_module_status_id_changed?
|
||||
before_validation :set_completed_on, if: :state_changed?
|
||||
before_save :exec_status_consequences, if: :my_module_status_id_changed?
|
||||
|
||||
auto_strip_attributes :name, :description, nullify: false
|
||||
|
@ -477,18 +475,6 @@ class MyModule < ApplicationRecord
|
|||
{ x: 0, y: positions.last[1] + HEIGHT }
|
||||
end
|
||||
|
||||
# Check if my_module is ready to become completed
|
||||
def check_completness_status
|
||||
if protocol && protocol.steps.count > 0
|
||||
completed = true
|
||||
protocol.steps.find_each do |step|
|
||||
completed = false unless step.completed
|
||||
end
|
||||
return true if completed
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def assign_user(user, assigned_by = nil)
|
||||
user_my_modules.create(
|
||||
assigned_by: assigned_by || user,
|
||||
|
@ -506,22 +492,6 @@ class MyModule < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def set_completed
|
||||
return if my_module_status.blank?
|
||||
|
||||
if my_module_status.final_status?
|
||||
self.state = 'completed'
|
||||
else
|
||||
self.state = 'uncompleted'
|
||||
end
|
||||
end
|
||||
|
||||
def set_completed_on
|
||||
return if completed? && completed_on.present?
|
||||
|
||||
self.completed_on = completed? ? DateTime.now : nil
|
||||
end
|
||||
|
||||
def create_blank_protocol
|
||||
protocols << Protocol.new_blank_for_module(self)
|
||||
end
|
||||
|
|
12
app/models/my_module_status_consequences/completion.rb
Normal file
12
app/models/my_module_status_consequences/completion.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Just an example, to be replaced with an actual implementation
|
||||
module MyModuleStatusConsequences
|
||||
class Completion < MyModuleStatusConsequence
|
||||
def call(my_module)
|
||||
my_module.state = 'completed'
|
||||
my_module.completed_on = DateTime.now
|
||||
my_module.save!
|
||||
end
|
||||
end
|
||||
end
|
14
app/models/my_module_status_consequences/uncompletion.rb
Normal file
14
app/models/my_module_status_consequences/uncompletion.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Just an example, to be replaced with an actual implementation
|
||||
module MyModuleStatusConsequences
|
||||
class Uncompletion < MyModuleStatusConsequence
|
||||
def call(my_module)
|
||||
return unless my_module.state == 'completed'
|
||||
|
||||
my_module.state = 'uncompleted'
|
||||
my_module.completed_on = nil
|
||||
my_module.save!
|
||||
end
|
||||
end
|
||||
end
|
|
@ -26,7 +26,7 @@
|
|||
<%= render partial: 'my_module_details' %>
|
||||
</div>
|
||||
<div class="task-flows">
|
||||
<%= render partial: 'my_modules/status_flow/task_flow_button', locals: { my_module: @my_module } if @my_module.my_module_status_flow && can_change_my_module_flow_status?(@my_module) %>
|
||||
<%= render partial: 'my_modules/status_flow/task_flow_button', locals: { my_module: @my_module } if @my_module.my_module_status_flow %>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Notes -->
|
||||
|
|
|
@ -21,38 +21,38 @@
|
|||
<span class="caret pull-right"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownTaskFlow" id="dropdownTaskFlowList" data-link-url="<%= update_state_my_module_url(my_module) %>">
|
||||
<% unless status.initial_status? %>
|
||||
<% previous_s = status.previous_status %>
|
||||
<% previous_s_errors = previous_s.conditions_errors(my_module) %>
|
||||
<li data-state-id="<%= previous_s.id %>" class="<%= 'disabled' if previous_s_errors.any? %>">
|
||||
<span><%= t('my_module_statuses.dropdown.return_label') %></span>
|
||||
<i class="fas fa-long-arrow-alt-right"></i>
|
||||
<div class=" status-container">
|
||||
<div class="status-name" style="<%= "background-color: #{previous_s.color}" %>"><%= previous_s.name %></div>
|
||||
</div>
|
||||
</li>
|
||||
<span class="error-message">
|
||||
<% previous_s_errors.each do |error| %>
|
||||
<%= error %><br>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if can_change_my_module_flow_status?(@my_module) %>
|
||||
<% unless status.initial_status? %>
|
||||
<% previous_s = status.previous_status %>
|
||||
<% previous_s_errors = previous_s.conditions_errors(my_module) %>
|
||||
<li data-state-id="<%= previous_s.id %>" class="<%= 'disabled' if previous_s_errors.any? %>">
|
||||
<span><%= t('my_module_statuses.dropdown.return_label') %></span>
|
||||
<i class="fas fa-long-arrow-alt-right"></i>
|
||||
<div class=" status-container">
|
||||
<div class="status-name" style="<%= "background-color: #{previous_s.color}" %>"><%= previous_s.name %></div>
|
||||
</div>
|
||||
</li>
|
||||
<span class="error-message"><% previous_s_errors.each do |error| %>
|
||||
<%= error %><br>
|
||||
<% end %></span>
|
||||
<% end %>
|
||||
|
||||
<% unless status.final_status? %>
|
||||
<% next_s = status.next_status %>
|
||||
<% next_s_errors = next_s.conditions_errors(my_module) %>
|
||||
<li data-state-id="<%= next_s.id %>" class="<%= 'disabled' if next_s_errors.any? %>">
|
||||
<span><%= t('my_module_statuses.dropdown.move_label') %></span>
|
||||
<i class="fas fa-long-arrow-alt-right"></i>
|
||||
<div class="status-container">
|
||||
<div class="status-name" style="<%= "background-color: #{next_s.color}" %>"><%= next_s.name %></div>
|
||||
</div>
|
||||
</li>
|
||||
<span class="error-message">
|
||||
<% next_s_errors.each do |error| %>
|
||||
<%= error %><br>
|
||||
<% end %>
|
||||
</span>
|
||||
<% unless status.final_status? %>
|
||||
<% next_s = status.next_status %>
|
||||
<% next_s_errors = next_s.conditions_errors(my_module) %>
|
||||
<li data-state-id="<%= next_s.id %>" class="<%= 'disabled' if next_s_errors.any? %>">
|
||||
<span><%= t('my_module_statuses.dropdown.move_label') %></span>
|
||||
<i class="fas fa-long-arrow-alt-right"></i>
|
||||
<div class="status-container">
|
||||
<div class="status-name" style="<%= "background-color: #{next_s.color}" %>"><%= next_s.name %></div>
|
||||
</div>
|
||||
</li>
|
||||
<span class="error-message"><% next_s_errors.each do |error| %>
|
||||
<%= error %><br>
|
||||
<% end %></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<span class="error-message permission-error"><%= t('my_module_statuses.dropdown.no_permission_label') %></span>
|
||||
<% end %>
|
||||
<li id="viewTaskFlow">
|
||||
<%= t('my_module_statuses.dropdown.view_flow_label') %>
|
||||
|
|
|
@ -327,7 +327,7 @@ class Extends
|
|||
|
||||
DEFAULT_FLOW_STATUSES = [
|
||||
{ name: 'Not started', color: '#406d86' },
|
||||
{ name: 'In progress', color: '#0065ff' },
|
||||
{ name: 'Completed', color: '#00b900' }
|
||||
{ name: 'In progress', color: '#0065ff', consequences: ['MyModuleStatusConsequences::Uncompletion'] },
|
||||
{ name: 'Completed', color: '#00b900', consequences: ['MyModuleStatusConsequences::Completion'] }
|
||||
]
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@ en:
|
|||
move_label: 'Move to'
|
||||
return_label: 'Return to'
|
||||
view_flow_label: 'View task flow'
|
||||
no_permission_label: 'You don’t have permission to change the status of this task.'
|
||||
update_status:
|
||||
error:
|
||||
no_permission: 'You dont have permission to change the status'
|
||||
|
|
|
@ -292,7 +292,7 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
|
|||
end
|
||||
end
|
||||
|
||||
context 'task completion, when has valid params' do
|
||||
context 'direct task completion disabled, when has valid params' do
|
||||
let(:request_body) do
|
||||
{
|
||||
data: {
|
||||
|
@ -304,23 +304,10 @@ RSpec.describe 'Api::V1::TasksController', type: :request do
|
|||
}
|
||||
end
|
||||
|
||||
it 'returns status 200' do
|
||||
it 'returns status 204, no changes to task' do
|
||||
action
|
||||
|
||||
expect(response).to have_http_status 200
|
||||
end
|
||||
|
||||
it 'returns well formated response' do
|
||||
action
|
||||
|
||||
expect(json).to match(
|
||||
hash_including(
|
||||
data: hash_including(
|
||||
type: 'tasks',
|
||||
attributes: hash_including(state: 'completed')
|
||||
)
|
||||
)
|
||||
)
|
||||
expect(response).to have_http_status 204
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue