Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout for wall create content form menu #5827

Merged
merged 39 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4c0ef1c
Layout for wall create content form menu
yurabakhtin Aug 3, 2022
a4c4921
Activate current content form menu
yurabakhtin Aug 17, 2022
9ac66a1
Display menu only on Post creating form
yurabakhtin Aug 17, 2022
e2deb13
Improve content form menu
yurabakhtin Aug 18, 2022
c59bc76
API for content form menu
yurabakhtin Aug 22, 2022
fe3e15b
Clean up code
yurabakhtin Aug 22, 2022
405ea53
API for content form menu
yurabakhtin Aug 22, 2022
aed77f7
Use icon from Content record for wall entry create menu
yurabakhtin Aug 23, 2022
a180d54
Improve code on load create wall entry form
yurabakhtin Aug 23, 2022
d133772
New property ContentActiveRecord::$createPermission
yurabakhtin Aug 23, 2022
18c8c21
Display create form wall entry menu only with defined property "creat…
yurabakhtin Aug 24, 2022
33cca19
Improve creating a content from wall stream
yurabakhtin Aug 25, 2022
6b50fe8
Update using of permission for create new post
yurabakhtin Aug 25, 2022
28fce66
Rename property to WallCreateContentForm->displayContentTabs
yurabakhtin Sep 7, 2022
57d7518
Initialize widgets after load content form from menu
yurabakhtin Sep 7, 2022
4399169
Fix reset content form after submit
yurabakhtin Sep 7, 2022
3cf1f86
Display a create content menu tab only of enabled module
yurabakhtin Sep 7, 2022
597948d
Update CHANGELOG.md (#5827)
yurabakhtin Sep 7, 2022
d7d1234
Fix click action of create content menu
yurabakhtin Sep 8, 2022
317244d
New method for register assets of create content menu item
yurabakhtin Sep 15, 2022
28c91a8
Use default sort order for create content menu item
yurabakhtin Sep 15, 2022
e7198ff
Change a sort order of the Post create menu item
yurabakhtin Sep 20, 2022
7632d9c
Remove unused function registerCreateContentMenuAssets()
yurabakhtin Sep 20, 2022
8d7e70a
Display top sorted content form on wall stream
yurabakhtin Sep 28, 2022
f5bc463
Merge branch 'develop' into enh/239-stream-create-form-menu
luke- Oct 7, 2022
6499c4f
Removed unused import
luke- Oct 7, 2022
8638d49
Code comment
yurabakhtin Oct 11, 2022
ee09a61
Fix @since version
yurabakhtin Oct 11, 2022
56ffeeb
Rename action of create form
yurabakhtin Oct 11, 2022
ddeaa10
Widget WallCreateContentFormFooter
yurabakhtin Oct 14, 2022
662b9ba
Improve visibility of menu and form of create wall entry
yurabakhtin Oct 15, 2022
8ca1de7
Style for create wall entry tabs on mobile screen
yurabakhtin Oct 17, 2022
026ff66
Fix menu visibility of create wall entry
yurabakhtin Oct 17, 2022
e961589
Fix visibility of errors on create a wall entry
yurabakhtin Oct 21, 2022
ff9a8ae
Create WallCreateContentFormContainer
yurabakhtin Oct 25, 2022
a463ae0
Refactored `ContentContainerModule:getContentClasses()` method signature
luke- Nov 8, 2022
087ecea
Fixed changed content name
luke- Nov 8, 2022
f781bb3
Minore changes
luke- Nov 8, 2022
d6c6a4a
Fixed Tests with new CreatePermission
luke- Nov 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG-DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ HumHub Changelog

1.13.0 (Unreleased)
-------------------
- Enh #5827: Wall menu tabs for create content forms
- Enh #5808: Add a menu to remove all members of a space
- Enh #5841: Possibility to show Members/Followers as list from Space about page
- Enh #5850: Display all levels by default on info logging page
Expand Down
4 changes: 2 additions & 2 deletions protected/humhub/components/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function behaviors()
*/
public function renderAjaxContent($content)
{
return $this->getView()->renderAjaxContent($content, $this);
return $this->getView()->renderAjaxContent($content);
}

/**
Expand All @@ -123,7 +123,7 @@ public function renderAjaxContent($content)
*/
public function renderAjaxPartial(string $content): string
{
return $this->getView()->renderAjaxPartial($content, $this);
return $this->getView()->renderAjaxPartial($content);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion protected/humhub/config/assets-prod.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/**
* This file is generated by the "yii asset" command.
* DO NOT MODIFY THIS FILE DIRECTLY.
* @version 2022-07-15 11:57:44
* @version 2022-08-17 11:53:49
*/
return [
'app' => [
Expand Down
77 changes: 63 additions & 14 deletions protected/humhub/modules/content/components/ContentActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ class ContentActiveRecord extends ActiveRecord implements ContentOwner, Movable
*/
protected $streamChannel = 'default';

/**
* Holds an extra create permission by providing one of the following
*
* - BasePermission class string
* - Array of type ['class' => '...', 'callback' => '...']
* - Anonymous function
* - BasePermission instance
*
* @var string permission instance
* @since 1.13
*/
protected $createPermission = ManageContent::class;

/**
* Holds an extra manage permission by providing one of the following
*
Expand Down Expand Up @@ -269,6 +282,31 @@ public function getContentDescription()
return "";
}

/**
* Returns the $createPermission settings interpretable by an PermissionManager instance.
*
* @since 1.13
* @see ContentActiveRecord::$createPermission
* @return null|object|string
*/
public function getCreatePermission()
{
return $this->hasCreatePermission()
? $this->getPermissionValue($this->createPermission)
: null;
}

/**
* Determines whether or not the record has an additional createPermission set.
*
* @since 1.13
* @return boolean
*/
public function hasCreatePermission()
{
return !empty($this->createPermission);
}

/**
* Returns the $managePermission settings interpretable by an PermissionManager instance.
*
Expand All @@ -278,29 +316,40 @@ public function getContentDescription()
*/
public function getManagePermission()
{
if(!$this->hasManagePermission()) {
return null;
}
return $this->hasManagePermission()
? $this->getPermissionValue($this->managePermission)
: null;
}

if(is_string($this->managePermission)) { // Simple Permission class specification
return $this->managePermission;
/**
* Returns the permission value interpretable by an PermissionManager instance.
*
* @since 1.13
* @see ContentActiveRecord::$managePermission, ContentActiveRecord::$createPermission
* @param string|array|null
* @return null|object|string
*/
private function getPermissionValue($perm)
{
if (is_string($perm)) { // Simple Permission class specification
return $perm;
}

if(is_array($this->managePermission)) {
if(isset($this->managePermission['class'])) { // ['class' => '...', 'callback' => '...']
$handler = $this->managePermission['class'].'::'.$this->managePermission['callback'];
if (is_array($perm)) {
if (isset($perm['class'])) { // ['class' => '...', 'callback' => '...']
$handler = $perm['class'].'::'.$perm['callback'];
return call_user_func($handler, $this);
}
// Simple Permission array specification
return $this->managePermission;
return $perm;
}

if(is_callable($this->managePermission)) { // anonymous function
return $this->managePermission($this);
if (is_callable($perm)) { // anonymous function
return call_user_func($perm, $this);
}

if($this->managePermission instanceof BasePermission) {
return $this->managePermission;
if ($perm instanceof BasePermission) {
return $perm;
}

return null;
Expand Down Expand Up @@ -358,7 +407,7 @@ public function getWallEntryWidget()

if($this->wallEntryClass) {
$class = $this->wallEntryClass;
$widget = new $class;
$widget = new $class(['model' => $this]);
return $widget;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,14 @@ protected function getGlobalPermissions()
return [];
}

/**
* Returns all content classes provided by the module.
*
* @return array
*/
public function getContentClasses(): array
{
return [];
luke- marked this conversation as resolved.
Show resolved Hide resolved
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yii;
use humhub\modules\content\models\ContentContainerModuleState;
use humhub\modules\content\models\ContentContainer;
use yii\base\InvalidConfigException;

/**
* ModuleManager handles modules of a content container.
Expand Down Expand Up @@ -142,6 +143,7 @@ public function getEnabled()
$enabled[] = $id;
}
}
$enabled[] = 'post';

return $enabled;
}
Expand Down Expand Up @@ -311,4 +313,29 @@ public static function getContentContainerQueryByModule($id)

return $query;
}

/**
* This method is called to determine classes of Content models which can be posted on wall.
*
* @since 1.13
* @param ContentContainerActiveRecord|null $contentContainer
* @return ContentActiveRecord[]
*/
public function getContentClasses(): array
{
$contentClasses = [];
foreach ($this->getEnabled() as $moduleId) {
$module = Yii::$app->getModule($moduleId);
foreach ($module->getContentClasses($this->contentContainer) as $class) {
$content = new $class($this->contentContainer);
if (!($content instanceof ContentActiveRecord)) {
throw new InvalidConfigException($class . ' must be instance of ContentActiveRecord!');
}
$contentClasses[] = $content;
}
}

return $contentClasses;
}

}
13 changes: 9 additions & 4 deletions protected/humhub/modules/content/models/Content.php
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ public function addTags($tags)
}

/**
* Checks if the given user can edit this content.
* Checks if the given user can edit/create this content.
*
* A user can edit a content if one of the following conditions are met:
*
Expand All @@ -735,7 +735,7 @@ public function addTags($tags)
* - The user meets the additional condition implemented by the model records class own `canEdit()` function.
*
* @param User|integer $user user instance or user id
* @return bool can edit this content
* @return bool can edit/create this content
* @throws Exception
* @throws IntegrityException
* @throws \Throwable
Expand Down Expand Up @@ -767,8 +767,13 @@ public function canEdit($user = null)
$model = $this->getModel();

// Check additional manage permission for the given container
if ($model->hasManagePermission() && $this->getContainer() && $this->getContainer()->getPermissionManager($user)->can($model->getManagePermission())) {
return true;
if ($this->container) {
if ($model->isNewRecord && $model->hasCreatePermission() && $this->container->getPermissionManager($user)->can($model->getCreatePermission())) {
return true;
}
if (!$model->isNewRecord && $model->hasManagePermission() && $this->container->getPermissionManager($user)->can($model->getManagePermission())) {
return true;
}
}

// Check if underlying models canEdit implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ humhub.module('content.form', function(module, require, $) {
var client = require('client');
var event = require('event');
var Widget = require('ui.widget').Widget;
var loader = require('ui.loader');

var instance;

Expand All @@ -21,26 +22,39 @@ humhub.module('content.form', function(module, require, $) {

CreateForm.prototype.init = function() {
this.$.hide();
this.menu = this.$.parent().prev('#contentFormMenu');
// Hide options by default
$('.contentForm_options').hide();

this.setDefaultVisibility();
this.$.fadeIn('fast');

if(!module.config['disabled']) {
var that = this;
$('#contentFormBody').on('click.humhub:content:form dragover.humhub:content:form', function(evt) {
// Prevent fading in for topic remove button clicks
if($(evt.target).closest('.topic-remove-label').length) {
return;
}

that.showMenu();
$('.contentForm_options').fadeIn();
});
} else {
$('#contentFormBody').find('.humhub-ui-richtext').trigger('disable');
}
};

CreateForm.prototype.showMenu = function() {
this.menu.find('li,a').removeClass('active');
const firstMenuWithForm = this.menu.find('a[data-action-click=loadForm]:eq(0)');
if (firstMenuWithForm.length) {
firstMenuWithForm.addClass('active')
.parent().addClass('active');
}
this.menu.fadeIn();
}

CreateForm.prototype.submit = function(evt) {
this.$.find('.preferences, .fileinput-button').hide();
this.$.find('.help-block-error').html('');
Expand Down Expand Up @@ -114,11 +128,15 @@ humhub.module('content.form', function(module, require, $) {

CreateForm.prototype.handleError = function(response) {
var that = this;
var model = that.$.find('.form-group:first').attr('class').replace(/^.+field-([^-]+).+$/, '$1');
$.each(response.errors, function(fieldName, errorMessages) {
that.$.find('.field-post-' + fieldName).addClass('has-error');
var fieldSelector = '.field-contentForm_' + fieldName;
that.$.find(fieldSelector + ', ' + fieldSelector + '_input')
.find('.help-block-error').html(errorMessages.join('<br>'));
var fieldSelector = '.field-' + model + '-' + fieldName;
var inputSelector = '.field-contentForm_' + fieldName;
var multiInputSelector = '[name="' + fieldName + '[]"]';
that.$.find(fieldSelector).addClass('has-error');
that.$.find(fieldSelector + ', ' + inputSelector + ', ' + inputSelector + '_input')
.find('.help-block-error:first').html(errorMessages.join('<br>'));
that.$.find(multiInputSelector).closest('.form-group').addClass('has-error');
});
};

Expand Down Expand Up @@ -168,6 +186,47 @@ humhub.module('content.form', function(module, require, $) {
}
};

const CreateFormMenu = Widget.extend();

CreateFormMenu.prototype.init = function() {
this.topMenu = this.$.find('ul.nav');
this.subMenu = this.$.find('li.content-create-menu-more');
this.formPanel = this.$.parent().find('.panel');
if (!this.formPanel.find('form').length) {
this.$.fadeIn();
this.$.addClass('menu-without-form');
}
}

CreateFormMenu.prototype.activateMenu = function (evt) {
this.topMenu.find('li,a').removeClass('active');
evt.$trigger.addClass('active').find('a').addClass('active');

if (evt.$trigger.closest('ul.dropdown-menu').length) {
// Move item from sub menu to top menu
this.subMenu.find('ul').prepend(this.subMenu.prev());
this.subMenu.before(evt.$trigger.parent());
}
}

CreateFormMenu.prototype.loadForm = function (evt) {
const that = this;

loader.set(that.formPanel);
that.activateMenu(evt);

client.get(evt).then(function(response) {
that.formPanel.replaceWith(response.html);
that.formPanel = that.$.parent().find('.panel');
that.formPanel.find('[data-action-component], [data-ui-widget]').each(function () {
Widget.instance($(this));
});
}).catch(function(e) {
module.log.error(e, true);
loader.reset(that.formPanel);
});
}

var init = function() {
var $root = $(CREATE_FORM_ROOT_SELECTOR);
if($root.length) {
Expand All @@ -181,6 +240,7 @@ humhub.module('content.form', function(module, require, $) {

module.export({
CreateForm: CreateForm,
CreateFormMenu: CreateFormMenu,
instance: instance,
init: init,
initOnPjaxLoad: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public function testManagePermission()
$space = Space::findOne(['id' => 3]);

$model = new TestContent($space, Content::VISIBILITY_PUBLIC);
$model->isNewRecord = false;

$model->setManagePermission([ManageContent::class]);

$this->becomeUser('User1');
Expand Down