diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
new file mode 100644
index 0000000000..783a8c9b0c
--- /dev/null
+++ b/apps/files/css/detailsView.css
@@ -0,0 +1,22 @@
+
+
+#app-content-files .detailsView {
+ position: absolute;
+ width: 300px;
+ top: 44px;
+ bottom: 0;
+ right: 0;
+ background-color: white;
+ border: 1px solid black;
+}
+
+#app-content-files .detailsView .thumbnail {
+ width: 32px;
+ height: 32px;
+ float: left;
+}
+
+#app-content-files .detailsView .detailList {
+ float: left;
+}
+
diff --git a/apps/files/index.php b/apps/files/index.php
index 4f103f975c..1cb7c16ce6 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -50,6 +50,12 @@ OCP\Util::addscript('files', 'search');
\OCP\Util::addScript('files', 'tagsplugin');
\OCP\Util::addScript('files', 'favoritesplugin');
+\OCP\Util::addScript('files', 'detailfileinfoview');
+\OCP\Util::addScript('files', 'detailtabview');
+\OCP\Util::addScript('files', 'detailsview');
+\OCP\Util::addScript('files', 'mainfileinfodetailview');
+\OCP\Util::addStyle('files', 'detailsView');
+
\OC_Util::addVendorScript('core', 'handlebars/handlebars');
OCP\App::setActiveNavigationEntry('files_index');
diff --git a/apps/files/js/detailfileinfoview.js b/apps/files/js/detailfileinfoview.js
new file mode 100644
index 0000000000..9585f57f1e
--- /dev/null
+++ b/apps/files/js/detailfileinfoview.js
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+ /**
+ * @class OCA.Files.DetailFileInfoView
+ * @classdesc
+ *
+ * Displays a block of details about the file info.
+ *
+ */
+ var DetailFileInfoView = function() {
+ this.initialize();
+ };
+ /**
+ * @memberof OCA.Files
+ */
+ DetailFileInfoView.prototype = {
+ /**
+ * jQuery element
+ */
+ $el: null,
+
+ _template: null,
+
+ /**
+ * Currently displayed file info
+ *
+ * @type OCA.Files.FileInfo
+ */
+ _fileInfo: null,
+
+ /**
+ * Initialize the details view
+ */
+ initialize: function() {
+ this.$el = $('
');
+ },
+
+ /**
+ * Destroy / uninitialize this instance.
+ */
+ destroy: function() {
+ if (this.$el) {
+ this.$el.remove();
+ }
+ },
+
+ /**
+ * Renders this details view
+ *
+ * @abstract
+ */
+ render: function() {
+ // to be implemented in subclass
+ },
+
+ /**
+ * Sets the file info to be displayed in the view
+ *
+ * @param {OCA.Files.FileInfo} fileInfo file info to set
+ */
+ setFileInfo: function(fileInfo) {
+ this._fileInfo = fileInfo;
+ this.render();
+ },
+
+ /**
+ * Returns the file info.
+ *
+ * @return {OCA.Files.FileInfo} file info
+ */
+ getFileInfo: function() {
+ return this._fileInfo;
+ }
+ };
+
+ OCA.Files.DetailFileInfoView = DetailFileInfoView;
+})();
+
diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js
new file mode 100644
index 0000000000..a8abac5c68
--- /dev/null
+++ b/apps/files/js/detailsview.js
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+
+ var TEMPLATE =
+ '' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+
+ var TEMPLATE_TAB_HEADER =
+ '';
+
+ /**
+ * @class OCA.Files.DetailsView
+ * @classdesc
+ *
+ * The details view show details about a selected file.
+ *
+ */
+ var DetailsView = function() {
+ this.initialize();
+ };
+ /**
+ * @memberof OCA.Files
+ */
+ DetailsView.prototype = {
+
+ /**
+ * jQuery element
+ */
+ $el: null,
+
+ _template: null,
+ _templateTabHeader: null,
+
+ /**
+ * Currently displayed file info
+ *
+ * @type OCA.Files.FileInfo
+ */
+ _fileInfo: null,
+
+ /**
+ * List of detail tab views
+ *
+ * @type Array
+ */
+ _tabViews: [],
+
+ /**
+ * List of detail file info views
+ *
+ * @type Array
+ */
+ _detailFileInfoViews: [],
+
+ /**
+ * Initialize the details view
+ */
+ initialize: function() {
+ this.$el = $('');
+ this.fileInfo = null;
+ this._tabViews = [];
+ this._detailFileInfoViews = [];
+ },
+
+ /**
+ * Destroy / uninitialize this instance.
+ */
+ destroy: function() {
+ if (this.$el) {
+ this.$el.remove();
+ }
+ },
+
+ /**
+ * Renders this details view
+ */
+ render: function() {
+ this.$el.empty();
+
+ if (!this._template) {
+ this._template = Handlebars.compile(TEMPLATE);
+ }
+
+ if (!this._templateTabHeader) {
+ this._templateTabHeader = Handlebars.compile(TEMPLATE_TAB_HEADER);
+ }
+
+ var $el = $(this._template());
+ var $tabHeadsContainer = $el.find('.tabHeadsContainer');
+ var $tabsContainer = $el.find('.tabContentsContainer');
+ var $detailsContainer = $el.find('.detailFileInfoContainer');
+
+ // render tabs
+ _.each(this._tabs, function(tabView) {
+ tabView.render();
+ // hidden by default
+ tabView.$el.addClass('hidden');
+ $tabsContainer.append(tabView.$el);
+
+ $tabHeadsContainer.append(this._templateTabHeader({label: tabView.getLabel()}));
+ });
+
+ // render details
+ _.each(this._detailFileInfoViews, function(detailView) {
+ detailView.render();
+ $detailsContainer.append(detailView.$el);
+ });
+
+ // select first tab
+ $el.find('.tabContentsContainer:first').removeClass('hidden');
+
+ this.$el.append($el);
+ },
+
+ /**
+ * Sets the file info to be displayed in the view
+ *
+ * @param {OCA.Files.FileInfo} fileInfo file info to set
+ */
+ setFileInfo: function(fileInfo) {
+ this._fileInfo = fileInfo;
+
+ // notify all panels
+ _.each(this._tabs, function(tabView) {
+ tabView.setFileInfo(fileInfo);
+ });
+ _.each(this._detailFileInfoViews, function(detailView) {
+ detailView.setFileInfo(fileInfo);
+ });
+ },
+
+ /**
+ * Returns the file info.
+ *
+ * @return {OCA.Files.FileInfo} file info
+ */
+ getFileInfo: function() {
+ return this._fileInfo;
+ },
+
+ /**
+ * Adds a tab in the tab view
+ *
+ * @param {OCA.Files.DetailTabView} tab view
+ */
+ addTabView: function(tabView) {
+ this._tabViews.push(tabView);
+ },
+
+ /**
+ * Adds a detail view for file info.
+ *
+ * @param {OCA.Files.DetailFileInfoView} detail view
+ */
+ addDetailView: function(detailView) {
+ this._detailFileInfoViews.push(detailView);
+ }
+ };
+
+ OCA.Files.DetailsView = DetailsView;
+})();
+
diff --git a/apps/files/js/detailtabview.js b/apps/files/js/detailtabview.js
new file mode 100644
index 0000000000..f630099111
--- /dev/null
+++ b/apps/files/js/detailtabview.js
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+
+ /**
+ * @class OCA.Files.DetailTabView
+ * @classdesc
+ *
+ * Base class for tab views to display file information.
+ *
+ */
+ var DetailTabView = function() {
+ this.initialize();
+ };
+
+ /**
+ * @memberof OCA.Files
+ */
+ DetailTabView.prototype = {
+ /**
+ * jQuery element
+ */
+ $el: null,
+
+ /**
+ * Tab id
+ */
+ _id: null,
+
+ /**
+ * Tab label
+ */
+ _label: null,
+
+ _template: null,
+
+ /**
+ * Currently displayed file info
+ *
+ * @type OCA.Files.FileInfo
+ */
+ _fileInfo: null,
+
+ /**
+ * Initialize the details view
+ */
+ initialize: function() {
+ this.$el = $('');
+ },
+
+ /**
+ * Destroy / uninitialize this instance.
+ */
+ destroy: function() {
+ if (this.$el) {
+ this.$el.remove();
+ }
+ },
+
+ /**
+ * Returns the tab label
+ *
+ * @return {String} label
+ */
+ getLabel: function() {
+ return 'Tab ' + this._id;
+ },
+
+ /**
+ * Renders this details view
+ *
+ * @abstract
+ */
+ render: function() {
+ // to be implemented in subclass
+ },
+
+ /**
+ * Sets the file info to be displayed in the view
+ *
+ * @param {OCA.Files.FileInfo} fileInfo file info to set
+ */
+ setFileInfo: function(fileInfo) {
+ this._fileInfo = fileInfo;
+ this.render();
+ },
+
+ /**
+ * Returns the file info.
+ *
+ * @return {OCA.Files.FileInfo} file info
+ */
+ getFileInfo: function() {
+ return this._fileInfo;
+ }
+ };
+
+ OCA.Files.DetailTabView = DetailTabView;
+})();
+
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index a7d4e41d0e..cbf946974e 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -64,6 +64,11 @@
*/
fileSummary: null,
+ /**
+ * @type OCA.Files.DetailsView
+ */
+ _detailsView: null,
+
/**
* Whether the file list was initialized already.
* @type boolean
@@ -262,6 +267,25 @@
this.fileActions.on('setDefault', this._onFileActionsUpdated);
},
+ /**
+ * Update the details view to display the given file
+ *
+ * @param {OCA.Files.FileInfo} fileInfo file info to display
+ */
+ _updateDetailsView: function(fileInfo) {
+ if (!this._detailsView) {
+ this._detailsView = new OCA.Files.DetailsView();
+ this.$el.append(this._detailsView.$el);
+
+ this._detailsView.addDetailView(new OCA.Files.MainFileInfoDetailView());
+
+ this._detailsView.render();
+ }
+ this._detailsView.setFileInfo(_.extend({
+ path: this.getCurrentDirectory()
+ }, fileInfo));
+ },
+
/**
* Event handler for when the window size changed
*/
@@ -350,6 +374,15 @@
this._selectFileEl($tr, !$checkbox.prop('checked'));
this.updateSelectionSummary();
} else {
+ var currentIndex = $tr.index();
+ var fileInfo = this.files[currentIndex];
+
+ this._updateDetailsView(fileInfo);
+ event.preventDefault();
+ return;
+
+ // FIXME: disabled for testing details view
+
var filename = $tr.attr('data-file');
var renaming = $tr.data('renaming');
if (!renaming) {
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
new file mode 100644
index 0000000000..3f3705c258
--- /dev/null
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function() {
+ var TEMPLATE =
+ '' +
+ '' +
+ ' - Name: {{name}}
' +
+ ' - Path: {{path}}
' +
+ '
';
+
+ /**
+ * @class OCA.Files.MainFileInfoDetailView
+ * @classdesc
+ *
+ * Displays main details about a file
+ *
+ */
+ var MainFileInfoDetailView = function() {
+ this.initialize();
+ };
+ /**
+ * @memberof OCA.Files
+ */
+ MainFileInfoDetailView.prototype = _.extend({}, OCA.Files.DetailFileInfoView.prototype,
+ /** @lends OCA.Files.MainFileInfoDetailView.prototype */ {
+ _template: null,
+
+ /**
+ * Initialize the details view
+ */
+ initialize: function() {
+ this.$el = $('');
+ },
+
+ /**
+ * Renders this details view
+ *
+ * @abstract
+ */
+ render: function() {
+ this.$el.empty();
+
+ if (!this._template) {
+ this._template = Handlebars.compile(TEMPLATE);
+ }
+
+ if (this._fileInfo) {
+ this.$el.append(this._template(this._fileInfo));
+ var $iconDiv = this.$el.find('.thumbnail');
+ // FIXME: use proper way, this is only for demo purposes
+ FileList.lazyLoadPreview({
+ path: this._fileInfo.path + '/' + this._fileInfo.name,
+ mime: this._fileInfo.mimetype,
+ etag: this._fileInfo.etag,
+ callback: function(url) {
+ $iconDiv.css('background-image', 'url("' + url + '")');
+ }
+ });
+ } else {
+ // TODO: render placeholder text?
+ }
+ }
+ });
+
+ OCA.Files.MainFileInfoDetailView = MainFileInfoDetailView;
+})();
+