diff --git a/lib/Listener/BeforeTemplateRenderedListener.php b/lib/Listener/BeforeTemplateRenderedListener.php index 80b5eed1..a92f92ec 100644 --- a/lib/Listener/BeforeTemplateRenderedListener.php +++ b/lib/Listener/BeforeTemplateRenderedListener.php @@ -34,6 +34,6 @@ public function handle(Event $event): void { return; } - Util::addScript(Application::APP_ID, Application::APP_ID . '-assistant'); + Util::addScript(Application::APP_ID, Application::APP_ID . '-main'); } } diff --git a/lib/Listener/TaskFailedListener.php b/lib/Listener/TaskFailedListener.php index 86e16176..6d4b6b17 100644 --- a/lib/Listener/TaskFailedListener.php +++ b/lib/Listener/TaskFailedListener.php @@ -2,8 +2,11 @@ namespace OCA\TPAssistant\Listener; +use OCA\TPAssistant\AppInfo\Application; +use OCA\TPAssistant\Event\BeforeAssistantNotificationEvent; use OCA\TPAssistant\Service\AssistantService; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventListener; use OCP\TextProcessing\Events\TaskFailedEvent; @@ -11,6 +14,7 @@ class TaskFailedListener implements IEventListener { public function __construct( private AssistantService $assistantService, + private IEventDispatcher $eventDispatcher, ) { } @@ -20,7 +24,24 @@ public function handle(Event $event): void { } $task = $event->getTask(); - $this->assistantService->sendNotification($task); - error_log('Task failed'); + error_log('Task failed ' . $task->getId()); + if ($task->getUserId() === null) { + return; + } + + $notificationTarget = null; + + // we dispatch an event to ask the app that scheduled the task if it wants a notification + // and what the target should be + if ($task->getAppId() !== Application::APP_ID) { + $beforeAssistantNotificationEvent = new BeforeAssistantNotificationEvent($task); + $this->eventDispatcher->dispatchTyped($beforeAssistantNotificationEvent); + if (!$beforeAssistantNotificationEvent->getWantsNotification()) { + return; + } + $notificationTarget = $beforeAssistantNotificationEvent->getNotificationTarget(); + } + + $this->assistantService->sendNotification($task, $notificationTarget); } } diff --git a/lib/Listener/TaskSuccessfulListener.php b/lib/Listener/TaskSuccessfulListener.php index 1de8005a..8262f3aa 100644 --- a/lib/Listener/TaskSuccessfulListener.php +++ b/lib/Listener/TaskSuccessfulListener.php @@ -24,6 +24,11 @@ public function handle(Event $event): void { } $task = $event->getTask(); + error_log('Task successful ' . $task->getId()); + if ($task->getUserId() === null) { + return; + } + $notificationTarget = null; // we dispatch an event to ask the app that scheduled the task if it wants a notification @@ -38,6 +43,5 @@ public function handle(Event $event): void { } $this->assistantService->sendNotification($task, $notificationTarget); - error_log('Task successful'); } } diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php index 6a2b5452..fdf6627a 100644 --- a/lib/Notification/Notifier.php +++ b/lib/Notification/Notifier.php @@ -84,6 +84,25 @@ public function prepare(INotification $notification, string $languageCode): INot return $notification; case 'failure': + $subject = $l->t('Assistant Task for app %1$s has failed', [$params['appId']]); + $content = $l->t('The input was: %1$s', [$params['input']]); + $link = $params['target'] ?? $this->url->linkToRouteAbsolute(Application::APP_ID . '.assistant.getTaskResultPage', ['taskId' => $params['id']]); + + $notification + ->setParsedSubject($subject) + ->setParsedMessage($content) + ->setLink($link) + ->setIcon($iconUrl); + + $actionLabel = $l->t('View results'); + $action = $notification->createAction(); + $action->setLabel($actionLabel) + ->setParsedLabel($actionLabel) + ->setLink($notification->getLink(), IAction::TYPE_WEB) + ->setPrimary(true); + + $notification->addParsedAction($action); + return $notification; default: diff --git a/src/assistant.js b/src/assistant.js index d7621d61..f3244042 100644 --- a/src/assistant.js +++ b/src/assistant.js @@ -22,7 +22,7 @@ __webpack_public_path__ = linkTo('textprocessing_assistant', 'js/') // eslint-di * @return {Promise} */ export async function openAssistantForm({ appId, identifier = '', taskType = null, input = '', isInsideViewer = undefined }) { - const { default: Vue } = await import(/* webpackChunkName: "vue-lazy" */'vue') + const { default: Vue } = await import(/* webpackChunkName: "vue-lazy1" */'vue') const { default: AssistantModal } = await import(/* webpackChunkName: "assistant-modal-lazy" */'./components/AssistantModal.vue') Vue.mixin({ methods: { t, n } }) @@ -68,7 +68,7 @@ export async function openAssistantForm({ appId, identifier = '', taskType = nul * @param {string} input the task input text * @return {Promise<*>} */ -async function scheduleTask(appId, identifier, taskType, input) { +export async function scheduleTask(appId, identifier, taskType, input) { const { default: axios } = await import(/* webpackChunkName: "axios-lazy" */'@nextcloud/axios') const { generateOcsUrl } = await import(/* webpackChunkName: "router-lazy" */'@nextcloud/router') const url = generateOcsUrl('textprocessing/schedule', 2) @@ -104,7 +104,7 @@ function handleNotification(event) { * * @return {Promise} */ -async function subscribeToNotifications() { +export async function subscribeToNotifications() { const { subscribe } = await import(/* webpackChunkName: "router-lazy" */'@nextcloud/event-bus') subscribe('notifications:action:execute', handleNotification) } @@ -133,7 +133,7 @@ async function showResults(taskId) { * @return {Promise} */ async function openAssistantResult(task) { - const { default: Vue } = await import(/* webpackChunkName: "vue-lazy" */'vue') + const { default: Vue } = await import(/* webpackChunkName: "vue-lazy2" */'vue') const { default: AssistantModal } = await import(/* webpackChunkName: "assistant-modal-lazy" */'./components/AssistantModal.vue') Vue.mixin({ methods: { t, n } }) @@ -167,13 +167,13 @@ async function openAssistantResult(task) { }) } -async function addAssistantMenuEntry() { +export async function addAssistantMenuEntry() { const headerRight = document.querySelector('#header .header-right') const menuEntry = document.createElement('div') menuEntry.id = 'assistant' headerRight.prepend(menuEntry) - const { default: Vue } = await import(/* webpackChunkName: "vue-lazy" */'vue') + const { default: Vue } = await import(/* webpackChunkName: "vue-lazy3" */'vue') const { default: AssistantHeaderMenuEntry } = await import(/* webpackChunkName: "assistant-modal-lazy" */'./components/AssistantHeaderMenuEntry.vue') Vue.mixin({ methods: { t, n } }) @@ -189,22 +189,3 @@ async function addAssistantMenuEntry() { }) }) } - -/** - * Expose OCA.TPAssistant.openTextProcessingModal to let apps use the assistant - * and add a header right menu entry - */ -function init() { - if (!OCA.TPAssistant) { - /** - * @namespace - */ - OCA.TPAssistant = { - openAssistantForm, - } - } - addAssistantMenuEntry() -} - -init() -subscribeToNotifications() diff --git a/src/main.js b/src/main.js new file mode 100644 index 00000000..8b159709 --- /dev/null +++ b/src/main.js @@ -0,0 +1,20 @@ +import { subscribeToNotifications, addAssistantMenuEntry, openAssistantForm } from './assistant.js' + +/** + * Expose OCA.TPAssistant.openTextProcessingModal to let apps use the assistant + * and add a header right menu entry + */ +function init() { + if (!OCA.TPAssistant) { + /** + * @namespace + */ + OCA.TPAssistant = { + openAssistantForm, + } + subscribeToNotifications() + addAssistantMenuEntry() + } +} + +init() diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index a91c3891..00000000 --- a/src/utils.js +++ /dev/null @@ -1,11 +0,0 @@ -let mytimer = 0 -export function delay(callback, ms) { - return function() { - const context = this - const args = arguments - clearTimeout(mytimer) - mytimer = setTimeout(function() { - callback.apply(context, args) - }, ms || 0) - } -} diff --git a/src/views/TaskResultPage.vue b/src/views/TaskResultPage.vue index 80f9f7f3..cce94732 100644 --- a/src/views/TaskResultPage.vue +++ b/src/views/TaskResultPage.vue @@ -7,7 +7,8 @@ class="form" :input="task.input" :output="task.output" - :selected-task-type-id="task.type" /> + :selected-task-type-id="task.type" + @submit="onSubmit" /> @@ -20,6 +21,7 @@ import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js' import AssistantForm from '../components/AssistantForm.vue' import { loadState } from '@nextcloud/initial-state' +import { scheduleTask } from '../assistant.js' export default { name: 'TaskResultPage', @@ -43,10 +45,18 @@ export default { }, mounted() { - console.debug('aaaaa MOUNTED', this.task) }, methods: { + onSubmit(data) { + scheduleTask(this.task.appId, this.task.identifier, data.taskTypeId, data.input) + .then((response) => { + console.debug('scheduled task', response.data?.ocs?.data?.task) + }) + .catch(error => { + console.error('Assistant scheduling error', error) + }) + }, }, } diff --git a/webpack.js b/webpack.js index 4e4d7d00..f7272e78 100644 --- a/webpack.js +++ b/webpack.js @@ -17,7 +17,7 @@ const appId = 'textprocessing_assistant' webpackConfig.entry = { personalSettings: { import: path.join(__dirname, 'src', 'personalSettings.js'), filename: appId + '-personalSettings.js' }, adminSettings: { import: path.join(__dirname, 'src', 'adminSettings.js'), filename: appId + '-adminSettings.js' }, - assistant: { import: path.join(__dirname, 'src', 'assistant.js'), filename: appId + '-assistant.js' }, + main: { import: path.join(__dirname, 'src', 'main.js'), filename: appId + '-main.js' }, taskResultPage: { import: path.join(__dirname, 'src', 'taskResultPage.js'), filename: appId + '-taskResultPage.js' }, }