diff --git a/src/components/TemplateSection.vue b/src/components/TemplateSection.vue
new file mode 100644
index 0000000000..fbb5e389fb
--- /dev/null
+++ b/src/components/TemplateSection.vue
@@ -0,0 +1,165 @@
+
+
+
+
+ {{ t('richdocuments', 'Create new') }}
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
diff --git a/src/views/OfficeOverview.vue b/src/views/OfficeOverview.vue
index 4b8666b040..c0c7e15515 100644
--- a/src/views/OfficeOverview.vue
+++ b/src/views/OfficeOverview.vue
@@ -8,9 +8,14 @@
+ @click="setCreator(creator)">
+
+
+
+
+
@@ -28,10 +33,14 @@
+
+
@@ -66,6 +75,27 @@
+
+
+
+
+
+ {{ t('richdocuments', 'Create') }}
+
+
+
+
@@ -75,26 +105,30 @@
import { sortNodes } from '@nextcloud/files'
import { loadState } from '@nextcloud/initial-state'
import { generateUrl } from '@nextcloud/router'
-import { NcAppContent, NcAppNavigation, NcAppNavigationItem, NcContent, NcDateTime, NcEmptyContent, NcLoadingIcon, NcTextField } from '@nextcloud/vue'
+import { NcAppContent, NcAppNavigation, NcAppNavigationItem, NcButton, NcContent, NcDateTime, NcDialog, NcEmptyContent, NcLoadingIcon, NcTextField } from '@nextcloud/vue'
import FileDocumentOutline from 'vue-material-design-icons/FileDocumentOutline.vue'
import FileCard from '../components/FileCard.vue'
-import { getAllOfficeFiles, filterByMimes } from '../services/officeFiles.js'
-import { getTemplates } from '../services/templates.js'
+import TemplateSection from '../components/TemplateSection.vue'
+import { getAllOfficeFiles, filterByMimes, invalidateOfficeFilesCache } from '../services/officeFiles.js'
+import { getTemplates, createFromTemplate } from '../services/templates.js'
export default {
name: 'OfficeOverview',
components: {
FileCard,
+ FileDocumentOutline,
NcAppContent,
NcAppNavigation,
NcAppNavigationItem,
+ NcButton,
NcContent,
NcDateTime,
+ NcDialog,
NcEmptyContent,
NcLoadingIcon,
NcTextField,
- FileDocumentOutline,
+ TemplateSection,
},
data() {
@@ -106,6 +140,12 @@ export default {
error: null,
previewEnabled: loadState('richdocuments', 'previewEnabled', false),
searchQuery: '',
+ showCreateDialog: false,
+ newFileName: '',
+ pendingCreator: null,
+ pendingTemplate: null,
+ creating: false,
+ createError: '',
}
},
@@ -137,6 +177,12 @@ export default {
},
methods: {
+ categoryName(creator) {
+ const base = creator.label.replace(/^new\s+/i, '').trim()
+ const capitalized = base.charAt(0).toUpperCase() + base.slice(1)
+ return capitalized.endsWith('s') ? capitalized : capitalized + 's'
+ },
+
setCreator(creator) {
this.activeCreator = creator
},
@@ -155,13 +201,53 @@ export default {
}
},
- async fetchAll() {
+ onTemplateSelect(creator, template) {
+ this.pendingCreator = creator
+ this.pendingTemplate = template
+ this.newFileName = creator.label.replace(/^New\s+/i, '') + creator.extension
+ this.createError = ''
+ this.showCreateDialog = true
+ this.$nextTick(() => {
+ const input = this.$refs.createInput?.$el?.querySelector('input')
+ if (input) {
+ input.focus()
+ input.setSelectionRange(0, this.newFileName.length - creator.extension.length)
+ }
+ })
+ },
+
+ async doCreateFromTemplate() {
+ if (!this.newFileName.trim() || this.creating) {
+ return
+ }
+ this.creating = true
+ this.createError = ''
+ try {
+ const filePath = '/' + this.newFileName.trim()
+ const templatePath = this.pendingTemplate?.filename ?? ''
+ const templateType = this.pendingTemplate ? 'user' : 'user_system'
+ await createFromTemplate(filePath, templatePath, templateType)
+ this.showCreateDialog = false
+ const previousCreator = this.activeCreator
+ invalidateOfficeFilesCache()
+ await this.fetchAll(previousCreator)
+ } catch (e) {
+ this.createError = t('richdocuments', 'A file with that name already exists')
+ } finally {
+ this.creating = false
+ }
+ },
+
+ async fetchAll(restoreCreator = null) {
this.loading = true
this.error = null
try {
this.creators = await getTemplates()
- this.activeCreator = this.creators[0] ?? null
+ const match = restoreCreator
+ ? this.creators.find(c => c.app === restoreCreator.app && c.extension === restoreCreator.extension)
+ : null
+ this.activeCreator = match ?? this.creators[0] ?? null
if (this.creators.length > 0) {
const allMimes = this.creators.flatMap(c => c.mimetypes)
@@ -211,4 +297,19 @@ export default {
max-width: 400px;
margin: 0 auto;
}
+
+.office-overview__create-form {
+ min-height: calc(2 * var(--default-clickable-area));
+}
+
+.office-overview__nav-icon {
+ display: flex;
+ width: 20px;
+ height: 20px;
+
+ :deep(svg) {
+ width: 100%;
+ height: 100%;
+ }
+}