pax_global_header 0000666 0000000 0000000 00000000064 12237172035 0014514 g ustar 00root root 0000000 0000000 52 comment=7978a8713dbb7d86888d57253bf2b24f729f3d86 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/ 0000775 0000000 0000000 00000000000 12237172035 0024746 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/.gitignore 0000664 0000000 0000000 00000000257 12237172035 0026742 0 ustar 00root root 0000000 0000000 # Python bytecode: *.py[co] # Packaging files: *.egg* # Editor temp files: *.swp *~ # Sphinx docs: build _build # SQLite3 database files: *.db # Logs: *.log .ropeproject CONTRIBUTORS.txt 0000664 0000000 0000000 00000000141 12237172035 0027361 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86 Adam Dudas Bence Danyi Daniel Bach Gergo Nagy Imre Szeberenyi Mate Ory Sandor Guba Viktor Kalman cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/LICENSE.txt 0000664 0000000 0000000 00000000206 12237172035 0026567 0 ustar 00root root 0000000 0000000 Copyright (c) 2012--2013 Budapest University of Technology and Economics (BME-IK), and contributors. [SOME OPEN SOURCE LICENSE HERE] cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/README.rst 0000664 0000000 0000000 00000000163 12237172035 0026435 0 ustar 00root root 0000000 0000000 ============= cirecle-cloud ============= This is the Django based controller and web portal of the CIRCLE Cloud. cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/ 0000775 0000000 0000000 00000000000 12237172035 0026207 5 ustar 00root root 0000000 0000000 __init__.py 0000664 0000000 0000000 00000000000 12237172035 0030227 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl/ 0000775 0000000 0000000 00000000000 12237172035 0026746 5 ustar 00root root 0000000 0000000 __init__.py 0000664 0000000 0000000 00000000000 12237172035 0030766 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl management/ 0000775 0000000 0000000 00000000000 12237172035 0031003 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl __init__.py 0000664 0000000 0000000 00000005267 12237172035 0033126 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl/management """ Creates Levels for all installed apps that have levels. """ from django.db.models import get_models, signals from django.db import DEFAULT_DB_ALIAS from django.core.exceptions import ImproperlyConfigured from ..models import Level, AclBase def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kwargs): """Create and set the weights of the configured Levels. Based on django.contrib.auth.management.__init__.create_permissions""" # if not router.allow_migrate(db, auth_app.Permission): # return from django.contrib.contenttypes.models import ContentType app_models = [k for k in get_models(app) if AclBase in k.__bases__] print "Creating levels for models: %s." % ", ".join([m.__name__ for m in app_models]) # This will hold the levels we're looking for as # (content_type, (codename, name)) searched_levels = list() level_weights = list() # The codenames and ctypes that should exist. ctypes = set() for klass in app_models: # Force looking up the content types in the current database # before creating foreign keys to them. ctype = ContentType.objects.db_manager(db).get_for_model(klass) ctypes.add(ctype) weight = 0 try: for codename, name in klass.ACL_LEVELS: searched_levels.append((ctype, (codename, name))) level_weights.append((ctype, codename, weight)) weight += 1 except AttributeError: raise ImproperlyConfigured( "Class %s doesn't have ACL_LEVELS attribute." % klass) # Find all the Levels that have a content_type for a model we're # looking for. We don't need to check for codenames since we already have # a list of the ones we're going to create. all_levels = set(Level.objects.using(db).filter( content_type__in=ctypes, ).values_list( "content_type", "codename" )) levels = [ Level(codename=codename, name=name, content_type=ctype) for ctype, (codename, name) in searched_levels if (ctype.pk, codename) not in all_levels ] Level.objects.using(db).bulk_create(levels) if verbosity >= 2: print("Adding levels [%s]." % ", ".join(levels)) print("Searched: [%s]." % ", ".join([unicode(l) for l in searched_levels])) print("All: [%s]." % ", ".join([unicode(l) for l in all_levels])) # set weights for ctype, codename, weight in level_weights: Level.objects.filter(codename=codename, content_type=ctype).update(weight=weight) signals.post_syncdb.connect( create_levels, dispatch_uid="circle.acl.management.create_levels") commands/ 0000775 0000000 0000000 00000000000 12237172035 0032604 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl/management __init__.py 0000664 0000000 0000000 00000000000 12237172035 0034703 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl/management/commands update_levels.py 0000664 0000000 0000000 00000000353 12237172035 0036013 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl/management/commands from django.core.management.base import BaseCommand from .. import create_levels class Command(BaseCommand): args = '' help = 'Regenerates Levels' def handle(self, *args, **options): create_levels(None, None, 3) models.py 0000664 0000000 0000000 00000014205 12237172035 0030526 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl import logging from django.contrib.auth.models import User, Group from django.contrib.contenttypes.generic import ( GenericForeignKey, GenericRelation ) from django.contrib.contenttypes.models import ContentType from django.db.models import ( ManyToManyField, ForeignKey, CharField, Model, IntegerField ) logger = logging.getLogger(__name__) class Level(Model): """Definition of a permission level. Instances are automatically populated based on AclBase.""" name = CharField('name', max_length=50) content_type = ForeignKey(ContentType) codename = CharField('codename', max_length=100) weight = IntegerField('weight', null=True) def __unicode__(self): return "<%s/%s>" % (unicode(self.content_type), self.name) class Meta: unique_together = (('content_type', 'codename'), # ('content_type', 'weight'), # TODO find a way of temp. disabling this constr. ) class ObjectLevel(Model): """Permission level for a specific object.""" level = ForeignKey(Level) content_type = ForeignKey(ContentType) object_id = CharField(max_length=255) content_object = GenericForeignKey() users = ManyToManyField(User) groups = ManyToManyField(Group) def __unicode__(self): return "<%s: %s>" % (unicode(self.content_object), unicode(self.level)) class Meta: unique_together = (('content_type', 'object_id', 'level'),) class AclBase(Model): """Define permission levels for Users/Groups per object.""" object_level_set = GenericRelation(ObjectLevel) def get_level_object(self, level): """Get Level object for this model by codename.""" ct = ContentType.objects.get_for_model(self) return Level.objects.get(codename=level, content_type=ct) def set_level(self, whom, level): """Set level of object for a user or group. :param whom: user or group the level is set for :type whom: User or Group :param level: codename of level to set :type level: Level or str or unicode """ if isinstance(whom, User): self.set_user_level(whom, level) elif isinstance(whom, Group): self.set_group_level(whom, level) else: raise AttributeError('"whom" must be a User or Group object.') def set_user_level(self, user, level): """Set level of object for a user. :param whom: user the level is set for :type whom: User :param level: codename of level to set :type level: Level or str or unicode """ logger.info('%s.set_user_level(%s, %s) called', *[unicode(p) for p in [self, user, level]]) if isinstance(level, basestring): level = self.get_level_object(level) if not self.object_level_set.filter(level_id=level.pk).exists(): self.object_level_set.create(level=level) for i in self.object_level_set.all(): if i.level_id != level.pk: i.users.remove(user) else: i.users.add(user) i.save() def set_group_level(self, group, level): """Set level of object for a user. :param whom: user the level is set for :type whom: User or unicode or str :param level: codename of level to set :type level: str or unicode """ logger.info('%s.set_group_level(%s, %s) called', *[unicode(p) for p in [self, group, level]]) if isinstance(level, basestring): level = self.get_level_object(level) #self.object_level_set.get_or_create(level=level, content_object=self) if not self.object_level_set.filter(level_id=level.pk).exists(): self.object_level_set.create(level=level) for i in self.object_level_set.all(): if i.level_id != level.pk: i.groups.remove(group) else: i.groups.add(group) i.save() def has_level(self, user, level, group_also=True): logger.debug('%s.has_level(%s, %s, %s) called', *[unicode(p) for p in [self, user, level, group_also]]) if getattr(user, 'is_superuser', False): logger.debug('- superuser granted') return True if isinstance(level, basestring): level = self.get_level_object(level) logger.debug("- level set by str: %s", unicode(level)) object_levels = self.object_level_set.filter( level__weight__gte=level.weight).all() if group_also: try: groups = user.group_set.values_list('id', flat=True) except AttributeError: pass # e.g. AnyonymousUser doesn't have group_set else: for i in object_levels: if i.users.filter(pk=user.pk).exists(): return True if (group_also and i.groups.filter(pk__in=groups).exists()): return True return False def get_users_with_level(self): logger.debug('%s.get_users_with_level() called', unicode(self)) object_levels = (self.object_level_set.select_related( 'users', 'level').all()) users = [] for object_level in object_levels: name = object_level.level.codename olusers = object_level.users.all() users.extend([(u, name) for u in olusers]) logger.debug('- %s: %s' % (name, [u.username for u in olusers])) return users def get_groups_with_level(self): logger.debug('%s.get_groups_with_level() called', unicode(self)) object_levels = (self.object_level_set.select_related( 'groups', 'level').all()) groups = [] for object_level in object_levels: name = object_level.level.codename olgroups = object_level.groups.all() groups.extend([(g, name) for g in olgroups]) logger.debug('- %s: %s' % (name, [g.name for g in olgroups])) return groups class Meta: abstract = True tests.py 0000664 0000000 0000000 00000000577 12237172035 0030414 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl """ This file demonstrates writing tests using the unittest module. These will pass when you run "manage.py test". Replace this with more appropriate tests for your application. """ from django.test import TestCase class SimpleTest(TestCase): def test_basic_addition(self): """ Tests that 1 + 1 always equals 2. """ self.assertEqual(1 + 1, 2) views.py 0000664 0000000 0000000 00000000032 12237172035 0030371 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/acl # Create your views here. circle/ 0000775 0000000 0000000 00000000000 12237172035 0027371 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle __init__.py 0000664 0000000 0000000 00000000000 12237172035 0031470 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle settings/ 0000775 0000000 0000000 00000000000 12237172035 0031231 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle __init__.py 0000664 0000000 0000000 00000000001 12237172035 0033331 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle/settings base.py 0000664 0000000 0000000 00000022731 12237172035 0032522 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle/settings """Common settings and globals.""" from datetime import timedelta from os import environ from os.path import abspath, basename, dirname, join, normpath from json import loads # from socket import SOCK_STREAM from sys import path # Normally you should not import ANYTHING from Django directly # into your settings, but ImproperlyConfigured is an exception. from django.core.exceptions import ImproperlyConfigured def get_env_variable(var_name, default=None): """ Get the environment variable or return exception/default """ try: return environ[var_name] except KeyError: if default is None: error_msg = "Set the %s environment variable" % var_name raise ImproperlyConfigured(error_msg) else: return default ########## PATH CONFIGURATION # Absolute filesystem path to the Django project directory: DJANGO_ROOT = dirname(dirname(abspath(__file__))) # Absolute filesystem path to the top-level project folder: SITE_ROOT = dirname(DJANGO_ROOT) # Site name: SITE_NAME = basename(DJANGO_ROOT) # Add our project to our pythonpath, this way we don't need to type our project # name in our dotted import paths: path.append(DJANGO_ROOT) ########## END PATH CONFIGURATION ########## DEBUG CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#debug DEBUG = False # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug TEMPLATE_DEBUG = DEBUG ########## END DEBUG CONFIGURATION ########## MANAGER CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#admins ADMINS = ( ('Root', 'root@localhost'), ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#managers MANAGERS = ADMINS ########## END MANAGER CONFIGURATION ########## DATABASE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.' + get_env_variable('DJANG_DB_TYPE', 'postgresql_psycopg2'), 'NAME': get_env_variable('DJANGO_DB_NAME', 'circle'), 'USER': get_env_variable('DJANGO_DB_USER', 'circle'), 'PASSWORD': get_env_variable('DJANGO_DB_PASSWORD'), 'HOST': get_env_variable('DJANGO_DB_HOST', ''), 'PORT': get_env_variable('DJANGO_DB_PORT', ''), } } ########## END DATABASE CONFIGURATION ########## GENERAL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#time-zone try: with open("/etc/timezone", "r") as f: systz = f.readline().rstrip() except: systz = None TIME_ZONE = get_env_variable('DJANGO_TIME_ZONE', default=systz) # See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code LANGUAGE_CODE = 'en-us' # See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id SITE_ID = 1 # See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n USE_I18N = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n USE_L10N = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz USE_TZ = True ########## END GENERAL CONFIGURATION ########## MEDIA CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root MEDIA_ROOT = normpath(join(SITE_ROOT, 'media')) # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url MEDIA_URL = get_env_variable('DJANGO_MEDIA_URL', default='/media/') ########## END MEDIA CONFIGURATION ########## STATIC FILE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root STATIC_ROOT = normpath(join(SITE_ROOT, 'static_collected')) # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url STATIC_URL = get_env_variable('DJANGO_STATIC_URL', default='/static/') # See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS STATICFILES_DIRS = ( normpath(join(SITE_ROOT, 'static')), ) # See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) ########## END STATIC FILE CONFIGURATION ########## SECRET CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # Note: This key should only be used for development and testing. SECRET_KEY = r"a5w*b0wajigd^kd7b=@w=5=+l_0c62@vljnhzqu3dfc@vx2jw-" ########## END SECRET CONFIGURATION ########## SITE CONFIGURATION # Hosts/domain names that are valid for this site # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts ALLOWED_HOSTS = [] ########## END SITE CONFIGURATION ########## FIXTURE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS FIXTURE_DIRS = ( normpath(join(SITE_ROOT, 'fixtures')), ) ########## END FIXTURE CONFIGURATION ########## TEMPLATE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors TEMPLATE_CONTEXT_PROCESSORS = ( 'django.contrib.auth.context_processors.auth', 'django.core.context_processors.debug', 'django.core.context_processors.i18n', 'django.core.context_processors.media', 'django.core.context_processors.static', 'django.core.context_processors.tz', 'django.contrib.messages.context_processors.messages', 'django.core.context_processors.request', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs TEMPLATE_DIRS = ( normpath(join(SITE_ROOT, 'templates')), ) ########## END TEMPLATE CONFIGURATION ########## MIDDLEWARE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes MIDDLEWARE_CLASSES = ( # Default Django middleware. 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) ########## END MIDDLEWARE CONFIGURATION ########## URL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf ROOT_URLCONF = '%s.urls' % SITE_NAME ########## END URL CONFIGURATION ########## APP CONFIGURATION DJANGO_APPS = ( # Default Django apps: 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', # Useful template tags: # 'django.contrib.humanize', # Admin panel and documentation: 'django.contrib.admin', # 'django.contrib.admindocs', ) THIRD_PARTY_APPS = ( 'south', 'django_tables2', 'crispy_forms', 'djcelery', 'sizefield', ) # Apps specific for this project go here. LOCAL_APPS = ( 'vm', 'storage', 'firewall', 'network', 'dashboard', 'manager', 'acl', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS ########## END APP CONFIGURATION ########## LOGGING CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#logging # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to # the site admins on every HTTP 500 error when DEBUG=False. # See http://docs.djangoproject.com/en/dev/topics/logging for # more details on how to customize your logging configuration. LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'simple': { 'format': '%(asctime)s [%(levelname)s]: %(name)s %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', }, }, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse' } }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' }, 'syslog': { 'level': 'INFO', 'class': 'logging.handlers.SysLogHandler', 'formatter': 'simple', 'address': '/dev/log', # 'socktype': SOCK_STREAM, # 'address': ('host', '514'), } }, 'loggers': { 'django.request': { 'handlers': ['mail_admins', 'syslog'], 'level': 'INFO', 'propagate': True, }, } } ########## END LOGGING CONFIGURATION ########## WSGI CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application WSGI_APPLICATION = '%s.wsgi.application' % SITE_NAME ########## END WSGI CONFIGURATION FIREWALL_SETTINGS = loads(get_env_variable('DJANGO_FIREWALL_SETTINGS')) CRISPY_TEMPLATE_PACK = 'bootstrap3' # format: id: (name, port, protocol) VM_ACCESS_PROTOCOLS = loads(get_env_variable('DJANGO_VM_ACCESS_PROTOCOLS', '''{"nx": ["NX", 22, "tcp"], "rdp": ["RDP", 3389, "tcp"], "ssh": ["SSH", 22, "tcp"]}''')) VM_SCHEDULER = 'manager.scheduler' # Set up periodic firewall tasks CELERYBEAT_SCHEDULE = { 'blabla': { 'task': 'firewall.tasks.local_tasks.periodic_task', 'schedule': timedelta(seconds=5), }, } local.py 0000664 0000000 0000000 00000004322 12237172035 0032676 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle/settings """Development settings and globals.""" # from os.path import join, normpath from base import * ########## DEBUG CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#debug DEBUG = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug TEMPLATE_DEBUG = DEBUG ########## END DEBUG CONFIGURATION ########## EMAIL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-backend EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ########## END EMAIL CONFIGURATION ########## DATABASE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': normpath(join(DJANGO_ROOT, 'default.db')), # 'USER': '', # 'PASSWORD': '', # 'HOST': '', # 'PORT': '', # } # } ########## END DATABASE CONFIGURATION ########## CACHE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#caches CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', } } ########## END CACHE CONFIGURATION ########## TOOLBAR CONFIGURATION # https://github.com/django-debug-toolbar/django-debug-toolbar#installation if get_env_variable('DJANGO_TOOLBAR', 'FALSE') == 'TRUE': INSTALLED_APPS += ( 'debug_toolbar', ) # https://github.com/django-debug-toolbar/django-debug-toolbar#installation INTERNAL_IPS = ( get_env_variable('SSH_CLIENT', '127.0.0.1').split(' ')[0], ) # https://github.com/django-debug-toolbar/django-debug-toolbar#installation MIDDLEWARE_CLASSES += ( 'debug_toolbar.middleware.DebugToolbarMiddleware', ) # https://github.com/django-debug-toolbar/django-debug-toolbar#installation DEBUG_TOOLBAR_CONFIG = { 'INTERCEPT_REDIRECTS': False, 'SHOW_TEMPLATE_CONTEXT': True, } ########## END TOOLBAR CONFIGURATION LOGGING['handlers']['console'] = {'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple'} for i in LOCAL_APPS: LOGGING['loggers'][i] = {'handlers': ['console'], 'level': 'DEBUG'} production.py 0000664 0000000 0000000 00000004533 12237172035 0033776 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle/settings """Production settings and globals.""" from os import environ from base import * def get_env_setting(setting): """ Get the environment setting or return exception """ try: return environ[setting] except KeyError: error_msg = "Set the %s env variable" % setting raise ImproperlyConfigured(error_msg) ########## HOST CONFIGURATION # See: https://docs.djangoproject.com/en/1.5/releases/1.5/#allowed-hosts-required-in-production ALLOWED_HOSTS = get_env_setting('DJANGO_ALLOWED_HOSTS').split(',') ########## END HOST CONFIGURATION ########## EMAIL CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-backend EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' try: # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-host EMAIL_HOST = environ.get('EMAIL_HOST') except ImproperlyConfigured: pass else: # https://docs.djangoproject.com/en/dev/ref/settings/#email-host-password EMAIL_HOST_PASSWORD = environ.get('EMAIL_HOST_PASSWORD', '') # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-host-user EMAIL_HOST_USER = environ.get('EMAIL_HOST_USER', 'your_email@example.com') # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-port EMAIL_PORT = environ.get('EMAIL_PORT', 587) # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-use-tls EMAIL_USE_TLS = True # See: https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix EMAIL_SUBJECT_PREFIX = '[%s] ' % SITE_NAME # See: https://docs.djangoproject.com/en/dev/ref/settings/#server-email SERVER_EMAIL = EMAIL_HOST_USER ########## END EMAIL CONFIGURATION ########## CACHE CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#caches try: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': get_env_variable('DJANGO_MEMCACHED'), } } except ImproperlyConfigured: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': SITE_NAME, } } ########## END CACHE CONFIGURATION ########## SECRET CONFIGURATION # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key SECRET_KEY = get_env_setting('SECRET_KEY') ########## END SECRET CONFIGURATION test.py 0000664 0000000 0000000 00000000656 12237172035 0032571 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle/settings from base import * ########## TEST SETTINGS TEST_RUNNER = 'discover_runner.DiscoverRunner' TEST_DISCOVER_TOP_LEVEL = SITE_ROOT TEST_DISCOVER_ROOT = SITE_ROOT TEST_DISCOVER_PATTERN = "test_*.py" ########## IN-MEMORY TEST DATABASE DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:", "USER": "", "PASSWORD": "", "HOST": "", "PORT": "", }, } urls.py 0000664 0000000 0000000 00000001123 12237172035 0030725 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle from django.conf.urls import patterns, include, url # from django.views.generic import TemplateView from django.contrib import admin admin.autodiscover() urlpatterns = patterns( '', #url(r'^$', TemplateView.as_view(template_name='base.html')), # Examples: # url(r'^$', 'circle.views.home', name='home'), # url(r'^circle/', include('circle.foo.urls')), # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)), url(r'^network/', include('network.urls')), url(r'^dashboard/', include('dashboard.urls')), ) wsgi.py 0000664 0000000 0000000 00000003421 12237172035 0030714 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/circle """ WSGI config for circle project. This module contains the WSGI application used by Django's development server and any production WSGI deployments. It should expose a module-level variable named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover this application via the ``WSGI_APPLICATION`` setting. Usually you will have the standard Django WSGI application here, but it also might make sense to replace the whole Django WSGI application with a custom one that later delegates to the Django one. For example, you could introduce WSGI middleware here, or combine a Django application with an application of another framework. """ import os from os.path import abspath, dirname from sys import path SITE_ROOT = dirname(dirname(abspath(__file__))) path.append(SITE_ROOT) # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks # if running multiple sites in the same mod_wsgi process. To fix this, use # mod_wsgi daemon mode with each site in its own daemon process, or use # os.environ["DJANGO_SETTINGS_MODULE"] = "jajaja.settings" os.environ.setdefault("DJANGO_SETTINGS_MODULE", "circle.settings.production") # This application object is used by any WSGI server configured to use this # file. This includes Django's development server, if the WSGI_APPLICATION # setting points here. from django.core.wsgi import get_wsgi_application _application = get_wsgi_application() def application(environ, start_response): # copy DJANGO_* wsgi-env vars to process-env for i in environ.keys(): if i.startswith('DJANGO_'): os.environ[i] = environ[i] return _application(environ, start_response) # Apply WSGI middleware here. # from helloworld.wsgi import HelloWorldApplication # application = HelloWorldApplication(application) common/ 0000775 0000000 0000000 00000000000 12237172035 0027420 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle __init__.py 0000664 0000000 0000000 00000000000 12237172035 0031517 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/common models.py 0000664 0000000 0000000 00000003213 12237172035 0031254 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/common from django.contrib.auth.models import User from django.db.models import (CharField, DateTimeField, ForeignKey, TextField) from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from model_utils.models import TimeStampedModel def activitycontextimpl(act): try: yield act except Exception as e: act.finish(str(e)) raise e else: act.finish() class ActivityModel(TimeStampedModel): activity_code = CharField(max_length=100, verbose_name=_('activity code')) parent = ForeignKey('self', blank=True, null=True) task_uuid = CharField(blank=True, max_length=50, null=True, unique=True, help_text=_('Celery task unique identifier.'), verbose_name=_('task_uuid')) user = ForeignKey(User, blank=True, null=True, verbose_name=_('user'), help_text=_('The person who started this activity.')) started = DateTimeField(verbose_name=_('started at'), blank=True, null=True, help_text=_('Time of activity initiation.')) finished = DateTimeField(verbose_name=_('finished at'), blank=True, null=True, help_text=_('Time of activity finalization.')) result = TextField(verbose_name=_('result'), blank=True, null=True, help_text=_('Human readable result of activity.')) class Meta: abstract = True def finish(self, result=None): if not self.finished: self.finished = timezone.now() self.result = result self.save() dashboard/ 0000775 0000000 0000000 00000000000 12237172035 0030057 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle __init__.py 0000664 0000000 0000000 00000000000 12237172035 0032156 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard models.py 0000664 0000000 0000000 00000000071 12237172035 0031712 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard from django.db import models # Create your models here. static/ 0000775 0000000 0000000 00000000000 12237172035 0031346 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard dashboard/ 0000775 0000000 0000000 00000000000 12237172035 0033275 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static bootstrap-slider/ 0000775 0000000 0000000 00000000000 12237172035 0036572 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard bootstrap-slider.js 0000664 0000000 0000000 00000025756 12237172035 0042444 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard/bootstrap-slider /* ========================================================= * bootstrap-slider.js v2.0.0 * http://www.eyecon.ro/bootstrap-slider * ========================================================= * Copyright 2012 Stefan Petre * * 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( $ ) { var Slider = function(element, options) { this.element = $(element); this.picker = $('
') .insertBefore(this.element) .append(this.element); this.id = this.element.data('slider-id')||options.id; if (this.id) { this.picker[0].id = this.id; } if (typeof Modernizr !== 'undefined' && Modernizr.touch) { this.touchCapable = true; } var tooltip = this.element.data('slider-tooltip')||options.tooltip; this.tooltip = this.picker.find('.tooltip'); this.tooltipInner = this.tooltip.find('div.tooltip-inner'); this.orientation = this.element.data('slider-orientation')||options.orientation; switch(this.orientation) { case 'vertical': this.picker.addClass('slider-vertical'); this.stylePos = 'top'; this.mousePos = 'pageY'; this.sizePos = 'offsetHeight'; this.tooltip.addClass('right')[0].style.left = '100%'; break; default: this.picker .addClass('slider-horizontal') .css('width', this.element.outerWidth()); this.orientation = 'horizontal'; this.stylePos = 'left'; this.mousePos = 'pageX'; this.sizePos = 'offsetWidth'; this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px'; break; } this.min = this.element.data('slider-min')||options.min; this.max = this.element.data('slider-max')||options.max; this.step = this.element.data('slider-step')||options.step; this.value = this.element.data('slider-value')||options.value; if (this.value[1]) { this.range = true; } this.selection = this.element.data('slider-selection')||options.selection; this.selectionEl = this.picker.find('.slider-selection'); if (this.selection === 'none') { this.selectionEl.addClass('hide'); } this.selectionElStyle = this.selectionEl[0].style; this.handle1 = this.picker.find('.slider-handle:first'); this.handle1Stype = this.handle1[0].style; this.handle2 = this.picker.find('.slider-handle:last'); this.handle2Stype = this.handle2[0].style; var handle = this.element.data('slider-handle')||options.handle; switch(handle) { case 'round': this.handle1.addClass('round'); this.handle2.addClass('round'); break case 'triangle': this.handle1.addClass('triangle'); this.handle2.addClass('triangle'); break } if (this.range) { this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0])); this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1])); } else { this.value = [ Math.max(this.min, Math.min(this.max, this.value))]; this.handle2.addClass('hide'); if (this.selection == 'after') { this.value[1] = this.max; } else { this.value[1] = this.min; } } this.diff = this.max - this.min; this.percentage = [ (this.value[0]-this.min)*100/this.diff, (this.value[1]-this.min)*100/this.diff, this.step*100/this.diff ]; this.offset = this.picker.offset(); this.size = this.picker[0][this.sizePos]; this.formater = options.formater; this.layout(); if (this.touchCapable) { // Touch: Bind touch events: this.picker.on({ touchstart: $.proxy(this.mousedown, this) }); } else { this.picker.on({ mousedown: $.proxy(this.mousedown, this) }); } if (tooltip === 'show') { this.picker.on({ mouseenter: $.proxy(this.showTooltip, this), mouseleave: $.proxy(this.hideTooltip, this) }); } else { this.tooltip.addClass('hide'); } }; Slider.prototype = { constructor: Slider, over: false, inDrag: false, showTooltip: function(){ this.tooltip.addClass('in'); //var left = Math.round(this.percent*this.width); //this.tooltip.css('left', left - this.tooltip.outerWidth()/2); this.over = true; }, hideTooltip: function(){ if (this.inDrag === false) { this.tooltip.removeClass('in'); } this.over = false; }, layout: function(){ this.handle1Stype[this.stylePos] = this.percentage[0]+'%'; this.handle2Stype[this.stylePos] = this.percentage[1]+'%'; if (this.orientation == 'vertical') { this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%'; this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%'; } else { this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%'; this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%'; } if (this.range) { this.tooltipInner.text( this.formater(this.value[0]) + ' : ' + this.formater(this.value[1]) ); this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px'; } else { this.tooltipInner.text( this.formater(this.value[0]) ); this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px'; } }, mousedown: function(ev) { // Touch: Get the original event: if (this.touchCapable && ev.type === 'touchstart') { ev = ev.originalEvent; } this.offset = this.picker.offset(); this.size = this.picker[0][this.sizePos]; var percentage = this.getPercentage(ev); if (this.range) { var diff1 = Math.abs(this.percentage[0] - percentage); var diff2 = Math.abs(this.percentage[1] - percentage); this.dragged = (diff1 < diff2) ? 0 : 1; } else { this.dragged = 0; } this.percentage[this.dragged] = percentage; this.layout(); if (this.touchCapable) { // Touch: Bind touch events: $(document).on({ touchmove: $.proxy(this.mousemove, this), touchend: $.proxy(this.mouseup, this) }); } else { $(document).on({ mousemove: $.proxy(this.mousemove, this), mouseup: $.proxy(this.mouseup, this) }); } this.inDrag = true; var val = this.calculateValue(); this.element.trigger({ type: 'slideStart', value: val }).trigger({ type: 'slide', value: val }); return false; }, mousemove: function(ev) { // Touch: Get the original event: if (this.touchCapable && ev.type === 'touchmove') { ev = ev.originalEvent; } var percentage = this.getPercentage(ev); if (this.range) { if (this.dragged === 0 && this.percentage[1] < percentage) { this.percentage[0] = this.percentage[1]; this.dragged = 1; } else if (this.dragged === 1 && this.percentage[0] > percentage) { this.percentage[1] = this.percentage[0]; this.dragged = 0; } } this.percentage[this.dragged] = percentage; this.layout(); var val = this.calculateValue(); this.element .trigger({ type: 'slide', value: val }) .data('value', val) .prop('value', val); return false; }, mouseup: function(ev) { if (this.touchCapable) { // Touch: Bind touch events: $(document).off({ touchmove: this.mousemove, touchend: this.mouseup }); } else { $(document).off({ mousemove: this.mousemove, mouseup: this.mouseup }); } this.inDrag = false; if (this.over == false) { this.hideTooltip(); } this.element; var val = this.calculateValue(); this.element .trigger({ type: 'slideStop', value: val }) .data('value', val) .prop('value', val); return false; }, calculateValue: function() { var val; if (this.range) { val = [ (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step), (this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step) ]; this.value = val; } else { val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step); this.value = [val, this.value[1]]; } return val; }, getPercentage: function(ev) { if (this.touchCapable) { ev = ev.touches[0]; } var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size; percentage = Math.round(percentage/this.percentage[2])*this.percentage[2]; return Math.max(0, Math.min(100, percentage)); }, getValue: function() { if (this.range) { return this.value; } return this.value[0]; }, setValue: function(val) { this.value = val; if (this.range) { this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0])); this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1])); } else { this.value = [ Math.max(this.min, Math.min(this.max, this.value))]; this.handle2.addClass('hide'); if (this.selection == 'after') { this.value[1] = this.max; } else { this.value[1] = this.min; } } this.diff = this.max - this.min; this.percentage = [ (this.value[0]-this.min)*100/this.diff, (this.value[1]-this.min)*100/this.diff, this.step*100/this.diff ]; this.layout(); } }; $.fn.slider = function ( option, val ) { return this.each(function () { var $this = $(this), data = $this.data('slider'), options = typeof option === 'object' && option; if (!data) { $this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options)))); } if (typeof option == 'string') { data[option](val); } }) }; $.fn.slider.defaults = { min: 0, max: 10, step: 1, orientation: 'horizontal', value: 5, selection: 'before', tooltip: 'show', handle: 'round', formater: function(value) { return value; } }; $.fn.slider.Constructor = Slider; }( window.jQuery ); less/ 0000775 0000000 0000000 00000000000 12237172035 0037540 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard/bootstrap-slider slider.less 0000664 0000000 0000000 00000004275 12237172035 0041722 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard/bootstrap-slider/less /*! * Slider for Bootstrap * * Copyright 2012 Stefan Petre * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * */ .slider { display: inline-block; vertical-align: middle; position: relative; &.slider-horizontal { width: 210px; height: @baseLineHeight; .slider-track { height: @baseLineHeight/2; width: 100%; margin-top: -@baseLineHeight/4; top: 50%; left: 0; } .slider-selection { height: 100%; top: 0; bottom: 0; } .slider-handle { margin-left: -@baseLineHeight/2; margin-top: -@baseLineHeight/4; &.triangle { border-width: 0 @baseLineHeight/2 @baseLineHeight/2 @baseLineHeight/2; width: 0; height: 0; border-bottom-color: #0480be; margin-top: 0; } } } &.slider-vertical { height: 210px; width: @baseLineHeight; .slider-track { width: @baseLineHeight/2; height: 100%; margin-left: -@baseLineHeight/4; left: 50%; top: 0; } .slider-selection { width: 100%; left: 0; top: 0; bottom: 0; } .slider-handle { margin-left: -@baseLineHeight/4; margin-top: -@baseLineHeight/2; &.triangle { border-width: @baseLineHeight/2 0 @baseLineHeight/2 @baseLineHeight/2; width: 1px; height: 1px; border-left-color: #0480be; margin-left: 0; } } } input { display: none; } .tooltip-inner { white-space: nowrap; } } .slider-track { position: absolute; cursor: pointer; #gradient > .vertical(#f5f5f5, #f9f9f9); .box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); .border-radius(@baseBorderRadius); } .slider-selection { position: absolute; #gradient > .vertical(#f9f9f9, #f5f5f5); .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); .box-sizing(border-box); .border-radius(@baseBorderRadius); } .slider-handle { position: absolute; width: @baseLineHeight; height: @baseLineHeight; #gradient > .vertical(#149bdf, #0480be); .box-shadow(~"inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)"); opacity: 0.8; border: 0px solid transparent; &.round { .border-radius(@baseLineHeight); } &.triangle { background: transparent none; } } slider.css 0000664 0000000 0000000 00000013523 12237172035 0040572 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard/bootstrap-slider /*! * Slider for Bootstrap * * Copyright 2012 Stefan Petre * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * */ .slider { display: inline-block; vertical-align: middle; position: relative; } .slider.slider-horizontal { width: 210px; height: 20px; } .slider.slider-horizontal .slider-track { height: 10px; width: 100%; margin-top: -5px; top: 50%; left: 0; } .slider.slider-horizontal .slider-selection { height: 100%; top: 0; bottom: 0; } .slider.slider-horizontal .slider-handle { margin-left: -10px; margin-top: -5px; } .slider.slider-horizontal .slider-handle.triangle { border-width: 0 10px 10px 10px; width: 0; height: 0; border-bottom-color: #0480be; margin-top: 0; } .slider.slider-vertical { height: 210px; width: 20px; } .slider.slider-vertical .slider-track { width: 10px; height: 100%; margin-left: -5px; left: 50%; top: 0; } .slider.slider-vertical .slider-selection { width: 100%; left: 0; top: 0; bottom: 0; } .slider.slider-vertical .slider-handle { margin-left: -5px; margin-top: -10px; } .slider.slider-vertical .slider-handle.triangle { border-width: 10px 0 10px 10px; width: 1px; height: 1px; border-left-color: #0480be; margin-left: 0; } .slider input { display: none; } .slider .tooltip-inner { white-space: nowrap; } .slider-track { position: absolute; cursor: pointer; background-color: #f7f7f7; background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .slider-selection { position: absolute; background-color: #f7f7f7; background-image: -moz-linear-gradient(top, #f9f9f9, #f5f5f5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f5f5f5)); background-image: -webkit-linear-gradient(top, #f9f9f9, #f5f5f5); background-image: -o-linear-gradient(top, #f9f9f9, #f5f5f5); background-image: linear-gradient(to bottom, #f9f9f9, #f5f5f5); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .slider-handle { position: absolute; width: 20px; height: 20px; background-color: #0e90d2; background-image: -moz-linear-gradient(top, #149bdf, #0480be); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); background-image: -webkit-linear-gradient(top, #149bdf, #0480be); background-image: -o-linear-gradient(top, #149bdf, #0480be); background-image: linear-gradient(to bottom, #149bdf, #0480be); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); opacity: 0.8; border: 0px solid transparent; } .slider-handle.round { -webkit-border-radius: 20px; -moz-border-radius: 20px; border-radius: 20px; } .slider-handle.triangle { background: transparent none; } /* custom */ .slider-handle, .slider-handle:hover { background-color: #3071a9; opacity: 1; width: 8px; height: 26px; margin-top: -4px!important; margin-left: -6px !important; border-radius: 0px; -moz-border-radius: 0px; -webkit-border-radius: 0px; text-shadow: 0 1px 0 #fff; background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); background-repeat: repeat-x; border-color: #2d6ca2; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); } .slider-handle:hover { background: #428bca; background-image: none; border-color: #2d6ca2; } .slider-track, .slider-selection { height: 20px !important; background: #ccc; background: -webkit-linear-gradient(top, #bbb, #ddd); background: -moz-linear-gradient(top, #bbb, #ddd); background: linear-gradient(top, #bbb, #ddd); -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; border: 1px solid #aaa; } .slider-selection { background-color: #8DCA09; background: -webkit-linear-gradient(top, #8DCA09, #72A307); background: -moz-linear-gradient(top, #8DCA09, #72A307); background: linear-gradient(top, #8DCA09, #72A307); border-color: #496805; } .vm-slider { width: 300px; } .output { padding-left: 10px; font-weight: bold; } dashboard.css 0000664 0000000 0000000 00000005671 12237172035 0035747 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard /* Move down content because we have a fixed navbar that is 50px tall */ body { padding-top: 50px; padding-bottom: 20px; } /* Set widths on the navbar form inputs since otherwise they're 100% wide */ .navbar-form input[type="text"], .navbar-form input[type="password"] { width: 180px; } /* Wrapping element */ /* Set some basic padding to keep content from hitting the edges */ .body-content { padding-left: 15px; padding-right: 15px; } /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { /* Let the jumbotron breathe */ .container > :first-child { margin-top: 20px; } /* Remove padding from wrapping element since we kick in the grid classes here */ .body-content { padding: 0; } } .no-margin { margin: 0!important; } .list-group .list-group-footer { padding-top: 5px; padding-bottom: 5px; } .big { font-size: 2em; } .bigbig { font-size: 3em; } .timeline { border-left: 4px #428bca solid; margin-left: 20px; padding-left: 20px; } .timeline > div { margin: 0; padding: 0; margin-left: -34px; margin-bottom: .5em; line-height: 24px; } .timeline > div:last-child { margin-bottom: 0; } .timeline .timeline-icon { margin: 0; padding: 0; width: 24px; height: 24px; text-align: center; display: inline-block; border-radius: 50%; background-color: #428bca; color: #fff; } .timeline-icon.timeline-warning { border-color: #c09853; border-style: solid; border-width: 2px; background-color: white; color: #c09853; line-height: 20px; } .timeline .timeline-icon.timeline-nobg { background-color: transparent; } .table-with-form-fields tbody tr td { line-height: 34px; } #vm-detail-panel .panel-body { min-height: 20em; } :link i:before:hover { text-decoration: none !important; } .slider { display: inline-block; } .slider .track { height: 20px; top: 50%; } .slider > .dragger, .slider > .dragger:hover { border-radius: 0px; -moz-border-radius: 0px; -webkit-border-radius: 0px; width: 8px; height: 24px; margin-top: -12px!important; text-shadow: 0 1px 0 #fff; background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); background-repeat: repeat-x; border-color: #2d6ca2; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); } .slider > .dragger:hover { background-color: #3071a9; background-image: none; border-color: #2d6ca2; } .slider > .highlight-track { height: 20px; top: 50%; } .slider + .output { } .rule-table tr >:nth-child(1) { text-align: right; } .rule-table tr >:nth-child(2) { text-align: center; } .dashboard-index .panel { height: 300px; } dashboard.js 0000664 0000000 0000000 00000003757 12237172035 0035576 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard $(function () { $('.vm-create').click(function(e) { $.ajax({ type: 'GET', url: '/dashboard/vm/create/', success: function(data) { $('body').append(data); vmCreateLoaded(); addSliderMiscs(); $('#vm-create-modal').modal('show'); $('#vm-create-modal').on('hidden.bs.modal', function() { $('#vm-create-modal').remove(); }); } }); return false; }); $('[href=#vm-graph-view]').click(function (e) { $('#vm-list-view').hide(); $('#vm-graph-view').show(); $('[href=#vm-list-view]').removeClass('disabled'); $('[href=#vm-graph-view]').addClass('disabled'); e.stopImmediatePropagation(); return false; }); $('[href=#vm-list-view]').click(function (e) { $('#vm-graph-view').hide(); $('#vm-list-view').show(); $('[href=#vm-list-view]').addClass('disabled'); $('[href=#vm-graph-view]').removeClass('disabled'); e.stopImmediatePropagation(); return false; }).addClass('disabled'); $('[title]').tooltip(); $(':input[title]').tooltip({trigger: 'focus', placement: 'auto right'}); $(".knob").knob(); if (window.location.hash) $("a[href=" + window.location.hash +"]").tab('show'); addSliderMiscs(); }); function addSliderMiscs() { $('.vm-slider').each(function() { $("").addClass("output").html($(this).val()).insertAfter($(this)); }); $('.vm-slider').slider() .on('slide', function(e) { $(this).val(e.value); $(this).parent('div').nextAll("span").html(e.value) }); refreshSliders(); } // ehhh function refreshSliders() { $('.vm-slider').each(function() { $(this).val($(this).slider().data('slider').getValue()); $(this).parent('div').nextAll("span").html($(this).val()); }); } js/ 0000775 0000000 0000000 00000000000 12237172035 0033711 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard jquery.knob.js 0000664 0000000 0000000 00000052324 12237172035 0036524 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard/js /*!jQuery Knob*/ /** * Downward compatible, touchable dial * * Version: 1.2.0 (15/07/2012) * Requires: jQuery v1.7+ * * Copyright (c) 2012 Anthony Terrien * Under MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Thanks to vor, eskimoblood, spiffistan, FabrizioC */ (function($) { /** * Kontrol library */ "use strict"; /** * Definition of globals and core */ var k = {}, // kontrol max = Math.max, min = Math.min; k.c = {}; k.c.d = $(document); k.c.t = function (e) { return e.originalEvent.touches.length - 1; }; /** * Kontrol Object * * Definition of an abstract UI control * * Each concrete component must call this one. *
* k.o.call(this);
*
*/
k.o = function () {
var s = this;
this.o = null; // array of options
this.$ = null; // jQuery wrapped element
this.i = null; // mixed HTMLInputElement or array of HTMLInputElement
this.g = null; // 2D graphics context for 'pre-rendering'
this.v = null; // value ; mixed array or integer
this.cv = null; // change value ; not commited value
this.x = 0; // canvas x position
this.y = 0; // canvas y position
this.$c = null; // jQuery canvas element
this.c = null; // rendered canvas context
this.t = 0; // touches index
this.isInit = false;
this.fgColor = null; // main color
this.pColor = null; // previous color
this.dH = null; // draw hook
this.cH = null; // change hook
this.eH = null; // cancel hook
this.rH = null; // release hook
this.scale = 1; // scale factor
this.run = function () {
var cf = function (e, conf) {
var k;
for (k in conf) {
s.o[k] = conf[k];
}
s.init();
s._configure()
._draw();
};
if(this.$.data('kontroled')) return;
this.$.data('kontroled', true);
this.extend();
this.o = $.extend(
{
// Config
min : this.$.data('min') || 0,
max : this.$.data('max') || 100,
stopper : true,
readOnly : this.$.data('readonly'),
// UI
cursor : (this.$.data('cursor') === true && 30)
|| this.$.data('cursor')
|| 0,
thickness : this.$.data('thickness') || 0.35,
lineCap : this.$.data('linecap') || 'butt',
width : this.$.data('width') || 200,
height : this.$.data('height') || 200,
displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'),
displayPrevious : this.$.data('displayprevious'),
fgColor : this.$.data('fgcolor') || '#87CEEB',
inputColor: this.$.data('inputcolor') || this.$.data('fgcolor') || '#87CEEB',
inline : false,
step : this.$.data('step') || 1,
// Hooks
draw : null, // function () {}
change : null, // function (value) {}
cancel : null, // function () {}
release : null, // function (value) {}
error : null // function () {}
}, this.o
);
// routing value
if(this.$.is('fieldset')) {
// fieldset = array of integer
this.v = {};
this.i = this.$.find('input')
this.i.each(function(k) {
var $this = $(this);
s.i[k] = $this;
s.v[k] = $this.val();
$this.bind(
'change'
, function () {
var val = {};
val[k] = $this.val();
s.val(val);
}
);
});
this.$.find('legend').remove();
} else {
// input = integer
this.i = this.$;
this.v = this.$.val();
(this.v == '') && (this.v = this.o.min);
this.$.bind(
'change'
, function () {
s.val(s._validate(s.$.val()));
}
);
}
(!this.o.displayInput) && this.$.hide();
this.$c = $('');
this.c = this.$c[0].getContext? this.$c[0].getContext('2d') : null;
if (!this.c) {
this.o.error && this.o.error();
return;
}
this.$
.wrap($(''))
.before(this.$c);
this.scale = (window.devicePixelRatio || 1) /
(
this.c.webkitBackingStorePixelRatio ||
this.c.mozBackingStorePixelRatio ||
this.c.msBackingStorePixelRatio ||
this.c.oBackingStorePixelRatio ||
this.c.backingStorePixelRatio || 1
);
if (this.scale !== 1) {
this.$c[0].width = this.$c[0].width * this.scale;
this.$c[0].height = this.$c[0].height * this.scale;
this.$c.width(this.o.width);
this.$c.height(this.o.height);
}
if (this.v instanceof Object) {
this.cv = {};
this.copy(this.v, this.cv);
} else {
this.cv = this.v;
}
this.$
.bind("configure", cf)
.parent()
.bind("configure", cf);
this._listen()
._configure()
._xy()
.init();
this.isInit = true;
this._draw();
return this;
};
this._draw = function () {
// canvas pre-rendering
var d = true,
c = document.createElement('canvas');
c.width = s.o.width * s.scale;
c.height = s.o.height * s.scale;
s.g = c.getContext('2d');
s.clear();
s.dH
&& (d = s.dH());
(d !== false) && s.draw();
s.c.drawImage(c, 0, 0);
c = null;
};
this._touch = function (e) {
var touchMove = function (e) {
var v = s.xy2val(
e.originalEvent.touches[s.t].pageX,
e.originalEvent.touches[s.t].pageY
);
if (v == s.cv) return;
if (
s.cH
&& (s.cH(v) === false)
) return;
s.change(s._validate(v));
s._draw();
};
// get touches index
this.t = k.c.t(e);
// First touch
touchMove(e);
// Touch events listeners
k.c.d
.bind("touchmove.k", touchMove)
.bind(
"touchend.k"
, function () {
k.c.d.unbind('touchmove.k touchend.k');
if (
s.rH
&& (s.rH(s.cv) === false)
) return;
s.val(s.cv);
}
);
return this;
};
this._mouse = function (e) {
var mouseMove = function (e) {
var v = s.xy2val(e.pageX, e.pageY);
if (v == s.cv) return;
if (
s.cH
&& (s.cH(v) === false)
) return;
s.change(s._validate(v));
s._draw();
};
// First click
mouseMove(e);
// Mouse events listeners
k.c.d
.bind("mousemove.k", mouseMove)
.bind(
// Escape key cancel current change
"keyup.k"
, function (e) {
if (e.keyCode === 27) {
k.c.d.unbind("mouseup.k mousemove.k keyup.k");
if (
s.eH
&& (s.eH() === false)
) return;
s.cancel();
}
}
)
.bind(
"mouseup.k"
, function (e) {
k.c.d.unbind('mousemove.k mouseup.k keyup.k');
if (
s.rH
&& (s.rH(s.cv) === false)
) return;
s.val(s.cv);
}
);
return this;
};
this._xy = function () {
var o = this.$c.offset();
this.x = o.left;
this.y = o.top;
return this;
};
this._listen = function () {
if (!this.o.readOnly) {
this.$c
.bind(
"mousedown"
, function (e) {
e.preventDefault();
s._xy()._mouse(e);
}
)
.bind(
"touchstart"
, function (e) {
e.preventDefault();
s._xy()._touch(e);
}
);
this.listen();
} else {
this.$.attr('readonly', 'readonly');
}
return this;
};
this._configure = function () {
// Hooks
if (this.o.draw) this.dH = this.o.draw;
if (this.o.change) this.cH = this.o.change;
if (this.o.cancel) this.eH = this.o.cancel;
if (this.o.release) this.rH = this.o.release;
if (this.o.displayPrevious) {
this.pColor = this.h2rgba(this.o.fgColor, "0.4");
this.fgColor = this.h2rgba(this.o.fgColor, "0.6");
} else {
this.fgColor = this.o.fgColor;
}
return this;
};
this._clear = function () {
this.$c[0].width = this.$c[0].width;
};
this._validate = function(v) {
return (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;
};
// Abstract methods
this.listen = function () {}; // on start, one time
this.extend = function () {}; // each time configure triggered
this.init = function () {}; // each time configure triggered
this.change = function (v) {}; // on change
this.val = function (v) {}; // on release
this.xy2val = function (x, y) {}; //
this.draw = function () {}; // on change / on release
this.clear = function () { this._clear(); };
// Utils
this.h2rgba = function (h, a) {
var rgb;
h = h.substring(1,7)
rgb = [parseInt(h.substring(0,2),16)
,parseInt(h.substring(2,4),16)
,parseInt(h.substring(4,6),16)];
return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")";
};
this.copy = function (f, t) {
for (var i in f) { t[i] = f[i]; }
};
};
/**
* k.Dial
*/
k.Dial = function () {
k.o.call(this);
this.startAngle = null;
this.xy = null;
this.radius = null;
this.lineWidth = null;
this.cursorExt = null;
this.w2 = null;
this.PI2 = 2*Math.PI;
this.extend = function () {
this.o = $.extend(
{
bgColor : this.$.data('bgcolor') || '#EEEEEE',
angleOffset : this.$.data('angleoffset') || 0,
angleArc : this.$.data('anglearc') || 360,
inline : true
}, this.o
);
};
this.val = function (v) {
if (null != v) {
this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;
this.v = this.cv;
this.$.val(this.v);
this._draw();
} else {
return this.v;
}
};
this.xy2val = function (x, y) {
var a, ret;
a = Math.atan2(
x - (this.x + this.w2)
, - (y - this.y - this.w2)
) - this.angleOffset;
if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {
// if isset angleArc option, set to min if .5 under min
a = 0;
} else if (a < 0) {
a += this.PI2;
}
ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc))
+ this.o.min;
this.o.stopper
&& (ret = max(min(ret, this.o.max), this.o.min));
return ret;
};
this.listen = function () {
// bind MouseWheel
var s = this,
mw = function (e) {
e.preventDefault();
var ori = e.originalEvent
,deltaX = ori.detail || ori.wheelDeltaX
,deltaY = ori.detail || ori.wheelDeltaY
,v = parseInt(s.$.val()) + (deltaX>0 || deltaY>0 ? s.o.step : deltaX<0 || deltaY<0 ? -s.o.step : 0);
if (
s.cH
&& (s.cH(v) === false)
) return;
s.val(v);
}
, kval, to, m = 1, kv = {37:-s.o.step, 38:s.o.step, 39:s.o.step, 40:-s.o.step};
this.$
.bind(
"keydown"
,function (e) {
var kc = e.keyCode;
// numpad support
if(kc >= 96 && kc <= 105) {
kc = e.keyCode = kc - 48;
}
kval = parseInt(String.fromCharCode(kc));
if (isNaN(kval)) {
(kc !== 13) // enter
&& (kc !== 8) // bs
&& (kc !== 9) // tab
&& (kc !== 189) // -
&& e.preventDefault();
// arrows
if ($.inArray(kc,[37,38,39,40]) > -1) {
e.preventDefault();
var v = parseInt(s.$.val()) + kv[kc] * m;
s.o.stopper
&& (v = max(min(v, s.o.max), s.o.min));
s.change(v);
s._draw();
// long time keydown speed-up
to = window.setTimeout(
function () { m*=2; }
,30
);
}
}
}
)
.bind(
"keyup"
,function (e) {
if (isNaN(kval)) {
if (to) {
window.clearTimeout(to);
to = null;
m = 1;
s.val(s.$.val());
}
} else {
// kval postcond
(s.$.val() > s.o.max && s.$.val(s.o.max))
|| (s.$.val() < s.o.min && s.$.val(s.o.min));
}
}
);
this.$c.bind("mousewheel DOMMouseScroll", mw);
this.$.bind("mousewheel DOMMouseScroll", mw)
};
this.init = function () {
if (
this.v < this.o.min
|| this.v > this.o.max
) this.v = this.o.min;
this.$.val(this.v);
this.w2 = this.o.width / 2;
this.cursorExt = this.o.cursor / 100;
this.xy = this.w2 * this.scale;
this.lineWidth = this.xy * this.o.thickness;
this.lineCap = this.o.lineCap;
this.radius = this.xy - this.lineWidth / 2;
this.o.angleOffset
&& (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);
this.o.angleArc
&& (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);
// deg to rad
this.angleOffset = this.o.angleOffset * Math.PI / 180;
this.angleArc = this.o.angleArc * Math.PI / 180;
// compute start and end angles
this.startAngle = 1.5 * Math.PI + this.angleOffset;
this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;
var s = max(
String(Math.abs(this.o.max)).length
, String(Math.abs(this.o.min)).length
, 2
) + 2;
this.o.displayInput
&& this.i.css({
'width' : ((this.o.width / 2 + 4) >> 0) + 'px'
,'height' : ((this.o.width / 3) >> 0) + 'px'
,'position' : 'absolute'
,'vertical-align' : 'middle'
,'margin-top' : ((this.o.width / 3) >> 0) + 'px'
,'margin-left' : '-' + ((this.o.width * 3 / 4 + 2) >> 0) + 'px'
,'border' : 0
,'background' : 'none'
,'font' : 'bold ' + ((this.o.width / s) >> 0) + 'px Arial'
,'text-align' : 'center'
,'color' : this.o.inputColor || this.o.fgColor
,'padding' : '0px'
,'-webkit-appearance': 'none'
})
|| this.i.css({
'width' : '0px'
,'visibility' : 'hidden'
});
};
this.change = function (v) {
this.cv = v;
this.$.val(v);
};
this.angle = function (v) {
return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);
};
this.draw = function () {
var c = this.g, // context
a = this.angle(this.cv) // Angle
, sat = this.startAngle // Start angle
, eat = sat + a // End angle
, sa, ea // Previous angles
, r = 1;
c.lineWidth = this.lineWidth;
c.lineCap = this.lineCap;
this.o.cursor
&& (sat = eat - this.cursorExt)
&& (eat = eat + this.cursorExt);
c.beginPath();
c.strokeStyle = this.o.bgColor;
c.arc(this.xy, this.xy, this.radius, this.endAngle, this.startAngle, true);
c.stroke();
if (this.o.displayPrevious) {
ea = this.startAngle + this.angle(this.v);
sa = this.startAngle;
this.o.cursor
&& (sa = ea - this.cursorExt)
&& (ea = ea + this.cursorExt);
c.beginPath();
c.strokeStyle = this.pColor;
c.arc(this.xy, this.xy, this.radius, sa, ea, false);
c.stroke();
r = (this.cv == this.v);
}
c.beginPath();
c.strokeStyle = r ? this.o.fgColor : this.fgColor ;
c.arc(this.xy, this.xy, this.radius, sat, eat, false);
c.stroke();
};
this.cancel = function () {
this.val(this.v);
};
};
$.fn.dial = $.fn.knob = function (o) {
return this.each(
function () {
var d = new k.Dial();
d.o = o;
d.$ = $(this);
d.run();
}
).parent();
};
})(jQuery); loopj-jquery-simple-slider-fa64f59/ 0000775 0000000 0000000 00000000000 12237172035 0041566 5 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard loopj-jquery-simple-slider-fa64f59/.gitignore 0000664 0000000 0000000 00000000034 12237172035 0043553 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard node_modules/
*.zip
gh-pages loopj-jquery-simple-slider-fa64f59/README.md 0000664 0000000 0000000 00000001302 12237172035 0043041 0 ustar 00root root 0000000 0000000 cloud-7978a8713dbb7d86888d57253bf2b24f729f3d86-7978a8713dbb7d86888d57253bf2b24f729f3d86/circle/dashboard/static/dashboard jQuery Simple Slider: Unobtrusive Numerical Slider
==================================================
SimpleSlider is a jQuery plugin for turning your text inputs into draggable
numerical sliders.
It has no external dependencies other than jQuery, and you don't need to write
a single line of JavaScript to get it to work.
How to Use
-----------
Include the javascript file in your page:
Turn your text input into a slider:
Documentation, Features and Demos
---------------------------------
Full details and documentation can be found on the project page here: