From 99876e9e3647ec222b4a1766ef4f7bac97c15f2a Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Tue, 7 Jul 2015 15:29:21 +0930 Subject: [PATCH] Initial refactor of client actions, data preloading, SEO An initial stab at flarum/core#126. Still WIP. Preliminary implementation of flarum/core#128 and flarum/core#13. --- js/forum/src/components/avatar-editor.js | 4 +- .../src/components/change-password-modal.js | 2 +- js/forum/src/components/discussion-list.js | 6 +- js/forum/src/components/discussion-page.js | 10 +- .../src/components/forgot-password-modal.js | 2 +- js/forum/src/components/notification-list.js | 2 +- js/forum/src/components/user-dropdown.js | 2 +- js/forum/src/components/welcome-hero.js | 4 +- js/lib/initializers/preload.js | 8 +- js/lib/initializers/store.js | 18 +- js/lib/model.js | 8 +- js/lib/models/forum.js | 5 + js/lib/session.js | 4 +- js/lib/store.js | 2 +- js/lib/utils/app.js | 11 +- src/Api/Client.php | 2 +- src/Api/Response.php | 16 ++ src/Api/Serializers/ForumSerializer.php | 9 +- src/Forum/Actions/ClientAction.php | 134 +++++++++++++++ src/Forum/Actions/DiscussionAction.php | 24 ++- src/Forum/Actions/IndexAction.php | 158 ++---------------- src/Forum/ForumServiceProvider.php | 10 +- src/Support/ClientView.php | 130 ++++++++++++++ views/app.blade.php | 41 +++++ views/discussion.blade.php | 1 + views/forum.blade.php | 2 +- views/index.blade.php | 39 +---- 27 files changed, 413 insertions(+), 241 deletions(-) create mode 100644 js/lib/models/forum.js create mode 100644 src/Api/Response.php create mode 100644 src/Forum/Actions/ClientAction.php create mode 100644 src/Support/ClientView.php create mode 100644 views/app.blade.php create mode 100644 views/discussion.blade.php diff --git a/js/forum/src/components/avatar-editor.js b/js/forum/src/components/avatar-editor.js index cab0834a8..f953a79f8 100644 --- a/js/forum/src/components/avatar-editor.js +++ b/js/forum/src/components/avatar-editor.js @@ -70,7 +70,7 @@ export default class AvatarEditor extends Component { m.redraw(); m.request({ method: 'POST', - url: app.config['api_url']+'/users/'+user.id()+'/avatar', + url: app.forum.attribute('apiUrl')+'/users/'+user.id()+'/avatar', data: data, serialize: data => data, background: true, @@ -91,7 +91,7 @@ export default class AvatarEditor extends Component { m.redraw(); m.request({ method: 'DELETE', - url: app.config['api_url']+'/users/'+user.id()+'/avatar', + url: app.forum.attribute('apiUrl')+'/users/'+user.id()+'/avatar', config: app.session.authorize.bind(app.session) }).then(function(data) { self.loading(false); diff --git a/js/forum/src/components/change-password-modal.js b/js/forum/src/components/change-password-modal.js index 76a995bf7..1f09ea014 100644 --- a/js/forum/src/components/change-password-modal.js +++ b/js/forum/src/components/change-password-modal.js @@ -20,7 +20,7 @@ export default class ChangePasswordModal extends FormModal { m.request({ method: 'POST', - url: app.config['api_url']+'/forgot', + url: app.forum.attribute('apiUrl')+'/forgot', data: {email: app.session.user().email()}, background: true }).then(response => { diff --git a/js/forum/src/components/discussion-list.js b/js/forum/src/components/discussion-list.js index aef43d3ad..5921ec2b4 100644 --- a/js/forum/src/components/discussion-list.js +++ b/js/forum/src/components/discussion-list.js @@ -64,9 +64,9 @@ export default class DiscussionList extends Component { } loadResults(offset) { - if (app.preload.response) { - var discussions = app.store.pushPayload(app.preload.response); - app.preload.response = null; + const discussions = app.preloadedDocument(); + + if (discussions) { return m.deferred().resolve(discussions).promise; } else { var params = this.params(); diff --git a/js/forum/src/components/discussion-page.js b/js/forum/src/components/discussion-page.js index 1181e1df1..9505d311f 100644 --- a/js/forum/src/components/discussion-page.js +++ b/js/forum/src/components/discussion-page.js @@ -43,17 +43,13 @@ export default class DiscussionPage extends mixin(Component, evented) { var params = this.params(); params.include = params.include.join(','); - var discussion; - if (app.preload.response) { + const discussion = app.preloadedDocument(); + if (discussion) { // We must wrap this in a setTimeout because if we are mounting this // component for the first time on page load, then any calls to m.redraw // will be ineffective and thus any configs (scroll code) will be run // before stuff is drawn to the page. - setTimeout(() => { - var discussion = app.store.pushPayload(app.preload.response); - app.preload.response = null; - this.setupDiscussion(discussion); - }); + setTimeout(this.setupDiscussion.bind(this, discussion)); } else { app.store.find('discussions', m.route.param('id'), params).then(this.setupDiscussion.bind(this)); } diff --git a/js/forum/src/components/forgot-password-modal.js b/js/forum/src/components/forgot-password-modal.js index 891167117..f7601c7bb 100644 --- a/js/forum/src/components/forgot-password-modal.js +++ b/js/forum/src/components/forgot-password-modal.js @@ -44,7 +44,7 @@ export default class ForgotPasswordModal extends FormModal { m.request({ method: 'POST', - url: app.config['api_url']+'/forgot', + url: app.forum.attribute('apiUrl')+'/forgot', data: {email: this.email()}, background: true, extract: xhr => { diff --git a/js/forum/src/components/notification-list.js b/js/forum/src/components/notification-list.js index 931571a67..37994d892 100644 --- a/js/forum/src/components/notification-list.js +++ b/js/forum/src/components/notification-list.js @@ -61,7 +61,7 @@ export default class NotificationList extends Component { badges && badges.length ? m('ul.badges', listItems(badges)) : '', group.discussion.title() ) - : m('div.notification-group-header', app.config['forum_title']), + : m('div.notification-group-header', app.forum.attribute('title')), m('ul.notification-group-list', group.notifications.map(notification => { var NotificationComponent = app.notificationComponentRegistry[notification.contentType()]; return NotificationComponent ? m('li', NotificationComponent.component({notification})) : ''; diff --git a/js/forum/src/components/user-dropdown.js b/js/forum/src/components/user-dropdown.js index df39362f1..5b3145290 100644 --- a/js/forum/src/components/user-dropdown.js +++ b/js/forum/src/components/user-dropdown.js @@ -45,7 +45,7 @@ export default class UserDropdown extends Component { ActionButton.component({ icon: 'wrench', label: 'Administration', - href: app.config['base_url']+'/admin' + href: app.forum.attribute('baseUrl')+'/admin' }) ); } diff --git a/js/forum/src/components/welcome-hero.js b/js/forum/src/components/welcome-hero.js index a8e56b4a1..7bf290d82 100644 --- a/js/forum/src/components/welcome-hero.js +++ b/js/forum/src/components/welcome-hero.js @@ -17,8 +17,8 @@ export default class WelcomeHero extends Component { m('div.container', [ m('button.close.btn.btn-icon.btn-link', {onclick: () => this.$().slideUp(this.hide.bind(this))}, m('i.fa.fa-times')), m('div.container-narrow', [ - m('h2', app.config['welcome_title']), - m('div.subtitle', m.trust(app.config['welcome_message'])) + m('h2', app.forum.attribute('welcomeTitle')), + m('div.subtitle', m.trust(app.forum.attribute('welcomeMessage'))) ]) ]) ]) diff --git a/js/lib/initializers/preload.js b/js/lib/initializers/preload.js index 0d370db2e..f568ee5c2 100644 --- a/js/lib/initializers/preload.js +++ b/js/lib/initializers/preload.js @@ -1,9 +1,9 @@ export default function(app) { - if (app.preload.data) { - app.store.pushPayload({data: app.preload.data}); - } + app.store.pushPayload({data: app.preload.data}); + app.forum = app.store.getById('forums', 1); + if (app.preload.session) { app.session.token(app.preload.session.token); app.session.user(app.store.getById('users', app.preload.session.userId)); } -}; +} diff --git a/js/lib/initializers/store.js b/js/lib/initializers/store.js index 3233aa032..f89ac56d4 100644 --- a/js/lib/initializers/store.js +++ b/js/lib/initializers/store.js @@ -1,4 +1,5 @@ import Store from 'flarum/store'; +import Forum from 'flarum/models/forum'; import User from 'flarum/models/user'; import Discussion from 'flarum/models/discussion'; import Post from 'flarum/models/post'; @@ -9,10 +10,13 @@ import Notification from 'flarum/models/notification'; export default function(app) { app.store = new Store(); - app.store.models['users'] = User; - app.store.models['discussions'] = Discussion; - app.store.models['posts'] = Post; - app.store.models['groups'] = Group; - app.store.models['activity'] = Activity; - app.store.models['notifications'] = Notification; -}; + app.store.models = { + forums: Forum, + users: User, + discussions: Discussion, + posts: Post, + groups: Group, + activity: Activity, + notifications: Notification + }; +} diff --git a/js/lib/model.js b/js/lib/model.js index f6b346460..3607c3156 100644 --- a/js/lib/model.js +++ b/js/lib/model.js @@ -10,6 +10,10 @@ export default class Model { return this.data().id; } + attribute(attribute) { + return this.data().attributes[attribute]; + } + pushData(newData) { var data = this.data(); @@ -90,7 +94,7 @@ export default class Model { return app.request({ method: this.exists ? 'PATCH' : 'POST', - url: app.config['api_url']+'/'+this.data().type+(this.exists ? '/'+this.data().id : ''), + url: app.forum.attribute('apiUrl')+'/'+this.data().type+(this.exists ? '/'+this.data().id : ''), data: {data}, background: true, config: app.session.authorize.bind(app.session) @@ -108,7 +112,7 @@ export default class Model { return app.request({ method: 'DELETE', - url: app.config['api_url']+'/'+this.data().type+'/'+this.data().id, + url: app.forum.attribute('apiUrl')+'/'+this.data().type+'/'+this.data().id, background: true, config: app.session.authorize.bind(app.session) }).then(() => this.exists = false); diff --git a/js/lib/models/forum.js b/js/lib/models/forum.js new file mode 100644 index 000000000..2bdcb6d86 --- /dev/null +++ b/js/lib/models/forum.js @@ -0,0 +1,5 @@ +import Model from 'flarum/model'; + +class Forum extends Model {} + +export default Forum; diff --git a/js/lib/session.js b/js/lib/session.js index 7cc730676..e364113f6 100644 --- a/js/lib/session.js +++ b/js/lib/session.js @@ -13,7 +13,7 @@ export default class Session extends mixin(class {}, evented) { var self = this; m.request({ method: 'POST', - url: app.config['base_url']+'/login', + url: app.forum.attribute('baseUrl')+'/login', data: {identification, password}, background: true }).then(function(response) { @@ -32,7 +32,7 @@ export default class Session extends mixin(class {}, evented) { } logout() { - window.location = app.config['base_url']+'/logout'; + window.location = app.forum.attribute('baseUrl')+'/logout?token='+this.token(); } authorize(xhr) { diff --git a/js/lib/store.js b/js/lib/store.js index 20934ea47..a82b31c89 100644 --- a/js/lib/store.js +++ b/js/lib/store.js @@ -38,7 +38,7 @@ export default class Store { } return app.request({ method: 'GET', - url: app.config['api_url']+'/'+endpoint, + url: app.forum.attribute('apiUrl')+'/'+endpoint, data: params, background: true, config: app.session.authorize.bind(app.session) diff --git a/js/lib/utils/app.js b/js/lib/utils/app.js index 998b2d224..bd50a34ac 100644 --- a/js/lib/utils/app.js +++ b/js/lib/utils/app.js @@ -15,8 +15,17 @@ class App { this.initializers.toArray().forEach((initializer) => initializer(this)); } + preloadedDocument() { + if (app.preload.document) { + const results = app.store.pushPayload(app.preload.document); + app.preload.document = null; + + return results; + } + } + setTitle(title) { - document.title = (title ? title+' - ' : '')+this.config['forum_title']; + document.title = (title ? title+' - ' : '')+this.forum.attribute('title'); } request(options) { diff --git a/src/Api/Client.php b/src/Api/Client.php index b1934ce6f..564921830 100644 --- a/src/Api/Client.php +++ b/src/Api/Client.php @@ -33,6 +33,6 @@ class Client $response = $action->handle(new Request($input, $actor)); - return json_decode($response->getBody()); + return new Response($response); } } diff --git a/src/Api/Response.php b/src/Api/Response.php new file mode 100644 index 000000000..8c89799a5 --- /dev/null +++ b/src/Api/Response.php @@ -0,0 +1,16 @@ +response = $response; + } + + public function getBody() + { + return json_decode($this->response->getBody()); + } +} diff --git a/src/Api/Serializers/ForumSerializer.php b/src/Api/Serializers/ForumSerializer.php index 12911a268..b8b623436 100644 --- a/src/Api/Serializers/ForumSerializer.php +++ b/src/Api/Serializers/ForumSerializer.php @@ -1,5 +1,7 @@ $forum->title + 'title' => $forum->title, + 'baseUrl' => Core::config('base_url'), + 'apiUrl' => Core::config('api_url'), + 'welcomeTitle' => Core::config('welcome_title'), + 'welcomeMessage' => Core::config('welcome_message'), + 'themePrimaryColor' => Core::config('theme_primary_color') ]; } } diff --git a/src/Forum/Actions/ClientAction.php b/src/Forum/Actions/ClientAction.php new file mode 100644 index 000000000..06b3445d2 --- /dev/null +++ b/src/Forum/Actions/ClientAction.php @@ -0,0 +1,134 @@ +apiClient = $apiClient; + $this->locales = $locales; + } + + /** + * @param Request $request + * @param array $routeParams + * @return \Flarum\Support\ClientView + */ + public function render(Request $request, array $routeParams = []) + { + $actor = app('flarum.actor'); + + $assets = $this->getAssets(); + $locale = $this->getLocaleCompiler($actor); + + $layout = 'flarum.forum::forum'; + + $view = new ClientView( + $request, + $actor, + $this->apiClient, + $layout, + $assets, + $locale + ); + + return $view; + } + + protected function getAssets() + { + $public = $this->getAssetDirectory(); + + $assets = new AssetManager( + new JsCompiler($public, 'forum.js'), + new LessCompiler($public, 'forum.css') + ); + + $root = __DIR__.'/../../..'; + $assets->addFile($root.'/js/forum/dist/app.js'); + $assets->addFile($root.'/less/forum/app.less'); + + foreach ($this->getLessVariables() as $name => $value) { + $assets->addLess("@$name: $value;"); + } + + $assets->addLess(Core::config('custom_less')); + + return $assets; + } + + protected function getLessVariables() + { + return [ + 'fl-primary-color' => Core::config('theme_primary_color', '#000'), + 'fl-secondary-color' => Core::config('theme_secondary_color', '#000'), + 'fl-dark-mode' => Core::config('theme_dark_mode') ? 'true' : 'false', + 'fl-colored-header' => Core::config('theme_colored_header') ? 'true' : 'false' + ]; + } + + protected function getLocaleCompiler(User $actor) + { + $locale = $actor->locale ?: Core::config('locale', 'en'); + +// $translations = $this->locales->getTranslations($locale); + $jsFiles = $this->locales->getJsFiles($locale); + + $compiler = new LocaleJsCompiler($this->getAssetDirectory(), 'locale-'.$locale.'.js'); +// $compiler->setTranslations(static::filterTranslations($translations)); + array_walk($jsFiles, [$compiler, 'addFile']); + + return $compiler; + } + + protected function getAssetDirectory() + { + return public_path().'/assets'; + } + + /** + * @param $translations + * @return array + */ +// protected static function filterTranslations($translations) +// { +// $filtered = []; +// +// foreach (static::$translations as $key) { +// $parts = explode('.', $key); +// $level = &$filtered; +// +// foreach ($parts as $part) { +// $level = &$level[$part]; +// } +// +// $level = array_get($translations, $key); +// } +// +// return $filtered; +// } +} diff --git a/src/Forum/Actions/DiscussionAction.php b/src/Forum/Actions/DiscussionAction.php index 4efcfbb58..9a0d0e925 100644 --- a/src/Forum/Actions/DiscussionAction.php +++ b/src/Forum/Actions/DiscussionAction.php @@ -2,19 +2,25 @@ use Psr\Http\Message\ServerRequestInterface as Request; -class DiscussionAction extends IndexAction +class DiscussionAction extends ClientAction { - protected function getDetails(Request $request, array $routeParams) + public function render(Request $request, array $routeParams = []) { - $response = $this->apiClient->send(app('flarum.actor'), 'Flarum\Api\Actions\Discussions\ShowAction', [ + $view = parent::render($request, $routeParams); + + $actor = app('flarum.actor'); + $action = 'Flarum\Api\Actions\Discussions\ShowAction'; + $params = [ 'id' => $routeParams['id'], 'page.near' => $routeParams['near'] - ]); - - // TODO: return an object instead of an array? - return [ - 'title' => $response->data->attributes->title, - 'response' => $response ]; + + $document = $this->apiClient->send($actor, $action, $params)->getBody(); + + $view->setTitle($document->data->attributes->title); + $view->setDocument($document); + $view->setContent(app('view')->make('flarum.forum::discussion', compact('document'))); + + return $view; } } diff --git a/src/Forum/Actions/IndexAction.php b/src/Forum/Actions/IndexAction.php index 723c7b278..2195ec8ae 100644 --- a/src/Forum/Actions/IndexAction.php +++ b/src/Forum/Actions/IndexAction.php @@ -11,33 +11,8 @@ use Flarum\Support\HtmlAction; use Illuminate\Database\ConnectionInterface; use Psr\Http\Message\ServerRequestInterface as Request; -class IndexAction extends HtmlAction +class IndexAction extends ClientAction { - /** - * @var Client - */ - protected $apiClient; - - /** - * @var ConnectionInterface - */ - protected $database; - - /** - * @var array - */ - public static $translations = []; - - /** - * @param Client $apiClient - * @param ConnectionInterface $database - */ - public function __construct(Client $apiClient, ConnectionInterface $database) - { - $this->apiClient = $apiClient; - $this->database = $database; - } - /** * @param Request $request * @param array $routeParams @@ -45,135 +20,22 @@ class IndexAction extends HtmlAction */ public function render(Request $request, array $routeParams = []) { - $config = $this->database->table('config') - ->whereIn('key', ['base_url', 'api_url', 'forum_title', 'welcome_title', 'welcome_message', 'theme_primary_color']) - ->lists('value', 'key'); - $session = []; + $view = parent::render($request, $routeParams); - $actor = app('flarum.actor'); - - $response = $this->apiClient->send($actor, 'Flarum\Api\Actions\Forum\ShowAction'); - - $data = [$response->data]; - if (isset($response->included)) { - $data = array_merge($data, $response->included); - } - - if ($actor->exists) { - $session = [ - 'userId' => $actor->id, - 'token' => $request->getCookieParams()['flarum_remember'], - ]; - - // TODO: calling on the API here results in an extra query to get - // the user + their groups, when we already have this information on - // $this->actor. Can we simply run the CurrentUserSerializer - // manually? - $response = $this->apiClient->send($actor, 'Flarum\Api\Actions\Users\ShowAction', ['id' => $actor->id]); - - $data[] = $response->data; - if (isset($response->included)) { - $data = array_merge($data, $response->included); - } - } - - $details = $this->getDetails($request, $routeParams); - - $data = array_merge($data, array_get($details, 'data', [])); - $response = array_get($details, 'response'); - $title = array_get($details, 'title'); - - $view = view('flarum.forum::index') - ->with('title', ($title ? $title.' - ' : '').Core::config('forum_title')) - ->with('config', $config) - ->with('layout', 'flarum.forum::forum') - ->with('data', $data) - ->with('response', $response) - ->with('session', $session); - - $root = __DIR__.'/../../..'; - $public = public_path().'/assets'; - - $assets = new AssetManager( - new JsCompiler($public, 'forum.js'), - new LessCompiler($public, 'forum.css') - ); - - $assets->addFile($root.'/js/forum/dist/app.js'); - $assets->addFile($root.'/less/forum/app.less'); - - $variables = [ - 'fl-primary-color' => Core::config('theme_primary_color', '#000'), - 'fl-secondary-color' => Core::config('theme_secondary_color', '#000'), - 'fl-dark-mode' => Core::config('theme_dark_mode') ? 'true' : 'false', - 'fl-colored-header' => Core::config('theme_colored_header') ? 'true' : 'false' - ]; - foreach ($variables as $name => $value) { - $assets->addLess("@$name: $value;"); - } - - $locale = $actor->locale ?: Core::config('locale', 'en'); - - $localeManager = app('flarum.localeManager'); - $translations = $localeManager->getTranslations($locale); - $jsFiles = $localeManager->getJsFiles($locale); - - $localeCompiler = new LocaleJsCompiler($public, 'locale-'.$locale.'.js'); - $localeCompiler->setTranslations(static::filterTranslations($translations)); - array_walk($jsFiles, [$localeCompiler, 'addFile']); - - event(new RenderView($view, $assets, $this)); - - return $view - ->with('styles', [$assets->getCssFile()]) - ->with('scripts', [$assets->getJsFile(), $localeCompiler->getFile()]); - } - - /** - * @param Request $request - * @param array $routeParams - * @return array - */ - protected function getDetails(Request $request, array $routeParams) - { $queryParams = $request->getQueryParams(); // Only preload data if we're viewing the default index with no filters, // otherwise we have to do all kinds of crazy stuff - if (!count($queryParams) && $request->getUri()->getPath() === '/') { - $response = $this->apiClient->send(app('flarum.actor'), 'Flarum\Api\Actions\Discussions\IndexAction'); + if (! count($queryParams) && $request->getUri()->getPath() === '/') { + $actor = app('flarum.actor'); + $action = 'Flarum\Api\Actions\Discussions\IndexAction'; - return [ - 'response' => $response - ]; + $document = $this->apiClient->send($actor, $action)->getBody(); + + $view->setDocument($document); + $view->setContent(app('view')->make('flarum.forum::index', compact('document'))); } - return []; - } - - /** - * @param $translations - * @return array - */ - protected static function filterTranslations($translations) - { - $filtered = []; - - foreach (static::$translations as $key) { - $parts = explode('.', $key); - $level = &$filtered; - - foreach ($parts as $part) { - if (! isset($level[$part])) { - $level[$part] = []; - } - - $level = &$level[$part]; - } - - $level = array_get($translations, $key); - } - - return $filtered; + return $view; } } diff --git a/src/Forum/ForumServiceProvider.php b/src/Forum/ForumServiceProvider.php index a6f906f46..354cac101 100644 --- a/src/Forum/ForumServiceProvider.php +++ b/src/Forum/ForumServiceProvider.php @@ -58,19 +58,13 @@ class ForumServiceProvider extends ServiceProvider ); $routes->get( - '/d/{id:\d+}/{slug}', + '/d/{id:\d+}/{slug}[/{near}]', 'flarum.forum.discussion', $this->action('Flarum\Forum\Actions\DiscussionAction') ); $routes->get( - '/d/{id:\d+}/{slug}/{near}', - 'flarum.forum.discussion.near', - $this->action('Flarum\Forum\Actions\DiscussionAction') - ); - - $routes->get( - '/u/{username}', + '/u/{username}[/{filter}]', 'flarum.forum.user', $this->action('Flarum\Forum\Actions\IndexAction') ); diff --git a/src/Support/ClientView.php b/src/Support/ClientView.php new file mode 100644 index 000000000..1b5832211 --- /dev/null +++ b/src/Support/ClientView.php @@ -0,0 +1,130 @@ +request = $request; + $this->actor = $actor; + $this->apiClient = $apiClient; + $this->layout = $layout; + $this->assets = $assets; + $this->locale = $locale; + } + + public function setActor(User $actor) + { + $this->actor = $actor; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function setDocument($document) + { + $this->document = $document; + } + + public function setContent($content) + { + $this->content = $content; + } + + public function render() + { + $view = app('view')->file(__DIR__.'/../../views/app.blade.php'); + + $forum = $this->getForumDocument(); + $data = $this->getDataFromDocument($forum); + + if ($this->actor->exists) { + $user = $this->getUserDocument(); + $data = array_merge($data, $this->getDataFromDocument($user)); + } + + $view->data = $data; + $view->session = $this->getSession(); + $view->title = ($this->title ? $this->title . ' - ' : '') . $forum->data->attributes->title; + $view->document = $this->document; + $view->forum = $forum->data; + $view->layout = $this->layout; + $view->content = $this->content; + + $view->styles = [$this->assets->getCssFile()]; + $view->scripts = [$this->assets->getJsFile(), $this->locale->getFile()]; + + return $view->render(); + } + + public function __toString() + { + return $this->render(); + } + + protected function getForumDocument() + { + return $this->apiClient->send($this->actor, 'Flarum\Api\Actions\Forum\ShowAction')->getBody(); + } + + protected function getUserDocument() + { + // TODO: calling on the API here results in an extra query to get + // the user + their groups, when we already have this information on + // $this->actor. Can we simply run the CurrentUserSerializer + // manually? + $document = $this->apiClient->send( + $this->actor, + 'Flarum\Api\Actions\Users\ShowAction', + ['id' => $this->actor->id] + )->getBody(); + + return $document; + } + + protected function getDataFromDocument($document) + { + $data[] = $document->data; + + if (isset($document->included)) { + $data = array_merge($data, $document->included); + } + + return $data; + } + + protected function getSession() + { + return [ + 'userId' => $this->actor->id, + 'token' => $this->request->getCookieParams()['flarum_remember'], + ]; + } +} diff --git a/views/app.blade.php b/views/app.blade.php new file mode 100644 index 000000000..c7dad90c7 --- /dev/null +++ b/views/app.blade.php @@ -0,0 +1,41 @@ + + + + + + {{ $title }} + + + + + @foreach ($styles as $file) + + @endforeach + + + + @include($layout) + + +
+ + @foreach ($scripts as $file) + + @endforeach + + + @if ($content) + + @endif + + diff --git a/views/discussion.blade.php b/views/discussion.blade.php new file mode 100644 index 000000000..93f5f2632 --- /dev/null +++ b/views/discussion.blade.php @@ -0,0 +1 @@ +discussion SEO content diff --git a/views/forum.blade.php b/views/forum.blade.php index 7a7dae34e..a98d44901 100644 --- a/views/forum.blade.php +++ b/views/forum.blade.php @@ -4,7 +4,7 @@