Support post messages and get messages
This patch adds "Post Messages" and "View Messages" actions. "delete" and "claim" actions for list messages dialog will be added by subsequent patches. Implement blueprint: post-get-messages Change-Id: I42f44e2d8ab9266ba8c21c853956ca69c62ecfce
This commit is contained in:
parent
be8708b36d
commit
ad6b606585
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import six
|
||||
import yaml
|
||||
|
||||
@ -138,7 +139,7 @@ class Queues(generic.View):
|
||||
|
||||
@urls.register
|
||||
class Subscriptions(generic.View):
|
||||
"""API for queues"""
|
||||
"""API for Subscriptions"""
|
||||
url_regex = r'zaqar/queues/(?P<queue_name>[^/]+)/subscriptions/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
@ -163,6 +164,35 @@ class Subscriptions(generic.View):
|
||||
return zaqar.subscription_create(request, queue_name, request.DATA)
|
||||
|
||||
|
||||
@urls.register
|
||||
class Messages(generic.View):
|
||||
"""API for messages"""
|
||||
url_regex = r'zaqar/queues/(?P<queue_name>[^/]+)/messages/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, queue_name):
|
||||
"""Get a list of messages"""
|
||||
result = zaqar.message_list(request, queue_name)
|
||||
messages = []
|
||||
for m in result:
|
||||
claim_id = None
|
||||
if m.claim_id:
|
||||
claim_id = m.claim_id()
|
||||
messages.append({'age': m.age,
|
||||
'body': m.body,
|
||||
'claim_id': claim_id,
|
||||
'id': m.id,
|
||||
'href': m.href,
|
||||
'ttl': m.ttl})
|
||||
return messages
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def post(self, request, queue_name):
|
||||
"""Create new messages"""
|
||||
messages = json.loads(request.DATA.get("messages"))
|
||||
return zaqar.message_post(request, queue_name, messages)
|
||||
|
||||
|
||||
@urls.register
|
||||
class Subscription(generic.View):
|
||||
"""API for retrieving a single subscription"""
|
||||
|
@ -94,6 +94,14 @@ def queue_purge(request, queue_name, resource_types):
|
||||
queue.purge(resource_types=resource_types)
|
||||
|
||||
|
||||
def message_post(request, queue_name, messages_data):
|
||||
return zaqarclient(request).queue(queue_name).post(messages_data)
|
||||
|
||||
|
||||
def message_list(request, queue_name):
|
||||
return zaqarclient(request).queue(queue_name).messages()
|
||||
|
||||
|
||||
def subscription_list(request, queue_name):
|
||||
return [{'subscriber': s.subscriber,
|
||||
'id': s.id,
|
||||
|
@ -65,6 +65,7 @@ module.exports = function (config) {
|
||||
toxPath + 'xstatic/pkg/tv4/data/tv4.js',
|
||||
toxPath + 'xstatic/pkg/objectpath/data/ObjectPath.js',
|
||||
toxPath + 'xstatic/pkg/angular_schema_form/data/schema-form.js',
|
||||
toxPath + 'xstatic/pkg/angular_fileupload/data/ng-file-upload.js',
|
||||
|
||||
// TODO: These should be mocked.
|
||||
toxPath + '/horizon/static/horizon/js/horizon.js',
|
||||
|
@ -29,6 +29,7 @@
|
||||
function ZaqarAPI(apiService, toast) {
|
||||
|
||||
var queuePath = '/api/zaqar/queues/';
|
||||
var msgPath = '/api/zaqar/queues/%s/messages/';
|
||||
var subPath = '/api/zaqar/queues/%s/subscriptions/';
|
||||
var poolPath = '/api/zaqar/pools/';
|
||||
var flavorPath = '/api/zaqar/flavors/';
|
||||
@ -40,6 +41,8 @@
|
||||
deleteQueue: deleteQueue,
|
||||
updateQueue: updateQueue,
|
||||
purgeQueue: purgeQueue,
|
||||
postMessages: postMessages,
|
||||
getMessages: getMessages,
|
||||
getSubscriptions: getSubscriptions,
|
||||
addSubscription: addSubscription,
|
||||
deleteSubscription: deleteSubscription,
|
||||
@ -92,6 +95,17 @@
|
||||
return apiService.post(url, form).error(error(msg));
|
||||
}
|
||||
|
||||
function getMessages(queueName) {
|
||||
var url = interpolate(msgPath, [queueName]);
|
||||
return apiService.get(url);
|
||||
}
|
||||
|
||||
function postMessages(queueName, msgs) {
|
||||
var msg = gettext('Unable to post messages.');
|
||||
var url = interpolate(msgPath, [queueName]);
|
||||
return apiService.post(url, msgs).error(error(msg));
|
||||
}
|
||||
|
||||
function getSubscriptions(queue) {
|
||||
var url = interpolate(subPath, [queue.name]);
|
||||
return apiService.get(url);
|
||||
|
@ -33,6 +33,8 @@
|
||||
'horizon.dashboard.project.queues.actions.deleteQueueService',
|
||||
'horizon.dashboard.project.queues.actions.updateQueueService',
|
||||
'horizon.dashboard.project.queues.actions.purgeQueueService',
|
||||
'horizon.dashboard.project.queues.actions.postMessageService',
|
||||
'horizon.dashboard.project.queues.actions.listMessageService',
|
||||
'horizon.dashboard.project.queues.actions.createSubscriptionService',
|
||||
'horizon.dashboard.project.queues.resourceType'
|
||||
];
|
||||
@ -43,12 +45,28 @@
|
||||
deleteQueueService,
|
||||
updateQueueService,
|
||||
purgeQueueService,
|
||||
postMessageService,
|
||||
listMessageService,
|
||||
createSubscriptionService,
|
||||
resourceType
|
||||
) {
|
||||
|
||||
var queueResourceType = registry.getResourceType(resourceType);
|
||||
queueResourceType.itemActions
|
||||
.append({
|
||||
id: 'messagesPost',
|
||||
service: postMessageService,
|
||||
template: {
|
||||
text: gettext('Post Messages')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'messagesList',
|
||||
service: listMessageService,
|
||||
template: {
|
||||
text: gettext('View Messages')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'queuesItemUpdate',
|
||||
service: updateQueueService,
|
||||
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright 2017 Catalyst IT Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name messageController
|
||||
* @ngController
|
||||
*
|
||||
* @description
|
||||
* Controller for the messages table
|
||||
*/
|
||||
angular
|
||||
.module('horizon.dashboard.project.queues.actions')
|
||||
.controller('horizon.dashboard.project.queues.actions.messageController',
|
||||
messageController);
|
||||
|
||||
messageController.$inject = [
|
||||
'$scope',
|
||||
'horizon.app.core.openstack-service-api.zaqar'
|
||||
];
|
||||
|
||||
function messageController($scope, zaqar) {
|
||||
|
||||
var ctrl = this;
|
||||
ctrl.queue = $scope.model.id;
|
||||
ctrl.messages = [];
|
||||
ctrl.claimMessage = claimMessage;
|
||||
ctrl.deleteMessage = deleteMessage;
|
||||
|
||||
zaqar.getMessages(ctrl.queue).success(function (response) {
|
||||
ctrl.messages = response;
|
||||
});
|
||||
|
||||
//////////
|
||||
|
||||
/* TODO: actions will be implemented later.
|
||||
function claimMessage(message) {
|
||||
console.info(message);
|
||||
}
|
||||
|
||||
function deleteMessage(message) {
|
||||
console.info(message);
|
||||
}
|
||||
*/
|
||||
}
|
||||
})();
|
@ -0,0 +1,33 @@
|
||||
<table class="table tabler-inner"
|
||||
ng-controller="horizon.dashboard.project.queues.actions.messageController as msgCtrl">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate>ID</th>
|
||||
<th translate>Body</th>
|
||||
<th translate>Time to Live</th>
|
||||
<th translate>Age</th>
|
||||
<!--
|
||||
<th></th>
|
||||
-->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="msgCtrl.messages.length === 0">
|
||||
<td colspan="100">No message to show.</td>
|
||||
</tr>
|
||||
<tr ng-repeat="msg in msgCtrl.messages">
|
||||
<td>{$ msg.id $}</td>
|
||||
<td>{$ msg.body $}</td>
|
||||
<td>{$ msg.ttl $}</td>
|
||||
<td>{$ msg.age $}</td>
|
||||
<!--
|
||||
<td>
|
||||
<button class="btn btn-xs btn-danger"
|
||||
ng-click="msgCtrl.deleteMessage(msg)">
|
||||
<span class="fa fa-trash"></span>
|
||||
</button>
|
||||
</td>
|
||||
-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.queues')
|
||||
.factory(
|
||||
'horizon.dashboard.project.queues.actions.listMessageService', listMessageService);
|
||||
|
||||
listMessageService.$inject = [
|
||||
'$q',
|
||||
'horizon.dashboard.project.queues.basePath',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.zaqar',
|
||||
'horizon.dashboard.project.queues.events',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc factory
|
||||
* @name horizon.dashboard.project.queues.actions.listMessageService
|
||||
* @param {Object} $q
|
||||
* @param {String} basePath
|
||||
* @param {Object} policy
|
||||
* @param {Object} zaqar
|
||||
* @param {Object} events
|
||||
* @param {Object} gettext
|
||||
* @param {Object} $qExtensions
|
||||
* @param {Object} modal
|
||||
* @param {Object} toast
|
||||
* @returns {Object} list messages service
|
||||
* @description Brings up the polling messages modal dialog.
|
||||
* On submit, poll messages from given queues.
|
||||
* On cancel, do nothing.
|
||||
*/
|
||||
function listMessageService(
|
||||
$q, basePath, policy, zaqar, events, gettext, $qExtensions, modal, toast
|
||||
) {
|
||||
// schema
|
||||
var schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
postMessages: {
|
||||
title: gettext("List Messages"),
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// form
|
||||
var form = [
|
||||
{
|
||||
type: 'section',
|
||||
htmlClass: 'row',
|
||||
items: [
|
||||
{
|
||||
type: 'section',
|
||||
htmlClass: 'col-sm-12',
|
||||
items: [
|
||||
{
|
||||
type: 'template',
|
||||
templateUrl: basePath + 'actions/list-message.html'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// model
|
||||
var model;
|
||||
|
||||
var message = {
|
||||
success: gettext('Messages has been posted to queue %s successfully.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initAction: initAction,
|
||||
perform: perform,
|
||||
allowed: allowed
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function initAction() {
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
return $qExtensions.booleanAsPromise(true);
|
||||
}
|
||||
|
||||
function perform(selected) {
|
||||
model = {
|
||||
id: selected.id,
|
||||
name: selected.name
|
||||
};
|
||||
// modal config
|
||||
var config = {
|
||||
"title": gettext('List Messages'),
|
||||
"submitText": gettext('List Messages'),
|
||||
"schema": schema,
|
||||
"form": form,
|
||||
"model": model
|
||||
};
|
||||
return modal.open(config).then(submit);
|
||||
}
|
||||
|
||||
function submit(context) {
|
||||
var id = context.model.id;
|
||||
var name = context.model.name;
|
||||
delete context.model.id;
|
||||
delete context.model.name;
|
||||
return zaqar.postMessages(id, context.model).then(function() {
|
||||
toast.add('success', interpolate(message.success, [name]));
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
describe('horizon.dashboard.project.queues.actions.messageController', function() {
|
||||
var zaqar, controller, $scope, $q, deferred;
|
||||
|
||||
beforeEach(module('horizon.framework'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.queues'));
|
||||
|
||||
beforeEach(inject(function ($injector, _$rootScope_) {
|
||||
$scope = _$rootScope_.$new();
|
||||
$scope.model = {
|
||||
id: ''
|
||||
};
|
||||
zaqar = $injector.get('horizon.app.core.openstack-service-api.zaqar');
|
||||
controller = $injector.get('$controller');
|
||||
controller(
|
||||
'horizon.dashboard.project.queues.actions.messageController',
|
||||
{
|
||||
$scope: $scope,
|
||||
zaqar: zaqar
|
||||
});
|
||||
deferred = $q.defer();
|
||||
deferred.resolve({data: {id: '1'}});
|
||||
spyOn(zaqar, 'getMessages').and.returnValue(deferred.promise);
|
||||
asdf();
|
||||
}));
|
||||
|
||||
it('should load messages for queue', function() {
|
||||
expect(zaqar.getMessages).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should queue_id is provided by scope variable', function() {
|
||||
$scope.model.id = '1';
|
||||
$scope.$apply();
|
||||
expect($scope.model.id).toBe('1');
|
||||
});
|
||||
});
|
||||
})();
|
@ -0,0 +1,28 @@
|
||||
<div class="hz-section col-sm-6" translate>
|
||||
<p>
|
||||
You can submit up to 10 messages in a single request, but you must always
|
||||
encapsulate the messages in a collection container (an array in JSON, even
|
||||
for a single message - without the JSON array, you receive the “Invalid
|
||||
request body” message). The resulting value of the Location header or
|
||||
response body might be used to retrieve the created messages for further
|
||||
processing.
|
||||
</p>
|
||||
<p>
|
||||
The client specifies only the body and TTL for the message. The server
|
||||
inserts metadata, such as ID and age.
|
||||
</p>
|
||||
<p>
|
||||
See a sample as below:
|
||||
</p>
|
||||
<pre>
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"event": "BackupProgress",
|
||||
"current_bytes": "2341134",
|
||||
"total_bytes": "99614720"
|
||||
}
|
||||
}
|
||||
]
|
||||
</pre>
|
||||
</div>
|
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use self file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.queues')
|
||||
.factory(
|
||||
'horizon.dashboard.project.queues.actions.postMessageService', postMessageService);
|
||||
|
||||
postMessageService.$inject = [
|
||||
'$q',
|
||||
'horizon.dashboard.project.queues.basePath',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.zaqar',
|
||||
'horizon.dashboard.project.queues.events',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc factory
|
||||
* @name horizon.dashboard.project.queues.actions.postMessageService
|
||||
* @param {Object} $q
|
||||
* @param {String} basePath
|
||||
* @param {Object} policy
|
||||
* @param {Object} zaqar
|
||||
* @param {Object} events
|
||||
* @param {Object} gettext
|
||||
* @param {Object} $qExtensions
|
||||
* @param {Object} modal
|
||||
* @param {Object} toast
|
||||
* @returns {Object} post messages service
|
||||
* @description Brings up the post messages modal dialog.
|
||||
* On submit, post messages to given queues.
|
||||
* On cancel, do nothing.
|
||||
*/
|
||||
function postMessageService(
|
||||
$q, basePath, policy, zaqar, events, gettext, $qExtensions, modal, toast
|
||||
) {
|
||||
// schema
|
||||
var schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
postMessages: {
|
||||
title: gettext("Post Messages"),
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// form
|
||||
var form = [
|
||||
{
|
||||
type: 'section',
|
||||
htmlClass: 'row',
|
||||
items: [
|
||||
{
|
||||
type: 'section',
|
||||
htmlClass: 'col-sm-6',
|
||||
items: [
|
||||
{
|
||||
key: 'messages',
|
||||
type: 'textarea'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'template',
|
||||
templateUrl: basePath + 'actions/post-message.help.html'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// model
|
||||
var model = {};
|
||||
|
||||
var message = {
|
||||
success: gettext('Messages has been posted to queue %s successfully.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initAction: initAction,
|
||||
perform: perform,
|
||||
allowed: allowed
|
||||
};
|
||||
|
||||
var scope;
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function initAction() {
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
return $qExtensions.booleanAsPromise(true);
|
||||
}
|
||||
|
||||
function perform(selected, $scope) {
|
||||
scope = $scope;
|
||||
model = {
|
||||
id: selected.id,
|
||||
name: selected.name
|
||||
};
|
||||
// modal config
|
||||
var config = {
|
||||
"title": gettext('List Messages'),
|
||||
"submitText": gettext('Post'),
|
||||
"schema": schema,
|
||||
"form": form,
|
||||
"model": model
|
||||
};
|
||||
return modal.open(config).then(submit);
|
||||
}
|
||||
|
||||
function submit(context) {
|
||||
var id = context.model.id;
|
||||
var name = context.model.name;
|
||||
delete context.model.id;
|
||||
delete context.model.name;
|
||||
return zaqar.postMessages(id, context.model).then(function() {
|
||||
toast.add('success', interpolate(message.success, [name]));
|
||||
scope.$emit(events.POST_MESSAGE_SUCCESS, name);
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
@ -50,6 +50,7 @@
|
||||
DELETE_SUCCESS: 'horizon.dashboard.project.queues.DELETE_SUCCESS',
|
||||
UPDATE_SUCCESS: 'horizon.dashboard.project.queues.UPDATE_SUCCESS',
|
||||
PURGE_SUCCESS: 'horizon.dashboard.project.queues.PURGE_SUCCESS',
|
||||
POST_MESSAGE_SUCCESS: 'horizon.dashboard.project.queues.POST_MESSAGE_SUCCESS',
|
||||
SUBSCRIPTION_CREATE_SUCCESS: 'horizon.dashboard.project.queues.SUBSCRIPTION_CREATE_SUCCESS'
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
|
||||
.subtitle {
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
textarea#messages {
|
||||
height: 28em;
|
||||
}
|
@ -55,12 +55,14 @@
|
||||
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
|
||||
var updateWatcher = $scope.$on(events.UPDATE_SUCCESS, onUpdateSuccess);
|
||||
var purgeWatcher = $scope.$on(events.PURGE_SUCCESS, onPurgeSuccess);
|
||||
var postMessageWatcher = $scope.$on(events.POST_MESSAGE_SUCCESS, onPostMessageSuccess);
|
||||
var subWatcher = $scope.$on(events.SUBSCRIPTION_CREATE_SUCCESS, broadcastEvents);
|
||||
$scope.$on('$destroy', function destroy() {
|
||||
createWatcher();
|
||||
deleteWatcher();
|
||||
updateWatcher();
|
||||
purgeWatcher();
|
||||
postMessageWatcher();
|
||||
subWatcher();
|
||||
});
|
||||
}
|
||||
@ -146,6 +148,10 @@
|
||||
refreshSubscriptions(queueName);
|
||||
}
|
||||
|
||||
function onPostMessageSuccess(e, queueName) {
|
||||
e.stopPropagation();
|
||||
refreshQueue(queueName);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -109,6 +109,7 @@
|
||||
</dl>
|
||||
</div>
|
||||
<ng-include src="table.subsTemplate"></ng-include>
|
||||
<ng-include src="table.msgsTemplate"></ng-include>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user