зеркало из https://github.com/nextcloud/notes.git
Merge pull request #1003 from JonnyTischbein/settings-dialog
This commit is contained in:
Коммит
66a5e4db9b
41
src/App.vue
41
src/App.vue
|
@ -17,18 +17,18 @@
|
|||
@category-selected="onSelectCategory"
|
||||
@note-deleted="onNoteDeleted"
|
||||
/>
|
||||
<NcAppNavigationItem
|
||||
:title="t('notes', 'Help')"
|
||||
:pinned="true"
|
||||
@click.prevent="openHelp"
|
||||
>
|
||||
<InfoIcon slot="icon" :size="20" />
|
||||
</NcAppNavigationItem>
|
||||
<AppHelp :open.sync="helpVisible" />
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<AppSettings v-if="!loading.notes && error !== true" @reload="reloadNotes" />
|
||||
<ul class="app-navigation-entry__settings">
|
||||
<NcAppNavigationItem
|
||||
:title="t('notes', 'Notes settings')"
|
||||
@click.prevent="openSettings"
|
||||
>
|
||||
<CogIcon slot="icon" :size="20" />
|
||||
</NcAppNavigationItem>
|
||||
</ul>
|
||||
<AppSettings v-if="!loading.notes && error !== true" :open.sync="settingsVisible" @reload="reloadNotes" />
|
||||
</template>
|
||||
</NcAppNavigation>
|
||||
|
||||
|
@ -57,12 +57,11 @@ import { loadState } from '@nextcloud/initial-state'
|
|||
import { showSuccess, TOAST_UNDO_TIMEOUT, TOAST_PERMANENT_TIMEOUT } from '@nextcloud/dialogs'
|
||||
import '@nextcloud/dialogs/dist/index.css'
|
||||
|
||||
import InfoIcon from 'vue-material-design-icons/Information.vue'
|
||||
import PlusIcon from 'vue-material-design-icons/Plus.vue'
|
||||
import CogIcon from 'vue-material-design-icons/Cog.vue'
|
||||
|
||||
import AppSettings from './components/AppSettings.vue'
|
||||
import NavigationList from './components/NavigationList.vue'
|
||||
import AppHelp from './components/AppHelp.vue'
|
||||
import EditorHint from './components/Modal/EditorHint.vue'
|
||||
|
||||
import { config } from './config.js'
|
||||
|
@ -73,16 +72,15 @@ export default {
|
|||
name: 'App',
|
||||
|
||||
components: {
|
||||
AppHelp,
|
||||
AppSettings,
|
||||
EditorHint,
|
||||
InfoIcon,
|
||||
NavigationList,
|
||||
NcAppContent,
|
||||
NcAppNavigation,
|
||||
NcAppNavigationNew,
|
||||
NcAppNavigationItem,
|
||||
NcContent,
|
||||
CogIcon,
|
||||
PlusIcon,
|
||||
},
|
||||
|
||||
|
@ -100,8 +98,8 @@ export default {
|
|||
undoTimer: null,
|
||||
deletedNotes: [],
|
||||
refreshTimer: null,
|
||||
helpVisible: false,
|
||||
editorHint: loadState('notes', 'editorHint', '') === 'yes' && window.OCA.Text?.createEditor,
|
||||
settingsVisible: false,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -248,8 +246,8 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
openHelp() {
|
||||
this.helpVisible = true
|
||||
openSettings() {
|
||||
this.settingsVisible = true
|
||||
},
|
||||
|
||||
onNewNote() {
|
||||
|
@ -345,3 +343,14 @@ export default {
|
|||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// Source for footer fix: https://github.com/nextcloud/server/blob/master/apps/files/src/views/Navigation.vue
|
||||
.app-navigation-entry__settings {
|
||||
height: auto !important;
|
||||
overflow: hidden !important;
|
||||
padding-top: 0 !important;
|
||||
// Prevent shrinking or growing
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<NcAppSettingsDialog
|
||||
:title="t('notes', 'Help')"
|
||||
:show-navigation="true"
|
||||
:open="helpOpen"
|
||||
@update:open="setHelpOpen($event)"
|
||||
>
|
||||
<NcAppSettingsSection id="help-basics" :title="t('notes', 'Basics')">
|
||||
<div class="feature icon-add">
|
||||
{{ t('notes', 'Start writing a note by clicking on “{newnote}” in the app navigation.', { newnote: t('notes', 'New note') }) }}
|
||||
</div>
|
||||
<div class="feature icon-fullscreen">
|
||||
{{ t('notes', 'Write down your thoughts without any distractions.') }}
|
||||
</div>
|
||||
<div class="feature icon-files-dark">
|
||||
{{ t('notes', 'Organize your notes in categories.') }}
|
||||
</div>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="help-markdown" :title="t('notes', 'Markdown')">
|
||||
<div class="feature icon-toggle-filelist">
|
||||
{{ t('notes', 'Use Markdown markups to style your text.') }}
|
||||
</div>
|
||||
<p>
|
||||
<CreateSampleButton @click="setHelpOpen(false)" />
|
||||
</p>
|
||||
<br>
|
||||
<table class="notes-help">
|
||||
<tr>
|
||||
<th>
|
||||
{{ t('notes', 'Sequence') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ t('notes', 'Result') }}
|
||||
</th>
|
||||
<th>
|
||||
{{ t('notes', 'Visualized') }}
|
||||
</th>
|
||||
</tr>
|
||||
<tr v-for="(item, index) in formatting" :key="index">
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<td v-html="item.sequence" />
|
||||
<td>
|
||||
{{ item.result }}
|
||||
</td>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<td v-html="item.visualized" />
|
||||
</tr>
|
||||
</table>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="help-shortcuts" :title="t('notes', 'Shortcuts')">
|
||||
<div class="feature icon-toggle-filelist">
|
||||
{{ t('notes', 'Use shortcuts to quickly navigate this app.') }}
|
||||
</div>
|
||||
<table class="notes-help">
|
||||
<tr>
|
||||
<th>{{ t('notes', 'Shortcut') }}</th>
|
||||
<th>{{ t('notes', 'Action') }}</th>
|
||||
</tr>
|
||||
<tr v-for="(item, index) in shortcuts" :key="index">
|
||||
<td>{{ item.shortcut }}</td>
|
||||
<td>{{ item.action }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="help-apps" :title="t('notes', 'Mobile apps')">
|
||||
<HelpMobile />
|
||||
</NcAppSettingsSection>
|
||||
</NcAppSettingsDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
NcAppSettingsDialog,
|
||||
NcAppSettingsSection,
|
||||
} from '@nextcloud/vue'
|
||||
|
||||
import CreateSampleButton from './CreateSampleButton.vue'
|
||||
import HelpMobile from './HelpMobile.vue'
|
||||
|
||||
export default {
|
||||
name: 'AppHelp',
|
||||
|
||||
components: {
|
||||
CreateSampleButton,
|
||||
HelpMobile,
|
||||
NcAppSettingsDialog,
|
||||
NcAppSettingsSection,
|
||||
},
|
||||
|
||||
props: {
|
||||
open: Boolean,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
helpOpen: this.open,
|
||||
shortcuts: [
|
||||
{ shortcut: t('notes', 'CTRL') + '+B', action: t('notes', 'Make the selection bold') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+I', action: t('notes', 'Make the selection italic') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+\'', action: t('notes', 'Wrap the selection in quotes') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'ALT') + '+C', action: t('notes', 'The selection will be turned into monospace') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+E', action: t('notes', 'Remove any styles from the selected text') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+L', action: t('notes', 'Makes the current line a list element') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'ALT') + '+L', action: t('notes', 'Makes the current line a list element with a number') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+H', action: t('notes', 'Toggle heading for current line') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'SHIFT') + '+H', action: t('notes', 'Set the current line as a big heading') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+K', action: t('notes', 'Insert link') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'ALT') + '+I', action: t('notes', 'Insert image') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+/', action: t('notes', 'Switch between editor and viewer') },
|
||||
],
|
||||
formatting: [
|
||||
{ sequence: '**' + t('notes', 'bold') + '**', result: t('notes', 'bold'), visualized: '<b>' + t('notes', 'bold') + '</b>' },
|
||||
{ sequence: '*' + t('notes', 'italic') + '*', result: t('notes', 'italic'), visualized: '<em>' + t('notes', 'italic') + '</em>' },
|
||||
{ sequence: '~~' + t('notes', 'strikethrough') + '~~', result: t('notes', 'strikethrough'), visualized: '<s>' + t('notes', 'strikethrough') + '</s>' },
|
||||
|
||||
{ sequence: '# ' + t('notes', 'Big header'), result: t('notes', 'Big header'), visualized: '<h2>' + t('notes', 'Big header') + '</h2>' },
|
||||
{ sequence: '## ' + t('notes', 'Medium header'), result: t('notes', 'Medium header'), visualized: '<b><h3>' + t('notes', 'Medium header') + '</h3></b>' },
|
||||
{ sequence: '### ' + t('notes', 'Small header'), result: t('notes', 'Small header'), visualized: '<h3>' + t('notes', 'Small header') + '</h3>' },
|
||||
{ sequence: '#### ' + t('notes', 'Tiny header'), result: t('notes', 'Tiny header'), visualized: '<h4>' + t('notes', 'Tiny header') + '</h4>' },
|
||||
|
||||
{ sequence: '* ' + t('notes', 'Generic list item'), result: t('notes', 'Generic list'), visualized: '<li>' + t('notes', 'Generic list item') + '</li>' },
|
||||
{ sequence: '- ' + t('notes', 'Generic list item'), result: t('notes', 'Generic list'), visualized: '<li>' + t('notes', 'Generic list item') + '</li>' },
|
||||
|
||||
{
|
||||
sequence: '1. William Riker<br>2. Deanna Troi<br>3. Beverly Crusher<br>',
|
||||
result: t('notes', 'Numbered list'),
|
||||
visualized: '<ol><li>William Riker</li><li>Deanna Troi</li><li>Beverly Crusher</li></ol>',
|
||||
},
|
||||
|
||||
{ sequence: '[' + t('notes', 'Link title') + '](http://www.example.com)', result: t('notes', 'link'), visualized: '<a href="http://www.example.com">' + t('notes', 'Link title') + '</a>' },
|
||||
{ sequence: '![' + t('notes', 'Image title') + '](http://www.example.com/image.jpg)', result: t('notes', 'image'), visualized: '<img src="http://www.example.com" alt="' + t('notes', 'Image title') + '" />' },
|
||||
{ sequence: '> ' + t('notes', 'This is a quote.'), result: t('notes', 'quote'), visualized: '<blockquote>' + t('notes', 'This is a quote.') + '</blockquote>' },
|
||||
|
||||
{ sequence: '`' + t('notes', 'code') + '`', result: t('notes', 'code'), visualized: '<code>' + t('notes', 'code') + '</code>' },
|
||||
{ sequence: '```<br>' + t('notes', 'Multi line block code') + '<br>```', result: t('notes', 'Multi line block code'), visualized: '<pre>' + t('notes', 'Multi line block code') + '</pre>' },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
open(newValue) {
|
||||
this.helpOpen = newValue
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
setHelpOpen(newValue) {
|
||||
this.helpOpen = newValue
|
||||
this.$emit('update:open', newValue)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
table.notes-help {
|
||||
width: 70%;
|
||||
border: 1px lightgray solid;
|
||||
border-spacing: 0;
|
||||
|
||||
border-collapse:separate;
|
||||
border-radius:6px;
|
||||
}
|
||||
|
||||
table.notes-help th {
|
||||
font-style: oblique;
|
||||
font-weight: bold;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table.notes-help th, table.notes-help td {
|
||||
padding: 5px;
|
||||
border-left: 1px lightgray solid;
|
||||
}
|
||||
|
||||
table.notes-help td:first-child, table.notes-help th:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
table.notes-help tr:nth-child(even) {
|
||||
background-color: var(--color-background-dark);
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,22 +1,37 @@
|
|||
<template>
|
||||
<NcAppNavigationSettings :title="t('notes', 'Notes settings')" :class="{ loading: saving }">
|
||||
<div class="settings-block">
|
||||
<p class="settings-hint">
|
||||
<label for="notesPath">{{ t('notes', 'Folder to store your notes') }}</label>
|
||||
<NcAppSettingsDialog
|
||||
:title="t('notes', 'Notes settings')"
|
||||
:class="{ loading: saving }"
|
||||
:show-navigation="true"
|
||||
:open="settingsOpen"
|
||||
@update:open="setSettingsOpen($event)"
|
||||
>
|
||||
<NcAppSettingsSection id="help-basics" :title="t('notes', 'Basics')">
|
||||
<div class="feature icon-add">
|
||||
{{ t('notes', 'Start writing a note by clicking on “{newnote}” in the app navigation.', { newnote: t('notes', 'New note') }) }}
|
||||
</div>
|
||||
<div class="feature icon-fullscreen">
|
||||
{{ t('notes', 'Write down your thoughts without any distractions.') }}
|
||||
</div>
|
||||
<div class="feature icon-files-dark">
|
||||
{{ t('notes', 'Organize your notes in categories.') }}
|
||||
</div>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="notes-path-section" :title="t('notes', 'Notes path')">
|
||||
<p class="app-settings-section__desc">
|
||||
{{ t('notes', 'Folder to store your notes') }}
|
||||
</p>
|
||||
<form @submit.prevent="onChangeSettingsReload">
|
||||
<input id="notesPath"
|
||||
v-model="settings.notesPath"
|
||||
type="text"
|
||||
name="notesPath"
|
||||
:placeholder="t('notes', 'Root directory')"
|
||||
@change="onChangeSettingsReload"
|
||||
><input type="submit" class="icon-confirm" value="">
|
||||
</form>
|
||||
</div>
|
||||
<div class="settings-block">
|
||||
<p class="settings-hint">
|
||||
<label for="fileSuffix">{{ t('notes', 'File extension for new notes') }}</label>
|
||||
<input id="notesPath"
|
||||
v-model="settings.notesPath"
|
||||
type="text"
|
||||
name="notesPath"
|
||||
:placeholder="t('notes', 'Root directory')"
|
||||
@click="onChangeNotePath"
|
||||
>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="file-suffix-section" :title="t('notes', 'File extension')">
|
||||
<p class="app-settings-section__desc">
|
||||
{{ t('notes', 'File extension for new notes') }}
|
||||
</p>
|
||||
<select id="fileSuffix" v-model="settings.fileSuffix" @change="onChangeSettings">
|
||||
<option v-for="extension in extensions" :key="extension.value" :value="extension.value">
|
||||
|
@ -31,33 +46,61 @@
|
|||
placeholder=".txt"
|
||||
@change="onChangeSettings"
|
||||
>
|
||||
</div>
|
||||
<div class="settings-block">
|
||||
<p class="settings-hint">
|
||||
<label for="noteMode">{{ t('notes', 'Display mode for notes') }}</label>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="note-mode-section" :title="t('notes', 'Display mode')">
|
||||
<p class="app-settings-section__desc">
|
||||
{{ t('notes', 'Display mode for notes') }}
|
||||
</p>
|
||||
<select id="noteMode" v-model="settings.noteMode" @change="onChangeSettings">
|
||||
<option v-for="mode in noteModes" :key="mode.value" :value="mode.value">
|
||||
{{ mode.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</NcAppNavigationSettings>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="help-shortcuts" :title="t('notes', 'Shortcuts')">
|
||||
<div class="feature icon-toggle-filelist">
|
||||
{{ t('notes', 'Use shortcuts to quickly navigate this app.') }}
|
||||
</div>
|
||||
<table class="notes-help">
|
||||
<tr>
|
||||
<th>{{ t('notes', 'Shortcut') }}</th>
|
||||
<th>{{ t('notes', 'Action') }}</th>
|
||||
</tr>
|
||||
<tr v-for="(item, index) in shortcuts" :key="index">
|
||||
<td>{{ item.shortcut }}</td>
|
||||
<td>{{ item.action }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</NcAppSettingsSection>
|
||||
<NcAppSettingsSection id="help-apps" :title="t('notes', 'Mobile apps')">
|
||||
<HelpMobile />
|
||||
</NcAppSettingsSection>
|
||||
</NcAppSettingsDialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
NcAppNavigationSettings,
|
||||
NcAppSettingsDialog,
|
||||
NcAppSettingsSection,
|
||||
} from '@nextcloud/vue'
|
||||
|
||||
import { FilePicker, FilePickerType } from '@nextcloud/dialogs'
|
||||
|
||||
import { setSettings } from '../NotesService.js'
|
||||
import store from '../store.js'
|
||||
import HelpMobile from './HelpMobile.vue'
|
||||
|
||||
export default {
|
||||
name: 'AppSettings',
|
||||
|
||||
components: {
|
||||
NcAppNavigationSettings,
|
||||
NcAppSettingsDialog,
|
||||
NcAppSettingsSection,
|
||||
HelpMobile,
|
||||
},
|
||||
|
||||
props: {
|
||||
open: Boolean,
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -73,6 +116,21 @@ export default {
|
|||
{ value: 'preview', label: t('notes', 'Open in preview mode') },
|
||||
],
|
||||
saving: false,
|
||||
settingsOpen: this.open,
|
||||
shortcuts: [
|
||||
{ shortcut: t('notes', 'CTRL') + '+B', action: t('notes', 'Make the selection bold') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+I', action: t('notes', 'Make the selection italic') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+\'', action: t('notes', 'Wrap the selection in quotes') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'ALT') + '+C', action: t('notes', 'The selection will be turned into monospace') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+E', action: t('notes', 'Remove any styles from the selected text') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+L', action: t('notes', 'Makes the current line a list element') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'ALT') + '+L', action: t('notes', 'Makes the current line a list element with a number') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+H', action: t('notes', 'Toggle heading for current line') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'SHIFT') + '+H', action: t('notes', 'Set the current line as a big heading') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+K', action: t('notes', 'Insert link') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+' + t('notes', 'ALT') + '+I', action: t('notes', 'Insert image') },
|
||||
{ shortcut: t('notes', 'CTRL') + '+/', action: t('notes', 'Switch between editor and viewer') },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -82,6 +140,12 @@ export default {
|
|||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
open(newValue) {
|
||||
this.settingsOpen = newValue
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
if (!window.OCA.Text?.createEditor) {
|
||||
this.noteModes.splice(0, 1)
|
||||
|
@ -89,6 +153,25 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
onChangeNotePath(event) {
|
||||
// Code Example from: https://github.com/nextcloud/text/blob/main/src/components/Menu/ActionInsertLink.vue#L130-L155
|
||||
const filePicker = new FilePicker(
|
||||
t('text', 'Select folder to link to'),
|
||||
false, // multiselect
|
||||
['text/directory'], // mime filter
|
||||
true, // modal
|
||||
FilePickerType.Choose, // type
|
||||
true, // directories
|
||||
event.target.value === '' ? '/' : event.target.value // path
|
||||
)
|
||||
filePicker.pick().then((file) => {
|
||||
const client = OC.Files.getClient()
|
||||
client.getFileInfo(file).then((_status, fileInfo) => {
|
||||
this.settings.notesPath = fileInfo.path === '/' ? `/${fileInfo.name}` : `${fileInfo.path}/${fileInfo.name}`
|
||||
this.onChangeSettingsReload()
|
||||
})
|
||||
})
|
||||
},
|
||||
onChangeSettings() {
|
||||
this.saving = true
|
||||
return setSettings(this.settings)
|
||||
|
@ -105,6 +188,11 @@ export default {
|
|||
this.$emit('reload')
|
||||
})
|
||||
},
|
||||
|
||||
setSettingsOpen(newValue) {
|
||||
this.settingsOpen = newValue
|
||||
this.$emit('update:open', newValue)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче