Skip to content

Commit

Permalink
Enhance template management and internationalization
Browse files Browse the repository at this point in the history
- Add custom template store with star/import/delete functionality
- Improve CreateSection template selection dialog with new UI and interactions
- Update localization files with new template-related translations
- Bump project version to 1.0.3
  • Loading branch information
yeongpin committed Feb 18, 2025
1 parent e65d608 commit d25f953
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 29 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@

## [1.0.3] - 2025-02-19
- Enhance template management and internationalization
- Add custom template store with star/import/delete functionality
- Improve CreateSection template selection dialog with new UI and interactions
- Update localization files with new template-related translations
- Bump project version to 1.0.3


## [1.0.2] - 2025-02-18

- Add logo and update app branding
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mine-knowledge-mma",
"version": "1.0.2",
"version": "1.0.3",
"description": "A Markdown knowledge base application",
"main": "src/main/index.js",
"author": "yeongpin",
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ const removeFavorite = (item) => {
// Update notes store status
notesStore.updateStarStatus(item.path, false)
$notify.info(
'取消收藏',
`已取消收藏: ${item.name}`
$t('notifications.unfavoriteSuccess'),
`${$t('notifications.unfavoriteSuccess')} ${item.name}`
)
}
Expand Down
248 changes: 230 additions & 18 deletions src/renderer/components/CreateSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,28 +41,87 @@
<!-- Template selection dialog -->
<el-dialog
v-model="dialogVisible"
:title="isTemplate ? $t('createSection.createFromTemplate') : $t('createSection.createBlankNote')"
:title="$t('createSection.selectTemplate')"
width="500px"
>
<el-form :model="form" label-width="100px">
<el-form-item :label="$t('createSection.selectFolder')">
<el-button @click="selectFolder">
{{ form.folder || $t('createSection.selectFolder') }}
</el-button>
<el-form :model="form" label-width="120px">
<el-form-item :label="$t('createSection.selectFolder')" required>
<el-input
v-model="form.folder"
:placeholder="$t('createSection.selectFolder')"
readonly
@click="selectFolder"
>
<template #append>
<el-button @click="selectFolder">
<el-icon><FolderOpened /></el-icon>
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('createSection.enterFileName')">

<el-form-item :label="$t('createSection.enterFileName')" required>
<el-input v-model="form.name" :placeholder="$t('createSection.enterFileName')" />
</el-form-item>

<el-form-item v-if="isTemplate" :label="$t('createSection.selectTemplate')">
<el-select v-model="form.template" :placeholder="$t('createSection.selectTemplate')">
<el-option-group :label="$t('createSection.builtInTemplates')">
<el-option
v-for="template in templates"
:key="template.name"
:label="template.name"
:value="template.path"
/>
</el-option-group>
<el-option-group
v-if="customTemplates.length"
:label="$t('createSection.customTemplates')"
>
<el-option
v-for="template in customTemplates"
:key="template.id"
:label="template.name"
:value="template.path"
class="custom-template-option"
>
<template #default>
<div class="template-option-content">
<span>{{ template.name }}</span>
<div class="template-actions">
<el-button
class="star-button"
:class="{ 'is-starred': isTemplateStarred(template) }"
link
size="small"
@click.stop="toggleStar(template)"
>
<el-icon>
<Star v-if="!isTemplateStarred(template)" />
<StarFilled v-else />
</el-icon>
</el-button>
<el-button
type="danger"
link
size="small"
@click.stop="confirmDeleteTemplate(template)"
>
<el-icon><Delete /></el-icon>
</el-button>
</div>
</div>
</template>
</el-option>
</el-option-group>
<el-divider />
<el-option
v-for="template in templates"
:key="template.name"
:label="template.name"
:value="template.path"
/>
:label="$t('createSection.importTemplate')"
value="import"
>
<el-icon><Upload /></el-icon>
{{ $t('createSection.importTemplate') }}
</el-option>
</el-select>
</el-form-item>
</el-form>
Expand All @@ -76,18 +135,23 @@
</template>

<script setup>
import { ref, computed, onMounted, getCurrentInstance } from 'vue'
import { ref, computed, onMounted, getCurrentInstance, watch } from 'vue'
import { useRouter } from 'vue-router'
import { Document, Plus, More } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { Document, Plus, More, FolderOpened, Upload, Delete, Star, StarFilled } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useNotesStore } from '../stores/notes'
import { useCustomTemplateStore } from '../stores/customTemplate'
import { useI18n } from 'vue-i18n'
const router = useRouter()
const notesStore = useNotesStore()
const customTemplateStore = useCustomTemplateStore()
const { t } = useI18n()
const dialogVisible = ref(false)
const isTemplate = ref(false)
const templates = ref([])
const selectedTemplate = ref(null)
const customTemplates = computed(() => customTemplateStore.customTemplates)
const { proxy: { $notify } } = getCurrentInstance()
Expand All @@ -99,7 +163,11 @@ const form = ref({
// Only display the first 2 templates
const displayTemplates = computed(() => {
return templates.value.slice(0, 2)
const baseTemplates = templates.value.slice(0, 2)
if (customTemplateStore.starredTemplate) {
return [...baseTemplates, customTemplateStore.starredTemplate]
}
return baseTemplates
})
// Whether there are more templates
Expand Down Expand Up @@ -219,6 +287,84 @@ const handleCreate = async () => {
ElMessage.error(t('notifications.createFailed'))
}
}
watch(() => form.value.template, async (newValue) => {
if (newValue === 'import') {
// Reset selection first
form.value.template = ''
try {
const files = await window.electronAPI.selectFiles({
filters: [{ name: 'Markdown', extensions: ['md', 'markdown'] }],
properties: ['openFile']
})
if (files && files.length > 0) {
const file = files[0]
customTemplateStore.addTemplate({
name: file.name,
path: file.path,
content: file.content
})
// Select the newly imported template
form.value.template = file.path
$notify.success(
t('notifications.importSuccess'),
`${t('notifications.importSuccess')} ${file.name}`
)
}
} catch (error) {
console.error('Import template failed:', error)
ElMessage.error(t('notifications.importFailed'))
}
}
})
// Add new function to confirm delete template
const confirmDeleteTemplate = async (template) => {
try {
await ElMessageBox.confirm(
t('createSection.deleteTemplateConfirm', { name: template.name }),
t('createSection.warning'),
{
confirmButtonText: t('createSection.confirm'),
cancelButtonText: t('createSection.cancel'),
type: 'warning'
}
)
customTemplateStore.removeTemplate(template.path)
ElMessage.success(t('createSection.deleteTemplateSuccess'))
} catch (error) {
if (error !== 'cancel') {
console.error('Delete template error:', error)
ElMessage.error(t('createSection.deleteTemplateFailed'))
}
}
}
// Add new function to toggle template star
const toggleStar = (template) => {
customTemplateStore.toggleStar(template)
if (isTemplateStarred(template)) {
$notify.success(
t('notifications.starSuccess'),
`${t('notifications.starSuccess')} ${template.name}`
)
} else {
$notify.success(
t('notifications.unstarSuccess'),
`${t('notifications.unstarSuccess')} ${template.name}`
)
}
}
// Add new function to check if template is starred
const isTemplateStarred = (template) => {
return customTemplateStore.starredTemplate?.path === template.path
}
</script>
<style scoped>
Expand Down Expand Up @@ -287,4 +433,70 @@ const handleCreate = async () => {
.more-card .card-icon {
color: var(--el-color-info);
}
.template-option-content {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.template-actions {
display: flex;
gap: 4px;
}
.template-actions .el-button {
visibility: hidden;
}
.star-button {
color: var(--el-text-color-secondary);
height: 24px;
width: 24px;
padding: 0;
}
.star-button.is-starred {
color: #f7ba2a;
visibility: visible !important;
}
.star-button:hover {
color: #f7ba2a;
}
.custom-template-option:hover .template-actions .el-button {
visibility: visible;
}
.template-actions .el-icon {
font-size: 16px;
}
:deep(.el-select-dropdown__item) {
padding: 0 25px;
}
:deep(.el-select-dropdown__item .template-option-content) {
height: 34px;
line-height: 34px;
}
:deep(.el-select-dropdown__item.selected) {
font-weight: bold;
color: var(--el-color-primary);
}
:deep(.el-select-dropdown__item:hover) {
background-color: var(--el-fill-color-light);
}
:deep(.el-select-group__title) {
padding-left: 12px;
}
:deep(.el-divider--horizontal) {
margin: 12px 0;
}
</style>
Loading

0 comments on commit d25f953

Please sign in to comment.