+__version__ = 'alpha'
+
+
from philo.contrib.gilbert.sites import GilbertSite, site
--- /dev/null
+GILBERT_PLUGINS.push(new (function() {
+ return {
+ init: function(application) {
+ if (GILBERT_LOGGED_IN) {
+ application.on('ready', this.addUserMenu, this, {
+ single: true,
+ });
+ } else {
+ application.on('ready', this.showLoginWindow, this, {
+ single: true,
+ });
+ }
+ },
+ addUserMenu: function(application) {
+ Gilbert.api.auth.whoami(function(result) {
+ application.mainmenu.add({
+ xtype: 'tbfill',
+ },{
+ xtype: 'tbseparator',
+ },{
+ xtype: 'button',
+ iconCls: 'user-silhouette',
+ text: '<span style="font-weight: bolder;">' + result + '</span>',
+ menu: [{
+ text: 'Change password',
+ iconCls: 'key--pencil',
+ handler: function(button, event) {
+ var change_password_window = application.createWindow({
+ layout: 'fit',
+ resizable: false,
+ title: 'Change password',
+ iconCls: 'key--pencil',
+ width: 266,
+ height: 170,
+ items: change_password_form = new Ext.FormPanel({
+ frame: true,
+ bodyStyle: 'padding: 5px 5px 0',
+ items: [{
+ fieldLabel: 'Current password',
+ name: 'current_password',
+ xtype: 'textfield',
+ inputType: 'password',
+ },{
+ fieldLabel: 'New password',
+ name: 'new_password',
+ xtype: 'textfield',
+ inputType: 'password',
+ },{
+ fieldLabel: 'New password (confirm)',
+ name: 'new_password_confirm',
+ xtype: 'textfield',
+ inputType: 'password',
+ }],
+ buttons: [{
+ text: 'Change password',
+ iconCls: 'key--pencil',
+ handler: function(button, event) {
+ var the_form = change_password_form.getForm().el.dom;
+ var current_password = the_form[0].value;
+ var new_password = the_form[1].value;
+ var new_password_confirm = the_form[2].value;
+ Gilbert.api.auth.passwd(current_password, new_password, new_password_confirm, function(result) {
+ if (result) {
+ Ext.MessageBox.alert('Password changed', 'Your password has been changed.');
+ } else {
+ Ext.MessageBox.alert('Password unchanged', 'Unable to change your password.', function() {
+ change_password_form.getForm().reset();
+ });
+ }
+ });
+ },
+ }],
+ })
+ });
+ change_password_window.show();
+ },
+ },{
+ text: 'Log out',
+ iconCls: 'door-open-out',
+ handler: function(button, event) {
+ Gilbert.api.auth.logout(function(result) {
+ if (result) {
+ document.location.reload();
+ } else {
+ Ext.MessageBox.alert('Log out failed', 'You have <strong>not</strong> been logged out. This could mean that your connection with the server has been severed. Please try again.');
+ }
+ })
+ }
+ }],
+ });
+ application.doLayout();
+ });
+ },
+ showLoginWindow: function(application) {
+ application.mainmenu.hide();
+ application.doLayout();
+ var login_window = application.createWindow({
+ header: false,
+ closable: false,
+ resizable: false,
+ draggable: false,
+ width: 266,
+ height: 130,
+ layout: 'fit',
+ items: login_form = new Ext.FormPanel({
+ frame: true,
+ bodyStyle: 'padding: 5px 5px 0',
+ items: [
+ {
+ fieldLabel: 'Username',
+ name: 'username',
+ xtype: 'textfield',
+ },
+ {
+ fieldLabel: 'Password',
+ name: 'password',
+ xtype: 'textfield',
+ inputType: 'password',
+ }
+ ],
+ buttons: [
+ {
+ text: 'Log in',
+ iconCls: 'door-open-in',
+ handler: function(button, event) {
+ var the_form = login_form.getForm().el.dom;
+ var username = the_form[0].value;
+ var password = the_form[1].value;
+ Gilbert.api.auth.login(username, password, function(result) {
+ if (result) {
+ document.location.reload();
+ } else {
+ Ext.MessageBox.alert('Log in failed', 'Unable to authenticate using the credentials provided. Please try again.', function() {
+ login_form.getForm().reset();
+ });
+ }
+ });
+ }
+ }
+ ],
+ }),
+ });
+ login_window.show();
+ },
+ }
+})());
\ No newline at end of file
--- /dev/null
+Ext.ns('Gilbert.lib');
+
+Gilbert.lib.Desktop = Ext.extend(Ext.Panel, {
+ constructor: function(config) {
+ Gilbert.lib.Desktop.superclass.constructor.call(this, Ext.applyIf(config||{}, {
+ region: 'center',
+ border: false,
+ padding: '5',
+ bodyStyle: 'background: none;',
+ }));
+ },
+});
+
+Gilbert.lib.MainMenu = Ext.extend(Ext.Toolbar, {
+ constructor: function(application) {
+ var application = this.application = application;
+ Gilbert.lib.MainMenu.superclass.constructor.call(this, {
+ region: 'north',
+ autoHeight: true,
+ });
+ },
+});
+
+Gilbert.lib.Application = Ext.extend(Ext.util.Observable, {
+ constructor: function(config) {
+ Ext.apply(this, config, {
+ renderTo: Ext.getBody(),
+ plugins: [],
+
+ });
+ Gilbert.lib.Application.superclass.constructor.call(this);
+ this.addEvents({
+ 'ready': true,
+ });
+ this.init();
+ },
+ init: function() {
+ Ext.QuickTips.init();
+
+ var desktop = this.desktop = new Gilbert.lib.Desktop();
+ var mainmenu = this.mainmenu = new Gilbert.lib.MainMenu(this);
+ var viewport = this.viewport = new Ext.Viewport({
+ renderTo: this.renderTo,
+ layout: 'border',
+ items: [
+ this.mainmenu,
+ this.desktop,
+ ],
+ });
+ var windows = this.windows = new Ext.WindowGroup();
+
+ if (this.plugins) {
+ if (Ext.isArray(this.plugins)) {
+ for (var i = 0; i < this.plugins.length; i++) {
+ this.plugins[i] = this.initPlugin(this.plugins[i]);
+ }
+ } else {
+ this.plugins = this.initPlugin(this.plugins);
+ }
+ }
+
+ this.doLayout();
+
+ this.fireEvent('ready', this);
+ },
+ initPlugin: function(plugin) {
+ plugin.init(this);
+ return plugin;
+ },
+ createWindow: function(config, cls) {
+ var win = new(cls||Ext.Window)(Ext.applyIf(config||{},{
+ renderTo: this.desktop.el,
+ manager: this.windows,
+ constrainHeader: true,
+ }));
+ win.render(this.desktop.el);
+ return win;
+ },
+ doLayout: function() {
+ this.mainmenu.doLayout();
+ this.viewport.doLayout();
+ }
+});
\ No newline at end of file
+++ /dev/null
-from philo.contrib.gilbert.utils import gilbert_method, is_gilbert_method, is_gilbert_class
-
-
-class GilbertClassBase(type):
- def __new__(cls, name, bases, attrs):
- if 'gilbert_class' not in attrs:
- attrs['gilbert_class'] = True
- if 'gilbert_class_name' not in attrs:
- attrs['gilbert_class_name'] = name
- if 'gilbert_class_methods' not in attrs:
- gilbert_class_methods = {}
- for attr in attrs.values():
- if is_gilbert_method(attr):
- gilbert_class_methods[attr.gilbert_method_name] = attr
- attrs['gilbert_class_methods'] = gilbert_class_methods
- return super(GilbertClassBase, cls).__new__(cls, name, bases, attrs)
-
-
-class GilbertClass(object):
- __metaclass__ = GilbertClassBase
-
-
-class GilbertPluginBase(type):
- def __new__(cls, name, bases, attrs):
- if 'gilbert_plugin' not in attrs:
- attrs['gilbert_plugin'] = True
- if 'gilbert_plugin_name' not in attrs:
- attrs['gilbert_plugin_name'] = name
- if 'gilbert_plugin_classes' not in attrs:
- gilbert_plugin_classes = {}
- for attr_name, attr in attrs.items():
- if is_gilbert_class(attr):
- gilbert_plugin_classes[attr_name] = attr
- attrs['gilbert_plugin_classes'] = gilbert_plugin_classes
- return super(GilbertPluginBase, cls).__new__(cls, name, bases, attrs)
-
-
-class GilbertPlugin(object):
- __metaclass__ = GilbertPluginBase
-
- def __init__(self, site):
- self.site = site
-
-
-class GilbertModelAdmin(GilbertClass):
- def __init__(self, site, model):
- self.site = site
- self.model = model
- self.gilbert_class_name = model._meta.object_name
-
- @gilbert_method
- def all(self):
- return list(self.model._default_manager.all().values())
-
- @gilbert_method
- def get(self, constraint):
- return self.model._default_manager.all().values().get(**constraint)
\ No newline at end of file
--- /dev/null
+from inspect import isclass, getargspec
+
+
+def is_gilbert_method(function):
+ return getattr(function, 'gilbert_method', False)
+
+
+def gilbert_method(function=None, name=None, argc=None, restricted=True):
+ def wrapper(function):
+ setattr(function, 'gilbert_method', True)
+ setattr(function, 'name', name or function.__name__)
+ setattr(function, 'restricted', restricted)
+ new_argc = argc
+ if new_argc is None:
+ args = getargspec(function)[0]
+ new_argc = len(args)
+ if new_argc > 0:
+ if args[0] == 'self':
+ args = args[1:]
+ new_argc = new_argc - 1
+ if new_argc > 0:
+ if args[0] == 'request':
+ args = args[1:]
+ new_argc = new_argc - 1
+ setattr(function, 'argc', new_argc)
+ return function
+ if function is not None:
+ return wrapper(function)
+ return wrapper
+
+
+class GilbertPluginBase(type):
+ def __new__(cls, name, bases, attrs):
+ if 'methods' not in attrs:
+ methods = []
+ for attr in attrs.values():
+ if is_gilbert_method(attr):
+ methods.append(attr.name)
+ attrs['methods'] = methods
+ return super(GilbertPluginBase, cls).__new__(cls, name, bases, attrs)
+
+
+class GilbertPlugin(object):
+ __metaclass__ = GilbertPluginBase
+
+ def __init__(self, site):
+ self.site = site
+
+ def get_method(self, method_name):
+ method = getattr(self, method_name, None)
+ if not is_gilbert_method(method):
+ return None
+ return method
+
+ @property
+ def urls(self):
+ return []
+
+ @property
+ def js(self):
+ return []
+
+ @property
+ def css(self):
+ return []
+
+ @property
+ def fugue_icons(self):
+ return []
+
+
+class GilbertModelAdmin(GilbertPlugin):
+ def __init__(self, site, model):
+ self.model = model
+ self.name = model._meta.object_name
+ super(GilbertModelAdmin, self).__init__(site)
+
+ @gilbert_method
+ def all(self):
+ return list(self.model._default_manager.all().values())
+
+ @gilbert_method
+ def get(self, constraint):
+ return self.model._default_manager.all().values().get(**constraint)
\ No newline at end of file
from django.contrib.admin.sites import AdminSite
from django.contrib.auth import authenticate, login, logout
-from django.conf.urls.defaults import url, patterns
+from django.conf.urls.defaults import url, patterns, include
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from django.conf import settings
from django.http import HttpResponse
from django.db.models.base import ModelBase
from philo.utils import fattr
-from philo.contrib.gilbert.options import GilbertModelAdmin, GilbertPlugin, GilbertClass
+from philo.contrib.gilbert.plugins import GilbertModelAdmin, GilbertPlugin, is_gilbert_method, gilbert_method
from philo.contrib.gilbert.exceptions import AlreadyRegistered, NotRegistered
from django.forms.models import model_to_dict
import sys
from traceback import format_tb
from inspect import getargspec
-from philo.contrib.gilbert.utils import is_gilbert_plugin, is_gilbert_class, is_gilbert_method, gilbert_method, call_gilbert_method
-
+from django.views.decorators.cache import never_cache
+from philo.contrib.gilbert import __version__ as gilbert_version
+import staticmedia
+import os
__all__ = ('GilbertSite', 'site')
-class GilbertSitePlugin(GilbertPlugin):
- class auth(GilbertClass):
- @gilbert_method(restricted=False)
- def login(self, request, username, password):
- user = authenticate(username=username, password=password)
- if user is not None and user.is_active:
- login(request, user)
- return True
- else:
- return False
-
- @gilbert_method(restricted=False)
- def logout(self, request):
- logout(request)
+class GilbertAuthPlugin(GilbertPlugin):
+ name = 'auth'
+
+ @property
+ def js(self):
+ return [staticmedia.url('gilbert/Gilbert.api.auth.js')]
+
+ @property
+ def fugue_icons(self):
+ return ['user-silhouette', 'key--pencil', 'door-open-out', 'door-open-in']
+
+ @gilbert_method(restricted=False)
+ def login(self, request, username, password):
+ user = authenticate(username=username, password=password)
+ if user is not None and user.is_active:
+ login(request, user)
return True
-
- @gilbert_method
- def passwd(self, request, current_password, new_password, new_password_confirm):
- user = request.user
- if user.check_password(current_password) and (new_password == new_password_confirm):
- user.set_password(new_password)
- user.save()
- return True
+ else:
return False
+
+ @gilbert_method
+ def logout(self, request):
+ logout(request)
+ return True
+
+ @gilbert_method
+ def passwd(self, request, current_password, new_password, new_password_confirm):
+ user = request.user
+ if user.check_password(current_password) and (new_password == new_password_confirm):
+ user.set_password(new_password)
+ user.save()
+ return True
+ return False
+
+ @gilbert_method
+ def whoami(self, request):
+ user = request.user
+ return user.get_full_name() or user.username
class GilbertSite(object):
+ version = gilbert_version
+
def __init__(self, namespace='gilbert', app_name='gilbert', title='Gilbert'):
self.namespace = namespace
self.app_name = app_name
self.title = title
- self.core_api = GilbertSitePlugin(self)
self.model_registry = SortedDict()
self.plugin_registry = SortedDict()
+ self.register_plugin(GilbertAuthPlugin)
def register_plugin(self, plugin):
- if is_gilbert_plugin(plugin):
- if plugin.gilbert_plugin_name in self.plugin_registry:
- raise AlreadyRegistered('A plugin named \'%s\' is already registered' % plugin.gilbert_plugin_name)
- self.plugin_registry[plugin.gilbert_plugin_name] = plugin(self)
- else:
- raise ValueError('register_plugin must be provided a valid plugin class or instance')
+ if plugin.name in self.plugin_registry:
+ raise AlreadyRegistered('A plugin named \'%s\' is already registered' % plugin.name)
+ self.plugin_registry[plugin.name] = plugin(self)
def register_model(self, model_or_iterable, admin_class=GilbertModelAdmin, **admin_attrs):
if isinstance(model_or_iterable, ModelBase):
if model._meta.app_label not in self.model_registry:
self.model_registry[model._meta.app_label] = SortedDict()
if model._meta.object_name in self.model_registry[model._meta.app_label]:
- raise AlreadyRegistered('The model %s is already registered' % model.__name__)
+ raise AlreadyRegistered('The model %s.%s is already registered' % (model._meta.app_label, model.__name__))
if admin_attrs:
admin_attrs['__module__'] = __name__
admin_class = type('%sAdmin' % model.__name__, (admin_class,), admin_attrs)
@property
def urls(self):
- return (patterns('',
+ urlpatterns = patterns('',
url(r'^$', self.index, name='index'),
- url(r'^css.css$', self.css, name='css'),
- url(r'^api.js$', self.api, name='api'),
+ url(r'^css$', self.css, name='css'),
+ url(r'^api$', self.api, name='api'),
url(r'^router/?$', self.router, name='router'),
- url(r'^models/(?P<app_label>\w+)/?$', self.router, name='models'),
- url(r'^plugins/(?P<plugin_name>\w+)/?$', self.router, name='plugins'),
+ url(r'^router/models/(?P<app_label>\w+)/?$', self.router, name='models'),
url(r'^login$', self.router, name='login'),
- ), self.app_name, self.namespace)
+ )
+
+ return (urlpatterns, self.app_name, self.namespace)
def request_context(self, request, extra_context=None):
from django.template import RequestContext
context.update({'gilbert': self, 'user': request.user, 'logged_in': self.has_permission(request)})
return context
+ @never_cache
def index(self, request, extra_context=None):
return render_to_response('gilbert/index.html', context_instance=self.request_context(request, extra_context))
def css(self, request, extra_context=None):
- return render_to_response('gilbert/css.css', context_instance=self.request_context(request, extra_context), mimetype='text/css')
+ icon_names = []
+ for plugin in self.plugin_registry.values():
+ icon_names.extend(plugin.fugue_icons)
+
+ icons = dict([(icon_name, staticmedia.url('gilbert/fugue-icons/icons/%s.png' % icon_name)) for icon_name in set(icon_names)])
+
+ context = extra_context or {}
+ context.update({'icons': icons})
+
+ return render_to_response('gilbert/styles.css', context_instance=self.request_context(request, context), mimetype='text/css')
+ @never_cache
def api(self, request, extra_context=None):
- return render_to_response('gilbert/api.js', context_instance=self.request_context(request, extra_context), mimetype='text/javascript')
+ providers = []
+ for app_label, models in self.model_registry.items():
+ app_provider = {
+ 'namespace': 'Gilbert.api.models.%s' % app_label,
+ 'url': reverse('%s:models' % self.namespace, current_app=self.app_name, kwargs={'app_label': app_label}),
+ 'type': 'remoting',
+ }
+ model_actions = {}
+ for model_name, admin in models.items():
+ model_methods = []
+ for method in [admin.get_method(method_name) for method_name in admin.methods]:
+ if method.restricted and not self.has_permission(request):
+ continue
+ model_methods.append({
+ 'name': method.name,
+ 'len': method.argc,
+ })
+ if model_methods:
+ model_actions[model_name] = model_methods
+ if model_actions:
+ app_provider['actions'] = model_actions
+ providers.append(app_provider)
+
+ plugin_provider = {
+ 'namespace': 'Gilbert.api',
+ 'url': reverse('%s:router' % self.namespace, current_app=self.app_name),
+ 'type': 'remoting',
+ }
+ plugin_actions = {}
+ for plugin_name, plugin in self.plugin_registry.items():
+ plugin_methods = []
+ for method in [plugin.get_method(method_name) for method_name in plugin.methods]:
+ if method.restricted and not self.has_permission(request):
+ continue
+ plugin_methods.append({
+ 'name': method.name,
+ 'len': method.argc,
+ })
+ if plugin_methods:
+ plugin_actions[plugin_name] = plugin_methods
+ if plugin_actions:
+ plugin_provider['actions'] = plugin_actions
+ providers.append(plugin_provider)
+
+ return HttpResponse(''.join(['Ext.Direct.addProvider('+json.dumps(provider, separators=(',', ':'))+');' for provider in providers]), mimetype='text/javascript')
- def router(self, request, app_label=None, plugin_name=None, extra_context=None):
+ def router(self, request, app_label=None, extra_context=None):
submitted_form = False
if request.META['CONTENT_TYPE'].startswith('application/x-www-form-urlencoded'):
submitted_form = True
'method': post_dict.pop('extMethod'),
'type': post_dict.pop('extType'),
'tid': post_dict.pop('extTID'),
+ 'upload': post_dict.pop('extUpload', False),
'data': None,
- 'kwdata': post_dict,
+ 'kwdata': post_dict
}
- if 'extUpload' in request.POST:
- ext_request['upload'] = request.POST['extUpload']
else:
ext_request = json.loads(request.raw_post_data)
+ ext_request['upload'] = False
ext_request['kwdata'] = None
try:
- gilbert_class = None
+ plugin = None
if app_label is not None:
try:
- gilbert_class = self.model_registry[app_label][ext_request['action']]
+ plugin = self.model_registry[app_label][ext_request['action']]
except KeyError:
raise NotImplementedError('A model named \'%s\' has not been registered' % ext_request['action'])
- elif plugin_name is not None:
- try:
- gilbert_plugin = self.plugin_registry[plugin_name]
- except KeyError:
- raise NotImplementedError('A plugin named \'%s\' has not been registered' % plugin_name)
- try:
- gilbert_class = gilbert_plugin.gilbert_plugin_classes[ext_request['action']]
- except KeyError:
- raise NotImplementedError('The plugin named \'%s\' does not provide a class named \'%s\'' % (plugin_name, ext_request['action']))
else:
try:
- gilbert_class = self.core_api.gilbert_plugin_classes[ext_request['action']]
+ plugin = self.plugin_registry[ext_request['action']]
except KeyError:
raise NotImplementedError('Gilbert does not provide a class named \'%s\'' % ext_request['action'])
- try:
- method = gilbert_class.gilbert_class_methods[ext_request['method']]
- except KeyError:
- raise NotImplementedError('The class named \'%s\' does not implement a method named \'%\'' % (gilbert_class.gilbert_class_name, ext_request['method']))
- if method.gilbert_method_restricted and not self.has_permission(request):
- raise NotImplementedError('The method named \'%s\' is not available' % method.gilbert_method_name)
- response = {'type': 'rpc', 'tid': ext_request['tid'], 'action': ext_request['action'], 'method': ext_request['method'], 'result': call_gilbert_method(method, gilbert_class, request, *(ext_request['data'] or []), **(ext_request['kwdata'] or {}))}
+ method = plugin.get_method(ext_request['method'])
+
+ if method is None or (method.restricted and not self.has_permission(request)):
+ raise NotImplementedError('The method named \'%s\' is not available' % method.name)
+
+ response = {'type': 'rpc', 'tid': ext_request['tid'], 'action': ext_request['action'], 'method': ext_request['method'], 'result': method(request, *(ext_request['data'] or []), **(ext_request['kwdata'] or {}))}
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
response = {'type': 'exception', 'tid': ext_request['tid'], 'message': ('%s: %s' % (exc_type, exc_value)), 'where': format_tb(exc_traceback)[0]}
+++ /dev/null
-{% load staticmedia %}
-
-Ext.Direct.addProvider({
- 'namespace': 'Gilbert.api',
- 'url': '{% url gilbert:router %}',
- 'type': 'remoting',
- 'actions': {{% for gilbert_class in gilbert.core_api.gilbert_plugin_classes.values %}
- '{{ gilbert_class.gilbert_class_name }}': [{% for method in gilbert_class.gilbert_class_methods.values %}{
- 'name': '{{ method.gilbert_method_name }}',
- 'len': {{ method.gilbert_method_argc }}
- },{% endfor %}],{% endfor %}
- }
-});
-
-{% if not logged_in %}
-
-Ext.onReady(function() {
- var login_form = new Ext.FormPanel({
- frame: true,
- bodyStyle: 'padding: 5px 5px 0',
- items: [
- {
- fieldLabel: 'Username',
- name: 'username',
- xtype: 'textfield',
- },
- {
- fieldLabel: 'Password',
- name: 'password',
- xtype: 'textfield',
- inputType: 'password',
- }
- ],
- buttons: [
- {
- text: 'Login',
- handler: function(sender) {
- // document.location.reload();
- var the_form = login_form.getForm().el.dom;
- var username = the_form[0].value;
- var password = the_form[1].value;
- Gilbert.api.auth.login(username, password, function(result) {
- if (result) {
- document.location.reload();
- } else {
- Ext.MessageBox.alert('Login failed', 'Unable to authenticate.', function() {
- login_form.getForm().reset();
- });
- }
- });
- }
- }
- ],
- });
- var login_window = new Ext.Window({
- title: 'Login',
- closable: false,
- width: 266,
- height: 130,
- layout: 'fit',
- items: login_form,
- });
- login_window.show();
-});
-
-
-{% else %}
-
-Ext.ns('Gilbert', 'Gilbert.ui', 'Gilbert.models', 'Gilbert.plugins');
-
-{% for app_label, models in gilbert.model_registry.items %}Ext.Direct.addProvider({
- 'namespace': 'Gilbert.models.{{ app_label }}',
- 'url': '{% url gilbert:models app_label %}',
- 'type': 'remoting',
- 'actions': {{% for model_name, admin in models.items %}
- '{{ model_name }}': [{% for method in admin.gilbert_class_methods.values %}{
- 'name': '{{ method.gilbert_method_name }}',
- 'len': {{ method.gilbert_method_argc }}
- },{% endfor %}],{% endfor %}
- }
-});{% endfor %}
-{% for plugin in gilbert.plugin_registry.values %}Ext.Direct.addProvider({
- 'namespace': 'Gilbert.plugins.{{ plugin.gilbert_plugin_name }}',
- 'url': '{% url gilbert:plugins plugin.gilbert_plugin_name %}',
- 'type': 'remoting',
- 'actions': {{% for gilbert_class in plugin.gilbert_plugin_classes %}
- '{{ gilbert_class.gilbert_class_name }}': [{% for method in gilbert_class.gilbert_class_methods.values %}{}
- 'name': '{{ method.gilbert_method_name }}',
- 'len': {{ method.gilbert_method_argc }}
- },{% endfor %}],{% endfor %}
- }
-});{% endfor %}
-
-Gilbert.ui.Application = function(cfg) {
- Ext.apply(this, cfg, {
- title: '{{ gilbert.title }}',
- });
- this.addEvents({
- 'ready': true,
- 'beforeunload': true,
- });
- Ext.onReady(this.initApplication, this);
-};
-
-Ext.extend(Gilbert.ui.Application, Ext.util.Observable, {
- initApplication: function() {
-
- Ext.QuickTips.init();
-
- this.desktop = new Ext.Panel({
- region: 'center',
- border: false,
- padding: '5',
- bodyStyle: 'background: none;',
- });
- var desktop = this.desktop;
-
- this.toolbar = new Ext.Toolbar({
- region: 'north',
- autoHeight: true,
- items: [
- {
- xtype: 'tbtext',
- text: this.title,
- style: 'font-weight: bolder; font-size: larger; text-transform: uppercase;',
- },
- {
- xtype: 'tbseparator',
- }
- ]
- });
- var toolbar = this.toolbar;
-
- this.viewport = new Ext.Viewport({
- renderTo: Ext.getBody(),
- layout: 'border',
- items: [
- toolbar,
- desktop,
- ],
- });
- var viewport = this.viewport;
-
- var windows = new Ext.WindowGroup();
-
- this.createWindow = function(config, cls) {
- var win = new(cls || Ext.Window)(Ext.applyIf(config || {},
- {
- renderTo: desktop.el,
- manager: windows,
- constrainHeader: true,
- maximizable: true,
- }));
- win.render(desktop.el);
- return win;
- };
- var createWindow = this.createWindow;
-
- if (this.plugins) {
- for (var pluginNum = 0; pluginNum < this.plugins.length; pluginNum++) {
- this.plugins[pluginNum].initWithApp(this);
- };
- };
-
- if (this.user) {
- var user = this.user;
- toolbar.add({ xtype: 'tbfill' });
- toolbar.add({ xtype: 'tbseparator' });
- toolbar.add({
- xtype: 'button',
- text: '<b>' + user + '</b>',
- style: 'font-weight: bolder !important; font-size: smaller !important; text-transform: uppercase !important;',
- menu: [
- {
- text: 'Change password',
- handler: function(button, event) {
- var edit_window = createWindow({
- layout: 'fit',
- title: 'Change password',
- width: 266,
- height: 170,
- layout: 'fit',
- items: _change_password_form = new Ext.FormPanel({
- frame: true,
- bodyStyle: 'padding: 5px 5px 0',
- items: [
- {
- fieldLabel: 'Current password',
- name: 'current_password',
- xtype: 'textfield',
- inputType: 'password',
- },
- {
- fieldLabel: 'New password',
- name: 'new_password',
- xtype: 'textfield',
- inputType: 'password',
- },
- {
- fieldLabel: 'New password (confirm)',
- name: 'new_password_confirm',
- xtype: 'textfield',
- inputType: 'password',
- }
- ],
- buttons: [
- {
- text: 'Change password',
- handler: function(sender) {
- // document.location.reload();
- var the_form = _change_password_form.getForm().el.dom;
- var current_password = the_form[0].value;
- var new_password = the_form[1].value;
- var new_password_confirm = the_form[2].value;
- Gilbert.api.auth.passwd(current_password, new_password, new_password_confirm, function(result) {
- if (result) {
- Ext.MessageBox.alert('Password changed', 'Your password has been changed.');
- } else {
- Ext.MessageBox.alert('Password unchanged', 'Unable to change your password.', function() {
- _change_password_form.getForm().reset();
- });
- }
- });
- }
- }
- ],
- }),
- });
- edit_window.show(this);
- },
- },
- {
- text: 'Log out',
- handler: function(button, event) {
- Gilbert.api.auth.logout(function(result) {
- if (result) {
- Ext.MessageBox.alert('Logout successful', 'You have been logged out.', function() {
- document.location.reload();
- });
- } else {
- Ext.MessageBox.alert('Logout failed', 'A bit odd, you might say.');
- }
- });
- },
- },
- ],
- });
- };
-
- toolbar.doLayout();
- viewport.doLayout();
- },
-});
-
-Ext.BLANK_IMAGE_URL = '{% mediaurl "gilbert/extjs/resources/images/default/s.gif" %}';
-
-Ext.onReady(function(){
- Gilbert.Application = new Gilbert.ui.Application({
- user: '{% filter force_escape %}{% firstof user.get_full_name user.username %}{% endfilter %}',
- plugins: [{% for plugin in gilbert.plugin_registry.values %}{% if plugin.gilbert_plugin_javascript %}
- {{ plugin.gilbert_plugin_javascript|safe }},
- {% endif %}{% endfor %}],
- });
-});
-{% endif %}
\ No newline at end of file
+++ /dev/null
-{% load staticmedia %}<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>{% block head %}
- <title>{% block title %}{{ gilbert.title }}{% endblock %}</title>
-
- {% block css %}
- <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/resources/css/ext-all.css' %}" />
- <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/resources/css/xtheme-gray.css' %}" />
- <link rel="stylesheet" type="text/css" href="{% url gilbert:css %}" />
- {% endblock %}
-
- {% block js %}
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/adapter/ext/ext-base.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/ext-all.js' %}"></script>
- <script type="text/javascript" src="{% url gilbert:api %}" id="api.js"></script>
- {% endblock %}
-
-{% endblock %}</head>
-<body style="background-image: url({% mediaurl 'gilbert/wallpaper.jpg' %});">{% block body %}{% endblock %}</body>
-</html>
-{% extends 'gilbert/base.html' %}
\ No newline at end of file
+{% load staticmedia %}<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>{% block head %}
+ <title>{% block title %}{{ gilbert.title }}{% endblock %}</title>
+
+ {% block css %}
+ <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/resources/css/ext-all.css' %}" />
+ <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/resources/css/xtheme-gray.css' %}" />
+ <link rel="stylesheet" type="text/css" href="{% url gilbert:css %}" />
+ {% for plugin in gilbert.plugin_registry.values %}{% for css in plugin.css %}
+ <link rel="stylesheet" type="text/css" href="{{ css }}" />
+ {% endfor %}{% endfor %}
+ {% endblock %}
+
+ {% block js %}
+ <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/adapter/ext/ext-base.js' %}"></script>
+ <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/ext-all.js' %}"></script>
+ <script type="text/javascript">
+ Ext.BLANK_IMAGE_URL = '{% mediaurl "gilbert/extjs/resources/images/default/s.gif" %}';
+ </script>
+ <script type="text/javascript" src="{% mediaurl 'gilbert/Gilbert.lib.js' %}"></script>
+ <script type="text/javascript" src="{% url gilbert:api %}"></script>
+ <script type="text/javascript">
+ GILBERT_LOGGED_IN = {% if logged_in %}true{% else %}false{% endif %};
+ GILBERT_PLUGINS = [];
+ </script>
+ {% for plugin in gilbert.plugin_registry.values %}{% for js in plugin.js %}
+ <script type="text/javascript" src="{{ js }}"></script>
+ {% endfor %}{% endfor %}
+ <script type="text/javascript">
+ Ext.onReady(function() {
+ GILBERT_APPLICATION = new Gilbert.lib.Application({
+ user: '{% filter force_escape %}{% firstof user.get_full_name user.username %}{% endfilter %}',
+ plugins: [new (function() {
+ return {
+ init: function(application) {
+ var plugin = this;
+ application.mainmenu.insert(0, {
+ xtype: 'button',
+ text: '<span style="font-weight: bolder; text-transform: uppercase;">Gilbert</span>',
+ handler: function(button, event) {
+ plugin.showAbout(button);
+ },
+ });
+ application.mainmenu.insert(1, {
+ xtype: 'tbseparator',
+ });
+ },
+ showAbout: function(sender) {
+ if (!this.about_window) {
+ var about_window = this.about_window = new Ext.Window({
+ height: 176,
+ width: 284,
+ header: false,
+ html: '<h1>{{ gilbert.title }}</h1><h2>Version {{ gilbert.version }}</h2>',
+ bodyStyle: 'background: none; font-size: larger; line-height: 1.4em; text-align: center;',
+ modal: true,
+ closeAction: 'hide',
+ renderTo: Ext.getBody(),
+ closable: false,
+ resizable: false,
+ draggable: false,
+ fbar: [{
+ text: 'OK',
+ handler: function(button, event) {
+ about_window.hide();
+ }
+ }],
+ defaultButton: 0,
+ });
+ }
+ this.about_window.render(Ext.getBody());
+ this.about_window.center();
+ this.about_window.show();
+ },
+ }
+ })()].concat(GILBERT_PLUGINS),
+ });
+ });
+ </script>
+ {% endblock %}
+
+{% endblock %}</head>
+<body style="background-image: url({% mediaurl 'gilbert/wallpaper.jpg' %});">{% block body %}{% endblock %}</body>
+</html>
--- /dev/null
+{% for icon, url in icons.items %}.{{icon}}{background:url({{ url }}) no-repeat !important;}{% endfor %}
\ No newline at end of file
+++ /dev/null
-from inspect import isclass, getargspec
-
-
-def is_gilbert_plugin(class_or_instance):
- from philo.contrib.gilbert.options import GilbertPluginBase, GilbertPlugin
- return (isclass(class_or_instance) and issubclass(class_or_instance, GilbertPlugin)) or isinstance(class_or_instance, GilbertPlugin) or (getattr(class_or_instance, '__metaclass__', None) is GilbertPluginBase) or (getattr(class_or_instance, 'gilbert_plugin', False) and (getattr(class_or_instance, 'gilbert_plugin_name', None) is not None) and (getattr(class_or_instance, 'gilbert_plugin_classes', None) is not None))
-
-
-def is_gilbert_class(class_or_instance):
- from philo.contrib.gilbert.options import GilbertClassBase, GilbertClass
- return (isclass(class_or_instance) and issubclass(class_or_instance, GilbertClass)) or isinstance(class_or_instance, GilbertClass) or (getattr(class_or_instance, '__metaclass__', None) is GilbertClassBase) or (getattr(class_or_instance, 'gilbert_class', False) and (getattr(class_or_instance, 'gilbert_class_name', None) is not None) and (getattr(class_or_instance, 'gilbert_class_methods', None) is not None))
-
-
-def is_gilbert_method(function):
- return getattr(function, 'gilbert_method', False)
-
-
-def gilbert_method(function=None, name=None, argc=None, restricted=True):
- def wrapper(function):
- setattr(function, 'gilbert_method', True)
- setattr(function, 'gilbert_method_name', name or function.__name__)
- setattr(function, 'gilbert_method_restricted', restricted)
- new_argc = argc
- if new_argc is None:
- args = getargspec(function)[0]
- new_argc = len(args)
- if new_argc > 0:
- if args[0] == 'self':
- args = args[1:]
- new_argc = new_argc - 1
- if new_argc > 0:
- if args[0] == 'request':
- args = args[1:]
- new_argc = new_argc - 1
- setattr(function, 'gilbert_method_argc', new_argc)
- return function
- if function is not None:
- return wrapper(function)
- return wrapper
-
-
-def call_gilbert_method(method, cls, request, *args, **kwargs):
- arg_list = getargspec(method)[0]
- if len(arg_list) > 0:
- if arg_list[0] == 'self':
- if len(arg_list) > 1 and arg_list[1] == 'request':
- return method(cls, request, *args, **kwargs)
- return method(cls, *args, **kwargs)
- elif arg_list[0] == 'request':
- return method(request, *args, **kwargs)
- else:
- return method(*args, **kwargs)
\ No newline at end of file