diff options
author | René Gieling <github@dartcafe.de> | 2022-11-01 23:26:59 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-01 23:26:59 +0300 |
commit | 8df58e63e2145b2754e94b0d55b77fc8e8131c7c (patch) | |
tree | 6ef6bc19680f1aba4bdaee847d7e879eed64453d | |
parent | e1074f3fb59d2fc78f9cc2e62ac4d66b0e2bea2e (diff) |
Change watch (#2624)
25 files changed, 244 insertions, 120 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 7d4fe3c8..7466a52a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -66,6 +66,7 @@ use OCA\Polls\Listener\OptionListener; use OCA\Polls\Listener\PollListener; use OCA\Polls\Listener\ShareListener; use OCA\Polls\Listener\VoteListener; +use OCA\Polls\Middleware\RequestAttributesMiddleware; use OCA\Polls\Provider\SearchProvider; class Application extends App implements IBootstrap { @@ -83,6 +84,8 @@ class Application extends App implements IBootstrap { public function register(IRegistrationContext $context): void { include_once __DIR__ . '/../../vendor/autoload.php'; + $context->registerMiddleWare(RequestAttributesMiddleware::class); + $context->registerEventListener(CommentAddEvent::class, CommentListener::class); $context->registerEventListener(CommentDeleteEvent::class, CommentListener::class); $context->registerEventListener(OptionConfirmedEvent::class, OptionListener::class); diff --git a/lib/Command/Db/Rebuild.php b/lib/Command/Db/Rebuild.php index 5b19be5d..753a74ef 100644 --- a/lib/Command/Db/Rebuild.php +++ b/lib/Command/Db/Rebuild.php @@ -215,7 +215,7 @@ class Rebuild extends Command { if ($schema->hasTable($tableName)) {
$dropped = true;
$schema->dropTable($tableName);
- $output->writeln('<info> - Dropped' . $tableName .'</info>');
+ $output->writeln('<info> - Dropped ' . $tableName .'</info>');
}
}
$this->connection->migrateToSchema($schema->getWrappedSchema());
diff --git a/lib/Db/Watch.php b/lib/Db/Watch.php index e1e72d83..6c3d026c 100644 --- a/lib/Db/Watch.php +++ b/lib/Db/Watch.php @@ -36,6 +36,8 @@ use OCP\AppFramework\Db\Entity; * @method void setTable(string $value) * @method int getUpdated() * @method void setUpdated(integer $value) + * @method int getSessionId() + * @method void setSessionId(string $value) */ class Watch extends Entity implements JsonSerializable { public const TABLE = 'polls_watch'; @@ -54,6 +56,9 @@ class Watch extends Entity implements JsonSerializable { /** @var int $updated */ protected $updated; + /** @var string $sessionId */ + protected $sessionId; + public function __construct() { $this->addType('pollId', 'int'); $this->addType('updated', 'int'); diff --git a/lib/Db/WatchMapper.php b/lib/Db/WatchMapper.php index 5b92933f..f01c753a 100644 --- a/lib/Db/WatchMapper.php +++ b/lib/Db/WatchMapper.php @@ -25,6 +25,7 @@ namespace OCA\Polls\Db; use OCP\IDBConnection; use OCP\AppFramework\Db\QBMapper; +use OCP\ISession; /** * @template-extends QBMapper<Watch> @@ -32,8 +33,15 @@ use OCP\AppFramework\Db\QBMapper; class WatchMapper extends QBMapper { public const TABLE = Watch::TABLE; - public function __construct(IDBConnection $db) { + /** @var ISession */ + protected $session = null; + + public function __construct( + IDBConnection $db, + ISession $session + ) { parent::__construct($db, self::TABLE, Watch::class); + $this->session = $session; } /** @@ -46,6 +54,9 @@ class WatchMapper extends QBMapper { $qb->select('*') ->from($this->getTableName()) ->where($qb->expr()->gt('updated', $qb->createNamedParameter($offset))) + ->andWhere( + $qb->expr()->neq('session_id', $qb->createNamedParameter(hash('md5', $this->session->get('ncPollsClientId')))) + ) ->andWhere($qb->expr()->orX( $qb->expr()->eq('poll_id', $qb->createNamedParameter($pollId)), $qb->expr()->eq('table', $qb->createNamedParameter('polls')) @@ -68,6 +79,9 @@ class WatchMapper extends QBMapper { ) ->andWhere( $qb->expr()->eq('table', $qb->createNamedParameter($table)) + ) + ->andWhere( + $qb->expr()->eq('session_id', $qb->createNamedParameter(hash('md5', $this->session->get('ncPollsClientId')))) ); return $this->findEntity($qb); diff --git a/lib/Middleware/RequestAttributesMiddleware.php b/lib/Middleware/RequestAttributesMiddleware.php new file mode 100644 index 00000000..83d52e8d --- /dev/null +++ b/lib/Middleware/RequestAttributesMiddleware.php @@ -0,0 +1,37 @@ +<?php + +namespace OCA\Polls\Middleware; + +use OCP\AppFramework\Middleware; +use OCP\ISession; +use OCP\IRequest; + +class RequestAttributesMiddleware extends Middleware { + private const CLIENT_ID_KEY = 'Nc-Polls-Client-Id'; + + /** @var ISession */ + protected $session; + + /** @var IRequest */ + protected $request; + + public function __construct( + IRequest $request, + ISession $session + ) { + $this->request = $request; + $this->session = $session; + } + + public function beforeController($controller, $methodName) { + $clientId = $this->request->getHeader(self::CLIENT_ID_KEY); + + if (!$clientId) { + $clientId = $this->session->getId(); + } + + if ($clientId) { + $this->session->set('ncPollsClientId', $clientId); + } + } +} diff --git a/lib/Migration/DeleteInvalidRecords.php b/lib/Migration/DeleteInvalidRecords.php index bf5bc6f6..562eae29 100644 --- a/lib/Migration/DeleteInvalidRecords.php +++ b/lib/Migration/DeleteInvalidRecords.php @@ -38,6 +38,7 @@ use OCA\Polls\Db\Poll; use OCA\Polls\Db\ShareMapper; use OCA\Polls\Db\SubscriptionMapper; use OCA\Polls\Db\VoteMapper; +use OCA\Polls\Db\WatchMapper; /** * Preparation before migration @@ -68,6 +69,9 @@ class DeleteInvalidRecords implements IRepairStep { /** @var VoteMapper */ private $voteMapper; + /** @var WatchMapper */ + private $watchMapper; + /** @var array */ protected $childTables = [ CommentMapper::TABLE, @@ -86,7 +90,8 @@ class DeleteInvalidRecords implements IRepairStep { PreferencesMapper $preferencesMapper, ShareMapper $shareMapper, SubscriptionMapper $subscriptionMapper, - VoteMapper $voteMapper + VoteMapper $voteMapper, + WatchMapper $watchMapper ) { $this->config = $config; $this->connection = $connection; @@ -96,6 +101,7 @@ class DeleteInvalidRecords implements IRepairStep { $this->shareMapper = $shareMapper; $this->subscriptionMapper = $subscriptionMapper; $this->voteMapper = $voteMapper; + $this->watchMapper = $watchMapper; } public function getName():string { @@ -112,6 +118,7 @@ class DeleteInvalidRecords implements IRepairStep { $this->shareMapper->removeDuplicates($output); $this->subscriptionMapper->removeDuplicates($output); $this->voteMapper->removeDuplicates($output); + $this->watchMapper->deleteOldEntries(time()); } } diff --git a/lib/Migration/TableSchema.php b/lib/Migration/TableSchema.php index e7bdecc1..a3901fa6 100644 --- a/lib/Migration/TableSchema.php +++ b/lib/Migration/TableSchema.php @@ -62,7 +62,7 @@ abstract class TableSchema { Share::TABLE => ['name' => 'UNIQ_shares', 'unique' => true, 'columns' => ['poll_id', 'user_id']], Vote::TABLE => ['name' => 'UNIQ_votes', 'unique' => true, 'columns' => ['poll_id', 'user_id', 'vote_option_text']], Preferences::TABLE => ['name' => 'UNIQ_preferences', 'unique' => true, 'columns' => ['user_id']], - Watch::TABLE => ['name' => 'UNIQ_watch', 'unique' => true, 'columns' => ['poll_id', 'table']], + Watch::TABLE => ['name' => 'UNIQ_watch', 'unique' => true, 'columns' => ['poll_id', 'table', 'session_id']], ]; /** @@ -101,12 +101,15 @@ abstract class TableSchema { '0109Date20210323120002', '030000Date20210611120000', '030000Date20210704120000', + '030200Date20210912120000', + '030400Date20211125120000', ]; /** * define obsolete tables to drop */ public const GONE_TABLES = [ + 'polls_watch', // always drop the watch table for a clean truncation and rely on recreation 'polls_events', // dropped in 1.0 'polls_dts', // dropped in 0.9 'polls_txts', // dropped in 0.9 @@ -222,6 +225,7 @@ abstract class TableSchema { 'poll_id' => ['type' => Types::INTEGER, 'options' => ['notnull' => true, 'default' => 0]], 'table' => ['type' => Types::STRING, 'options' => ['notnull' => false, 'default' => '', 'length' => 64]], 'updated' => ['type' => Types::INTEGER, 'options' => ['notnull' => true, 'default' => 0]], + 'session_id' => ['type' => Types::STRING, 'options' => ['notnull' => false, 'default' => null]], ], Preferences::TABLE => [ 'id' => ['type' => Types::INTEGER, 'options' => ['autoincrement' => true, 'notnull' => true]], @@ -277,7 +281,7 @@ abstract class TableSchema { foreach (self::GONE_TABLES as $tableName) { if ($schema->hasTable($tableName)) { $schema->dropTable($tableName); - $output->info('Dropped orphaned table ' . $tableName); + $output->info('Dropped table ' . $tableName); } } } diff --git a/lib/Migration/Version030400Date20211125120000.php b/lib/Migration/Version040100Date20221030070000.php index e71aadb2..6d9f36ab 100644 --- a/lib/Migration/Version030400Date20211125120000.php +++ b/lib/Migration/Version040100Date20221030070000.php @@ -23,12 +23,12 @@ namespace OCA\Polls\Migration; +use OCA\Polls\Db\Poll; use OCP\DB\ISchemaWrapper; use OCP\IConfig; use OCP\IDBConnection; use OCP\Migration\SimpleMigrationStep; use OCP\Migration\IOutput; -use OCA\Polls\Db\Poll; /** * Installation class for the polls app. @@ -36,7 +36,7 @@ use OCA\Polls\Db\Poll; * Changed class naming: Version[jjmmpp]Date[YYYYMMDDHHMMSS] * Version: jj = major version, mm = minor, pp = patch */ -class Version030400Date20211125120000 extends SimpleMigrationStep { +class Version040100Date20221030070000 extends SimpleMigrationStep { /** @var IDBConnection */ protected $connection; diff --git a/lib/Service/WatchService.php b/lib/Service/WatchService.php index 81166a76..c873a5e1 100644 --- a/lib/Service/WatchService.php +++ b/lib/Service/WatchService.php @@ -28,11 +28,16 @@ use OCA\Polls\Db\WatchMapper; use OCA\Polls\Exceptions\NoUpdatesException; use OCA\Polls\Model\Settings\AppSettings; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\DB\Exception; +use OCP\ISession; class WatchService { /** @var AppSettings */ private $appSettings; + /** @var ISession */ + protected $session; + /** @var WatchMapper */ private $watchMapper; @@ -40,11 +45,13 @@ class WatchService { private $watch; public function __construct( + ISession $session, WatchMapper $watchMapper ) { - $this->watchMapper = $watchMapper; $this->appSettings = new AppSettings; + $this->session = $session; $this->watch = new Watch; + $this->watchMapper = $watchMapper; } /** @@ -86,13 +93,19 @@ class WatchService { * @return Watch */ public function writeUpdate(int $pollId, string $table): Watch { + $sessionId = hash('md5', $this->session->get('ncPollsClientId')); + $this->watch = new Watch(); + $this->watch->setPollId($pollId); + $this->watch->setTable($table); + $this->watch->setSessionId($sessionId); + try { - $this->watch = $this->watchMapper->findForPollIdAndTable($pollId, $table); - } catch (DoesNotExistException $e) { - $this->watch = new Watch(); - $this->watch->setPollId($pollId); - $this->watch->setTable($table); $this->watch = $this->watchMapper->insert($this->watch); + } catch (Exception $e) { + if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) { + throw $e; + } + $this->watch = $this->watchMapper->findForPollIdAndTable($pollId, $table); } $this->watch->setUpdated(time()); diff --git a/src/js/helpers/AxiosDefault.js b/src/js/helpers/AxiosDefault.js new file mode 100644 index 00000000..834b13e6 --- /dev/null +++ b/src/js/helpers/AxiosDefault.js @@ -0,0 +1,31 @@ +/**
+ * @copyright Copyright (c) 2022 Rene Gieling <github@dartcafe.de>
+ *
+ * @author Rene Gieling <github@dartcafe.de>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * 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/>.
+ *
+ */
+
+const clientSessionId = Math.random().toString(36).substring(2)
+const axiosDefaultConfig = {
+ headers: {
+ Accept: 'application/json',
+ 'Nc-Polls-Client-Id': clientSessionId,
+ },
+}
+
+export default axiosDefaultConfig
diff --git a/src/js/mixins/watchPolls.js b/src/js/mixins/watchPolls.js index 6f545ec6..4e3b4e6d 100644 --- a/src/js/mixins/watchPolls.js +++ b/src/js/mixins/watchPolls.js @@ -26,6 +26,7 @@ import { generateUrl } from '@nextcloud/router' import { getCurrentUser } from '@nextcloud/auth' import { mapState } from 'vuex' import { InvalidJSON } from '../Exceptions/Exceptions.js' +import axiosDefaultConfig from '../helpers/AxiosDefault.js' const defaultSleepTimeout = 30 @@ -54,48 +55,45 @@ export const watchPolls = { methods: { async watchPolls() { - // quit if polling for updates is disabled - if (this.updateType === 'noPolling') { - return - } - if (this.cancelToken) { - // there is already a cancelToken, so just cancel the previous session and exit - this.cancelWatch() - return + this.cancelWatch() // there is already a cancelToken, cancel the previous session } - this.cancelToken = axios.CancelToken.source() + this.cancelToken = axios.CancelToken.source() // get a new cancel token while (this.retryCounter < this.maxTries) { - // Avoid requests, if the tab/window is not visible - if (!document.hidden) { - // reset sleep timer to default - this.sleepTimeout = defaultSleepTimeout - this.gotValidResponse = false - await this.$store.dispatch('appSettings/get') - - if (this.updateType === 'noPolling') { - console.debug('[polls]', 'Polling for updates is disabled. Cancel watch.') - this.cancelWatch() - return - } + this.sleepTimeout = defaultSleepTimeout // reset sleep timer to default + this.gotValidResponse = false + + if (this.updateType === 'noPolling') { + // leave if polling is disabled + console.debug('[polls]', 'Polling for updates is disabled. Cancel watch.') + this.cancelWatch() + return + } - try { - console.debug('[polls]', 'Watch for updates') - await this.handleResponse(await this.fetchUpdates()) + // loop while tab is hidden and avoid further requests + while (document.hidden) { + console.debug('[polls]', 'app is in background') + await new Promise((resolve) => setTimeout(resolve, 2000)) + } + + try { + console.debug('[polls]', 'Watch for updates') + await this.handleResponse(await this.fetchUpdates()) - } catch (e) { - if (axios.isCancel(e)) { - this.handleCanceledRequest() - } else { - this.handleConnectionError(e) - } + } catch (e) { + if (axios.isCancel(e)) { + this.handleCanceledRequest() + } else { + this.handleConnectionError(e) } } - if (this.updateType !== 'longPolling' || !this.gotValidResponse || document.hidden) { + // sleep if request was invalid or polling is set to something else than "longPolling" + if (this.updateType !== 'longPolling' || !this.gotValidResponse) { await this.sleep() + console.debug('[polls]', 'continue after sleep') } } @@ -114,11 +112,16 @@ export const watchPolls = { this.endPoint = `apps/polls/poll/${this.$route.params.id ?? 0}/watch` } - return await axios.get(generateUrl(this.endPoint), { + await this.$store.dispatch('appSettings/get') + + const response = await axios.get(generateUrl(this.endPoint), { + ...axiosDefaultConfig, params: { offset: this.lastUpdated }, cancelToken: this.cancelToken.token, - headers: { Accept: 'application/json' }, }) + + return response + }, cancelWatch() { @@ -128,9 +131,7 @@ export const watchPolls = { sleep() { let reason = `Connection error, Attempt: ${this.retryCounter}/${this.maxTries})` - if (document.hidden) { - reason = 'app is in background' - } else if (this.gotValidResponse) { + if (this.gotValidResponse) { reason = this.updateType } @@ -147,7 +148,6 @@ export const watchPolls = { return } - // console.debug('[polls]', `No JSON response recieved, got "${response.headers['content-type']}"`) this.gotValidResponse = false throw new InvalidJSON(`No JSON response recieved, got "${response.headers['content-type']}"`) }, @@ -183,22 +183,25 @@ export const watchPolls = { async loadTables(tables) { let dispatches = ['activity/list'] + console.debug('[polls]', 'fetching updates', tables) tables.forEach((item) => { this.lastUpdated = Math.max(item.updated, this.lastUpdated) - if (item.table === 'polls') { if (this.isAdmin) { + console.debug('[polls]', 'update admin view', item.table) // If user is an admin, also load admin list dispatches = [...dispatches, 'pollsAdmin/list'] } if (item.pollId === parseInt(this.$route.params.id ?? this.$store.state.share.pollId)) { // if current poll is affected, load current poll configuration + console.debug('[polls]', 'current poll', item.table) dispatches = [...dispatches, 'poll/get'] } if (this.isLoggedin) { // if user is an authorized user load polls list + console.debug('[polls]', 'update list', item.table) dispatches = [...dispatches, `${item.table}/list`] } } else if (!this.isLoggedin && (item.table === 'shares')) { diff --git a/src/js/store/index.js b/src/js/store/index.js index b815c149..456f5088 100644 --- a/src/js/store/index.js +++ b/src/js/store/index.js @@ -27,10 +27,9 @@ import modules from './modules/index.js' Vue.use(Vuex) -/* eslint-disable-next-line no-unused-vars */ const debug = process.env.NODE_ENV !== 'production' export default new Store({ modules, - strict: process.env.NODE_ENV !== 'production', + strict: debug, }) diff --git a/src/js/store/modules/activity.js b/src/js/store/modules/activity.js index ee924caa..b8ec60bd 100644 --- a/src/js/store/modules/activity.js +++ b/src/js/store/modules/activity.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateOcsUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultActivities = () => ({ list: [], @@ -30,7 +31,6 @@ const defaultActivities = () => ({ const namespaced = true const state = defaultActivities() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { diff --git a/src/js/store/modules/appSettings.js b/src/js/store/modules/appSettings.js index 8e9879d1..3e2f23a8 100644 --- a/src/js/store/modules/appSettings.js +++ b/src/js/store/modules/appSettings.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultAppSettings = () => ({ allAccessGroups: [], @@ -55,7 +56,6 @@ const defaultAppSettings = () => ({ const namespaced = true const state = defaultAppSettings() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { reset(state) { diff --git a/src/js/store/modules/combo.js b/src/js/store/modules/combo.js index 334f553d..19128926 100644 --- a/src/js/store/modules/combo.js +++ b/src/js/store/modules/combo.js @@ -25,6 +25,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' import { uniqueOptions, uniqueParticipants } from '../../helpers/arrayHelper.js' import { sortBy } from 'lodash' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultCombo = () => ({ id: 1, @@ -36,7 +37,6 @@ const defaultCombo = () => ({ const namespaced = true const state = defaultCombo() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { diff --git a/src/js/store/modules/comments.js b/src/js/store/modules/comments.js index 7e1425f8..487e0f80 100644 --- a/src/js/store/modules/comments.js +++ b/src/js/store/modules/comments.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultComments = () => ({ list: [], @@ -30,7 +31,6 @@ const defaultComments = () => ({ const namespaced = true const state = defaultComments() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { diff --git a/src/js/store/modules/options.js b/src/js/store/modules/options.js index 5270d1f8..f59d3bd8 100644 --- a/src/js/store/modules/options.js +++ b/src/js/store/modules/options.js @@ -25,6 +25,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' import { orderBy } from 'lodash' import moment from '@nextcloud/moment' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultOptions = () => ({ list: [], @@ -33,7 +34,6 @@ const defaultOptions = () => ({ const namespaced = true const state = defaultOptions() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { @@ -184,22 +184,6 @@ const actions = { } }, - async addBulk(context, payload) { - const endPoint = 'apps/polls/option/bulk' - - try { - const response = await axios.post(generateUrl(endPoint), { - pollId: context.rootState.route.params.id, - text: payload.text, - }, axiosDefaultConfig) - context.commit('set', { options: response.data.options }) - } catch (e) { - console.error(`Error adding option: ${e.response.data}`, { error: e.response }, { payload }) - context.dispatch('list') - throw e - } - }, - async update(context, payload) { const endPoint = `apps/polls/option/${payload.option.id}` @@ -236,6 +220,22 @@ const actions = { } }, + async addBulk(context, payload) { + const endPoint = 'apps/polls/option/bulk' + + try { + const response = await axios.post(generateUrl(endPoint), { + pollId: context.rootState.route.params.id, + text: payload.text, + }, axiosDefaultConfig) + context.commit('set', { options: response.data.options }) + } catch (e) { + console.error(`Error adding option: ${e.response.data}`, { error: e.response }, { payload }) + context.dispatch('list') + throw e + } + }, + async confirm(context, payload) { const endPoint = `apps/polls/option/${payload.option.id}/confirm` diff --git a/src/js/store/modules/poll.js b/src/js/store/modules/poll.js index dcad3e38..aa587336 100644 --- a/src/js/store/modules/poll.js +++ b/src/js/store/modules/poll.js @@ -26,6 +26,7 @@ import moment from '@nextcloud/moment' import { generateUrl } from '@nextcloud/router' import acl from './subModules/acl.js' import { uniqueArrayOfObjects } from '../../helpers/arrayHelper.js' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultPoll = () => ({ id: 0, @@ -60,7 +61,6 @@ const defaultPoll = () => ({ const namespaced = true const modules = { acl } const state = defaultPoll() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { @@ -200,38 +200,44 @@ const actions = { async add(context, payload) { const endPoint = 'apps/polls/poll/add' try { - return await axios.post(generateUrl(endPoint), { + const response = await axios.post(generateUrl(endPoint), { title: payload.title, type: payload.type, }, axiosDefaultConfig) + + context.dispatch('polls/list', null, { root: true }) + return response } catch (e) { console.error('Error adding poll:', { error: e.response }, { state: context.state }) throw e } }, - async clone(context, payload) { - const endPoint = `apps/polls/poll/${payload.pollId}/clone` - try { - return await axios.post(generateUrl(endPoint), null, axiosDefaultConfig) - } catch (e) { - console.error('Error cloning poll', { error: e.response }, { payload }) - } - }, - async update(context) { const endPoint = `apps/polls/poll/${context.state.id}` try { const response = await axios.put(generateUrl(endPoint), { poll: context.state, }, axiosDefaultConfig) - context.commit('set', response.data) context.commit('acl/set', response.data) - context.dispatch('options/list', null, { root: true }) } catch (e) { console.error('Error updating poll:', { error: e.response }, { poll: context.state }) + context.dispatch('get') throw e + } finally { + context.dispatch('polls/list', null, { root: true }) + } + }, + + async delete(context, payload) { + const endPoint = `apps/polls/poll/${payload.pollId}` + try { + await axios.delete(generateUrl(endPoint), axiosDefaultConfig) + } catch (e) { + console.error('Error deleting poll', { error: e.response }, { payload }) + } finally { + context.dispatch('polls/list', null, { root: true }) } }, @@ -241,25 +247,29 @@ const actions = { await axios.put(generateUrl(endPoint), null, axiosDefaultConfig) } catch (e) { console.error('Error archiving/restoring', { error: e.response }, { payload }) + } finally { + context.dispatch('polls/list', null, { root: true }) } }, - async sendConfirmation(context, payload) { - const endPoint = `apps/polls/poll/${context.rootState.route.params.id}/confirmation` + async clone(context, payload) { + const endPoint = `apps/polls/poll/${payload.pollId}/clone` try { const response = await axios.post(generateUrl(endPoint), null, axiosDefaultConfig) - return response.data.confirmations + context.dispatch('polls/list', null, { root: true }) + return response } catch (e) { - console.error('Error sending confirmation', { error: e.response }, { payload }) + console.error('Error cloning poll', { error: e.response }, { payload }) } }, - async delete(context, payload) { - const endPoint = `apps/polls/poll/${payload.pollId}` + async sendConfirmation(context, payload) { + const endPoint = `apps/polls/poll/${context.rootState.route.params.id}/confirmation` try { - await axios.delete(generateUrl(endPoint), axiosDefaultConfig) + const response = await axios.post(generateUrl(endPoint), null, axiosDefaultConfig) + return response.data.confirmations } catch (e) { - console.error('Error deleting poll', { error: e.response }, { payload }) + console.error('Error sending confirmation', { error: e.response }, { payload }) } }, @@ -271,7 +281,6 @@ const actions = { console.error('Error retrieving email addresses', { error: e.response }) } }, - } export default { namespaced, state, mutations, getters, actions, modules } diff --git a/src/js/store/modules/polls.js b/src/js/store/modules/polls.js index 9095b52c..e188ac7b 100644 --- a/src/js/store/modules/polls.js +++ b/src/js/store/modules/polls.js @@ -27,6 +27,7 @@ import axios from '@nextcloud/axios' import moment from '@nextcloud/moment' import { generateUrl } from '@nextcloud/router' import { orderBy } from 'lodash' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const state = { list: [], @@ -138,7 +139,6 @@ const state = { } const namespaced = true -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { diff --git a/src/js/store/modules/pollsAdmin.js b/src/js/store/modules/pollsAdmin.js index a0182d42..d30f1338 100644 --- a/src/js/store/modules/pollsAdmin.js +++ b/src/js/store/modules/pollsAdmin.js @@ -4,8 +4,6 @@ * * @author Rene Gieling <github@dartcafe.de> * - * @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com> - * * @license AGPL-3.0-or-later * * This program is free software: you can redistribute it and/or modify @@ -26,12 +24,12 @@ import axios from '@nextcloud/axios' import { getCurrentUser } from '@nextcloud/auth' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const namespaced = true const state = { list: [], } -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { diff --git a/src/js/store/modules/settings.js b/src/js/store/modules/settings.js index 7f8fae6f..b5e03338 100644 --- a/src/js/store/modules/settings.js +++ b/src/js/store/modules/settings.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultSettings = () => ({ user: { @@ -49,7 +50,6 @@ const defaultSettings = () => ({ const namespaced = true const state = defaultSettings() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { reset(state) { @@ -57,6 +57,7 @@ const mutations = { }, setPreference(state, payload) { + // change values in case of old settings if (payload.defaultViewTextPoll === 'desktop') { payload.defaultViewTextPoll = 'table-view' } diff --git a/src/js/store/modules/share.js b/src/js/store/modules/share.js index c5d5e604..43b50adb 100644 --- a/src/js/store/modules/share.js +++ b/src/js/store/modules/share.js @@ -24,6 +24,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' import { setCookie } from '../../helpers/cookieHelper.js' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultShares = () => ({ displayName: '', @@ -39,7 +40,6 @@ const defaultShares = () => ({ const namespaced = true const state = defaultShares() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { diff --git a/src/js/store/modules/shares.js b/src/js/store/modules/shares.js index 497364d3..8095cb36 100644 --- a/src/js/store/modules/shares.js +++ b/src/js/store/modules/shares.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultShares = () => ({ list: [], @@ -30,7 +31,6 @@ const defaultShares = () => ({ const namespaced = true const state = defaultShares() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { @@ -99,21 +99,6 @@ const actions = { } }, - async delete(context, payload) { - const endPoint = `apps/polls/share/${payload.share.token}` - - context.commit('delete', { share: payload.share }) - - try { - await axios.delete(generateUrl(endPoint), axiosDefaultConfig) - } catch (e) { - console.error('Error removing share', { error: e.response }, { payload }) - throw e - } finally { - context.dispatch('list') - } - }, - async switchAdmin(context, payload) { let endPoint = `apps/polls/share/${payload.share.token}` @@ -171,6 +156,21 @@ const actions = { context.dispatch('list') } }, + + async delete(context, payload) { + const endPoint = `apps/polls/share/${payload.share.token}` + + context.commit('delete', { share: payload.share }) + + try { + await axios.delete(generateUrl(endPoint), axiosDefaultConfig) + } catch (e) { + console.error('Error removing share', { error: e.response }, { payload }) + throw e + } finally { + context.dispatch('list') + } + }, } export default { namespaced, state, mutations, actions, getters } diff --git a/src/js/store/modules/subscription.js b/src/js/store/modules/subscription.js index 607f45a6..3a531066 100644 --- a/src/js/store/modules/subscription.js +++ b/src/js/store/modules/subscription.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultSubscription = () => ({ subscribed: false, @@ -30,7 +31,6 @@ const defaultSubscription = () => ({ const namespaced = true const state = defaultSubscription() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { diff --git a/src/js/store/modules/votes.js b/src/js/store/modules/votes.js index 9e836df8..9a7fb92d 100644 --- a/src/js/store/modules/votes.js +++ b/src/js/store/modules/votes.js @@ -23,6 +23,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' +import axiosDefaultConfig from '../../helpers/AxiosDefault.js' const defaultVotes = () => ({ list: [], @@ -30,7 +31,6 @@ const defaultVotes = () => ({ const namespaced = true const state = defaultVotes() -const axiosDefaultConfig = { headers: { Accept: 'application/json' } } const mutations = { set(state, payload) { |