Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@

use OCA\Forms\Capabilities;
use OCA\Forms\FormsMigrator;
use OCA\Forms\Listener\BeforeTemplateRenderedListener;
use OCA\Forms\Listener\UserDeletedListener;
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;
use OCP\User\Events\UserDeletedEvent;

class Application extends App implements IBootstrap {
Expand All @@ -59,6 +61,7 @@ public function register(IRegistrationContext $context): void {
$context->registerCapability(Capabilities::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerUserMigrator(FormsMigrator::class);
$context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
}

/**
Expand Down
26 changes: 26 additions & 0 deletions lib/Listener/BeforeTemplateRenderedListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace OCA\Forms\Listener;

use OCA\Text\Event\LoadEditor;
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\EventDispatcher\IEventListener;

/** @template-implements IEventListener<Event|BeforeTemplateRenderedEvent> */
class BeforeTemplateRenderedListener implements IEventListener {
public function __construct(private IEventDispatcher $eventDispatcher) {
}

public function handle(Event $event): void {
if (!($event instanceof BeforeTemplateRenderedEvent)) {
return;
}

$isFormsResponse = $event->getResponse()->getApp() === \OCA\Forms\AppInfo\Application::APP_ID;
if ($isFormsResponse && class_exists(LoadEditor::class)) {
$this->eventDispatcher->dispatchTyped(new LoadEditor());
}
}
}
73 changes: 61 additions & 12 deletions src/components/Questions/Question.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,24 @@
</NcActions>
</div>
<div v-if="hasDescription || !readOnly" class="question__header__description">
<textarea v-if="!readOnly"
ref="description"
dir="auto"
:value="description"
:placeholder="t('forms', 'Description (formatting using Markdown is supported)')"
:maxlength="maxStringLengths.questionDescription"
class="question__header__description__input"
@input="onDescriptionChange" />
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-else class="question__header__description__output" v-html="computedDescription" />
<div v-show="editor">
<label>{{ t('forms', 'Description') }}</label>
<div v-if="!readOnly" ref="editor" />
</div>

<template v-if="!editor">
<textarea v-if="!readOnly"
ref="description"
dir="auto"
:value="description"
:placeholder="t('forms', 'Description (formatting using Markdown is supported)')"
:maxlength="maxStringLengths.questionDescription"
class="question__header__description__input"
@input="onDescriptionChange" />

<!-- eslint-disable-next-line vue/no-v-html -->
<div v-else class="question__header__description__output" v-html="computedDescription" />
</template>
</div>
</div>

Expand All @@ -162,6 +170,7 @@ import IconDragHorizontalVariant from 'vue-material-design-icons/DragHorizontalV
import IconDotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
import IconIdentifier from 'vue-material-design-icons/Identifier.vue'
import IconOverlay from '../Icons/IconOverlay.vue'
import debounce from 'debounce'

export default {
name: 'Question',
Expand Down Expand Up @@ -241,6 +250,12 @@ export default {
},
},

data() {
return {
editor: null,
}
},

computed: {
/**
* Extend text with asterisk if question is required
Expand Down Expand Up @@ -279,10 +294,18 @@ export default {
return this.description !== ''
},
},

// Ensure description is sized correctly on initial render
mounted() {
async mounted() {
this.$nextTick(() => this.resizeDescription())

await this.setupEditor()
},

beforeDestroy() {
this.editor?.destroy()
},

methods: {
onTitleChange({ target }) {
this.$emit('update:text', target.value)
Expand Down Expand Up @@ -338,6 +361,28 @@ export default {
onClone() {
this.$emit('clone')
},

async setupEditor() {
if (!window.OCA.Text || this.readOnly) {
return
}

this.editor = await window.OCA.Text.createEditor({
el: this.$refs.editor,
content: this.description,
readOnly: false,
onUpdate: ({ markdown }) => {
this.updateEditorContent(markdown)
},
onFileInsert() {
console.log(arguments)
},
})
},

updateEditorContent: debounce(function(markdown) {
this.$emit('update:description', markdown)
}, 200, { immediate: true }),
},
}
</script>
Expand All @@ -358,6 +403,10 @@ export default {

&--editable {
padding-inline-start: 56px; // add 12px for the title input box

:deep(.ProseMirror) {
padding-bottom: 10px;
}
}

> * {
Expand Down Expand Up @@ -449,7 +498,7 @@ export default {
}

&__description {
display: flex;
//display: flex;

&__input {
margin: 0px;
Expand Down
69 changes: 54 additions & 15 deletions src/views/Create.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,27 @@
autofocus
@input="onTitleChange" />
</h2>
<label class="hidden-visually" for="form-desc">
{{ t('forms', 'Description') }}
</label>
<textarea id="form-desc"
ref="description"
class="form-desc"
rows="1"
dir="auto"
:value="form.description"
:placeholder="t('forms', 'Description (formatting using Markdown is supported)')"
:maxlength="maxStringLengths.formDescription"
@input="updateDescription" />

<div v-show="editor">
<label for="form-desc-editor">{{ t('forms', 'Description') }}</label>
<div id="form-desc-editor" ref="editor" />
</div>

<template v-if="!editor">
<label class="hidden-visually" for="form-desc">
{{ t('forms', 'Description') }}
</label>
<textarea id="form-desc"
ref="description"
class="form-desc"
rows="1"
dir="auto"
:value="form.description"
:placeholder="t('forms', 'Description (formatting using Markdown is supported)')"
:maxlength="maxStringLengths.formDescription"
@input="updateDescription" />
</template>

<!-- Show expiration message-->
<p v-if="form.expires && form.showExpiration" class="info-message">
{{ expirationMessage }}
Expand Down Expand Up @@ -177,6 +186,7 @@ window.axios = axios

export default {
name: 'Create',

components: {
Draggable,
IconLock,
Expand All @@ -193,7 +203,9 @@ export default {
TopBar,
},

mixins: [ViewsMixin],
mixins: [
ViewsMixin,
],

data() {
return {
Expand All @@ -205,6 +217,7 @@ export default {

maxStringLengths: loadState('forms', 'maxStringLengths'),
questionMenuOpened: false,
editor: null,
}
},

Expand Down Expand Up @@ -285,9 +298,15 @@ export default {
},
},

mounted() {
this.fetchFullForm(this.form.id)
async mounted() {
await this.fetchFullForm(this.form.id)
SetWindowTitle(this.formTitle)

await this.setupEditor()
},

beforeDestroy() {
this.editor?.destroy()
},

methods: {
Expand Down Expand Up @@ -465,6 +484,22 @@ export default {
this.isLoadingQuestions = false
}
},

async setupEditor() {
if (!window.OCA.Text) {
return
}

this.editor = await window.OCA.Text.createEditor({
el: this.$refs.editor,
content: this.form.description,
readOnly: false,
onUpdate: ({ markdown }) => {
this.form.description = markdown
this.saveDescription()
},
})
},
},
}
</script>
Expand Down Expand Up @@ -524,6 +559,10 @@ export default {
}
}

:deep(.ProseMirror) {
padding-bottom: 10px;
}

.form-desc,
.info-message {
font-size: 100%;
Expand Down