Improved right sidebar
Added owner info. Added animation, but causes scrollbal. Default file action now when clicking on name directly. Fixed icon. Added empty share tab.
This commit is contained in:
parent
9854e71d2c
commit
12e5f310dd
9 changed files with 328 additions and 74 deletions
|
@ -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 {
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -65,6 +72,15 @@
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the tab element id
|
||||
*
|
||||
* @return {string} tab id
|
||||
*/
|
||||
getId: function() {
|
||||
return this._id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the tab 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>');
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
@ -2260,6 +2284,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.
|
||||
*
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
63
apps/files_sharing/js/sharedetailview.js
Normal file
63
apps/files_sharing/js/sharedetailview.js
Normal file
|
@ -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;
|
||||
})();
|
||||
|
64
apps/files_sharing/js/sharetabview.js
Normal file
64
apps/files_sharing/js/sharetabview.js
Normal file
|
@ -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;
|
||||
})();
|
||||
|
Loading…
Reference in a new issue