diff --git a/templates/web/admin/index.html.twig b/templates/web/admin/index.html.twig
index a1cbd08ef7..380a20852a 100644
--- a/templates/web/admin/index.html.twig
+++ b/templates/web/admin/index.html.twig
@@ -8,202 +8,64 @@
{% endblock %}
{% block stylesheet %}
-
+
{% endblock %}
{% block javascript %}
- {% include "common/templates.html.twig" %}
- {# note: Tinymce must be include here without minify else URL resolution for tinymce plugins will fail #}
-
-
-
+
+
{% endblock %}
-
{% block content %}
-
+
+
- {% include 'admin/tree.html.twig' %}
+ {% include 'admin/tree.html.twig' %}
@@ -217,7 +79,7 @@
{% endif %}
@@ -245,4 +107,5 @@
+
{% endblock %}
diff --git a/www/scripts/apps/admin/main/app.js b/www/scripts/apps/admin/main/app.js
new file mode 100644
index 0000000000..34e96cf985
--- /dev/null
+++ b/www/scripts/apps/admin/main/app.js
@@ -0,0 +1,81 @@
+/*
+ * This file is part of Phraseanet
+ *
+ * (c) 2005-2014 Alchemy
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+define([
+ "jquery",
+ "underscore",
+ "backbone",
+ "common/websockets/connection",
+ "apps/admin/main/views/leftPanel",
+ "apps/admin/main/views/rightPanel"
+], function ($, _, Backbone, WSConnection, LeftPanel, RightPanel) {
+ window.AdminApp = {
+ $scope: $("#admin-app"),
+ $leftView : $(".left-view", this.$scope),
+ $rightView : $(".right-view", this.$scope),
+ eventManager: _.extend({}, Backbone.Events)
+ };
+
+ var sessionActive = function() {
+ $.ajax({
+ type: "POST",
+ url: "/session/update/",
+ dataType: 'json',
+ data: {
+ module : 3,
+ usr : AdminApp.$scope.data("usr")
+ },
+ error: function(){
+ window.setTimeout(function() {sessionActive();}, 10000);
+ },
+ timeout: function(){
+ window.setTimeout(function() {sessionActive();}, 10000);
+ },
+ success: function(data){
+ if(data) {
+ manageSession(data);
+ var t = 120000;
+ if(data.apps && parseInt(data.apps)>1) {
+ t = Math.round((Math.sqrt(parseInt(data.apps)-1) * 1.3 * 120000));
+ }
+ window.setTimeout(function() {sessionActive();}, t);
+ }
+ }
+ })
+ };
+
+ var initialize = function (options) {
+ if (false === "wsurl" in options) {
+ throw "You must define a websocket url";
+ }
+
+ if (false === WSConnection.hasSession()) {
+ WSConnection.connect(options.wsurl);
+ }
+
+ AdminApp.LeftView = new LeftPanel({
+ el: AdminApp.$leftView,
+ eventManager: AdminApp.eventManager
+ });
+
+ AdminApp.RightView = new RightPanel({
+ el: AdminApp.$rightView,
+ eventManager: AdminApp.eventManager
+ });
+
+ AdminApp.LeftView.activeTree();
+ AdminApp.LeftView.clickSelected();
+
+ window.setTimeout(function() {sessionActive();}, 15000);
+ };
+
+ return {
+ initialize: initialize
+ };
+});
diff --git a/www/scripts/apps/admin/main/main.js b/www/scripts/apps/admin/main/main.js
new file mode 100644
index 0000000000..c10990db8c
--- /dev/null
+++ b/www/scripts/apps/admin/main/main.js
@@ -0,0 +1,56 @@
+/*
+ * This file is part of Phraseanet
+ *
+ * (c) 2005-2014 Alchemy
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+// configure AMD loading
+require.config({
+ baseUrl: "/scripts",
+ paths: {
+ jquery: "../assets/jquery/jquery",
+ "jquery.ui": "../assets/jquery.ui/jquery-ui",
+ underscore: "../assets/underscore-amd/underscore",
+ backbone: "../assets/backbone-amd/backbone",
+ "jquery.ui.widget": "../assets/jquery-file-upload/jquery.ui.widget",
+ "jquery.cookie": "../assets/jquery.cookie/jquery.cookie",
+ "jquery.treeview": "../assets/jquery.treeview/jquery.treeview",
+ "jquery.tooltip": "../assets/jquery.tooltip/jquery.tooltip",
+ "blueimp.loadimage" : "../assets/blueimp-load-image/load-image",
+ "jfu.iframe-transport": "../assets/jquery-file-upload/jquery.iframe-transport",
+ "jfu.fileupload": "../assets/jquery-file-upload/jquery.fileupload"
+ },
+ shim: {
+ "jquery.treeview": {
+ deps: ['jquery', 'jquery.cookie'],
+ exports: '$.fn.treeview'
+ },
+ "jquery.cookie": {
+ deps: ["jquery"],
+ exports: '$.fn.cookie'
+ },
+ "jquery.tooltip": {
+ deps: ["jquery"],
+ exports: '$.fn.tooltip'
+ },
+ "jquery.ui": {
+ deps: ["jquery"]
+ },
+ "jquery.ui.widget": {
+ deps: ["jquery"]
+ },
+ "jfu.fileupload": {
+ deps: ["jquery.ui.widget"]
+ }
+ }
+});
+
+// launch application
+require(["jquery", "apps/admin/main/app"], function ($, App) {
+ App.initialize({
+ "wsurl": $("#left").data("websocket")
+ });
+});
diff --git a/www/scripts/apps/admin/main/views/leftPanel.js b/www/scripts/apps/admin/main/views/leftPanel.js
new file mode 100644
index 0000000000..cf98aedc81
--- /dev/null
+++ b/www/scripts/apps/admin/main/views/leftPanel.js
@@ -0,0 +1,106 @@
+/*
+ * This file is part of Phraseanet
+ *
+ * (c) 2005-2014 Alchemy
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+define([
+ "jquery",
+ "underscore",
+ "backbone",
+ "common/websockets/subscriberManager",
+ "jquery.treeview"
+], function ($, _, Backbone, SubscriberManager) {
+ var LeftPanelView = Backbone.View.extend({
+ initialize: function (options) {
+ if (false === "eventManager" in options) {
+ throw "You must set en event manager";
+ }
+ this.delegateEvents(this.events);
+ this.eventManager = options.eventManager;
+ this.$treeview = $("#FNDR", this.$el);
+
+ var $this = this;
+ this.eventManager.on("panel:left:success", function(data, click) {
+ $this.render.append(data);
+ $this.activeTree();
+ if (click) {
+ $this.clickSelected();
+ }
+ })
+ },
+ render : function(data) {
+ this.$treeview.empty().append(data);
+ },
+ events: {
+ "click a[target=right]": "clickAction"
+ },
+ activeTree: function() {
+ // tree view jquery module is not loaded as a module
+ this.$treeview.treeview({
+ collapsed: true,
+ animated: "medium"
+ });
+ },
+ clickSelected: function () {
+ if($('.selected', this.$el).length > 0) {
+ $('.selected a', this.$el).trigger('click');
+ } else {
+ $('.zone_online_users', this.$el).trigger('click');
+ }
+ },
+ reloadTree: function (position, click) {
+ var $this = this;
+ $.ajax({
+ type: "GET",
+ url: "/admin/tree/",
+ data: {position : position},
+ success: function(data){
+ $this.eventManager.trigger('panel:left:success', data , click)
+ },
+ beforeSend: function(){
+ $this.eventManager.trigger('panel:left:beforeSend');
+ },
+ complete: function(){
+ $this.eventManager.trigger('panel:left:complete');
+ }
+ });
+ },
+ clickAction: function(event) {
+ event.preventDefault();
+ var $this = this;
+ var link = $(event.currentTarget);
+
+ $.ajax({
+ type: "GET",
+ url: link.attr('href'),
+ success: function(data) {
+ $this.eventManager.trigger('panel:right:success', data);
+ },
+ beforeSend: function(){
+ $this.eventManager.trigger('panel:right:beforeSend');
+ },
+ complete: function(){
+ $this.eventManager.trigger('panel:right:complete');
+ }
+ });
+
+ if ("undefined" !== typeof link.data("ws-topic")) {
+ console.log(link.data("ws-topic"));
+ SubscriberManager.register(link.data("ws-topic"));
+ }
+
+ $this.selectLink(link);
+ link.removeAttr('target');
+ },
+ selectLink: function(link) {
+ $('.selected', this.$el).removeClass('selected');
+ link.parent().addClass('selected');
+ }
+ });
+
+ return LeftPanelView;
+});
diff --git a/www/scripts/apps/admin/main/views/rightPanel.js b/www/scripts/apps/admin/main/views/rightPanel.js
new file mode 100644
index 0000000000..5c91a77bdc
--- /dev/null
+++ b/www/scripts/apps/admin/main/views/rightPanel.js
@@ -0,0 +1,104 @@
+/*
+ * This file is part of Phraseanet
+ *
+ * (c) 2005-2014 Alchemy
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+define([
+ "jquery",
+ "underscore",
+ "backbone",
+ "jquery.tooltip",
+ "blueimp.loadimage",
+ "jfu.iframe-transport",
+ "jfu.fileupload",
+ "jquery.ui"
+], function ($, _, Backbone) {
+ var RightPanelView = Backbone.View.extend({
+ initialize: function (options) {
+ if (false === "eventManager" in options) {
+ throw "You must set en event manager";
+ }
+ this.delegateEvents(this.events);
+ this.eventManager = options.eventManager;
+
+ var $this = this;
+ this.eventManager.on("panel:right:beforeSend", function() {
+ $this.$el.empty();
+ $this.loadingState(true);
+ });
+ this.eventManager.on("panel:right:complete", function() {
+ $this.loadingState(false);
+ });
+ this.eventManager.on("panel:right:success", function(data) {
+ $this.render(data);
+ })
+ },
+ events: {
+ "submit form:not(.no-ajax)": "submitAction",
+ "click a:not(.no-ajax)": "clickAction"
+ },
+ render: function (data) {
+ this.$el.html(data);
+
+ return this;
+ },
+ clickAction: function(event) {
+ event.preventDefault();
+ var $this = this;
+ var link = $(event.currentTarget);
+ var url = link.attr('href');
+
+ if(url && url.indexOf('#') !== 0) {
+ $.ajax({
+ type: link.attr("method") || "GET",
+ url: url,
+ success: function(data) {
+ $this.eventManager.trigger('panel:right:success', data);
+ },
+ beforeSend: function(){
+ $this.eventManager.trigger('panel:right:beforeSend');
+ },
+ complete: function(){
+ $this.eventManager.trigger('panel:right:complete');
+ }
+ });
+ }
+ },
+ submitAction: function(event) {
+ event.preventDefault();
+ var $this = this;
+ var link = $(event.currentTarget);
+ var url = link.attr('action') || 'GET';
+
+ if(url) {
+ $.ajax({
+ type: link.attr('method'),
+ url: url,
+ data: link.serializeArray(),
+ success: function (data) {
+ $this.eventManager.trigger("panel:right:success", data);
+ },
+ beforeSend: function(){
+ $this.eventManager.trigger('panel:right:beforeSend');
+ },
+ complete: function(){
+ $this.eventManager.trigger('panel:right:complete');
+ }
+ });
+ }
+ },
+ loadingState: function(state) {
+ if (state) {
+ this.$el.addClass("loading");
+ } else {
+ this.$el.removeClass("loading");
+ }
+ }
+ });
+
+ return RightPanelView;
+});