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

Text field #51

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
- 0.3.4
- Flarum beta 13 compatibility #50
- Fix ability to sort fields #52
- Fix users without profile being redirected when "force completion" is enabled #2
- 0.3.3
- UI Improvements
- Fix "force profile" not working with subfolder installation
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ The user profile generator. Includes:

## Installation

Use [Bazaar](https://discuss.flarum.org/d/5151) or install manually:

```bash
composer require fof/masquerade
```
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
}
],
"require": {
"flarum/core": "^0.1.0-beta.8"
"flarum/core": "^0.1.0-beta.12"
},
"replace": {
"flagrow/masquerade": "*"
Expand Down
3 changes: 2 additions & 1 deletion extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
->get('/masquerade/profile/{id:[0-9]+}', 'masquerade.api.profile', Api\UserProfileController::class)
->get('/masquerade/configure', 'masquerade.api.configure', Api\UserConfigureController::class)
->post('/masquerade/configure', 'masquerade.api.configure.save', Api\UserConfigureController::class),
(new Extend\Middleware('forum'))
->add(Middleware\DemandProfileCompletion::class),
(new Extend\Locales(__DIR__ . '/resources/locale')),
function (Dispatcher $events) {
$events->subscribe(Listeners\InjectPermissions::class);
$events->subscribe(Listeners\InjectSettings::class);
$events->subscribe(Listeners\DemandProfileCompletion::class);
$events->subscribe(Listeners\AddUserGambits::class);
$events->subscribe(Listeners\AddUserBioRelationship::class);
}
Expand Down
2,180 changes: 2,179 additions & 1 deletion js/dist/admin.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/dist/admin.js.map

Large diffs are not rendered by default.

1,309 changes: 1,308 additions & 1 deletion js/dist/forum.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/dist/forum.js.map

Large diffs are not rendered by default.

3,271 changes: 1,575 additions & 1,696 deletions js/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"name": "@fof/masquerade",
"dependencies": {
"flarum-webpack-config": "0.1.0-beta.10",
"html5sortable": "^0.9.17",
"webpack": "^4.0.0",
"webpack-cli": "^3.0.7"
},
Expand Down
27 changes: 14 additions & 13 deletions js/src/admin/panes/ProfileConfigurePane.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import sortable from 'html5sortable/dist/html5sortable.es.js';

import app from 'flarum/app';
import icon from 'flarum/helpers/icon';
import Component from 'flarum/Component';
Expand Down Expand Up @@ -26,19 +28,17 @@ export default class ProfileConfigurePane extends Component {
* Configures the component.
*/
config() {
this.$('.js-sortable-fields')
.sortable({
cancel: '',
})
.on('sortupdate', (e, ui) => {
const sorting = this.$('.js-sortable-fields > .Field')
.map(function () {
return $(this).data('id');
})
.get();

this.updateSort(sorting);
});
sortable(this.element.querySelector('.js-sortable-fields'), {
handle: 'legend',
})[0].addEventListener('sortupdate', () => {
const sorting = this.$('.js-sortable-fields > .Field')
.map(function () {
return $(this).data('id');
})
.get();

this.updateSort(sorting);
});
}

/**
Expand Down Expand Up @@ -382,6 +382,7 @@ export default class ProfileConfigurePane extends Component {
email: app.translator.trans('fof-masquerade.admin.types.email'),
boolean: app.translator.trans('fof-masquerade.admin.types.boolean'),
select: app.translator.trans('fof-masquerade.admin.types.select'),
text: app.translator.trans('fof-masquerade.admin.types.text'),
null: app.translator.trans('fof-masquerade.admin.types.advanced'),
};
}
Expand Down
10 changes: 9 additions & 1 deletion js/src/forum/panes/ProfilePane.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ export default class ProfileConfigurePane extends UserPage {
m('.Fields', this.fields
.sort((a, b) => a.sort() - b.sort())
.map(field => {
let content = null;
// UserID check must be done with == because userId() is number while id() is string
this.answers[field.id()] = field.answer() && field.answer().userId() == this.user.id() ? field.answer().content() : null;
if (field.answer() && field.answer().userId() == this.user.id()) {
if (field.type() === 'text') {
content = field.answer().contentHtml();
} else {
content = field.answer().content()
}
}
this.answers[field.id()] = content;

return this.field(field);
})
Expand Down
9 changes: 8 additions & 1 deletion js/src/forum/types/BaseField.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,14 @@ export default class BaseField {

answerField() {
const iconName = this.readAttribute(this.field, 'icon');
const type = this.readAttribute(this.field, 'type');

return m('.Masquerade-Bio-Set', [
m('span.Masquerade-Bio-Field', [
iconName ? [icon(iconName), ' '] : null,
this.readAttribute(this.field, 'name') + ': ',
]),
m('span.Masquerade-Bio-Answer', this.answerContent()),
m('span.Masquerade-Bio-Answer' + (type ? '.Masquerade-Bio-Answer-' + this.capitalize(type) : ''), this.answerContent()),
]);
}

Expand All @@ -93,4 +94,10 @@ export default class BaseField {
// The value can be '' when the field does not exist on the user (the empty string is set in ProfileConfigurePane)
return value === null || value === '';
}

capitalize(s) {
if (typeof s !== 'string') return ''
return s.charAt(0).toUpperCase() + s.slice(1)
}

}
53 changes: 53 additions & 0 deletions js/src/forum/types/TextField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Button from 'flarum/components/Button';
import BaseField from './BaseField';

export default class TextField extends BaseField {
static updateInterval;

editorInputProps() {
let props = super.editorInputProps();
props.placeholder = '';
props.onfocus = this.startUpdatingPreview.bind(this);
props.onfocusout = this.stopUpdatingPreview.bind(this);
return props;
}

baseElementSelector() {
return '.Field-text[data-id="'+this.field.id()+'"]';
}

startUpdatingPreview() {
TextField.updateInterval = setInterval(this.updatePreview.bind(this), 200);
}

stopUpdatingPreview() {
clearInterval(TextField.updateInterval);
document.querySelector(this.baseElementSelector() + ' .js-preview').style.display = 'none';
}

updatePreview() {
const content = document.querySelector(this.baseElementSelector() + ' textarea').value;
s9e.TextFormatter.preview(content, document.querySelector(this.baseElementSelector() + ' .js-preview'));
document.querySelector(this.baseElementSelector() + ' .js-preview').style.display = 'block';
}

answerContent() {
return m.trust(this.value() || '');
}

editorInput() {
return m('.Field-text', {'data-id': this.field.id()}, [
m('.js-preview', {
style: {
display: 'none',
opacity: 0.5,
'max-height': '400px',
overflow: 'auto',
},
}),
m('textarea', this.editorInputProps())
]);
}

}

2 changes: 2 additions & 0 deletions js/src/forum/types/TypeFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import BooleanField from './BooleanField';
import EmailField from './EmailField';
import SelectField from './SelectField';
import UrlField from './UrlField';
import TextField from './TextField';

export default class TypeFactory {
static typeForField({field, set, value}) {
Expand Down Expand Up @@ -35,6 +36,7 @@ export default class TypeFactory {
email: EmailField,
select: SelectField,
url: UrlField,
text: TextField,
};
}

Expand Down
1 change: 1 addition & 0 deletions js/src/lib/models/Answer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import mixin from 'flarum/utils/mixin';

export default class Answer extends mixin(Model, {
content: Model.attribute('content'),
contentHtml: Model.attribute('content_html'),
field: Model.hasOne('field'),
userId: Model.attribute('user_id')
}) {
Expand Down
4 changes: 4 additions & 0 deletions resources/less/forum.less
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,9 @@
display: inline-block;
width: 50%;
}
.Masquerade-Bio-Answer-Text {
display: block;
width: 100%;
}
}
}
1 change: 1 addition & 0 deletions resources/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ fof-masquerade:
email: Email
select: Dropdown
url: URL
text: Text
11 changes: 11 additions & 0 deletions src/Api/Controllers/UserConfigureController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Illuminate\Support\Arr;
use Psr\Http\Message\ServerRequestInterface;
use Tobscure\JsonApi\Document;
use s9e\TextFormatter\Bundles\Fatdown as TextFormatter;

class UserConfigureController extends AbstractListController
{
Expand Down Expand Up @@ -69,6 +70,8 @@ protected function processUpdate(User $actor, $answers, &$fields)
$content = Arr::get($answers, $field->id);

$this->processBoolean($field, $content);

$this->processText($field, $content);

$this->validator->setField($field);

Expand Down Expand Up @@ -96,4 +99,12 @@ protected function processBoolean(Field $field, &$content)
}
}
}

protected function processText(Field $field, &$content)
{
// For Text field type, convert the values to XML
if ($field->type === 'text') {
$content = TextFormatter::parse($content ? $content : '');
}
}
}
10 changes: 9 additions & 1 deletion src/Api/Serializers/AnswerSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use FoF\Masquerade\Field;
use Flarum\Api\Serializer\AbstractSerializer;
use s9e\TextFormatter\Bundles\Fatdown as TextFormatter;

class AnswerSerializer extends AbstractSerializer
{
Expand All @@ -16,7 +17,14 @@ class AnswerSerializer extends AbstractSerializer
*/
protected function getDefaultAttributes($model)
{
return $model->toArray();
$answer = $model->toArray();
if ($answer['field']['type'] == 'text') {
// render HTML for text field
// TODO make something like "render" method for each field type
$answer['content_html'] = $answer['content'] ? nl2br(TextFormatter::render($answer['content'])) : '';
$answer['content'] = TextFormatter::unparse($answer['content']);
}
return $answer;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Api/Serializers/FieldSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function answer($model)
$for = $model->for ? $model->for : $this->getActor()->id;

if ($answer = $model->answers()->where('user_id', $for)->first()) {
// just so load field data into $answer
$answer->field;
return new Relationship(new Resource(
$answer,
new AnswerSerializer
Expand Down
8 changes: 8 additions & 0 deletions src/FieldType/TextField.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace FoF\Masquerade\FieldType;

class TextField extends BaseField
{
}

1 change: 1 addition & 0 deletions src/FieldType/TypeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ protected static function typeMapping()
'email' => EmailField::class,
'select' => BaseField::class,
'url' => UrlField::class,
'text' => TextField::class,
];
}

Expand Down
38 changes: 0 additions & 38 deletions src/Listeners/DemandProfileCompletion.php

This file was deleted.

17 changes: 11 additions & 6 deletions src/Middleware/DemandProfileCompletion.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

namespace FoF\Masquerade\Middleware;

use FoF\Masquerade\Repositories\FieldRepository;
use Flarum\Http\UrlGenerator;
use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\User;
use FoF\Masquerade\Repositories\FieldRepository;
use Laminas\Diactoros\Response\RedirectResponse;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Zend\Diactoros\Response\RedirectResponse;

class DemandProfileCompletion implements MiddlewareInterface
{
/**
* @var SettingsRepositoryInterface
*/
protected $settings;
/**
* @var FieldRepository
*/
Expand All @@ -26,8 +31,9 @@ class DemandProfileCompletion implements MiddlewareInterface
*/
protected $configureProfilePathWithoutBase;

public function __construct(FieldRepository $fields, UrlGenerator $url)
public function __construct(SettingsRepositoryInterface $settings, FieldRepository $fields, UrlGenerator $url)
{
$this->settings = $settings;
$this->fields = $fields;
$this->configureProfileUrl = $url->to('forum')->route('masquerade.profile.configure');
$this->configureProfilePathWithoutBase = str_replace($url->to('forum')->base(), '', $this->configureProfileUrl);
Expand All @@ -40,9 +46,8 @@ public function process(Request $request, RequestHandlerInterface $handler): Res

if (
$this->configureProfilePathWithoutBase != $request->getUri()->getPath() &&
$actor &&
$actor->exists &&
$actor->is_email_confirmed &&
$actor->can('fof.masquerade.have-profile') &&
$this->settings->get('masquerade.force-profile-completion') &&
!$this->fields->completed($actor->id)
) {
return new RedirectResponse(
Expand Down