1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-22 13:34:04 +03:00

* Added "Service Pool Group" full logic, so new we can add services pools to groups, so we can visualzize them grouped. (already needs the visualizarion part)

* Finished basic taglist edition (fixed a bug & added the possibility of insert serveral comma separated values at once')
This commit is contained in:
Adolfo Gómez García 2016-02-12 04:47:44 +01:00
parent e1b8c43cca
commit a08fe53383
22 changed files with 349 additions and 29 deletions

View File

@ -52,7 +52,7 @@ class Authenticators(ModelHandler):
# Custom get method "search" that requires authenticator id
custom_methods = [('search', True)]
detail = {'users': Users, 'groups': Groups}
save_fields = ['name', 'comments', 'priority', 'small_name']
save_fields = ['name', 'comments', 'tags', 'priority', 'small_name']
table_title = _('Current authenticators')
table_fields = [
@ -80,7 +80,7 @@ class Authenticators(ModelHandler):
def getGui(self, type_):
try:
return self.addDefaultFields(auths.factory().lookup(type_).guiDescription(), ['name', 'comments', 'priority', 'small_name'])
return self.addDefaultFields(auths.factory().lookup(type_).guiDescription(), ['name', 'comments', 'tags', 'priority', 'small_name'])
except:
raise NotFound('type not found')

View File

@ -53,7 +53,7 @@ class Calendars(ModelHandler):
model = Calendar
detail = {'rules': CalendarRules}
save_fields = ['name', 'comments']
save_fields = ['name', 'comments', 'tags']
table_title = _('Calendars')
table_fields = [
@ -73,4 +73,4 @@ class Calendars(ModelHandler):
}
def getGui(self, type_):
return self.addDefaultFields([], ['name', 'comments'])
return self.addDefaultFields([], ['name', 'comments', 'tags'])

View File

@ -78,7 +78,7 @@ class Images(ModelHandler):
'value': '',
'label': ugettext('Image'),
'tooltip': ugettext('Image object'),
'type': gui.InputField.IMAGE_TYPE,
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 100, # At end
}
)

View File

