mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Revert "CLOUDSTACK-6565: [UI] New Zones tab for Templates and ISOs"
This reverts commit 348fb7bcb675f60d1a3c649a8c0af8404044642f.
This commit is contained in:
parent
aa03af7df7
commit
7ae8dc8fbd
@ -1271,7 +1271,6 @@ label.zone.type=Zone Type
|
||||
label.zone.wide=Zone-Wide
|
||||
label.zone=Zone
|
||||
label.zones=Zones
|
||||
label.multiplezones=Multiple Zones
|
||||
label.zoneWizard.trafficType.guest=Guest\: Traffic between end-user virtual machines
|
||||
label.zoneWizard.trafficType.management=Management\: Traffic between CloudStack\\\\'s internal resources, including any components that communicate with the Management Server, such as hosts and CloudStack system VMs
|
||||
label.zoneWizard.trafficType.public=Public\: Traffic between the internet and virtual machines in the cloud.
|
||||
|
||||
7
ui/css/cloudstack3.css
Executable file → Normal file
7
ui/css/cloudstack3.css
Executable file → Normal file
@ -1298,11 +1298,6 @@ div.panel div.list-view div.data-table table {
|
||||
border-left: 1px solid #CACACA;
|
||||
}
|
||||
|
||||
.detail-view div#details-tab-zones div.list-view div.data-table table td div.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
div.panel div.list-view div.fixed-header {
|
||||
position: absolute;
|
||||
top: 29px;
|
||||
@ -1318,7 +1313,7 @@ div.panel div.list-view div.fixed-header {
|
||||
.detail-view div.list-view div.fixed-header {
|
||||
width: 703px !important;
|
||||
top: 49px !important;
|
||||
left: 25px !important;
|
||||
left: 32px !important;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
|
||||
@ -1237,8 +1237,6 @@ dictionary = {
|
||||
'label.yes': '<fmt:message key="label.yes" />',
|
||||
'label.zone.details': '<fmt:message key="label.zone.details" />',
|
||||
'label.zone': '<fmt:message key="label.zone" />',
|
||||
'label.zones': '<fmt:message key="label.zones" />',
|
||||
'label.multiplezones': '<fmt:message key="label.multiplezones" />',
|
||||
'label.zone.id': '<fmt:message key="label.zone.id" />',
|
||||
'label.zone.name': '<fmt:message key="label.zone.name" />',
|
||||
'label.zone.step.1.title': '<fmt:message key="label.zone.step.1.title" />',
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
name: {
|
||||
label: 'label.name'
|
||||
},
|
||||
zones: {
|
||||
zonename: {
|
||||
label: 'label.zone'
|
||||
},
|
||||
hypervisor: {
|
||||
@ -601,31 +601,9 @@
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var items = json.listtemplatesresponse.template;
|
||||
var itemsView = [];
|
||||
|
||||
$(items).each(function(index, item) {
|
||||
var existing = $.grep(itemsView, function(it){
|
||||
return it != null && it.id !=null && it.id == item.id;
|
||||
});
|
||||
|
||||
if (existing.length == 0) {
|
||||
itemsView.push({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
description: item.description,
|
||||
zones: item.zonename,
|
||||
zoneids: [item.zoneid]
|
||||
});
|
||||
}
|
||||
else {
|
||||
existing[0].zones = 'label.multiplezones';
|
||||
existing[0].zoneids.push(item.zoneid);
|
||||
}
|
||||
});
|
||||
|
||||
args.response.success({
|
||||
actionFilter: templateActionfilter,
|
||||
data: itemsView
|
||||
data: items
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -771,6 +749,91 @@
|
||||
}
|
||||
},
|
||||
|
||||
copyTemplate: {
|
||||
label: 'label.action.copy.template',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'message.copy.template.confirm';
|
||||
},
|
||||
success: function(args) {
|
||||
return 'message.template.copying';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.action.copy.template';
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
title: 'label.action.copy.template',
|
||||
desc: '',
|
||||
fields: {
|
||||
destinationZoneId: {
|
||||
label: 'label.destination.zone',
|
||||
docID: 'helpCopyTemplateDestination',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
$.ajax({
|
||||
url: createURL("listZones&available=true"),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var zoneObjs = [];
|
||||
var items = json.listzonesresponse.zone;
|
||||
if (items != null) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if (items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone
|
||||
zoneObjs.push({
|
||||
id: items[i].id,
|
||||
description: items[i].name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
args.response.success({
|
||||
data: zoneObjs
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var data = {
|
||||
id: args.context.templates[0].id,
|
||||
destzoneid: args.data.destinationZoneId
|
||||
};
|
||||
if (args.context.templates[0].zoneid != undefined) {
|
||||
$.extend(data, {
|
||||
sourcezoneid: args.context.templates[0].zoneid
|
||||
});
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL('copyTemplate'),
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var jid = json.copytemplateresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid,
|
||||
getUpdatedItem: function(json) {
|
||||
return {}; //nothing in this template needs to be updated
|
||||
},
|
||||
getActionFilter: function() {
|
||||
return templateActionfilter;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
},
|
||||
|
||||
downloadTemplate: {
|
||||
label: 'label.action.download.template',
|
||||
messages: {
|
||||
@ -817,6 +880,40 @@
|
||||
}
|
||||
},
|
||||
|
||||
remove: {
|
||||
label: 'label.action.delete.template',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'message.action.delete.template';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.action.delete.template';
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var array1 = [];
|
||||
if (args.context.templates[0].zoneid != null)
|
||||
array1.push("&zoneid=" + args.context.templates[0].zoneid);
|
||||
|
||||
$.ajax({
|
||||
url: createURL("deleteTemplate&id=" + args.context.templates[0].id + array1.join("")),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var jid = json.deletetemplateresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
tabs: {
|
||||
details: {
|
||||
@ -846,6 +943,14 @@
|
||||
}
|
||||
}
|
||||
}, {
|
||||
isready: {
|
||||
label: 'state.ready',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
},
|
||||
status: {
|
||||
label: 'label.status'
|
||||
},
|
||||
|
||||
hypervisor: {
|
||||
label: 'label.hypervisor'
|
||||
},
|
||||
@ -945,6 +1050,9 @@
|
||||
}
|
||||
},
|
||||
|
||||
zonename: {
|
||||
label: 'label.zone.name'
|
||||
},
|
||||
crossZones: {
|
||||
label: 'label.cross.zones',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
@ -974,6 +1082,9 @@
|
||||
|
||||
id: {
|
||||
label: 'label.id'
|
||||
},
|
||||
zoneid: {
|
||||
label: 'label.zone.id'
|
||||
}
|
||||
}],
|
||||
|
||||
@ -1009,160 +1120,6 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
zones: {
|
||||
title: 'label.zones',
|
||||
listView: {
|
||||
id: 'zones',
|
||||
fields: {
|
||||
zonename: {
|
||||
label: 'label.name'
|
||||
},
|
||||
status: {
|
||||
label: 'label.status'
|
||||
},
|
||||
isready: {
|
||||
label: 'state.ready',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
}
|
||||
},
|
||||
hideSearchBar: true,
|
||||
actions: {
|
||||
remove: {
|
||||
label: 'label.action.delete.template',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'message.action.delete.template';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.action.delete.template';
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
$.ajax({
|
||||
url: createURL("deleteTemplate&id=" + args.context.templates[0].id + "&zoneid=" + args.context.zones[0].zoneid),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var jid = json.deletetemplateresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
},
|
||||
copyTemplate: {
|
||||
label: 'label.action.copy.template',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'message.copy.template.confirm';
|
||||
},
|
||||
success: function(args) {
|
||||
return 'message.template.copying';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.action.copy.template';
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
title: 'label.action.copy.template',
|
||||
desc: '',
|
||||
fields: {
|
||||
destinationZoneId: {
|
||||
label: 'label.destination.zone',
|
||||
docID: 'helpCopyTemplateDestination',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
$.ajax({
|
||||
url: createURL("listZones&available=true"),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var zoneObjs = [];
|
||||
var items = json.listzonesresponse.zone;
|
||||
if (items != null) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if ($.inArray(items[i].id, args.context.templates[0].zoneids) == -1) { //destination zones should not contain zones where the template is already available
|
||||
zoneObjs.push({
|
||||
id: items[i].id,
|
||||
description: items[i].name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
args.response.success({
|
||||
data: zoneObjs
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var data = {
|
||||
id: args.context.templates[0].id,
|
||||
destzoneid: args.data.destinationZoneId
|
||||
};
|
||||
$.extend(data, {
|
||||
sourcezoneid: args.context.templates[0].zoneid
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: createURL('copyTemplate'),
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var jid = json.copytemplateresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid,
|
||||
getUpdatedItem: function(json) {
|
||||
return {}; //nothing in this template needs to be updated
|
||||
},
|
||||
getActionFilter: function() {
|
||||
return templateActionfilter;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dataProvider: function(args) {
|
||||
var jsonObj = args.context.templates[0];
|
||||
var apiCmd = "listTemplates&templatefilter=self&id=" + jsonObj.id;
|
||||
|
||||
$.ajax({
|
||||
url: createURL(apiCmd),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var templates = json.listtemplatesresponse.template;
|
||||
var zones = [];
|
||||
zones = templates;
|
||||
|
||||
args.response.success({
|
||||
actionFilter: templateActionfilter,
|
||||
data: zones
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1197,7 +1154,7 @@
|
||||
name: {
|
||||
label: 'label.name'
|
||||
},
|
||||
zones: {
|
||||
zonename: {
|
||||
label: 'label.zone'
|
||||
}
|
||||
},
|
||||
@ -1477,30 +1434,9 @@
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var items = json.listisosresponse.iso;
|
||||
|
||||
var itemsView = [];
|
||||
$(items).each(function(index, item) {
|
||||
var existing = $.grep(itemsView, function(it){
|
||||
return it != null && it.id !=null && it.id == item.id;
|
||||
});
|
||||
if (existing.length == 0) {
|
||||
itemsView.push({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
description: item.description,
|
||||
zones: item.zonename,
|
||||
zoneids: [item.zoneid]
|
||||
});
|
||||
}
|
||||
else {
|
||||
existing[0].zones = 'Multiple Zones';
|
||||
existing[0].zoneids.push(item.zoneid);
|
||||
}
|
||||
}
|
||||
);
|
||||
args.response.success({
|
||||
actionFilter: isoActionfilter,
|
||||
data: itemsView
|
||||
data: items
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1595,6 +1531,85 @@
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
copyISO: {
|
||||
label: 'label.action.copy.ISO',
|
||||
messages: {
|
||||
notification: function(args) {
|
||||
return 'Copying ISO';
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
title: 'label.action.copy.ISO',
|
||||
desc: 'label.action.copy.ISO',
|
||||
fields: {
|
||||
destinationZoneId: {
|
||||
label: 'label.destination.zone',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
$.ajax({
|
||||
url: createURL("listZones&available=true"),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var zoneObjs = [];
|
||||
var items = json.listzonesresponse.zone;
|
||||
if (items != null) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if (items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone
|
||||
zoneObjs.push({
|
||||
id: items[i].id,
|
||||
description: items[i].name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
args.response.success({
|
||||
data: zoneObjs
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var data = {
|
||||
id: args.context.isos[0].id,
|
||||
destzoneid: args.data.destinationZoneId
|
||||
};
|
||||
if (args.context.isos[0].zoneid != undefined) {
|
||||
$.extend(data, {
|
||||
sourcezoneid: args.context.isos[0].zoneid
|
||||
});
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL('copyIso'),
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var jid = json.copytemplateresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid,
|
||||
getUpdatedItem: function(json) {
|
||||
return {}; //nothing in this ISO needs to be updated
|
||||
},
|
||||
getActionFilter: function() {
|
||||
return isoActionfilter;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
},
|
||||
|
||||
downloadISO: {
|
||||
label: 'label.action.download.ISO',
|
||||
messages: {
|
||||
@ -1639,7 +1654,42 @@
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
},
|
||||
|
||||
remove: {
|
||||
label: 'label.action.delete.ISO',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'message.action.delete.ISO';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.action.delete.ISO';
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var array1 = [];
|
||||
if (args.context.isos[0].zoneid != null)
|
||||
array1.push("&zoneid=" + args.context.isos[0].zoneid);
|
||||
|
||||
$.ajax({
|
||||
url: createURL("deleteIso&id=" + args.context.isos[0].id + array1.join("")),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var jid = json.deleteisosresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
tabs: {
|
||||
@ -1658,6 +1708,12 @@
|
||||
id: {
|
||||
label: 'ID'
|
||||
},
|
||||
zonename: {
|
||||
label: 'label.zone.name'
|
||||
},
|
||||
zoneid: {
|
||||
label: 'label.zone.id'
|
||||
},
|
||||
displaytext: {
|
||||
label: 'label.description',
|
||||
isEditable: true,
|
||||
@ -1665,6 +1721,13 @@
|
||||
required: true
|
||||
}
|
||||
},
|
||||
isready: {
|
||||
label: 'state.Ready',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
},
|
||||
status: {
|
||||
label: 'label.status'
|
||||
},
|
||||
size: {
|
||||
label: 'label.size',
|
||||
converter: function(args) {
|
||||
@ -1771,158 +1834,6 @@
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
zones: {
|
||||
title: 'label.zones',
|
||||
listView: {
|
||||
id: 'zones',
|
||||
fields: {
|
||||
zonename: {
|
||||
label: 'label.name'
|
||||
},
|
||||
status: {
|
||||
label: 'label.status'
|
||||
},
|
||||
isready: {
|
||||
label: 'state.ready',
|
||||
converter: cloudStack.converters.toBooleanText
|
||||
}
|
||||
},
|
||||
hideSearchBar: true,
|
||||
actions: {
|
||||
copyISO: {
|
||||
label: 'label.action.copy.ISO',
|
||||
messages: {
|
||||
notification: function(args) {
|
||||
return 'Copying ISO';
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
title: 'label.action.copy.ISO',
|
||||
desc: 'label.action.copy.ISO',
|
||||
fields: {
|
||||
destinationZoneId: {
|
||||
label: 'label.destination.zone',
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
select: function(args) {
|
||||
$.ajax({
|
||||
url: createURL("listZones&available=true"),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var zoneObjs = [];
|
||||
var items = json.listzonesresponse.zone;
|
||||
if (items != null) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if ($.inArray(items[i].id, args.context.isos[0].zoneids) == -1) { //destination zones should not contain zones where the ISO is already available
|
||||
zoneObjs.push({
|
||||
id: items[i].id,
|
||||
description: items[i].name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
args.response.success({
|
||||
data: zoneObjs
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var data = {
|
||||
id: args.context.isos[0].id,
|
||||
destzoneid: args.data.destinationZoneId
|
||||
};
|
||||
if (args.context.isos[0].zoneid != undefined) {
|
||||
$.extend(data, {
|
||||
sourcezoneid: args.context.isos[0].zoneid
|
||||
});
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: createURL('copyIso'),
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var jid = json.copytemplateresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid,
|
||||
getUpdatedItem: function(json) {
|
||||
return {}; //nothing in this ISO needs to be updated
|
||||
},
|
||||
getActionFilter: function() {
|
||||
return isoActionfilter;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
},
|
||||
|
||||
remove: {
|
||||
label: 'label.action.delete.ISO',
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'message.action.delete.ISO';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'label.action.delete.ISO';
|
||||
}
|
||||
},
|
||||
action: function(args) {
|
||||
var array1 = [];
|
||||
if (args.context.isos[0].zoneid != null)
|
||||
array1.push("&zoneid=" + args.context.isos[0].zoneid);
|
||||
|
||||
$.ajax({
|
||||
url: createURL("deleteIso&id=" + args.context.isos[0].id + "&zoneid=" + args.context.zones[0].zoneid),
|
||||
dataType: "json",
|
||||
async: true,
|
||||
success: function(json) {
|
||||
var jid = json.deleteisosresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dataProvider: function(args) {
|
||||
var jsonObj = args.context.isos[0];
|
||||
var apiCmd = "listIsos&isofilter=self&id=" + jsonObj.id;
|
||||
|
||||
$.ajax({
|
||||
url: createURL(apiCmd),
|
||||
dataType: "json",
|
||||
success: function(json) {
|
||||
var isos = json.listisosresponse.iso;
|
||||
var zones = [];
|
||||
zones = isos;
|
||||
|
||||
args.response.success({
|
||||
actionFilter: isoActionfilter,
|
||||
data: zones
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user