mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-06 03:46:39 +08:00
Protocol activities refactoring, without tests
This commit is contained in:
parent
c476816359
commit
cd7a87348f
7 changed files with 134 additions and 198 deletions
|
@ -376,6 +376,7 @@ class ProtocolsController < ApplicationController
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Everything good, display flash & render 200
|
# Everything good, display flash & render 200
|
||||||
|
log_activity_task_protocol(:update_protocol_in_task_from_repository)
|
||||||
flash[:success] = t(
|
flash[:success] = t(
|
||||||
'my_modules.protocols.revert_flash'
|
'my_modules.protocols.revert_flash'
|
||||||
)
|
)
|
||||||
|
@ -415,18 +416,7 @@ class ProtocolsController < ApplicationController
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Everything good, record activity, display flash & render 200
|
# Everything good, record activity, display flash & render 200
|
||||||
Activity.create(
|
log_activity_task_protocol(:update_protocol_in_repository_from_task)
|
||||||
type_of: :revert_protocol,
|
|
||||||
project: @protocol.my_module.experiment.project,
|
|
||||||
experiment: @protocol.my_module.experiment,
|
|
||||||
my_module: @protocol.my_module,
|
|
||||||
user: current_user,
|
|
||||||
message: I18n.t(
|
|
||||||
'activities.revert_protocol',
|
|
||||||
user: current_user.full_name,
|
|
||||||
protocol: @protocol.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
flash[:success] = t(
|
flash[:success] = t(
|
||||||
'my_modules.protocols.update_parent_flash'
|
'my_modules.protocols.update_parent_flash'
|
||||||
)
|
)
|
||||||
|
@ -466,6 +456,7 @@ class ProtocolsController < ApplicationController
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Everything good, display flash & render 200
|
# Everything good, display flash & render 200
|
||||||
|
log_activity_task_protocol(:update_protocol_in_task_from_repository)
|
||||||
flash[:success] = t(
|
flash[:success] = t(
|
||||||
'my_modules.protocols.update_from_parent_flash'
|
'my_modules.protocols.update_from_parent_flash'
|
||||||
)
|
)
|
||||||
|
@ -505,18 +496,7 @@ class ProtocolsController < ApplicationController
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Everything good, record activity, display flash & render 200
|
# Everything good, record activity, display flash & render 200
|
||||||
Activity.create(
|
log_activity_task_protocol(:load_protocol_to_task_from_repository)
|
||||||
type_of: :load_protocol_from_repository,
|
|
||||||
project: @protocol.my_module.experiment.project,
|
|
||||||
experiment: @protocol.my_module.experiment,
|
|
||||||
my_module: @protocol.my_module,
|
|
||||||
user: current_user,
|
|
||||||
message: I18n.t(
|
|
||||||
'activities.load_protocol_from_repository',
|
|
||||||
user: current_user.full_name,
|
|
||||||
protocol: @source.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
flash[:success] = t('my_modules.protocols.load_from_repository_flash')
|
flash[:success] = t('my_modules.protocols.load_from_repository_flash')
|
||||||
flash.keep(:success)
|
flash.keep(:success)
|
||||||
format.json { render json: {}, status: :ok }
|
format.json { render json: {}, status: :ok }
|
||||||
|
@ -553,18 +533,15 @@ class ProtocolsController < ApplicationController
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Everything good, record activity, display flash & render 200
|
# Everything good, record activity, display flash & render 200
|
||||||
Activity.create(
|
Activities::CreateActivityService
|
||||||
type_of: :load_protocol_from_file,
|
.call(activity_type: :load_protocol_to_task_from_file,
|
||||||
|
owner: current_user,
|
||||||
|
subject: @protocol,
|
||||||
|
team: current_team,
|
||||||
project: @protocol.my_module.experiment.project,
|
project: @protocol.my_module.experiment.project,
|
||||||
experiment: @protocol.my_module.experiment,
|
message_items: {
|
||||||
my_module: @protocol.my_module,
|
protocol: @protocol.id
|
||||||
user: current_user,
|
})
|
||||||
message: I18n.t(
|
|
||||||
'activities.load_protocol_from_file',
|
|
||||||
user: current_user.full_name,
|
|
||||||
protocol: @protocol_json[:name]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
flash[:success] = t(
|
flash[:success] = t(
|
||||||
'my_modules.protocols.load_from_file_flash'
|
'my_modules.protocols.load_from_file_flash'
|
||||||
)
|
)
|
||||||
|
@ -1234,4 +1211,17 @@ class ProtocolsController < ApplicationController
|
||||||
protocol: @protocol.id
|
protocol: @protocol.id
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_activity_task_protocol(type_of)
|
||||||
|
Activities::CreateActivityService
|
||||||
|
.call(activity_type: type_of,
|
||||||
|
owner: current_user,
|
||||||
|
subject: @protocol,
|
||||||
|
team: current_team,
|
||||||
|
project: @protocol.my_module.experiment.project,
|
||||||
|
message_items: {
|
||||||
|
protocol_task: @protocol.id,
|
||||||
|
protocol_reporitory: @protocol.parent.id
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,19 +52,7 @@ class StepCommentsController < ApplicationController
|
||||||
step_comment_annotation_notification
|
step_comment_annotation_notification
|
||||||
# Generate activity (this can only occur in module,
|
# Generate activity (this can only occur in module,
|
||||||
# but nonetheless check if my module is not nil)
|
# but nonetheless check if my module is not nil)
|
||||||
Activity.create(
|
log_activity(:add_comment_to_step)
|
||||||
type_of: :add_comment_to_step,
|
|
||||||
user: current_user,
|
|
||||||
project: @step.my_module.experiment.project,
|
|
||||||
experiment: @step.my_module.experiment,
|
|
||||||
my_module: @step.my_module,
|
|
||||||
message: t(
|
|
||||||
"activities.add_comment_to_step",
|
|
||||||
user: current_user.full_name,
|
|
||||||
step: @step.position + 1,
|
|
||||||
step_name: @step.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
format.json {
|
format.json {
|
||||||
render json: {
|
render json: {
|
||||||
|
@ -111,19 +99,8 @@ class StepCommentsController < ApplicationController
|
||||||
|
|
||||||
step_comment_annotation_notification(old_text)
|
step_comment_annotation_notification(old_text)
|
||||||
# Generate activity
|
# Generate activity
|
||||||
Activity.create(
|
log_activity(:edit_step_comment)
|
||||||
type_of: :edit_step_comment,
|
|
||||||
user: current_user,
|
|
||||||
project: @step.my_module.experiment.project,
|
|
||||||
experiment: @step.my_module.experiment,
|
|
||||||
my_module: @step.my_module,
|
|
||||||
message: t(
|
|
||||||
'activities.edit_step_comment',
|
|
||||||
user: current_user.full_name,
|
|
||||||
step: @step.position + 1,
|
|
||||||
step_name: @step.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
message = custom_auto_link(@comment.message, team: current_team)
|
message = custom_auto_link(@comment.message, team: current_team)
|
||||||
render json: { comment: message }, status: :ok
|
render json: { comment: message }, status: :ok
|
||||||
else
|
else
|
||||||
|
@ -138,20 +115,7 @@ class StepCommentsController < ApplicationController
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
if @comment.destroy
|
if @comment.destroy
|
||||||
# Generate activity
|
log_activity(:delete_step_comment)
|
||||||
Activity.create(
|
|
||||||
type_of: :delete_step_comment,
|
|
||||||
user: current_user,
|
|
||||||
project: @step.my_module.experiment.project,
|
|
||||||
experiment: @step.my_module.experiment,
|
|
||||||
my_module: @step.my_module,
|
|
||||||
message: t(
|
|
||||||
'activities.delete_step_comment',
|
|
||||||
user: current_user.full_name,
|
|
||||||
step: @step.position + 1,
|
|
||||||
step_name: @step.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
render json: {}, status: :ok
|
render json: {}, status: :ok
|
||||||
else
|
else
|
||||||
render json: { message: I18n.t('comments.delete_error') },
|
render json: { message: I18n.t('comments.delete_error') },
|
||||||
|
@ -215,4 +179,18 @@ class StepCommentsController < ApplicationController
|
||||||
protocols_my_module_url(@step.my_module)))
|
protocols_my_module_url(@step.my_module)))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_activity(type_of)
|
||||||
|
Activities::CreateActivityService
|
||||||
|
.call(activity_type: type_of,
|
||||||
|
owner: current_user,
|
||||||
|
subject: @protocol,
|
||||||
|
team: current_team,
|
||||||
|
project: @step.my_module.experiment.project,
|
||||||
|
message_items: {
|
||||||
|
protocol: @protocol.id,
|
||||||
|
step: @step.id,
|
||||||
|
step_position: { id: @step.id, value_for: 'position' }
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,19 +67,7 @@ class StepsController < ApplicationController
|
||||||
|
|
||||||
# Generate activity
|
# Generate activity
|
||||||
if @protocol.in_module?
|
if @protocol.in_module?
|
||||||
Activity.create(
|
log_activity(:create_step, @my_module.experiment.project)
|
||||||
type_of: :create_step,
|
|
||||||
user: current_user,
|
|
||||||
project: @my_module.experiment.project,
|
|
||||||
experiment: @my_module.experiment,
|
|
||||||
my_module: @my_module,
|
|
||||||
message: t(
|
|
||||||
"activities.create_step",
|
|
||||||
user: current_user.full_name,
|
|
||||||
step: @step.position + 1,
|
|
||||||
step_name: @step.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
log_activity(:add_step_to_protocol_repository)
|
log_activity(:add_step_to_protocol_repository)
|
||||||
end
|
end
|
||||||
|
@ -186,19 +174,7 @@ class StepsController < ApplicationController
|
||||||
|
|
||||||
# Generate activity
|
# Generate activity
|
||||||
if @protocol.in_module?
|
if @protocol.in_module?
|
||||||
Activity.create(
|
log_activity(:edit_step, @my_module.experiment.project)
|
||||||
type_of: :edit_step,
|
|
||||||
user: current_user,
|
|
||||||
project: @my_module.experiment.project,
|
|
||||||
experiment: @my_module.experiment,
|
|
||||||
my_module: @my_module,
|
|
||||||
message: t(
|
|
||||||
"activities.edit_step",
|
|
||||||
user: current_user.full_name,
|
|
||||||
step: @step.position + 1,
|
|
||||||
step_name: @step.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
log_activity(:edit_step_in_protocol_repository)
|
log_activity(:edit_step_in_protocol_repository)
|
||||||
end
|
end
|
||||||
|
@ -276,41 +252,34 @@ class StepsController < ApplicationController
|
||||||
|
|
||||||
# Create activity
|
# Create activity
|
||||||
if changed
|
if changed
|
||||||
str = if checked
|
|
||||||
'activities.check_step_checklist_item'
|
|
||||||
else
|
|
||||||
'activities.uncheck_step_checklist_item'
|
|
||||||
end
|
|
||||||
completed_items = @chk_item.checklist.checklist_items
|
completed_items = @chk_item.checklist.checklist_items
|
||||||
.where(checked: true).count
|
.where(checked: true).count
|
||||||
all_items = @chk_item.checklist.checklist_items.count
|
all_items = @chk_item.checklist.checklist_items.count
|
||||||
text_activity = smart_annotation_parser(@chk_item.text)
|
text_activity = smart_annotation_parser(@chk_item.text)
|
||||||
.gsub(/\s+/, ' ')
|
.gsub(/\s+/, ' ')
|
||||||
message = t(
|
type_of = if checked
|
||||||
str,
|
|
||||||
user: current_user.full_name,
|
|
||||||
checkbox: text_activity,
|
|
||||||
step: @chk_item.checklist.step.position + 1,
|
|
||||||
step_name: @chk_item.checklist.step.name,
|
|
||||||
completed: completed_items,
|
|
||||||
all: all_items
|
|
||||||
)
|
|
||||||
|
|
||||||
# This should always hold true (only in module can
|
|
||||||
# check items be checked, but still check just in case)
|
|
||||||
if @protocol.in_module?
|
|
||||||
Activity.create(
|
|
||||||
user: current_user,
|
|
||||||
project: @protocol.my_module.experiment.project,
|
|
||||||
experiment: @protocol.my_module.experiment,
|
|
||||||
my_module: @protocol.my_module,
|
|
||||||
message: message,
|
|
||||||
type_of: if checked
|
|
||||||
:check_step_checklist_item
|
:check_step_checklist_item
|
||||||
else
|
else
|
||||||
:uncheck_step_checklist_item
|
:uncheck_step_checklist_item
|
||||||
end
|
end
|
||||||
)
|
# This should always hold true (only in module can
|
||||||
|
# check items be checked, but still check just in case)
|
||||||
|
if @protocol.in_module?
|
||||||
|
Activities::CreateActivityService
|
||||||
|
.call(activity_type: type_of,
|
||||||
|
owner: current_user,
|
||||||
|
subject: @protocol,
|
||||||
|
team: current_team,
|
||||||
|
project: @protocol.my_module.experiment.project,
|
||||||
|
message_items: {
|
||||||
|
protocol: @protocol.id,
|
||||||
|
step: @chk_item.checklist.step.id,
|
||||||
|
step_position: { id: @chk_item.checklist.step.id,
|
||||||
|
value_for: 'position' },
|
||||||
|
checkbox: text_activity,
|
||||||
|
num_completed: completed_items.to_s,
|
||||||
|
num_all: all_items.to_s
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -340,30 +309,25 @@ class StepsController < ApplicationController
|
||||||
if changed
|
if changed
|
||||||
completed_steps = @protocol.steps.where(completed: true).count
|
completed_steps = @protocol.steps.where(completed: true).count
|
||||||
all_steps = @protocol.steps.count
|
all_steps = @protocol.steps.count
|
||||||
str = 'activities.uncomplete_step'
|
|
||||||
str = 'activities.complete_step' if completed
|
|
||||||
|
|
||||||
message = t(
|
|
||||||
str,
|
|
||||||
user: current_user.full_name,
|
|
||||||
step: @step.position + 1,
|
|
||||||
step_name: @step.name,
|
|
||||||
completed: completed_steps,
|
|
||||||
all: all_steps
|
|
||||||
)
|
|
||||||
|
|
||||||
|
type_of = completed ? :complete_step : :uncomplete_step
|
||||||
# Toggling step state can only occur in
|
# Toggling step state can only occur in
|
||||||
# module protocols, so my_module is always
|
# module protocols, so my_module is always
|
||||||
# not nil; nonetheless, check if my_module is present
|
# not nil; nonetheless, check if my_module is present
|
||||||
if @protocol.in_module?
|
if @protocol.in_module?
|
||||||
Activity.create(
|
Activities::CreateActivityService
|
||||||
user: current_user,
|
.call(activity_type: type_of,
|
||||||
|
owner: current_user,
|
||||||
|
subject: @protocol,
|
||||||
|
team: current_team,
|
||||||
project: @protocol.my_module.experiment.project,
|
project: @protocol.my_module.experiment.project,
|
||||||
experiment: @protocol.my_module.experiment,
|
message_items: {
|
||||||
my_module: @protocol.my_module,
|
protocol: @protocol.id,
|
||||||
message: message,
|
step: @step.id,
|
||||||
type_of: completed ? :complete_step : :uncomplete_step
|
step_position: { id: @step.id, value_for: 'position' },
|
||||||
)
|
num_completed: completed_steps.to_s,
|
||||||
|
num_all: all_steps.to_s
|
||||||
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -652,15 +616,17 @@ class StepsController < ApplicationController
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def log_activity(type_of)
|
def log_activity(type_of, project = nil)
|
||||||
Activities::CreateActivityService
|
Activities::CreateActivityService
|
||||||
.call(activity_type: type_of,
|
.call(activity_type: type_of,
|
||||||
owner: current_user,
|
owner: current_user,
|
||||||
subject: @protocol,
|
subject: @protocol,
|
||||||
team: current_team,
|
team: current_team,
|
||||||
|
project: project,
|
||||||
message_items: {
|
message_items: {
|
||||||
protocol: @protocol.id,
|
protocol: @protocol.id,
|
||||||
step: @step.id
|
step: @step.id,
|
||||||
|
step_position: { id: @step.id, value_for: 'position' }
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -131,19 +131,17 @@ class Step < ApplicationRecord
|
||||||
# Generate "delete" activity, but only if protocol is
|
# Generate "delete" activity, but only if protocol is
|
||||||
# located inside module
|
# located inside module
|
||||||
if (protocol.my_module.present?) then
|
if (protocol.my_module.present?) then
|
||||||
Activity.create(
|
Activities::CreateActivityService
|
||||||
type_of: :destroy_step,
|
.call(activity_type: :destroy_step,
|
||||||
|
owner: @current_user,
|
||||||
|
subject: protocol,
|
||||||
|
team: protocol.my_module.experiment.project.team,
|
||||||
project: protocol.my_module.experiment.project,
|
project: protocol.my_module.experiment.project,
|
||||||
experiment: protocol.my_module.experiment,
|
message_items: {
|
||||||
my_module: protocol.my_module,
|
protocol: protocol.id,
|
||||||
user: @current_user,
|
step: id,
|
||||||
message: I18n.t(
|
step_position: { id: id, value_for: 'position' }
|
||||||
"activities.destroy_step",
|
})
|
||||||
user: @current_user.full_name,
|
|
||||||
step: position + 1,
|
|
||||||
step_name: name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -73,41 +73,40 @@ module WopiUtil
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_wopi_file_activity(current_user, started_editing)
|
def create_wopi_file_activity(current_user, started_editing)
|
||||||
if @assoc.class == Step
|
action = if started_editing
|
||||||
activity = Activity.new(
|
t('activities.wupi_file_editing.started')
|
||||||
type_of: :start_edit_wopi_file,
|
else
|
||||||
user: current_user,
|
t('activities.wupi_file_editing.finished')
|
||||||
message: t(
|
|
||||||
started_editing ? 'activities.start_edit_wopi_file_step' :
|
|
||||||
'activities.unlock_wopi_file_step',
|
|
||||||
user: current_user.full_name,
|
|
||||||
file: @asset.file_file_name,
|
|
||||||
step: @asset.step.position + 1,
|
|
||||||
step_name: @asset.step.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if @protocol.in_module?
|
|
||||||
activity.my_module = @protocol.my_module
|
|
||||||
activity.project = @protocol.my_module.experiment.project
|
|
||||||
end
|
end
|
||||||
|
if @assoc.class == Step
|
||||||
activity.save
|
if @protocol.in_module?
|
||||||
|
project = @protocol.my_module.experiment.project
|
||||||
|
end
|
||||||
|
Activities::CreateActivityService
|
||||||
|
.call(activity_type: :edit_wopi_file_on_step,
|
||||||
|
owner: current_user,
|
||||||
|
subject: @protocol,
|
||||||
|
team: current_team,
|
||||||
|
project: project,
|
||||||
|
message_items: {
|
||||||
|
protocol: @protocol.id,
|
||||||
|
step: @asset.step.id,
|
||||||
|
step_position: { id: @asset.step.id, value_for: 'position' },
|
||||||
|
asset_name: { id: @asset.id, value_for: 'file_file_name' },
|
||||||
|
action: action
|
||||||
|
})
|
||||||
elsif @assoc.class == Result
|
elsif @assoc.class == Result
|
||||||
Activity.create(
|
Activities::CreateActivityService
|
||||||
type_of: :start_edit_wopi_file,
|
.call(activity_type: :edit_wopi_file_on_result,
|
||||||
user: current_user,
|
owner: current_user,
|
||||||
|
subject: @asset.result,
|
||||||
|
team: @my_module.experiment.project.team,
|
||||||
project: @my_module.experiment.project,
|
project: @my_module.experiment.project,
|
||||||
experiment: @my_module.experiment,
|
message_items: {
|
||||||
my_module: @my_module,
|
result: @asset.result.id,
|
||||||
message: t(
|
asset_name: { id: @asset.id, value_for: 'file_file_name' },
|
||||||
started_editing ? 'activities.start_edit_wopi_file_result' :
|
action: action
|
||||||
'activities.unlock_wopi_file_result',
|
})
|
||||||
user: current_user.full_name,
|
|
||||||
file: @asset.file_file_name,
|
|
||||||
result: @asset.result.name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -142,9 +142,9 @@ class Extends
|
||||||
destroy_result: 42,
|
destroy_result: 42,
|
||||||
start_edit_wopi_file: 43,
|
start_edit_wopi_file: 43,
|
||||||
unlock_wopi_file: 44,
|
unlock_wopi_file: 44,
|
||||||
load_protocol_from_file: 45,
|
load_protocol_to_task_from_file: 45,
|
||||||
load_protocol_from_repository: 46,
|
load_protocol_to_task_from_repository: 46,
|
||||||
revert_protocol: 47,
|
update_protocol_in_task_from_repository: 47,
|
||||||
create_report: 48,
|
create_report: 48,
|
||||||
delete_report: 49,
|
delete_report: 49,
|
||||||
edit_report: 50,
|
edit_report: 50,
|
||||||
|
@ -195,6 +195,8 @@ class Extends
|
||||||
export_projects: 95,
|
export_projects: 95,
|
||||||
export_inventory_items: 96,
|
export_inventory_items: 96,
|
||||||
export_audit_trails: 97,
|
export_audit_trails: 97,
|
||||||
export_system_logs: 98
|
export_system_logs: 98,
|
||||||
|
edit_wopi_file_on_result: 99,
|
||||||
|
edit_wopi_file_on_step: 100
|
||||||
}.freeze
|
}.freeze
|
||||||
end
|
end
|
||||||
|
|
|
@ -1317,6 +1317,9 @@ en:
|
||||||
text: "text"
|
text: "text"
|
||||||
table: "table"
|
table: "table"
|
||||||
asset: "file"
|
asset: "file"
|
||||||
|
wupi_file_editing:
|
||||||
|
started: "editing started"
|
||||||
|
finished: "editing finished"
|
||||||
create_project: "<i>%{user}</i> created project <strong>%{project}</strong>."
|
create_project: "<i>%{user}</i> created project <strong>%{project}</strong>."
|
||||||
rename_project: "<i>%{user}</i> renamed project <strong>%{project}</strong>."
|
rename_project: "<i>%{user}</i> renamed project <strong>%{project}</strong>."
|
||||||
change_project_visibility: "<i>%{user}</i> changed project <strong>%{project}</strong>'s visibility to %{visibility}."
|
change_project_visibility: "<i>%{user}</i> changed project <strong>%{project}</strong>'s visibility to %{visibility}."
|
||||||
|
|
Loading…
Add table
Reference in a new issue