mirror of
https://github.com/marktext/marktext.git
synced 2025-05-03 12:10:38 +08:00
Notification (#337)
* rewrite notice module * optimization: show some notification when export html or pdf * optimization: style of open project button * little bug fix * style: uniform titlebar hight to remove some style error
This commit is contained in:
parent
311d7ddf1a
commit
4be72ade97
@ -20,16 +20,23 @@ const handleResponseForExport = (e, { type, content, filename, pathname }) => {
|
|||||||
defaultPath
|
defaultPath
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// If export PDF, the content will be undefined.
|
||||||
if (!content && type === 'pdf') {
|
if (!content && type === 'pdf') {
|
||||||
win.webContents.printToPDF({ printBackground: true }, (err, data) => {
|
win.webContents.printToPDF({ printBackground: true }, (err, data) => {
|
||||||
if (err) log(err)
|
if (err) log(err)
|
||||||
else {
|
else {
|
||||||
writeFile(filePath, data, extension)
|
writeFile(filePath, data, extension)
|
||||||
|
.then(() => {
|
||||||
|
win.webContents.send('AGANI::export-success', { type, filePath })
|
||||||
|
})
|
||||||
.catch(log)
|
.catch(log)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
writeFile(filePath, content, extension)
|
writeFile(filePath, content, extension)
|
||||||
|
.then(() => {
|
||||||
|
win.webContents.send('AGANI::export-success', { type, filePath })
|
||||||
|
})
|
||||||
.catch(log)
|
.catch(log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ autoUpdater.autoDownload = false
|
|||||||
|
|
||||||
autoUpdater.on('error', error => {
|
autoUpdater.on('error', error => {
|
||||||
if (win) {
|
if (win) {
|
||||||
win.webContents.send('AGANI::UPDATE_ERROR', error === null ? 'Error: unknown' : (error.stack || error).toString())
|
win.webContents.send('AGANI::UPDATE_ERROR', error === null ? 'Error: unknown' : (error.message || error).toString())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="editor-container"
|
class="editor-container"
|
||||||
:class="[{ 'frameless': platform !== 'darwin' }]"
|
|
||||||
>
|
>
|
||||||
<title-bar
|
<title-bar
|
||||||
:pathname="pathname"
|
:pathname="pathname"
|
||||||
@ -130,6 +129,7 @@
|
|||||||
dispatch('LINTEN_FOR_SET_LINE_ENDING')
|
dispatch('LINTEN_FOR_SET_LINE_ENDING')
|
||||||
dispatch('LISTEN_FOR_NEW_TAB')
|
dispatch('LISTEN_FOR_NEW_TAB')
|
||||||
dispatch('LISTEN_FOR_CLOSE_TAB')
|
dispatch('LISTEN_FOR_CLOSE_TAB')
|
||||||
|
dispatch('LINTEN_FOR_EXPORT_SUCCESS')
|
||||||
// module: notification
|
// module: notification
|
||||||
dispatch('LISTEN_FOR_NOTIFICATION')
|
dispatch('LISTEN_FOR_NOTIFICATION')
|
||||||
}
|
}
|
||||||
@ -138,9 +138,6 @@
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.editor-container {
|
.editor-container {
|
||||||
padding-top: 22px;
|
|
||||||
}
|
|
||||||
.editor-container.frameless {
|
|
||||||
padding-top: 25px;
|
padding-top: 25px;
|
||||||
}
|
}
|
||||||
.editor-container .hide {
|
.editor-container .hide {
|
||||||
@ -151,6 +148,7 @@
|
|||||||
}
|
}
|
||||||
.editor-middle {
|
.editor-middle {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
min-height: calc(100vh - 25px);
|
||||||
& > .editor {
|
& > .editor {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -4,18 +4,15 @@
|
|||||||
v-if="!sourceCode"
|
v-if="!sourceCode"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
></search>
|
></search>
|
||||||
<status></status>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Search from './search'
|
import Search from './search'
|
||||||
import Status from './status'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Search,
|
Search
|
||||||
Status
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
sourceCode: Boolean,
|
sourceCode: Boolean,
|
||||||
|
@ -477,7 +477,7 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.ag-dialog-table {
|
.ag-dialog-table {
|
||||||
border-radius: 3px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 1px 3px rgba(230, 230, 230, .3);
|
box-shadow: 0 1px 3px rgba(230, 230, 230, .3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="editor-with-tabs"
|
class="editor-with-tabs"
|
||||||
:class="[{ 'frameless': platform !== 'darwin' }]"
|
|
||||||
>
|
>
|
||||||
<tabs v-show="showTabBar"></tabs>
|
<tabs v-show="showTabBar"></tabs>
|
||||||
<editor
|
<editor
|
||||||
@ -22,7 +21,6 @@
|
|||||||
import Tabs from './tabs.vue'
|
import Tabs from './tabs.vue'
|
||||||
import Editor from './editor.vue'
|
import Editor from './editor.vue'
|
||||||
import SourceCode from './sourceCode.vue'
|
import SourceCode from './sourceCode.vue'
|
||||||
import { mapState } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@ -49,11 +47,6 @@
|
|||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
...mapState([
|
|
||||||
'platform'
|
|
||||||
])
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
Tabs,
|
Tabs,
|
||||||
Editor,
|
Editor,
|
||||||
@ -67,10 +60,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: calc(100vh - 22px);
|
height: calc(100vh - 25px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.editor-with-tabs.frameless {
|
|
||||||
height: calc(100vh - 25px);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
<div
|
<div
|
||||||
class="source-code"
|
class="source-code"
|
||||||
ref="sourceCode"
|
ref="sourceCode"
|
||||||
:class="[theme, { 'frameless': platform !== 'darwin' }]"
|
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -12,7 +11,6 @@
|
|||||||
import { wordCount as getWordCount } from '../../../editor/utils'
|
import { wordCount as getWordCount } from '../../../editor/utils'
|
||||||
import { adjustCursor } from '../../util'
|
import { adjustCursor } from '../../util'
|
||||||
import bus from '../../bus'
|
import bus from '../../bus'
|
||||||
import { mapState } from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@ -24,12 +22,6 @@
|
|||||||
cursor: Object
|
cursor: Object
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
|
||||||
...mapState([
|
|
||||||
'platform'
|
|
||||||
])
|
|
||||||
},
|
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
contentState: null,
|
contentState: null,
|
||||||
@ -129,13 +121,10 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.source-code {
|
.source-code {
|
||||||
height: calc(100vh - 22px);
|
height: calc(100vh - 25px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.source-code.frameless {
|
|
||||||
height: calc(100vh - 25px);
|
|
||||||
}
|
|
||||||
.source-code .CodeMirror {
|
.source-code .CodeMirror {
|
||||||
margin: 50px auto;
|
margin: 50px auto;
|
||||||
max-width: 860px;
|
max-width: 860px;
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
<div
|
<div
|
||||||
class="recent-files-projects"
|
class="recent-files-projects"
|
||||||
:class="theme"
|
:class="theme"
|
||||||
|
@click="newFile"
|
||||||
>
|
>
|
||||||
<h1>Mark Text</h1>
|
|
||||||
<div>Make you fall in love with writing</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -16,6 +15,11 @@
|
|||||||
...mapState({
|
...mapState({
|
||||||
'theme': state => state.preferences.theme
|
'theme': state => state.preferences.theme
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
newFile () {
|
||||||
|
this.$store.dispatch('NEW_BLANK_FILE')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -23,29 +27,11 @@
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.recent-files-projects {
|
.recent-files-projects {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
& h1 {
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 100;
|
|
||||||
font-size: 4rem;
|
|
||||||
margin-top: 200px;
|
|
||||||
font-family: monospace;
|
|
||||||
color: var(--primaryColor);
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
& > div {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-family: cursive;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--regularColor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.dark.recent-files-projects {
|
.dark.recent-files-projects {
|
||||||
background: var(--darkBgColor);
|
background: var(--darkBgColor);
|
||||||
& > h1 {
|
|
||||||
color: var(--baseBorder);
|
|
||||||
}
|
|
||||||
& > div {
|
& > div {
|
||||||
color: var(--placeholerColor);
|
color: var(--baseBorder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div
|
<div
|
||||||
v-show="showSideBar"
|
v-show="showSideBar"
|
||||||
class="side-bar"
|
class="side-bar"
|
||||||
:class="[theme, { 'frameless': platform !== 'darwin' }]"
|
:class="[theme]"
|
||||||
ref="sideBar"
|
ref="sideBar"
|
||||||
:style="{ 'width': `${finalSideBarWidth}px` }"
|
:style="{ 'width': `${finalSideBarWidth}px` }"
|
||||||
>
|
>
|
||||||
@ -81,9 +81,6 @@
|
|||||||
'sideBarWidth': state => state.project.sideBarWidth,
|
'sideBarWidth': state => state.project.sideBarWidth,
|
||||||
'tabs': state => state.editor.tabs
|
'tabs': state => state.editor.tabs
|
||||||
}),
|
}),
|
||||||
...mapState([
|
|
||||||
'platform'
|
|
||||||
]),
|
|
||||||
...mapGetters(['fileList']),
|
...mapGetters(['fileList']),
|
||||||
finalSideBarWidth () {
|
finalSideBarWidth () {
|
||||||
const { showSideBar, rightColumn, sideBarViewWidth } = this
|
const { showSideBar, rightColumn, sideBarViewWidth } = this
|
||||||
@ -145,13 +142,10 @@
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.side-bar {
|
.side-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: calc(100vh - 22px);
|
height: calc(100vh - 25px);
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--secondaryColor);
|
color: var(--secondaryColor);
|
||||||
}
|
}
|
||||||
.side-bar.frameless {
|
|
||||||
height: calc(100vh - 25px);
|
|
||||||
}
|
|
||||||
.side-bar.dark {
|
.side-bar.dark {
|
||||||
background: var(--darkBgColor);
|
background: var(--darkBgColor);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="open-project">
|
<div v-else class="open-project">
|
||||||
<a href="javascript:;" @click="openProject">Open Project</a>
|
<a href="javascript:;" @click="openProject" title="Open Project">
|
||||||
|
<svg class="icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-create-project"></use>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -295,8 +299,23 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: -100px;
|
margin-top: -100px;
|
||||||
& > a {
|
& > a {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
border-radius: 50%;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--activeColor);
|
background: rgba(31, 116, 255, .5);
|
||||||
|
transition: all .3s ease;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
& > svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background: var(--primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.new-input {
|
.new-input {
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="bottom-status"
|
|
||||||
:class="{'error': error}"
|
|
||||||
v-show="showStatus"
|
|
||||||
>
|
|
||||||
<div class="status-wrapper">
|
|
||||||
<span class="message" :title="message">{{ message }}</span>
|
|
||||||
<span class="yes" v-show="showYes" @click="handleYesClick">[ Y ]</span>
|
|
||||||
<span class="no" @click="close(true)">[ X ]</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import bus from '../bus'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
error: false,
|
|
||||||
showStatus: false,
|
|
||||||
message: '',
|
|
||||||
showYes: false,
|
|
||||||
eventId: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
bus.$on('status-error', msg => {
|
|
||||||
this.showStatus = true
|
|
||||||
this.error = true
|
|
||||||
this.message = msg
|
|
||||||
})
|
|
||||||
bus.$on('status-message', (msg, timeout) => {
|
|
||||||
this.showStatus = true
|
|
||||||
this.error = false
|
|
||||||
this.message = msg
|
|
||||||
if (timeout) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.close(true)
|
|
||||||
}, timeout)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
bus.$on('status-promote', (msg, eventId) => {
|
|
||||||
this.showStatus = true
|
|
||||||
this.error = false
|
|
||||||
this.eventId = eventId
|
|
||||||
this.showYes = true
|
|
||||||
this.message = msg
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
close (isEmit = false) {
|
|
||||||
const { eventId } = this
|
|
||||||
this.error = false
|
|
||||||
this.showStatus = false
|
|
||||||
this.message = ''
|
|
||||||
this.showYes = false
|
|
||||||
this.eventId = ''
|
|
||||||
if (isEmit && eventId) {
|
|
||||||
bus.$emit(eventId, false)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleYesClick () {
|
|
||||||
const { eventId } = this
|
|
||||||
if (eventId) {
|
|
||||||
bus.$emit(eventId, true)
|
|
||||||
}
|
|
||||||
this.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.bottom-status {
|
|
||||||
width: 100%;
|
|
||||||
height: 25px;
|
|
||||||
background-color: #2196F3;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.bottom-status.error {
|
|
||||||
background-color: var(--dangerColor);
|
|
||||||
}
|
|
||||||
.status-wrapper {
|
|
||||||
text-align: center;
|
|
||||||
line-height: 25px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.message {
|
|
||||||
max-width: 70%;
|
|
||||||
display: inline-block;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap
|
|
||||||
}
|
|
||||||
.message, .yes {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
.yes, .no {
|
|
||||||
vertical-align: top;
|
|
||||||
color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="title-bar"
|
<div
|
||||||
|
class="title-bar"
|
||||||
:class="[{ 'active': active }, theme, { 'frameless': platform !== 'darwin' }]"
|
:class="[{ 'active': active }, theme, { 'frameless': platform !== 'darwin' }]"
|
||||||
>
|
>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
@ -166,7 +167,7 @@
|
|||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 22px;
|
height: 25px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: #F2F6FC;
|
color: #F2F6FC;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -177,9 +178,6 @@
|
|||||||
transition: color .4s ease-in-out;
|
transition: color .4s ease-in-out;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
.title-bar.frameless {
|
|
||||||
height: 25px;
|
|
||||||
}
|
|
||||||
.active {
|
.active {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
@ -191,10 +189,17 @@
|
|||||||
.title {
|
.title {
|
||||||
padding: 0 100px;
|
padding: 0 100px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 22px;
|
line-height: 25px;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: all .25s ease-in-out;
|
transition: all .25s ease-in-out;
|
||||||
|
& .filename {
|
||||||
|
transition: all .25s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar:not(.frameless) .title .filename:hover {
|
||||||
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.active .save-dot {
|
.active .save-dot {
|
||||||
@ -237,10 +242,10 @@
|
|||||||
}
|
}
|
||||||
.word-count {
|
.word-count {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
color: #F2F6FC;
|
color: #F2F6FC;
|
||||||
height: 15px;
|
height: 17px;
|
||||||
line-height: 15px;
|
line-height: 17px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
padding: 1px 5px;
|
padding: 1px 5px;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
|
@ -189,11 +189,15 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.button a.active, .button a.twitter:hover {
|
.button a.active {
|
||||||
background: var(--activeColor);
|
background: var(--primary);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
.button a.active {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
.button a.github {
|
.button a.github {
|
||||||
color: var(--secondaryColor);
|
color: var(--secondaryColor);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@ -211,4 +215,8 @@
|
|||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
color: var(--darkInputColor);
|
color: var(--darkInputColor);
|
||||||
}
|
}
|
||||||
|
.tweet-dialog.light .el-dialog__header {
|
||||||
|
background: var(--primary);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
:root {
|
:root {
|
||||||
|
--primary: #409eff;
|
||||||
|
--info: #909399;
|
||||||
|
--warning: rgb(255, 130, 0);
|
||||||
|
--error: rgb(242, 19, 93);
|
||||||
--lightBarColor: rgb(245, 245, 245);
|
--lightBarColor: rgb(245, 245, 245);
|
||||||
--lightTabColor: rgb(243, 243, 243);
|
--lightTabColor: rgb(243, 243, 243);
|
||||||
--darkBgColor: rgb(45, 45, 45);
|
--darkBgColor: rgb(45, 45, 45);
|
||||||
|
@ -8,6 +8,9 @@ import store from './store'
|
|||||||
import './assets/symbolIcon'
|
import './assets/symbolIcon'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import { Dialog, Form, FormItem, InputNumber, Button, Tooltip, Upload, Slider, ColorPicker, Col, Row } from 'element-ui'
|
import { Dialog, Form, FormItem, InputNumber, Button, Tooltip, Upload, Slider, ColorPicker, Col, Row } from 'element-ui'
|
||||||
|
import services from './services'
|
||||||
|
|
||||||
|
// import notice from './services/notification'
|
||||||
// In the renderer process:
|
// In the renderer process:
|
||||||
// var webFrame = require('electron').webFrame
|
// var webFrame = require('electron').webFrame
|
||||||
// var SpellCheckProvider = require('electron-spell-check-provider')
|
// var SpellCheckProvider = require('electron-spell-check-provider')
|
||||||
@ -55,6 +58,10 @@ if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
|||||||
Vue.http = Vue.prototype.$http = axios
|
Vue.http = Vue.prototype.$http = axios
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
services.forEach(s => {
|
||||||
|
Vue.prototype['$' + s.name] = s[s.name]
|
||||||
|
})
|
||||||
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
new Vue({
|
new Vue({
|
||||||
components: { App },
|
components: { App },
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { getFileStateFromData } from '../store/help.js'
|
import { getFileStateFromData } from '../store/help.js'
|
||||||
import { message } from '../notice'
|
|
||||||
|
|
||||||
export const tabsMixins = {
|
export const tabsMixins = {
|
||||||
methods: {
|
methods: {
|
||||||
@ -31,7 +30,13 @@ export const fileMixins = {
|
|||||||
this.$store.dispatch('UPDATE_CURRENT_FILE', fileState)
|
this.$store.dispatch('UPDATE_CURRENT_FILE', fileState)
|
||||||
|
|
||||||
if (isMixed && !isOpened) {
|
if (isMixed && !isOpened) {
|
||||||
message(`${filename} has mixed line endings which are automatically normalized to ${lineEnding.toUpperCase()}.`, 20000)
|
this.$notify({
|
||||||
|
title: 'Line Ending',
|
||||||
|
message: `${filename} has mixed line endings which are automatically normalized to ${lineEnding.toUpperCase()}.`,
|
||||||
|
type: 'primary',
|
||||||
|
time: 20000,
|
||||||
|
showConfirm: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
import bus from '../bus'
|
|
||||||
import { getUniqueId } from '../../editor/utils'
|
|
||||||
|
|
||||||
export const error = msg => {
|
|
||||||
bus.$emit('status-error', msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const message = (msg, timeout) => {
|
|
||||||
bus.$emit('status-message', msg, timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const promote = msg => {
|
|
||||||
const eventId = getUniqueId()
|
|
||||||
bus.$emit('status-promote', msg, eventId)
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
bus.$on(eventId, bool => {
|
|
||||||
bool ? resolve() : reject(bool) // reject bool just for fix the esint error: `prefer-promise-reject-errors`
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
5
src/renderer/services/index.js
Normal file
5
src/renderer/services/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import notification from './notification'
|
||||||
|
|
||||||
|
export default [
|
||||||
|
notification
|
||||||
|
]
|
116
src/renderer/services/notification/index.css
Normal file
116
src/renderer/services/notification/index.css
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
.mt-notification {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 10000;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 5px;
|
||||||
|
max-width: 350px;
|
||||||
|
min-width: 280px;
|
||||||
|
transition: all .2s ease;
|
||||||
|
box-shadow: 0px 12px 0px 0px rgba(0, 0, 0, 0.0);
|
||||||
|
backface-visibility: hidden;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
|
||||||
|
& > .notice-bg {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
position: absolute;
|
||||||
|
transition: all .8s ease,left .4s ease,top .4s ease;
|
||||||
|
border-radius: 50%;
|
||||||
|
z-index: 10;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .content {
|
||||||
|
z-index: 100;
|
||||||
|
color: #fff;
|
||||||
|
position: relative;
|
||||||
|
& .icon-wrapper {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
background: rgba(255, 255, 255, .2);
|
||||||
|
}
|
||||||
|
& .title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 5px;
|
||||||
|
& svg.icon {
|
||||||
|
width: .85em;
|
||||||
|
height: .85em;
|
||||||
|
}
|
||||||
|
& span {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
& .close {
|
||||||
|
margin-right: 10px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all .2s ease;
|
||||||
|
transform: scale(0);
|
||||||
|
cursor: pointer;
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& .body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
& .left-text {
|
||||||
|
overflow: hidden;
|
||||||
|
word-wrap: break-word;
|
||||||
|
padding: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
& .confirm {
|
||||||
|
display: none;
|
||||||
|
margin-left: 7px;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& .fluent-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 40;
|
||||||
|
display: block;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
& .fluent {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 50;
|
||||||
|
display: block;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: opacity 1s ease,width .4s ease,height .4s ease;
|
||||||
|
background: rgba(255, 255, 255, .2);
|
||||||
|
opacity: 0;
|
||||||
|
filter: blur(22px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .content .title .close {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mt-notification.mt-confirm .content .body {
|
||||||
|
& .left-text {
|
||||||
|
width: calc(100% - 45px);
|
||||||
|
}
|
||||||
|
& .confirm {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
27
src/renderer/services/notification/index.html
Normal file
27
src/renderer/services/notification/index.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<div class="mt-notification">
|
||||||
|
<div class="notice-bg"></div>
|
||||||
|
<div class="fluent-container">
|
||||||
|
<div class="fluent"></div>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">
|
||||||
|
<div class="icon-wrapper">
|
||||||
|
<svg class="icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#{{icon}}"></use>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span>{{title}}</span>
|
||||||
|
<svg class="icon close" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-close"></use>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
|
<div class="left-text">{{message}}</div>
|
||||||
|
<div class="confirm icon-wrapper">
|
||||||
|
<svg class="icon" aria-hidden="true">
|
||||||
|
<use xlink:href="#icon-confirm"></use>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
145
src/renderer/services/notification/index.js
Normal file
145
src/renderer/services/notification/index.js
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import template from './index.html'
|
||||||
|
import './index.css'
|
||||||
|
|
||||||
|
const INON_HASH = {
|
||||||
|
primary: 'icon-message',
|
||||||
|
error: 'icon-error',
|
||||||
|
warning: 'icon-warn',
|
||||||
|
info: 'icon-info'
|
||||||
|
}
|
||||||
|
|
||||||
|
const notification = {
|
||||||
|
name: 'notify',
|
||||||
|
notify ({
|
||||||
|
time = 10000,
|
||||||
|
title = '',
|
||||||
|
message = '',
|
||||||
|
type = 'primary',
|
||||||
|
showConfirm = false
|
||||||
|
}) {
|
||||||
|
let rs
|
||||||
|
let rj
|
||||||
|
let timer = null
|
||||||
|
|
||||||
|
const fragment = document.createElement('div')
|
||||||
|
fragment.innerHTML = template
|
||||||
|
.replace(/\{\{icon\}\}/, INON_HASH[type])
|
||||||
|
.replace(/\{\{title\}\}/, title)
|
||||||
|
.replace(/\{\{message\}\}/, message)
|
||||||
|
|
||||||
|
const noticeContainer = fragment.querySelector('.mt-notification')
|
||||||
|
const bgNotice = noticeContainer.querySelector('.notice-bg')
|
||||||
|
const fluent = noticeContainer.querySelector('.fluent')
|
||||||
|
const close = noticeContainer.querySelector('.close')
|
||||||
|
const { offsetHeight } = noticeContainer
|
||||||
|
let target = noticeContainer
|
||||||
|
noticeContainer.classList.add(`mt-${type}`)
|
||||||
|
|
||||||
|
if (showConfirm) {
|
||||||
|
noticeContainer.classList.add(`mt-confirm`)
|
||||||
|
target = noticeContainer.querySelector('.confirm')
|
||||||
|
}
|
||||||
|
|
||||||
|
bgNotice.style.backgroundColor = `var(--${type})`
|
||||||
|
|
||||||
|
fluent.style.height = offsetHeight * 2 + 'px'
|
||||||
|
fluent.style.width = offsetHeight * 2 + 'px'
|
||||||
|
|
||||||
|
const setCloseTimer = () => {
|
||||||
|
if (typeof time === 'number' && time > 0) {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
remove()
|
||||||
|
}, time)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mousemoveHandler = event => {
|
||||||
|
const { left, top } = noticeContainer.getBoundingClientRect()
|
||||||
|
const x = event.pageX
|
||||||
|
const y = event.pageY
|
||||||
|
fluent.style.left = x - left + 'px'
|
||||||
|
fluent.style.top = y - top + 'px'
|
||||||
|
fluent.style.opacity = '1'
|
||||||
|
fluent.style.height = noticeContainer.offsetHeight * 2 + 'px'
|
||||||
|
fluent.style.width = noticeContainer.offsetHeight * 2 + 'px'
|
||||||
|
|
||||||
|
if (timer) clearTimeout(timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mouseleaveHandler = event => {
|
||||||
|
fluent.style.opacity = '0'
|
||||||
|
fluent.style.height = noticeContainer.offsetHeight * 4 + 'px'
|
||||||
|
fluent.style.width = noticeContainer.offsetHeight * 4 + 'px'
|
||||||
|
|
||||||
|
if (timer) clearTimeout(timer)
|
||||||
|
setCloseTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickHandler = event => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
remove()
|
||||||
|
rs && rs()
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeHandler = event => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
remove()
|
||||||
|
rj && rj()
|
||||||
|
}
|
||||||
|
|
||||||
|
const rePositionNotices = () => {
|
||||||
|
const notices = document.querySelectorAll('.mt-notification')
|
||||||
|
let i
|
||||||
|
let hx = 0
|
||||||
|
let len = notices.length
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
notices[i].style.transform = `translate(0, -${hx}px)`
|
||||||
|
notices[i].style.zIndex = 10000 - i
|
||||||
|
hx += notices[i].offsetHeight + 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const remove = () => {
|
||||||
|
fluent.style.filter = 'blur(10px)'
|
||||||
|
fluent.style.opacity = '0'
|
||||||
|
fluent.style.height = noticeContainer.offsetHeight * 5 + 'px'
|
||||||
|
fluent.style.width = noticeContainer.offsetHeight * 5 + 'px'
|
||||||
|
|
||||||
|
noticeContainer.style.opacity = '0'
|
||||||
|
noticeContainer.style.right = '-400px'
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
noticeContainer.removeEventListener('mousemove', mousemoveHandler)
|
||||||
|
noticeContainer.removeEventListener('mouseleave', mouseleaveHandler)
|
||||||
|
target.removeEventListener('click', clickHandler)
|
||||||
|
close.removeEventListener('click', closeHandler)
|
||||||
|
noticeContainer.remove()
|
||||||
|
rePositionNotices()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
noticeContainer.addEventListener('mousemove', mousemoveHandler)
|
||||||
|
noticeContainer.addEventListener('mouseleave', mouseleaveHandler)
|
||||||
|
target.addEventListener('click', clickHandler)
|
||||||
|
close.addEventListener('click', closeHandler)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
bgNotice.style.width = noticeContainer.offsetWidth * 3.5 + 'px'
|
||||||
|
bgNotice.style.height = noticeContainer.offsetWidth * 3.5 + 'px'
|
||||||
|
rePositionNotices()
|
||||||
|
}, 50)
|
||||||
|
|
||||||
|
setCloseTimer()
|
||||||
|
|
||||||
|
document.body.prepend(noticeContainer, document.body.firstChild)
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
rs = resolve
|
||||||
|
rj = reject
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default notification
|
@ -1,5 +1,5 @@
|
|||||||
import { ipcRenderer } from 'electron'
|
import { ipcRenderer } from 'electron'
|
||||||
import { error, message, promote } from '../notice'
|
import notice from '../services/notification'
|
||||||
|
|
||||||
const state = {}
|
const state = {}
|
||||||
|
|
||||||
@ -10,17 +10,35 @@ const mutations = {}
|
|||||||
// AGANI::UPDATE_DOWNLOADED
|
// AGANI::UPDATE_DOWNLOADED
|
||||||
const actions = {
|
const actions = {
|
||||||
LISTEN_FOR_UPDATE ({ commit }) {
|
LISTEN_FOR_UPDATE ({ commit }) {
|
||||||
ipcRenderer.on('AGANI::UPDATE_ERROR', (e, msg) => {
|
ipcRenderer.on('AGANI::UPDATE_ERROR', (e, message) => {
|
||||||
error(msg)
|
notice.notify({
|
||||||
|
title: 'Update',
|
||||||
|
type: 'error',
|
||||||
|
time: 10000,
|
||||||
|
message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
ipcRenderer.on('AGANI::UPDATE_NOT_AVAILABLE', (e, msg) => {
|
ipcRenderer.on('AGANI::UPDATE_NOT_AVAILABLE', (e, message) => {
|
||||||
message(msg)
|
notice.notify({
|
||||||
|
title: 'Update not Available',
|
||||||
|
type: 'warning',
|
||||||
|
message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
ipcRenderer.on('AGANI::UPDATE_DOWNLOADED', (e, msg) => {
|
ipcRenderer.on('AGANI::UPDATE_DOWNLOADED', (e, message) => {
|
||||||
message(msg)
|
notice.notify({
|
||||||
|
title: 'Update Downloaded',
|
||||||
|
type: 'info',
|
||||||
|
message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
ipcRenderer.on('AGANI::UPDATE_AVAILABLE', (e, msg) => {
|
ipcRenderer.on('AGANI::UPDATE_AVAILABLE', (e, message) => {
|
||||||
promote(msg)
|
notice.notify({
|
||||||
|
title: 'Update Available',
|
||||||
|
type: 'primary',
|
||||||
|
message,
|
||||||
|
showConfirm: true
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const needUpdate = true
|
const needUpdate = true
|
||||||
ipcRenderer.send('AGANI::NEED_UPDATE', { needUpdate })
|
ipcRenderer.send('AGANI::NEED_UPDATE', { needUpdate })
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { ipcRenderer } from 'electron'
|
import { ipcRenderer, shell } from 'electron'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import bus from '../bus'
|
import bus from '../bus'
|
||||||
import { hasKeys } from '../util'
|
import { hasKeys } from '../util'
|
||||||
import { getOptionsFromState, getSingleFileState, getBlankFileState } from './help'
|
import { getOptionsFromState, getSingleFileState, getBlankFileState } from './help'
|
||||||
|
import notice from '../services/notification'
|
||||||
|
|
||||||
const toc = require('markdown-toc')
|
const toc = require('markdown-toc')
|
||||||
|
|
||||||
@ -434,6 +435,19 @@ const actions = {
|
|||||||
ipcRenderer.send('AGANI::response-export', { type, content, filename, pathname })
|
ipcRenderer.send('AGANI::response-export', { type, content, filename, pathname })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
LINTEN_FOR_EXPORT_SUCCESS ({ commit }) {
|
||||||
|
ipcRenderer.on('AGANI::export-success', (e, { type, filePath }) => {
|
||||||
|
notice.notify({
|
||||||
|
title: 'Export',
|
||||||
|
message: `Export ${path.basename(filePath)} successfully`,
|
||||||
|
showConfirm: true
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
shell.showItemInFolder(filePath)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
LISTEN_FOR_INSERT_IMAGE ({ commit, state }) {
|
LISTEN_FOR_INSERT_IMAGE ({ commit, state }) {
|
||||||
ipcRenderer.on('AGANI::INSERT_IMAGE', (e, { filename: imagePath, type }) => {
|
ipcRenderer.on('AGANI::INSERT_IMAGE', (e, { filename: imagePath, type }) => {
|
||||||
if (!hasKeys(state.currentFile)) return
|
if (!hasKeys(state.currentFile)) return
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ipcRenderer } from 'electron'
|
import { ipcRenderer } from 'electron'
|
||||||
import { error, message } from '../notice'
|
import notice from '../services/notification'
|
||||||
|
|
||||||
const state = {}
|
const state = {}
|
||||||
|
|
||||||
@ -10,11 +10,20 @@ const mutations = {
|
|||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
LISTEN_FOR_NOTIFICATION ({ commit }) {
|
LISTEN_FOR_NOTIFICATION ({ commit }) {
|
||||||
ipcRenderer.on('AGANI::show-error-notification', (e, msg) => {
|
ipcRenderer.on('AGANI::show-error-notification', (e, message) => {
|
||||||
error(msg)
|
notice.notify({
|
||||||
|
title: 'Error',
|
||||||
|
type: 'error',
|
||||||
|
message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
ipcRenderer.on('AGANI::show-info-notification', (e, { msg, timeout }) => {
|
ipcRenderer.on('AGANI::show-info-notification', (e, { message, timeout }) => {
|
||||||
message(msg, timeout)
|
notice.notify({
|
||||||
|
title: 'Infomation',
|
||||||
|
type: 'info',
|
||||||
|
time: timeout,
|
||||||
|
message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { ipcRenderer, shell } from 'electron'
|
|||||||
import { addFile, unlinkFile, changeFile, addDirectory, unlinkDirectory } from './treeCtrl'
|
import { addFile, unlinkFile, changeFile, addDirectory, unlinkDirectory } from './treeCtrl'
|
||||||
import bus from '../bus'
|
import bus from '../bus'
|
||||||
import { create, paste, rename } from '../util/fileSystem'
|
import { create, paste, rename } from '../util/fileSystem'
|
||||||
import { error } from '../notice'
|
import notice from '../services/notification'
|
||||||
|
|
||||||
const width = localStorage.getItem('side-bar-width')
|
const width = localStorage.getItem('side-bar-width')
|
||||||
const sideBarWidth = typeof +width === 'number' ? Math.max(+width, 180) : 280
|
const sideBarWidth = typeof +width === 'number' ? Math.max(+width, 180) : 280
|
||||||
@ -164,7 +164,11 @@ const actions = {
|
|||||||
commit('SET_CLIPBOARD', null)
|
commit('SET_CLIPBOARD', null)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
error(err.message)
|
notice.notify({
|
||||||
|
title: 'Paste Error',
|
||||||
|
type: 'error',
|
||||||
|
message: err.message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -182,7 +186,11 @@ const actions = {
|
|||||||
commit('CREATE_PATH', {})
|
commit('CREATE_PATH', {})
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
error(err.message)
|
notice.notify({
|
||||||
|
title: 'Error in Side Bar',
|
||||||
|
type: 'error',
|
||||||
|
message: err.message
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user