mirror of
https://github.com/humhub/humhub.git
synced 2025-04-21 15:41:54 +02:00
JS Action/Content refactoring Implementation of action components.
This commit is contained in:
parent
06e69903ea
commit
fdd223a985
34
Gruntfile.js
34
Gruntfile.js
@ -1,16 +1,16 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
|
||||
grunt.initConfig({
|
||||
concat: {
|
||||
options: {
|
||||
separator: ';',
|
||||
},
|
||||
dist: {
|
||||
src: ['js/humhub.core.js', 'js/humhub.util.js' ,'js/humhub.additions.js',
|
||||
'js/humhub.client.js', 'js/humhub.ui.js', 'js/humhub.ui.modal.js', 'js/humhub.actions.js',
|
||||
'js/humhub.content.js', 'js/humhub.stream.js'],
|
||||
dest: 'js/dist/humhub.all.js'
|
||||
}
|
||||
options: {
|
||||
separator: ';',
|
||||
},
|
||||
dist: {
|
||||
src: ['js/humhub.core.js', 'js/humhub.util.js', 'js/humhub.additions.js',
|
||||
'js/humhub.client.js', 'js/humhub.ui.js', 'js/humhub.ui.modal.js', 'js/humhub.actions.js',
|
||||
'js/humhub.content.js', 'js/humhub.stream.js'],
|
||||
dest: 'js/dist/humhub.all.js'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
js: {
|
||||
@ -22,17 +22,25 @@ module.exports = function (grunt) {
|
||||
uglify: {
|
||||
build: {
|
||||
files: {
|
||||
'js/dist/humhub.all.min.js' : ['js/dist/humhub.all.js']
|
||||
'js/dist/humhub.all.min.js': ['js/dist/humhub.all.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
less: {
|
||||
dev: {
|
||||
files: {
|
||||
'themes/HumHub/css/less/theme.css': 'themes/HumHub/css/less/theme.less'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
|
||||
|
||||
grunt.registerTask('default', ['watch']);
|
||||
grunt.registerTask('build', ['concat', 'uglify', 'clean']);
|
||||
};
|
509
js/dist/humhub.all.js
vendored
509
js/dist/humhub.all.js
vendored
@ -177,17 +177,17 @@ var humhub = humhub || (function($) {
|
||||
return this.get(module, key, defaultVal) === true;
|
||||
},
|
||||
|
||||
set : function(module, key, value) {
|
||||
set : function(moduleId, key, value) {
|
||||
//Moduleid with multiple values
|
||||
if(arguments.length === 1) {
|
||||
var that = this;
|
||||
$.each(module, function(moduleKey, config) {
|
||||
that.set(module, config);
|
||||
$.each(moduleId, function(moduleKey, config) {
|
||||
that.set(moduleKey, config);
|
||||
});
|
||||
}else if(arguments.length === 2) {
|
||||
$.extend(this.getModuleConfig(module), key);
|
||||
$.extend(this.getModuleConfig(moduleId), key);
|
||||
} else if(arguments.length === 3) {
|
||||
this.getModuleConfig(module)[key] = value;
|
||||
this.getModuleConfig(moduleId)[key] = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -909,7 +909,101 @@ humhub.initModule('actions', function (module, require, $) {
|
||||
var object = require('util').object;
|
||||
var string = require('util').string;
|
||||
var client = require('client');
|
||||
|
||||
var DATA_COMPONENT = 'action-component';
|
||||
var DATA_COMPONENT_SELECTOR = '[data-'+DATA_COMPONENT+']';
|
||||
|
||||
var Component = function(container) {
|
||||
if(!container) {
|
||||
return;
|
||||
}
|
||||
this.$ = (object.isString(container)) ? $('#' + container) : container;
|
||||
this.base = this.$.data(DATA_COMPONENT);
|
||||
};
|
||||
|
||||
Component.prototype.data = function(dataSuffix) {
|
||||
var result = this.$.data(dataSuffix);
|
||||
if(!result) {
|
||||
var parentComponent = this.parent();
|
||||
if(parentComponent) {
|
||||
return parentComponent.data(dataSuffix);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Component.prototype.parent = function() {
|
||||
var $parent = this.$.parent().closest(DATA_COMPONENT_SELECTOR);
|
||||
if($parent.length) {
|
||||
try {
|
||||
var ParentType = require($parent.data(DATA_COMPONENT));
|
||||
return new ParentType($parent);
|
||||
} catch(err) {
|
||||
console.error('Could not instantiate parent component: '+$parent.data(DATA_COMPONENT));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Component.prototype.children = function() {
|
||||
var result = [];
|
||||
this.$.find(DATA_COMPONENT_SELECTOR).each(function() {
|
||||
var component = Component.getInstance($(this));
|
||||
if(component) {
|
||||
result.push(component);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
Component.prototype.hasAction = function(action) {
|
||||
return this.actions().indexOf(action) >= 0;
|
||||
};
|
||||
|
||||
Component.prototype.actions = function() {
|
||||
return [];
|
||||
};
|
||||
|
||||
Component.getInstance = function($node) {
|
||||
//Determine closest component node (parent or or given node)
|
||||
$node = (object.isString($node)) ? $('#'+$node) : $node;
|
||||
var $componentRoot = ($node.data(DATA_COMPONENT)) ? $node : Component.getClosestComponentNode($node);
|
||||
|
||||
var componentType = $componentRoot.data(DATA_COMPONENT);
|
||||
|
||||
var ComponentType = require(componentType);
|
||||
if(ComponentType) {
|
||||
return new ComponentType($componentRoot);
|
||||
} else {
|
||||
console.error('Tried to instantiate component with invalid type: '+componentType);
|
||||
}
|
||||
};
|
||||
|
||||
Component.getClosestComponentNode = function($element) {
|
||||
return $element.closest(DATA_COMPONENT_SELECTOR);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the given componentAction event. The event should provide the following properties:
|
||||
*
|
||||
* $trigger (required) : the trigger node of the event
|
||||
* handler (required) : the handler functionn name to be executed on the component
|
||||
* type (optoinal) : the event type 'click', 'change',...
|
||||
*
|
||||
* @param {object} event - event object
|
||||
* @returns {Boolean} true if the componentAction could be executed else false
|
||||
*/
|
||||
Component.handleAction = function(event) {
|
||||
var component = Component.getInstance(event.$trigger);
|
||||
if(component) {
|
||||
//Check if the content instance provides this actionhandler
|
||||
if(event.handler && component[event.handler]) {
|
||||
component[event.handler](event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for initializing the module.
|
||||
*/
|
||||
@ -1029,19 +1123,33 @@ humhub.initModule('actions', function (module, require, $) {
|
||||
|
||||
//Search and execute a stand alone handler or try to call the content action handler
|
||||
try {
|
||||
//Direct action handler
|
||||
if(object.isFunction(directHandler)) {
|
||||
//Direct action handler
|
||||
directHandler.apply($trigger, [event]);
|
||||
} else if (_handler[handlerId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Component handler
|
||||
if(Component.handleAction(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Registered handler
|
||||
if(_handler[handlerId]) {
|
||||
//Registered action handler
|
||||
var handler = _handler[handlerId];
|
||||
handler.apply($trigger, [event]);
|
||||
} else if (!_handler['humhub.modules.content.actiontHandler'](event)) { //Content action handler
|
||||
//If the content handler did not accept this event we try to find a handler by namespace
|
||||
var splittedNS = handlerId.split('.');
|
||||
var handler = splittedNS[splittedNS.length - 1];
|
||||
var target = require(string.cutsuffix(handlerId, '.' + handler));
|
||||
target[handler]({type: type, $trigger: $trigger});
|
||||
return;
|
||||
}
|
||||
|
||||
//As last resort we try to call the action by namespace handler
|
||||
var splittedNS = handlerId.split('.');
|
||||
var handler = splittedNS[splittedNS.length - 1];
|
||||
var target = require(string.cutsuffix(handlerId, '.' + handler));
|
||||
if(object.isFunction(target)) {
|
||||
target[handler]({type: type, $trigger: $trigger});
|
||||
} else {
|
||||
console.error('Could not determine actionhandler for: '+handlerId);
|
||||
}
|
||||
} catch (e) {
|
||||
//TODO: handle error !
|
||||
@ -1061,6 +1169,10 @@ humhub.initModule('actions', function (module, require, $) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.export({
|
||||
Component: Component
|
||||
});
|
||||
});;/**
|
||||
* This module provides an api for handling content objects e.g. Posts, Polls...
|
||||
*
|
||||
@ -1071,49 +1183,31 @@ humhub.initModule('content', function(module, require, $) {
|
||||
var client = require('client');
|
||||
var object = require('util').object;
|
||||
var actions = require('actions');
|
||||
var Component = actions.Component;
|
||||
|
||||
var DATA_CONTENT_KEY = "content-key";
|
||||
var DATA_CONTENT_EDIT_URL = "content-edit-url";
|
||||
var DATA_CONTENT_SAVE_SELECTOR = "[data-content-save]";
|
||||
var DATA_CONTENT_DELETE_URL = "content-delete-url";
|
||||
|
||||
|
||||
var Content = function(container) {
|
||||
if(!container) { //Create content
|
||||
return;
|
||||
}
|
||||
this.$ = (object.isString(container)) ? $('#' + container) : container;
|
||||
this.contentBase = this.$.data('content-base');
|
||||
Component.call(this, container);
|
||||
};
|
||||
|
||||
Content.prototype.getContentActions = function() {
|
||||
object.inherits(Content, Component);
|
||||
|
||||
Content.prototype.actions = function() {
|
||||
return ['create','edit','delete'];
|
||||
};
|
||||
|
||||
Content.prototype.getKey = function () {
|
||||
return this.$.data('content-pk');
|
||||
};
|
||||
|
||||
Content.prototype.data = function(dataSuffix) {
|
||||
var result = this.$.data(dataSuffix);
|
||||
if(!result) {
|
||||
var parentContent = this.getParentContentBase();
|
||||
if(parentContent) {
|
||||
return parentContent.data(dataSuffix);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Content.prototype.getParentContentBase = function() {
|
||||
var $parent = this.$.parent().closest('[data-content-base]');
|
||||
if($parent.length) {
|
||||
try {
|
||||
var ParentType = require($parent.data('content-base'));
|
||||
return new ParentType($parent);
|
||||
} catch(err) {
|
||||
console.error('Could not instantiate parent content base: '+$parent.data('content-base'));
|
||||
}
|
||||
}
|
||||
return this.$.data(DATA_CONTENT_KEY);
|
||||
};
|
||||
|
||||
Content.prototype.create = function (addContentHandler) {
|
||||
//Note that this Content won't have an id, so the backend will create an instance
|
||||
if(indexOf(this.getContentActions(), 'create') < 0) {
|
||||
if(this.hasAction('create')) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1121,11 +1215,11 @@ humhub.initModule('content', function(module, require, $) {
|
||||
};
|
||||
|
||||
Content.prototype.edit = function (successHandler) {
|
||||
if(indexOf(this.getContentActions(), 'edit') < 0) {
|
||||
if(!this.hasAction('edit')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var editUrl = this.data('content-edit-url');
|
||||
var editUrl = this.data(DATA_CONTENT_EDIT_URL);
|
||||
var contentId = this.getKey();
|
||||
var modal = require('ui.modal').global;
|
||||
|
||||
@ -1148,7 +1242,7 @@ humhub.initModule('content', function(module, require, $) {
|
||||
//Successfully retrieved the edit form, now show it within a modal
|
||||
modal.content(response.getContent(), function() {
|
||||
//Bind direct action handler we could use a global registeredHandler but this is more efficient
|
||||
actions.bindAction(modal.getBody(), 'click', '[data-content-save]', function(event) {
|
||||
actions.bindAction(modal.getBody(), 'click', DATA_CONTENT_SAVE_SELECTOR, function(event) {
|
||||
client.submit(modal.getForm(), {
|
||||
success : function(response) {
|
||||
if(object.isFunction(successHandler)) {
|
||||
@ -1179,14 +1273,14 @@ humhub.initModule('content', function(module, require, $) {
|
||||
};
|
||||
|
||||
Content.prototype.delete = function () {
|
||||
if(this.getContentActions().indexOf('delete') < 0) {
|
||||
if(!this.hasAction('delete')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
require('ui.modal').confirm({
|
||||
confirm : function() {
|
||||
var url = that.data('content-delete-url');
|
||||
var url = that.data(DATA_CONTENT_DELETE_URL);
|
||||
if(url) {
|
||||
client.post(url, {
|
||||
data: {
|
||||
@ -1198,7 +1292,7 @@ humhub.initModule('content', function(module, require, $) {
|
||||
console.error('Error removing content',err);
|
||||
});
|
||||
} else {
|
||||
console.error('Content delete was called, but no url could be determined for '+this.contentBase);
|
||||
console.error('Content delete was called, but no url could be determined for '+this.base);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1206,21 +1300,6 @@ humhub.initModule('content', function(module, require, $) {
|
||||
return;
|
||||
};
|
||||
|
||||
Content.prototype.replaceContent = function(content) {
|
||||
try {
|
||||
var that = this;
|
||||
this.$.animate({ opacity: 0 }, 'fast', function() {
|
||||
that.$.html($(content).children());
|
||||
that.$.stop().animate({ opacity: 1 }, 'fast');
|
||||
if(that.highlight) {
|
||||
that.highlight();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
console.error('Error occured while replacing content: '+this.$.attr('id') , e);
|
||||
}
|
||||
};
|
||||
|
||||
Content.prototype.remove = function() {
|
||||
var that = this;
|
||||
this.$.animate({ height: 'toggle', opacity: 'toggle' }, 'fast', function() {
|
||||
@ -1229,62 +1308,8 @@ humhub.initModule('content', function(module, require, $) {
|
||||
});
|
||||
};
|
||||
|
||||
Content.getContentBase = function($element) {
|
||||
return $element.closest('[data-content-base]');
|
||||
};
|
||||
|
||||
Content.getInstance = function($contentBase) {
|
||||
$contentBase = (object.isString($contentBase)) ? $('#'+$contentBase) : $contentBase;
|
||||
var contentTypePath = $contentBase.data('content-base');
|
||||
|
||||
if(!contentTypePath) {
|
||||
return;
|
||||
|
||||
}
|
||||
var ContentType = require(contentTypePath);
|
||||
if(ContentType) {
|
||||
return new ContentType($contentBase);
|
||||
}
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
actions.registerHandler('humhub.modules.content.actiontHandler', function(event) {
|
||||
return module.handleAction(event);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the given contentAction event. The event should provide the following properties:
|
||||
*
|
||||
* $trigger (required) : the trigger node of the event
|
||||
* handler (required) : the handler functionn name to be executed on the content
|
||||
* type (optoinal) : the event type 'click', 'change',...
|
||||
*
|
||||
* @param {object} event - event object
|
||||
* @returns {Boolean} true if the contentAction could be executed else false
|
||||
*/
|
||||
handleAction = function(event) {
|
||||
var $contentBase = Content.getContentBase(event.$trigger);
|
||||
if($contentBase.length) {
|
||||
//Initialize a content instance by means of the content-base type and execute the handler
|
||||
var content = Content.getInstance($contentBase);
|
||||
if(content) {
|
||||
//Check if the content instance provides this actionhandler
|
||||
if(event.handler && content[event.handler]) {
|
||||
content[event.handler](event);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
console.error('No ContentType found for '+$contentBase.data('content-base'));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
module.export({
|
||||
Content : Content,
|
||||
init : init,
|
||||
handleAction: handleAction
|
||||
Content : Content
|
||||
});
|
||||
});;/**
|
||||
* Core module for managing Streams and StreamItems
|
||||
@ -1298,31 +1323,60 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
var client = require('client');
|
||||
var Content = require('content').Content;
|
||||
|
||||
/**
|
||||
* Number of initial stream enteis loaded when stream is initialized.
|
||||
* @type Number
|
||||
*/
|
||||
var STREAM_INIT_COUNT = 8;
|
||||
|
||||
/**
|
||||
* Number of stream entries loaded with each request (except initial request)
|
||||
* @type Number
|
||||
*/
|
||||
var STREAM_LOAD_COUNT = 4;
|
||||
|
||||
/**
|
||||
* Set on the stream root node to identify a stream. The value of this data
|
||||
* attribute contains the stream url for loading new entries.
|
||||
* @type String
|
||||
*/
|
||||
var DATA_STREAM_SELECTOR = '[data-stream]';
|
||||
|
||||
/**
|
||||
* Set on a stream entry root node to identify stream-entries.
|
||||
* @type String
|
||||
*/
|
||||
var DATA_STREAM_ENTRY_SELECTOR = '[data-stream-entry]';
|
||||
|
||||
/**
|
||||
* If a data-stream-contentid is set on the stream root only one entry will
|
||||
* be loaded. e.g. for permlinks
|
||||
* @type String
|
||||
*/
|
||||
var DATA_STREAM_CONTENTID = 'stream-contentid';
|
||||
|
||||
|
||||
//TODO: load streamUrl from config
|
||||
//TODO: readonly
|
||||
|
||||
/**
|
||||
* Base class for all StreamContent
|
||||
* Represents an stream entry within a stream.
|
||||
* @param {type} id
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var StreamEntry = function (id) {
|
||||
this.$ = object.isString(id) ? this.$ = $('#' + id) : id;
|
||||
Content.call(this);
|
||||
Content.call(this, id);
|
||||
};
|
||||
|
||||
|
||||
object.inherits(StreamEntry, Content);
|
||||
|
||||
StreamEntry.prototype.getContentActions = function() {
|
||||
|
||||
StreamEntry.prototype.actions = function () {
|
||||
return ['delete', 'edit'];
|
||||
};
|
||||
|
||||
|
||||
StreamEntry.prototype.delete = function () {
|
||||
var content = this.getContentInstance();
|
||||
if(content && content.delete) {
|
||||
var content = this.getContentComponent();
|
||||
if (content && content.delete) {
|
||||
//TODO: modalconfirm
|
||||
content.delete();
|
||||
} else {
|
||||
@ -1330,20 +1384,21 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
}
|
||||
};
|
||||
|
||||
StreamEntry.prototype.getContentComponent = function () {
|
||||
var children = this.children();
|
||||
return children.length ? children[0] : undefined;
|
||||
};
|
||||
|
||||
StreamEntry.prototype.reload = function () {
|
||||
getStream().reload(this);
|
||||
};
|
||||
|
||||
StreamEntry.prototype.edit = function () {
|
||||
//Search for data-content-edit-url on root.
|
||||
//Call this url with data-content-pk
|
||||
//Call this url with data-content-key
|
||||
//Trigger delete event
|
||||
};
|
||||
|
||||
StreamEntry.prototype.getContentInstance = function () {
|
||||
return Content.getInstance(this.$.find('[data-content-base]'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Stream implementation.
|
||||
*
|
||||
@ -1351,19 +1406,15 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var Stream = function (container) {
|
||||
this.$ = (object.isString(container)) ? $('#' + container) : container;
|
||||
|
||||
if (!this.$.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
Content.call(this, container);
|
||||
|
||||
//If a contentId is set on the stream root we will only show the single content
|
||||
if(this.$.data('stream-contentid')) {
|
||||
this.contentId = parseInt(this.$.data('stream-contentid'));
|
||||
if (this.$.data(DATA_STREAM_CONTENTID)) {
|
||||
this.contentId = parseInt(this.$.data(DATA_STREAM_CONTENTID));
|
||||
}
|
||||
|
||||
|
||||
this.$stream = this.$.find(".s2_stream");
|
||||
|
||||
|
||||
//Cache some stream relevant data/nodes
|
||||
this.url = this.$.data('stream'); //TODO: set this in config instead of data field
|
||||
this.$loader = this.$stream.find(".streamLoader");
|
||||
@ -1373,16 +1424,14 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
//TODO: make this configurable
|
||||
this.filters = [];
|
||||
this.sort = "c";
|
||||
|
||||
Content.call(this);
|
||||
};
|
||||
|
||||
|
||||
object.inherits(Stream, Content);
|
||||
|
||||
Stream.prototype.getContentActions = function() {
|
||||
|
||||
Stream.prototype.getContentActions = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the stream, by clearing the stream and reloading initial stream entries,
|
||||
* this should be called if any filter/sort settings are changed or the stream
|
||||
@ -1400,9 +1449,9 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Stream.prototype.clear = function() {
|
||||
this.lastEntryLoaded = false;
|
||||
|
||||
Stream.prototype.clear = function () {
|
||||
this.lastEntryLoaded = false;
|
||||
this.readOnly = false;
|
||||
this.loading = false;
|
||||
this.$.find(".s2_streamContent").empty();
|
||||
@ -1415,34 +1464,34 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
this.$filter.hide();
|
||||
};
|
||||
|
||||
Stream.prototype.loadSingleEntry = function(contentId) {
|
||||
Stream.prototype.loadSingleEntry = function (contentId) {
|
||||
this.$.find('.back_button_holder').show();
|
||||
this.loadEntries(1, (contentId + 1), '');
|
||||
};
|
||||
|
||||
Stream.prototype.reloadEntry = function(entry) {
|
||||
|
||||
Stream.prototype.reloadEntry = function (entry) {
|
||||
var that = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
entry = (entry instanceof StreamEntry) ? entry : that.getEntry(entry);
|
||||
|
||||
if(!entry) {
|
||||
console.warn('Attempt to reload of non existent entry: '+entry);
|
||||
return new Promise(function (resolve, reject) {
|
||||
entry = (entry instanceof StreamEntry) ? entry : that.getEntry(entry);
|
||||
|
||||
if (!entry) {
|
||||
console.warn('Attempt to reload of non existent entry: ' + entry);
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
var contentId = entry.getKey();
|
||||
return that._load(1, (contentId + 1), '').then(function(response) {
|
||||
if(response.content[contentId]) {
|
||||
entry.replaceContent(response.content[contentId].output);
|
||||
resolve(entry);
|
||||
} else {
|
||||
console.warn('Reload failed: ContentId not found in response: '+contentId);
|
||||
reject();
|
||||
}
|
||||
}, reject);
|
||||
return that._load(1, (contentId + 1), '').then(function (response) {
|
||||
if (response.content[contentId]) {
|
||||
entry.replaceContent(response.content[contentId].output);
|
||||
resolve(entry);
|
||||
} else {
|
||||
console.warn('Reload failed: ContentId not found in response: ' + contentId);
|
||||
reject();
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
Stream.prototype.loadEntries = function (limit, from, filter, sort) {
|
||||
if (this.loading || this.lastEntryLoaded) {
|
||||
@ -1454,14 +1503,14 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
this.loading = true;
|
||||
|
||||
//Overwrite the stream settings if provided
|
||||
limit = limit || STREAM_LOAD_COUNT;
|
||||
from = from || this.getLastContentId();
|
||||
filter = filter || this.getFilterString();
|
||||
sort = sort || this.sort;
|
||||
|
||||
limit = limit || STREAM_LOAD_COUNT;
|
||||
from = from || this.getLastContentId();
|
||||
filter = filter || this.getFilterString();
|
||||
sort = sort || this.sort;
|
||||
|
||||
var that = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
that._load(limit, from, filter,sort).then(function(response) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
that._load(limit, from, filter, sort).then(function (response) {
|
||||
that.$loader.hide();
|
||||
if (object.isEmpty(response.content)) {
|
||||
that.lastEntryLoaded = true;
|
||||
@ -1470,11 +1519,11 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
that.lastEntryLoaded = response.is_last;
|
||||
that.appendEntries(response);
|
||||
}
|
||||
|
||||
|
||||
that.loading = false;
|
||||
that.onChange();
|
||||
resolve();
|
||||
}).catch(function(err) {
|
||||
}).catch(function (err) {
|
||||
//TODO: handle error
|
||||
that.loading = false;
|
||||
that.$loader.hide();
|
||||
@ -1482,7 +1531,7 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype._load = function (limit, from, filter, sort) {
|
||||
return client.ajax(this.url, {
|
||||
data: {
|
||||
@ -1495,9 +1544,9 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
};
|
||||
|
||||
Stream.prototype.getLastContentId = function () {
|
||||
var $lastEntry = this.$stream.find('[data-content-pk]').last();
|
||||
var $lastEntry = this.$stream.find(DATA_STREAM_ENTRY_SELECTOR).last();
|
||||
if ($lastEntry.length) {
|
||||
return $lastEntry.data('stream-contentid');
|
||||
return $lastEntry.data(DATA_STREAM_CONTENTID);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1505,7 +1554,7 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
var that = this;
|
||||
var result = '';
|
||||
$.each(response.contentIds, function (i, key) {
|
||||
var $entry = that.$.find('[data-content-pk="' + key + '"]');
|
||||
var $entry = that.getEntry(key);
|
||||
if ($entry.length) {
|
||||
$entry.remove();
|
||||
}
|
||||
@ -1531,15 +1580,17 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
this.$filter.hide();
|
||||
} else if (!hasEntries) {
|
||||
this.$.find('.emptyFilterStreamMessage').hide();
|
||||
} else if(!this.isShowSingleEntry()) {
|
||||
} else if (!this.isShowSingleEntry()) {
|
||||
this.$filter.show();
|
||||
this.$.find('.emptyStreamMessage').hide();
|
||||
this.$.find('.emptyFilterStreamMessage').hide();
|
||||
}
|
||||
|
||||
this.$entryCache = this.getEntryNodes();
|
||||
|
||||
//TODO: fire global event
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.isShowSingleEntry = function () {
|
||||
return object.isDefined(this.contentId);
|
||||
};
|
||||
@ -1549,46 +1600,50 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
};
|
||||
|
||||
Stream.prototype.getEntryCount = function () {
|
||||
return this.$.find('[data-content-pk]').length;
|
||||
return this.$.find(DATA_STREAM_ENTRY_SELECTOR).length;
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.getEntryNodes = function () {
|
||||
return this.$.find(DATA_STREAM_ENTRY_SELECTOR);
|
||||
};
|
||||
|
||||
Stream.prototype.hasFilter = function () {
|
||||
return this.filters.length > 0;
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.getFilterString = function () {
|
||||
var result = '';
|
||||
$.each(this.filters, function(i, filter) {
|
||||
result += filter+',';
|
||||
$.each(this.filters, function (i, filter) {
|
||||
result += filter + ',';
|
||||
});
|
||||
|
||||
|
||||
return string.cutsuffix(result, ',');
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.setFilter = function (filterId) {
|
||||
if(this.filters.indexOf(filterId) < 0) {
|
||||
if (this.filters.indexOf(filterId) < 0) {
|
||||
this.filters.push(filterId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.unsetFilter = function (filterId) {
|
||||
var index = this.filters.indexOf(filterId);
|
||||
if(index > -1) {
|
||||
if (index > -1) {
|
||||
this.filters.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
Stream.prototype.getEntry = function(key) {
|
||||
return new StreamEntry(this.$.find('[data-content-pk="' + key + '"]'));
|
||||
Stream.prototype.getEntry = function (key) {
|
||||
return new StreamEntry(this.$.find(DATA_STREAM_ENTRY_SELECTOR+'[data-content-key="' + key + '"]'));
|
||||
};
|
||||
|
||||
Stream.prototype.getEntryByNode = function($childNode) {
|
||||
return new StreamEntry($childNode.closest('[data-content-pk]'));
|
||||
|
||||
Stream.prototype.getEntryByNode = function ($childNode) {
|
||||
return new StreamEntry($childNode.closest(DATA_STREAM_ENTRY_SELECTOR));
|
||||
};
|
||||
|
||||
var getStream = function () {
|
||||
if (!module.instance) {
|
||||
var $stream = $('[data-stream]').first();
|
||||
var $stream = $(DATA_STREAM_SELECTOR).first();
|
||||
module.instance = $stream.length ? new Stream($stream) : undefined;
|
||||
}
|
||||
return module.instance;
|
||||
@ -1600,37 +1655,63 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
|
||||
var init = function () {
|
||||
var stream = getStream();
|
||||
|
||||
if(!stream) {
|
||||
|
||||
if (!stream) {
|
||||
console.log('Non-Stream Page!');
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream.init();
|
||||
|
||||
|
||||
var lastKey;
|
||||
$(window).scroll(function () {
|
||||
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
|
||||
var $window = $(window);
|
||||
var scrollTop = $window.scrollTop();
|
||||
var windowHeight = $window.height();
|
||||
if (scrollTop === ($(document).height() - $window.height())) {
|
||||
if (stream && !stream.loading && !stream.isShowSingleEntry() && !stream.lastEntryLoaded) {
|
||||
stream.loadEntries();
|
||||
}
|
||||
}
|
||||
|
||||
// Defines our base y position for changing the current entry
|
||||
var yLimit = scrollTop + (windowHeight / 2);
|
||||
|
||||
// Get id of current scroll item
|
||||
//TODO: chache the entry nodes !
|
||||
var matchingNodes = stream.$entryCache.map(function () {
|
||||
var $this = $(this);
|
||||
if ($this.offset().top < yLimit) {
|
||||
return $this;
|
||||
}
|
||||
});
|
||||
|
||||
// Get the id of the current element
|
||||
var $current = matchingNodes[matchingNodes.length - 1];
|
||||
var currentKey = $current && $current.length ? $current.data('content-key') : "";
|
||||
|
||||
if (lastKey !== currentKey) {
|
||||
lastKey = currentKey;
|
||||
// Set/remove active class
|
||||
console.log(currentKey);
|
||||
}
|
||||
});
|
||||
|
||||
stream.$.on('click', '.singleBackLink', function() {
|
||||
|
||||
stream.$.on('click', '.singleBackLink', function () {
|
||||
stream.contentId = undefined;
|
||||
stream.init();
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
|
||||
initFilterNav();
|
||||
};
|
||||
|
||||
var initFilterNav = function() {
|
||||
var initFilterNav = function () {
|
||||
$(".wallFilter").click(function () {
|
||||
var $filter = $(this);
|
||||
var checkboxi = $filter.children("i");
|
||||
checkboxi.toggleClass('fa-square-o').toggleClass('fa-check-square-o');
|
||||
if(checkboxi.hasClass('fa-check-square-o')) {
|
||||
if (checkboxi.hasClass('fa-check-square-o')) {
|
||||
getStream().setFilter($filter.attr('id').replace('filter_', ''));
|
||||
} else {
|
||||
getStream().unsetFilter($filter.attr('id').replace('filter_', ''));
|
||||
@ -1641,7 +1722,7 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
$(".wallSorting").click(function () {
|
||||
var newSortingMode = $(this).attr('id');
|
||||
|
||||
// uncheck all sorting
|
||||
// uncheck all sortings
|
||||
$(".wallSorting").find('i')
|
||||
.removeClass('fa-check-square-o')
|
||||
.addClass('fa-square-o');
|
||||
|
2
js/dist/humhub.all.min.js
vendored
2
js/dist/humhub.all.min.js
vendored
File diff suppressed because one or more lines are too long
@ -7,7 +7,101 @@ humhub.initModule('actions', function (module, require, $) {
|
||||
var object = require('util').object;
|
||||
var string = require('util').string;
|
||||
var client = require('client');
|
||||
|
||||
var DATA_COMPONENT = 'action-component';
|
||||
var DATA_COMPONENT_SELECTOR = '[data-'+DATA_COMPONENT+']';
|
||||
|
||||
var Component = function(container) {
|
||||
if(!container) {
|
||||
return;
|
||||
}
|
||||
this.$ = (object.isString(container)) ? $('#' + container) : container;
|
||||
this.base = this.$.data(DATA_COMPONENT);
|
||||
};
|
||||
|
||||
Component.prototype.data = function(dataSuffix) {
|
||||
var result = this.$.data(dataSuffix);
|
||||
if(!result) {
|
||||
var parentComponent = this.parent();
|
||||
if(parentComponent) {
|
||||
return parentComponent.data(dataSuffix);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Component.prototype.parent = function() {
|
||||
var $parent = this.$.parent().closest(DATA_COMPONENT_SELECTOR);
|
||||
if($parent.length) {
|
||||
try {
|
||||
var ParentType = require($parent.data(DATA_COMPONENT));
|
||||
return new ParentType($parent);
|
||||
} catch(err) {
|
||||
console.error('Could not instantiate parent component: '+$parent.data(DATA_COMPONENT));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Component.prototype.children = function() {
|
||||
var result = [];
|
||||
this.$.find(DATA_COMPONENT_SELECTOR).each(function() {
|
||||
var component = Component.getInstance($(this));
|
||||
if(component) {
|
||||
result.push(component);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
Component.prototype.hasAction = function(action) {
|
||||
return this.actions().indexOf(action) >= 0;
|
||||
};
|
||||
|
||||
Component.prototype.actions = function() {
|
||||
return [];
|
||||
};
|
||||
|
||||
Component.getInstance = function($node) {
|
||||
//Determine closest component node (parent or or given node)
|
||||
$node = (object.isString($node)) ? $('#'+$node) : $node;
|
||||
var $componentRoot = ($node.data(DATA_COMPONENT)) ? $node : Component.getClosestComponentNode($node);
|
||||
|
||||
var componentType = $componentRoot.data(DATA_COMPONENT);
|
||||
|
||||
var ComponentType = require(componentType);
|
||||
if(ComponentType) {
|
||||
return new ComponentType($componentRoot);
|
||||
} else {
|
||||
console.error('Tried to instantiate component with invalid type: '+componentType);
|
||||
}
|
||||
};
|
||||
|
||||
Component.getClosestComponentNode = function($element) {
|
||||
return $element.closest(DATA_COMPONENT_SELECTOR);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the given componentAction event. The event should provide the following properties:
|
||||
*
|
||||
* $trigger (required) : the trigger node of the event
|
||||
* handler (required) : the handler functionn name to be executed on the component
|
||||
* type (optoinal) : the event type 'click', 'change',...
|
||||
*
|
||||
* @param {object} event - event object
|
||||
* @returns {Boolean} true if the componentAction could be executed else false
|
||||
*/
|
||||
Component.handleAction = function(event) {
|
||||
var component = Component.getInstance(event.$trigger);
|
||||
if(component) {
|
||||
//Check if the content instance provides this actionhandler
|
||||
if(event.handler && component[event.handler]) {
|
||||
component[event.handler](event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for initializing the module.
|
||||
*/
|
||||
@ -127,19 +221,33 @@ humhub.initModule('actions', function (module, require, $) {
|
||||
|
||||
//Search and execute a stand alone handler or try to call the content action handler
|
||||
try {
|
||||
//Direct action handler
|
||||
if(object.isFunction(directHandler)) {
|
||||
//Direct action handler
|
||||
directHandler.apply($trigger, [event]);
|
||||
} else if (_handler[handlerId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Component handler
|
||||
if(Component.handleAction(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Registered handler
|
||||
if(_handler[handlerId]) {
|
||||
//Registered action handler
|
||||
var handler = _handler[handlerId];
|
||||
handler.apply($trigger, [event]);
|
||||
} else if (!_handler['humhub.modules.content.actiontHandler'](event)) { //Content action handler
|
||||
//If the content handler did not accept this event we try to find a handler by namespace
|
||||
var splittedNS = handlerId.split('.');
|
||||
var handler = splittedNS[splittedNS.length - 1];
|
||||
var target = require(string.cutsuffix(handlerId, '.' + handler));
|
||||
target[handler]({type: type, $trigger: $trigger});
|
||||
return;
|
||||
}
|
||||
|
||||
//As last resort we try to call the action by namespace handler
|
||||
var splittedNS = handlerId.split('.');
|
||||
var handler = splittedNS[splittedNS.length - 1];
|
||||
var target = require(string.cutsuffix(handlerId, '.' + handler));
|
||||
if(object.isFunction(target)) {
|
||||
target[handler]({type: type, $trigger: $trigger});
|
||||
} else {
|
||||
console.error('Could not determine actionhandler for: '+handlerId);
|
||||
}
|
||||
} catch (e) {
|
||||
//TODO: handle error !
|
||||
@ -159,4 +267,8 @@ humhub.initModule('actions', function (module, require, $) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.export({
|
||||
Component: Component
|
||||
});
|
||||
});
|
@ -8,49 +8,31 @@ humhub.initModule('content', function(module, require, $) {
|
||||
var client = require('client');
|
||||
var object = require('util').object;
|
||||
var actions = require('actions');
|
||||
var Component = actions.Component;
|
||||
|
||||
var DATA_CONTENT_KEY = "content-key";
|
||||
var DATA_CONTENT_EDIT_URL = "content-edit-url";
|
||||
var DATA_CONTENT_SAVE_SELECTOR = "[data-content-save]";
|
||||
var DATA_CONTENT_DELETE_URL = "content-delete-url";
|
||||
|
||||
|
||||
var Content = function(container) {
|
||||
if(!container) { //Create content
|
||||
return;
|
||||
}
|
||||
this.$ = (object.isString(container)) ? $('#' + container) : container;
|
||||
this.contentBase = this.$.data('content-base');
|
||||
Component.call(this, container);
|
||||
};
|
||||
|
||||
Content.prototype.getContentActions = function() {
|
||||
object.inherits(Content, Component);
|
||||
|
||||
Content.prototype.actions = function() {
|
||||
return ['create','edit','delete'];
|
||||
};
|
||||
|
||||
Content.prototype.getKey = function () {
|
||||
return this.$.data('content-pk');
|
||||
};
|
||||
|
||||
Content.prototype.data = function(dataSuffix) {
|
||||
var result = this.$.data(dataSuffix);
|
||||
if(!result) {
|
||||
var parentContent = this.getParentContentBase();
|
||||
if(parentContent) {
|
||||
return parentContent.data(dataSuffix);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Content.prototype.getParentContentBase = function() {
|
||||
var $parent = this.$.parent().closest('[data-content-base]');
|
||||
if($parent.length) {
|
||||
try {
|
||||
var ParentType = require($parent.data('content-base'));
|
||||
return new ParentType($parent);
|
||||
} catch(err) {
|
||||
console.error('Could not instantiate parent content base: '+$parent.data('content-base'));
|
||||
}
|
||||
}
|
||||
return this.$.data(DATA_CONTENT_KEY);
|
||||
};
|
||||
|
||||
Content.prototype.create = function (addContentHandler) {
|
||||
//Note that this Content won't have an id, so the backend will create an instance
|
||||
if(indexOf(this.getContentActions(), 'create') < 0) {
|
||||
if(this.hasAction('create')) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -58,11 +40,11 @@ humhub.initModule('content', function(module, require, $) {
|
||||
};
|
||||
|
||||
Content.prototype.edit = function (successHandler) {
|
||||
if(indexOf(this.getContentActions(), 'edit') < 0) {
|
||||
if(!this.hasAction('edit')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var editUrl = this.data('content-edit-url');
|
||||
var editUrl = this.data(DATA_CONTENT_EDIT_URL);
|
||||
var contentId = this.getKey();
|
||||
var modal = require('ui.modal').global;
|
||||
|
||||
@ -85,7 +67,7 @@ humhub.initModule('content', function(module, require, $) {
|
||||
//Successfully retrieved the edit form, now show it within a modal
|
||||
modal.content(response.getContent(), function() {
|
||||
//Bind direct action handler we could use a global registeredHandler but this is more efficient
|
||||
actions.bindAction(modal.getBody(), 'click', '[data-content-save]', function(event) {
|
||||
actions.bindAction(modal.getBody(), 'click', DATA_CONTENT_SAVE_SELECTOR, function(event) {
|
||||
client.submit(modal.getForm(), {
|
||||
success : function(response) {
|
||||
if(object.isFunction(successHandler)) {
|
||||
@ -116,14 +98,14 @@ humhub.initModule('content', function(module, require, $) {
|
||||
};
|
||||
|
||||
Content.prototype.delete = function () {
|
||||
if(this.getContentActions().indexOf('delete') < 0) {
|
||||
if(!this.hasAction('delete')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
require('ui.modal').confirm({
|
||||
confirm : function() {
|
||||
var url = that.data('content-delete-url');
|
||||
var url = that.data(DATA_CONTENT_DELETE_URL);
|
||||
if(url) {
|
||||
client.post(url, {
|
||||
data: {
|
||||
@ -135,7 +117,7 @@ humhub.initModule('content', function(module, require, $) {
|
||||
console.error('Error removing content',err);
|
||||
});
|
||||
} else {
|
||||
console.error('Content delete was called, but no url could be determined for '+this.contentBase);
|
||||
console.error('Content delete was called, but no url could be determined for '+this.base);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -143,21 +125,6 @@ humhub.initModule('content', function(module, require, $) {
|
||||
return;
|
||||
};
|
||||
|
||||
Content.prototype.replaceContent = function(content) {
|
||||
try {
|
||||
var that = this;
|
||||
this.$.animate({ opacity: 0 }, 'fast', function() {
|
||||
that.$.html($(content).children());
|
||||
that.$.stop().animate({ opacity: 1 }, 'fast');
|
||||
if(that.highlight) {
|
||||
that.highlight();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
console.error('Error occured while replacing content: '+this.$.attr('id') , e);
|
||||
}
|
||||
};
|
||||
|
||||
Content.prototype.remove = function() {
|
||||
var that = this;
|
||||
this.$.animate({ height: 'toggle', opacity: 'toggle' }, 'fast', function() {
|
||||
@ -166,61 +133,7 @@ humhub.initModule('content', function(module, require, $) {
|
||||
});
|
||||
};
|
||||
|
||||
Content.getContentBase = function($element) {
|
||||
return $element.closest('[data-content-base]');
|
||||
};
|
||||
|
||||
Content.getInstance = function($contentBase) {
|
||||
$contentBase = (object.isString($contentBase)) ? $('#'+$contentBase) : $contentBase;
|
||||
var contentTypePath = $contentBase.data('content-base');
|
||||
|
||||
if(!contentTypePath) {
|
||||
return;
|
||||
|
||||
}
|
||||
var ContentType = require(contentTypePath);
|
||||
if(ContentType) {
|
||||
return new ContentType($contentBase);
|
||||
}
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
actions.registerHandler('humhub.modules.content.actiontHandler', function(event) {
|
||||
return module.handleAction(event);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the given contentAction event. The event should provide the following properties:
|
||||
*
|
||||
* $trigger (required) : the trigger node of the event
|
||||
* handler (required) : the handler functionn name to be executed on the content
|
||||
* type (optoinal) : the event type 'click', 'change',...
|
||||
*
|
||||
* @param {object} event - event object
|
||||
* @returns {Boolean} true if the contentAction could be executed else false
|
||||
*/
|
||||
handleAction = function(event) {
|
||||
var $contentBase = Content.getContentBase(event.$trigger);
|
||||
if($contentBase.length) {
|
||||
//Initialize a content instance by means of the content-base type and execute the handler
|
||||
var content = Content.getInstance($contentBase);
|
||||
if(content) {
|
||||
//Check if the content instance provides this actionhandler
|
||||
if(event.handler && content[event.handler]) {
|
||||
content[event.handler](event);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
console.error('No ContentType found for '+$contentBase.data('content-base'));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
module.export({
|
||||
Content : Content,
|
||||
init : init,
|
||||
handleAction: handleAction
|
||||
Content : Content
|
||||
});
|
||||
});
|
@ -177,17 +177,17 @@ var humhub = humhub || (function($) {
|
||||
return this.get(module, key, defaultVal) === true;
|
||||
},
|
||||
|
||||
set : function(module, key, value) {
|
||||
set : function(moduleId, key, value) {
|
||||
//Moduleid with multiple values
|
||||
if(arguments.length === 1) {
|
||||
var that = this;
|
||||
$.each(module, function(moduleKey, config) {
|
||||
that.set(module, config);
|
||||
$.each(moduleId, function(moduleKey, config) {
|
||||
that.set(moduleKey, config);
|
||||
});
|
||||
}else if(arguments.length === 2) {
|
||||
$.extend(this.getModuleConfig(module), key);
|
||||
$.extend(this.getModuleConfig(moduleId), key);
|
||||
} else if(arguments.length === 3) {
|
||||
this.getModuleConfig(module)[key] = value;
|
||||
this.getModuleConfig(moduleId)[key] = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -10,31 +10,60 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
var client = require('client');
|
||||
var Content = require('content').Content;
|
||||
|
||||
/**
|
||||
* Number of initial stream enteis loaded when stream is initialized.
|
||||
* @type Number
|
||||
*/
|
||||
var STREAM_INIT_COUNT = 8;
|
||||
|
||||
/**
|
||||
* Number of stream entries loaded with each request (except initial request)
|
||||
* @type Number
|
||||
*/
|
||||
var STREAM_LOAD_COUNT = 4;
|
||||
|
||||
/**
|
||||
* Set on the stream root node to identify a stream. The value of this data
|
||||
* attribute contains the stream url for loading new entries.
|
||||
* @type String
|
||||
*/
|
||||
var DATA_STREAM_SELECTOR = '[data-stream]';
|
||||
|
||||
/**
|
||||
* Set on a stream entry root node to identify stream-entries.
|
||||
* @type String
|
||||
*/
|
||||
var DATA_STREAM_ENTRY_SELECTOR = '[data-stream-entry]';
|
||||
|
||||
/**
|
||||
* If a data-stream-contentid is set on the stream root only one entry will
|
||||
* be loaded. e.g. for permlinks
|
||||
* @type String
|
||||
*/
|
||||
var DATA_STREAM_CONTENTID = 'stream-contentid';
|
||||
|
||||
|
||||
//TODO: load streamUrl from config
|
||||
//TODO: readonly
|
||||
|
||||
/**
|
||||
* Base class for all StreamContent
|
||||
* Represents an stream entry within a stream.
|
||||
* @param {type} id
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var StreamEntry = function (id) {
|
||||
this.$ = object.isString(id) ? this.$ = $('#' + id) : id;
|
||||
Content.call(this);
|
||||
Content.call(this, id);
|
||||
};
|
||||
|
||||
|
||||
object.inherits(StreamEntry, Content);
|
||||
|
||||
StreamEntry.prototype.getContentActions = function() {
|
||||
|
||||
StreamEntry.prototype.actions = function () {
|
||||
return ['delete', 'edit'];
|
||||
};
|
||||
|
||||
|
||||
StreamEntry.prototype.delete = function () {
|
||||
var content = this.getContentInstance();
|
||||
if(content && content.delete) {
|
||||
var content = this.getContentComponent();
|
||||
if (content && content.delete) {
|
||||
//TODO: modalconfirm
|
||||
content.delete();
|
||||
} else {
|
||||
@ -42,20 +71,21 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
}
|
||||
};
|
||||
|
||||
StreamEntry.prototype.getContentComponent = function () {
|
||||
var children = this.children();
|
||||
return children.length ? children[0] : undefined;
|
||||
};
|
||||
|
||||
StreamEntry.prototype.reload = function () {
|
||||
getStream().reload(this);
|
||||
};
|
||||
|
||||
StreamEntry.prototype.edit = function () {
|
||||
//Search for data-content-edit-url on root.
|
||||
//Call this url with data-content-pk
|
||||
//Call this url with data-content-key
|
||||
//Trigger delete event
|
||||
};
|
||||
|
||||
StreamEntry.prototype.getContentInstance = function () {
|
||||
return Content.getInstance(this.$.find('[data-content-base]'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Stream implementation.
|
||||
*
|
||||
@ -63,19 +93,15 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
* @returns {undefined}
|
||||
*/
|
||||
var Stream = function (container) {
|
||||
this.$ = (object.isString(container)) ? $('#' + container) : container;
|
||||
|
||||
if (!this.$.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
Content.call(this, container);
|
||||
|
||||
//If a contentId is set on the stream root we will only show the single content
|
||||
if(this.$.data('stream-contentid')) {
|
||||
this.contentId = parseInt(this.$.data('stream-contentid'));
|
||||
if (this.$.data(DATA_STREAM_CONTENTID)) {
|
||||
this.contentId = parseInt(this.$.data(DATA_STREAM_CONTENTID));
|
||||
}
|
||||
|
||||
|
||||
this.$stream = this.$.find(".s2_stream");
|
||||
|
||||
|
||||
//Cache some stream relevant data/nodes
|
||||
this.url = this.$.data('stream'); //TODO: set this in config instead of data field
|
||||
this.$loader = this.$stream.find(".streamLoader");
|
||||
@ -85,16 +111,14 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
//TODO: make this configurable
|
||||
this.filters = [];
|
||||
this.sort = "c";
|
||||
|
||||
Content.call(this);
|
||||
};
|
||||
|
||||
|
||||
object.inherits(Stream, Content);
|
||||
|
||||
Stream.prototype.getContentActions = function() {
|
||||
|
||||
Stream.prototype.getContentActions = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the stream, by clearing the stream and reloading initial stream entries,
|
||||
* this should be called if any filter/sort settings are changed or the stream
|
||||
@ -112,9 +136,9 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Stream.prototype.clear = function() {
|
||||
this.lastEntryLoaded = false;
|
||||
|
||||
Stream.prototype.clear = function () {
|
||||
this.lastEntryLoaded = false;
|
||||
this.readOnly = false;
|
||||
this.loading = false;
|
||||
this.$.find(".s2_streamContent").empty();
|
||||
@ -127,34 +151,34 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
this.$filter.hide();
|
||||
};
|
||||
|
||||
Stream.prototype.loadSingleEntry = function(contentId) {
|
||||
Stream.prototype.loadSingleEntry = function (contentId) {
|
||||
this.$.find('.back_button_holder').show();
|
||||
this.loadEntries(1, (contentId + 1), '');
|
||||
};
|
||||
|
||||
Stream.prototype.reloadEntry = function(entry) {
|
||||
|
||||
Stream.prototype.reloadEntry = function (entry) {
|
||||
var that = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
entry = (entry instanceof StreamEntry) ? entry : that.getEntry(entry);
|
||||
|
||||
if(!entry) {
|
||||
console.warn('Attempt to reload of non existent entry: '+entry);
|
||||
return new Promise(function (resolve, reject) {
|
||||
entry = (entry instanceof StreamEntry) ? entry : that.getEntry(entry);
|
||||
|
||||
if (!entry) {
|
||||
console.warn('Attempt to reload of non existent entry: ' + entry);
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
var contentId = entry.getKey();
|
||||
return that._load(1, (contentId + 1), '').then(function(response) {
|
||||
if(response.content[contentId]) {
|
||||
entry.replaceContent(response.content[contentId].output);
|
||||
resolve(entry);
|
||||
} else {
|
||||
console.warn('Reload failed: ContentId not found in response: '+contentId);
|
||||
reject();
|
||||
}
|
||||
}, reject);
|
||||
return that._load(1, (contentId + 1), '').then(function (response) {
|
||||
if (response.content[contentId]) {
|
||||
entry.replaceContent(response.content[contentId].output);
|
||||
resolve(entry);
|
||||
} else {
|
||||
console.warn('Reload failed: ContentId not found in response: ' + contentId);
|
||||
reject();
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
Stream.prototype.loadEntries = function (limit, from, filter, sort) {
|
||||
if (this.loading || this.lastEntryLoaded) {
|
||||
@ -166,14 +190,14 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
this.loading = true;
|
||||
|
||||
//Overwrite the stream settings if provided
|
||||
limit = limit || STREAM_LOAD_COUNT;
|
||||
from = from || this.getLastContentId();
|
||||
filter = filter || this.getFilterString();
|
||||
sort = sort || this.sort;
|
||||
|
||||
limit = limit || STREAM_LOAD_COUNT;
|
||||
from = from || this.getLastContentId();
|
||||
filter = filter || this.getFilterString();
|
||||
sort = sort || this.sort;
|
||||
|
||||
var that = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
that._load(limit, from, filter,sort).then(function(response) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
that._load(limit, from, filter, sort).then(function (response) {
|
||||
that.$loader.hide();
|
||||
if (object.isEmpty(response.content)) {
|
||||
that.lastEntryLoaded = true;
|
||||
@ -182,11 +206,11 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
that.lastEntryLoaded = response.is_last;
|
||||
that.appendEntries(response);
|
||||
}
|
||||
|
||||
|
||||
that.loading = false;
|
||||
that.onChange();
|
||||
resolve();
|
||||
}).catch(function(err) {
|
||||
}).catch(function (err) {
|
||||
//TODO: handle error
|
||||
that.loading = false;
|
||||
that.$loader.hide();
|
||||
@ -194,7 +218,7 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype._load = function (limit, from, filter, sort) {
|
||||
return client.ajax(this.url, {
|
||||
data: {
|
||||
@ -207,9 +231,9 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
};
|
||||
|
||||
Stream.prototype.getLastContentId = function () {
|
||||
var $lastEntry = this.$stream.find('[data-content-pk]').last();
|
||||
var $lastEntry = this.$stream.find(DATA_STREAM_ENTRY_SELECTOR).last();
|
||||
if ($lastEntry.length) {
|
||||
return $lastEntry.data('stream-contentid');
|
||||
return $lastEntry.data(DATA_STREAM_CONTENTID);
|
||||
}
|
||||
};
|
||||
|
||||
@ -217,7 +241,7 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
var that = this;
|
||||
var result = '';
|
||||
$.each(response.contentIds, function (i, key) {
|
||||
var $entry = that.$.find('[data-content-pk="' + key + '"]');
|
||||
var $entry = that.getEntry(key);
|
||||
if ($entry.length) {
|
||||
$entry.remove();
|
||||
}
|
||||
@ -243,15 +267,17 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
this.$filter.hide();
|
||||
} else if (!hasEntries) {
|
||||
this.$.find('.emptyFilterStreamMessage').hide();
|
||||
} else if(!this.isShowSingleEntry()) {
|
||||
} else if (!this.isShowSingleEntry()) {
|
||||
this.$filter.show();
|
||||
this.$.find('.emptyStreamMessage').hide();
|
||||
this.$.find('.emptyFilterStreamMessage').hide();
|
||||
}
|
||||
|
||||
this.$entryCache = this.getEntryNodes();
|
||||
|
||||
//TODO: fire global event
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.isShowSingleEntry = function () {
|
||||
return object.isDefined(this.contentId);
|
||||
};
|
||||
@ -261,46 +287,50 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
};
|
||||
|
||||
Stream.prototype.getEntryCount = function () {
|
||||
return this.$.find('[data-content-pk]').length;
|
||||
return this.$.find(DATA_STREAM_ENTRY_SELECTOR).length;
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.getEntryNodes = function () {
|
||||
return this.$.find(DATA_STREAM_ENTRY_SELECTOR);
|
||||
};
|
||||
|
||||
Stream.prototype.hasFilter = function () {
|
||||
return this.filters.length > 0;
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.getFilterString = function () {
|
||||
var result = '';
|
||||
$.each(this.filters, function(i, filter) {
|
||||
result += filter+',';
|
||||
$.each(this.filters, function (i, filter) {
|
||||
result += filter + ',';
|
||||
});
|
||||
|
||||
|
||||
return string.cutsuffix(result, ',');
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.setFilter = function (filterId) {
|
||||
if(this.filters.indexOf(filterId) < 0) {
|
||||
if (this.filters.indexOf(filterId) < 0) {
|
||||
this.filters.push(filterId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Stream.prototype.unsetFilter = function (filterId) {
|
||||
var index = this.filters.indexOf(filterId);
|
||||
if(index > -1) {
|
||||
if (index > -1) {
|
||||
this.filters.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
Stream.prototype.getEntry = function(key) {
|
||||
return new StreamEntry(this.$.find('[data-content-pk="' + key + '"]'));
|
||||
Stream.prototype.getEntry = function (key) {
|
||||
return new StreamEntry(this.$.find(DATA_STREAM_ENTRY_SELECTOR+'[data-content-key="' + key + '"]'));
|
||||
};
|
||||
|
||||
Stream.prototype.getEntryByNode = function($childNode) {
|
||||
return new StreamEntry($childNode.closest('[data-content-pk]'));
|
||||
|
||||
Stream.prototype.getEntryByNode = function ($childNode) {
|
||||
return new StreamEntry($childNode.closest(DATA_STREAM_ENTRY_SELECTOR));
|
||||
};
|
||||
|
||||
var getStream = function () {
|
||||
if (!module.instance) {
|
||||
var $stream = $('[data-stream]').first();
|
||||
var $stream = $(DATA_STREAM_SELECTOR).first();
|
||||
module.instance = $stream.length ? new Stream($stream) : undefined;
|
||||
}
|
||||
return module.instance;
|
||||
@ -312,37 +342,63 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
|
||||
var init = function () {
|
||||
var stream = getStream();
|
||||
|
||||
if(!stream) {
|
||||
|
||||
if (!stream) {
|
||||
console.log('Non-Stream Page!');
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream.init();
|
||||
|
||||
|
||||
var lastKey;
|
||||
$(window).scroll(function () {
|
||||
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
|
||||
var $window = $(window);
|
||||
var scrollTop = $window.scrollTop();
|
||||
var windowHeight = $window.height();
|
||||
if (scrollTop === ($(document).height() - $window.height())) {
|
||||
if (stream && !stream.loading && !stream.isShowSingleEntry() && !stream.lastEntryLoaded) {
|
||||
stream.loadEntries();
|
||||
}
|
||||
}
|
||||
|
||||
// Defines our base y position for changing the current entry
|
||||
var yLimit = scrollTop + (windowHeight / 2);
|
||||
|
||||
// Get id of current scroll item
|
||||
//TODO: chache the entry nodes !
|
||||
var matchingNodes = stream.$entryCache.map(function () {
|
||||
var $this = $(this);
|
||||
if ($this.offset().top < yLimit) {
|
||||
return $this;
|
||||
}
|
||||
});
|
||||
|
||||
// Get the id of the current element
|
||||
var $current = matchingNodes[matchingNodes.length - 1];
|
||||
var currentKey = $current && $current.length ? $current.data('content-key') : "";
|
||||
|
||||
if (lastKey !== currentKey) {
|
||||
lastKey = currentKey;
|
||||
// Set/remove active class
|
||||
console.log(currentKey);
|
||||
}
|
||||
});
|
||||
|
||||
stream.$.on('click', '.singleBackLink', function() {
|
||||
|
||||
stream.$.on('click', '.singleBackLink', function () {
|
||||
stream.contentId = undefined;
|
||||
stream.init();
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
|
||||
initFilterNav();
|
||||
};
|
||||
|
||||
var initFilterNav = function() {
|
||||
var initFilterNav = function () {
|
||||
$(".wallFilter").click(function () {
|
||||
var $filter = $(this);
|
||||
var checkboxi = $filter.children("i");
|
||||
checkboxi.toggleClass('fa-square-o').toggleClass('fa-check-square-o');
|
||||
if(checkboxi.hasClass('fa-check-square-o')) {
|
||||
if (checkboxi.hasClass('fa-check-square-o')) {
|
||||
getStream().setFilter($filter.attr('id').replace('filter_', ''));
|
||||
} else {
|
||||
getStream().unsetFilter($filter.attr('id').replace('filter_', ''));
|
||||
@ -353,7 +409,7 @@ humhub.initModule('stream', function (module, require, $) {
|
||||
$(".wallSorting").click(function () {
|
||||
var newSortingMode = $(this).attr('id');
|
||||
|
||||
// uncheck all sorting
|
||||
// uncheck all sortings
|
||||
$(".wallSorting").find('i')
|
||||
.removeClass('fa-check-square-o')
|
||||
.addClass('fa-square-o');
|
||||
|
@ -4,6 +4,7 @@
|
||||
"grunt-contrib-clean": "^1.0.0",
|
||||
"grunt-contrib-concat": "^1.0.0",
|
||||
"grunt-contrib-uglify": "^1.0.1",
|
||||
"grunt-contrib-watch": "^1.0.0"
|
||||
"grunt-contrib-watch": "^1.0.0",
|
||||
"grunt-contrib-less": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
@ -211,11 +211,7 @@ action.registerAjaxHandler('humhub.modules.myModule.sendAjax', {
|
||||
}
|
||||
|
||||
//No need to call bindAction, since data-action-click nodes are bound automatically
|
||||
```
|
||||
> TIP: The action handler will determine the action url and execute the provides success/error handler automatically
|
||||
|
||||
> TIP: If you have multiple actions with different action urls you can specify `data-action-url-click`, `data-action-url-change`,...
|
||||
data-action-url is always used as fallback
|
||||
``
|
||||
|
||||
Example a `namepace-handler`:
|
||||
|
||||
@ -224,27 +220,32 @@ Example a `namepace-handler`:
|
||||
<button data-action-click="humhub.modules.myModule.myFunction">Do something !</button>
|
||||
```
|
||||
|
||||
> TIP: The action handler will determine the action url and execute the provides success/error handler automatically
|
||||
|
||||
> TIP: If you have multiple actions with different action urls you can specify `data-action-url-click`, `data-action-url-change`,...
|
||||
data-action-url is always used as fallback
|
||||
|
||||
> TIP: The action module binds some default actions like click, dbclick and change to nodes with a data-action-<type> attribute, so these event types do not have to be bound manually.
|
||||
|
||||
## Content
|
||||
### Components
|
||||
|
||||
One of the main tasks of HumHub is the manipulation (create/edit/delete) of content entries as posts, wikis and polls. The `humhub.modules.content` module provides a
|
||||
interface for representing and handling content entries on the frontend.
|
||||
|
||||
### Content Base
|
||||
|
||||
To mark a dom node as a container of content information you have to set a `data-content-base` attribute with the content class (e.g. `data-content-base="humhub.modules.tasks.Task"`).
|
||||
Nodes provided with this attribute are either container of content entries (e.g. a list of tasks) or a content entry itself (e.g. task). This makes it possible
|
||||
to cascade different types `data-content-base`.
|
||||
Action components can be used to connect specific dom sections to a javascript action component class. The root of a component is marked with a ´data-action-component´ assignment. This data attribute
|
||||
contains the component type e.g `humhub.modules.tasks.Task` or short `tasks.Task`. The component class must be dereived from ´humhub.modules.action.Component´.
|
||||
Action components can be cascaded for to share data between a container and entry components e.g. a `tasks.TaskList` contains multiple `tasks.Task` entries.
|
||||
The TaskList can provide action urls for all its Task entries and provide additional actions.
|
||||
For this purpose the components `data` function can be used to search for data values which are either set on the component root itself or a parent component root.
|
||||
|
||||
```html
|
||||
<!-- In my view -->
|
||||
<div id="taskContainer" data-content-base="humhub.modules.tasks.TaskList"
|
||||
<!-- Start of container component TaskList with given data values needed by its entries -->
|
||||
<div id="taskContainer" data-action-component="tasks.TaskList"
|
||||
data-content-edit-url="<?= $contentContainer->createUrl('/tasks/task/edit') ?>"
|
||||
data-content-delete-url="<?= $contentContainer->createUrl('/tasks/task/delete') ?>">
|
||||
|
||||
<!-- Will execute tasks.TaskList.create on click -->
|
||||
<a data-action-click="create">Create new</a>
|
||||
|
||||
<div class="task" data-content-base="humhub.modules.tasks.Task" data-content-pk="<?= $task->id ?>">
|
||||
<!-- First Task entry with data-content-key -->
|
||||
<div class="task" data-action-component="tasks.Task" data-content-key="<?= $task->id ?>">
|
||||
...
|
||||
<button data-action-click="edit">Edit</button>
|
||||
<button data-action-click="delete">Delete</button>
|
||||
@ -253,6 +254,21 @@ to cascade different types `data-content-base`.
|
||||
</div>
|
||||
```
|
||||
|
||||
> TIP: If you want to handle content models as posts which are extending [[humhub\modules\content\components\ContentActiveRecord]] you should extend the content-component described in the next section!
|
||||
|
||||
### Content
|
||||
|
||||
One of the main tasks of HumHub is the manipulation (create/edit/delete) of content entries as posts, wikis and polls. The `humhub.modules.content` module provides a
|
||||
interface for representing and handling content entries on the frontend. The following module implements a task module with an Task content component and a Tasklist content component.
|
||||
If your content class supports the actions edit and delete, it will have to set a data-content-key attribute with the given content id. This is not necessary if your
|
||||
implementation does not support these functions as in the TaskList example.
|
||||
|
||||
The ´Content´ component class provides the following actions by default:
|
||||
|
||||
- ´delete´ deletes a content object by using a confirm modal
|
||||
- ´edit´ edits the given content by loading a edit modal
|
||||
- ´create´ used to create new content
|
||||
|
||||
```javascript
|
||||
//Initializing the tasks module
|
||||
humhub.initModule('tasks', function(module, require, $) {
|
||||
@ -293,16 +309,16 @@ humhub.initModule('tasks', function(module, require, $) {
|
||||
__How does it work:__
|
||||
|
||||
1. An action-event-handler is bound to all dom nodes with a `data-action-click` on startup.
|
||||
2. If a click event is fired on this node, the action-event-handler will search for a global registered event "edit" (which should not be registered)
|
||||
3. Since there is no global "edit" handler the action-handler will try to call the content-action-handler
|
||||
4. This handler will search a parent node of the triggered button node with a data-content-base and instanziate the content by type.
|
||||
5. After content instance creation, the given handler is called (in this case edit).
|
||||
2. When triggered the action-event-handler does check if a direct handler was provided
|
||||
2. If not it will try to call `Component.handleAction`
|
||||
3. If this handler does find a sorrounding component it will instantiate the component and try to execute the given handler.
|
||||
4. If no other handler was found, the handler will try to find a handler in the humhub namespace.
|
||||
|
||||
The default action-handler for actions like delete/edit need to determine an action url this can either be done by adding a data-action-url/data-action-url-click directly to the trigger node
|
||||
or by adding data-content-edit-url/data-content-delete-url to the data-content-base or a parent data-content-base, in which the direct trigger assignment will overwrite an data-content-base
|
||||
assignment, which will overwrite the url setting of a parent data-content-base.
|
||||
The content-action-handler for actions like delete/edit need to lookup an action url this can either be done by adding a data-action-url/data-action-url-click directly to the trigger node
|
||||
or by adding data-content-edit-url/data-content-delete-url to the component root or a parent component root. A direct trigger assignment will overwrite a direct component assignment,
|
||||
which will overwrite the setting of a parent data-content-base.
|
||||
|
||||
> TIP: If your content does not need to overwrite the defaults or provides some additional actions (Like the Task in the example) you can just set the data-content-base without any value.
|
||||
> TIP: If your content does not need to overwrite the defaults or provides some additional actions (Like the Task in the example) you can just set ´content.Content´ as ´data-action-component´.
|
||||
|
||||
> TIP: beside the default handler the content can define other handler by simply adding it to the content prototype
|
||||
|
||||
|
@ -14,8 +14,8 @@
|
||||
$cssClass = ($entry->sticked) ? 'wall-entry sticked-entry' : 'wall-entry';
|
||||
|
||||
if ($mode != "activity") : ?>
|
||||
<div class="<?php echo $cssClass ?>" data-content-base="humhub.modules.stream.StreamEntry"
|
||||
data-content-pk="<?php echo $entry->id; ?>" data-stream-sticked="<?= $entry->sticked ?>">
|
||||
<div class="<?php echo $cssClass ?>" data-stream-entry data-stream-sticked="<?= $entry->sticked ?>"
|
||||
data-action-component="stream.StreamEntry" data-content-key="<?php echo $entry->id; ?>" >
|
||||
<?php endif; ?>
|
||||
|
||||
<?php echo $content; ?>
|
||||
|
@ -36,7 +36,7 @@ $contentIdData = ($contentId != "") ? 'data-stream-contentid="'.$contentId.'"' :
|
||||
|
||||
<!-- Stream content -->
|
||||
<div id="wallStream" data-stream="<?= $streamUrl ?>" <?= $contentIdData ?>
|
||||
data-content-base="humhub.modules.stream.Stream"
|
||||
data-action-component="humhub.modules.stream.Stream"
|
||||
data-content-delete-url="<?= Url::to(['/content/content/delete']) ?>">
|
||||
|
||||
<!-- DIV for a normal wall stream -->
|
||||
|
4961
themes/HumHub/css/less/styleguide.html
Normal file
4961
themes/HumHub/css/less/styleguide.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@
|
||||
@import "@{HUMHUB}/modules/modules.less";
|
||||
@import "@{HUMHUB}/modules/dropdown.less";
|
||||
@import "@{HUMHUB}/modules/panels.less";
|
||||
@import "@{HUMHUB}/modules/modals.less";
|
||||
@import "@{HUMHUB}/modules/pagination.less";
|
||||
@import "@{HUMHUB}/modules/thumbnails.less";
|
||||
@import "@{HUMHUB}/modules/nav.less";
|
||||
|
Loading…
x
Reference in New Issue
Block a user