Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change/streamline editor autosave #8457

Merged
Merged
Show file tree
Hide file tree
Changes from 6 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
8 changes: 8 additions & 0 deletions changelog/unreleased/change-configurable-extension-autosave
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Change: Configurable extension autosave

We have added a global setting in the configuration to enable autosave (and the corresponding timeout) for bundled and external extensions,
instead of having a per-extension configuration which was limited to external extensions.
Handling of the provided autosave needs to be taken care of by the extension itself.

https://github.com/owncloud/web/pull/8455
https://github.com/owncloud/web/pull/8457
5 changes: 5 additions & 0 deletions changelog/unreleased/enhancement-autosave-text-editor-changes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Autosave content changes in text editor

We have added the configurable functionality to autosave content changes in text editor.

https://github.com/owncloud/web/pull/8455
1 change: 0 additions & 1 deletion dev/docker/ocis.web.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"path": "web-app-draw-io",
"config": {
"url": "https://embed.diagrams.net",
"autosave": false,
"theme": "minimal"
}
}
Expand Down
2 changes: 2 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ hovers the row with his mouse. Defaults to `false`.
- `option.routing` This accepts an object with the following fields to customize the routing behaviour:
- `options.routing.idBased` Enable or disable fileIds being added to the URL. Defaults to `true` because otherwise e.g. spaces with name clashes can't be resolved correctly. Only disable this if you can guarantee server side that spaces of the same namespace can't have name clashes.
- `options.upload.xhr.timeout` Specifies the timeout for XHR uploads in milliseconds.
- `options.editor.autosaveEnabled` Specifies if the autosave for the editor apps is enabled.
- `options.editor.autosaveInterval` Specifies the time interval for the autosave of editor apps in milliseconds.

### Sentry

Expand Down
32 changes: 17 additions & 15 deletions packages/web-app-draw-io/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,25 @@
</main>
</template>
<script lang="ts">
import { mapActions } from 'vuex'
import qs from 'qs'
import { DateTime } from 'luxon'
import { DavPermission, DavProperty } from 'web-client/src/webdav/constants'
import { useAppDefaults } from 'web-pkg/src/composables'
import { defineComponent } from 'vue'
import { basename } from 'path'
import qs from 'qs'
import { defineComponent } from 'vue'
import { mapActions } from 'vuex'
import { DavPermission, DavProperty } from 'web-client/src/webdav/constants'
import { useAppDefaults, useStore } from 'web-pkg/src/composables'

export default defineComponent({
name: 'DrawIoEditor',
setup() {
const store = useStore()
const isAutoSaveEnabled = store.getters.configuration.options.editor.autosaveEnabled

return {
...useAppDefaults({
applicationId: 'draw-io'
})
}),
isAutoSaveEnabled
}
},
data: () => ({
Expand All @@ -40,12 +44,8 @@ export default defineComponent({
}),
computed: {
config() {
const {
url = 'https://embed.diagrams.net',
theme = 'minimal',
autosave = false
} = this.applicationConfig
return { url, theme, autosave: autosave ? 1 : 0 }
const { url = 'https://embed.diagrams.net', theme = 'minimal' } = this.applicationConfig
return { url, theme }
},
urlHost() {
const url = new URL(this.config.url)
Expand Down Expand Up @@ -88,7 +88,9 @@ export default defineComponent({
this.fileExtension === 'vsdx' ? this.importVisio() : this.load()
break
case 'autosave':
this.save(payload, true)
if (this.isAutoSaveEnabled) {
this.save(payload, true)
}
break
case 'save':
this.save(payload)
Expand Down Expand Up @@ -148,7 +150,7 @@ export default defineComponent({
JSON.stringify({
action: 'load',
xml: response.body,
autosave: this.config.autosave
autosave: this.isAutoSaveEnabled
}),
this.urlHost
)
Expand Down Expand Up @@ -189,7 +191,7 @@ export default defineComponent({
JSON.stringify({
action: 'load',
xml: reader.result,
autosave: this.config.autosave
autosave: this.isAutoSaveEnabled
}),
this.urlHost
)
Expand Down
19 changes: 18 additions & 1 deletion packages/web-app-text-editor/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export default defineComponent({
const resource: Ref<Resource> = ref()
const store = useStore()
const { $gettext, interpolate: $gettextInterpolate } = useGettext()
let autosaveIntervalId = null

const errorPopup = (error) => {
store.dispatch('showMessage', {
Expand All @@ -111,6 +112,12 @@ export default defineComponent({
})
}

const autosavePopup = () => {
store.dispatch('showMessage', {
title: $gettext('File autosaved')
})
}

const loadFileTask = useTask(function* () {
resource.value = yield getFileInfo(currentFileContext, {
davProperties: [DavProperty.FileId, DavProperty.Permissions, DavProperty.Name]
Expand Down Expand Up @@ -194,7 +201,7 @@ export default defineComponent({
})

const isLoading = computed(() => {
return loadFileTask.isRunning || saveFileTask.isRunning
return loadFileTask.isRunning
})

const showPreview = computed(() => {
Expand All @@ -215,11 +222,21 @@ export default defineComponent({
document.addEventListener('keydown', handleSKey, false)
// Ensure reload is not possible if there are changes
window.addEventListener('beforeunload', handleUnload)

const editorOptions = store.getters.configuration.options.editor
if (editorOptions.autosaveEnabled) {
autosaveIntervalId = setInterval(() => {
if (isDirty.value) {
save().then((r) => autosavePopup())
}
}, editorOptions.autosaveInterval)
}
})

onBeforeUnmount(() => {
window.removeEventListener('beforeunload', handleUnload)
document.removeEventListener('keydown', handleSKey, false)
clearInterval(autosaveIntervalId)
})

const save = async function () {
Expand Down
8 changes: 4 additions & 4 deletions packages/web-app-text-editor/tests/unit/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import App from '../../src/App.vue'
import { useAppDefaultsMock } from 'web-test-helpers/src/mocks/useAppDefaultsMock'
import { FileContext, useAppDefaults } from 'web-pkg/src/composables/appDefaults'
import { mock } from 'jest-mock-extended'
import { ref } from 'vue'
import { Resource } from 'web-client'
import { FileContext, useAppDefaults } from 'web-pkg/src/composables/appDefaults'
import {
createStore,
defaultPlugins,
Expand All @@ -11,7 +10,8 @@ import {
defaultComponentMocks,
defaultStubs
} from 'web-test-helpers'
import { Resource } from 'web-client'
import { useAppDefaultsMock } from 'web-test-helpers/src/mocks/useAppDefaultsMock'
import App from '../../src/App.vue'

jest.mock('web-pkg/src/composables/appDefaults')

Expand Down
1 change: 0 additions & 1 deletion packages/web-pkg/src/composables/appDefaults/useAppMeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ interface AppMetaOptions {

export interface AppMetaObject {
config: AppConfigObject
autosave: boolean
theme: string
url: string
icon: string
Expand Down
4 changes: 4 additions & 0 deletions packages/web-runtime/src/store/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const state = {
options: {
contextHelpers: true,
defaultExtension: 'files',
editor: {
autosaveEnabled: false,
autosaveInterval: 120000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I said earlier in a zoom call, I'm not a fan of configuring this in ms. I know that it was consistency vs practicality. Giving the admin the chance to let an editor autosave a file every 100 milliseconds doesn't sound like a good idea to me. But I get the consistency argument... no veto, but wanted to express my meh.

},
// ugly hack to still have notifications but don't have
// them blocking UI elements in acceptance/E2E tests
topCenterNotifications: false,
Expand Down
1 change: 0 additions & 1 deletion packages/web-runtime/tests/unit/helpers/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ const validConfig = `{
"path": "web-app-draw-io",
"config": {
"url": "https://embed.diagrams.net",
"autosave": false,
"theme": "minimal"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ export const defaultStoreMockOptions = {
quota: jest.fn(() => ({})),
capabilities: jest.fn().mockImplementation(() => ({})),
user: jest.fn().mockImplementation(() => ({})),
configuration: jest
.fn()
.mockImplementation(() => ({ currentTheme: { general: { slogan: '' } } }))
configuration: jest.fn().mockImplementation(() => ({
currentTheme: { general: { slogan: '' } },
options: {
editor: {
autosaveEnabled: false,
autosaveInterval: 120000
}
}
}))
},
modules: {
...filesModuleMockOptions,
Expand Down