@ -53,7 +53,7 @@ class Networks(ModelHandler):
Implements specific handling for network related requests using GUI
'''
model = Network
save_fields = ['name', 'net_string']
save_fields = ['name', 'net_string', 'tags']
table_title = _('Current Networks')
table_fields = [
@ -74,7 +74,7 @@ class Networks(ModelHandler):
def getGui(self, type_):
return self.addField(
self.addDefaultFields([], ['name']), {
self.addDefaultFields([], ['name', 'tags']), {
'name': 'net_string',
'value': '',
'label': ugettext('Network range'),

View File

@ -50,7 +50,7 @@ logger = logging.getLogger(__name__)
class OsManagers(ModelHandler):
model = OSManager
save_fields = ['name', 'comments']
save_fields = ['name', 'comments', 'tags']
table_title = _('Current OS Managers')
table_fields = [
@ -89,6 +89,6 @@ class OsManagers(ModelHandler):
# Gui related
def getGui(self, type_):
try:
return self.addDefaultFields(factory().lookup(type_).guiDescription(), ['name', 'comments'])
return self.addDefaultFields(factory().lookup(type_).guiDescription(), ['name', 'comments', 'tags'])
except:
raise NotFound('type not found')

View File

@ -56,7 +56,7 @@ class Providers(ModelHandler):
detail = {'services': DetailServices}
custom_methods = [('allservices', False), ('service', False), ('maintenance', True)]
save_fields = ['name', 'comments']
save_fields = ['name', 'comments', 'tags']
table_title = _('Service providers')

View File

@ -35,7 +35,7 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext as _
from uds.models import Service, UserService
from uds.models import Service, UserService, Tag
from uds.core.services import Service as coreService
from uds.core.util import log
@ -130,7 +130,9 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
# Extract item db fields
# We need this fields for all
logger.debug('Saving service {0} / {1}'.format(parent, item))
fields = self.readFieldsFromParams(['name', 'comments', 'data_type'])
fields = self.readFieldsFromParams(['name', 'comments', 'data_type', 'tags'])
tags = fields['tags']
del fields['tags']
service = None
try:
if item is None: # Create new
@ -139,6 +141,8 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
service = parent.services.get(uuid=processUuid(item))
service.__dict__.update(fields)
service.tags = [Tag.objects.get_or_create(tag=val)[0] for val in tags]
service.data = service.getInstance(self._params).serialize()
service.save()
except Service.DoesNotExist:
@ -209,7 +213,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
parentInstance = parent.getInstance()
serviceType = parentInstance.getServiceByType(forType)
service = serviceType(Environment.getTempEnv(), parentInstance) # Instantiate it so it has the opportunity to alter gui description based on parent
return self.addDefaultFields(service.guiDescription(service), ['name', 'comments'])
return self.addDefaultFields(service.guiDescription(service), ['name', 'comments', 'tags'])
except Exception as e:
logger.exception('getGui')
raise ResponseError(unicode(e))

View File

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
@itemor: Adolfo Gómez, dkmaster at dkmon dot com
'''
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _, ugettext
from uds.models import ServicesPoolGroup, Image
from uds.core.util.model import processUuid
from uds.core.ui.UserInterface import gui
from uds.core.ui.images import DEFAULT_THUMB_BASE64
from uds.REST.model import ModelHandler
import logging
logger = logging.getLogger(__name__)
# Enclosed methods under /item path
class ServicesPoolGroups(ModelHandler):
'''
Handles the gallery REST interface
'''
needs_admin = True
path = 'gallery'
model = ServicesPoolGroup
save_fields = ['name', 'comments', 'image_id']
table_title = _('Services Pool Groups')
table_fields = [
{'name': {'title': _('Name')}},
{'thumb': {'title': _('Image'), 'visible': True, 'type': 'image'}},
]
def beforeSave(self, fields):
imgId = fields['image_id']
fields['image_id'] = None
logger.debug('Image id: {}'.format(imgId))
try:
if imgId != '-1':
image = Image.objects.get(uuid=processUuid(imgId))
fields['image_id'] = image.id
except Exception:
logger.exception('At image recovering')
# Gui related
def getGui(self, type_):
g = self.addDefaultFields([], ['name', 'comments'])
for f in [{
'name': 'image_id',
'values': [gui.choiceImage(-1, '--------', DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.thumb64) for v in Image.objects.all()]),
'label': ugettext('Associated Image'),
'tooltip': ugettext('Image assocciated with this service'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 102,
}]:
self.addField(g, f)
return g
def item_as_dict(self, item):
return {
'id': item.uuid,
'name': item.name,
'image_id': item.image.uuid,
}
def item_as_dict_overview(self, item):
return {
'id': item.uuid,
'name': item.name,
'thumb': item.image.thumb64,
}

View File

