mirror of
https://github.com/humhub/humhub.git
synced 2025-01-17 22:28:51 +01:00
Major js api enhancements + stream rewrite
This commit is contained in:
parent
c889256aa3
commit
ae65760599
1862
js/dist/humhub.all.js
vendored
1862
js/dist/humhub.all.js
vendored
File diff suppressed because it is too large
Load Diff
1
js/dist/humhub.all.min.js
vendored
1
js/dist/humhub.all.min.js
vendored
File diff suppressed because one or more lines are too long
367
js/humhub/humhub.action.js
Normal file
367
js/humhub/humhub.action.js
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
/**
|
||||||
|
* Thid module can be used by humhub sub modules for registering handlers and serves as core module for executing actions triggered in the gui.
|
||||||
|
* A module can either register global handler by using the registerHandler and registerAjaxHandler functions or use the content mechanism.
|
||||||
|
*/
|
||||||
|
humhub.initModule('action', function (module, require, $) {
|
||||||
|
var _handler = {};
|
||||||
|
var object = require('util').object;
|
||||||
|
var string = require('util').string;
|
||||||
|
var client = require('client');
|
||||||
|
var loader = require('ui.loader');
|
||||||
|
|
||||||
|
module.initOnPjaxLoad = false;
|
||||||
|
|
||||||
|
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), err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
||||||
|
module.log.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.
|
||||||
|
*/
|
||||||
|
module.init = function () {
|
||||||
|
//Binding default action types
|
||||||
|
this.bindAction(document, 'click', '[data-action-click]');
|
||||||
|
this.bindAction(document, 'dblclick', '[data-action-dblclick]');
|
||||||
|
this.bindAction(document, 'change', '[data-action-mouseout]');
|
||||||
|
|
||||||
|
updateBindings();
|
||||||
|
|
||||||
|
//Add addition for loader buttons
|
||||||
|
require('ui.additions').registerAddition('[data-action-load-button]', function () {
|
||||||
|
var that = this;
|
||||||
|
this.on('click.humhub-action-load-button', function (evt) {
|
||||||
|
if (!that.find('.action-loader').length) {
|
||||||
|
that.append('<span class="action-loader"><i class="fa fa-spinner fa-pulse"></i></span>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a given handler with the given id.
|
||||||
|
*
|
||||||
|
* This handler will be called e.g. after clicking a button with the handler id as
|
||||||
|
* data-action-click attribute.
|
||||||
|
*
|
||||||
|
* The handler can access additional event information through the argument event.
|
||||||
|
* The this object within the handler will be the trigger of the event.
|
||||||
|
*
|
||||||
|
* @param {string} id handler id should contain the module namespace
|
||||||
|
* @param {function} handler function with one event argument
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
module.registerHandler = function (id, handler) {
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handler) {
|
||||||
|
_handler[id] = handler;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an ajax eventhandler.
|
||||||
|
* The function can either be called with four arguments (id, successhandler, errorhandler, additional config)
|
||||||
|
* or with two (id, cfg) where tha handlers are contained in the config object itself.
|
||||||
|
*
|
||||||
|
* The successhandler will be called only if the response does not contain any errors or errormessages.
|
||||||
|
* So the errorhandler is called for application and http errors.
|
||||||
|
*
|
||||||
|
* The config can contain additional ajax settings.
|
||||||
|
*
|
||||||
|
* @param {type} id
|
||||||
|
* @param {type} success
|
||||||
|
* @param {type} error
|
||||||
|
* @param {type} cfg
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
module.registerAjaxHandler = function (id, success, error, cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object.isFunction(success)) {
|
||||||
|
cfg.success = success;
|
||||||
|
cfg.error = error;
|
||||||
|
} else {
|
||||||
|
cfg = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
_handler[id] = function (event) {
|
||||||
|
var path = $(this).data('action-url-' + event.type) || $(this).data('action-url');
|
||||||
|
client.ajax(path, cfg);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var actionBindings = [];
|
||||||
|
|
||||||
|
var updateBindings = function () {
|
||||||
|
module.log.debug('Update bindings');
|
||||||
|
$.each(actionBindings, function (i, binding) {
|
||||||
|
var $targets = $(binding.selector);
|
||||||
|
$targets.off(binding.event).on(binding.event, function (evt) {
|
||||||
|
module.log.debug('Handle direct trigger action', evt);
|
||||||
|
return binding.handle(evt, $(this));
|
||||||
|
});
|
||||||
|
$targets.data('action-'+binding.event, true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActionBinding instances are used to store the binding settings and handling
|
||||||
|
* binding events.
|
||||||
|
*
|
||||||
|
* @param {type} cfg
|
||||||
|
* @returns {humhub_action_L5.ActionBinding}
|
||||||
|
*/
|
||||||
|
var ActionBinding = function (cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
this.parent = cfg.parent;
|
||||||
|
this.eventType = cfg.type;
|
||||||
|
this.event = cfg.event;
|
||||||
|
this.selector = cfg.selector;
|
||||||
|
this.directHandler = cfg.directHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles an action event for the given $trigger node.
|
||||||
|
*
|
||||||
|
* This handler searches for a valid handler, by checking the following handler types in the given order:
|
||||||
|
*
|
||||||
|
* - Direct-ActionHandler is called if a directHandler was given when binding the action.
|
||||||
|
* - Component-ActionHandler is called if $trigger is part of a component and the component handler can be resolved
|
||||||
|
* - Global-ActionHandler is called if we find a handler in the _handler array. See registerHandler, registerAjaxHandler
|
||||||
|
* - Namespace-ActionHandler is called if we can resolve an action by namespace e.g: data-action-click="myModule.myAction"
|
||||||
|
*
|
||||||
|
* @param {type} evt the originalEvent
|
||||||
|
* @param {type} $trigger the jQuery node which triggered the event
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
ActionBinding.prototype.handle = function (evt, $trigger) {
|
||||||
|
module.log.debug('Handle Action', this);
|
||||||
|
evt.preventDefault();
|
||||||
|
|
||||||
|
var event = this.createActionEvent(evt, $trigger);
|
||||||
|
|
||||||
|
// Search and execute a stand alone handler or try to call the content action handler
|
||||||
|
try {
|
||||||
|
// Check for a direct action handler
|
||||||
|
if (object.isFunction(this.directHandler)) {
|
||||||
|
this.directHandler.apply($trigger, [event]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a component action handler
|
||||||
|
if (Component.handleAction(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for global registered handlers
|
||||||
|
if (_handler[this.handler]) {
|
||||||
|
_handler[this.handler].apply($trigger, [event]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// As last resort we try to call the action by namespace for handlers like humhub.modules.myModule.myAction
|
||||||
|
var splittedNS = this.handler.split('.');
|
||||||
|
var handlerAction = splittedNS[splittedNS.length - 1];
|
||||||
|
var target = require(string.cutsuffix(this.handler, '.' + handlerAction));
|
||||||
|
|
||||||
|
if (object.isFunction(target)) {
|
||||||
|
target[handlerAction](event);
|
||||||
|
} else {
|
||||||
|
module.log.error('actionHandlerNotFound', this, true);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
module.log.error('default', e, true);
|
||||||
|
_removeLoaderFromEventTarget(evt);
|
||||||
|
} finally {
|
||||||
|
// Just to get sure the handler is not called twice.
|
||||||
|
if(evt.originalEvent) {
|
||||||
|
evt.originalEvent.actionHandled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ActionBinding.prototype.createActionEvent = function (evt, $trigger) {
|
||||||
|
var event = $.Event(this.eventType);
|
||||||
|
event.originalEvent = evt;
|
||||||
|
|
||||||
|
// Add some additional action related data to our event.
|
||||||
|
event.$trigger = $trigger;
|
||||||
|
|
||||||
|
// If the trigger contains an url setting we add it to the event object, and prefer the typed url over the global data-action-url
|
||||||
|
event.url = $trigger.data('action-' + this.eventType + '-url') || $trigger.data('action-url');
|
||||||
|
event.params = $trigger.data('action-' + this.eventType + '-params') || $trigger.data('action-params');
|
||||||
|
|
||||||
|
//Get the handler id, either a stand alone handler or a content handler function e.g: 'edit'
|
||||||
|
event.handler = $trigger.data('action' + '-' + this.eventType);
|
||||||
|
|
||||||
|
if ($trigger.is(':submit')) {
|
||||||
|
event.$form = $trigger.closest('form');
|
||||||
|
}
|
||||||
|
|
||||||
|
event.finish = function () {
|
||||||
|
_removeLoaderFromEventTarget(evt);
|
||||||
|
};
|
||||||
|
|
||||||
|
return event;
|
||||||
|
};
|
||||||
|
|
||||||
|
var _removeLoaderFromEventTarget = function (evt) {
|
||||||
|
if (evt && evt.target) {
|
||||||
|
loader.reset(evt.target);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds an delegate wrapper event handler to the parent node. This is used to detect action handlers like
|
||||||
|
* data-action-click events and map the call to either a stand alone handler or a content
|
||||||
|
* action handler. The trigger of a contentAction has to be contained in a data-content-base node.
|
||||||
|
*
|
||||||
|
* This function uses the jQuery event delegation:
|
||||||
|
*
|
||||||
|
* $(parent).on(type, selector, function(){...});
|
||||||
|
*
|
||||||
|
* This assures the event binding for dynamic content (ajax content etc..)
|
||||||
|
*
|
||||||
|
* @see {@link humhub.modules.content.handleAction}
|
||||||
|
* @param {Node|jQuery} parent - the event target
|
||||||
|
* @param {string} type - event type e.g. click, change,...
|
||||||
|
* @param {string} selector - jQuery selector
|
||||||
|
* @param {string} selector - jQuery selector
|
||||||
|
*/
|
||||||
|
module.bindAction = function (parent, type, selector, directHandler) {
|
||||||
|
parent = parent || document;
|
||||||
|
var $parent = parent.jquery ? parent : $(parent);
|
||||||
|
var actionEvent = type + '.humhub-action';
|
||||||
|
|
||||||
|
var actionBinding = new ActionBinding({
|
||||||
|
parent: parent,
|
||||||
|
type: type,
|
||||||
|
event: actionEvent,
|
||||||
|
selector: selector,
|
||||||
|
directHandler: directHandler
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add new ActionBinding with given settings.
|
||||||
|
actionBindings.push(actionBinding);
|
||||||
|
|
||||||
|
$parent.on(actionEvent, selector, function (evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
|
||||||
|
// Get sure we don't call the handler twice if the event was already handled by trigger.
|
||||||
|
if ($(this).data('action-'+actionBinding.event)
|
||||||
|
|| evt.originalEvent && evt.originalEvent.actionHandled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.log.debug('Detected unhandled action', actionBinding);
|
||||||
|
updateBindings();
|
||||||
|
actionBinding.handle(evt, $(this));
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
Component: Component
|
||||||
|
});
|
||||||
|
});
|
@ -1,274 +0,0 @@
|
|||||||
/**
|
|
||||||
* Thid module can be used by humhub sub modules for registering handlers and serves as core module for executing actions triggered in the gui.
|
|
||||||
* A module can either register global handler by using the registerHandler and registerAjaxHandler functions or use the content mechanism.
|
|
||||||
*/
|
|
||||||
humhub.initModule('actions', function (module, require, $) {
|
|
||||||
var _handler = {};
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
module.init = function () {
|
|
||||||
//Binding default action types
|
|
||||||
this.bindAction(document, 'click', '[data-action-click]');
|
|
||||||
this.bindAction(document, 'dblclick', '[data-action-dblclick]');
|
|
||||||
this.bindAction(document, 'change', '[data-action-mouseout]');
|
|
||||||
|
|
||||||
//Add addition for loader buttons
|
|
||||||
require('additions').registerAddition('[data-action-load-button]', function () {
|
|
||||||
var that = this;
|
|
||||||
this.on('click.humhub-action-load-button', function (evt) {
|
|
||||||
if (!that.find('.action-loader').length) {
|
|
||||||
that.append('<span class="action-loader"><i class="fa fa-spinner fa-pulse"></i></span>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a given handler with the given id.
|
|
||||||
*
|
|
||||||
* This handler will be called e.g. after clicking a button with the handler id as
|
|
||||||
* data-action-click attribute.
|
|
||||||
*
|
|
||||||
* The handler can access additional event information through the argument event.
|
|
||||||
* The this object within the handler will be the trigger of the event.
|
|
||||||
*
|
|
||||||
* @param {string} id handler id should contain the module namespace
|
|
||||||
* @param {function} handler function with one event argument
|
|
||||||
* @returns {undefined}
|
|
||||||
*/
|
|
||||||
module.registerHandler = function (id, handler) {
|
|
||||||
if (!id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handler) {
|
|
||||||
_handler[id] = handler;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers an ajax eventhandler.
|
|
||||||
* The function can either be called with four arguments (id, successhandler, errorhandler, additional config)
|
|
||||||
* or with two (id, cfg) where tha handlers are contained in the config object itself.
|
|
||||||
*
|
|
||||||
* The successhandler will be called only if the response does not contain any errors or errormessages.
|
|
||||||
* So the errorhandler is called for application and http errors.
|
|
||||||
*
|
|
||||||
* The config can contain additional ajax settings.
|
|
||||||
*
|
|
||||||
* @param {type} id
|
|
||||||
* @param {type} success
|
|
||||||
* @param {type} error
|
|
||||||
* @param {type} cfg
|
|
||||||
* @returns {undefined}
|
|
||||||
*/
|
|
||||||
module.registerAjaxHandler = function (id, success, error, cfg) {
|
|
||||||
cfg = cfg || {};
|
|
||||||
if (!id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (object.isFunction(success)) {
|
|
||||||
cfg.success = success;
|
|
||||||
cfg.error = error;
|
|
||||||
} else {
|
|
||||||
cfg = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
_handler[id] = function (event) {
|
|
||||||
var path = $(this).data('action-url-' + event.type) || $(this).data('action-url');
|
|
||||||
client.ajax(path, cfg);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds an delegate wrapper event handler to the parent node. This is used to detect action handlers like
|
|
||||||
* data-action-click events and map the call to either a stand alone handler or a content
|
|
||||||
* action handler. The trigger of a contentAction has to be contained in a data-content-base node.
|
|
||||||
*
|
|
||||||
* This function uses the jQuery event delegation:
|
|
||||||
*
|
|
||||||
* $(parent).on(type, selector, function(){...});
|
|
||||||
*
|
|
||||||
* This assures the event binding for dynamic content (ajax content etc..)
|
|
||||||
*
|
|
||||||
* @see {@link humhub.modules.content.handleAction}
|
|
||||||
* @param {Node|jQuery} parent - the event target
|
|
||||||
* @param {string} type - event type e.g. click, change,...
|
|
||||||
* @param {string} selector - jQuery selector
|
|
||||||
* @param {string} selector - jQuery selector
|
|
||||||
*/
|
|
||||||
module.bindAction = function (parent, type, selector, directHandler) {
|
|
||||||
parent = parent || document;
|
|
||||||
var $parent = parent.jquery ? parent : $(parent);
|
|
||||||
$parent.on(type+'.humhub-action', selector, function (evt) {
|
|
||||||
evt.preventDefault();
|
|
||||||
//The element which triggered the action e.g. a button or link
|
|
||||||
$trigger = $(this);
|
|
||||||
|
|
||||||
//Get the handler id, either a stand alone handler or a content handler function e.g: 'edit'
|
|
||||||
var handlerId = $trigger.data('action' + '-' + type);
|
|
||||||
var event = {type: type, $trigger: $trigger, handler: handlerId};
|
|
||||||
|
|
||||||
event.finish = function() {
|
|
||||||
_removeLoaderFromEventTarget(evt);
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO: handle with $.Event
|
|
||||||
//var event = $.Event(type, {$trigger: $trigger});
|
|
||||||
//event.originalEvent = evt;
|
|
||||||
|
|
||||||
//Search and execute a stand alone handler or try to call the content action handler
|
|
||||||
try {
|
|
||||||
//Direct action handler
|
|
||||||
if(object.isFunction(directHandler)) {
|
|
||||||
directHandler.apply($trigger, [event]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Component handler
|
|
||||||
if(Component.handleAction(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Registered handler
|
|
||||||
if(_handler[handlerId]) {
|
|
||||||
//Registered action handler
|
|
||||||
var handler = _handler[handlerId];
|
|
||||||
handler.apply($trigger, [event]);
|
|
||||||
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 !
|
|
||||||
console.error('Error while handling action event for handler "' + handlerId+'"', e);
|
|
||||||
_removeLoaderFromEventTarget(evt);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var _removeLoaderFromEventTarget = function (evt) {
|
|
||||||
if (evt.target) {
|
|
||||||
$target = $(evt.target);
|
|
||||||
$loader = $target.find('.action-loader');
|
|
||||||
|
|
||||||
if ($loader.length) {
|
|
||||||
$loader.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.export({
|
|
||||||
Component: Component
|
|
||||||
});
|
|
||||||
});
|
|
@ -5,32 +5,17 @@
|
|||||||
humhub.initModule('client', function (module, require, $) {
|
humhub.initModule('client', function (module, require, $) {
|
||||||
var object = require('util').object;
|
var object = require('util').object;
|
||||||
|
|
||||||
var init = function () {
|
|
||||||
/*$.ajaxPrefilter('html', function(options, originalOptions, jqXHR) {
|
|
||||||
debugger;
|
|
||||||
console.log(options);
|
|
||||||
var pjaxHandler = options.success;
|
|
||||||
options.success = function(result, textStatus, xhr) {
|
|
||||||
console.log(result);
|
|
||||||
pjaxHandler(result, textStatus, xhr);
|
|
||||||
};
|
|
||||||
options.error = function(err) {
|
|
||||||
debugger;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
$.pjax.defaults.maxCacheLength = 0;
|
|
||||||
$('a.dashboard').on('click', function(evt) {
|
|
||||||
debugger;
|
|
||||||
evt.preventDefault();
|
|
||||||
$.pjax({url:$(this).attr('href'), container: '#main-content', maxCacheLength:0, timeout:2000});
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Response Wrapper Object for easily accessing common data
|
* Response Wrapper Object for easily accessing common data
|
||||||
*/
|
*/
|
||||||
var Response = function (data) {
|
var Response = function (data, dataType) {
|
||||||
$.extend(this, data);
|
if(!dataType || dataType === 'json') {
|
||||||
|
$.extend(this, data);
|
||||||
|
} else if(dataType) {
|
||||||
|
this[dataType] = data;
|
||||||
|
} else {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +73,8 @@ humhub.initModule('client', function (module, require, $) {
|
|||||||
$form = object.isString($form) ? $($form) : $form;
|
$form = object.isString($form) ? $($form) : $form;
|
||||||
cfg.type = $form.attr('method') || 'post';
|
cfg.type = $form.attr('method') || 'post';
|
||||||
cfg.data = $form.serialize();
|
cfg.data = $form.serialize();
|
||||||
ajax($form.attr('action'), cfg);
|
var url = cfg['url'] || $form.attr('action');
|
||||||
|
return ajax(url, cfg);
|
||||||
};
|
};
|
||||||
|
|
||||||
var post = function (path, cfg) {
|
var post = function (path, cfg) {
|
||||||
@ -97,28 +83,39 @@ humhub.initModule('client', function (module, require, $) {
|
|||||||
cfg.method = 'POST';
|
cfg.method = 'POST';
|
||||||
return ajax(path, cfg);
|
return ajax(path, cfg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var get = function (path, cfg) {
|
||||||
|
var cfg = cfg || {};
|
||||||
|
cfg.type = 'GET';
|
||||||
|
cfg.method = 'GET';
|
||||||
|
return ajax(path, cfg);
|
||||||
|
};
|
||||||
|
|
||||||
var ajax = function (path, cfg) {
|
var ajax = function (path, cfg) {
|
||||||
|
if(object.isFunction(cfg)) {
|
||||||
|
cfg = {'success' : cfg};
|
||||||
|
}
|
||||||
|
|
||||||
var promise = new Promise(function (resolve, reject) {
|
var promise = new Promise(function (resolve, reject) {
|
||||||
cfg = cfg || {};
|
cfg = cfg || {};
|
||||||
|
|
||||||
//Wrap the actual error handler with our own and call
|
//Wrap the actual error handler with our own and call
|
||||||
var errorHandler = cfg.error;
|
var errorHandler = cfg.error;
|
||||||
var error = function (xhr, textStatus, errorThrown, data, status) {
|
var error = function (xhr, textStatus, errorThrown, data) {
|
||||||
//Textstatus = "timeout", "error", "abort", "parsererror", "application"
|
//Textstatus = "timeout", "error", "abort", "parsererror", "application"
|
||||||
if (errorHandler && object.isFunction(errorHandler)) {
|
if (errorHandler && object.isFunction(errorHandler)) {
|
||||||
var response = new Response();
|
var response = new Response();
|
||||||
response.setAjaxError(xhr, errorThrown, textStatus, data, status);
|
response.setAjaxError(xhr, errorThrown, textStatus, data, xhr.status);
|
||||||
errorHandler(response);
|
errorHandler(response);
|
||||||
}
|
}
|
||||||
reject(xhr, textStatus, errorThrown, data, status);
|
reject({'textStatus': textStatus, 'response': xhr.responseJSON, 'error': errorThrown, 'data': data, 'status': xhr.status});
|
||||||
};
|
};
|
||||||
|
|
||||||
var successHandler = cfg.success;
|
var successHandler = cfg.success;
|
||||||
var success = function (json, textStatus, xhr) {
|
var success = function (data, textStatus, xhr) {
|
||||||
var response = new Response(json);
|
var response = new Response(data, cfg.dataType);
|
||||||
if (response.isError()) { //Application errors
|
if (response.isError()) { //Application errors
|
||||||
return error(xhr, "application", response.getErrors(), json, response.getStatus());
|
return error(xhr, "application", response.getErrors(), data, response.getStatus());
|
||||||
} else if (successHandler) {
|
} else if (successHandler) {
|
||||||
response.textStatus = textStatus;
|
response.textStatus = textStatus;
|
||||||
response.xhr = xhr;
|
response.xhr = xhr;
|
||||||
@ -129,7 +126,7 @@ humhub.initModule('client', function (module, require, $) {
|
|||||||
|
|
||||||
promise.then(function() {
|
promise.then(function() {
|
||||||
// If content with <link> tags are inserted in resolve, the ajaxComplete handler in yii.js
|
// If content with <link> tags are inserted in resolve, the ajaxComplete handler in yii.js
|
||||||
// makes shure redundant stylesheets are removed.
|
// makes sure redundant stylesheets are removed. Here we get sure it is called after inserting the response.
|
||||||
$(document).trigger('ajaxComplete');
|
$(document).trigger('ajaxComplete');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -152,8 +149,8 @@ humhub.initModule('client', function (module, require, $) {
|
|||||||
module.export({
|
module.export({
|
||||||
ajax: ajax,
|
ajax: ajax,
|
||||||
post: post,
|
post: post,
|
||||||
submit: submit,
|
get: get,
|
||||||
init: init
|
submit: submit
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
humhub.initModule('client.pjax', function (module, require, $) {
|
humhub.initModule('client.pjax', function (module, require, $) {
|
||||||
var object = require('util').object;
|
var event = require('event');
|
||||||
|
|
||||||
|
module.initOnPjaxLoad = false;
|
||||||
|
|
||||||
var init = function () {
|
var init = function () {
|
||||||
pjaxRedirectFix();
|
pjaxRedirectFix();
|
||||||
installLoader();
|
module.installLoader();
|
||||||
}
|
};
|
||||||
|
|
||||||
var pjaxRedirectFix = function () {
|
var pjaxRedirectFix = function () {
|
||||||
var pjaxXhr;
|
var pjaxXhr;
|
||||||
@ -18,8 +20,18 @@ humhub.initModule('client.pjax', function (module, require, $) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on("pjax:success", function (evt, data, status, xhr, options) {
|
||||||
|
event.trigger('humhub:modules:client:pjax:afterPageLoad', {
|
||||||
|
'originalEvent': evt,
|
||||||
|
'data': data,
|
||||||
|
'status': status,
|
||||||
|
'xhr': xhr,
|
||||||
|
'options': options
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$.ajaxPrefilter('html', function (options, originalOptions, jqXHR) {
|
$.ajaxPrefilter('html', function (options, originalOptions, jqXHR) {
|
||||||
orgErrorHandler = options.error;
|
var orgErrorHandler = options.error;
|
||||||
options.error = function (xhr, textStatus, errorThrown) {
|
options.error = function (xhr, textStatus, errorThrown) {
|
||||||
var redirect = (xhr.status >= 301 && xhr.status <= 303)
|
var redirect = (xhr.status >= 301 && xhr.status <= 303)
|
||||||
if (redirect && xhr.getResponseHeader('X-PJAX-REDIRECT-URL') != "") {
|
if (redirect && xhr.getResponseHeader('X-PJAX-REDIRECT-URL') != "") {
|
||||||
@ -31,19 +43,20 @@ humhub.initModule('client.pjax', function (module, require, $) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
var installLoader = function () {
|
var installLoader = function () {
|
||||||
NProgress.configure({showSpinner: false});
|
NProgress.configure({showSpinner: false});
|
||||||
NProgress.configure({template: '<div class="bar" role="bar"></div>'});
|
NProgress.configure({template: '<div class="bar" role="bar"></div>'});
|
||||||
|
|
||||||
jQuery(document).on('pjax:start', function () {
|
$(document).on('pjax:start', function () {
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
});
|
});
|
||||||
jQuery(document).on('pjax:end', function () {
|
|
||||||
|
$(document).on('pjax:end', function () {
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
module.export({
|
module.export({
|
||||||
init: init,
|
init: init,
|
||||||
|
@ -13,6 +13,12 @@ var humhub = humhub || (function($) {
|
|||||||
*/
|
*/
|
||||||
var modules = {};
|
var modules = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flat array with all registered modules.
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
var moduleArr = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to collect modules added while initial page load.
|
* Used to collect modules added while initial page load.
|
||||||
* These modules will be intitialized after the document is ready.
|
* These modules will be intitialized after the document is ready.
|
||||||
@ -20,6 +26,13 @@ var humhub = humhub || (function($) {
|
|||||||
*/
|
*/
|
||||||
var initialModules = [];
|
var initialModules = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains all modules which needs to be reinitialized after a pjax reload
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
var pjaxInitModules = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is set wehen document is ready
|
* Is set wehen document is ready
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
@ -27,7 +40,8 @@ var humhub = humhub || (function($) {
|
|||||||
var initialized = false;
|
var initialized = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an module to the namespace. And initializes either after dom is ready.
|
* Adds a module to the namespace. And initializes after dom is ready.
|
||||||
|
*
|
||||||
* The id can be provided either as
|
* The id can be provided either as
|
||||||
*
|
*
|
||||||
* - full namespace humhub.modules.ui.modal
|
* - full namespace humhub.modules.ui.modal
|
||||||
@ -81,6 +95,14 @@ var humhub = humhub || (function($) {
|
|||||||
var instance = resolveNameSpace(id, true);
|
var instance = resolveNameSpace(id, true);
|
||||||
instance.id = 'humhub.modules.'+_cutModulePrefix(id);
|
instance.id = 'humhub.modules.'+_cutModulePrefix(id);
|
||||||
instance.require = require;
|
instance.require = require;
|
||||||
|
instance.initOnPjaxLoad = true;
|
||||||
|
instance.config = require('config').module(instance);
|
||||||
|
instance.isModule = true;
|
||||||
|
|
||||||
|
instance.text = function($key) {
|
||||||
|
return instance.config['text'][$key];
|
||||||
|
};
|
||||||
|
|
||||||
instance.export = function(exports) {
|
instance.export = function(exports) {
|
||||||
$.extend(instance, exports);
|
$.extend(instance, exports);
|
||||||
};
|
};
|
||||||
@ -92,10 +114,17 @@ var humhub = humhub || (function($) {
|
|||||||
console.error('Error while creating module: '+id, err);
|
console.error('Error while creating module: '+id, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moduleArr.push(instance);
|
||||||
|
|
||||||
|
if(instance.init && instance.initOnPjaxLoad) {
|
||||||
|
pjaxInitModules.push(instance);
|
||||||
|
}
|
||||||
|
|
||||||
//Initialize the module when document is ready
|
//Initialize the module when document is ready
|
||||||
if(!initialized) {
|
if(!initialized) {
|
||||||
initialModules.push(instance);
|
initialModules.push(instance);
|
||||||
} else {
|
} else {
|
||||||
|
addModuleLogger(instance);
|
||||||
instance.init();
|
instance.init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -148,25 +177,29 @@ var humhub = humhub || (function($) {
|
|||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
//TODO: handle could not resolve type/namespace error
|
var log = require('log') || console;
|
||||||
return;
|
log.error('Error while resolving namespace: '+typePathe, e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config implementation
|
* Config implementation
|
||||||
*/
|
*/
|
||||||
|
var config = modules['config'] = {
|
||||||
var config = {
|
id : 'config',
|
||||||
|
|
||||||
get : function(module, key, defaultVal) {
|
get : function(module, key, defaultVal) {
|
||||||
if(arguments.length === 1) {
|
if(arguments.length === 1) {
|
||||||
return this.getModuleConfig(module);
|
return this.module(module);
|
||||||
} else if(_isDefined(key)) {
|
} else if(_isDefined(key)) {
|
||||||
var result = this.getModuleConfig(module)[key];
|
var result = this.module(module)[key];
|
||||||
return (_isDefined(result)) ? result : defaultVal;
|
return (_isDefined(result)) ? result : defaultVal;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getModuleConfig: function(module) {
|
|
||||||
|
module: function(module) {
|
||||||
|
module = (module.id) ? module.id : module;
|
||||||
|
module = _cutModulePrefix(module);
|
||||||
if(!this[module]) {
|
if(!this[module]) {
|
||||||
this[module] = {};
|
this[module] = {};
|
||||||
}
|
}
|
||||||
@ -185,13 +218,29 @@ var humhub = humhub || (function($) {
|
|||||||
that.set(moduleKey, config);
|
that.set(moduleKey, config);
|
||||||
});
|
});
|
||||||
}else if(arguments.length === 2) {
|
}else if(arguments.length === 2) {
|
||||||
$.extend(this.getModuleConfig(moduleId), key);
|
$.extend(this.module(moduleId), key);
|
||||||
} else if(arguments.length === 3) {
|
} else if(arguments.length === 3) {
|
||||||
this.getModuleConfig(moduleId)[key] = value;
|
this.module(moduleId)[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var event = modules['event'] = {
|
||||||
|
events : $({}),
|
||||||
|
on : function(event, selector, data, handler) {
|
||||||
|
this.events.on(event , selector, data, handler);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
trigger : function(eventType, extraParameters) {
|
||||||
|
this.events.trigger(eventType, extraParameters);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
one : function(event, selector, data, handler) {
|
||||||
|
this.events.one(event , selector, data, handler);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cuts the prefix humub.modules or modules. from the given value.
|
* Cuts the prefix humub.modules or modules. from the given value.
|
||||||
* @param {type} value
|
* @param {type} value
|
||||||
@ -233,18 +282,43 @@ var humhub = humhub || (function($) {
|
|||||||
return typeof obj !== 'undefined';
|
return typeof obj !== 'undefined';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var addModuleLogger = function(module, log) {
|
||||||
|
log = log || require('log');
|
||||||
|
module.log = log.module(module);
|
||||||
|
}
|
||||||
|
|
||||||
//Initialize all initial modules
|
//Initialize all initial modules
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
var log = require('log');
|
||||||
|
|
||||||
|
$.each(moduleArr, function(i, module) {
|
||||||
|
addModuleLogger(module, log);
|
||||||
|
});
|
||||||
|
|
||||||
$.each(initialModules, function(i, module) {
|
$.each(initialModules, function(i, module) {
|
||||||
|
event.trigger('humhub:beforeInitModule', module);
|
||||||
if(module.init) {
|
if(module.init) {
|
||||||
try {
|
try {
|
||||||
|
event.trigger(module.id)
|
||||||
module.init();
|
module.init();
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error('Could not initialize module: '+module.id, err);
|
log.error('Could not initialize module: '+module.id, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initialized = true;
|
event.trigger('humhub:afterInitModule', module);
|
||||||
console.log('Module initialized: '+module.id);
|
log.debug('Module initialized: '+module.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
event.trigger('humhub:afterInit');
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
event.on('humhub:modules:client:pjax:afterPageLoad', function (evt) {
|
||||||
|
$.each(pjaxInitModules, function(i, module) {
|
||||||
|
if(module.initOnPjaxLoad) {
|
||||||
|
module.init();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -253,6 +327,7 @@ var humhub = humhub || (function($) {
|
|||||||
return {
|
return {
|
||||||
initModule: initModule,
|
initModule: initModule,
|
||||||
modules: modules,
|
modules: modules,
|
||||||
config: config
|
config: config,
|
||||||
|
event: event,
|
||||||
};
|
};
|
||||||
})($);
|
})($);
|
@ -1,331 +0,0 @@
|
|||||||
var humhub = humhub || {};
|
|
||||||
|
|
||||||
humhub.util = (function(module, $) {
|
|
||||||
module.object = {
|
|
||||||
isFunction: function(obj) {
|
|
||||||
return Object.prototype.toString.call(obj) === '[object Function]';
|
|
||||||
},
|
|
||||||
|
|
||||||
isObject: function(obj) {
|
|
||||||
return $.isPlainObject(obj);
|
|
||||||
},
|
|
||||||
|
|
||||||
isJQuery: function(obj) {
|
|
||||||
return obj.jquery;
|
|
||||||
},
|
|
||||||
|
|
||||||
isString: function(obj) {
|
|
||||||
return typeof obj === 'string';
|
|
||||||
},
|
|
||||||
|
|
||||||
isNumber: function(n) {
|
|
||||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
||||||
},
|
|
||||||
|
|
||||||
isBoolean: function(obj) {
|
|
||||||
return typeof obj === 'boolean';
|
|
||||||
},
|
|
||||||
|
|
||||||
isDefined: function(obj) {
|
|
||||||
if(arguments.length > 1) {
|
|
||||||
var result = true;
|
|
||||||
var that = this;
|
|
||||||
this.each(arguments, function(index, value) {
|
|
||||||
if(!that.isDefined(value)) {
|
|
||||||
result = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return typeof obj !== 'undefined';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return module;
|
|
||||||
})(humhub.util || {}, $);
|
|
||||||
|
|
||||||
humhub.modules = (function(module, $) {
|
|
||||||
var _handler = {};
|
|
||||||
var _errorHandler = {};
|
|
||||||
var object = humhub.util.object;
|
|
||||||
|
|
||||||
var DATA_ACTION = 'action';
|
|
||||||
|
|
||||||
module.registerHandler = function(id, handler) {
|
|
||||||
if(!id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(handler) {
|
|
||||||
_handler[id] = handler;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.registerAjaxHandler = function(id, success, error, cfg) {
|
|
||||||
debugger;
|
|
||||||
cfg = cfg || {};
|
|
||||||
if(!id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(object.isFunction(success)) {
|
|
||||||
cfg.success = success;
|
|
||||||
cfg.error = error;
|
|
||||||
} else {
|
|
||||||
cfg = success;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(success) {
|
|
||||||
var that = this;
|
|
||||||
_handler[id] = function(event) {
|
|
||||||
var path = $(this).data('url-'+event.type) || $(this).data('url');
|
|
||||||
that.ajax(path, cfg, event);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(error) {
|
|
||||||
_errorHandler[id] = success;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.bindAction = function(parent, type, selector) {
|
|
||||||
parent = parent || document;
|
|
||||||
var $parent = parent.jquery ? parent : $(parent);
|
|
||||||
$parent.on(type, selector, function(evt) {
|
|
||||||
evt.preventDefault();
|
|
||||||
//The element which triggered the action e.g. a button or link
|
|
||||||
$trigger = $(this);
|
|
||||||
var handlerId = $trigger.data(DATA_ACTION+'-'+type);
|
|
||||||
var handler = _handler[handlerId];
|
|
||||||
var event = {type:type, $trigger:$trigger};
|
|
||||||
handler.apply($trigger, [event]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.bindAction(document, 'click', '[data-action-click]');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response Wrapper Object for
|
|
||||||
* easily accessing common data
|
|
||||||
*/
|
|
||||||
var Response = function(data) {
|
|
||||||
this.data = data;
|
|
||||||
};
|
|
||||||
|
|
||||||
Response.prototype.isConfirmation = function() {
|
|
||||||
return this.data && (this.data.status === 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
Response.prototype.isError = function() {
|
|
||||||
return this.data && this.data.status && (this.data.status > 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
Response.prototype.getErrors = function() {
|
|
||||||
return this.data.errors;
|
|
||||||
};
|
|
||||||
|
|
||||||
Response.prototype.getErrorCode = function() {
|
|
||||||
return this.data.errorCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
Response.prototype.toString = function() {
|
|
||||||
return "{ status: "+this.data.status+" error: "+this.data.error+" data: "+this.data.data+" }";
|
|
||||||
};
|
|
||||||
|
|
||||||
var errorHandler = function(cfg, xhr,type,errorThrown, errorCode, path) {
|
|
||||||
errorCode = (xhr) ? xhr.status : parseInt(errorCode);
|
|
||||||
console.warn("AjaxError: "+type+" "+errorThrown+" - "+errorCode);
|
|
||||||
|
|
||||||
if(cfg.error && object.isFunction(cfg.error)) {
|
|
||||||
// "timeout", "error", "abort", "parsererror" or "application"
|
|
||||||
//TODO: den trigger als this verwenden
|
|
||||||
cfg.error(errorThrown, errorCode, type);
|
|
||||||
} else {
|
|
||||||
console.warn('Unhandled ajax error: '+path+" type"+type+" error: "+errorThrown);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.ajax = function(path, cfg) {
|
|
||||||
var cfg = cfg || {};
|
|
||||||
var async = cfg.async || true;
|
|
||||||
var dataType = cfg.dataType || "json";
|
|
||||||
|
|
||||||
var error = function(xhr,type,errorThrown, errorCode) {
|
|
||||||
errorHandler(cfg, xhr,type,errorThrown, errorCode, path);
|
|
||||||
};
|
|
||||||
|
|
||||||
var success = function(response) {
|
|
||||||
var responseWrapper = new Response(response);
|
|
||||||
|
|
||||||
if(responseWrapper.isError()) { //Application errors
|
|
||||||
return error(undefined,"application",responseWrapper.getError(), responseWrapper.getErrorCode());
|
|
||||||
} else if(cfg.success) {
|
|
||||||
cfg.success(responseWrapper);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: path,
|
|
||||||
//crossDomain: true, //TODO: read from config
|
|
||||||
type : cfg.type,
|
|
||||||
processData : cfg.processData,
|
|
||||||
contentType: cfg.contentType,
|
|
||||||
async : async,
|
|
||||||
dataType: dataType,
|
|
||||||
success: success,
|
|
||||||
error: error
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
})(humhub.modules || {}, $);
|
|
||||||
|
|
||||||
humhub.modules.stream = (function(module, $) {
|
|
||||||
|
|
||||||
var ENTRY_ID_SELECTOR_PREFIX = '#wallEntry_';
|
|
||||||
var WALLSTREAM_ID = 'wallStream';
|
|
||||||
|
|
||||||
module.Entry = function(id) {
|
|
||||||
if(typeof id === 'string') {
|
|
||||||
this.id = id;
|
|
||||||
this.$ = $('#'+id);
|
|
||||||
} else if(id.jquery) {
|
|
||||||
this.$ = id;
|
|
||||||
this.id = this.$.attr('id');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Entry.prototype.remove = function() {
|
|
||||||
this.$.remove();
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Entry.prototype.highlightContent = function() {
|
|
||||||
var $content = this.getContent();
|
|
||||||
$content.addClass('highlight');
|
|
||||||
$content.delay(200).animate({backgroundColor: 'transparent'}, 1000, function() {
|
|
||||||
$content.removeClass('highlight');
|
|
||||||
$content.css('backgroundColor', '');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Entry.prototype.getContent = function() {
|
|
||||||
return this.$.find('.content');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Stream = function(id) {
|
|
||||||
this.id = id;
|
|
||||||
this.$ = $('#'+id);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Stream.prototype.getEntry = function(id) {
|
|
||||||
return new module.Entry(this.$.find(ENTRY_ID_SELECTOR_PREFIX+id));
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Stream.prototype.wallStick = function(url) {
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
if (currentStream) {
|
|
||||||
$.each(data.wallEntryIds, function (k, wallEntryId) {
|
|
||||||
currentStream.deleteEntry(wallEntryId);
|
|
||||||
currentStream.prependEntry(wallEntryId);
|
|
||||||
});
|
|
||||||
$('html, body').animate({scrollTop: 0}, 'slow');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert(data.errorMessage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.Stream.prototype.wallUnstick = function(url) {
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
//Reload the whole stream, since we have to reorder the entries
|
|
||||||
currentStream.showStream();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click Handler for Archive Link of Wall Posts
|
|
||||||
* (archiveLink.php)
|
|
||||||
*
|
|
||||||
* @param {type} className
|
|
||||||
* @param {type} id
|
|
||||||
*/
|
|
||||||
module.Stream.prototype.wallArchive = function(id) {
|
|
||||||
|
|
||||||
url = wallArchiveLinkUrl.replace('-id-', id);
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
if (currentStream) {
|
|
||||||
$.each(data.wallEntryIds, function (k, wallEntryId) {
|
|
||||||
//currentStream.reloadWallEntry(wallEntryId);
|
|
||||||
// fade out post
|
|
||||||
setInterval(fadeOut(), 1000);
|
|
||||||
|
|
||||||
function fadeOut() {
|
|
||||||
// fade out current archived post
|
|
||||||
$('#wallEntry_' + wallEntryId).fadeOut('slow');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click Handler for Un Archive Link of Wall Posts
|
|
||||||
* (archiveLink.php)
|
|
||||||
*
|
|
||||||
* @param {type} className
|
|
||||||
* @param {type} id
|
|
||||||
*/
|
|
||||||
module.Stream.prototype.wallUnarchive = function(id) {
|
|
||||||
url = wallUnarchiveLinkUrl.replace('-id-', id);
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
if (currentStream) {
|
|
||||||
$.each(data.wallEntryIds, function (k, wallEntryId) {
|
|
||||||
currentStream.reloadWallEntry(wallEntryId);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
module.getStream = function() {
|
|
||||||
if(!module.mainStream) {
|
|
||||||
module.mainStream = new module.Stream(WALLSTREAM_ID);
|
|
||||||
}
|
|
||||||
return module.mainStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.getEntry = function(id) {
|
|
||||||
return module.getStream().getEntry(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
return module;
|
|
||||||
})(humhub.core || {}, $);
|
|
230
js/humhub/humhub.log.js
Normal file
230
js/humhub/humhub.log.js
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {type} param1
|
||||||
|
* @param {type} param2
|
||||||
|
*/
|
||||||
|
humhub.initModule('log', function (module, require, $) {
|
||||||
|
|
||||||
|
var event = require('event');
|
||||||
|
|
||||||
|
var TRACE_TRACE = 0;
|
||||||
|
var TRACE_DEBUG = 1;
|
||||||
|
var TRACE_INFO = 2;
|
||||||
|
var TRACE_SUCCESS = 3;
|
||||||
|
var TRACE_WARN = 4;
|
||||||
|
var TRACE_ERROR = 5;
|
||||||
|
var TRACE_FATAL = 6;
|
||||||
|
var TRACE_OFF = 7;
|
||||||
|
|
||||||
|
var traceLevels = ['TRACE', 'DEBUG', 'INFO', 'SUCCESS', 'WARN', 'ERROR', 'FATAL', 'OFF'];
|
||||||
|
var config = require('config').module(module);
|
||||||
|
var object = require('util').object;
|
||||||
|
|
||||||
|
var logger = {};
|
||||||
|
|
||||||
|
var Logger = function (module) {
|
||||||
|
if(object.isString(module)) {
|
||||||
|
this.module = require('module');
|
||||||
|
this.moduleId = module;
|
||||||
|
} else if(module){
|
||||||
|
this.module = module;
|
||||||
|
this.moduleId = module.id;
|
||||||
|
}
|
||||||
|
this.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.update = function () {
|
||||||
|
var result;
|
||||||
|
if (this.moduleId) {
|
||||||
|
var moduleConfig = require('config').module(this.moduleId);
|
||||||
|
if (moduleConfig.traceLevel && traceLevels.indexOf(moduleConfig.traceLevel.toUpperCase()) >= 0) {
|
||||||
|
result = traceLevels.indexOf(moduleConfig.traceLevel.toUpperCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
result = config.traceLevel || TRACE_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.traceLevel = result;
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.trace = function (msg,details, setStatus) {
|
||||||
|
this._log(msg, details, setStatus, TRACE_TRACE);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.debug = function (msg, details, setStatus) {
|
||||||
|
this._log(msg, details, setStatus, TRACE_DEBUG);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.info = function (msg, details, setStatus) {
|
||||||
|
this._log(msg, details, setStatus, TRACE_INFO);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.success = function (msg, setStatus) {
|
||||||
|
setStatus = object.isDefined(setStatus) ? setStatus : true;
|
||||||
|
this._log(msg, undefined, setStatus, TRACE_SUCCESS);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.warn = function (msg, error, setStatus) {
|
||||||
|
this._log(msg, error, setStatus, TRACE_WARN);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.error = function (msg, error, setStatus) {
|
||||||
|
this._log(msg, error, setStatus, TRACE_ERROR);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.fatal = function (msg, error, setStatus) {
|
||||||
|
this._log(msg, error, setStatus, TRACE_FATAL);
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype._log = function (msg, details, setStatus, level) {
|
||||||
|
try {
|
||||||
|
if (object.isBoolean(details)) {
|
||||||
|
setStatus = details;
|
||||||
|
details = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg instanceof Error && level >= TRACE_WARN) {
|
||||||
|
details = msg;
|
||||||
|
msg = this.getMessage(details.message, true);
|
||||||
|
} else if(object.isObject(msg) && msg.status && level >= TRACE_WARN) {
|
||||||
|
details = msg;
|
||||||
|
msg = this.getMessage(msg.status, true);
|
||||||
|
} else if(!object.isObject(msg)) {
|
||||||
|
msg = this.getMessage(msg, (!object.isDefined(msg) && level >= TRACE_WARN));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.traceLevel > level) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._consoleLog(msg, level, details);
|
||||||
|
|
||||||
|
if (setStatus) {
|
||||||
|
event.trigger('humhub:modules:log:setStatus', [msg, details, level]);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error('Error while generating log', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype.getMessage = function (key, returnDefault) {
|
||||||
|
if(!object.isString(key)) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result;
|
||||||
|
|
||||||
|
if(this.module) {
|
||||||
|
result = this.module.text(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
result = module.text(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!result && returnDefault) {
|
||||||
|
result = module.text('default.error');
|
||||||
|
} else if(!result){
|
||||||
|
result = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.prototype._consoleLog = function (msg, level, details) {
|
||||||
|
if (window.console) {
|
||||||
|
var consoleMsg = this.moduleId || 'root';
|
||||||
|
consoleMsg += '(' + traceLevels[level] + '): ' + msg;
|
||||||
|
switch (level) {
|
||||||
|
case TRACE_ERROR:
|
||||||
|
case TRACE_FATAL:
|
||||||
|
console.error(consoleMsg, details);
|
||||||
|
break;
|
||||||
|
case TRACE_WARN:
|
||||||
|
if (details) {
|
||||||
|
console.warn(consoleMsg, details);
|
||||||
|
} else {
|
||||||
|
console.warn(consoleMsg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (details) {
|
||||||
|
console.log(consoleMsg, details);
|
||||||
|
} else {
|
||||||
|
console.log(consoleMsg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function () {
|
||||||
|
module.rootLogger = new Logger();
|
||||||
|
};
|
||||||
|
|
||||||
|
var getRootLogger = function () {
|
||||||
|
if (!module.rootLogger) {
|
||||||
|
module.rootLogger = new Logger();
|
||||||
|
}
|
||||||
|
return module.rootLogger;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getModuleLogger = function (module) {
|
||||||
|
var moduleId = (object.isString(module)) ? module : module.id;
|
||||||
|
if (!logger[moduleId]) {
|
||||||
|
logger[moduleId] = new Logger(module);
|
||||||
|
}
|
||||||
|
return logger[moduleId];
|
||||||
|
};
|
||||||
|
|
||||||
|
var trace = function (msg, details, setStatus) {
|
||||||
|
module.getRootLogger().trace(msg, details, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
var debug = function (msg, details, setStatus) {
|
||||||
|
module.getRootLogger().debug(msg, details, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
var success = function (msg, details, setStatus) {
|
||||||
|
module.getRootLogger().success(msg, details, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
var info = function (msg, details, setStatus) {
|
||||||
|
module.getRootLogger().info(msg, details, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
var warn = function (msg, error, setStatus) {
|
||||||
|
module.getRootLogger().warn(msg, error, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
var error = function (msg, error, setStatus) {
|
||||||
|
module.getRootLogger().error(msg, error, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
var fatal = function (msg, error, setStatus) {
|
||||||
|
module.getRootLogger().fatal(msg, error, setStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
init: init,
|
||||||
|
Logger: Logger,
|
||||||
|
module: getModuleLogger,
|
||||||
|
getRootLogger: getRootLogger,
|
||||||
|
trace: trace,
|
||||||
|
debug: debug,
|
||||||
|
info: info,
|
||||||
|
success: success,
|
||||||
|
warn: warn,
|
||||||
|
error: error,
|
||||||
|
fata: fatal,
|
||||||
|
TRACE_TRACE: TRACE_TRACE,
|
||||||
|
TRACE_DEBUG: TRACE_DEBUG,
|
||||||
|
TRACE_INFO: TRACE_INFO,
|
||||||
|
TRACE_SUCCESS: TRACE_SUCCESS,
|
||||||
|
TRACE_WARN: TRACE_WARN,
|
||||||
|
TRACE_ERROR: TRACE_ERROR,
|
||||||
|
TRACE_OFF: TRACE_OFF
|
||||||
|
});
|
||||||
|
});
|
@ -5,9 +5,12 @@
|
|||||||
* An addition can be registered for a specific selector e.g: <input data-addition-richtext ... />
|
* An addition can be registered for a specific selector e.g: <input data-addition-richtext ... />
|
||||||
* It is possible to register multiple additions for the same selector.
|
* It is possible to register multiple additions for the same selector.
|
||||||
*/
|
*/
|
||||||
humhub.initModule('additions', function(module, require, $) {
|
humhub.initModule('ui.additions', function (module, require, $) {
|
||||||
|
|
||||||
|
var event = require('event');
|
||||||
|
|
||||||
var _additions = {};
|
var _additions = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an addition for a given jQuery selector. There can be registered
|
* Registers an addition for a given jQuery selector. There can be registered
|
||||||
* multiple additions for the same selector.
|
* multiple additions for the same selector.
|
||||||
@ -17,35 +20,47 @@ humhub.initModule('additions', function(module, require, $) {
|
|||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
module.registerAddition = function (selector, addition) {
|
module.registerAddition = function (selector, addition) {
|
||||||
if(!_additions[selector]) {
|
if (!_additions[selector]) {
|
||||||
_additions[selector] = [];
|
_additions[selector] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
_additions[selector].push(addition);
|
_additions[selector].push(addition);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies all matched additions to the given element and its children
|
* Applies all matched additions to the given element and its children
|
||||||
* @param {type} element
|
* @param {type} element
|
||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
module.applyTo = function(element) {
|
module.applyTo = function (element) {
|
||||||
var $element = $(element);
|
var $element = $(element);
|
||||||
$.each(_additions, function(selector, additions) {
|
$.each(_additions, function (selector, additions) {
|
||||||
$.each(additions, function(i, addition) {
|
$.each(additions, function (i, addition) {
|
||||||
$.each($element.find(selector).addBack(selector), function() {
|
$.each($element.find(selector).addBack(selector), function () {
|
||||||
try {
|
try {
|
||||||
var $match = $(this);
|
var $match = $(this);
|
||||||
addition.apply($match, [$match, $element]);
|
addition.apply($match, [$match, $element]);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.error('Error while applying addition '+addition+' on selector '+selector);
|
console.error('Error while applying addition on selector ' + selector, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.init = function() {
|
module.init = function () {
|
||||||
|
event.on('humhub:modules:client:pjax:afterPageLoad', function (evt, cfg) {
|
||||||
|
module.applyTo(cfg.options.container);
|
||||||
|
});
|
||||||
|
|
||||||
|
event.on('humhub:afterInit', function (evt) {
|
||||||
|
module.applyTo($('html'));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.registerAddition('.autosize', function ($match) {
|
||||||
|
$match.autosize();
|
||||||
|
});
|
||||||
|
|
||||||
//TODO: apply to html on startup, the problem is this could crash legacy code.
|
//TODO: apply to html on startup, the problem is this could crash legacy code.
|
||||||
};
|
};
|
||||||
});
|
});
|
@ -1,8 +0,0 @@
|
|||||||
humhub.initModule('ui', function(module, require, $) {
|
|
||||||
var additions = require('additions');
|
|
||||||
module.init = function() {
|
|
||||||
additions.registerAddition('.autosize', function($match) {
|
|
||||||
$match.autosize();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
166
js/humhub/humhub.ui.loader.js
Normal file
166
js/humhub/humhub.ui.loader.js
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* Module for adding loader animations to dom nodes.
|
||||||
|
*
|
||||||
|
* The default loader animation can be added or appended/prepended as follows
|
||||||
|
*
|
||||||
|
* var loader = require('ui.loader');
|
||||||
|
*
|
||||||
|
* // Overwrite current html content with loader animation
|
||||||
|
* loader.set(myNode);
|
||||||
|
*
|
||||||
|
* // Remove loader animation
|
||||||
|
* loader.reset(myNode);
|
||||||
|
*
|
||||||
|
* The loader module also adds an click handler to all buttons and links with a
|
||||||
|
* data-ui-loader attribute set.
|
||||||
|
*
|
||||||
|
* If a data-ui-loader button is used within a yii ActiveForm we automaticly reset all loader buttons
|
||||||
|
* in case of form validation errors.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param {type} param1
|
||||||
|
* @param {type} param2
|
||||||
|
*/
|
||||||
|
humhub.initModule('ui.loader', function (module, require, $) {
|
||||||
|
|
||||||
|
var DEFAULT_LOADER_SELECTOR = '#humhub-ui-loader-default';
|
||||||
|
|
||||||
|
module.initOnPjaxLoad = false;
|
||||||
|
|
||||||
|
var set = function (node, cfg) {
|
||||||
|
var $node = $(node);
|
||||||
|
if ($node.length) {
|
||||||
|
$node.each(function () {
|
||||||
|
var $this = $(this);
|
||||||
|
$this.data('htmlOld', $node.html());
|
||||||
|
$this.html(getInstance(cfg));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var append = function (node, cfg) {
|
||||||
|
var $node = $(node);
|
||||||
|
if ($node.length) {
|
||||||
|
$node.append(getInstance(cfg));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var prepend = function (node, cfg) {
|
||||||
|
var $node = $(node);
|
||||||
|
if ($node.length) {
|
||||||
|
$node.prepend(getInstance(cfg));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var reset = function (node) {
|
||||||
|
var $node = $(node);
|
||||||
|
var $loader = $node.find('.loader').length;
|
||||||
|
if (!$loader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$node.removeClass('disabled');
|
||||||
|
|
||||||
|
if ($loader && $node.data('htmlOld')) {
|
||||||
|
$node.html($node.data('htmlOld'));
|
||||||
|
} else if ($loader) {
|
||||||
|
$node.find('.loader').remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var getInstance = function (cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
|
||||||
|
var $result = $(DEFAULT_LOADER_SELECTOR).clone().removeAttr('id').show();
|
||||||
|
|
||||||
|
if (cfg['cssClass']) {
|
||||||
|
$result.addClass(cfg['cssClass']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg['id']) {
|
||||||
|
$result.attr('id', cfg['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg['css']) {
|
||||||
|
$result.css(cfg['css']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg['position']) {
|
||||||
|
if (cfg['position'] === 'left') {
|
||||||
|
$result.find('.sk-spinner').css('margin', '0');
|
||||||
|
}
|
||||||
|
$result.css(cfg['css']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg['size']) {
|
||||||
|
var size = cfg['size'];
|
||||||
|
$result.find('.sk-bounce1').css({'width': size, 'height': size});
|
||||||
|
$result.find('.sk-bounce2').css({'width': size, 'height': size});
|
||||||
|
$result.find('.sk-bounce3').css({'width': size, 'height': size});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function (cfg) {
|
||||||
|
$(document).on('click.humhub:modules:ui:loader', 'a[data-ui-loader], button[data-ui-loader]', function (evt) {
|
||||||
|
module.initLoaderButton(this, evt);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('afterValidate.humhub:modules:ui:loader', function (evt, messages, errors) {
|
||||||
|
if (errors.length) {
|
||||||
|
$(evt.target).find('[data-ui-loader]').each(function () {
|
||||||
|
reset(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var initLoaderButton = function (node, evt) {
|
||||||
|
var $node = $(node);
|
||||||
|
var loader = $node.find('.loader').length > 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent multiple mouse clicks, if originalEvent is present its a real mouse event otherwise its script triggered
|
||||||
|
* This is a workaround since yii version 2.0.10 changed the activeForm submission from $form.submit() to data.submitObject.trigger("click");
|
||||||
|
* which triggers this handler twice. Here we get sure not to block the script triggered submission.
|
||||||
|
*/
|
||||||
|
if (loader && evt.originalEvent) {
|
||||||
|
return false;
|
||||||
|
} else if (loader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adopt current color for the loader animation
|
||||||
|
var color = $node.css('color') || '#ffffff';
|
||||||
|
var $loader = $(module.template);
|
||||||
|
|
||||||
|
// Align bouncer animation color and size
|
||||||
|
$loader.find('.sk-bounce1, .sk-bounce2, .sk-bounce3')
|
||||||
|
.addClass('disabled')
|
||||||
|
.css({'background-color': color, 'width': '10px', 'height': '10px'});
|
||||||
|
|
||||||
|
// The loader does have some margin we have to hide
|
||||||
|
$node.css('overflow', 'hidden');
|
||||||
|
$node.addClass('disabled');
|
||||||
|
|
||||||
|
// Prevent the container from resizing
|
||||||
|
$node.css('min-width', node.getBoundingClientRect().width);
|
||||||
|
$node.data('htmlOld', $node.html());
|
||||||
|
$node.html($loader);
|
||||||
|
};
|
||||||
|
|
||||||
|
var template = '<span class="loader"><span class="sk-spinner sk-spinner-three-bounce"><span class="sk-bounce1"></span><span class="sk-bounce2"></span><span class="sk-bounce3"></span></span></span>';
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
set: set,
|
||||||
|
append: append,
|
||||||
|
prepend: prepend,
|
||||||
|
reset: reset,
|
||||||
|
getInstance: getInstance,
|
||||||
|
template: template,
|
||||||
|
initLoaderButton: initLoaderButton,
|
||||||
|
init: init
|
||||||
|
});
|
||||||
|
});
|
@ -17,14 +17,26 @@
|
|||||||
*/
|
*/
|
||||||
humhub.initModule('ui.modal', function (module, require, $) {
|
humhub.initModule('ui.modal', function (module, require, $) {
|
||||||
var object = require('util').object;
|
var object = require('util').object;
|
||||||
var additions = require('additions');
|
var additions = require('ui.additions');
|
||||||
var config = humhub.config.getModuleConfig('ui.modal');
|
var config = require('config').module(module);
|
||||||
|
|
||||||
|
var loader = require('ui.loader');
|
||||||
|
|
||||||
|
module.initOnPjaxLoad = false;
|
||||||
|
|
||||||
//Keeps track of all initialized modals
|
//Keeps track of all initialized modals
|
||||||
var modals = [];
|
var modals = [];
|
||||||
|
|
||||||
var TMPL_MODAL_CONTAINER = '<div class="modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none; background:rgba(0,0,0,0.1)"><div class="modal-dialog"><div class="modal-content"></div></div></div>';
|
|
||||||
var TMPL_MODAL_HEADER = '<div class="modal-header"><button type="button" class="close" data-modal-close="true" aria-hidden="true">×</button><h4 class="modal-title"></h4></div>';
|
/**
|
||||||
var TMPL_MODAL_BODY = '<div class="modal-body"></div>';
|
* Template for the modal splitted into different parts. Those can be overwritten my changing or overwriting module.template.
|
||||||
|
*/
|
||||||
|
var template = {
|
||||||
|
container : '<div class="modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none; background:rgba(0,0,0,0.1)"><div class="modal-dialog"><div class="modal-content"></div></div></div>',
|
||||||
|
header : '<div class="modal-header"><button type="button" class="close" data-modal-close="true" aria-hidden="true">×</button><h4 class="modal-title"></h4></div>',
|
||||||
|
body: '<div class="modal-body"></div>',
|
||||||
|
}
|
||||||
|
|
||||||
var ERROR_DEFAULT_TITLE = 'Error';
|
var ERROR_DEFAULT_TITLE = 'Error';
|
||||||
var ERROR_DEFAULT_MESSAGE = 'An unknown error occured!';
|
var ERROR_DEFAULT_MESSAGE = 'An unknown error occured!';
|
||||||
|
|
||||||
@ -50,7 +62,7 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
Modal.prototype.createModal = function (id) {
|
Modal.prototype.createModal = function (id) {
|
||||||
this.$modal = $(TMPL_MODAL_CONTAINER).attr('id', id);
|
this.$modal = $(module.template.container).attr('id', id);
|
||||||
$('body').append(this.$modal);
|
$('body').append(this.$modal);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -97,7 +109,7 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
Modal.prototype.reset = function () {
|
Modal.prototype.reset = function () {
|
||||||
this.setBody('<div class="loader"><div class="sk-spinner sk-spinner-three-bounce"><div class="sk-bounce1"></div><div class="sk-bounce2"></div><div class="sk-bounce3"></div></div></div>');
|
loader.set(this.$body);
|
||||||
this.isFilled = false;
|
this.isFilled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -241,7 +253,7 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
Modal.prototype.setTitle = function (title) {
|
Modal.prototype.setTitle = function (title) {
|
||||||
var $header = this.getHeader();
|
var $header = this.getHeader();
|
||||||
if (!$header.length) {
|
if (!$header.length) {
|
||||||
this.getContent().prepend($(TMPL_MODAL_HEADER));
|
this.getContent().prepend($(module.template.header));
|
||||||
$header = this.getHeader();
|
$header = this.getHeader();
|
||||||
}
|
}
|
||||||
$header.find('.modal-title').html(title);
|
$header.find('.modal-title').html(title);
|
||||||
@ -255,7 +267,7 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
Modal.prototype.setBody = function (content) {
|
Modal.prototype.setBody = function (content) {
|
||||||
var $body = this.getBody();
|
var $body = this.getBody();
|
||||||
if (!$body.length) {
|
if (!$body.length) {
|
||||||
this.getContent().append($(TMPL_MODAL_BODY));
|
this.getContent().append($(module.template.body));
|
||||||
$body = this.getBody();
|
$body = this.getBody();
|
||||||
}
|
}
|
||||||
$body.html(content);
|
$body.html(content);
|
||||||
@ -277,13 +289,14 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
return this.$modal.find('.modal-body');
|
return this.$modal.find('.modal-body');
|
||||||
};
|
};
|
||||||
|
|
||||||
var ConfirmModal = function(id, cfg) {
|
var ConfirmModal = function(id) {
|
||||||
Modal.call(this, id);
|
Modal.call(this, id);
|
||||||
};
|
};
|
||||||
|
|
||||||
object.inherits(ConfirmModal, Modal);
|
object.inherits(ConfirmModal, Modal);
|
||||||
|
|
||||||
ConfirmModal.prototype.open = function(cfg) {
|
ConfirmModal.prototype.open = function(cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
this.clear();
|
this.clear();
|
||||||
cfg['header'] = cfg['header'] || config['defaultConfirmHeader'];
|
cfg['header'] = cfg['header'] || config['defaultConfirmHeader'];
|
||||||
cfg['body'] = cfg['body'] || config['defaultConfirmBody'];
|
cfg['body'] = cfg['body'] || config['defaultConfirmBody'];
|
||||||
@ -323,8 +336,6 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
cfg['cancel'](evt);
|
cfg['cancel'](evt);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.export({
|
module.export({
|
||||||
@ -335,6 +346,7 @@ humhub.initModule('ui.modal', function (module, require, $) {
|
|||||||
module.globalConfirm.open(cfg);
|
module.globalConfirm.open(cfg);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
Modal: Modal
|
Modal: Modal,
|
||||||
|
template: template
|
||||||
});
|
});
|
||||||
});
|
});
|
189
js/humhub/humhub.ui.status.js
Normal file
189
js/humhub/humhub.ui.status.js
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {type} param1
|
||||||
|
* @param {type} param2
|
||||||
|
*/
|
||||||
|
humhub.initModule('ui.status', function (module, require, $) {
|
||||||
|
|
||||||
|
var event = require('event');
|
||||||
|
var log = require('log');
|
||||||
|
var object = require('util').object;
|
||||||
|
|
||||||
|
var SELECTOR_ROOT = '#status-bar';
|
||||||
|
var SELECTOR_BODY = '.status-bar-body';
|
||||||
|
var SELECTOR_CONTENT = '.status-bar-content';
|
||||||
|
|
||||||
|
var AUTOCLOSE_DELAY = 6000;
|
||||||
|
|
||||||
|
var StatusBar = function () {
|
||||||
|
this.$ = $(SELECTOR_ROOT);
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.info = function (msg, closeAfter) {
|
||||||
|
closeAfter = closeAfter || AUTOCLOSE_DELAY;
|
||||||
|
this._trigger('<i class="fa fa-info-circle info"></i><span>' + msg + '</span>', undefined, closeAfter);
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.success = function (msg, closeAfter) {
|
||||||
|
closeAfter = closeAfter || AUTOCLOSE_DELAY;
|
||||||
|
this._trigger('<i class="fa fa-check-circle success"></i><span>' + msg + '</span>', undefined, closeAfter);
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.warning = function (msg, error, closeAfter) {
|
||||||
|
this._trigger('<i class="fa fa-exclamation-triangle warning"></i><span>' + msg + '</span>', error, closeAfter);
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.error = function (msg, error, closeAfter) {
|
||||||
|
this._trigger('<i class="fa fa-exclamation-circle error"></i><span>' + msg + '</span>', error, closeAfter);
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype._trigger = function (content, error, closeAfter) {
|
||||||
|
if (this.closeTimer) {
|
||||||
|
clearTimeout(this.closeTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
this.hide(function () {
|
||||||
|
that.setContent(content, error).show(function () {
|
||||||
|
if (closeAfter > 0) {
|
||||||
|
that.closeTimer = setTimeout(function () {
|
||||||
|
that.hide();
|
||||||
|
}, closeAfter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.setContent = function (content, error) {
|
||||||
|
var that = this;
|
||||||
|
var $content = this.$.find(SELECTOR_CONTENT).html(content);
|
||||||
|
var $closeButton = $('<a class="status-bar-close pull-right" style="">×</a>');
|
||||||
|
|
||||||
|
if (error && module.config['showMore']) {
|
||||||
|
this._addShowMoreButton($content, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$closeButton.on('click', function () {
|
||||||
|
that.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
$content.prepend($closeButton);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype._addShowMoreButton = function ($content, error) {
|
||||||
|
var $showMore = $('<a class="showMore"><i class="fa fa-angle-up"></i></a>');
|
||||||
|
$showMore.on('click', function () {
|
||||||
|
var $details = $content.find('.status-bar-details');
|
||||||
|
if($details.length) {
|
||||||
|
$details.stop().slideToggle('fast', function() {
|
||||||
|
$details.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
$showMore.find('i').attr('class', 'fa fa-angle-up');
|
||||||
|
} else {
|
||||||
|
$details = $('<div class="status-bar-details" style="display:none;"><pre>' + getErrorMessage(error) + '</pre><div>');
|
||||||
|
$content.append($details);
|
||||||
|
$details.slideToggle('fast');
|
||||||
|
$showMore.find('i').attr('class', 'fa fa-angle-down');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$content.append($showMore);
|
||||||
|
};
|
||||||
|
|
||||||
|
var getErrorMessage = function (error) {
|
||||||
|
try {
|
||||||
|
if (!error) {
|
||||||
|
return;
|
||||||
|
} else if (object.isString(error)) {
|
||||||
|
return error;
|
||||||
|
} else if (error instanceof Error) {
|
||||||
|
var result = error.toString();
|
||||||
|
if(error.stack) {
|
||||||
|
result += error.stack;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return JSON.stringify(error, null, 4);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBar.prototype.show = function (callback) {
|
||||||
|
// Make the container transparent for beeing able to measure the body height
|
||||||
|
this.$.css('opacity', 0);
|
||||||
|
this.$.show();
|
||||||
|
|
||||||
|
// Prepare the body node for animation, we set auto height to get the real node height
|
||||||
|
var $body = this.$.find(SELECTOR_BODY).stop().css('height', 'auto');
|
||||||
|
var height = $body.innerHeight();
|
||||||
|
|
||||||
|
// Hide element before animation
|
||||||
|
$body.css({'opacity': '0', 'bottom': -height});
|
||||||
|
|
||||||
|
// Show root container
|
||||||
|
this.$.css('opacity', 1);
|
||||||
|
|
||||||
|
$body.animate({bottom: '0', opacity: 1.0}, 500, function () {
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.hide = function (callback) {
|
||||||
|
var that = this;
|
||||||
|
var $body = this.$.find(SELECTOR_BODY);
|
||||||
|
var height = $body.innerHeight();
|
||||||
|
|
||||||
|
$body.stop().animate({bottom: -height, opacity:0}, 500, function () {
|
||||||
|
that.$.hide();
|
||||||
|
$body.css('bottom', '0');
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function () {
|
||||||
|
module.statusBar = new StatusBar();
|
||||||
|
event.on('humhub:modules:log:setStatus', function (evt, msg, details, level) {
|
||||||
|
switch (level) {
|
||||||
|
case log.TRACE_ERROR:
|
||||||
|
case log.TRACE_FATAL:
|
||||||
|
module.statusBar.error(msg, details);
|
||||||
|
break;
|
||||||
|
case log.TRACE_WARN:
|
||||||
|
module.statusBar.warning(msg, details);
|
||||||
|
break;
|
||||||
|
case log.TRACE_SUCCESS:
|
||||||
|
module.statusBar.success(msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
module.statusBar.info(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
init: init,
|
||||||
|
StatusBar: StatusBar,
|
||||||
|
success: function (msg, closeAfter) {
|
||||||
|
module.statusBar.success(msg, closeAfter);
|
||||||
|
},
|
||||||
|
info: function (msg, closeAfter) {
|
||||||
|
module.statusBar.info(msg, closeAfter);
|
||||||
|
},
|
||||||
|
warn: function (msg, error, closeAfter) {
|
||||||
|
module.statusBar.warn(msg, error, closeAfter);
|
||||||
|
},
|
||||||
|
error: function (msg, error, closeAfter) {
|
||||||
|
module.statusBar.error(msg, error, closeAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
135
js/humhub/humhub.ui.tabbedForm.js
Normal file
135
js/humhub/humhub.ui.tabbedForm.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/**
|
||||||
|
* Module for creating an manipulating modal dialoges.
|
||||||
|
* Normal layout of a dialog:
|
||||||
|
*
|
||||||
|
* <div class="modal">
|
||||||
|
* <div class="modal-dialog">
|
||||||
|
* <div class="modal-content">
|
||||||
|
* <div class="modal-header"></div>
|
||||||
|
* <div class="modal-body"></div>
|
||||||
|
* <div class="modal-footer"></div>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
* @param {type} param1
|
||||||
|
* @param {type} param2
|
||||||
|
*/
|
||||||
|
humhub.initModule('ui.tabbedForm', function (module, require, $) {
|
||||||
|
|
||||||
|
|
||||||
|
var additions = require('ui.additions');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares all included fieldsets for $form indexed
|
||||||
|
* by its label (legend).
|
||||||
|
*
|
||||||
|
* @param {type} $form
|
||||||
|
* @returns {$lastFieldSet$fieldSet} Array of fieldsets indexed by its label
|
||||||
|
*/
|
||||||
|
var getPreparedFieldSets = function ($form) {
|
||||||
|
var result = {};
|
||||||
|
var $lastFieldSet;
|
||||||
|
|
||||||
|
// Assamble all fieldsets with label
|
||||||
|
$form.find('fieldset').each(function () {
|
||||||
|
var $fieldSet = $(this).hide();
|
||||||
|
|
||||||
|
var legend = $fieldSet.children('legend').text();
|
||||||
|
|
||||||
|
// If we have a label we add the fieldset as is else we append its inputs to the previous fieldset
|
||||||
|
if (legend && legend.length) {
|
||||||
|
result[legend] = $lastFieldSet = $fieldSet;
|
||||||
|
} else if($lastFieldSet) {
|
||||||
|
$lastFieldSet.append($fieldSet.children(".form-group"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for errors in a specific category.
|
||||||
|
* @param _object
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
var hasErrors = function($fieldSet) {
|
||||||
|
return $fieldSet.find('.error, .has-error').length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var init = function () {
|
||||||
|
additions.registerAddition('[data-ui-tabbed-form]', function ($form) {
|
||||||
|
var activeTab = 0;
|
||||||
|
|
||||||
|
var $tabContent = $('<div class="tab-content"></div>');
|
||||||
|
var $tabs = $('<ul id="profile-tabs" class="nav nav-tabs" data-tabs="tabs"></ul>');
|
||||||
|
$form.prepend($tabContent);
|
||||||
|
$form.prepend($tabs);
|
||||||
|
|
||||||
|
var index = 0;
|
||||||
|
$.each(getPreparedFieldSets($form), function (label, $fieldSet) {
|
||||||
|
|
||||||
|
// activate this tab if there are any errors
|
||||||
|
if (hasErrors($fieldSet)) {
|
||||||
|
activeTab = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init tab structure
|
||||||
|
$tabs.append('<li><a href="#tab-' + index + '" data-toggle="tab">' + label + '</a></li>');
|
||||||
|
$tabContent.append('<div class="tab-pane" data-tab-index="' + index + '" id="tab-' + index + '"></div>');
|
||||||
|
|
||||||
|
// clone inputs from fieldSet into our tab structure
|
||||||
|
var $inputs = $fieldSet.children(".form-group");
|
||||||
|
$('#tab-' + index).html($inputs.clone());
|
||||||
|
|
||||||
|
// remove old fieldset from dom
|
||||||
|
$fieldSet.remove();
|
||||||
|
|
||||||
|
// change tab on tab key for the last input of each tab
|
||||||
|
var tabIndex = index;
|
||||||
|
$tabContent.find('.form-control').last().on('keydown', function (e) {
|
||||||
|
var keyCode = e.keyCode || e.which;
|
||||||
|
|
||||||
|
if (keyCode === 9) { //Tab
|
||||||
|
var $nextTabLink = $tabs.find('a[href="#tab-' + (tabIndex + 1) + '"]');
|
||||||
|
if ($nextTabLink.length) {
|
||||||
|
e.preventDefault();
|
||||||
|
$nextTabLink.tab('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
index++;
|
||||||
|
});
|
||||||
|
|
||||||
|
// prepend error summary to form if exists
|
||||||
|
var $errorSummary = $('.errorSummary');
|
||||||
|
if ($errorSummary.length) {
|
||||||
|
$form.prepend($errorSummary.clone());
|
||||||
|
$errorSummary.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// focus first input on tab change
|
||||||
|
$form.find('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
|
var tabId = $(e.target).attr('href'); // newly activated tab
|
||||||
|
$(tabId).find('.form-control').first().focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// activate the first tab or the tab with errors
|
||||||
|
$tabs.find('a[href="#tab-' + activeTab + '"]').tab('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure frontend validation also activates the tab with errors.
|
||||||
|
$(document).on('afterValidate.humhub:ui:tabbedForm', function (evt, messages, errors) {
|
||||||
|
if (errors.length) {
|
||||||
|
var index = $(errors[0].container).closest('.tab-pane').data('tab-index');
|
||||||
|
$('a[href="#tab-' + index + '"]').tab('show');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
init: init
|
||||||
|
});
|
||||||
|
});
|
@ -166,23 +166,6 @@ $(document).ready(function () {
|
|||||||
setModalHandler();
|
setModalHandler();
|
||||||
|
|
||||||
initPlugins();
|
initPlugins();
|
||||||
|
|
||||||
$(document).on('click', 'a[data-ui-loader], button[data-ui-loader]', function () {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('afterValidate', function(evt, messages, errors) {
|
|
||||||
if(errors.length) {
|
|
||||||
$('[data-ui-loader]').each(function() {
|
|
||||||
var $this = $(this);
|
|
||||||
if($this.find('.loader').length) {
|
|
||||||
$this.html($this.data('text'));
|
|
||||||
$this.removeClass('disabled');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function setModalHandler() {
|
function setModalHandler() {
|
||||||
|
112
js/tabbedForm.js
112
js/tabbedForm.js
@ -1,112 +0,0 @@
|
|||||||
$(document).ready(function () {
|
|
||||||
/**
|
|
||||||
* Prepares all included fieldsets for $form indexed
|
|
||||||
* by its label (legend).
|
|
||||||
*
|
|
||||||
* @param {type} $form
|
|
||||||
* @returns {$lastFieldSet$fieldSet} Array of fieldsets indexed by its label
|
|
||||||
*/
|
|
||||||
var getPreparedFieldSets = function ($form) {
|
|
||||||
var result = {};
|
|
||||||
var $lastFieldSet;
|
|
||||||
|
|
||||||
// Assamble all fieldsets with label
|
|
||||||
$form.find('fieldset').each(function () {
|
|
||||||
var $fieldSet = $(this).hide();
|
|
||||||
|
|
||||||
var legend = $fieldSet.children('legend').text();
|
|
||||||
|
|
||||||
// If we have a label we add the fieldset as is else we append its inputs to the previous fieldset
|
|
||||||
if (legend && legend.length) {
|
|
||||||
result[legend] = $lastFieldSet = $fieldSet;
|
|
||||||
} else if($lastFieldSet) {
|
|
||||||
$lastFieldSet.append($fieldSet.children(".form-group"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for errors in a specific category.
|
|
||||||
* @param _object
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
var hasErrors = function($fieldSet) {
|
|
||||||
return $fieldSet.find('.error, .has-error').length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize tabbed forms.
|
|
||||||
* Note: this currently does only work with on form per page because of the tab id's
|
|
||||||
*/
|
|
||||||
$('[data-ui-tabbed-form]').each(function () {
|
|
||||||
var activeTab = 0;
|
|
||||||
|
|
||||||
var $form = $(this);
|
|
||||||
var $tabContent = $('<div class="tab-content"></div>');
|
|
||||||
var $tabs = $('<ul id="profile-tabs" class="nav nav-tabs" data-tabs="tabs"></ul>');
|
|
||||||
$form.prepend($tabContent);
|
|
||||||
$form.prepend($tabs);
|
|
||||||
|
|
||||||
var index = 0;
|
|
||||||
$.each(getPreparedFieldSets($form), function(label, $fieldSet) {
|
|
||||||
|
|
||||||
// activate this tab if there are any errors
|
|
||||||
if (hasErrors($fieldSet)) {
|
|
||||||
activeTab = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init tab structure
|
|
||||||
$tabs.append('<li><a href="#tab-' + index + '" data-toggle="tab">' + label + '</a></li>');
|
|
||||||
$tabContent.append('<div class="tab-pane" data-tab-index="'+index+'" id="tab-' + index + '"></div>');
|
|
||||||
|
|
||||||
// clone inputs from fieldSet into our tab structure
|
|
||||||
var $inputs = $fieldSet.children(".form-group");
|
|
||||||
$('#tab-' + index).html($inputs.clone());
|
|
||||||
|
|
||||||
// remove old fieldset from dom
|
|
||||||
$fieldSet.remove();
|
|
||||||
|
|
||||||
// change tab on tab key for the last input of each tab
|
|
||||||
var tabIndex = index;
|
|
||||||
$tabContent.find('.form-control').last().on('keydown', function(e) {
|
|
||||||
var keyCode = e.keyCode || e.which;
|
|
||||||
|
|
||||||
if(keyCode === 9) { //Tab
|
|
||||||
var $nextTabLink = $tabs.find('a[href="#tab-' + (tabIndex+1) + '"]');
|
|
||||||
if($nextTabLink.length) {
|
|
||||||
e.preventDefault();
|
|
||||||
$nextTabLink.tab('show');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
index++;
|
|
||||||
});
|
|
||||||
|
|
||||||
// prepend error summary to form if exists
|
|
||||||
var $errorSummary = $('.errorSummary');
|
|
||||||
if ($errorSummary.length) {
|
|
||||||
$form.prepend($errorSummary.clone());
|
|
||||||
$errorSummary.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// focus first input on tab change
|
|
||||||
$form.find('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
|
||||||
var tabId = $(e.target).attr('href'); // newly activated tab
|
|
||||||
$(tabId).find('.form-control').first().focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// activate the first tab or the tab with errors
|
|
||||||
$tabs.find('a[href="#tab-' + activeTab + '"]').tab('show');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Make sure frontend validation also activates the tab with errors.
|
|
||||||
$(document).on('afterValidate', function(evt, messages, errors) {
|
|
||||||
if(errors.length) {
|
|
||||||
var index = $(errors[0].container).closest('.tab-pane').data('tab-index');
|
|
||||||
$('a[href="#tab-' + index + '"]').tab('show');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -45,13 +45,15 @@ class CoreApiAsset extends AssetBundle
|
|||||||
'js/humhub/legacy/app.js',
|
'js/humhub/legacy/app.js',
|
||||||
'js/humhub/humhub.core.js',
|
'js/humhub/humhub.core.js',
|
||||||
'js/humhub/humhub.util.js',
|
'js/humhub/humhub.util.js',
|
||||||
|
'js/humhub/humhub.log.js',
|
||||||
//'js/humhub/humhub.scripts.js',
|
//'js/humhub/humhub.scripts.js',
|
||||||
'js/humhub/humhub.additions.js',
|
'js/humhub/humhub.ui.status.js',
|
||||||
|
'js/humhub/humhub.ui.additions.js',
|
||||||
|
'js/humhub/humhub.ui.loader.js',
|
||||||
|
'js/humhub/humhub.ui.modal.js',
|
||||||
'js/humhub/humhub.client.js',
|
'js/humhub/humhub.client.js',
|
||||||
'js/humhub/humhub.client.pjax.js',
|
'js/humhub/humhub.client.pjax.js',
|
||||||
'js/humhub/humhub.ui.js',
|
'js/humhub/humhub.action.js'
|
||||||
'js/humhub/humhub.ui.modal.js',
|
|
||||||
'js/humhub/humhub.actions.js'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
91
protected/humhub/assets/HumHub.php
Executable file
91
protected/humhub/assets/HumHub.php
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\assets;
|
||||||
|
|
||||||
|
use yii\web\AssetBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AppAsset assets are included in the core layout.
|
||||||
|
* This Assetbundle includes some core dependencies and the humhub core api.
|
||||||
|
*/
|
||||||
|
class AppAsset extends AssetBundle
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $basePath = '@webroot';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $baseUrl = '@web';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $css = [
|
||||||
|
'css/temp.css',
|
||||||
|
'css/bootstrap-wysihtml5.css',
|
||||||
|
'css/flatelements.css',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $jsOptions = ['position' => \yii\web\View::POS_BEGIN];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $js = [
|
||||||
|
'js/ekko-lightbox-modified.js',
|
||||||
|
//'js/modernizr.js', // In use???
|
||||||
|
'js/jquery.highlight.min.js',
|
||||||
|
//'js/wysihtml5-0.3.0.js',
|
||||||
|
//'js/bootstrap3-wysihtml5.js',
|
||||||
|
'js/desktop-notify-min.js',
|
||||||
|
'js/desktop-notify-config.js',
|
||||||
|
'js/jquery.nicescroll.min.js',
|
||||||
|
'resources/file/fileuploader.js',
|
||||||
|
'resources/user/userpicker.js',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $depends = [
|
||||||
|
'yii\web\YiiAsset',
|
||||||
|
'yii\bootstrap\BootstrapAsset',
|
||||||
|
'yii\bootstrap\BootstrapPluginAsset',
|
||||||
|
/**
|
||||||
|
* Temporary disabled
|
||||||
|
* https://github.com/inuyaksa/jquery.nicescroll/issues/574
|
||||||
|
*/
|
||||||
|
//'humhub\assets\JqueryNiceScrollAsset',
|
||||||
|
'humhub\assets\BluebirdAsset',
|
||||||
|
'humhub\assets\JqueryTimeAgoAsset',
|
||||||
|
'humhub\assets\JqueryWidgetAsset',
|
||||||
|
'humhub\assets\JqueryColorAsset', //TODO: only required for post/comment/stream
|
||||||
|
'humhub\assets\JqueryPlaceholderAsset',
|
||||||
|
'humhub\assets\FontAwesomeAsset',
|
||||||
|
'humhub\assets\BlueimpFileUploadAsset',
|
||||||
|
'humhub\assets\JqueryHighlightAsset',
|
||||||
|
'humhub\assets\JqueryCookieAsset',
|
||||||
|
'humhub\assets\JqueryAutosizeAsset',
|
||||||
|
'humhub\assets\AtJsAsset',
|
||||||
|
'humhub\assets\AnimateCssAsset',
|
||||||
|
'humhub\assets\CoreApiAsset',
|
||||||
|
'humhub\modules\content\assets\ContentAsset',
|
||||||
|
'humhub\assets\NProgressAsset',
|
||||||
|
'humhub\assets\IE9FixesAsset',
|
||||||
|
'humhub\assets\IEFixesAsset',
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
@ -18,7 +18,7 @@ use yii\web\AssetBundle;
|
|||||||
class TabbedFormAsset extends AssetBundle
|
class TabbedFormAsset extends AssetBundle
|
||||||
{
|
{
|
||||||
|
|
||||||
public $jsOptions = ['position' => \yii\web\View::POS_BEGIN];
|
public $jsOptions = ['position' => \yii\web\View::POS_END];
|
||||||
|
|
||||||
public $basePath = '@webroot';
|
public $basePath = '@webroot';
|
||||||
public $baseUrl = '@web';
|
public $baseUrl = '@web';
|
||||||
@ -26,10 +26,10 @@ class TabbedFormAsset extends AssetBundle
|
|||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
public $js = ['js/tabbedForm.js'];
|
public $js = ['js/humhub/humhub.ui.tabbedForm.js'];
|
||||||
|
|
||||||
public $depends = [
|
public $depends = [
|
||||||
'humhub\assets\AppAsset'
|
'humhub\assets\CoreApiAsset'
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ class View extends \yii\web\View
|
|||||||
{
|
{
|
||||||
|
|
||||||
private $_pageTitle;
|
private $_pageTitle;
|
||||||
|
private $jsConfig = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets current page title
|
* Sets current page title
|
||||||
@ -50,6 +51,21 @@ class View extends \yii\web\View
|
|||||||
$jsCode = "var " . $name . " = '" . addslashes($value) . "';\n";
|
$jsCode = "var " . $name . " = '" . addslashes($value) . "';\n";
|
||||||
$this->registerJs($jsCode, View::POS_HEAD, $name);
|
$this->registerJs($jsCode, View::POS_HEAD, $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function registerJsConfig($module, $params = null) {
|
||||||
|
if(is_array($module)) {
|
||||||
|
foreach($module as $moduleId => $value) {
|
||||||
|
$this->registerJsConfig($moduleId, $value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($this->jsConfig[$module])) {
|
||||||
|
$this->jsConfig[$module] = yii\helpers\ArrayHelper::merge($this->jsConfig[$module], $params);
|
||||||
|
} else {
|
||||||
|
$this->jsConfig[$module] = $params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a string as Ajax including assets.
|
* Renders a string as Ajax including assets.
|
||||||
@ -124,12 +140,16 @@ class View extends \yii\web\View
|
|||||||
*/
|
*/
|
||||||
public function endBody()
|
public function endBody()
|
||||||
{
|
{
|
||||||
|
$this->registerJs("humhub.config.set(".json_encode($this->jsConfig).");", View::POS_BEGIN, 'jsConfig');
|
||||||
|
|
||||||
if (Yii::$app->request->isAjax) {
|
if (Yii::$app->request->isAjax) {
|
||||||
return parent::endBody();
|
return parent::endBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo \humhub\widgets\LayoutAddons::widget();
|
||||||
|
|
||||||
// Add Layout Addons
|
// Add Layout Addons
|
||||||
return \humhub\widgets\LayoutAddons::widget() . parent::endBody();
|
return parent::endBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/**
|
/**
|
||||||
* This file is generated by the "yii asset" command.
|
* This file is generated by the "yii asset" command.
|
||||||
* DO NOT MODIFY THIS FILE DIRECTLY.
|
* DO NOT MODIFY THIS FILE DIRECTLY.
|
||||||
* @version 2016-09-12 17:54:43
|
* @version 2016-10-21 15:35:07
|
||||||
*/
|
*/
|
||||||
return [
|
return [
|
||||||
'all' => [
|
'all' => [
|
||||||
@ -10,11 +10,13 @@ return [
|
|||||||
'basePath' => '@webroot',
|
'basePath' => '@webroot',
|
||||||
'baseUrl' => '@web',
|
'baseUrl' => '@web',
|
||||||
'js' => [
|
'js' => [
|
||||||
'js/all-cbb2ffbc142aa643edde05905376dd29.js',
|
'js/all-a366b3723e2189716ce68fbe333d59bd.js',
|
||||||
],
|
],
|
||||||
'css' => [
|
'css' => [
|
||||||
'css/all-5f84fd9cb4f93bb90cc038bed1ec4f2d.css',
|
'css/all-2d605362857c9db6fdb10a1df599e902.css',
|
||||||
],
|
],
|
||||||
|
'sourcePath' => null,
|
||||||
|
'depends' => [],
|
||||||
],
|
],
|
||||||
'yii\\web\\JqueryAsset' => [
|
'yii\\web\\JqueryAsset' => [
|
||||||
'sourcePath' => null,
|
'sourcePath' => null,
|
||||||
|
@ -87,7 +87,6 @@ $config = [
|
|||||||
'class' => '\humhub\components\AssetManager',
|
'class' => '\humhub\components\AssetManager',
|
||||||
'appendTimestamp' => true,
|
'appendTimestamp' => true,
|
||||||
'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),
|
'bundles' => require(__DIR__ . '/' . (YII_ENV_PROD ? 'assets-prod.php' : 'assets-dev.php')),
|
||||||
#'bundles' => require(__DIR__ . '/' . 'assets-prod.php'),
|
|
||||||
],
|
],
|
||||||
'view' => [
|
'view' => [
|
||||||
'class' => '\humhub\components\View',
|
'class' => '\humhub\components\View',
|
||||||
|
@ -12,10 +12,24 @@ Build
|
|||||||
- npm update (in humhub root)
|
- npm update (in humhub root)
|
||||||
- npm install grunt --save-dev
|
- npm install grunt --save-dev
|
||||||
|
|
||||||
|
|
||||||
## Assets
|
## Assets
|
||||||
- Yii asset management http://www.yiiframework.com/doc-2.0/guide-structure-assets.html#combining-compressing-assets
|
|
||||||
- php yii asset humhub/config/assets.php humhub/config/assets-prod.php
|
HumHub uses the Yii's build in mechanism for compressing and combining assets as javascript or stylesheet files in combination with grunt.
|
||||||
|
HumHub will only use the compressed assets if operated in [production mode](admin-installation.md#disable-errors-debugging), otherwise
|
||||||
|
all assets are included seperatly.
|
||||||
|
|
||||||
|
The compressed production assets are build by calling:
|
||||||
|
|
||||||
|
```
|
||||||
|
yii asset humhub/config/assets.php humhub/config/assets-prod.php
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create the following files:
|
||||||
|
|
||||||
|
- /humhub/js/all-*.js - compressed js file with all core libraries
|
||||||
|
- /humhub/css/all-*.css - compressed css files with all core stylesheets
|
||||||
|
|
||||||
|
More information is available on http://www.yiiframework.com/doc-2.0/guide-structure-assets.html#combining-compressing-assets
|
||||||
|
|
||||||
### Grunt Tasks
|
### Grunt Tasks
|
||||||
- watch
|
- watch
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Here you will learn how you can adapt existing modules to working fine with actually versions.
|
Here you will learn how you can adapt existing modules to working fine with actually versions.
|
||||||
|
|
||||||
|
## Migrate from 1.1 to 1.2
|
||||||
|
|
||||||
## Migrate from 1.0 to 1.1
|
## Migrate from 1.0 to 1.1
|
||||||
|
|
||||||
- Dropped unused space attribute "website"
|
- Dropped unused space attribute "website"
|
||||||
|
@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
Here you will learn how you can adapt existing themes to working fine with actually versions.
|
Here you will learn how you can adapt existing themes to working fine with actually versions.
|
||||||
|
|
||||||
|
## Migrate to 1.2
|
||||||
|
|
||||||
|
### Stream
|
||||||
|
|
||||||
|
Set data-stream attributes for stream
|
||||||
|
|
||||||
|
### Status Bar
|
||||||
|
|
||||||
## Migrate to 1.1
|
## Migrate to 1.1
|
||||||
|
|
||||||
- Make sure to update your themed less file with the latest version.
|
- Make sure to update your themed less file with the latest version.
|
||||||
|
26
protected/humhub/modules/activity/assets/ActivityAsset.php
Executable file
26
protected/humhub/modules/activity/assets/ActivityAsset.php
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\modules\activity\assets;
|
||||||
|
|
||||||
|
use yii\web\AssetBundle;
|
||||||
|
|
||||||
|
class ActivityAsset extends AssetBundle
|
||||||
|
{
|
||||||
|
|
||||||
|
public $sourcePath = '@activity/assets';
|
||||||
|
public $css = [];
|
||||||
|
public $js = [
|
||||||
|
'js/humhub.activity.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
public $depends = [
|
||||||
|
'humhub\assets\CoreApiAsset'
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
134
protected/humhub/modules/activity/assets/js/humhub.activity.js
Normal file
134
protected/humhub/modules/activity/assets/js/humhub.activity.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* Core module for managing Streams and StreamItems
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
humhub.initModule('activity', function (module, require, $) {
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
var object = util.object;
|
||||||
|
var string = util.string;
|
||||||
|
var stream = require('stream');
|
||||||
|
var loader = require('ui.loader');
|
||||||
|
var event = require('event');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of initial stream enteis loaded when stream is initialized.
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
var STREAM_INIT_COUNT = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of stream entries loaded with each request (except initial request)
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
var STREAM_LOAD_COUNT = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of stream entries loaded with each request (except initial request)
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
var ACTIVITY_STREAM_SELECTOR = '#activityStream';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityStream instance;
|
||||||
|
* @type ActivityStream
|
||||||
|
*/
|
||||||
|
var instance;
|
||||||
|
|
||||||
|
|
||||||
|
var ActivityStreamEntry = function (id) {
|
||||||
|
stream.StreamEntry.call(this, id);
|
||||||
|
};
|
||||||
|
|
||||||
|
object.inherits(ActivityStreamEntry, stream.StreamEntry);
|
||||||
|
|
||||||
|
|
||||||
|
ActivityStreamEntry.prototype.actions = function () {
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
ActivityStreamEntry.prototype.delete = function () {/* Not implemented */}
|
||||||
|
ActivityStreamEntry.prototype.edit = function () {/* Not implemented */}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityStream implementation.
|
||||||
|
*
|
||||||
|
* @param {type} container id or jQuery object of the stream container
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
var ActivityStream = function (container) {
|
||||||
|
stream.Stream.call(this, container, {
|
||||||
|
'loadInitialCount': STREAM_INIT_COUNT,
|
||||||
|
'loadCount': STREAM_LOAD_COUNT,
|
||||||
|
'streamEntryClass': ActivityStreamEntry
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
object.inherits(ActivityStream, stream.Stream);
|
||||||
|
|
||||||
|
ActivityStream.prototype.showLoader = function() {
|
||||||
|
var $loaderListItem = $('<li id="activityLoader" class="streamLoader">');
|
||||||
|
loader.append($loaderListItem);
|
||||||
|
this.$content.append($loaderListItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
ActivityStream.prototype.hideLoader = function() {
|
||||||
|
this.$content.find('#activityLoader').remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
var getStream = function () {
|
||||||
|
instance = instance || new ActivityStream($(ACTIVITY_STREAM_SELECTOR));
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function () {
|
||||||
|
instance = undefined;
|
||||||
|
|
||||||
|
var stream = getStream();
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
console.log('No activity stream found!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.init();
|
||||||
|
|
||||||
|
var activityLastEntryReached = false;
|
||||||
|
|
||||||
|
// listen for scrolling event yes or no
|
||||||
|
var scrolling = true;
|
||||||
|
|
||||||
|
stream.$content.scroll(function () {
|
||||||
|
|
||||||
|
// save height of the overflow container
|
||||||
|
var _containerHeight = $("#activityContents").height();
|
||||||
|
|
||||||
|
// save scroll height
|
||||||
|
var _scrollHeight = $("#activityContents").prop("scrollHeight");
|
||||||
|
|
||||||
|
// save current scrollbar position
|
||||||
|
var _currentScrollPosition = $('#activityContents').scrollTop();
|
||||||
|
|
||||||
|
// load more activites if current scroll position is near scroll height
|
||||||
|
if (_currentScrollPosition >= (_scrollHeight - _containerHeight - 30)) {
|
||||||
|
// checking if ajax loading is necessary or the last entries are already loaded
|
||||||
|
if (activityLastEntryReached == false) {
|
||||||
|
if (scrolling == true) {
|
||||||
|
// stop listening for scrolling event to load the new activity range only one time
|
||||||
|
scrolling = false;
|
||||||
|
// load more activities
|
||||||
|
stream.loadEntries().finally(function() {
|
||||||
|
scrolling = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
ActivityStream: ActivityStream,
|
||||||
|
getStream: getStream,
|
||||||
|
init: init
|
||||||
|
});
|
||||||
|
});
|
@ -1,5 +1,5 @@
|
|||||||
<?php if ($clickable): ?><a href="#" onClick="activityShowItem(<?= $record->id; ?>); return false;"><?php endif; ?>
|
<?php if ($clickable): ?><a href="#" onClick="activityShowItem(<?= $record->id; ?>); return false;"><?php endif; ?>
|
||||||
<li class="activity-entry">
|
<li class="activity-entry" data-stream-entry data-action-component="activity.ActivityStreamEntry" data-content-key="<?= $record->content->id ?>">
|
||||||
<div class="media">
|
<div class="media">
|
||||||
<?php if ($originator !== null) : ?>
|
<?php if ($originator !== null) : ?>
|
||||||
<!-- Show user image -->
|
<!-- Show user image -->
|
||||||
|
@ -54,11 +54,9 @@ class Stream extends \yii\base\Widget
|
|||||||
|
|
||||||
protected function getStreamUrl()
|
protected function getStreamUrl()
|
||||||
{
|
{
|
||||||
$params = array(
|
$params = [
|
||||||
'limit' => '10',
|
|
||||||
'from' => '-from-',
|
|
||||||
'mode' => \humhub\modules\stream\actions\Stream::MODE_ACTIVITY
|
'mode' => \humhub\modules\stream\actions\Stream::MODE_ACTIVITY
|
||||||
);
|
];
|
||||||
|
|
||||||
if ($this->contentContainer) {
|
if ($this->contentContainer) {
|
||||||
return $this->contentContainer->createUrl($this->streamAction, $params);
|
return $this->contentContainer->createUrl($this->streamAction, $params);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
/* @var $this humhub\components\View */
|
/* @var $this humhub\components\View */
|
||||||
|
|
||||||
|
\humhub\modules\activity\assets\ActivityAsset::register($this);
|
||||||
|
|
||||||
$this->registerJsFile('@web/resources/activity/activies.js');
|
//$this->registerJsFile('@web/resources/activity/activies.js');
|
||||||
$this->registerJsVar('activityStreamUrl', $streamUrl);
|
//$this->registerJsVar('activityStreamUrl', $streamUrl);
|
||||||
$this->registerJsVar('activityInfoUrl', $infoUrl);
|
$this->registerJsVar('activityInfoUrl', $infoUrl);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
@ -11,13 +12,13 @@ $this->registerJsVar('activityInfoUrl', $infoUrl);
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="panel-heading"><?php echo Yii::t('ActivityModule.widgets_views_activityStream', '<strong>Latest</strong> activities'); ?></div>
|
class="panel-heading"><?php echo Yii::t('ActivityModule.widgets_views_activityStream', '<strong>Latest</strong> activities'); ?></div>
|
||||||
<div id="activityStream">
|
<div id="activityStream" data-stream="<?= $streamUrl ?>">
|
||||||
<div id="activityEmpty" style="display:none">
|
<div id="activityEmpty" style="display:none">
|
||||||
<div
|
<div
|
||||||
class="placeholder"><?php echo Yii::t('ActivityModule.widgets_views_activityStream', 'There are no activities yet.'); ?></div>
|
class="placeholder"><?php echo Yii::t('ActivityModule.widgets_views_activityStream', 'There are no activities yet.'); ?></div>
|
||||||
</div>
|
</div>
|
||||||
<ul id="activityContents" class="media-list activities">
|
<ul id="activityContents" class="media-list activities" data-stream-content>
|
||||||
<li id="activityLoader">
|
<li id="activityLoader" class="streamLoader">
|
||||||
<?php echo \humhub\widgets\LoaderWidget::widget(); ?>
|
<?php echo \humhub\widgets\LoaderWidget::widget(); ?>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -20,7 +20,6 @@ use humhub\models\Setting;
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<?php echo $form->labelEx($model, 'expireTime'); ?>
|
<?php echo $form->labelEx($model, 'expireTime'); ?>
|
||||||
<?php echo $form->textField($model, 'expireTime', array('class' => 'form-control', 'readonly' => Setting::IsFixed('cache.expireTime'))); ?>
|
<?php echo $form->textField($model, 'expireTime', array('class' => 'form-control', 'readonly' => Setting::IsFixed('cache.expireTime'))); ?>
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
28
protected/humhub/modules/content/assets/ContentFormAsset.php
Executable file
28
protected/humhub/modules/content/assets/ContentFormAsset.php
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\modules\content\assets;
|
||||||
|
|
||||||
|
use yii\web\AssetBundle;
|
||||||
|
|
||||||
|
class ContentFormAsset extends AssetBundle
|
||||||
|
{
|
||||||
|
|
||||||
|
public $jsOptions = ['position' => \yii\web\View::POS_END];
|
||||||
|
|
||||||
|
public $sourcePath = '@content/assets';
|
||||||
|
public $css = [];
|
||||||
|
public $js = [
|
||||||
|
'js/humhub.content.form.js'
|
||||||
|
];
|
||||||
|
|
||||||
|
public $depends = [
|
||||||
|
'humhub\assets\CoreApiAsset'
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* Core module for managing Streams and StreamItems
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
humhub.initModule('content.form', function (module, require, $) {
|
||||||
|
|
||||||
|
var CREATE_FORM_ROOT_SELECTOR = '#contentFormBody';
|
||||||
|
|
||||||
|
var util = require('util');
|
||||||
|
var client = require('client');
|
||||||
|
|
||||||
|
var config = require('config').module(module);
|
||||||
|
var event = require('event');
|
||||||
|
|
||||||
|
var instance;
|
||||||
|
|
||||||
|
var CreateForm = function () {
|
||||||
|
this.$ = $(CREATE_FORM_ROOT_SELECTOR);
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateForm.prototype.init = function () {
|
||||||
|
this.$.hide();
|
||||||
|
|
||||||
|
// Hide options by default
|
||||||
|
$('.contentForm_options').hide();
|
||||||
|
$('#contentFormError').hide();
|
||||||
|
// Remove info text from the textinput
|
||||||
|
$('#contentFormBody').click(function () {
|
||||||
|
// Hide options by default
|
||||||
|
$('.contentForm_options').fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setDefaultVisibility();
|
||||||
|
|
||||||
|
this.$.fadeIn('fast');
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateForm.prototype.actions = function () {
|
||||||
|
return ['submit', 'notifyUser', 'changeVisibility'];
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateForm.prototype.submit = function (evt) {
|
||||||
|
$("#contentFormError").hide();
|
||||||
|
$("#contentFormError li").remove();
|
||||||
|
$(".contentForm_options .btn").hide();
|
||||||
|
$("#postform-loader").removeClass("hidden");
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
client.submit(this.getForm(), {url: evt.url}).then(function (response) {
|
||||||
|
if (!response.errors) {
|
||||||
|
event.trigger('humhub:modules:content:newEntry', response.output);
|
||||||
|
that.resetForm();
|
||||||
|
} else {
|
||||||
|
that.handleError(response);
|
||||||
|
}
|
||||||
|
$('.contentForm_options .btn').show();
|
||||||
|
$('#postform-loader').addClass('hidden');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Todo: this is post form only, this needs to be added to post module perhaps by calling $form.trigger('humhub:form:clear');
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
CreateForm.prototype.resetForm = function () {
|
||||||
|
// Reset Form (Empty State)
|
||||||
|
$('.contentForm_options').hide();
|
||||||
|
$('.contentForm').filter(':text').val('');
|
||||||
|
$('.contentForm').filter('textarea').val('').trigger('autosize.resize');
|
||||||
|
$('.contentForm').attr('checked', false);
|
||||||
|
$('.userInput').remove(); // used by UserPickerWidget
|
||||||
|
$('#notifyUserContainer').addClass('hidden');
|
||||||
|
$('#notifyUserInput').val('');
|
||||||
|
|
||||||
|
this.setDefaultVisibility();
|
||||||
|
|
||||||
|
$('#contentFrom_files').val('');
|
||||||
|
$('#public').attr('checked', false);
|
||||||
|
$('#contentForm_message_contenteditable').addClass('atwho-placeholder');
|
||||||
|
|
||||||
|
$('#contentFormBody').find('.atwho-input').trigger('clear');
|
||||||
|
|
||||||
|
// Notify FileUploadButtonWidget to clear (by providing uploaderId)
|
||||||
|
// TODO: use api
|
||||||
|
resetUploader('contentFormFiles');
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateForm.prototype.handleError = function (response) {
|
||||||
|
$('#contentFormError').show();
|
||||||
|
$.each(response.errors, function (fieldName, errorMessage) {
|
||||||
|
// Mark Fields as Error
|
||||||
|
var fieldId = 'contentForm_' + fieldName;
|
||||||
|
$('#' + fieldId).addClass('error');
|
||||||
|
$.each(errorMessage, function (key, msg) {
|
||||||
|
$('#contentFormError').append('<li><i class=\"icon-warning-sign\"></i> ' + msg + '</li>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateForm.prototype.getForm = function () {
|
||||||
|
return this.$.find('form:visible');
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateForm.prototype.changeVisibility = function() {
|
||||||
|
if (!$('#contentForm_visibility').prop('checked')) {
|
||||||
|
this.setPublicVisibility();
|
||||||
|
} else {
|
||||||
|
this.setPrivateVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateForm.prototype.setDefaultVisibility = function() {
|
||||||
|
if (config['defaultVisibility']) {
|
||||||
|
this.setPublicVisibility();
|
||||||
|
} else {
|
||||||
|
this.setPrivateVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateForm.prototype.setPublicVisibility = function() {
|
||||||
|
$('#contentForm_visibility').prop("checked", true);
|
||||||
|
$('#contentForm_visibility_entry').html('<i class="fa fa-lock"></i>'+config['text']['makePrivate']);
|
||||||
|
$('.label-public').removeClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateForm.prototype.setPrivateVisibility = function() {
|
||||||
|
$('#contentForm_visibility').prop("checked", false);
|
||||||
|
$('#contentForm_visibility_entry').html('<i class="fa fa-unlock"></i>'+config['text']['makePublic']);
|
||||||
|
$('.label-public').addClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateForm.prototype.notifyUser = function() {
|
||||||
|
$('#notifyUserContainer').removeClass('hidden');
|
||||||
|
$('#notifyUserInput_tag_input_field').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
var init = function () {
|
||||||
|
instance = new CreateForm();
|
||||||
|
instance.init();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.export({
|
||||||
|
CreateForm: CreateForm,
|
||||||
|
instance: instance,
|
||||||
|
init: init
|
||||||
|
});
|
||||||
|
});
|
@ -7,8 +7,9 @@
|
|||||||
humhub.initModule('content', function(module, require, $) {
|
humhub.initModule('content', function(module, require, $) {
|
||||||
var client = require('client');
|
var client = require('client');
|
||||||
var object = require('util').object;
|
var object = require('util').object;
|
||||||
var actions = require('actions');
|
var actions = require('action');
|
||||||
var Component = actions.Component;
|
var Component = actions.Component;
|
||||||
|
var event = require('event');
|
||||||
|
|
||||||
var DATA_CONTENT_KEY = "content-key";
|
var DATA_CONTENT_KEY = "content-key";
|
||||||
var DATA_CONTENT_EDIT_URL = "content-edit-url";
|
var DATA_CONTENT_EDIT_URL = "content-edit-url";
|
||||||
@ -20,6 +21,10 @@ humhub.initModule('content', function(module, require, $) {
|
|||||||
Component.call(this, container);
|
Component.call(this, container);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Content.getNodeByKey = function(key) {
|
||||||
|
return $('[data-content-key="'+key+'"]');
|
||||||
|
};
|
||||||
|
|
||||||
object.inherits(Content, Component);
|
object.inherits(Content, Component);
|
||||||
|
|
||||||
Content.prototype.actions = function() {
|
Content.prototype.actions = function() {
|
||||||
@ -30,6 +35,7 @@ humhub.initModule('content', function(module, require, $) {
|
|||||||
return this.$.data(DATA_CONTENT_KEY);
|
return this.$.data(DATA_CONTENT_KEY);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: return promise
|
||||||
Content.prototype.create = function (addContentHandler) {
|
Content.prototype.create = function (addContentHandler) {
|
||||||
//Note that this Content won't have an id, so the backend will create an instance
|
//Note that this Content won't have an id, so the backend will create an instance
|
||||||
if(this.hasAction('create')) {
|
if(this.hasAction('create')) {
|
||||||
@ -39,6 +45,7 @@ humhub.initModule('content', function(module, require, $) {
|
|||||||
this.edit(addContentHandler);
|
this.edit(addContentHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: return promise
|
||||||
Content.prototype.edit = function (successHandler) {
|
Content.prototype.edit = function (successHandler) {
|
||||||
if(!this.hasAction('edit')) {
|
if(!this.hasAction('edit')) {
|
||||||
return;
|
return;
|
||||||
@ -91,12 +98,13 @@ humhub.initModule('content', function(module, require, $) {
|
|||||||
},
|
},
|
||||||
error: function(errResponse) {
|
error: function(errResponse) {
|
||||||
modal.error(errResponse);
|
modal.error(errResponse);
|
||||||
console.log('Error occured while editing content: '+errResponse.getFirstError());
|
console.error('Error occured while editing content: '+errResponse.getFirstError());
|
||||||
//Todo: handle error
|
//Todo: handle error
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: return promise
|
||||||
Content.prototype.delete = function () {
|
Content.prototype.delete = function () {
|
||||||
if(!this.hasAction('delete')) {
|
if(!this.hasAction('delete')) {
|
||||||
return;
|
return;
|
||||||
@ -127,10 +135,14 @@ humhub.initModule('content', function(module, require, $) {
|
|||||||
|
|
||||||
Content.prototype.remove = function() {
|
Content.prototype.remove = function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
this.$.animate({ height: 'toggle', opacity: 'toggle' }, 'fast', function() {
|
return new Promise(function(resolve, reject) {
|
||||||
that.$.remove();
|
that.$.animate({ height: 'toggle', opacity: 'toggle' }, 'fast', function() {
|
||||||
//TODO: fire global event
|
that.$.remove();
|
||||||
|
event.trigger('humhub:modules:content:afterRemove', that);
|
||||||
|
resolve(that);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.export({
|
module.export({
|
||||||
|
@ -97,7 +97,6 @@ class ContentController extends Controller
|
|||||||
$content->archive();
|
$content->archive();
|
||||||
|
|
||||||
$json['success'] = true;
|
$json['success'] = true;
|
||||||
$json['wallEntryIds'] = $content->getWallEntryIds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $json;
|
return $json;
|
||||||
@ -123,7 +122,6 @@ class ContentController extends Controller
|
|||||||
$content->unarchive();
|
$content->unarchive();
|
||||||
|
|
||||||
$json['success'] = true;
|
$json['success'] = true;
|
||||||
$json['wallEntryIds'] = $content->getWallEntryIds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $json;
|
return $json;
|
||||||
@ -149,7 +147,7 @@ class ContentController extends Controller
|
|||||||
$content->stick();
|
$content->stick();
|
||||||
|
|
||||||
$json['success'] = true;
|
$json['success'] = true;
|
||||||
$json['wallEntryIds'] = $content->getWallEntryIds();
|
$json['contentId'] = $content->id;
|
||||||
} else {
|
} else {
|
||||||
$json['errorMessage'] = Yii::t('ContentModule.controllers_ContentController', "Maximum number of sticked items reached!\n\nYou can stick only two items at once.\nTo however stick this item, unstick another before!");
|
$json['errorMessage'] = Yii::t('ContentModule.controllers_ContentController', "Maximum number of sticked items reached!\n\nYou can stick only two items at once.\nTo however stick this item, unstick another before!");
|
||||||
}
|
}
|
||||||
@ -178,7 +176,6 @@ class ContentController extends Controller
|
|||||||
if ($content !== null && $content->canStick()) {
|
if ($content !== null && $content->canStick()) {
|
||||||
$content->unstick();
|
$content->unstick();
|
||||||
$json['success'] = true;
|
$json['success'] = true;
|
||||||
$json['wallEntryIds'] = $content->getWallEntryIds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $json;
|
return $json;
|
||||||
|
@ -45,36 +45,13 @@ class PermaController extends Controller
|
|||||||
$id = (int) Yii::$app->request->get('id', "");
|
$id = (int) Yii::$app->request->get('id', "");
|
||||||
|
|
||||||
$content = Content::findOne(['id' => $id]);
|
$content = Content::findOne(['id' => $id]);
|
||||||
|
|
||||||
if ($content !== null) {
|
if ($content !== null) {
|
||||||
return $this->redirect($content->getUrl());
|
return $this->redirect($content->container->createUrl(null, array('contentId' => $id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new HttpException(404, Yii::t('ContentModule.controllers_PermaController', 'Could not find requested content!'));
|
throw new HttpException(404, Yii::t('ContentModule.controllers_PermaController', 'Could not find requested content!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* On given WallEntryId redirect the user to the corresponding content object.
|
|
||||||
*
|
|
||||||
* This is mainly used by ActivityStream or Permalinks.
|
|
||||||
*/
|
|
||||||
public function actionWallEntry()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Id of wall entry
|
|
||||||
$id = Yii::$app->request->get('id', "");
|
|
||||||
|
|
||||||
$wallEntry = WallEntry::find()->joinWith('content')->where(['wall_entry.id' => $id])->one();
|
|
||||||
|
|
||||||
if ($wallEntry != null) {
|
|
||||||
$obj = $wallEntry->content; // Type of IContent
|
|
||||||
if ($obj) {
|
|
||||||
return $this->redirect($obj->container->createUrl(null, array('wallEntryId' => $id)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new HttpException(404, Yii::t('ContentModule.controllers_PermaController', 'Could not find requested permalink!'));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -3,15 +3,18 @@
|
|||||||
|
|
||||||
use yii\helpers\Url;
|
use yii\helpers\Url;
|
||||||
|
|
||||||
$this->registerJsVar('wallArchiveLinkUrl', Url::to(['/content/content/archive', 'id' => '-id-']));
|
$archiveLink = Url::to(['/content/content/archive', 'id' => $id]);
|
||||||
$this->registerJsVar('wallUnarchiveLinkUrl', Url::to(['/content/content/unarchive', 'id' => '-id-']));
|
$unarchiveLink = Url::to(['/content/content/unarchive', 'id' => $id]);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<li>
|
<li>
|
||||||
<?php if ($object->content->isArchived()): ?>
|
<?php if ($object->content->isArchived()): ?>
|
||||||
<a href="#" onClick="wallUnarchive('<?php echo $id; ?>');
|
<a href="#" data-action-click="unarchive" data-action-url="<?= $unarchiveLink ?>">
|
||||||
return false;"><i class="fa fa-archive"></i> <?php echo Yii::t('ContentModule.widgets_views_archiveLink', 'Unarchive'); ?></a>
|
<i class="fa fa-archive"></i> <?php echo Yii::t('ContentModule.widgets_views_archiveLink', 'Unarchive'); ?>
|
||||||
|
</a>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a href="#" onClick="wallArchive('<?php echo $id; ?>');
|
<a href="#" data-action-click="archive" data-action-url="<?= $archiveLink ?>">
|
||||||
return false;"><i class="fa fa-archive"></i> <?php echo Yii::t('ContentModule.widgets_views_archiveLink', 'Move to archive'); ?></a>
|
<i class="fa fa-archive"></i> <?php echo Yii::t('ContentModule.widgets_views_archiveLink', 'Move to archive'); ?>
|
||||||
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</li>
|
</li>
|
||||||
|
@ -9,17 +9,4 @@ use yii\helpers\Url;
|
|||||||
<a href="#" data-action-click="delete">
|
<a href="#" data-action-click="delete">
|
||||||
<i class="fa fa-trash-o"></i> <?= Yii::t('ContentModule.widgets_views_deleteLink', 'Delete') ?>
|
<i class="fa fa-trash-o"></i> <?= Yii::t('ContentModule.widgets_views_deleteLink', 'Delete') ?>
|
||||||
</a>
|
</a>
|
||||||
<?php
|
|
||||||
/*echo humhub\widgets\ModalConfirm::widget(array(
|
|
||||||
'uniqueID' => 'modal_postdelete_' . $id,
|
|
||||||
'linkOutput' => 'a',
|
|
||||||
'title' => Yii::t('ContentModule.widgets_views_deleteLink', '<strong>Confirm</strong> post deleting'),
|
|
||||||
'message' => Yii::t('ContentModule.widgets_views_deleteLink', 'Do you really want to delete this post? All likes and comments will be lost!'),
|
|
||||||
'buttonTrue' => Yii::t('ContentModule.widgets_views_deleteLink', 'Delete'),
|
|
||||||
'buttonFalse' => Yii::t('ContentModule.widgets_views_deleteLink', 'Cancel'),
|
|
||||||
'linkContent' => '<i class="fa fa-trash-o"></i> ' . Yii::t('ContentModule.widgets_views_deleteLink', 'Delete'),
|
|
||||||
'linkHref' => Url::to(['/content/content/delete', 'model' => $model, 'id' => $id]),
|
|
||||||
'confirmJS' => 'function(json) { $(".wall_"+json.uniqueId).remove(); }'
|
|
||||||
));*/
|
|
||||||
?>
|
|
||||||
</li>
|
</li>
|
@ -1,23 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
use yii\web\JsExpression;
|
|
||||||
|
|
||||||
/* @var $this humhub\components\View */
|
/* @var $this humhub\components\View */
|
||||||
?>
|
?>
|
||||||
<li>
|
<li>
|
||||||
<?php
|
<a href="#" data-action-click="edit"
|
||||||
echo \humhub\widgets\AjaxButton::widget([
|
data-action-url="<?= $editUrl ?>"><i class="fa fa-pencil"></i> <?= Yii::t('ContentModule.widgets_views_editLink', 'Edit') ?></a>
|
||||||
'label' => '<i class="fa fa-pencil"></i> ' . Yii::t('ContentModule.widgets_views_editLink', 'Edit'),
|
|
||||||
'tag' => 'a',
|
|
||||||
'ajaxOptions' => [
|
|
||||||
'type' => 'POST',
|
|
||||||
'success' => new JsExpression('function(html){ $(".preferences .dropdown").removeClass("open"); $("#wall_content_' . $content->getUniqueId() . '").replaceWith(html); }'),
|
|
||||||
'url' => $editUrl,
|
|
||||||
],
|
|
||||||
'htmlOptions' => [
|
|
||||||
'href' => '#'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
?>
|
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<li>
|
<li>
|
||||||
<?php if ($isSticked): ?>
|
<?php if ($isSticked): ?>
|
||||||
<a href="#" onClick="wallUnstick('<?php echo $unstickUrl; ?>');
|
<a href="#" data-action-click="unstick" data-action-url="<?= $unstickUrl ?>">
|
||||||
return false;"><i class="fa fa-arrow-up"></i> <?php echo Yii::t('ContentModule.widgets_views_stickLink', 'Unstick'); ?></a>
|
<i class="fa fa-arrow-up"></i> <?php echo Yii::t('ContentModule.widgets_views_stickLink', 'Unstick'); ?>
|
||||||
|
</a>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a href="#" onClick="wallStick('<?php echo $stickUrl; ?>');
|
<a href="#" data-action-click="stick" data-action-url="<?= $stickUrl ?>">
|
||||||
return false;"><i class="fa fa-arrow-up"></i> <?php echo Yii::t('ContentModule.widgets_views_stickLink', 'Stick'); ?></a>
|
<i class="fa fa-arrow-up"></i> <?php echo Yii::t('ContentModule.widgets_views_stickLink', 'Stick'); ?>
|
||||||
|
</a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</li>
|
</li>
|
||||||
|
@ -3,11 +3,22 @@
|
|||||||
use yii\helpers\Html;
|
use yii\helpers\Html;
|
||||||
use yii\helpers\Url;
|
use yii\helpers\Url;
|
||||||
use humhub\modules\space\models\Space;
|
use humhub\modules\space\models\Space;
|
||||||
|
|
||||||
|
\humhub\modules\content\assets\ContentFormAsset::register($this);
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$this->registerJsConfig('content.form', [
|
||||||
|
'defaultVisibility' => $defaultVisibility,
|
||||||
|
'text' => [
|
||||||
|
'makePrivate' => Yii::t('ContentModule.widgets_views_contentForm', 'Make private'),
|
||||||
|
'makePublic' => Yii::t('ContentModule.widgets_views_contentForm', 'Make public')
|
||||||
|
]]);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body" id="contentFormBody">
|
<div class="panel-body" id="contentFormBody" style="display:none;" data-action-component="content.form.CreateForm" data-action-param="{defaultVisibility: <?= $defaultVisibility ?>}">
|
||||||
|
|
||||||
<?php echo Html::beginForm('', 'POST'); ?>
|
<?php echo Html::beginForm('', 'POST'); ?>
|
||||||
|
|
||||||
<ul id="contentFormError">
|
<ul id="contentFormError">
|
||||||
@ -48,25 +59,11 @@ use humhub\modules\space\models\Space;
|
|||||||
<div class="btn_container">
|
<div class="btn_container">
|
||||||
|
|
||||||
<?php echo \humhub\widgets\LoaderWidget::widget(['id' => 'postform-loader', 'cssClass' => 'loader-postform hidden']); ?>
|
<?php echo \humhub\widgets\LoaderWidget::widget(['id' => 'postform-loader', 'cssClass' => 'loader-postform hidden']); ?>
|
||||||
|
|
||||||
<?php
|
<button id="post_submit_button" data-action-click="submit" data-action-url="<?= $submitUrl ?>" class="btn btn-info">
|
||||||
echo \humhub\widgets\AjaxButton::widget([
|
<?= $submitButtonText ?>
|
||||||
'label' => $submitButtonText,
|
</button>
|
||||||
'ajaxOptions' => [
|
|
||||||
'url' => $submitUrl,
|
|
||||||
'type' => 'POST',
|
|
||||||
'dataType' => 'json',
|
|
||||||
'beforeSend' => "function() { $('.contentForm').removeClass('error'); $('#contentFormError').hide(); $('#contentFormError').empty(); }",
|
|
||||||
'beforeSend' => 'function(){ $("#contentFormError").hide(); $("#contentFormError li").remove(); $(".contentForm_options .btn").hide(); $("#postform-loader").removeClass("hidden"); }',
|
|
||||||
'success' => "function(response) { handleResponse(response);}"
|
|
||||||
],
|
|
||||||
'htmlOptions' => [
|
|
||||||
'id' => "post_submit_button",
|
|
||||||
'data-action' => 'post_create',
|
|
||||||
'class' => 'btn btn-info',
|
|
||||||
'type' => 'submit'
|
|
||||||
]]);
|
|
||||||
?>
|
|
||||||
<?php
|
<?php
|
||||||
// Creates Uploading Button
|
// Creates Uploading Button
|
||||||
echo humhub\modules\file\widgets\FileUploadButton::widget(array(
|
echo humhub\modules\file\widgets\FileUploadButton::widget(array(
|
||||||
@ -74,20 +71,6 @@ use humhub\modules\space\models\Space;
|
|||||||
'fileListFieldName' => 'fileList',
|
'fileListFieldName' => 'fileList',
|
||||||
));
|
));
|
||||||
?>
|
?>
|
||||||
<script>
|
|
||||||
$('#fileUploaderButton_contentFormFiles').bind('fileuploaddone', function (e, data) {
|
|
||||||
$('.btn_container').show();
|
|
||||||
});
|
|
||||||
$('#fileUploaderButton_contentFormFiles').bind('fileuploadprogressall', function (e, data) {
|
|
||||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
|
||||||
if (progress != 100) {
|
|
||||||
// Fix: remove focus from upload button to hide tooltip
|
|
||||||
$('#post_submit_button').focus();
|
|
||||||
// hide form buttons
|
|
||||||
$('.btn_container').hide();
|
|
||||||
}
|
|
||||||
});</script>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- public checkbox -->
|
<!-- public checkbox -->
|
||||||
<?php echo Html::checkbox("visibility", "", array('id' => 'contentForm_visibility', 'class' => 'contentForm hidden')); ?>
|
<?php echo Html::checkbox("visibility", "", array('id' => 'contentForm_visibility', 'class' => 'contentForm hidden')); ?>
|
||||||
@ -103,14 +86,14 @@ use humhub\modules\space\models\Space;
|
|||||||
class="fa fa-cogs"></i></a>
|
class="fa fa-cogs"></i></a>
|
||||||
<ul class="dropdown-menu pull-right">
|
<ul class="dropdown-menu pull-right">
|
||||||
<li>
|
<li>
|
||||||
<a href="javascript:notifyUser();"><i
|
<a data-action-click="notifyUser">
|
||||||
class="fa fa-bell"></i> <?php echo Yii::t('ContentModule.widgets_views_contentForm', 'Notify members'); ?>
|
<i class="fa fa-bell"></i> <?php echo Yii::t('ContentModule.widgets_views_contentForm', 'Notify members'); ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php if ($canSwitchVisibility): ?>
|
<?php if ($canSwitchVisibility): ?>
|
||||||
<li>
|
<li>
|
||||||
<a id="contentForm_visibility_entry" href="javascript:changeVisibility();"><i
|
<a id="contentForm_visibility_entry" data-action-click="changeVisibility">
|
||||||
class="fa fa-unlock"></i> <?php echo Yii::t('ContentModule.widgets_views_contentForm', 'Make public'); ?>
|
<i class="fa fa-unlock"></i> <?php echo Yii::t('ContentModule.widgets_views_contentForm', 'Make public'); ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -129,102 +112,12 @@ use humhub\modules\space\models\Space;
|
|||||||
'uploaderId' => 'contentFormFiles'
|
'uploaderId' => 'contentFormFiles'
|
||||||
));
|
));
|
||||||
?>
|
?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /contentForm_Options -->
|
<!-- /contentForm_Options -->
|
||||||
<?php echo Html::endForm(); ?>
|
<?php echo Html::endForm(); ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /panel body -->
|
<!-- /panel body -->
|
||||||
</div> <!-- /panel -->
|
</div> <!-- /panel -->
|
||||||
|
|
||||||
<div class="clearFloats"></div>
|
<div class="clearFloats"></div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
// Hide options by default
|
|
||||||
jQuery('.contentForm_options').hide();
|
|
||||||
$('#contentFormError').hide();
|
|
||||||
// Remove info text from the textinput
|
|
||||||
jQuery('#contentFormBody').click(function () {
|
|
||||||
|
|
||||||
// Hide options by default
|
|
||||||
jQuery('.contentForm_options').fadeIn();
|
|
||||||
});
|
|
||||||
|
|
||||||
setDefaultVisibility();
|
|
||||||
|
|
||||||
function setDefaultVisibility() {
|
|
||||||
<?php if ($defaultVisibility == humhub\modules\content\models\Content::VISIBILITY_PRIVATE) : ?>
|
|
||||||
setPrivateVisibility();
|
|
||||||
<?php endif ;?>
|
|
||||||
|
|
||||||
<?php if ($defaultVisibility == humhub\modules\content\models\Content::VISIBILITY_PUBLIC) : ?>
|
|
||||||
setPublicVisibility();
|
|
||||||
<?php endif ;?>
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPublicVisibility() {
|
|
||||||
$('#contentForm_visibility').prop( "checked", true );
|
|
||||||
$('#contentForm_visibility_entry').html('<i class="fa fa-lock"></i> <?php echo Yii::t('ContentModule.widgets_views_contentForm', 'Make private'); ?>');
|
|
||||||
$('.label-public').removeClass('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPrivateVisibility() {
|
|
||||||
$('#contentForm_visibility').prop( "checked", false );
|
|
||||||
$('#contentForm_visibility_entry').html('<i class="fa fa-unlock"></i> <?php echo Yii::t('ContentModule.widgets_views_contentForm', 'Make public'); ?>');
|
|
||||||
$('.label-public').addClass('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeVisibility() {
|
|
||||||
if (!$('#contentForm_visibility').prop('checked')) {
|
|
||||||
setPublicVisibility();
|
|
||||||
} else {
|
|
||||||
setPrivateVisibility();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function notifyUser() {
|
|
||||||
$('#notifyUserContainer').removeClass('hidden');
|
|
||||||
$('#notifyUserInput_tag_input_field').focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleResponse(response) {
|
|
||||||
if (!response.errors) {
|
|
||||||
// application.modules_core.wall function
|
|
||||||
humhub.modules.stream.getStream().appendEntry(response);
|
|
||||||
|
|
||||||
// Reset Form (Empty State)
|
|
||||||
jQuery('.contentForm_options').hide();
|
|
||||||
$('.contentForm').filter(':text').val('');
|
|
||||||
$('.contentForm').filter('textarea').val('').trigger('autosize.resize');
|
|
||||||
$('.contentForm').attr('checked', false);
|
|
||||||
$('.userInput').remove(); // used by UserPickerWidget
|
|
||||||
$('#notifyUserContainer').addClass('hidden');
|
|
||||||
$('#notifyUserInput').val('');
|
|
||||||
|
|
||||||
setDefaultVisibility();
|
|
||||||
|
|
||||||
$('#contentFrom_files').val('');
|
|
||||||
$('#public').attr('checked', false);
|
|
||||||
$('#contentForm_message_contenteditable').html('<?php echo Html::encode(Yii::t("ContentModule.widgets_views_contentForm", "What's on your mind?")); ?>');
|
|
||||||
$('#contentForm_message_contenteditable').addClass('atwho-placeholder');
|
|
||||||
|
|
||||||
$('#contentFormBody').find('.atwho-input').trigger('clear');
|
|
||||||
|
|
||||||
// Notify FileUploadButtonWidget to clear (by providing uploaderId)
|
|
||||||
resetUploader('contentFormFiles');
|
|
||||||
} else {
|
|
||||||
$('#contentFormError').show();
|
|
||||||
$.each(response.errors, function (fieldName, errorMessage) {
|
|
||||||
// Mark Fields as Error
|
|
||||||
fieldId = 'contentForm_' + fieldName;
|
|
||||||
$('#' + fieldId).addClass('error');
|
|
||||||
$.each(errorMessage, function (key, msg) {
|
|
||||||
$('#contentFormError').append('<li><i class=\"icon-warning-sign\"></i> ' + msg + '</li>');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$('.contentForm_options .btn').show();
|
|
||||||
$('#postform-loader').addClass('hidden');
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -89,8 +89,10 @@ $container = $object->content->container;
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php echo $content; ?>
|
<?php echo $content; ?>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="clearfix">
|
||||||
<?php echo \humhub\modules\content\widgets\WallEntryAddons::widget(['object' => $object]); ?>
|
<span class="entry-loader"></span>
|
||||||
|
<?php echo \humhub\modules\content\widgets\WallEntryAddons::widget(['object' => $object]); ?>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
humhub.modules.post = (function(module, $) {
|
|
||||||
humhub.modules.registerAjaxHandler('humhub.modules.post.create', function(json) {
|
|
||||||
humhub.modules.stream.getStream();
|
|
||||||
}, function(error) {
|
|
||||||
if(error)
|
|
||||||
alert(error);
|
|
||||||
});
|
|
||||||
return module;
|
|
||||||
|
|
||||||
humhub.ui.richtext.register()
|
|
||||||
})(humhub.modules.post || {}, $);
|
|
@ -24,24 +24,10 @@ use humhub\compat\CActiveForm;
|
|||||||
'object' => $post
|
'object' => $post
|
||||||
));
|
));
|
||||||
?>
|
?>
|
||||||
|
<button type="submit" class="btn btn-default btn-sm btn-comment-submit" data-action-click="editSubmit" data-action-url="<?= $post->content->container->createUrl('/post/post/edit', ['id' => $post->id]) ?>">
|
||||||
<?php
|
<?= Yii::t('PostModule.views_edit', 'Save') ?>
|
||||||
echo \humhub\widgets\AjaxButton::widget([
|
</button>
|
||||||
'label' => Yii::t('PostModule.views_edit', 'Save'),
|
|
||||||
'ajaxOptions' => [
|
|
||||||
'type' => 'POST',
|
|
||||||
'beforeSend' => new yii\web\JsExpression('function(html){ $("#post_input_' . $post->id . '_contenteditable").hide(); showLoader("' . $post->id . '"); }'),
|
|
||||||
'success' => new yii\web\JsExpression('function(html){ $(".wall_' . $post->getUniqueId() . '").replaceWith(html); }'),
|
|
||||||
'statusCode' => ['400' => new yii\web\JsExpression('function(xhr) { $("#post_edit_'. $post->id.'").replaceWith(xhr.responseText); }')],
|
|
||||||
'url' => $post->content->container->createUrl('/post/post/edit', ['id' => $post->id]),
|
|
||||||
],
|
|
||||||
'htmlOptions' => [
|
|
||||||
'class' => 'btn btn-default btn-sm btn-comment-submit',
|
|
||||||
'id' => 'post_edit_post_' . $post->id,
|
|
||||||
'type' => 'submit'
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
?>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
47
protected/humhub/modules/post/widgets/CreateForm.php
Normal file
47
protected/humhub/modules/post/widgets/CreateForm.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\modules\post\widgets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This widget is used include the post form.
|
||||||
|
* It normally should be placed above a steam.
|
||||||
|
*
|
||||||
|
* @since 0.5
|
||||||
|
*/
|
||||||
|
class Form extends \humhub\modules\content\widgets\WallCreateContentForm
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public $submitUrl = '/post/post/post';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function renderForm()
|
||||||
|
{
|
||||||
|
return $this->render('form', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
if (!$this->contentContainer->permissionManager->can(new \humhub\modules\post\permissions\CreatePost())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::run();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
14
protected/humhub/modules/post/widgets/views/createForm.php
Normal file
14
protected/humhub/modules/post/widgets/views/createForm.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use yii\helpers\Html;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php echo Html::textarea("message", '', array('id' => 'contentForm_message', 'class' => 'form-control autosize contentForm', 'rows' => '1', 'placeholder' => Yii::t("PostModule.widgets_views_postForm", "What's on your mind?"))); ?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* Modify textarea for mention input */
|
||||||
|
echo \humhub\widgets\RichTextEditor::widget(array(
|
||||||
|
'id' => 'contentForm_message',
|
||||||
|
));
|
||||||
|
?>
|
@ -57,6 +57,12 @@ abstract class Stream extends Action
|
|||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $mode;
|
public $mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to load single content entries.
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
public $contentId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First wall entry id to deliver
|
* First wall entry id to deliver
|
||||||
@ -112,6 +118,8 @@ abstract class Stream extends Action
|
|||||||
|
|
||||||
// Read parameters
|
// Read parameters
|
||||||
if (!Yii::$app->request->isConsoleRequest) {
|
if (!Yii::$app->request->isConsoleRequest) {
|
||||||
|
$this->contentId = Yii::$app->getRequest()->get('id');
|
||||||
|
|
||||||
$from = Yii::$app->getRequest()->get('from', 0);
|
$from = Yii::$app->getRequest()->get('from', 0);
|
||||||
if ($from != 0) {
|
if ($from != 0) {
|
||||||
$this->from = (int) $from;
|
$this->from = (int) $from;
|
||||||
@ -131,10 +139,12 @@ abstract class Stream extends Action
|
|||||||
if ($limit != "" && $limit <= self::MAX_LIMIT) {
|
if ($limit != "" && $limit <= self::MAX_LIMIT) {
|
||||||
$this->limit = $limit;
|
$this->limit = $limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mode = Yii::$app->getRequest()->get('mode', '');
|
$mode = Yii::$app->getRequest()->get('mode', '');
|
||||||
if ($mode != "" && ($mode == self::MODE_ACTIVITY || $mode == self::MODE_NORMAL)) {
|
if ($mode != "" && ($mode == self::MODE_ACTIVITY || $mode == self::MODE_NORMAL)) {
|
||||||
$this->mode = $mode;
|
$this->mode = $mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (explode(',', Yii::$app->getRequest()->get('filters', "")) as $filter) {
|
foreach (explode(',', Yii::$app->getRequest()->get('filters', "")) as $filter) {
|
||||||
$this->filters[] = trim($filter);
|
$this->filters[] = trim($filter);
|
||||||
}
|
}
|
||||||
@ -166,6 +176,11 @@ abstract class Stream extends Action
|
|||||||
} else {
|
} else {
|
||||||
$this->activeQuery->andWhere(['!=', 'content.object_model', \humhub\modules\activity\models\Activity::className()]);
|
$this->activeQuery->andWhere(['!=', 'content.object_model', \humhub\modules\activity\models\Activity::className()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->contentId) {
|
||||||
|
$this->activeQuery->andWhere(['content.id' => $this->contentId]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup Sorting
|
* Setup Sorting
|
||||||
|
@ -16,11 +16,11 @@ class StreamAsset extends AssetBundle
|
|||||||
public $sourcePath = '@humhub/modules/stream/assets';
|
public $sourcePath = '@humhub/modules/stream/assets';
|
||||||
public $css = [];
|
public $css = [];
|
||||||
public $js = [
|
public $js = [
|
||||||
'js/humhub.stream.js'
|
'js/humhub.stream.js',
|
||||||
];
|
];
|
||||||
|
|
||||||
public $depends = [
|
public $depends = [
|
||||||
'humhub\assets\CoreApiAsset'
|
'humhub\modules\content\assets\ContentAsset'
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,42 +9,58 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
var string = util.string;
|
var string = util.string;
|
||||||
var client = require('client');
|
var client = require('client');
|
||||||
var Content = require('content').Content;
|
var Content = require('content').Content;
|
||||||
|
var Component = require('action').Component;
|
||||||
|
var loader = require('ui.loader');
|
||||||
|
var event = require('event');
|
||||||
|
var log = require('log').module(module);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of initial stream enteis loaded when stream is initialized.
|
* Number of initial stream enteis loaded when stream is initialized.
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
var STREAM_INIT_COUNT = 8;
|
var STREAM_INIT_COUNT = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of stream entries loaded with each request (except initial request)
|
* Number of stream entries loaded with each request (except initial request)
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
var STREAM_LOAD_COUNT = 4;
|
var STREAM_LOAD_COUNT = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set on the stream root node to identify a stream. The value of this data
|
* Set on the stream root node to identify a stream. The value of this data
|
||||||
* attribute contains the stream url for loading new entries.
|
* attribute contains the stream url for loading new entries.
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
var DATA_STREAM_SELECTOR = '[data-stream]';
|
var DATA_STREAM_SELECTOR = '[data-stream]';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of stream entries loaded with each request (except initial request)
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
var DATA_WALL_STREAM_SELECTOR = '#wallStream';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set on a stream entry root node to identify stream-entries.
|
* Set on a stream entry root node to identify stream-entries.
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
var DATA_STREAM_ENTRY_SELECTOR = '[data-stream-entry]';
|
var DATA_STREAM_ENTRY_SELECTOR = '[data-stream-entry]';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a data-stream-contentid is set on the stream root only one entry will
|
* If a data-stream-contentid is set on the stream root only one entry will
|
||||||
* be loaded. e.g. for permlinks
|
* be loaded. e.g. for permlinks
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
var DATA_STREAM_CONTENTID = 'stream-contentid';
|
var DATA_STREAM_CONTENTID = 'stream-contentid';
|
||||||
|
|
||||||
|
|
||||||
//TODO: load streamUrl from config
|
/**
|
||||||
//TODO: readonly
|
* 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_ENTRY_ID_SELECTOR = 'content-key';
|
||||||
|
|
||||||
|
|
||||||
|
var streams = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an stream entry within a stream.
|
* Represents an stream entry within a stream.
|
||||||
@ -64,57 +80,192 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
StreamEntry.prototype.delete = function () {
|
StreamEntry.prototype.delete = function () {
|
||||||
var content = this.getContentComponent();
|
var content = this.getContentComponent();
|
||||||
if (content && content.delete) {
|
if (content && content.delete) {
|
||||||
//TODO: modalconfirm
|
|
||||||
content.delete();
|
content.delete();
|
||||||
} else {
|
} else {
|
||||||
StreamEntry._super.delete.call(this);
|
StreamEntry._super.delete.call(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
StreamEntry.prototype.getContentComponent = function () {
|
StreamEntry.prototype.getContentComponent = function () {
|
||||||
var children = this.children();
|
var children = this.children();
|
||||||
return children.length ? children[0] : undefined;
|
return children.length ? children[0] : undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
StreamEntry.prototype.reload = function () {
|
StreamEntry.prototype.reload = function () {
|
||||||
getStream().reload(this);
|
return getStream().reloadEntry(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
StreamEntry.prototype.edit = function () {
|
StreamEntry.prototype.edit = function (evt) {
|
||||||
//Search for data-content-edit-url on root.
|
var that = this;
|
||||||
//Call this url with data-content-key
|
this.loader();
|
||||||
//Trigger delete event
|
client.get(evt.url, {
|
||||||
|
dataType: 'html',
|
||||||
|
success: function (response) {
|
||||||
|
var $content = that.$.find('.content:first');
|
||||||
|
var $oldContent = $content.clone();
|
||||||
|
$content.replaceWith(response.html);
|
||||||
|
that.$.data('oldContent', $oldContent);
|
||||||
|
that.$.find('input[type="text"], textarea, [contenteditable="true"]').first().focus();
|
||||||
|
that.unsetLoader();
|
||||||
|
},
|
||||||
|
error: function(e) {
|
||||||
|
//TODO: handle error
|
||||||
|
that.unsetLoader();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen to click events outside of the stream entry and cancel edit.
|
||||||
|
$('body').off('click.humhub:modules:stream:edit').on('click.humhub:modules:stream:edit', function (e) {
|
||||||
|
if (!$(e.target).closest('[data-content-key="' + that.getKey() + '"]').length) {
|
||||||
|
var $editContent = that.$.find('.content_edit:first');
|
||||||
|
if ($editContent && that.$.data('oldContent')) {
|
||||||
|
$editContent.replaceWith(that.$.data('oldContent'));
|
||||||
|
that.$.data('oldContent', undefined);
|
||||||
|
}
|
||||||
|
$('body').off('click.humhub:modules:stream:edit');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.loader = function (selector) {
|
||||||
|
//selector = selector || '.content:first';
|
||||||
|
selector = selector || '.entry-loader';
|
||||||
|
loader.set(this.$.find(selector), {
|
||||||
|
'position': 'left',
|
||||||
|
'size': '8px',
|
||||||
|
'css': {
|
||||||
|
'padding': '0px'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.unsetLoader = function (selector) {
|
||||||
|
//selector = selector || '.content:first';
|
||||||
|
selector = selector || '.entry-loader';
|
||||||
|
loader.reset(this.$.find(selector));
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.editSubmit = function (evt) {
|
||||||
|
var that = this;
|
||||||
|
client.submit(evt.$form, {
|
||||||
|
url: evt.url,
|
||||||
|
dataType: 'html',
|
||||||
|
beforeSend: function () {
|
||||||
|
//that.loader('.content_edit:first');
|
||||||
|
that.loader();
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
that.$.html(response.html);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.stick = function (evt) {
|
||||||
|
var that = this;
|
||||||
|
this.loader();
|
||||||
|
var stream = that.getStream();
|
||||||
|
client.post(evt.url).done(function (data) {
|
||||||
|
if (data.success) {
|
||||||
|
that.remove().then(function () {
|
||||||
|
stream.loadEntry(that.getKey(), {'prepend': true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.unstick = function (evt) {
|
||||||
|
this.loader();
|
||||||
|
client.post(evt.url).done(function (data) {
|
||||||
|
module.init();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.archive = function (evt) {
|
||||||
|
var that = this;
|
||||||
|
this.loader();
|
||||||
|
client.post(evt.url).then(function (response) {
|
||||||
|
if (response.success) {
|
||||||
|
that.reload().then(function () {
|
||||||
|
log.info(module.text('info.archive.success'), true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(function (e) {
|
||||||
|
log.error(e, true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.unarchive = function (evt) {
|
||||||
|
var that = this;
|
||||||
|
this.loader();
|
||||||
|
client.post(evt.url).then(function (response) {
|
||||||
|
if (response.success) {
|
||||||
|
that.reload().then(function () {
|
||||||
|
log.info(module.text('info.unarchive.success'), true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(function (e) {
|
||||||
|
log.error('Unexpected error', e, true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StreamEntry.prototype.getStream = function () {
|
||||||
|
// Just return the parent stream component.
|
||||||
|
return this.parent();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream implementation.
|
* Generic Stream implementation.
|
||||||
*
|
*
|
||||||
* @param {type} container id or jQuery object of the stream container
|
* @param {type} container id or jQuery object of the stream container
|
||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
*/
|
*/
|
||||||
var Stream = function (container) {
|
var Stream = function (container, cfg) {
|
||||||
Content.call(this, container);
|
Component.call(this, container);
|
||||||
|
this.cfg = this.initConfig(cfg);
|
||||||
|
|
||||||
//If a contentId is set on the stream root we will only show the single content
|
//If a contentId is set on the stream, the root we will only show a single entry
|
||||||
if (this.$.data(DATA_STREAM_CONTENTID)) {
|
if (this.$.data(DATA_STREAM_CONTENTID)) {
|
||||||
this.contentId = parseInt(this.$.data(DATA_STREAM_CONTENTID));
|
this.contentId = parseInt(this.$.data(DATA_STREAM_CONTENTID));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$stream = this.$.find(".s2_stream");
|
this.$stream = this.$;
|
||||||
|
|
||||||
//Cache some stream relevant data/nodes
|
//Cache some stream relevant data/nodes
|
||||||
this.url = this.$.data('stream'); //TODO: set this in config instead of data field
|
this.url = this.$.data('stream');
|
||||||
this.$loader = this.$stream.find(".streamLoader");
|
this.$loader = this.$stream.find(this.cfg['loaderSelector']);
|
||||||
this.$content = this.$stream.find('.s2_streamContent');
|
this.$content = this.$stream.find(this.cfg['contentSelector']);
|
||||||
this.$filter = $('.wallFilterPanel');
|
this.$filter = this.cfg['filterPanel'];
|
||||||
|
|
||||||
//TODO: make this configurable
|
//TODO: make this configurable
|
||||||
this.filters = [];
|
this.filters = [];
|
||||||
this.sort = "c";
|
this.sort = "c";
|
||||||
};
|
};
|
||||||
|
|
||||||
object.inherits(Stream, Content);
|
object.inherits(Stream, Component);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the stream configuration with default values.
|
||||||
|
*
|
||||||
|
* @param {type} cfg
|
||||||
|
* @returns {humhub_stream_L5.Stream.prototype.initConfig.cfg}
|
||||||
|
*/
|
||||||
|
Stream.prototype.initConfig = function (cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
cfg['filterPanel'] = cfg['filterPanel'] || $('<div></div>');
|
||||||
|
cfg['loaderSelector'] = cfg['loaderSelector'] || ".streamLoader";
|
||||||
|
cfg['filterSelector'] = cfg['filterSelector'] || ".wallFilterPanel";
|
||||||
|
cfg['contentSelector'] = cfg['contentSelector'] || "[data-stream-content]";
|
||||||
|
cfg['loadInitialCount'] = cfg['loadInitialCount'] || STREAM_INIT_COUNT;
|
||||||
|
cfg['loadCount'] = cfg['loadCount'] || STREAM_LOAD_COUNT;
|
||||||
|
cfg['streamEntryClass'] = cfg['streamEntryClass'] || StreamEntry;
|
||||||
|
return cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The stream itself does not provide any content actions.
|
||||||
|
*
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
Stream.prototype.getContentActions = function () {
|
Stream.prototype.getContentActions = function () {
|
||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
@ -129,128 +280,210 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
Stream.prototype.init = function () {
|
Stream.prototype.init = function () {
|
||||||
this.clear();
|
this.clear();
|
||||||
this.$stream.show();
|
this.$stream.show();
|
||||||
|
|
||||||
if (this.isShowSingleEntry()) {
|
if (this.isShowSingleEntry()) {
|
||||||
this.loadSingleEntry(this.contentId);
|
this.loadEntry(this.contentId);
|
||||||
} else {
|
} else {
|
||||||
this.loadEntries(STREAM_INIT_COUNT).then(function() {
|
this.loadEntries({'limit': this.cfg['loadInitialCount']}).then(function () {
|
||||||
/**
|
/**
|
||||||
* TODO: REWRITE OLD INITPLUGINS!!!
|
* TODO: REWRITE OLD INITPLUGINS!!!
|
||||||
*/
|
*/
|
||||||
initPlugins();
|
initPlugins();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the stream content.
|
||||||
|
*
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
Stream.prototype.clear = function () {
|
Stream.prototype.clear = function () {
|
||||||
this.lastEntryLoaded = false;
|
this.lastEntryLoaded = false;
|
||||||
this.readOnly = false;
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.$.find(".s2_streamContent").empty();
|
this.$content.empty();
|
||||||
this.$.find(".s2_stream").hide();
|
this.$stream.hide();
|
||||||
this.$.find(".s2_single").hide();
|
//this.$.find(".s2_single").hide();
|
||||||
this.$.find(".streamLoader").hide();
|
this.hideLoader();
|
||||||
this.$.find(".emptyStreamMessage").hide();
|
|
||||||
this.$.find(".emptyFilterStreamMessage").hide();
|
|
||||||
this.$.find('.back_button_holder').hide();
|
|
||||||
this.$filter.hide();
|
this.$filter.hide();
|
||||||
|
this.$.trigger('humhub:modules:stream:clear', this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Stream.prototype.loadSingleEntry = function (contentId) {
|
/**
|
||||||
this.$.find('.back_button_holder').show();
|
* Loads a single stream entry by a given content id.
|
||||||
this.loadEntries(1, (contentId + 1), '');
|
*
|
||||||
|
* @param {type} contentId
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
Stream.prototype.loadEntry = function (contentId, cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
cfg['contentId'] = contentId;
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
that.loadEntries(cfg).then(function ($entryNode) {
|
||||||
|
resolve($entryNode);
|
||||||
|
}).catch(reject);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads a given entry either by providing the contentId or a StreamEntry instance.
|
||||||
|
* This function returns a Promise instance.
|
||||||
|
*
|
||||||
|
* @param {string|StreamEntry} entry
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
Stream.prototype.reloadEntry = function (entry) {
|
Stream.prototype.reloadEntry = function (entry) {
|
||||||
var that = this;
|
var that = this;
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
entry = (entry instanceof StreamEntry) ? entry : that.getEntry(entry);
|
entry = (object.isString(entry)) ? that.getEntry(entry) : entry;
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
console.warn('Attempt to reload of non existent entry: ' + entry);
|
log.warn('Attempt to reload non existing entry');
|
||||||
reject();
|
return reject();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentId = entry.getKey();
|
var contentId = entry.getKey();
|
||||||
return that._load(1, (contentId + 1), '').then(function (response) {
|
that.loadEntry(contentId, {'preventInsert': true}).then(function ($entryNode) {
|
||||||
if (response.content[contentId]) {
|
if (!$entryNode || !$entryNode.length) {
|
||||||
entry.replaceContent(response.content[contentId].output);
|
entry.remove();
|
||||||
resolve(entry);
|
resolve(entry);
|
||||||
} else {
|
} else {
|
||||||
console.warn('Reload failed: ContentId not found in response: ' + contentId);
|
entry.$.fadeOut();
|
||||||
reject();
|
entry.$.replaceWith($entryNode);
|
||||||
|
$entryNode.fadeIn(function () {
|
||||||
|
resolve(entry);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}, reject);
|
}, reject);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Stream.prototype.loadEntries = function (limit, from, filter, sort) {
|
/**
|
||||||
if (this.loading || this.lastEntryLoaded) {
|
* Loads new entries to a stream by the given stream settings.
|
||||||
return;
|
*
|
||||||
}
|
* @param {type} limit
|
||||||
|
* @param {type} from
|
||||||
|
* @param {type} filter
|
||||||
|
* @param {type} sort
|
||||||
|
* @returns {Promise|undefined}
|
||||||
|
*/
|
||||||
|
Stream.prototype.loadEntries = function (cfg) {
|
||||||
|
// Overwrite the default stream settings if provided
|
||||||
|
cfg = this.initLoadConfig(cfg);
|
||||||
|
|
||||||
//Initialize loading process
|
this.$.trigger('humhub:modules:stream:beforeLoadEntries', [this, cfg]);
|
||||||
this.$loader.show();
|
|
||||||
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;
|
|
||||||
|
|
||||||
var that = this;
|
var that = this;
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
that._load(limit, from, filter, sort).then(function (response) {
|
var $result;
|
||||||
that.$loader.hide();
|
// Don't proceed if stream is already loading
|
||||||
if (object.isEmpty(response.content)) {
|
if (that.loading || that.lastEntryLoaded) {
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
that.showLoader();
|
||||||
|
that.loading = true;
|
||||||
|
that._load(cfg).then(function (response) {
|
||||||
|
that.hideLoader();
|
||||||
|
|
||||||
|
// If its not a single entry load and we get no content, we expect last entry is loaded
|
||||||
|
// This may have to be change if we require to reload multiple elements.
|
||||||
|
if (!cfg['contentId'] && object.isEmpty(response.content)) {
|
||||||
that.lastEntryLoaded = true;
|
that.lastEntryLoaded = true;
|
||||||
$('#btn-load-more').hide();
|
that.$.trigger('humhub:modules:stream:lastEntryLoaded');
|
||||||
} else {
|
} else {
|
||||||
that.lastEntryLoaded = response.isLast;
|
that.lastEntryLoaded = response.isLast;
|
||||||
that.appendEntries(response);
|
$result = that.addEntries(response, cfg['prepend']);
|
||||||
}
|
}
|
||||||
|
|
||||||
that.loading = false;
|
that.loading = false;
|
||||||
that.onChange();
|
that.onChange();
|
||||||
resolve();
|
that.$.trigger('humhub:modules:stream:afterLoadEntries', this);
|
||||||
|
resolve($result);
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
//TODO: handle error
|
//TODO: handle error
|
||||||
that.loading = false;
|
that.loading = false;
|
||||||
that.$loader.hide();
|
that.hideLoader();
|
||||||
reject();
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Stream.prototype._load = function (limit, from, filter, sort) {
|
Stream.prototype.initLoadConfig = function (cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
if (!object.isDefined(cfg['contentId'])) {
|
||||||
|
cfg['limit'] = object.isDefined(cfg['limit']) ? cfg['limit'] : this.loadCount;
|
||||||
|
cfg['from'] = object.isDefined(cfg['from']) ? cfg['from'] : this.getLastContentId();
|
||||||
|
cfg['sort'] = cfg['sort'] || this.sort;
|
||||||
|
} else {
|
||||||
|
cfg['limit'] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg['filter'] = cfg['filter'] || this.getFilterString();
|
||||||
|
|
||||||
|
cfg['prepend'] = object.isDefined(cfg['prepend']) ? cfg['prepend'] : false;
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream.prototype.showLoader = function () {
|
||||||
|
loader.append(this.$content);
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream.prototype.hideLoader = function () {
|
||||||
|
this.$content.find('.humhub-ui-loader').remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream.prototype._load = function (cfg) {
|
||||||
|
cfg = cfg || {}
|
||||||
return client.ajax(this.url, {
|
return client.ajax(this.url, {
|
||||||
data: {
|
data: {
|
||||||
filters: filter,
|
filters: cfg.filter,
|
||||||
sort: sort,
|
sort: cfg.sort,
|
||||||
from: from,
|
from: cfg.from,
|
||||||
limit: limit
|
limit: cfg.limit,
|
||||||
|
id: cfg.contentId
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content id of the last entry loaded.
|
||||||
|
* @returns {unresolved}
|
||||||
|
*/
|
||||||
Stream.prototype.getLastContentId = function () {
|
Stream.prototype.getLastContentId = function () {
|
||||||
var $lastEntry = this.$stream.find(DATA_STREAM_ENTRY_SELECTOR).last();
|
var $lastEntry = this.$stream.find(DATA_STREAM_ENTRY_SELECTOR).last();
|
||||||
if ($lastEntry.length) {
|
if ($lastEntry.length) {
|
||||||
return $lastEntry.data(DATA_STREAM_CONTENTID);
|
return $lastEntry.data(DATA_STREAM_ENTRY_ID_SELECTOR);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Stream.prototype.prependEntry = function (response) {
|
|
||||||
return this.$content.prepend(response.output);
|
|
||||||
};
|
|
||||||
|
|
||||||
Stream.prototype.appendEntry = function (response) {
|
Stream.prototype.prependEntry = function (html) {
|
||||||
return this.$content.append(response.output);
|
var $html = $(html).hide();
|
||||||
|
this.$content.prepend($html);
|
||||||
|
$html.fadeIn();
|
||||||
};
|
};
|
||||||
|
|
||||||
Stream.prototype.appendEntries = function (response) {
|
Stream.prototype.appendEntry = function (html) {
|
||||||
|
var $html = $(html).hide();
|
||||||
|
this.$content.append($html);
|
||||||
|
$html.fadeIn();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends all entries of a given stream response to the stream content.
|
||||||
|
*
|
||||||
|
* @param {type} response
|
||||||
|
* @returns {unresolved}
|
||||||
|
*/
|
||||||
|
Stream.prototype.addEntries = function (response, cfg) {
|
||||||
var that = this;
|
var that = this;
|
||||||
var result = '';
|
var result = '';
|
||||||
$.each(response.contentOrder, function (i, key) {
|
$.each(response.contentOrder, function (i, key) {
|
||||||
@ -260,20 +493,31 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
}
|
}
|
||||||
result += response.content[key].output;
|
result += response.content[key].output;
|
||||||
});
|
});
|
||||||
return this.$content.append(result);
|
|
||||||
|
|
||||||
|
var $result = $(result).hide();
|
||||||
|
|
||||||
|
if (cfg['preventInsert']) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$.trigger('humhub:modules:stream:beforeAddEntries', [response, result]);
|
||||||
|
|
||||||
|
if (cfg['prepend']) {
|
||||||
|
this.prependEntry($result);
|
||||||
|
} else {
|
||||||
|
this.appendEntry($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$.trigger('humhub:modules:stream:afterAddEntries', [response, result]);
|
||||||
|
$result.fadeIn('fast');
|
||||||
|
return $result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired when new entries are shown
|
* Fired when new entries are shown
|
||||||
*/
|
*/
|
||||||
Stream.prototype.onChange = function () {
|
Stream.prototype.onChange = function () {
|
||||||
if (this.readOnly) {
|
|
||||||
$('.wallReadOnlyHide').hide();
|
|
||||||
$('.wallReadOnlyShow').show();
|
|
||||||
} else {
|
|
||||||
$('.wallReadOnlyShow').hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasEntries = this.hasEntries();
|
var hasEntries = this.hasEntries();
|
||||||
if (!hasEntries && !this.hasFilter()) {
|
if (!hasEntries && !this.hasFilter()) {
|
||||||
this.$.find('.emptyStreamMessage').show();
|
this.$.find('.emptyStreamMessage').show();
|
||||||
@ -285,32 +529,57 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
this.$.find('.emptyStreamMessage').hide();
|
this.$.find('.emptyStreamMessage').hide();
|
||||||
this.$.find('.emptyFilterStreamMessage').hide();
|
this.$.find('.emptyFilterStreamMessage').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$entryCache = this.getEntryNodes();
|
|
||||||
|
|
||||||
//TODO: fire global event
|
this.$entryCache = this.getEntryNodes();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the stream is single entry mode.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
Stream.prototype.isShowSingleEntry = function () {
|
Stream.prototype.isShowSingleEntry = function () {
|
||||||
return object.isDefined(this.contentId);
|
return object.isDefined(this.contentId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the stream has entries loaded.
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
Stream.prototype.hasEntries = function () {
|
Stream.prototype.hasEntries = function () {
|
||||||
return this.getEntryCount() > 0;
|
return this.getEntryCount() > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the count of loaded stream entries.
|
||||||
|
*
|
||||||
|
* @returns {humhub_stream_L5.Stream.$.find.length}
|
||||||
|
*/
|
||||||
Stream.prototype.getEntryCount = function () {
|
Stream.prototype.getEntryCount = function () {
|
||||||
return this.$.find(DATA_STREAM_ENTRY_SELECTOR).length;
|
return this.$.find(DATA_STREAM_ENTRY_SELECTOR).length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all stream entry nodes.
|
||||||
|
*
|
||||||
|
* @returns {unresolved}
|
||||||
|
*/
|
||||||
Stream.prototype.getEntryNodes = function () {
|
Stream.prototype.getEntryNodes = function () {
|
||||||
return this.$.find(DATA_STREAM_ENTRY_SELECTOR);
|
return this.$.find(DATA_STREAM_ENTRY_SELECTOR);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a stream has filter settings.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
Stream.prototype.hasFilter = function () {
|
Stream.prototype.hasFilter = function () {
|
||||||
return this.filters.length > 0;
|
return this.filters.length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a filter string out of the filter array.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
Stream.prototype.getFilterString = function () {
|
Stream.prototype.getFilterString = function () {
|
||||||
var result = '';
|
var result = '';
|
||||||
$.each(this.filters, function (i, filter) {
|
$.each(this.filters, function (i, filter) {
|
||||||
@ -320,12 +589,24 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
return string.cutsuffix(result, ',');
|
return string.cutsuffix(result, ',');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a given filterId to the filter array.
|
||||||
|
*
|
||||||
|
* @param {type} filterId
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
Stream.prototype.setFilter = function (filterId) {
|
Stream.prototype.setFilter = function (filterId) {
|
||||||
if (this.filters.indexOf(filterId) < 0) {
|
if (this.filters.indexOf(filterId) < 0) {
|
||||||
this.filters.push(filterId);
|
this.filters.push(filterId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears a given filter.
|
||||||
|
*
|
||||||
|
* @param {type} filterId
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
Stream.prototype.unsetFilter = function (filterId) {
|
Stream.prototype.unsetFilter = function (filterId) {
|
||||||
var index = this.filters.indexOf(filterId);
|
var index = this.filters.indexOf(filterId);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
@ -333,29 +614,78 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a StreamEntry instance for a iven content id.
|
||||||
|
* @param {type} key
|
||||||
|
* @returns {humhub_stream_L5.StreamEntry}
|
||||||
|
*/
|
||||||
Stream.prototype.getEntry = function (key) {
|
Stream.prototype.getEntry = function (key) {
|
||||||
return new StreamEntry(this.$.find(DATA_STREAM_ENTRY_SELECTOR+'[data-content-key="' + key + '"]'));
|
return new this.cfg.streamEntryClass(this.$.find(DATA_STREAM_ENTRY_SELECTOR + '[data-content-key="' + key + '"]'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new StreamEntry out of the given childNode.
|
||||||
|
* @param {type} $childNode
|
||||||
|
* @returns {humhub_stream_L5.StreamEntry}
|
||||||
|
*/
|
||||||
Stream.prototype.getEntryByNode = function ($childNode) {
|
Stream.prototype.getEntryByNode = function ($childNode) {
|
||||||
return new StreamEntry($childNode.closest(DATA_STREAM_ENTRY_SELECTOR));
|
return new this.cfg.streamEntryClass($childNode.closest(DATA_STREAM_ENTRY_SELECTOR));
|
||||||
};
|
};
|
||||||
|
|
||||||
var getStream = function () {
|
/**
|
||||||
if (!module.instance) {
|
* Stream implementation for main wall streams.
|
||||||
var $stream = $(DATA_STREAM_SELECTOR).first();
|
*
|
||||||
module.instance = $stream.length ? new Stream($stream) : undefined;
|
* @param {type} container
|
||||||
|
* @param {type} cfg
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
var WallStream = function (container, cfg) {
|
||||||
|
cfg = cfg || {};
|
||||||
|
cfg['filterPanel'] = $('.wallFilterPanel');
|
||||||
|
Stream.call(this, container, cfg);
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
this.$.on('humhub:modules:stream:clear', function () {
|
||||||
|
that.$.find(".emptyStreamMessage").hide();
|
||||||
|
that.$.find(".emptyFilterStreamMessage").hide();
|
||||||
|
that.$.find('.back_button_holder').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$.on('humhub:modules:stream:afterAppendEntries', function (evt, stream) {
|
||||||
|
if (that.isShowSingleEntry()) {
|
||||||
|
that.$.find('.back_button_holder').show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$.on('humhub:modules:stream:lastEntryLoaded', function () {
|
||||||
|
$('#btn-load-more').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
object.inherits(WallStream, Stream);
|
||||||
|
|
||||||
|
var getStream = function ($selector) {
|
||||||
|
$selector = $selector || DATA_WALL_STREAM_SELECTOR;
|
||||||
|
if (!streams[$selector]) {
|
||||||
|
var $stream = (!$selector) ? $(DATA_WALL_STREAM_SELECTOR) : $($selector).first();
|
||||||
|
return streams[$selector] = $stream.length ? new WallStream($stream) : undefined;
|
||||||
}
|
}
|
||||||
return module.instance;
|
return streams[$selector];
|
||||||
};
|
};
|
||||||
|
|
||||||
var getEntry = function (id) {
|
var getEntry = function (id) {
|
||||||
return module.getStream().getEntry(id);
|
return module.getStream().getEntry(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes wall stream
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
var init = function () {
|
var init = function () {
|
||||||
var stream = getStream();
|
streams = {};
|
||||||
|
|
||||||
|
var stream = getStream();
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
console.log('Non-Stream Page!');
|
console.log('Non-Stream Page!');
|
||||||
return;
|
return;
|
||||||
@ -363,8 +693,14 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
|
|
||||||
stream.init();
|
stream.init();
|
||||||
|
|
||||||
var lastKey;
|
event.on('humhub:modules:content:newEntry', function (evt, html) {
|
||||||
|
stream.prependEntry(html);
|
||||||
|
});
|
||||||
|
|
||||||
$(window).scroll(function () {
|
$(window).scroll(function () {
|
||||||
|
if (stream.isShowSingleEntry()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var $window = $(window);
|
var $window = $(window);
|
||||||
var scrollTop = $window.scrollTop();
|
var scrollTop = $window.scrollTop();
|
||||||
var windowHeight = $window.height();
|
var windowHeight = $window.height();
|
||||||
@ -374,27 +710,32 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines our base y position for changing the current entry
|
/*
|
||||||
var yLimit = scrollTop + (windowHeight / 2);
|
|
||||||
|
This can be used to trace the currently visible entries
|
||||||
// Get id of current scroll item
|
|
||||||
//TODO: chache the entry nodes !
|
var lastKey;
|
||||||
var matchingNodes = stream.$entryCache.map(function () {
|
// Defines our base y position for changing the current entry
|
||||||
var $this = $(this);
|
var yLimit = scrollTop + (windowHeight / 2);
|
||||||
if ($this.offset().top < yLimit) {
|
|
||||||
return $this;
|
// Get id of current scroll item
|
||||||
}
|
//TODO: chache the entry nodes !
|
||||||
});
|
var matchingNodes = stream.$entryCache.map(function () {
|
||||||
|
var $this = $(this);
|
||||||
// Get the id of the current element
|
if ($this.offset().top < yLimit) {
|
||||||
var $current = matchingNodes[matchingNodes.length - 1];
|
return $this;
|
||||||
var currentKey = $current && $current.length ? $current.data('content-key') : "";
|
}
|
||||||
|
});
|
||||||
if (lastKey !== currentKey) {
|
|
||||||
lastKey = currentKey;
|
// Get the id of the current element
|
||||||
// Set/remove active class
|
var $current = matchingNodes[matchingNodes.length - 1];
|
||||||
console.log(currentKey);
|
var currentKey = $current && $current.length ? $current.data('content-key') : "";
|
||||||
}
|
|
||||||
|
if (lastKey !== currentKey) {
|
||||||
|
lastKey = currentKey;
|
||||||
|
// Set/remove active class
|
||||||
|
}
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
stream.$.on('click', '.singleBackLink', function () {
|
stream.$.on('click', '.singleBackLink', function () {
|
||||||
@ -444,108 +785,14 @@ humhub.initModule('stream', function (module, require, $) {
|
|||||||
module.export({
|
module.export({
|
||||||
StreamEntry: StreamEntry,
|
StreamEntry: StreamEntry,
|
||||||
Stream: Stream,
|
Stream: Stream,
|
||||||
|
WallStream: WallStream,
|
||||||
getStream: getStream,
|
getStream: getStream,
|
||||||
getEntry: getEntry,
|
getEntry: getEntry,
|
||||||
init: init
|
init: init
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/* TODO:
|
/*
|
||||||
Stream.prototype.wallStick = function (url) {
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
if (currentStream) {
|
|
||||||
$.each(data.wallEntryIds, function (k, wallEntryId) {
|
|
||||||
currentStream.deleteEntry(wallEntryId);
|
|
||||||
currentStream.prependEntry(wallEntryId);
|
|
||||||
});
|
|
||||||
$('html, body').animate({scrollTop: 0}, 'slow');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert(data.errorMessage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Stream.prototype.wallUnstick = function (url) {
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
//Reload the whole stream, since we have to reorder the entries
|
|
||||||
currentStream.showStream();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click Handler for Archive Link of Wall Posts
|
|
||||||
* (archiveLink.php)
|
|
||||||
*
|
|
||||||
* @param {type} className
|
|
||||||
* @param {type} id
|
|
||||||
|
|
||||||
Stream.prototype.wallArchive = function (id) {
|
|
||||||
|
|
||||||
url = wallArchiveLinkUrl.replace('-id-', id);
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
if (currentStream) {
|
|
||||||
$.each(data.wallEntryIds, function (k, wallEntryId) {
|
|
||||||
//currentStream.reloadWallEntry(wallEntryId);
|
|
||||||
// fade out post
|
|
||||||
setInterval(fadeOut(), 1000);
|
|
||||||
|
|
||||||
function fadeOut() {
|
|
||||||
// fade out current archived post
|
|
||||||
$('#wallEntry_' + wallEntryId).fadeOut('slow');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click Handler for Un Archive Link of Wall Posts
|
|
||||||
* (archiveLink.php)
|
|
||||||
*
|
|
||||||
* @param {type} className
|
|
||||||
* @param {type} id
|
|
||||||
|
|
||||||
Stream.prototype.wallUnarchive = function (id) {
|
|
||||||
url = wallUnarchiveLinkUrl.replace('-id-', id);
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
dataType: "json",
|
|
||||||
type: 'post',
|
|
||||||
url: url
|
|
||||||
}).done(function (data) {
|
|
||||||
if (data.success) {
|
|
||||||
if (currentStream) {
|
|
||||||
$.each(data.wallEntryIds, function (k, wallEntryId) {
|
|
||||||
currentStream.reloadWallEntry(wallEntryId);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
module.StreamItem.prototype.highlightContent = function () {
|
module.StreamItem.prototype.highlightContent = function () {
|
||||||
var $content = this.getContent();
|
var $content = this.getContent();
|
||||||
$content.addClass('highlight');
|
$content.addClass('highlight');
|
||||||
|
@ -5,7 +5,18 @@ use yii\web\View;
|
|||||||
|
|
||||||
\humhub\modules\stream\assets\StreamAsset::register($this);
|
\humhub\modules\stream\assets\StreamAsset::register($this);
|
||||||
|
|
||||||
$contentId = (int) Yii::$app->request->getQueryParam('wallEntryId');
|
$this->registerJsConfig([
|
||||||
|
'stream' => [
|
||||||
|
'text' => [
|
||||||
|
'info.archive.success' => Yii::t('ContentModule.widgets_views_stream', 'The content has been successfully archived.'),
|
||||||
|
'info.unarchive.success' => Yii::t('ContentModule.widgets_views_stream', 'The content has been successfully unarchived.'),
|
||||||
|
'info.stick.success' => Yii::t('ContentModule.widgets_views_stream', 'The content has been successfully sticked.'),
|
||||||
|
'info.unstick.success' => Yii::t('ContentModule.widgets_views_stream', 'The content has been successfully unsticked.'),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$contentId = (int) Yii::$app->request->getQueryParam('contentId');
|
||||||
$contentIdData = ($contentId != "") ? 'data-stream-contentid="' . $contentId . '"' : '';
|
$contentIdData = ($contentId != "") ? 'data-stream-contentid="' . $contentId . '"' : '';
|
||||||
|
|
||||||
if (Yii::$app->settings->get('horImageScrollOnMobile'))
|
if (Yii::$app->settings->get('horImageScrollOnMobile'))
|
||||||
@ -49,16 +60,15 @@ $this->registerJsVar('defaultStreamSort', ($defaultStreamSort != '') ? $defaultS
|
|||||||
|
|
||||||
<!-- Stream content -->
|
<!-- Stream content -->
|
||||||
<div id="wallStream" data-stream="<?= $streamUrl ?>" <?= $contentIdData ?>
|
<div id="wallStream" data-stream="<?= $streamUrl ?>" <?= $contentIdData ?>
|
||||||
data-action-component="humhub.modules.stream.Stream"
|
data-action-component="stream.WallStream"
|
||||||
data-content-delete-url="<?= Url::to(['/content/content/delete']) ?>">
|
data-content-delete-url="<?= Url::to(['/content/content/delete']) ?>">
|
||||||
|
|
||||||
<!-- DIV for a normal wall stream -->
|
<!-- DIV for a normal wall stream -->
|
||||||
<div class="s2_stream" style="display:none">
|
<div class="s2_stream">
|
||||||
<div class="back_button_holder" style="display:none">
|
<div class="back_button_holder" style="display:none">
|
||||||
<a href="#" class="singleBackLink btn btn-primary"><?php echo Yii::t('ContentModule.widgets_views_stream', 'Back to stream'); ?></a><br><br>
|
<a href="#" class="singleBackLink btn btn-primary"><?php echo Yii::t('ContentModule.widgets_views_stream', 'Back to stream'); ?></a><br><br>
|
||||||
</div>
|
</div>
|
||||||
<div class="s2_streamContent"></div>
|
<div class="s2_streamContent" data-stream-content></div>
|
||||||
<?php echo \humhub\widgets\LoaderWidget::widget(['cssClass' => 'streamLoader']); ?>
|
|
||||||
|
|
||||||
<div class="emptyStreamMessage" style="display:none;">
|
<div class="emptyStreamMessage" style="display:none;">
|
||||||
<div class="<?php echo $this->context->messageStreamEmptyCss; ?>">
|
<div class="<?php echo $this->context->messageStreamEmptyCss; ?>">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?php //[STAMP] 74c0c3a2840b2412882616390669c863
|
<?php //[STAMP] 25c2b4e8b8fd2158213a3465a3ef3b60
|
||||||
namespace user\_generated;
|
namespace user\_generated;
|
||||||
|
|
||||||
// This class was automatically generated by build task
|
// This class was automatically generated by build task
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace tests\codeception\_support;
|
namespace tests\codeception\_support;
|
||||||
|
|
||||||
use Codeception\Module;
|
use Codeception\Module;
|
||||||
|
use Yii;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This helper is used to populate the database with needed fixtures before any tests are run.
|
* This helper is used to populate the database with needed fixtures before any tests are run.
|
||||||
@ -21,5 +22,17 @@ class WebHelper extends Module
|
|||||||
public function _beforeSuite($settings = [])
|
public function _beforeSuite($settings = [])
|
||||||
{
|
{
|
||||||
include __DIR__.'/../acceptance/_bootstrap.php';
|
include __DIR__.'/../acceptance/_bootstrap.php';
|
||||||
|
$this->initModules();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes modules defined in @tests/codeception/config/test.config.php
|
||||||
|
* Note the config key in test.config.php is modules and not humhubModules!
|
||||||
|
*/
|
||||||
|
protected function initModules() {
|
||||||
|
$cfg = \Codeception\Configuration::config();
|
||||||
|
if(!empty($cfg['humhub_modules'])) {
|
||||||
|
Yii::$app->moduleManager->enableModules($cfg['humhub_modules']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
protected/humhub/widgets/GlobalConfirmModal.php
Normal file
29
protected/humhub/widgets/GlobalConfirmModal.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\widgets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GlobalConfirmModal used as template for humhub.ui.modal.confirm actions.
|
||||||
|
*
|
||||||
|
* @see LayoutAddons
|
||||||
|
* @author buddha
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class GlobalConfirmModal extends \yii\base\Widget
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
return $this->render('globalConfirmModal');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
namespace humhub\widgets;
|
namespace humhub\widgets;
|
||||||
|
|
||||||
use yii\base\Widget;
|
use yii\base\Widget;
|
||||||
|
use Yii;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AjaxButton is an replacement for Yii1 CHtml::AjaxButton
|
* AjaxButton is an replacement for Yii1 CHtml::AjaxButton
|
||||||
@ -17,9 +18,39 @@ use yii\base\Widget;
|
|||||||
*/
|
*/
|
||||||
class JSConfig extends Widget
|
class JSConfig extends Widget
|
||||||
{
|
{
|
||||||
|
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
return $this->render('jsConfig');
|
$this->getView()->registerJsConfig(
|
||||||
|
[
|
||||||
|
'action' => [
|
||||||
|
'text' => [
|
||||||
|
'actionHandlerNotFound' => Yii::t('base', 'An error occured while handling your last action. (Handler not found).'),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'ui.modal' => [
|
||||||
|
'defaultConfirmHeader' => Yii::t('base', '<strong>Confirm</strong> Action'),
|
||||||
|
'defaultConfirmBody' => Yii::t('base', 'Do you really want to perform this Action?'),
|
||||||
|
'defaultConfirmText' => Yii::t('base', 'Confirm'),
|
||||||
|
'defaultCancelText' => Yii::t('base', 'Cancel')
|
||||||
|
],
|
||||||
|
'log' => [
|
||||||
|
'traceLevel' => (YII_DEBUG) ? 'DEBUG' : 'INFO',
|
||||||
|
'text' => [
|
||||||
|
'default.error' => Yii::t('base', 'An unexpected error occured. If this keeps happening, please contact a site administrator.'),
|
||||||
|
'0' => Yii::t('base', 'An unexpected error occured. If this keeps happening, please contact a site administrator.'),
|
||||||
|
'403' => Yii::t('base', 'You are not allowed to run this action.'),
|
||||||
|
'500' => Yii::t('base', 'An unexpected server error occured. If this keeps happening, please contact a site administrator.')
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'ui.status' => [
|
||||||
|
'showMore' => Yii::$app->user->isAdmin() || YII_DEBUG,
|
||||||
|
'text' => [
|
||||||
|
'showMore' => Yii::t('base', 'Show more'),
|
||||||
|
'showLess' => Yii::t('base', 'Show less')
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,13 @@ class LayoutAddons extends BaseStack
|
|||||||
*/
|
*/
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->addWidget(GlobalModal::className());
|
$this->addWidget(GlobalModal::className());
|
||||||
|
$this->addWidget(GlobalConfirmModal::className());
|
||||||
$this->addWidget(\humhub\modules\tour\widgets\Tour::className());
|
$this->addWidget(\humhub\modules\tour\widgets\Tour::className());
|
||||||
$this->addWidget(\humhub\modules\admin\widgets\TrackingWidget::className());
|
$this->addWidget(\humhub\modules\admin\widgets\TrackingWidget::className());
|
||||||
|
$this->addWidget(LoaderWidget::className(), ['show' => false, 'id' => "humhub-ui-loader-default"]);
|
||||||
|
$this->addWidget(StatusBar::className());
|
||||||
|
|
||||||
if (Yii::$app->params['enablePjax']) {
|
if (Yii::$app->params['enablePjax']) {
|
||||||
$this->addWidget(Pjax::className());
|
$this->addWidget(Pjax::className());
|
||||||
|
@ -43,6 +43,11 @@ class LoaderWidget extends \yii\base\Widget
|
|||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $cssClass = "";
|
public $cssClass = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* defines if the loader is initially shown
|
||||||
|
*/
|
||||||
|
public $show = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays / Run the Widgets
|
* Displays / Run the Widgets
|
||||||
@ -52,6 +57,7 @@ class LoaderWidget extends \yii\base\Widget
|
|||||||
return $this->render('loader', [
|
return $this->render('loader', [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'cssClass' => $this->cssClass,
|
'cssClass' => $this->cssClass,
|
||||||
|
'show' => $this->show
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,7 @@ class Modal extends Widget
|
|||||||
* @var type
|
* @var type
|
||||||
*/
|
*/
|
||||||
public $initialLoader;
|
public $initialLoader;
|
||||||
|
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$dialogClass = 'modal-dialog';
|
$dialogClass = 'modal-dialog';
|
||||||
|
@ -29,6 +29,7 @@ namespace humhub\widgets;
|
|||||||
* @package humhub.widgets
|
* @package humhub.widgets
|
||||||
* @since 0.5
|
* @since 0.5
|
||||||
* @author Andreas Strobel
|
* @author Andreas Strobel
|
||||||
|
* @deprecated 1.2 Prefer using js api humhub.ui.modal.confirm.
|
||||||
*/
|
*/
|
||||||
class ModalConfirm extends \yii\base\Widget
|
class ModalConfirm extends \yii\base\Widget
|
||||||
{
|
{
|
||||||
|
29
protected/humhub/widgets/StatusBar.php
Normal file
29
protected/humhub/widgets/StatusBar.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://www.humhub.org/
|
||||||
|
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||||
|
* @license https://www.humhub.com/licences
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace humhub\widgets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StatusBar for user feedback (error/warning/info).
|
||||||
|
*
|
||||||
|
* @see LayoutAddons
|
||||||
|
* @author buddha
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class StatusBar extends \yii\base\Widget
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
return $this->render('statusBar');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,19 +1,10 @@
|
|||||||
<!-- check if flash message exists -->
|
<!-- check if flash message exists -->
|
||||||
<?php if(Yii::$app->getSession()->hasFlash('data-saved')): ?>
|
<?php if(Yii::$app->getSession()->hasFlash('data-saved')): ?>
|
||||||
|
|
||||||
<!-- <span> element to display the message -->
|
|
||||||
<span class="data-saved"><i class="fa fa-check-circle"></i> <?php echo Yii::$app->getSession()->getFlash('data-saved'); ?></span>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
$(function() {
|
||||||
/* animate the flash message */
|
humhub.modules.log.success('<?php echo Yii::$app->getSession()->getFlash('data-saved'); ?>', true);
|
||||||
$('.data-saved').hide();
|
|
||||||
$('.data-saved').fadeIn('slow', function() {
|
|
||||||
$('.data-saved').delay(1000).fadeOut('slow', function() {
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
11
protected/humhub/widgets/views/globalConfirmModal.php
Normal file
11
protected/humhub/widgets/views/globalConfirmModal.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
echo \humhub\widgets\Modal::widget([
|
||||||
|
'id' => 'globalModalConfirm',
|
||||||
|
'size' => 'extra-small',
|
||||||
|
'centerText' => true,
|
||||||
|
'animation' => 'pulse',
|
||||||
|
'footer' => '<button data-modal-cancel data-modal-close class="btn btn-primary"></button><button data-modal-confirm data-modal-close class="btn btn-primary"></button>'
|
||||||
|
]);
|
||||||
|
|
||||||
|
?>
|
@ -1,3 +1,4 @@
|
|||||||
|
<?php //Todo: use base Modal widget ?>
|
||||||
<div class="modal" id="globalModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
<div class="modal" id="globalModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
<script type="text/javascript">
|
|
||||||
humhub.config.set({
|
|
||||||
'ui.modal': {
|
|
||||||
'defaultConfirmHeader': '<?= Yii::t('base', '<strong>Confirm</strong> Action') ?>',
|
|
||||||
'defaultConfirmBody': '<?=Yii::t('base', 'Do you really want to perform this Action?') ?>',
|
|
||||||
'defaultConfirmText': '<?=Yii::t('base', 'Confirm') ?>',
|
|
||||||
'defaultCancelText': '<?=Yii::t('base', 'Cancel') ?>'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
<div id="<?php echo $id; ?>" class="loader <?php echo $cssClass; ?>">
|
<div id="<?php echo $id; ?>" class="loader humhub-ui-loader <?php echo $cssClass; ?>" <?php if(isset($show) && !$show) : ?> style="display:none;" <?php endif; ?>>
|
||||||
<div class="sk-spinner sk-spinner-three-bounce">
|
<div class="sk-spinner sk-spinner-three-bounce">
|
||||||
<div class="sk-bounce1"></div>
|
<div class="sk-bounce1"></div>
|
||||||
<div class="sk-bounce2"></div>
|
<div class="sk-bounce2"></div>
|
||||||
|
5
protected/humhub/widgets/views/statusBar.php
Normal file
5
protected/humhub/widgets/views/statusBar.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<div id="status-bar" style="display:none;">
|
||||||
|
<div class="status-bar-body">
|
||||||
|
<div class="status-bar-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
File diff suppressed because one or more lines are too long
@ -3030,8 +3030,92 @@ img.bounceIn {
|
|||||||
background: lighten(@info, 25%) !important;
|
background: lighten(@info, 25%) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#nprogress .bar {
|
#nprogress .bar {
|
||||||
height:2px;
|
height:2px;
|
||||||
background: @info;
|
background: @info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Statusbar
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
#status-bar {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-body {
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
z-index: 9999999;
|
||||||
|
bottom: 0px;
|
||||||
|
display: block;
|
||||||
|
line-height:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-close {
|
||||||
|
color:white;
|
||||||
|
fonfont-weight:bold;
|
||||||
|
font-size:21px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-close:hover {
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-close i {
|
||||||
|
vertical-align:top !important;
|
||||||
|
padding-top:3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content i {
|
||||||
|
margin-right:10px;
|
||||||
|
font-size:21px;
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content .showMore {
|
||||||
|
color: @info;
|
||||||
|
margin-left:10px;
|
||||||
|
font-size:0.7em;
|
||||||
|
cursor:pointer;
|
||||||
|
vertical-align:middle;
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content .status-bar-details {
|
||||||
|
text-align:left;
|
||||||
|
font-size:0.7em;
|
||||||
|
margin-top:20px;
|
||||||
|
max-height:200px;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content span {
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content i.error, .status-bar-content i.fatal {
|
||||||
|
color:@danger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content i.warning {
|
||||||
|
color:@warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content i.info, .status-bar-content i.debug {
|
||||||
|
color:@info;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar-content i.success {
|
||||||
|
color:#85CA2B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-loader {
|
||||||
|
float:right;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user