aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/css/detailsView.css30
-rw-r--r--apps/files/index.php2
-rw-r--r--apps/files/js/detailsview.js45
-rw-r--r--apps/files/js/detailtabview.js25
-rw-r--r--apps/files/js/filelist.js118
-rw-r--r--apps/files/js/mainfileinfodetailview.js48
-rw-r--r--apps/files_sharing/js/share.js7
-rw-r--r--apps/files_sharing/js/sharedetailview.js63
-rw-r--r--apps/files_sharing/js/sharetabview.js64
9 files changed, 328 insertions, 74 deletions
diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
index 783a8c9b0c3..0bbdfe94903 100644
--- a/apps/files/css/detailsView.css
+++ b/apps/files/css/detailsView.css
@@ -1,19 +1,45 @@
+#app-content-files .detailsView.disappear {
+ margin-right: -300px;
+}
+
#app-content-files .detailsView {
position: absolute;
width: 300px;
top: 44px;
bottom: 0;
right: 0;
+ left: auto;
background-color: white;
border: 1px solid black;
+ -webkit-transition: margin-right 300ms;
+ -moz-transition: margin-right 300ms;
+ -o-transition: margin-right 300ms;
+ transition: margin-right 300ms;
+}
+
+#app-content-files .detailsView .detailFileInfoContainer {
+ min-height: 200px;
+ padding: 10px;
+}
+
+#app-content-files .detailsView .detailFileInfoContainer > div{
+ clear: both;
+ margin-left: 5px;
}
#app-content-files .detailsView .thumbnail {
- width: 32px;
- height: 32px;
+ width: 50px;
+ height: 50px;
float: left;
+ margin: 5px;
+ background-size: 50px;
+}
+
+#app-content-files .detailsView .fileName {
+ font-weight: bold;
+ font-size: 17px;
}
#app-content-files .detailsView .detailList {
diff --git a/apps/files/index.php b/apps/files/index.php
index 1cb7c16ce6b..dca3e5ae74d 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -52,8 +52,8 @@ OCP\Util::addscript('files', 'search');
\OCP\Util::addScript('files', 'detailfileinfoview');
\OCP\Util::addScript('files', 'detailtabview');
-\OCP\Util::addScript('files', 'detailsview');
\OCP\Util::addScript('files', 'mainfileinfodetailview');
+\OCP\Util::addScript('files', 'detailsview');
\OCP\Util::addStyle('files', 'detailsView');
\OC_Util::addVendorScript('core', 'handlebars/handlebars');
diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js
index a8abac5c68f..719299485a6 100644
--- a/apps/files/js/detailsview.js
+++ b/apps/files/js/detailsview.js
@@ -14,14 +14,14 @@
'<div>' +
' <div class="detailFileInfoContainer">' +
' </div>' +
- ' <div class="tabHeadsContainer">' +
- ' </div>' +
- ' <div class="tabContentsContainer">' +
+ ' <div class="tabsContainer">' +
+ ' <ul class="tabHeadsContainer">' +
+ ' </ul>' +
' </div>' +
'</div>';
var TEMPLATE_TAB_HEADER =
- '<div class="tabHeaders">{{label}}</div>';
+ '<li class="tabHeaders"><a href="#{{tabId}}">{{label}}</a></li>';
/**
* @class OCA.Files.DetailsView
@@ -33,6 +33,7 @@
var DetailsView = function() {
this.initialize();
};
+
/**
* @memberof OCA.Files
*/
@@ -90,6 +91,7 @@
* Renders this details view
*/
render: function() {
+ var self = this;
this.$el.empty();
if (!this._template) {
@@ -101,30 +103,37 @@
}
var $el = $(this._template());
+ var $tabsContainer = $el.find('.tabsContainer');
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');
+ if (this._tabViews.length > 0) {
+ // render tabs
+ _.each(this._tabViews, function(tabView) {
+ tabView.render();
+ // hidden by default
+ $tabsContainer.append(tabView.$el);
+
+ $tabHeadsContainer.append(self._templateTabHeader({
+ tabId: tabView.getId(),
+ label: tabView.getLabel()
+ }));
+ });
+ }
+
+ // TODO: select current tab
this.$el.append($el);
+
+ if (this._tabViews.length > 0) {
+ $tabsContainer.tabs({});
+ }
},
/**
@@ -136,7 +145,7 @@
this._fileInfo = fileInfo;
// notify all panels
- _.each(this._tabs, function(tabView) {
+ _.each(this._tabViews, function(tabView) {
tabView.setFileInfo(fileInfo);
});
_.each(this._detailFileInfoViews, function(detailView) {
diff --git a/apps/files/js/detailtabview.js b/apps/files/js/detailtabview.js
index f630099111d..767ece2297c 100644
--- a/apps/files/js/detailtabview.js
+++ b/apps/files/js/detailtabview.js
@@ -17,8 +17,8 @@
* Base class for tab views to display file information.
*
*/
- var DetailTabView = function() {
- this.initialize();
+ var DetailTabView = function(id) {
+ this.initialize(id);
};
/**
@@ -51,9 +51,16 @@
/**
* Initialize the details view
+ *
+ * @param {string} id tab id
*/
- initialize: function() {
+ initialize: function(id) {
+ if (!id) {
+ throw 'Argument "id" is required';
+ }
+ this._id = id;
this.$el = $('<div class="detailTabView"></div>');
+ this.$el.attr('id', id);
},
/**
@@ -66,6 +73,15 @@
},
/**
+ * Returns the tab element id
+ *
+ * @return {string} tab id
+ */
+ getId: function() {
+ return this._id;
+ },
+
+ /**
* Returns the tab label
*
* @return {String} label
@@ -81,6 +97,9 @@
*/
render: function() {
// to be implemented in subclass
+ // FIXME: code is only for testing
+ this.$el.empty();
+ this.$el.append('<div>Hello ' + this._id + '</div>');
},
/**
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index cbf946974eb..355c76f9c64 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -221,6 +221,13 @@
this.updateSearch();
+ this.$el.on('click', function(event) {
+ var $target = $(event.target);
+ // click outside file row ?
+ if (!$target.closest('tbody').length) {
+ self._updateDetailsView(null);
+ }
+ });
this.$fileList.on('click','td.filename>a.name', _.bind(this._onClickFile, this));
this.$fileList.on('change', 'td.filename>.selectCheckBox', _.bind(this._onClickFileCheckbox, this));
this.$el.on('urlChanged', _.bind(this._onUrlChanged, this));
@@ -273,17 +280,35 @@
* @param {OCA.Files.FileInfo} fileInfo file info to display
*/
_updateDetailsView: function(fileInfo) {
+ var self = this;
+ if (!fileInfo) {
+ if (this._detailsView) {
+ // hide it
+ this._detailsView.$el.addClass('disappear');
+ this._detailsView.setFileInfo(null);
+ }
+ return;
+ }
+
if (!this._detailsView) {
this._detailsView = new OCA.Files.DetailsView();
- this.$el.append(this._detailsView.$el);
-
this._detailsView.addDetailView(new OCA.Files.MainFileInfoDetailView());
-
+ _.each(this._detailFileInfoViews, function(view) {
+ self._detailsView.addDetailView(view);
+ });
+ _.each(this._tabViews, function(view) {
+ self._detailsView.addTabView(view);
+ });
+ this.$el.append(this._detailsView.$el);
+ this._detailsView.$el.addClass('disappear');
this._detailsView.render();
}
this._detailsView.setFileInfo(_.extend({
path: this.getCurrentDirectory()
}, fileInfo));
+ _.defer(function() {
+ self._detailsView.$el.removeClass('disappear');
+ });
},
/**
@@ -374,36 +399,34 @@
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) {
- this.fileActions.currentFile = $tr.find('td');
- var mime = this.fileActions.getCurrentMimeType();
- var type = this.fileActions.getCurrentType();
- var permissions = this.fileActions.getCurrentPermissions();
- var action = this.fileActions.getDefault(mime,type, permissions);
- if (action) {
- event.preventDefault();
- // also set on global object for legacy apps
- window.FileActions.currentFile = this.fileActions.currentFile;
- action(filename, {
- $file: $tr,
- fileList: this,
- fileActions: this.fileActions,
- dir: $tr.attr('data-path') || this.getCurrentDirectory()
- });
+ // clicked directly on the name
+ if ($(event.target).is('.nametext') || $(event.target).closest('.nametext').length) {
+ var filename = $tr.attr('data-file');
+ var renaming = $tr.data('renaming');
+ if (!renaming) {
+ this.fileActions.currentFile = $tr.find('td');
+ var mime = this.fileActions.getCurrentMimeType();
+ var type = this.fileActions.getCurrentType();
+ var permissions = this.fileActions.getCurrentPermissions();
+ var action = this.fileActions.getDefault(mime,type, permissions);
+ if (action) {
+ event.preventDefault();
+ // also set on global object for legacy apps
+ window.FileActions.currentFile = this.fileActions.currentFile;
+ action(filename, {
+ $file: $tr,
+ fileList: this,
+ fileActions: this.fileActions,
+ dir: $tr.attr('data-path') || this.getCurrentDirectory()
+ });
+ }
+ // deselect row
+ $(event.target).closest('a').blur();
}
- // deselect row
- $(event.target).closest('a').blur();
+ } else {
+ var fileInfo = this.files[$tr.index()];
+ this._updateDetailsView(fileInfo);
+ event.preventDefault();
}
}
},
@@ -858,7 +881,7 @@
var formatted;
var text;
if (mtime > 0) {
- formatted = formatDate(mtime);
+ formatted = OC.Util.formatDate(mtime);
text = OC.Util.relativeModifiedDate(mtime);
} else {
formatted = t('files', 'Unable to determine date');
@@ -1554,6 +1577,7 @@
tr.remove();
tr = self.add(fileInfo, {updateSummary: false, silent: true});
self.$fileList.trigger($.Event('fileActionsReady', {fileList: self, $files: $(tr)}));
+ self._updateDetailsView(fileInfo);
}
});
} else {
@@ -2261,6 +2285,34 @@
};
/**
+ * Globally registered tab views
+ *
+ * @type OCA.Files.DetailTabView
+ */
+ FileList.prototype._tabViews = [];
+
+ /**
+ * Globally registered detail views
+ *
+ * @type OCA.Files.DetailFileInfoView
+ */
+ FileList.prototype._detailFileInfoViews = [];
+
+ /**
+ * Register a tab view to be added to all views
+ */
+ FileList.prototype.registerTabView = function(tabView) {
+ this._tabViews.push(tabView);
+ };
+
+ /**
+ * Register a detail view to be added to all views
+ */
+ FileList.prototype.registerDetailView = function(detailView) {
+ this._detailFileInfoViews.push(detailView);
+ };
+
+ /**
* File info attributes.
*
* @todo make this a real class in the future
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
index 3f3705c2586..5eb74145f12 100644
--- a/apps/files/js/mainfileinfodetailview.js
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -10,11 +10,8 @@
(function() {
var TEMPLATE =
- '<div class="thumbnail"></div>' +
- '<ul class="detailList">' +
- ' <li>Name: {{name}}</li>' +
- ' <li>Path: {{path}}</li>' +
- '</ul>';
+ '<div class="thumbnail"></div><div class="fileName">{{name}}</div>' +
+ '<div><span title="{{altSize}}">{{size}}</span>, <span title="{{altDate}}">{{date}}</span></div>';
/**
* @class OCA.Files.MainFileInfoDetailView
@@ -42,8 +39,6 @@
/**
* Renders this details view
- *
- * @abstract
*/
render: function() {
this.$el.empty();
@@ -53,17 +48,36 @@
}
if (this._fileInfo) {
- this.$el.append(this._template(this._fileInfo));
+ this.$el.append(this._template({
+ nameLabel: t('files', 'Name'),
+ name: this._fileInfo.name,
+ pathLabel: t('files', 'Path'),
+ path: this._fileInfo.path,
+ sizeLabel: t('files', 'Size'),
+ // TODO: refactor and use size formatter
+ size: OC.Util.humanFileSize(this._fileInfo.size, true),
+ altSize: this._fileInfo.size,
+ dateLabel: t('files', 'Modified'),
+ altDate: OC.Util.formatDate(this._fileInfo.mtime),
+ date: OC.Util.relativeModifiedDate(this._fileInfo.mtime)
+ }));
+
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 + '")');
- }
- });
+ // TODO: we really need OC.Previews
+ if (this._fileInfo.mimetype !== 'httpd/unix-directory') {
+ // FIXME: use proper way, this is only for demo purposes
+ var previewUrl = FileList.generatePreviewUrl({
+ file: this._fileInfo.path + '/' + this._fileInfo.name,
+ c: this._fileInfo.etag,
+ x: 50,
+ y: 50
+ });
+ previewUrl = previewUrl.replace('(', '%28').replace(')', '%29');
+ $iconDiv.css('background-image', 'url("' + previewUrl + '")');
+ } else {
+ // TODO: special icons / shared / external
+ $iconDiv.css('background-image', 'url("' + OC.MimeType.getIconUrl('dir') + '")');
+ }
} else {
// TODO: render placeholder text?
}
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index e7823454c53..227eec79578 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -140,6 +140,13 @@
}
});
}, t('files_sharing', 'Share'));
+
+ OC.addScript('files_sharing', 'sharetabview').done(function() {
+ fileList.registerTabView(new OCA.Sharing.ShareTabView('shareTabView'));
+ });
+ OC.addScript('files_sharing', 'sharedetailview').done(function() {
+ fileList.registerDetailView(new OCA.Sharing.ShareDetailView());
+ });
},
/**
diff --git a/apps/files_sharing/js/sharedetailview.js b/apps/files_sharing/js/sharedetailview.js
new file mode 100644
index 00000000000..a18a6d19d15
--- /dev/null
+++ b/apps/files_sharing/js/sharedetailview.js
@@ -0,0 +1,63 @@
+/*
+ * 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 =
+ '<ul class="shareDetailList">' +
+ ' <li>Owner: {{owner}}</li>' +
+ '</ul>';
+
+ /**
+ * @class OCA.Files.MainFileInfoDetailView
+ * @classdesc
+ *
+ * Displays main details about a file
+ *
+ */
+ var ShareDetailView = function() {
+ this.initialize();
+ };
+ /**
+ * @memberof OCA.Sharing
+ */
+ ShareDetailView.prototype = _.extend({}, OCA.Files.DetailFileInfoView.prototype,
+ /** @lends OCA.Sharing.ShareDetailView.prototype */ {
+ _template: null,
+
+ /**
+ * Initialize the details view
+ */
+ initialize: function() {
+ this.$el = $('<div class="shareDetailView"></div>');
+ },
+
+ /**
+ * Renders this details view
+ */
+ render: function() {
+ this.$el.empty();
+
+ if (!this._template) {
+ this._template = Handlebars.compile(TEMPLATE);
+ }
+
+ if (this._fileInfo) {
+ this.$el.append(this._template({
+ owner: this._fileInfo.shareOwner || OC.currentUser
+ }));
+ } else {
+ // TODO: render placeholder text?
+ }
+ }
+ });
+
+ OCA.Sharing.ShareDetailView = ShareDetailView;
+})();
+
diff --git a/apps/files_sharing/js/sharetabview.js b/apps/files_sharing/js/sharetabview.js
new file mode 100644
index 00000000000..48dfcae16d8
--- /dev/null
+++ b/apps/files_sharing/js/sharetabview.js
@@ -0,0 +1,64 @@
+/*
+ * 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 =
+ '<div>TODO: here comes the share dialog</div>';
+
+ /**
+ * @class OCA.Sharing.ShareTabView
+ * @classdesc
+ *
+ * Displays sharing information
+ *
+ */
+ var ShareTabView = function(id) {
+ this.initialize(id);
+ };
+ /**
+ * @memberof OCA.Sharing
+ */
+ ShareTabView.prototype = _.extend({}, OCA.Files.DetailTabView.prototype,
+ /** @lends OCA.Sharing.ShareTabView.prototype */ {
+ _template: null,
+
+ /**
+ * Initialize the details view
+ */
+ initialize: function() {
+ OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments);
+ this.$el.addClass('shareTabView');
+ },
+
+ getLabel: function() {
+ return t('files_sharing', 'Sharing');
+ },
+
+ /**
+ * Renders this details view
+ */
+ render: function() {
+ this.$el.empty();
+
+ if (!this._template) {
+ this._template = Handlebars.compile(TEMPLATE);
+ }
+
+ if (this._fileInfo) {
+ this.$el.append(this._template());
+ } else {
+ // TODO: render placeholder text?
+ }
+ }
+ });
+
+ OCA.Sharing.ShareTabView = ShareTabView;
+})();
+