@ -33,7 +33,7 @@
from __future__ import unicode_literals
from django.utils.translation import ugettext, ugettext_lazy as _
from uds.models import DeployedService, OSManager, Service, Image
from uds.models import DeployedService, OSManager, Service, Image, ServicesPoolGroup
from uds.core.ui.images import DEFAULT_THUMB_BASE64
from uds.core.util.State import State
from uds.core.util.model import processUuid
@ -64,7 +64,7 @@ class ServicesPools(ModelHandler):
'changelog': Changelog
}
save_fields = ['name', 'comments', 'service_id', 'osmanager_id', 'image_id', 'initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs', 'show_transports']
save_fields = ['name', 'comments', 'tags', 'service_id', 'osmanager_id', 'image_id', 'servicesPoolGroup_id', 'initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs', 'show_transports']
remove_fields = ['osmanager_id', 'service_id']
table_title = _('Service Pools')
@ -73,7 +73,7 @@ class ServicesPools(ModelHandler):
{'parent': {'title': _('Parent Service')}},
{'state': {'title': _('status'), 'type': 'dict', 'dict': State.dictionary()}},
{'show_transports': {'title': _('Shows transports'), 'type': 'callback'}},
{'comments': {'title': _('Comments')}},
{'servicesPoolGroup': {'title': _('Services Pool Group')}},
]
# Field from where to get "class" and prefix for that class, so this will generate "row-state-A, row-state-X, ....
table_row_style = {'field': 'state', 'prefix': 'row-state-'}
@ -93,6 +93,8 @@ class ServicesPools(ModelHandler):
'service_id': item.service.uuid,
'provider_id': item.service.provider.uuid,
'image_id': item.image.uuid if item.image is not None else None,
'servicesPoolGroup_id': item.servicesPoolGroup.uuid if item.servicesPoolGroup is not None else None,
'servicesPoolGroup': item.servicesPoolGroup.name if item.servicesPoolGroup is not None else _('Default'),
'initial_srvs': item.initial_srvs,
'cache_l1_srvs': item.cache_l1_srvs,
'cache_l2_srvs': item.cache_l2_srvs,
@ -116,7 +118,7 @@ class ServicesPools(ModelHandler):
if Service.objects.count() < 1:
raise ResponseError(ugettext('Create at least a service before creating a new service pool'))
g = self.addDefaultFields([], ['name', 'comments'])
g = self.addDefaultFields([], ['name', 'comments', 'tags'])
for f in [{
'name': 'service_id',
@ -141,6 +143,13 @@ class ServicesPools(ModelHandler):
'tooltip': ugettext('Image assocciated with this service'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 102,
}, {
'name': 'servicesPoolGroup_id',
'values': [gui.choiceImage(-1, _('Default'), DEFAULT_THUMB_BASE64)] + gui.sortedChoices([gui.choiceImage(v.uuid, v.name, v.image.thumb64) for v in ServicesPoolGroup.objects.all()]),
'label': ugettext('Pool group'),
'tooltip': ugettext('Pool group for this pool (for pool clasify on display)'),
'type': gui.InputField.IMAGECHOICE_TYPE,
'order': 103,
}, {
'name': 'initial_srvs',
'value': '0',
@ -148,7 +157,7 @@ class ServicesPools(ModelHandler):
'label': ugettext('Initial available services'),
'tooltip': ugettext('Services created initially for this service pool'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 103,
'order': 110,
}, {
'name': 'cache_l1_srvs',
'value': '0',
@ -156,7 +165,7 @@ class ServicesPools(ModelHandler):
'label': ugettext('Services to keep in cache'),
'tooltip': ugettext('Services kept in cache for improved user service assignation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 104,
'order': 111,
}, {
'name': 'cache_l2_srvs',
'value': '0',
@ -164,7 +173,7 @@ class ServicesPools(ModelHandler):
'label': ugettext('Services to keep in L2 cache'),
'tooltip': ugettext('Services kept in cache of level2 for improved service generation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 105,
'order': 112,
}, {
'name': 'max_srvs',
'value': '0',
@ -172,14 +181,14 @@ class ServicesPools(ModelHandler):
'label': ugettext('Maximum number of services to provide'),
'tooltip': ugettext('Maximum number of service (assigned and L1 cache) that can be created for this service'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 106,
'order': 113,
}, {
'name': 'show_transports',
'value': True,
'label': ugettext('Show transports'),
'tooltip': ugettext('If active, alternative transports for user will be shown'),
'type': gui.InputField.CHECKBOX_TYPE,
'order': 107,
'order': 120,
}]:
self.addField(g, f)
@ -226,6 +235,17 @@ class ServicesPools(ModelHandler):
except Exception:
logger.exception('At image recovering')
# Servicepool Group
spgrpId = fields['servicesPoolGroup_id']
fields['servicesPoolGroup_id'] = None
logger.debug('servicesPoolGroup_id: {}'.format(spgrpId))
try:
if imgId != '-1':
spgrp = ServicesPoolGroup.objects.get(uuid=processUuid(spgrpId))
fields['servicesPoolGroup_id'] = spgrp.id
except Exception:
logger.exception('At service pool group recovering')
except (RequestError, ResponseError):
raise
except Exception as e:

View File

@ -48,7 +48,7 @@ logger = logging.getLogger(__name__)
class Transports(ModelHandler):
model = Transport
save_fields = ['name', 'comments', 'priority', 'nets_positive']
save_fields = ['name', 'comments', 'tags', ' priority', 'nets_positive']
table_title = _('Current Transports')
table_fields = [
@ -64,7 +64,7 @@ class Transports(ModelHandler):
def getGui(self, type_):
try:
return self.addField(
self.addField(self.addDefaultFields(factory().lookup(type_).guiDescription(), ['name', 'comments', 'priority']), {
self.addField(self.addDefaultFields(factory().lookup(type_).guiDescription(), ['name', 'comments', 'tags', 'priority']), {
'name': 'nets_positive',
'value': True,
'label': ugettext('Network access'),

View File

@ -42,6 +42,8 @@ from uds.REST.handlers import Handler, HandlerError
from uds.core.util import log
from uds.core.util import permissions
from uds.core.util.model import processUuid
from uds.models import Tag
import fnmatch
import re
@ -52,7 +54,7 @@ import logging
logger = logging.getLogger(__name__)
__updated__ = '2016-02-10'
__updated__ = '2016-02-12'
# a few constants
@ -841,6 +843,13 @@ class ModelHandler(BaseModelHandler):
args = self.readFieldsFromParams(self.save_fields)
logger.debug('Args: {}'.format(args))
self.beforeSave(args)
# If tags is in save fields, treat it "specially"
if 'tags' in self.save_fields:
tags = args['tags']
del args['tags']
else:
tags = None
deleteOnError = False
if len(self._args) == 0: # create new
item = self.model.objects.create(**args)
@ -852,6 +861,12 @@ class ModelHandler(BaseModelHandler):
if v in args:
del args[v]
item.__dict__.update(args) # Update fields from args
# Now if tags, update them
if tags is not None:
logger.debug('Updating tags: {}'.format(tags))
item.tags = [ Tag.objects.get_or_create(tag=val)[0] for val in tags]
except self.model.DoesNotExist:
raise NotFound('Item not found')
except IntegrityError: # Duplicate key probably

View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uds', '0019_auto_20160210_0144'),
]
operations = [
migrations.CreateModel(
name='ServicesPoolGroup',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('uuid', models.CharField(default=None, max_length=50, unique=True, null=True)),
('name', models.CharField(default='', max_length=128)),
('comments', models.CharField(default='', max_length=256)),
('image', models.ForeignKey(related_name='servicesPoolsGrou', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='uds.Image', null=True)),
],
options={
'abstract': False,
'db_table': 'uds__pools_groups',
},
),
migrations.AddField(
model_name='deployedservice',
name='servicesPoolGroup',
field=models.ForeignKey(related_name='servicesPools', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='uds.ServicesPoolGroup', null=True),
),
]

View File

@ -49,6 +49,7 @@ from uds.models.Service import Service
from uds.models.Transport import Transport
from uds.models.Group import Group
from uds.models.Image import Image
from uds.models.ServicesPoolGroup import ServicesPoolGroup
from uds.models.Util import NEVER
from uds.models.Util import getSqlDatetime
@ -56,7 +57,7 @@ from uds.models.Util import getSqlDatetime
from datetime import timedelta
import logging
__updated__ = '2016-02-10'
__updated__ = '2016-02-12'
logger = logging.getLogger(__name__)
@ -78,12 +79,16 @@ class DeployedService(UUIDModel, TaggingMixin):
state_date = models.DateTimeField(default=NEVER)
show_transports = models.BooleanField(default=True)
image = models.ForeignKey(Image, null=True, blank=True, related_name='deployedServices', on_delete=models.SET_NULL)
servicesPoolGroup = models.ForeignKey(ServicesPoolGroup, null=True, blank=True, related_name='servicesPools', on_delete=models.SET_NULL)
initial_srvs = models.PositiveIntegerField(default=0)
cache_l1_srvs = models.PositiveIntegerField(default=0)
cache_l2_srvs = models.PositiveIntegerField(default=0)
max_srvs = models.PositiveIntegerField(default=0)
current_pub_revision = models.PositiveIntegerField(default=1)
# Meta service related
meta_pools = models.ManyToManyField('self', symmetrical=False)

View File

@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
'''
from __future__ import unicode_literals
from django.db import models
from django.db.models import signals
from django.utils.encoding import python_2_unicode_compatible
from uds.models.UUIDModel import UUIDModel
from uds.models.Image import Image
import logging
__updated__ = '2016-02-12'
logger = logging.getLogger(__name__)
@python_2_unicode_compatible
class ServicesPoolGroup(UUIDModel):
'''
A deployed service is the Service produced element that is assigned finally to an user (i.e. a Virtual Machine, etc..)
'''
# pylint: disable=model-missing-unicode
name = models.CharField(max_length=128, default='')
comments = models.CharField(max_length=256, default='')
image = models.ForeignKey(Image, null=True, blank=True, related_name='servicesPoolsGrou', on_delete=models.SET_NULL)
class Meta(UUIDModel.Meta):
'''
Meta class to declare the name of the table at database
'''
db_table = 'uds__pools_groups'
app_label = 'uds'
def __str__(self):
return u"Service Pool group {0}({1})".format(self.name, self.comments)

View File

@ -65,6 +65,7 @@ from .Group import Group
# Provisioned services
from .ServicesPool import DeployedService # Old name, will continue here for a while already
from .ServicesPool import ServicePool # New name
from .ServicesPoolGroup import ServicesPoolGroup
from .ServicesPoolPublication import DeployedServicePublication
from .UserService import UserService
from .UserServiceProperty import UserServiceProperty
@ -101,7 +102,7 @@ from .CalendarRule import CalendarRule
# Tagging
from .Tag import Tag
__updated__ = '2016-02-10'
__updated__ = '2016-02-12'
logger = logging.getLogger(__name__)

View File

@ -425,6 +425,7 @@ api.networks = new BasicModelRest("networks")
api.servicesPools = new BasicModelRest("servicespools")
api.configuration = new BasicModelRest("config")
api.gallery = new BasicModelRest("gallery/images")
api.sPoolGroups = new BasicModelRest("gallery/servicespoolgroups")
api.system = new BasicModelRest("system")
api.reports = new BasicModelRest("reports") # Not fully used, but basic usage is common
api.calendars = new BasicModelRest("calendars")

View File

@ -0,0 +1,28 @@
gui.sPoolGroups = new GuiElement(api.sPoolGroups, "spal")
gui.sPoolGroups.link = ->
gui.doLog 'Executing pool groups'
"use strict"
if api.config.admin is false
return
api.templates.get "services_pool_groups", (tmpl) ->
gui.clearWorkspace()
gui.appendToWorkspace api.templates.evaluate(tmpl,
sPoolGroups: "sPoolGroups-placeholder"
)
gui.sPoolGroups.table
icon: 'sPoolGroups'
container: "sPoolGroups-placeholder"
rowSelect: "single"
buttons: [
"new"
"edit"
"delete"
]
onNew: gui.methods.typedNew(gui.sPoolGroups, gettext("New services Services Pool Group"), gettext("Services Services Pool Group creation error"))
onEdit: gui.methods.typedEdit(gui.sPoolGroups, gettext("Edit services Services Pool Group"), gettext("Services Provider saving error"))
onDelete: gui.methods.del(gui.sPoolGroups, gettext("Delete Services Pool Group"), gettext("Services Pool Group error"))
return
return

View File

@ -240,6 +240,11 @@
exec: gui.calendars.link
cleanup: true
}
{
id: "lnk-spoolsgroup"
exec: gui.sPoolGroups.link
cleanup: true
}
]
$.each sidebarLinks, (index, value) ->
gui.doLog "Adding " + value.id

View File

@ -121,6 +121,7 @@
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-servicespools.coffee"></script>
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-config.coffee"></script>
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-gallery.coffee"></script>
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-servicespoolsgroup.coffee"></script>
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-reports.coffee"></script>
<script type="text/coffeescript" charset="utf-8" src="{% get_static_prefix %}adm/js/gui-d-calendar.coffee"></script>
<!-- base64 encoding -->

View File

@ -30,6 +30,7 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><img class="icon" src="{{ STATIC_URL }}/adm/img/icons/tools.png"/> <span class="menu-lnk">{% trans 'Tools' %} <b class="caret"></b></span></a>
<ul class="dropdown-menu">
<li><a class="lnk-gallery" href="#"><img class="icon" src="{{ STATIC_URL }}/adm/img/icons/gallery.png"/> <span class="menu-lnk">{% trans 'Gallery' %}</span></a></li>
<li><a class="lnk-spoolsgroup" href="#"><img class="icon" src="{{ STATIC_URL }}/adm/img/icons/groups.png"/> <span class="menu-lnk">{% trans 'Services Pool Group' %}</span></a></li>
<li><a class="lnk-reports" href=""><img class="icon" src="{{ STATIC_URL }}/adm/img/icons/reports.png"/> <span class="menu-lnk">{% trans 'Reports' %}</a></span></li>
<li><a class="lnk-configuration" href="#"><img class="icon" src="{{ STATIC_URL }}/adm/img/icons/configuration.png"/> <span class="menu-lnk">{% trans 'Configuration' %}</span></a></li>
<li><a class="lnk-clear_cache" href="#"><img class="icon" src="{{ STATIC_URL }}/adm/img/icons/flush-cache.png"/> <span class="menu-lnk">{% trans 'Flush cache' %}</span></a></li>

View File

@ -8,7 +8,7 @@
<span class="label label-success tag tagadder" id="adder{{ id }}">{% endverbatim %}{% trans 'Add Tag...' %}{% verbatim %}</span>
{{/ unless }}
<input id="h{{ id }}" type="hidden" data-uds="list" name="{{ name }}" value="{{ value }}" class="{{ css }}" />
<input id="h{{ id }}" type="hidden" data-uds="commaList" name="{{ name }}" value="{{ value }}" class="{{ css }}" />
{% endverbatim %}
{% comment %}<script>/*This is a little trick to make IDE recognize sintax hightlight, will not be show on render :-)*/{% endcomment %}
@ -44,7 +44,9 @@
// Tagadder never gets destroyed, so we only set the event once
$('#adder{{ id }}').on('click', function(){
var text = prompt('Enter new tag');
addTag(text);
$.each( text.split(','), function (idx, value) {
addTag(value);
});
});
{{/ unless }}

View File

@ -0,0 +1,28 @@
{% load i18n html5 static %}
<div class="row">
<div class="col-xs-12">
<h1>{% trans 'UDS Services Pool Groups' %}</h1>
<!-- <ol class="breadcrumb">
<li><a class="lnk-dashboard" href="#">Dashboard</a></li>
<li>{% trans 'Gallery' %}</li>
</ol> -->
</div>
</div><!-- /.row -->
{% if messages %}
<div class="row">
<div class="col-md-offset-2 col-md-8">
{% for message in messages %}
<div class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
{{ message }}
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% verbatim %}
<div class="row">
<div id="{{ sPoolGroups }}" class="col-xs-12"></div>
</div>
{% endverbatim %}