...
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   .gitignore
#	modified:   __init__.py
#	modified:   content/css/branding.less
#	modified:   content/css/branding.less.c.css
#	modified:   content/css/branding.less.css
#	modified:   content/css/player.less
#	modified:   content/css/player.less.c.css
#	modified:   content/css/player.less.css
#	modified:   content/js/player.coffee
#	modified:   content/js/player.coffee.c.js
#	modified:   layout/projects-main.xml
#	modified:   layout/video-main.xml
#	modified:   projects/__init__.py
#	modified:   projects/main.py
#	modified:   video/__init__.py
#	modified:   video/main.py
#
diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
diff --git a/__init__.py b/__init__.py
old mode 100644
new mode 100755
diff --git a/content/css/branding.less b/content/css/branding.less
old mode 100644
new mode 100755
diff --git a/content/css/branding.less.c.css b/content/css/branding.less.c.css
old mode 100644
new mode 100755
diff --git a/content/css/branding.less.css b/content/css/branding.less.css
old mode 100644
new mode 100755
diff --git a/content/css/player.less b/content/css/player.less
old mode 100644
new mode 100755
diff --git a/content/css/player.less.c.css b/content/css/player.less.c.css
old mode 100644
new mode 100755
diff --git a/content/css/player.less.css b/content/css/player.less.css
old mode 100644
new mode 100755
diff --git a/content/js/player.coffee b/content/js/player.coffee
old mode 100644
new mode 100755
diff --git a/content/js/player.coffee.c.js b/content/js/player.coffee.c.js
index c00285f..3027b90 100644
--- a/content/js/player.coffee.c.js
+++ b/content/js/player.coffee.c.js
@@ -1,79 +1 @@
-// Generated by CoffeeScript 1.4.0
-(function() {
-  var __hasProp = {}.hasOwnProperty,
-    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
-  window.Controls.video = (function(_super) {
-
-    __extends(video, _super);
-
-    function video() {
-      return video.__super__.constructor.apply(this, arguments);
-    }
-
-    video.prototype.createDom = function() {
-      var timestamp,
-        _this = this;
-      this.dom = $("<div class=\"control video\">\n    <video controls>\n        <source src=\"" + (this.properties.path ? "/elements/video/" + this.properties.path : '') + "\" type=\"video/mp4\">\n    </video>\n    <div class=\"timestamp\">\n        00:00:00.000\n    </div>\n    <div>\n        <a class=\"control button style-normal\"><i class=\"icon-cut\"></i> Cut</a>\n    </div>\n</div>");
-      timestamp = this.dom.find('.timestamp');
-      this.video = this.dom.find('video')[0];
-      this.video.addEventListener('canplay', function() {
-        if (!_this.video) {
-          return;
-        }
-        _this.video.pause();
-        if (_this.properties.position) {
-          _this.video.currentTime = _this.properties.position;
-        }
-        if (_this.properties.autoplay) {
-          return _this.video.play();
-        }
-      });
-      this.video.addEventListener('timeupdate', function() {
-        var h, m, ms, s, ts;
-        if (!_this.video) {
-          return;
-        }
-        ts = _this.video.currentTime;
-        _this.lastTimestamp = ts;
-        h = Math.floor(ts / 3600);
-        m = Math.floor(ts / 60 % 60);
-        s = Math.floor(ts % 60);
-        ms = Math.floor(ts * 1000 % 1000);
-        ts = h + ':' + (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s + '.' + (ms < 100 ? '0' : '') + (ms < 10 ? '0' : '') + ms;
-        timestamp.text(ts);
-        return _this.lastTimestampText = ts;
-      });
-      return this.dom.find('a').click(function() {
-        return _this.event('cut', {
-          time: _this.lastTimestamp,
-          time_text: _this.lastTimestampText
-        });
-      });
-    };
-
-    video.prototype.detectUpdates = function() {
-      var r;
-      r = {};
-      if (this.video.paused === this.properties.autoplay) {
-        r.autoplay = !this.video.paused;
-      }
-      if (this.video.currentTime !== this.properties.position) {
-        r.position = this.video.currentTime;
-      }
-      return r;
-    };
-
-    video.prototype.onBroadcast = function(msg) {
-      if (msg === 'destruct') {
-        this.video.pause();
-        delete this.video;
-        return $(this.dom).empty();
-      }
-    };
-
-    return video;
-
-  })(window.Control);
-
-}).call(this);
+(function(){var __hasProp={}.hasOwnProperty,__extends=function(child,parent){for(var key in parent){if(__hasProp.call(parent,key)){child[key]=parent[key]}}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor();child.__super__=parent.prototype;return child};window.Controls.video=(function(_super){__extends(video,_super);function video(){return video.__super__.constructor.apply(this,arguments)}video.prototype.createDom=function(){var timestamp,_this=this;this.dom=$('<div class="control video">\n    <video controls>\n        <source src="'+(this.properties.path?"/elements/video/"+this.properties.path:"")+'" type="video/mp4">\n    </video>\n    <div class="timestamp">\n        00:00:00.000\n    </div>\n    <div>\n        <a class="control button style-normal"><i class="icon-cut"></i> Cut</a>\n    </div>\n</div>');timestamp=this.dom.find(".timestamp");this.video=this.dom.find("video")[0];this.video.addEventListener("canplay",function(){if(!_this.video){return}_this.video.pause();if(_this.properties.position){_this.video.currentTime=_this.properties.position}if(_this.properties.autoplay){return _this.video.play()}});this.video.addEventListener("timeupdate",function(){var h,m,ms,s,ts;if(!_this.video){return}ts=_this.video.currentTime;_this.lastTimestamp=ts;h=Math.floor(ts/3600);m=Math.floor(ts/60%60);s=Math.floor(ts%60);ms=Math.floor(ts*1000%1000);ts=h+":"+(m<10?"0":"")+m+":"+(s<10?"0":"")+s+"."+(ms<100?"0":"")+(ms<10?"0":"")+ms;timestamp.text(ts);return _this.lastTimestampText=ts});return this.dom.find("a").click(function(){return _this.event("cut",{time:_this.lastTimestamp,time_text:_this.lastTimestampText})})};video.prototype.detectUpdates=function(){var r;r={};if(this.video.paused===this.properties.autoplay){r.autoplay=!this.video.paused}if(this.video.currentTime!==this.properties.position){r.position=this.video.currentTime}return r};video.prototype.onBroadcast=function(msg){if(msg==="destruct"){this.video.pause();delete this.video;return $(this.dom).empty()}};return video})(window.Control)}).call(this);
\ No newline at end of file
diff --git a/layout/projects-main.xml b/layout/projects-main.xml
old mode 100644
new mode 100755
index 959549b..e845a90
--- a/layout/projects-main.xml
+++ b/layout/projects-main.xml
@@ -13,7 +13,10 @@
                                     </right>
                                     <hc>
                                         <icon icon="suitcase" />
-                                        <label bind="name" />
+                                        <box width="300">
+                                            <label bind="name" />
+                                        </box>
+                                        <label bind="description" />
                                     </hc>   
                                 </box>
                                 
@@ -25,6 +28,12 @@
                                                     <formline text="Name">
                                                         <textbox bind="name" />
                                                     </formline>
+                                                    <formline text="Description">
+                                                        <textbox bind="description" />
+                                                    </formline>
+                                                    <formline text="Long description">
+                                                        <codearea bind="long_description" width="300" />
+                                                    </formline>
                                                 </formgroup>
                                                 <formgroup text="Access control">
                                                     <bind:collection id="permissions" bind="permissions">
diff --git a/layout/video-main.xml b/layout/video-main.xml
old mode 100644
new mode 100755
diff --git a/projects/__init__.py b/projects/__init__.py
old mode 100644
new mode 100755
diff --git a/projects/main.py b/projects/main.py
old mode 100644
new mode 100755
index 9f7dfbc..a414b74
--- a/projects/main.py
+++ b/projects/main.py
@@ -40,6 +40,8 @@ class ElementsProject (object):
             self.directory = slugify(self.name)
         defaults = {
             'lock': None,
+            'description': '',
+            'long_description': '',
             'emulate_avid': False,
             'share_nfs': False,
             'share_afp': False,
@@ -119,7 +121,6 @@ class ElementsProjectManager (BasePlugin):
 
     def __call_quota(self, p, args):
         d = subprocess.check_output(['snquota', '-F', 'snfs1', '-d', '.projects/' + p.directory] + args)
-        print d
         return d
 
     def _parse_quotasize(self, s):
@@ -166,51 +167,58 @@ class ElementsProjectManager (BasePlugin):
         s.guest_ok = True
         self.smb_config.tree.shares.append(s)
 
-        for p in self.projects:
-            self.__call_quota(p, ['-C'])
-            if p.quota_size_hard:
-                self.__call_quota(p, ['-S', '-h', '%sg' % p.quota_size_hard, '-s', '%sg' % p.quota_size_soft, '-t', '1d'])
-
-            if p.share_smb:
-                s = reconfigure.items.samba.ShareData()
-                s.name = p.name
-                s.comment = IDENTIFICATION_COMMENT
-                s.path = os.path.join(ROOT, p.directory)
-                s.read_only = False
-                s.guest_ok = True
-                self.smb_config.tree.shares.append(s)
-            if p.share_nfs:
-                s = reconfigure.items.exports.ExportData()
-                s.name = os.path.join(ROOT, p.directory)
-                c = reconfigure.items.exports.ClientData()
-                c.name = '*'
-                c.options = 'rw,insecure,no_subtree_check,rsize=2097152,wsize=2097152,async,tcp'
-                s.comment = IDENTIFICATION_COMMENT
-                s.clients.append(c)
-                self.nfs_config.tree.exports.append(s)
-            if p.share_afp:
-                s = reconfigure.items.netatalk.ShareData()
-                s.name = p.name
-                s.comment = IDENTIFICATION_COMMENT
-                s.path = os.path.join(ROOT, p.directory)
-                s.read_only = False
-                s.valid_users = 'root,client'
-                self.afp_config.tree.shares.append(s)
-
-        # Read quota status
-        q = json.loads(subprocess.check_output(['snquota', '-L', '-Fsnfs1', '-ojson']))
-        q = q['directoryQuotas']
-        for e in q:
-            if e['type'] == 'dir':
-                for p in self.projects:
-                    if e['name'] == '/.projects/' + p.directory:
-                        p.quota_size_status = e['status']
-                        try:
-                            p.quota_size_current = self._parse_quotasize(e['curSize'])
-                            p.quota_size_usage = p.quota_size_current / p.quota_size_hard
-                        except:
-                            p.quota_size_current = 0
-                            p.quota_size_usage = 0
+        try:
+            subprocess.check_call(['which', 'snquota'])
+            has_quotas = True
+        except:
+            has_quotas = False
+
+        if has_quotas:
+            for p in self.projects:
+                self.__call_quota(p, ['-C'])
+                if p.quota_size_hard:
+                    self.__call_quota(p, ['-S', '-h', '%sg' % p.quota_size_hard, '-s', '%sg' % p.quota_size_soft, '-t', '1d'])
+
+                if p.share_smb:
+                    s = reconfigure.items.samba.ShareData()
+                    s.name = p.name
+                    s.comment = IDENTIFICATION_COMMENT
+                    s.path = os.path.join(ROOT, p.directory)
+                    s.read_only = False
+                    s.guest_ok = True
+                    self.smb_config.tree.shares.append(s)
+                if p.share_nfs:
+                    s = reconfigure.items.exports.ExportData()
+                    s.name = os.path.join(ROOT, p.directory)
+                    c = reconfigure.items.exports.ClientData()
+                    c.name = '*'
+                    c.options = 'rw,insecure,no_subtree_check,rsize=2097152,wsize=2097152,async,tcp'
+                    s.comment = IDENTIFICATION_COMMENT
+                    s.clients.append(c)
+                    self.nfs_config.tree.exports.append(s)
+                if p.share_afp:
+                    s = reconfigure.items.netatalk.ShareData()
+                    s.name = p.name
+                    s.comment = IDENTIFICATION_COMMENT
+                    s.path = os.path.join(ROOT, p.directory)
+                    s.read_only = False
+                    s.valid_users = 'root,client'
+                    self.afp_config.tree.shares.append(s)
+
+            # Read quota status
+            q = json.loads(subprocess.check_output(['snquota', '-L', '-Fsnfs1', '-ojson']))
+            q = q['directoryQuotas']
+            for e in q:
+                if e['type'] == 'dir':
+                    for p in self.projects:
+                        if e['name'] == '/.projects/' + p.directory:
+                            p.quota_size_status = e['status']
+                            try:
+                                p.quota_size_current = self._parse_quotasize(e['curSize'])
+                                p.quota_size_usage = p.quota_size_current / p.quota_size_hard
+                            except:
+                                p.quota_size_current = 0
+                                p.quota_size_usage = 0
 
         self.smb_config.save()
         self.nfs_config.save()
@@ -240,12 +248,6 @@ class ElementsProjects (SectionPlugin):
         self.category = 'Elements'
         self.append(self.ui.inflate('elements:projects-main'))
 
-        #def post_graph_bind(o, c, i, u):
-        #    for plot in u.nearest(lambda x: x.typeid == 'munin:plot'):
-        #        plot.on('widget', self.on_add_widget, i)
-        #
-        #self.find('graphs').post_item_bind = post_graph_bind
-
         self.find('projects').new_item = lambda c: ElementsProject()
         self.find('permissions').new_item = lambda c: ElementsProjectPermission()
         self.find('user-dropdown').labels = self.find('user-dropdown').values = list(ajenti.config.tree.users)
@@ -275,6 +277,7 @@ class ElementsProjects (SectionPlugin):
     def save(self):
         self.binder.update()
         self.mgr.save()
+        self.refresh()
 
 
 @plugin
diff --git a/video/__init__.py b/video/__init__.py
old mode 100644
new mode 100755
diff --git a/video/main.py b/video/main.py
old mode 100644
new mode 100755
