Create task from talk message
Signed-off-by: Jakob Röhrl <jakob.roehrl@web.de>
This commit is contained in:
parent
4873158062
commit
033d851712
|
@ -0,0 +1 @@
|
|||
@include icon-black-white('tasks', 'tasks', 1);
|
|
@ -23,10 +23,12 @@
|
|||
namespace OCA\Tasks\AppInfo;
|
||||
|
||||
use OCA\Tasks\Dashboard\TasksWidget;
|
||||
use OCA\Tasks\Listeners\BeforeTemplateRenderedListener;
|
||||
use OCP\AppFramework\App;
|
||||
use OCP\AppFramework\Bootstrap\IBootContext;
|
||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
||||
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
|
||||
|
||||
class Application extends App implements IBootstrap {
|
||||
|
||||
|
@ -42,6 +44,8 @@ class Application extends App implements IBootstrap {
|
|||
|
||||
public function register(IRegistrationContext $context): void {
|
||||
$context->registerDashboardWidget(TasksWidget::class);
|
||||
|
||||
$context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
* @author Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace OCA\Tasks\Listeners;
|
||||
|
||||
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\IRequest;
|
||||
use OCP\Util;
|
||||
|
||||
class BeforeTemplateRenderedListener implements IEventListener {
|
||||
private $request;
|
||||
|
||||
public function __construct(IRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function handle(Event $event): void {
|
||||
if (!($event instanceof BeforeTemplateRenderedEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$event->isLoggedIn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pathInfo = $this->request->getPathInfo();
|
||||
if (strpos($pathInfo, '/call/') === 0 || strpos($pathInfo, '/apps/spreed') === 0) {
|
||||
Util::addScript('tasks', 'tasks-talk');
|
||||
Util::addStyle('tasks', 'tasks-talk');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
:disabled="isDisabled"
|
||||
:options="calendars"
|
||||
:value="calendar"
|
||||
:placeholder="$t('tasks', 'Select a calendar')"
|
||||
:placeholder="translate('tasks', 'Select a calendar')"
|
||||
@select="change">
|
||||
<template slot="singleLabel" slot-scope="scope">
|
||||
<CalendarPickerOption v-bind="scope.option" />
|
||||
|
@ -43,7 +43,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
color=""
|
||||
owner=""
|
||||
:is-shared-with-me="false"
|
||||
:display-name="$t('tasks', 'No calendar matches the search.')" />
|
||||
:display-name="translate('tasks', 'No calendar matches the search.')" />
|
||||
</template>
|
||||
</Multiselect>
|
||||
</div>
|
||||
|
@ -52,6 +52,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|||
<script>
|
||||
import CalendarPickerOption from './CalendarPickerOption.vue'
|
||||
|
||||
import { translate } from '@nextcloud/l10n'
|
||||
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
|
||||
|
||||
export default {
|
||||
|
@ -62,7 +63,7 @@ export default {
|
|||
props: {
|
||||
calendar: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
calendars: {
|
||||
type: Array,
|
||||
|
@ -79,6 +80,7 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
translate,
|
||||
/**
|
||||
* TODO: this should emit the calendar id instead
|
||||
* @param {Object} newCalendar The selected calendar
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
<!--
|
||||
Nextcloud - Tasks
|
||||
|
||||
@author Julius Härtl
|
||||
@copyright 2021 Julius Härtl <jus@bitgrid.net>
|
||||
|
||||
@author Jakob Röhrl
|
||||
@copyright 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
|
||||
@author Raimund Schlüßler
|
||||
@copyright 2021 Raimund Schlüßler <raimund.schluessler@mailbox.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or any later version.
|
||||
|
||||
This library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-->
|
||||
|
||||
<template>
|
||||
<Modal class="task-selector" @close="close">
|
||||
<div class="modal-scroller">
|
||||
<div v-if="!creating && !created" id="modal-inner" :class="{ 'icon-loading': loading }">
|
||||
<h3>{{ t('tasks', 'Create a new task') }}</h3>
|
||||
|
||||
<CalendarPickerItem
|
||||
:disabled="loading"
|
||||
:calendar="pendingCalendar"
|
||||
:calendars="writableCalendars"
|
||||
@changeCalendar="changeCalendar" />
|
||||
|
||||
<input v-model="pendingTitle"
|
||||
type="text"
|
||||
:placeholder="t('tasks', 'Create a new task')"
|
||||
:disabled="loading">
|
||||
|
||||
<textarea v-model="pendingDescription"
|
||||
:disabled="loading" />
|
||||
<div class="modal-buttons">
|
||||
<button @click="close">
|
||||
{{ t('tasks', 'Cancel') }}
|
||||
</button>
|
||||
<button :disabled="loading"
|
||||
class="primary"
|
||||
@click="addTask">
|
||||
{{ t('tasks', 'Create task') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else id="modal-inner">
|
||||
<EmptyContent v-if="creating" icon="icon-loading">
|
||||
{{ t('tasks', 'Creating the new task…') }}
|
||||
</EmptyContent>
|
||||
<EmptyContent v-else-if="created" icon="icon-checkmark">
|
||||
{{ t('tasks', '"{task}" was added to "{calendar}"', { task: pendingTitle, calendar: pendingCalendar.displayName }, undefined, { sanitize: false, escape: false }) }}
|
||||
<template #desc>
|
||||
<button class="primary" @click="openNewTask">
|
||||
{{ t('tasks', 'Open task') }}
|
||||
</button>
|
||||
<button @click="close">
|
||||
{{ t('tasks', 'Close') }}
|
||||
</button>
|
||||
</template>
|
||||
</EmptyContent>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import CalendarPickerItem from './AppSidebar/CalendarPickerItem.vue'
|
||||
import client from '../services/cdav.js'
|
||||
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
|
||||
import Modal from '@nextcloud/vue/dist/Components/Modal'
|
||||
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'TaskCreateDialog',
|
||||
components: {
|
||||
CalendarPickerItem,
|
||||
EmptyContent,
|
||||
Modal,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pendingTitle: '',
|
||||
pendingDescription: '',
|
||||
pendingCalendar: null,
|
||||
loading: true,
|
||||
creating: false,
|
||||
created: false,
|
||||
newTask: null,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({
|
||||
writableCalendars: 'getSortedWritableCalendars',
|
||||
defaultCalendar: 'getDefaultCalendar',
|
||||
}),
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.fetchCalendars()
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.pendingTitle = this.title
|
||||
this.pendingDescription = this.description
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions([
|
||||
'createTask',
|
||||
]),
|
||||
|
||||
t,
|
||||
|
||||
changeCalendar(calendar) {
|
||||
this.pendingCalendar = calendar
|
||||
},
|
||||
|
||||
close() {
|
||||
this.$root.$emit('close')
|
||||
},
|
||||
|
||||
async fetchCalendars() {
|
||||
this.loading = true
|
||||
await client.connect({ enableCalDAV: true })
|
||||
await this.$store.dispatch('fetchCurrentUserPrincipal')
|
||||
await this.$store.dispatch('getCalendars')
|
||||
// TODO: Would be good to select the default calendar instead of the first one
|
||||
this.pendingCalendar = this.writableCalendars[0]
|
||||
this.loading = false
|
||||
},
|
||||
|
||||
async addTask() {
|
||||
this.creating = true
|
||||
const task = {
|
||||
summary: this.pendingTitle,
|
||||
note: this.pendingDescription,
|
||||
calendar: this.pendingCalendar,
|
||||
}
|
||||
this.newTask = await this.createTask(task)
|
||||
this.creating = false
|
||||
this.created = true
|
||||
},
|
||||
openNewTask() {
|
||||
window.location = generateUrl('apps/tasks') + `/#/calendars/${this.pendingCalendar.id}/tasks/${this.newTask.uri}`
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-scroller {
|
||||
overflow: scroll;
|
||||
max-height: calc(80vh - 40px);
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#modal-inner {
|
||||
width: 90vw;
|
||||
max-width: 400px;
|
||||
padding: 10px;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
width: 100%;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.modal-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.task-selector::v-deep .modal-container {
|
||||
overflow: visible !important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* @copyright Copyright (c) 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
* @author Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
import Vue from 'vue'
|
||||
import store from '../store/store.js'
|
||||
|
||||
const buildSelector = (selector, propsData = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const container = document.createElement('div')
|
||||
document.getElementById('body-user').append(container)
|
||||
const View = Vue.extend(selector)
|
||||
const ComponentVM = new View({
|
||||
propsData,
|
||||
store,
|
||||
}).$mount(container)
|
||||
ComponentVM.$root.$on('close', () => {
|
||||
ComponentVM.$el.remove()
|
||||
ComponentVM.$destroy()
|
||||
reject(new Error('Selection canceled'))
|
||||
})
|
||||
ComponentVM.$root.$on('select', (id) => {
|
||||
ComponentVM.$el.remove()
|
||||
ComponentVM.$destroy()
|
||||
resolve(id)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
buildSelector,
|
||||
}
|
|
@ -320,7 +320,14 @@ const mutations = {
|
|||
*/
|
||||
addCalendar(state, calendar) {
|
||||
// extend the calendar to the default model
|
||||
state.calendars.push(Object.assign({}, calendarModel, calendar))
|
||||
calendar = Object.assign({}, calendarModel, calendar)
|
||||
// Only add the calendar if it is not already present
|
||||
if (state.calendars.some(cal => {
|
||||
return cal.id === calendar.id
|
||||
})) {
|
||||
return
|
||||
}
|
||||
state.calendars.push(calendar)
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,7 @@ import { findVTODObyUid } from './cdav-requests.js'
|
|||
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import moment from '@nextcloud/moment'
|
||||
|
||||
import ICAL from 'ical.js'
|
||||
|
@ -702,36 +703,34 @@ const actions = {
|
|||
const vData = ICAL.stringify(task.jCal)
|
||||
|
||||
if (!task.dav) {
|
||||
await task.calendar.dav.createVObject(vData)
|
||||
.then((response) => {
|
||||
Vue.set(task, 'dav', response)
|
||||
task.syncStatus = new SyncStatus('success', OCA.Tasks.$t('tasks', 'Successfully created the task.'))
|
||||
context.commit('appendTask', task)
|
||||
context.commit('addTaskToCalendar', task)
|
||||
const parent = context.getters.getTaskByUid(task.related)
|
||||
context.commit('addTaskToParent', { task, parent })
|
||||
const response = await task.calendar.dav.createVObject(vData)
|
||||
Vue.set(task, 'dav', response)
|
||||
task.syncStatus = new SyncStatus('success', t('tasks', 'Successfully created the task.'))
|
||||
context.commit('appendTask', task)
|
||||
context.commit('addTaskToCalendar', task)
|
||||
const parent = context.getters.getTaskByUid(task.related)
|
||||
context.commit('addTaskToParent', { task, parent })
|
||||
|
||||
// Open the details view for the new task
|
||||
const calendarId = context.rootState.route.params.calendarId
|
||||
const collectionId = context.rootState.route.params.collectionId
|
||||
// Only open the details view if there is enough space or if it is already open.
|
||||
if (document.documentElement.clientWidth >= 768 || context.rootState.route.params.taskId !== undefined) {
|
||||
if (calendarId) {
|
||||
router.push({ name: 'calendarsTask', params: { calendarId, taskId: task.uri } })
|
||||
} else if (collectionId) {
|
||||
if (collectionId === 'week') {
|
||||
router.push({
|
||||
name: 'collectionsParamTask',
|
||||
params: { collectionId, taskId: task.uri, collectionParam: '0' },
|
||||
})
|
||||
} else {
|
||||
router.push({ name: 'collectionsTask', params: { collectionId, taskId: task.uri } })
|
||||
}
|
||||
}
|
||||
// In case the task is created in Talk, we don't have a route
|
||||
// Only open the details view if there is enough space or if it is already open.
|
||||
if (context.rootState.route !== undefined && (document.documentElement.clientWidth >= 768 || context.rootState.route?.params.taskId !== undefined)) {
|
||||
// Open the details view for the new task
|
||||
const calendarId = context.rootState.route.params.calendarId
|
||||
const collectionId = context.rootState.route.params.collectionId
|
||||
if (calendarId) {
|
||||
router.push({ name: 'calendarsTask', params: { calendarId, taskId: task.uri } })
|
||||
} else if (collectionId) {
|
||||
if (collectionId === 'week') {
|
||||
router.push({
|
||||
name: 'collectionsParamTask',
|
||||
params: { collectionId, taskId: task.uri, collectionParam: '0' },
|
||||
})
|
||||
} else {
|
||||
router.push({ name: 'collectionsTask', params: { collectionId, taskId: task.uri } })
|
||||
}
|
||||
|
||||
})
|
||||
.catch((error) => { throw error })
|
||||
}
|
||||
}
|
||||
return task
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -783,7 +782,7 @@ const actions = {
|
|||
})
|
||||
.catch((error) => {
|
||||
console.debug(error)
|
||||
task.syncStatus = new SyncStatus('error', OCA.Tasks.$t('tasks', 'Could not delete the task.'))
|
||||
task.syncStatus = new SyncStatus('error', t('tasks', 'Could not delete the task.'))
|
||||
})
|
||||
} else {
|
||||
deleteTaskFromStore()
|
||||
|
@ -875,10 +874,10 @@ const actions = {
|
|||
|
||||
if (!task.conflict) {
|
||||
task.dav.data = vCalendar
|
||||
task.syncStatus = new SyncStatus('sync', OCA.Tasks.$t('tasks', 'Synchronizing to the server.'))
|
||||
task.syncStatus = new SyncStatus('sync', t('tasks', 'Synchronizing to the server.'))
|
||||
return task.dav.update()
|
||||
.then((response) => {
|
||||
task.syncStatus = new SyncStatus('success', OCA.Tasks.$t('tasks', 'Task successfully saved to server.'))
|
||||
task.syncStatus = new SyncStatus('success', t('tasks', 'Task successfully saved to server.'))
|
||||
})
|
||||
.catch((error) => {
|
||||
// Wrong etag, we most likely have a conflict
|
||||
|
@ -886,13 +885,13 @@ const actions = {
|
|||
// Saving the new etag so that the user can manually
|
||||
// trigger a fetchCompleteData without any further errors
|
||||
task.conflict = error.xhr.getResponseHeader('etag')
|
||||
task.syncStatus = new SyncStatus('conflict', OCA.Tasks.$t('tasks', 'Could not update the task because it was changed on the server. Please click to refresh it, local changes will be discarded.'))
|
||||
task.syncStatus = new SyncStatus('conflict', t('tasks', 'Could not update the task because it was changed on the server. Please click to refresh it, local changes will be discarded.'))
|
||||
} else {
|
||||
task.syncStatus = new SyncStatus('error', OCA.Tasks.$t('tasks', 'Could not update the task.'))
|
||||
task.syncStatus = new SyncStatus('error', t('tasks', 'Could not update the task.'))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
task.syncStatus = new SyncStatus('conflict', OCA.Tasks.$t('tasks', 'Could not update the task because it was changed on the server. Please click to refresh it, local changes will be discarded.'))
|
||||
task.syncStatus = new SyncStatus('conflict', t('tasks', 'Could not update the task because it was changed on the server. Please click to refresh it, local changes will be discarded.'))
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1304,7 +1303,7 @@ const actions = {
|
|||
return task.dav.fetchCompleteData()
|
||||
.then((response) => {
|
||||
const newTask = new Task(task.dav.data, task.calendar)
|
||||
task.syncStatus = new SyncStatus('success', OCA.Tasks.$t('tasks', 'Successfully updated the task.'))
|
||||
task.syncStatus = new SyncStatus('success', t('tasks', 'Successfully updated the task.'))
|
||||
task.conflict = false
|
||||
context.commit('updateTask', newTask)
|
||||
})
|
||||
|
@ -1376,11 +1375,11 @@ const actions = {
|
|||
// Remove the task from the calendar, add it to the new one
|
||||
context.commit('addTaskToCalendar', task)
|
||||
context.commit('appendTask', task)
|
||||
task.syncStatus = new SyncStatus('success', OCA.Tasks.$t('tasks', 'Task successfully moved to new calendar.'))
|
||||
task.syncStatus = new SyncStatus('success', t('tasks', 'Task successfully moved to new calendar.'))
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
showError(OCA.Tasks.$t('tasks', 'An error occurred'))
|
||||
showError(t('tasks', 'An error occurred'))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Nextcloud - Tasks
|
||||
*
|
||||
* @author Julius Härtl
|
||||
* @copyright 2021 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Jakob Röhrl
|
||||
* @copyright 2021 Jakob Röhrl <jakob.roehrl@web.de>
|
||||
*
|
||||
* @author Raimund Schlüßler
|
||||
* @copyright 2021 Raimund Schlüßler <raimund.schluessler@mailbox.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library 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 library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import TaskCreateDialog from './components/TaskCreateDialog'
|
||||
import { buildSelector } from './helpers/selector'
|
||||
|
||||
import { getRequestToken } from '@nextcloud/auth'
|
||||
import { translate as t, translatePlural as n } from '@nextcloud/l10n'
|
||||
import { generateUrl, generateFilePath } from '@nextcloud/router'
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
// eslint-disable-next-line
|
||||
__webpack_nonce__ = btoa(getRequestToken())
|
||||
|
||||
// eslint-disable-next-line
|
||||
__webpack_public_path__ = generateFilePath('tasks', '', 'js/')
|
||||
|
||||
Vue.prototype.t = t
|
||||
Vue.prototype.n = n
|
||||
Vue.prototype.OC = OC
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
if (!window.OCA?.Talk?.registerMessageAction) {
|
||||
return
|
||||
}
|
||||
|
||||
window.OCA.Talk.registerMessageAction({
|
||||
label: t('tasks', 'Create a task'),
|
||||
icon: 'icon-tasks',
|
||||
async callback({ message: { message, actorDisplayName }, metadata: { name: conversationName, token: conversationToken } }) {
|
||||
const shortenedMessageCandidate = message.replace(/^(.{255}[^\s]*).*/, '$1')
|
||||
const shortenedMessage = shortenedMessageCandidate === '' ? message.substr(0, 255) : shortenedMessageCandidate
|
||||
try {
|
||||
await buildSelector(TaskCreateDialog, {
|
||||
title: shortenedMessage,
|
||||
description: message + '\n\n' + '['
|
||||
+ t('tasks', 'Message from {author} in {conversationName}', { author: actorDisplayName, conversationName })
|
||||
+ '](' + generateUrl('/call/' + conversationToken) + ')',
|
||||
})
|
||||
} catch (e) {
|
||||
console.debug('Task creation dialog was canceled')
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
|
@ -24,4 +24,14 @@ export class OC {
|
|||
return false
|
||||
}
|
||||
|
||||
L10N = {
|
||||
translate(app, text) {
|
||||
return text
|
||||
},
|
||||
|
||||
translatePlural(app, text) {
|
||||
return text
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ const path = require('path')
|
|||
webpackConfig.entry = {
|
||||
...webpackConfig.entry,
|
||||
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
|
||||
talk: path.join(__dirname, 'src', 'talk.js'),
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
|
|
Loading…
Reference in New Issue