1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-02-02 09:47:13 +03:00

Finished (i hope... :-) ) Image Gallery & Service Pools usage

This commit is contained in:
Adolfo Gómez García 2014-11-06 22:08:22 +01:00
parent 42845e6243
commit 97787b7eba
9 changed files with 159 additions and 64 deletions

View File

@ -91,7 +91,7 @@ class Images(ModelHandler):
def item_as_dict_overview(self, item):
return {
'id': item.uuid,
'size': '{}x{}, {} bytes'.format(item.width, item.height, len(item.data)),
'size': '{}x{}, {} bytes (thumb {} bytes)'.format(item.width, item.height, len(item.data), len(item.thumb)),
'name': item.name,
'thumb': item.thumb64,
}

View File

@ -33,7 +33,8 @@
from __future__ import unicode_literals
from django.utils.translation import ugettext, ugettext_lazy as _
from uds.models import DeployedService, OSManager, Service
from uds.models import DeployedService, OSManager, Service, Image
from uds.core.ui.images import DEFAULT_THUMB_BASE64
from uds.core.util.State import State
from uds.core.util import log
from uds.REST.model import ModelHandler
@ -56,7 +57,8 @@ class ServicesPools(ModelHandler):
'publications': Publications,
}
save_fields = ['name', 'comments', 'service_id', 'osmanager_id', 'initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs']
save_fields = ['name', 'comments', 'service_id', 'osmanager_id', 'image_id', 'initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs']
remove_fields = ['osmanager_id', 'service_id']
table_title = _('Service Pools')
table_fields = [
@ -69,6 +71,8 @@ class ServicesPools(ModelHandler):
table_row_style = {'field': 'state', 'prefix': 'row-state-'}
def item_as_dict(self, item):
# if item does not have an associated service, hide it (the case, for example, for a removed service)
# Access from dict will raise an exception, and item will be skipped
val = {
'id': item.uuid,
'name': item.name,
@ -76,6 +80,7 @@ class ServicesPools(ModelHandler):
'state': item.state,
'service_id': item.service.uuid,
'provider_id': item.service.provider.uuid,
'image_id': item.image.uuid if item.image is not None else None,
'initial_srvs': item.initial_srvs,
'cache_l1_srvs': item.cache_l1_srvs,
'cache_l2_srvs': item.cache_l2_srvs,
@ -89,6 +94,18 @@ class ServicesPools(ModelHandler):
return val
def item_as_dict_overview(self, item):
# if item does not have an associated service, hide it (the case, for example, for a removed service)
# Access from dict will raise an exception, and item will be skipped
return {
'id': item.uuid,
'name': item.name,
'comments': item.comments,
'state': item.state,
'thumb': item.image.thumb64 if item.image is not None else DEFAULT_THUMB_BASE64,
'service_id': item.service.uuid
}
# Gui related
def getGui(self, type_):
if OSManager.objects.count() < 1: # No os managers, can't create db
@ -114,34 +131,41 @@ class ServicesPools(ModelHandler):
'type': gui.InputField.CHOICE_TYPE,
'rdonly': True,
'order': 101, # At end
}, {
'name': 'image_id',
'values': [gui.choiceItem(-1, '')] + [gui.choiceItem(v.uuid, v.name) for v in Image.objects.all()],
'label': ugettext('Associated Image'),
'tooltip': ugettext('Image assocciated with this service'),
'type': gui.InputField.CHOICE_TYPE,
'order': 102, # At end
}, {
'name': 'initial_srvs',
'value': '0',
'label': ugettext('Initial available services'),
'tooltip': ugettext('Services created initially for this service pool'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 102, # At end
'order': 103, # At end
}, {
'name': 'cache_l1_srvs',
'value': '0',
'label': ugettext('Services to keep in cache'),
'tooltip': ugettext('Services keeped in cache for improved user service assignation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 103, # At end
'order': 104, # At end
}, {
'name': 'cache_l2_srvs',
'value': '0',
'label': ugettext('Services to keep in L2 cache'),
'tooltip': ugettext('Services keeped in cache of level2 for improved service generation'),
'type': gui.InputField.NUMERIC_TYPE,
'order': 104, # At end
'order': 105, # At end
}, {
'name': 'max_srvs',
'value': '0',
'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': 105, # At end
'order': 106, # At end
}]:
self.addField(g, f)
@ -153,8 +177,7 @@ class ServicesPools(ModelHandler):
try:
try:
service = Service.objects.get(uuid=fields['service_id'])
del fields['service_id']
fields['service'] = service
fields['service_id'] = service.id
except:
raise RequestError(ugettext('Base service does not exists anymore'))
@ -162,8 +185,9 @@ class ServicesPools(ModelHandler):
serviceType = service.getType()
if serviceType.needsManager is True:
osmanager = OSManager.objects.get(uuid=fields['osmanager_id'])
fields['osmanager'] = osmanager
del fields['osmanager_id']
fields['osmanager_id'] = osmanager.id
else:
del fields['osmanager_id']
if serviceType.usesCache is False:
for k in ('initial_srvs', 'cache_l1_srvs', 'cache_l2_srvs', 'max_srvs'):
@ -172,6 +196,16 @@ class ServicesPools(ModelHandler):
except Exception:
raise RequestError(ugettext('This service requires an os manager'))
imgId = fields['image_id']
fields['image_id'] = None
logger.debug('Image id: {}'.format(imgId))
try:
if imgId != '-1':
image = Image.objects.get(uuid=imgId)
fields['image_id'] = image.id
except Exception:
logger.exception('At image recovering')
except (RequestError, ResponseError):
raise
except Exception as e:

View File

@ -47,7 +47,7 @@ import logging
logger = logging.getLogger(__name__)
__updated__ = '2014-11-05'
__updated__ = '2014-11-06'
# a few constants
@ -432,6 +432,8 @@ class ModelHandler(BaseModelHandler):
detail = None # Dictionary containing detail routing
# Put needed fields
save_fields = []
# Put removable fields before updating
remove_fields = []
# Table info needed fields and title
table_fields = []
table_row_style = {}
@ -579,8 +581,9 @@ class ModelHandler(BaseModelHandler):
for item in self.model.objects.filter(*args, **kwargs):
try:
yield self.item_as_dict_overview(item)
except Exception:
logger.exception('Exception getting item from {0}'.format(self.model))
except Exception: # maybe an exception is thrown to skip an item
# logger.exception('Exception getting item from {0}'.format(self.model))
pass
def get(self):
'''
@ -597,9 +600,12 @@ class ModelHandler(BaseModelHandler):
if nArgs == 0:
result = []
for val in self.model.objects.all():
res = self.item_as_dict(val)
self.fillIntanceFields(val, res)
result.append(res)
try:
res = self.item_as_dict(val)
self.fillIntanceFields(val, res)
result.append(res)
except Exception: # maybe an exception is thrown to skip an item
pass
return result
# if has custom methods, look for if this request matches any of them
@ -703,6 +709,9 @@ class ModelHandler(BaseModelHandler):
else: # Must have 1 arg
# We have to take care with this case, update will efectively update records on db
item = self.model.objects.get(uuid=self._args[0].upper())
for v in self.remove_fields:
if v in args:
del args[v]
item.__dict__.update(args) # Update fields from args
except self.model.DoesNotExist:
raise NotFound('Item not found')

File diff suppressed because one or more lines are too long

View File

@ -55,7 +55,7 @@ class Image(UUIDModel):
'''
MAX_IMAGE_SIZE = (128, 128)
THUMBNAIL_SIZE = (32, 32)
THUMBNAIL_SIZE = (48, 48)
name = models.CharField(max_length=128, unique=True, db_index=True)
stamp = models.DateTimeField() # Date creation or validation of this entry. Set at write time
@ -73,7 +73,7 @@ class Image(UUIDModel):
@staticmethod
def encode64(data):
return base64.encodestring(data)[:-1] # Removes trailing \n
return base64.encodestring(data).replace('\n', '') # Removes \n
@staticmethod
def decode64(data64):
@ -166,11 +166,11 @@ class Image(UUIDModel):
return HttpResponse(self.data, content_type='image/png')
def thumbnailResponse(self):
return HttpResponse(self.data, content_type='image/png')
return HttpResponse(self.thumb, content_type='image/png')
def save(self, *args, **kwargs):
self.stamp = getSqlDatetime()
return UUIDModel.save(self, *args, **kwargs)
def __unicode__(self):
return 'Image "{}", {} bytes'.format(self.name, len(self.data))
return 'Image id {}, name {}, {} bytes, {} bytes thumb'.format(self.id, self.name, len(self.data), len(self.thumb))

View File

@ -2,38 +2,55 @@ gui.gallery = new GuiElement(api.gallery, "imgal")
gui.gallery.link = ->
"use strict"
newImage = (meth, table, refreshFnc) ->
api.templates.get "new_image", (tmpl) ->
content = api.templates.evaluate(tmpl,
)
modalId = gui.launchModal(gettext("New image"), content,
actionButton: "<button type=\"button\" class=\"btn btn-success button-accept\">" + gettext("Upload") + "</button>"
)
gui.tools.applyCustoms modalId
$(modalId + " .button-accept").click ->
file = $('#id-image_for_gallery')[0].files[0]
name = $('#id_image_name').val()
if name == ""
name = file.name
newEditImageFnc = (forEdit) ->
realFnc = (value, refreshFnc) ->
api.templates.get "new_image", (tmpl) ->
content = api.templates.evaluate(tmpl,
)
modalId = gui.launchModal(gettext("New image"), content,
actionButton: "<button type=\"button\" class=\"btn btn-success button-accept\">" + gettext("Upload") + "</button>"
)
gui.doLog value.name
gui.tools.applyCustoms modalId
value is null or $("#id_image_name").val(value.name)
$(modalId + " .button-accept").click ->
file = $('#id-image_for_gallery')[0].files[0]
if file.size > 256*1024
gui.notify gettext("Image is too big (max. upload size is 256Kb)")
return
if file is null
gui.notify gettext("You must select an image")
return
name = $('#id_image_name').val()
if name == ""
name = file.name
$(modalId).modal "hide"
reader = new FileReader()
if file.size > 256*1024
gui.notify gettext("Image is too big (max. upload size is 256Kb)")
return
reader.onload = (res) ->
img = res.target.result
img = img.substr img.indexOf("base64,") + 7
data = {
data: img
name: name
}
api.gallery.create data, refreshFnc
$(modalId).modal "hide"
reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (res) ->
img = res.target.result
img = img.substr img.indexOf("base64,") + 7
data = {
data: img
name: name
}
if value is null
api.gallery.create data, refreshFnc
else
data.id = value.id
api.gallery.save data, refreshFnc
reader.readAsDataURL(file)
if forEdit is true
(value, event, table, refreshFnc) ->
realFnc value, refreshFnc
else
(meth, table, refreshFnc) ->
realFnc null, refreshFnc
api.templates.get "gallery", (tmpl) ->
gui.clearWorkspace()
@ -45,9 +62,11 @@ gui.gallery.link = ->
rowSelect: "single"
buttons: [
"new"
"edit"
"delete"
]
onNew: newImage
onNew: newEditImageFnc false
onEdit: newEditImageFnc true
onDelete: gui.methods.del(gui.gallery, gettext("Delete Image"), gettext("Image deletion error"))
return

View File

@ -59,10 +59,7 @@ gui.servicesPools.link = (event) ->
$cacheL2Fld.prop "disabled", "disabled"
else
$cacheL2Fld.prop "disabled", false
if data.info.needs_publication is false
$publishOnSaveFld.bootstrapSwitch "setDisabled", true
else
$publishOnSaveFld.bootstrapSwitch "setDisabled", false
$publishOnSaveFld.bootstrapSwitch "toggleReadonly", data.info.needs_publication
$osmFld.selectpicker "refresh" if $osmFld.hasClass("selectpicker")
return
@ -448,12 +445,14 @@ gui.servicesPools.link = (event) ->
onData: (data) ->
gui.doLog "onData", data
$.each data, (index, value) ->
gui.doLog value.thumb
try
service = availableServices[value.service_id]
if not service?
value.parent = gettext("undefined")
return
style = "display:inline-block; background: url(data:image/png;base64," + service.info.icon + "); background-size: 16px 16px; background-repeat: no-repeat; width: 16px; height: 16px; vertical-align: middle;"
style = "display:inline-block; background: url(data:image/png;base64," + value.thumb + "); background-size: 16px 16px; background-repeat: no-repeat; width: 16px; height: 16px; vertical-align: middle;"
gui.doLog style
if value.restrained
value.name = "<span class=\"fa fa-exclamation text-danger\"></span> " + value.name
value.state = gettext("Restrained")

View File

@ -7,7 +7,7 @@
<input id="id_image_name" name="image_name" type="text" class="form-control" placeholder="{% trans 'Image name' %}" autofocus required>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'Name of the image. If left empty, will get the filename as name'%}">{% trans 'Image name' %}</label>
<label class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'Name of the image. If left empty, will get the filename as name'%}">{% trans 'Image' %}</label>
<div class="fileinput fileinput-new" data-provides="fileinput">
<div class="fileinput-preview thumbnail" data-trigger="fileinput" style="width: {{ size.0 }}px; height: {{ size.1 }}px;"></div>
<div>

View File

@ -39,13 +39,14 @@ from django.template import RequestContext
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django.views.decorators.http import last_modified
from django.views.decorators.cache import cache_page
from django.views.decorators.cache import cache_page, cache_control
from django.views.i18n import javascript_catalog
from django.utils import timezone
from django.contrib.staticfiles import finders
from uds.core.auths.auth import webLogin, webLogout, webLoginRequired, authenticate, webPassword, authenticateViaCallback, authLogLogin, authLogLogout, getUDSCookie
from uds.models import Authenticator, DeployedService, Transport, UserService, Network, Image
from uds.core.ui.images import DEFAULT_IMAGE
from uds.web.forms.LoginForm import LoginForm
from uds.core.managers.UserServiceManager import UserServiceManager
from uds.core.managers.UserPrefsManager import UserPrefsManager
@ -331,7 +332,6 @@ def sernotify(request, idUserService, notification):
return HttpResponse('ok', content_type='text/plain')
@cache_page(60 * 10) # Cache images 10 minutes
def transportIcon(request, idTrans):
try:
icon = Transport.objects.get(uuid=idTrans).getInstance().icon(False)
@ -340,7 +340,6 @@ def transportIcon(request, idTrans):
return HttpResponseRedirect('/static/img/unknown.png')
@cache_page(60 * 10) # Cache images 10 minutes
def serviceImage(request, idImage):
try:
icon = Image.objects.get(uuid=idImage)
@ -352,12 +351,7 @@ def serviceImage(request, idImage):
icon = Transport.objects.get(uuid=idImage).getInstance().icon(False)
return HttpResponse(icon, content_type='image/png')
except Exception:
result = finders.find('img/uds-service.png')
if isinstance(result, (list, tuple)):
result = result[0]
with open(result) as f:
icon = f.read()
return HttpResponse(icon, content_type='image/png')
return HttpResponse(DEFAULT_IMAGE, content_type='image/png')
@transformId