Change watch (#2624)
This commit is contained in:
Родитель
e1074f3fb5
Коммит
8df58e63e2
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -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());
|
||||
|
|
|
@ -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
|
|
@ -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')
|
||||
this.sleepTimeout = defaultSleepTimeout // reset sleep timer to default
|
||||
this.gotValidResponse = false
|
||||
|
||||
if (this.updateType === 'noPolling') {
|
||||
console.debug('[polls]', 'Polling for updates is disabled. Cancel watch.')
|
||||
this.cancelWatch()
|
||||
return
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
if (axios.isCancel(e)) {
|
||||
this.handleCanceledRequest()
|
||||
} else {
|
||||
this.handleConnectionError(e)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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')) {
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 = {
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
|
|
@ -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,6 +247,19 @@ 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 clone(context, payload) {
|
||||
const endPoint = `apps/polls/poll/${payload.pollId}/clone`
|
||||
try {
|
||||
const response = await axios.post(generateUrl(endPoint), null, axiosDefaultConfig)
|
||||
context.dispatch('polls/list', null, { root: true })
|
||||
return response
|
||||
} catch (e) {
|
||||
console.error('Error cloning poll', { error: e.response }, { payload })
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -254,15 +273,6 @@ const actions = {
|
|||
}
|
||||
},
|
||||
|
||||
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 })
|
||||
}
|
||||
},
|
||||
|
||||
async getParticipantsEmailAddresses(context) {
|
||||
const endPoint = `apps/polls/poll/${context.state.id}/addresses`
|
||||
try {
|
||||
|
@ -271,7 +281,6 @@ const actions = {
|
|||
console.error('Error retrieving email addresses', { error: e.response })
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export default { namespaced, state, mutations, getters, actions, modules }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 = {
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче