👌 IMPROVE: use vue Content components and transmit serverData over initialState

- use vue components `Content` and `AppContent` with it's respective styling
  to be independent from server styling
- use OCP\IInitialStateService and @nextcloud/initial-state to transmit the serverData
  instead of using a hidden span element and jsonEncode/Decode
  this is needed to use the `Content` component, so the vue instance can be mounted to
  #content directly (otherwise server styling for #content interfers with the vue styling)
- also improves some general styling (mostly widths and margins/paddings)

Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
pull/994/head
Jonas Sulzer 2020-09-02 00:54:44 +02:00
rodzic 3aced1be96
commit ff9224e4ad
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6D1DC8E0D9904C83
12 zmienionych plików z 110 dodań i 121 usunięć

Wyświetl plik

@ -8,6 +8,7 @@ declare(strict_types=1);
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Jonas Sulzer <jonas@violoncello.ch>
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @license GNU AGPL version 3 or any later version
@ -50,6 +51,7 @@ use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\IInitialStateService;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IURLGenerator;
@ -109,7 +111,7 @@ class NavigationController extends Controller {
* @param MiscService $miscService
*/
public function __construct(
IL10N $l10n, IRequest $request, $userId, IConfig $config, IURLGenerator $urlGenerator,
IL10N $l10n, IRequest $request, $userId, IConfig $config, IInitialStateService $initialStateService, IURLGenerator $urlGenerator,
AccountService $accountService, DocumentService $documentService,
ConfigService $configService, CheckService $checkService, MiscService $miscService
) {
@ -118,6 +120,7 @@ class NavigationController extends Controller {
$this->userId = $userId;
$this->l10n = $l10n;
$this->config = $config;
$this->initialStateService = $initialStateService;
$this->urlGenerator = $urlGenerator;
$this->checkService = $checkService;
@ -141,33 +144,32 @@ class NavigationController extends Controller {
* @throws SocialAppConfigException
*/
public function navigate(string $path = ''): TemplateResponse {
$data = [
'serverData' => [
'public' => false,
'firstrun' => false,
'setup' => false,
'isAdmin' => OC::$server->getGroupManager()
->isAdmin($this->userId),
'cliUrl' => $this->getCliUrl()
]
$serverData = [
'public' => false,
'firstrun' => false,
'setup' => false,
'isAdmin' => OC::$server->getGroupManager()
->isAdmin($this->userId),
'cliUrl' => $this->getCliUrl()
];
try {
$data['serverData']['cloudAddress'] = $this->configService->getCloudUrl();
$serverData['cloudAddress'] = $this->configService->getCloudUrl();
} catch (SocialAppConfigException $e) {
$this->checkService->checkInstallationStatus(true);
$cloudAddress = $this->setupCloudAddress();
if ($cloudAddress !== '') {
$data['serverData']['cloudAddress'] = $cloudAddress;
$serverData['cloudAddress'] = $cloudAddress;
} else {
$data['serverData']['setup'] = true;
$serverData['setup'] = true;
if ($data['serverData']['isAdmin']) {
if ($serverData['isAdmin']) {
$cloudAddress = $this->request->getParam('cloudAddress');
if ($cloudAddress !== null) {
$this->configService->setCloudUrl($cloudAddress);
} else {
return new TemplateResponse(Application::APP_NAME, 'main', $data);
$this->initialStateService->provideInitialState(Application::APP_NAME, 'serverData', $serverData);
return new TemplateResponse(Application::APP_NAME, 'main');
}
}
}
@ -179,9 +181,9 @@ class NavigationController extends Controller {
$this->configService->setSocialUrl();
}
if ($data['serverData']['isAdmin']) {
if ($serverData['isAdmin']) {
$checks = $this->checkService->checkDefault();
$data['serverData']['checks'] = $checks;
$serverData['checks'] = $checks;
}
/*
@ -189,7 +191,7 @@ class NavigationController extends Controller {
*/
try {
$this->accountService->createActor($this->userId, $this->userId);
$data['serverData']['firstrun'] = true;
$serverData['firstrun'] = true;
} catch (AccountAlreadyExistsException $e) {
// we do nothing
} catch (NoUserException $e) {
@ -198,7 +200,8 @@ class NavigationController extends Controller {
// neither.
}
return new TemplateResponse(Application::APP_NAME, 'main', $data);
$this->initialStateService->provideInitialState(Application::APP_NAME, 'serverData', $serverData);
return new TemplateResponse(Application::APP_NAME, 'main');
}
private function setupCloudAddress(): string {

Wyświetl plik

@ -8,6 +8,7 @@ declare(strict_types=1);
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Jonas Sulzer <jonas@violoncello.ch>
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @license GNU AGPL version 3 or any later version
@ -44,6 +45,7 @@ use OCA\Social\Service\MiscService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IInitialStateService;
use OCP\IRequest;
use OCP\IUserManager;
use OCP\IUserSession;
@ -83,11 +85,12 @@ class OStatusController extends Controller {
* @param IUserSession $userSession
*/
public function __construct(
IRequest $request, CacheActorService $cacheActorService, AccountService $accountService,
IRequest $request, IInitialStateService $initialStateService, CacheActorService $cacheActorService, AccountService $accountService,
CurlService $curlService, MiscService $miscService, IUserSession $userSession
) {
parent::__construct(Application::APP_NAME, $request);
$this->initialStateService = $initialStateService;
$this->cacheActorService = $cacheActorService;
$this->accountService = $accountService;
$this->curlService = $curlService;
@ -118,16 +121,15 @@ class OStatusController extends Controller {
throw new Exception('Failed to retrieve current user');
}
return new TemplateResponse(
'social', 'ostatus', [
'serverData' => [
'account' => $actor->getAccount(),
'currentUser' => [
'uid' => $user->getUID(),
'displayName' => $user->getDisplayName(),
]
$this->initialStateService->provideInitialState('social', 'serverData', [
'account' => $actor->getAccount(),
'currentUser' => [
'uid' => $user->getUID(),
'displayName' => $user->getDisplayName(),
]
], 'guest'
]);
return new TemplateResponse(
'social', 'main', 'guest'
);
} catch (Exception $e) {
return $this->fail($e);
@ -148,13 +150,12 @@ class OStatusController extends Controller {
try {
$following = $this->accountService->getActor($local);
$this->initialStateService->provideInitialState('social', 'serverData', [
'local' => $local,
'account' => $following->getAccount()
]);
return new TemplateResponse(
'social', 'ostatus', [
'serverData' => [
'local' => $local,
'account' => $following->getAccount()
]
], 'guest'
'social', 'main', 'guest'
);
} catch (Exception $e) {
return $this->fail($e);

Wyświetl plik

@ -8,6 +8,7 @@ declare(strict_types=1);
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Jonas Sulzer <jonas@violoncello.ch>
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @license GNU AGPL version 3 or any later version
@ -48,6 +49,7 @@ use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IInitialStateService;
use OCP\IL10N;
use OCP\IRequest;
@ -98,13 +100,14 @@ class SocialPubController extends Controller {
* @param ConfigService $configService
*/
public function __construct(
$userId, IRequest $request, IL10N $l10n, NavigationController $navigationController,
$userId, IInitialStateService $initialStateService, IRequest $request, IL10N $l10n, NavigationController $navigationController,
CacheActorService $cacheActorService, AccountService $accountService, StreamService $streamService,
ConfigService $configService
) {
parent::__construct(Application::APP_NAME, $request);
$this->userId = $userId;
$this->initialStateService = $initialStateService;
$this->l10n = $l10n;
$this->navigationController = $navigationController;
$this->accountService = $accountService;
@ -126,9 +129,6 @@ class SocialPubController extends Controller {
return $this->navigationController->navigate('');
}
$data = [
'serverData' => [
'public' => true,
],
'application' => 'Social'
];
@ -142,6 +142,10 @@ class SocialPubController extends Controller {
} catch (Exception $e) {
return $this->fail($e);
}
$this->initialStateService->provideInitialState('social', 'serverData', [
'public' => true,
]);
$page = new PublicTemplateResponse(Application::APP_NAME, 'main', $data);
$page->setStatus($status);
$page->setHeaderTitle($this->l10n->t('Social'));
@ -229,14 +233,14 @@ class SocialPubController extends Controller {
$stream = $this->streamService->getStreamById($postId, true);
$data = [
'id' => $postId,
'item' => $stream,
'serverData' => [
'public' => ($this->userId === null),
],
'application' => 'Social'
];
return new TemplateResponse(Application::APP_NAME, 'stream', $data);
$this->initialStateService->provideInitialState(Application::APP_NAME, 'item', $stream );
$this->initialStateService->provideInitialState(Application::APP_NAME, 'serverData', [
'public' => ($this->userId === null),
]);
return new TemplateResponse(Application::APP_NAME, 'main', $data);
}

Wyświetl plik

@ -30,6 +30,7 @@
"@babel/runtime": "^7.11.2",
"@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.3.3",
"@nextcloud/initial-state": "^1.1.2",
"@nextcloud/logger": "^1.1.2",
"@nextcloud/vue": "^2.6.1",
"he": "^1.2.0",

Wyświetl plik

@ -1,10 +1,10 @@
<template>
<div v-if="!serverData.setup" id="app-social" :class="{public: serverData.public}">
<AppNavigation v-if="!serverData.public" id="app-navigation">
<Content v-if="!serverData.setup" app-name="social" :class="{public: serverData.public}">
<AppNavigation v-if="!serverData.public">
<AppNavigationItem v-for="item in menu.items" :key="item.key" :to="item.to"
:title="item.title" :icon="item.icon" :exact="true" />
</AppNavigation>
<div id="app-content">
<AppContent>
<div v-if="serverData.isAdmin && !serverData.checks.success" class="setup social__wrapper">
<h3 v-if="!serverData.checks.checks.wellknown">
{{ t('social', '.well-known/webfinger isn\'t properly set up!') }}
@ -20,10 +20,10 @@
</div>
<Search v-if="searchTerm !== ''" :term="searchTerm" />
<router-view v-if="searchTerm === ''" :key="$route.fullPath" />
</div>
</div>
<div v-else class="setup">
<template v-if="serverData.isAdmin">
</AppContent>
</Content>
<Content v-else app-name="social">
<AppContent v-if="serverData.isAdmin" class="setup">
<h2>{{ t('social', 'Social app setup') }}</h2>
<p>{{ t('social', 'ActivityPub requires a fixed URL to make entries unique. Note that this can not be changed later without resetting the Social app.') }}</p>
<form @submit.prevent="setCloudAddress">
@ -51,38 +51,29 @@
</p>
</template>
</form>
</template>
<template v-else>
</AppContent>
<AppContent v-else class="setup">
<p>{{ t('social', 'The Social app needs to be set up by the server administrator.') }}</p>
</template>
</div>
</AppContent>
</Content>
</template>
<style scoped>
#app-social {
width: 100%;
}
#app-content .social__wrapper {
#app-content-vue .social__wrapper {
padding: 15px;
max-width: 600px;
max-width: 630px;
margin: auto;
}
@media (min-width: 1200px) {
#app-social:not(.public) #app-content .social__wrapper {
margin: 15px calc(50% - 350px - 75px);
max-width: 600px;
}
}
.setup {
margin: auto;
width: 700px;
margin: 0 auto !important;
padding: 15px;
max-width: 630px;
}
.setup input[type=url] {
width: 300px;
max-width: 100%;
}
#social-spacer a:hover,
@ -97,15 +88,21 @@
</style>
<script>
import { AppNavigation, AppNavigationItem } from '@nextcloud/vue'
import Content from '@nextcloud/vue/dist/Components/Content'
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation'
import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
import axios from '@nextcloud/axios'
import Search from './components/Search.vue'
import currentuserMixin from './mixins/currentUserMixin'
import { loadState } from '@nextcloud/initial-state'
export default {
name: 'App',
components: {
Content,
AppContent,
AppNavigation,
AppNavigationItem,
Search
@ -201,10 +198,7 @@ export default {
},
beforeMount: function() {
// importing server data into the store
const serverDataElmt = document.getElementById('serverData')
if (serverDataElmt !== null) {
this.$store.commit('setServerData', JSON.parse(serverDataElmt.dataset.server))
}
this.$store.commit('setServerData', loadState('social', 'serverData'))
if (!this.serverData.public) {
this.search = new OCA.Search(this.search, this.resetSearch)

Wyświetl plik

@ -64,4 +64,4 @@ new Vue({
router: router,
render: h => h(App),
store: store
}).$mount('#vue-content')
}).$mount('#content')

Wyświetl plik

@ -38,4 +38,4 @@ Vue.prototype.OCA = OCA
new Vue({
render: h => h(OStatus),
store: store
}).$mount('#vue-content')
}).$mount('#content')

Wyświetl plik

@ -63,6 +63,7 @@
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
import axios from '@nextcloud/axios'
import currentuserMixin from './../mixins/currentUserMixin'
import { loadState } from '@nextcloud/initial-state'
export default {
name: 'App',
@ -100,9 +101,8 @@ export default {
},
beforeMount: function() {
// importing server data into the store
const serverDataElmt = document.getElementById('serverData')
if (serverDataElmt !== null) {
const serverData = JSON.parse(document.getElementById('serverData').dataset.server)
try {
const serverData = loadState('social', 'serverData')
if (serverData.currentUser) {
window.oc_current_user = JSON.parse(JSON.stringify(serverData.currentUser))
}
@ -113,7 +113,8 @@ export default {
if (this.serverData.local) {
this.$store.dispatch('fetchPublicAccountInfo', this.serverData.local)
}
} catch {
/* empty */
}
},
methods: {

Wyświetl plik

@ -22,6 +22,7 @@
import Logger from '../logger'
import TimelineEntry from './../components/TimelineEntry.vue'
import TimelineList from './../components/TimelineList.vue'
import { loadState } from '@nextcloud/initial-state'
export default {
name: 'TimelineSinglePost',
@ -43,7 +44,7 @@ export default {
// Get data of post clicked on
if (typeof this.$route.params.id === 'undefined') {
Logger.debug('displaying the single post timeline for a non logged-in user')
this.mainPost = JSON.parse(document.getElementById('postData').dataset.server)
this.mainPost = loadState('social', 'item')
} else {
this.mainPost = this.$store.getters.getPostFromTimeline(this.$route.params.id)
}

Wyświetl plik

@ -1,6 +1,26 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Jonas Sulzer <jonas@violoncello.ch>
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
script('social', 'social');
style('social', 'style');
?>
<span id="serverData" data-server="<?php p(json_encode($_['serverData']));?>"></span>
<div id="vue-content"></div>

Wyświetl plik

@ -1,29 +0,0 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
script('social', 'ostatus');
style('social', 'style');
?>
<span id="serverData" data-server="<?php p(json_encode($_['serverData']));?>"></span>
<div id="vue-content"></div>

Wyświetl plik

@ -1,7 +0,0 @@
<?php
script('social', 'social');
style('social', 'style');
?>
<span id="postData" data-server="<?php p(json_encode($_['item']));?>"></span>
<span id="serverData" data-server="<?php p(json_encode($_['serverData']));?>"></span>
<div id="vue-content"></div>