Merge branch 'develop' of git.znuny.com:zammad/zammad into develop
This commit is contained in:
commit
f086b30957
11 changed files with 299 additions and 4 deletions
|
@ -80,6 +80,21 @@ class App.UiElement.user_permission
|
||||||
groupAccesses: App.Group.accesses()
|
groupAccesses: App.Group.accesses()
|
||||||
) )
|
) )
|
||||||
|
|
||||||
|
throttled = _.throttle( (e) ->
|
||||||
|
input = $(@).find('input')
|
||||||
|
upcoming_state = !input.prop('checked')
|
||||||
|
value = input.val()
|
||||||
|
console.log(upcoming_state)
|
||||||
|
console.log(value)
|
||||||
|
|
||||||
|
if value is 'full' and upcoming_state is true
|
||||||
|
$(@).closest('tr').find('input:not([value=full])').prop('checked', false)
|
||||||
|
else if value isnt 'full' and upcoming_state is true
|
||||||
|
$(@).closest('tr').find('input[value=full]').prop('checked', false)
|
||||||
|
, 300, { trailing: false })
|
||||||
|
|
||||||
|
item.on('click', '.checkbox-replacement', throttled)
|
||||||
|
|
||||||
# if customer, remove admin and agent
|
# if customer, remove admin and agent
|
||||||
item.find('[name=role_ids]').bind('change', (e) ->
|
item.find('[name=role_ids]').bind('change', (e) ->
|
||||||
element = $(e.currentTarget)
|
element = $(e.currentTarget)
|
||||||
|
|
|
@ -415,7 +415,7 @@ class App.TicketOverview extends App.Controller
|
||||||
group = App.Group.find(groupId)
|
group = App.Group.find(groupId)
|
||||||
users = []
|
users = []
|
||||||
|
|
||||||
for user_id in group.user_ids
|
for user_id in _.uniq(group.user_ids)
|
||||||
if App.User.exists(user_id)
|
if App.User.exists(user_id)
|
||||||
user = App.User.find(user_id)
|
user = App.User.find(user_id)
|
||||||
if user.active is true
|
if user.active is true
|
||||||
|
@ -620,7 +620,7 @@ class App.TicketOverview extends App.Controller
|
||||||
users.push user
|
users.push user
|
||||||
for group in groups
|
for group in groups
|
||||||
valid_user_ids = []
|
valid_user_ids = []
|
||||||
for user_id in group.user_ids
|
for user_id in _.uniq(group.user_ids)
|
||||||
if App.User.exists(user_id)
|
if App.User.exists(user_id)
|
||||||
if App.User.find(user_id).active is true
|
if App.User.find(user_id).active is true
|
||||||
valid_user_ids.push user_id
|
valid_user_ids.push user_id
|
||||||
|
|
|
@ -90,6 +90,7 @@ class Index extends App.ControllerSubContent
|
||||||
item = App.User.find(id)
|
item = App.User.find(id)
|
||||||
|
|
||||||
rerender = =>
|
rerender = =>
|
||||||
|
App.Group.fetch()
|
||||||
@renderResult(user_ids)
|
@renderResult(user_ids)
|
||||||
|
|
||||||
new App.ControllerGenericEdit(
|
new App.ControllerGenericEdit(
|
||||||
|
|
|
@ -817,8 +817,6 @@ returns
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def cache_delete
|
def cache_delete
|
||||||
super
|
super
|
||||||
|
|
||||||
|
@ -831,6 +829,8 @@ returns
|
||||||
Cache.delete(key)
|
Cache.delete(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def check_name
|
def check_name
|
||||||
if firstname.present?
|
if firstname.present?
|
||||||
firstname.strip!
|
firstname.strip!
|
||||||
|
|
|
@ -10,4 +10,32 @@ class UserGroup < ApplicationModel
|
||||||
def self.ref_key
|
def self.ref_key
|
||||||
:user_id
|
:user_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cache_update
|
||||||
|
group.cache_update(nil)
|
||||||
|
user.cache_update(nil)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def cache_delete
|
||||||
|
group.cache_update(nil)
|
||||||
|
user.cache_update(nil)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def validate_access
|
||||||
|
query = self.class.where(group: group, user: user)
|
||||||
|
|
||||||
|
query = if access == 'full'
|
||||||
|
query.where.not(access: 'full')
|
||||||
|
else
|
||||||
|
query.where(access: 'full')
|
||||||
|
end
|
||||||
|
|
||||||
|
errors.add(:access, 'User can have full or granular access to group') if query.exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
validate :validate_access
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,9 +16,11 @@ if [ "$LEVEL" == '1' ]; then
|
||||||
rm test/browser/abb_one_group_test.rb
|
rm test/browser/abb_one_group_test.rb
|
||||||
rm test/browser/admin_channel_email_test.rb
|
rm test/browser/admin_channel_email_test.rb
|
||||||
rm test/browser/admin_calendar_sla_test.rb
|
rm test/browser/admin_calendar_sla_test.rb
|
||||||
|
rm test/browser/admin_drag_drop_to_new_group_test.rb
|
||||||
rm test/browser/admin_object_manager_test.rb
|
rm test/browser/admin_object_manager_test.rb
|
||||||
rm test/browser/admin_object_manager_tree_select_test.rb
|
rm test/browser/admin_object_manager_tree_select_test.rb
|
||||||
rm test/browser/admin_overview_test.rb
|
rm test/browser/admin_overview_test.rb
|
||||||
|
rm test/browser/admin_permissions_granular_vs_full_test.rb
|
||||||
rm test/browser/admin_role_test.rb
|
rm test/browser/admin_role_test.rb
|
||||||
# test/browser/agent_navigation_and_title_test.rb
|
# test/browser/agent_navigation_and_title_test.rb
|
||||||
# test/browser/agent_organization_profile_test.rb
|
# test/browser/agent_organization_profile_test.rb
|
||||||
|
@ -86,9 +88,11 @@ elif [ "$LEVEL" == '2' ]; then
|
||||||
# test/browser/abb_one_group_test.rb
|
# test/browser/abb_one_group_test.rb
|
||||||
rm test/browser/admin_channel_email_test.rb
|
rm test/browser/admin_channel_email_test.rb
|
||||||
rm test/browser/admin_calendar_sla_test.rb
|
rm test/browser/admin_calendar_sla_test.rb
|
||||||
|
rm test/browser/admin_drag_drop_to_new_group_test.rb
|
||||||
rm test/browser/admin_object_manager_test.rb
|
rm test/browser/admin_object_manager_test.rb
|
||||||
rm test/browser/admin_object_manager_tree_select_test.rb
|
rm test/browser/admin_object_manager_tree_select_test.rb
|
||||||
rm test/browser/admin_overview_test.rb
|
rm test/browser/admin_overview_test.rb
|
||||||
|
rm test/browser/admin_permissions_granular_vs_full_test.rb
|
||||||
#rm test/browser/admin_role_test.rb
|
#rm test/browser/admin_role_test.rb
|
||||||
rm test/browser/agent_navigation_and_title_test.rb
|
rm test/browser/agent_navigation_and_title_test.rb
|
||||||
rm test/browser/agent_organization_profile_test.rb
|
rm test/browser/agent_organization_profile_test.rb
|
||||||
|
@ -156,9 +160,11 @@ elif [ "$LEVEL" == '3' ]; then
|
||||||
# test/browser/abb_one_group_test.rb
|
# test/browser/abb_one_group_test.rb
|
||||||
rm test/browser/admin_channel_email_test.rb
|
rm test/browser/admin_channel_email_test.rb
|
||||||
rm test/browser/admin_calendar_sla_test.rb
|
rm test/browser/admin_calendar_sla_test.rb
|
||||||
|
rm test/browser/admin_drag_drop_to_new_group_test.rb
|
||||||
rm test/browser/admin_object_manager_test.rb
|
rm test/browser/admin_object_manager_test.rb
|
||||||
rm test/browser/admin_object_manager_tree_select_test.rb
|
rm test/browser/admin_object_manager_tree_select_test.rb
|
||||||
rm test/browser/admin_overview_test.rb
|
rm test/browser/admin_overview_test.rb
|
||||||
|
rm test/browser/admin_permissions_granular_vs_full_test.rb
|
||||||
rm test/browser/admin_role_test.rb
|
rm test/browser/admin_role_test.rb
|
||||||
rm test/browser/agent_navigation_and_title_test.rb
|
rm test/browser/agent_navigation_and_title_test.rb
|
||||||
rm test/browser/agent_organization_profile_test.rb
|
rm test/browser/agent_organization_profile_test.rb
|
||||||
|
@ -226,9 +232,11 @@ elif [ "$LEVEL" == '4' ]; then
|
||||||
# test/browser/abb_one_group_test.rb
|
# test/browser/abb_one_group_test.rb
|
||||||
rm test/browser/admin_channel_email_test.rb
|
rm test/browser/admin_channel_email_test.rb
|
||||||
rm test/browser/admin_calendar_sla_test.rb
|
rm test/browser/admin_calendar_sla_test.rb
|
||||||
|
rm test/browser/admin_drag_drop_to_new_group_test.rb
|
||||||
rm test/browser/admin_object_manager_test.rb
|
rm test/browser/admin_object_manager_test.rb
|
||||||
rm test/browser/admin_object_manager_tree_select_test.rb
|
rm test/browser/admin_object_manager_tree_select_test.rb
|
||||||
rm test/browser/admin_overview_test.rb
|
rm test/browser/admin_overview_test.rb
|
||||||
|
rm test/browser/admin_permissions_granular_vs_full_test.rb
|
||||||
rm test/browser/admin_role_test.rb
|
rm test/browser/admin_role_test.rb
|
||||||
rm test/browser/agent_navigation_and_title_test.rb
|
rm test/browser/agent_navigation_and_title_test.rb
|
||||||
rm test/browser/agent_organization_profile_test.rb
|
rm test/browser/agent_organization_profile_test.rb
|
||||||
|
@ -295,9 +303,11 @@ elif [ "$LEVEL" == '5' ]; then
|
||||||
# test/browser/abb_one_group_test.rb
|
# test/browser/abb_one_group_test.rb
|
||||||
# test/browser/admin_channel_email_test.rb
|
# test/browser/admin_channel_email_test.rb
|
||||||
# test/browser/admin_calendar_sla_test.rb
|
# test/browser/admin_calendar_sla_test.rb
|
||||||
|
# rm test/browser/admin_drag_drop_to_new_group_test.rb
|
||||||
# test/browser/admin_object_manager_test.rb
|
# test/browser/admin_object_manager_test.rb
|
||||||
# test/browser/admin_object_manager_tree_select_test.rb
|
# test/browser/admin_object_manager_tree_select_test.rb
|
||||||
# test/browser/admin_overview_test.rb
|
# test/browser/admin_overview_test.rb
|
||||||
|
# rm test/browser/admin_permissions_granular_vs_full_test.rb
|
||||||
rm test/browser/admin_role_test.rb
|
rm test/browser/admin_role_test.rb
|
||||||
rm test/browser/agent_navigation_and_title_test.rb
|
rm test/browser/agent_navigation_and_title_test.rb
|
||||||
rm test/browser/agent_organization_profile_test.rb
|
rm test/browser/agent_organization_profile_test.rb
|
||||||
|
@ -367,9 +377,11 @@ elif [ "$LEVEL" == '6' ]; then
|
||||||
rm test/browser/abb_one_group_test.rb
|
rm test/browser/abb_one_group_test.rb
|
||||||
rm test/browser/admin_channel_email_test.rb
|
rm test/browser/admin_channel_email_test.rb
|
||||||
rm test/browser/admin_calendar_sla_test.rb
|
rm test/browser/admin_calendar_sla_test.rb
|
||||||
|
rm test/browser/admin_drag_drop_to_new_group_test.rb
|
||||||
rm test/browser/admin_object_manager_test.rb
|
rm test/browser/admin_object_manager_test.rb
|
||||||
rm test/browser/admin_object_manager_tree_select_test.rb
|
rm test/browser/admin_object_manager_tree_select_test.rb
|
||||||
rm test/browser/admin_overview_test.rb
|
rm test/browser/admin_overview_test.rb
|
||||||
|
rm test/browser/admin_permissions_granular_vs_full_test.rb
|
||||||
rm test/browser/admin_role_test.rb
|
rm test/browser/admin_role_test.rb
|
||||||
rm test/browser/agent_navigation_and_title_test.rb
|
rm test/browser/agent_navigation_and_title_test.rb
|
||||||
rm test/browser/agent_organization_profile_test.rb
|
rm test/browser/agent_organization_profile_test.rb
|
||||||
|
|
93
test/browser/admin_drag_drop_to_new_group_test.rb
Normal file
93
test/browser/admin_drag_drop_to_new_group_test.rb
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
require 'browser_test_helper'
|
||||||
|
|
||||||
|
class AdminDragDropToNewGroupTest < TestCase
|
||||||
|
def test_new_group
|
||||||
|
new_group_name = "d_n_d_group#{rand(99_999_999)}"
|
||||||
|
@browser = browser_instance
|
||||||
|
login(
|
||||||
|
username: 'master@example.com',
|
||||||
|
password: 'test',
|
||||||
|
url: browser_url,
|
||||||
|
)
|
||||||
|
tasks_close_all()
|
||||||
|
|
||||||
|
click(css: '.user-menu a[title=Admin')
|
||||||
|
click(css: '.content.active a[href="#manage/groups"]')
|
||||||
|
click(css: '.content.active a[data-type="new"]')
|
||||||
|
|
||||||
|
modal_ready
|
||||||
|
|
||||||
|
element = @browser.find_element(css: '.modal input[name=name]')
|
||||||
|
element.clear
|
||||||
|
element.send_keys(new_group_name)
|
||||||
|
click(css: '.modal button.js-submit')
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
click(css: '.content.active a[href="#manage/users"]')
|
||||||
|
|
||||||
|
user_css = '.user-list .js-tableBody tr td'
|
||||||
|
watch_for(css: user_css)
|
||||||
|
click(css: user_css)
|
||||||
|
|
||||||
|
modal_ready
|
||||||
|
|
||||||
|
scroll_script = "var el = document.getElementsByClassName('modal')[0];"
|
||||||
|
scroll_script += 'el.scrollTo(0, el.scrollHeight);'
|
||||||
|
|
||||||
|
@browser.execute_script scroll_script
|
||||||
|
|
||||||
|
group = @browser.find_elements(css: '.modal .settings-list tbody tr').find do |el|
|
||||||
|
el.find_element(css: 'td').text == new_group_name
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_not_nil(group)
|
||||||
|
|
||||||
|
%w[read create].each { |val| toggle_checkbox(group, val) }
|
||||||
|
|
||||||
|
click(css: '.modal button.js-submit')
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
click(css: '.menu-item[href="#ticket/view"]')
|
||||||
|
click(css: '.overview-header .tabsHolder a.tab[href="#ticket/view/all_unassigned"]')
|
||||||
|
|
||||||
|
element = @browser.find_element(css: '.js-tableBody .item')
|
||||||
|
|
||||||
|
@browser
|
||||||
|
.action
|
||||||
|
.click_and_hold(element)
|
||||||
|
.move_by(100, 100)
|
||||||
|
.perform
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
@browser
|
||||||
|
.action
|
||||||
|
.move_to(@browser.find_element(css: '.js-batch-assign-circle'))
|
||||||
|
.perform
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
group_containers = @browser.find_elements(css: '.batch-overlay-assign-entry[data-action=group_assign]')
|
||||||
|
|
||||||
|
new_group_container = group_containers.find do |g|
|
||||||
|
g.find_element(css: '.batch-overlay-assign-entry-name').text.downcase == new_group_name
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_not_nil new_group_container
|
||||||
|
|
||||||
|
group_description = new_group_container.find_element(css: '.batch-overlay-assign-entry-detail').text
|
||||||
|
assert_equal('1 PEOPLE', group_description)
|
||||||
|
|
||||||
|
@browser
|
||||||
|
.action
|
||||||
|
.move_to(new_group_container)
|
||||||
|
.perform
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
users_in_group = @browser.find_elements(css: '.js-batch-assign-group-inner .batch-overlay-assign-entry[data-action=user_assign]')
|
||||||
|
assert_equal(1, users_in_group.count)
|
||||||
|
end
|
||||||
|
end
|
58
test/browser/admin_permissions_granular_vs_full_test.rb
Normal file
58
test/browser/admin_permissions_granular_vs_full_test.rb
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
require 'browser_test_helper'
|
||||||
|
|
||||||
|
class AdminPermissionsGranularVsFullTest < TestCase
|
||||||
|
def test_permissions_selecting
|
||||||
|
new_group_name = "permissions_test_group#{rand(99_999_999)}"
|
||||||
|
@browser = browser_instance
|
||||||
|
login(
|
||||||
|
username: 'master@example.com',
|
||||||
|
password: 'test',
|
||||||
|
url: browser_url,
|
||||||
|
)
|
||||||
|
tasks_close_all()
|
||||||
|
|
||||||
|
click(css: '.user-menu a[title=Admin')
|
||||||
|
click(css: '.content.active a[href="#manage/groups"]')
|
||||||
|
click(css: '.content.active a[data-type="new"]')
|
||||||
|
|
||||||
|
modal_ready
|
||||||
|
|
||||||
|
element = @browser.find_element(css: '.modal input[name=name]')
|
||||||
|
element.clear
|
||||||
|
element.send_keys(new_group_name)
|
||||||
|
click(css: '.modal button.js-submit')
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
click(css: '.content.active a[href="#manage/users"]')
|
||||||
|
|
||||||
|
user_css = '.user-list .js-tableBody tr td'
|
||||||
|
watch_for(css: user_css)
|
||||||
|
click(css: user_css)
|
||||||
|
|
||||||
|
modal_ready
|
||||||
|
|
||||||
|
scroll_script = "var el = document.getElementsByClassName('modal')[0];"
|
||||||
|
scroll_script += 'el.scrollTo(0, el.scrollHeight);'
|
||||||
|
|
||||||
|
@browser.execute_script scroll_script
|
||||||
|
|
||||||
|
group = @browser.find_elements(css: '.modal .settings-list tbody tr').find do |el|
|
||||||
|
el.find_element(css: 'td').text == new_group_name
|
||||||
|
end
|
||||||
|
|
||||||
|
toggle_checkbox(group, 'full')
|
||||||
|
sleep(1)
|
||||||
|
assert(checkbox_is_selected(group, 'full'))
|
||||||
|
|
||||||
|
toggle_checkbox(group, 'read')
|
||||||
|
sleep(1)
|
||||||
|
assert(!checkbox_is_selected(group, 'full'))
|
||||||
|
assert(checkbox_is_selected(group, 'read'))
|
||||||
|
|
||||||
|
toggle_checkbox(group, 'full')
|
||||||
|
sleep(1)
|
||||||
|
assert(checkbox_is_selected(group, 'full'))
|
||||||
|
assert(!checkbox_is_selected(group, 'read'))
|
||||||
|
end
|
||||||
|
end
|
|
@ -3871,4 +3871,18 @@ wait untill text in selector disabppears
|
||||||
container: original_element
|
container: original_element
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def toggle_checkbox(scope, value)
|
||||||
|
checkbox = scope.find_element(css: "input[value=#{value}]")
|
||||||
|
|
||||||
|
@browser
|
||||||
|
.action
|
||||||
|
.move_to(checkbox)
|
||||||
|
.click
|
||||||
|
.perform
|
||||||
|
end
|
||||||
|
|
||||||
|
def checkbox_is_selected(scope, value)
|
||||||
|
scope.find_element(css: "input[value=#{value}]").property('checked')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
44
test/unit/user_group_test.rb
Normal file
44
test/unit/user_group_test.rb
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class UserGroupTest < ActiveSupport::TestCase
|
||||||
|
test 'user group permissions' do
|
||||||
|
rand = rand(9_999_999_999)
|
||||||
|
agent1 = User.create!(
|
||||||
|
login: "agent-permission-check#{rand}@example.com",
|
||||||
|
firstname: 'vaild_agent_group_permission-1',
|
||||||
|
lastname: 'Agent',
|
||||||
|
email: "agent-permission-check#{rand}@example.com",
|
||||||
|
password: 'agentpw',
|
||||||
|
active: true,
|
||||||
|
roles: Role.where(name: 'Agent'),
|
||||||
|
groups: Group.all,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
group1 = Group.create!(
|
||||||
|
name: "GroupPermissionsTest-#{rand(9_999_999_999)}",
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_nothing_raised do
|
||||||
|
UserGroup.create!(user: agent1, group: group1, access: 'full')
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raises do
|
||||||
|
UserGroup.create!(user: agent1, group: group1, access: 'read')
|
||||||
|
end
|
||||||
|
|
||||||
|
UserGroup.where(user: agent1, group: group1).destroy_all
|
||||||
|
|
||||||
|
assert_nothing_raised do
|
||||||
|
UserGroup.create!(user: agent1, group: group1, access: 'read')
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raises do
|
||||||
|
UserGroup.create!(user: agent1, group: group1, access: 'full')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1270,4 +1270,34 @@ class UserTest < ActiveSupport::TestCase
|
||||||
assert_equal(0, RecentView.where(created_by_id: agent1_id).count)
|
assert_equal(0, RecentView.where(created_by_id: agent1_id).count)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'adding group drops cache' do
|
||||||
|
agent1 = User.create!(
|
||||||
|
login: "agent-cleanup_check-1#{name}@example.com",
|
||||||
|
firstname: 'vaild_agent_group_permission-1',
|
||||||
|
lastname: "Agent#{name}",
|
||||||
|
email: "agent-cleanup_check-1#{name}@example.com",
|
||||||
|
password: 'agentpw',
|
||||||
|
active: true,
|
||||||
|
roles: Role.where(name: 'Agent'),
|
||||||
|
groups: Group.all,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
group1 = Group.create_or_update(
|
||||||
|
name: "GroupWithoutPermission-#{rand(9_999_999_999)}",
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
differences = %w[
|
||||||
|
group1.attributes_with_association_ids['user_ids'].count
|
||||||
|
agent1.attributes_with_association_ids['group_ids'].keys.count
|
||||||
|
]
|
||||||
|
|
||||||
|
assert_difference differences, 1 do
|
||||||
|
agent1.groups << group1
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue