mirror of
https://github.com/frappe/books.git
synced 2024-12-22 19:09:01 +00:00
incr: update plugin page with delete and update
This commit is contained in:
parent
31b1eed124
commit
94ee5cda35
@ -5,6 +5,7 @@ export class Plugin extends Doc {
|
|||||||
name?: string;
|
name?: string;
|
||||||
version?: string;
|
version?: string;
|
||||||
info?: string;
|
info?: string;
|
||||||
|
data?: string;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
override get canDelete(): boolean {
|
override get canDelete(): boolean {
|
||||||
|
@ -230,12 +230,18 @@ export default defineComponent({
|
|||||||
const { onboardingComplete } = await fyo.doc.get('GetStarted');
|
const { onboardingComplete } = await fyo.doc.get('GetStarted');
|
||||||
const { hideGetStarted } = await fyo.doc.get('SystemSettings');
|
const { hideGetStarted } = await fyo.doc.get('SystemSettings');
|
||||||
|
|
||||||
let route = '/get-started';
|
let fallback, route;
|
||||||
|
fallback = route = '/get-started';
|
||||||
if (hideGetStarted || onboardingComplete) {
|
if (hideGetStarted || onboardingComplete) {
|
||||||
route = localStorage.getItem('lastRoute') || '/';
|
route = localStorage.getItem('lastRoute') || '/';
|
||||||
|
fallback = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
await routeTo(route);
|
await routeTo(route);
|
||||||
|
} catch {
|
||||||
|
await routeTo(fallback);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async showDbSelector(): Promise<void> {
|
async showDbSelector(): Promise<void> {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
@ -1,36 +1,75 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<PageHeader :title="doc && doc.inserted ? doc.name : ''">
|
<PageHeader :title="title">
|
||||||
<Button @click="selectPluginFile">{{ t`Select Plugin` }}</Button>
|
<Button v-if="!doc?.info" @click="selectPluginFile">{{
|
||||||
|
t`Select Plugin`
|
||||||
|
}}</Button>
|
||||||
<Button
|
<Button
|
||||||
v-if="doc?.canSave && doc.data"
|
v-if="doc?.canSave && doc.data && !exists"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="doc.sync()"
|
@click="installPlugin()"
|
||||||
>
|
>
|
||||||
{{ t`Save` }}
|
{{ t`Install` }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="doc?.canSave && doc.data && exists"
|
||||||
|
type="primary"
|
||||||
|
@click="updatePlugin()"
|
||||||
|
>
|
||||||
|
{{ t`Update` }}
|
||||||
|
</Button>
|
||||||
|
<Button v-if="doc?.canDelete" @click="deletePlugin()">{{
|
||||||
|
t`Delete`
|
||||||
|
}}</Button>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<div class="p-4 text-sm">
|
<div v-if="info" class="p-4 text-sm">
|
||||||
<pre>{{ JSON.stringify(JSON.parse(doc?.info || '{}'), null, 2) }}</pre>
|
<pre>{{ JSON.stringify(info, null, 2) }}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ModelNameEnum } from 'models/types';
|
import { Doc } from 'fyo/model/doc';
|
||||||
import PageHeader from 'src/components/PageHeader.vue';
|
|
||||||
import Button from 'src/components/Button.vue';
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Plugin } from 'fyo/models/Plugin';
|
import { Plugin } from 'fyo/models/Plugin';
|
||||||
|
import { ModelNameEnum } from 'models/types';
|
||||||
|
import Button from 'src/components/Button.vue';
|
||||||
|
import PageHeader from 'src/components/PageHeader.vue';
|
||||||
|
import { showDialog, showToast } from 'src/utils/interactive';
|
||||||
|
import { commonDocSync, deleteDocWithPrompt } from 'src/utils/ui';
|
||||||
|
import { PluginInfo } from 'utils/types';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO:
|
||||||
|
* - [ ] Display plugin README.md
|
||||||
|
* - [ ] Display plugin info properly
|
||||||
|
*/
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { PageHeader, Button },
|
components: { PageHeader, Button },
|
||||||
props: { name: { type: String, required: true } },
|
props: { name: { type: String, required: true } },
|
||||||
data() {
|
data() {
|
||||||
return { doc: null as null | Plugin };
|
return {
|
||||||
|
info: null as null | PluginInfo,
|
||||||
|
doc: null as null | Plugin,
|
||||||
|
exists: false as boolean,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
title(): string {
|
||||||
|
if (this.info) {
|
||||||
|
return this.info.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
if (this.name) {
|
if (this.name) {
|
||||||
|
try {
|
||||||
this.doc = await this.fyo.doc.get(ModelNameEnum.Plugin, this.name);
|
this.doc = await this.fyo.doc.get(ModelNameEnum.Plugin, this.name);
|
||||||
|
} catch {
|
||||||
|
this.doc = this.fyo.doc.new(ModelNameEnum.Plugin);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.doc = this.fyo.doc.new(ModelNameEnum.Plugin);
|
this.doc = this.fyo.doc.new(ModelNameEnum.Plugin);
|
||||||
}
|
}
|
||||||
@ -38,8 +77,18 @@ export default defineComponent({
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.p = this;
|
window.p = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setInfo();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setInfo(info?: string) {
|
||||||
|
info ??= this.doc?.info;
|
||||||
|
if (!info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.info = JSON.parse(info) as PluginInfo;
|
||||||
|
},
|
||||||
async selectPluginFile() {
|
async selectPluginFile() {
|
||||||
const { filePath } = await ipc.selectFile({
|
const { filePath } = await ipc.selectFile({
|
||||||
title: this.t`Select Plugin File`,
|
title: this.t`Select Plugin File`,
|
||||||
@ -53,8 +102,95 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await ipc.getPluginData(filePath);
|
const data = await ipc.getPluginData(filePath);
|
||||||
|
this.setInfo(data.info);
|
||||||
|
this.exists = await this.fyo.db.exists(
|
||||||
|
ModelNameEnum.Plugin,
|
||||||
|
this.info?.name ?? ''
|
||||||
|
);
|
||||||
|
|
||||||
await this.doc?.set(data);
|
await this.doc?.set(data);
|
||||||
},
|
},
|
||||||
|
async installPlugin() {
|
||||||
|
if (!this.doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = await commonDocSync(this.doc as Doc, true);
|
||||||
|
if (success) {
|
||||||
|
this.showReloadToast();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async updatePlugin() {
|
||||||
|
const { name, info, data } = this.doc ?? {};
|
||||||
|
|
||||||
|
if (!name || !info || !data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldDoc = (await this.fyo.doc.get(
|
||||||
|
ModelNameEnum.Plugin,
|
||||||
|
name
|
||||||
|
)) as Plugin;
|
||||||
|
|
||||||
|
const newInfo = JSON.parse(info) as PluginInfo;
|
||||||
|
const oldInfo = JSON.parse(oldDoc.info ?? '{}') as PluginInfo;
|
||||||
|
|
||||||
|
let message = this
|
||||||
|
.t`Plugin ${name} exists, update data with selected file?`;
|
||||||
|
|
||||||
|
if (
|
||||||
|
oldInfo.version !== newInfo.version &&
|
||||||
|
oldInfo.name === newInfo.name
|
||||||
|
) {
|
||||||
|
message = this
|
||||||
|
.t`Update plugin data from version ${oldInfo.version} to ${newInfo.version}?`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = await showDialog({
|
||||||
|
title: this.t`Update ${name}`,
|
||||||
|
message,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
label: this.t`Yes`,
|
||||||
|
async action() {
|
||||||
|
await oldDoc.set({ info, data });
|
||||||
|
await oldDoc.sync();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.t`No`,
|
||||||
|
action() {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
this.doc = oldDoc;
|
||||||
|
this.showReloadToast();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async deletePlugin() {
|
||||||
|
if (!this.doc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = await deleteDocWithPrompt(this.doc as Doc);
|
||||||
|
if (success) {
|
||||||
|
const route = `/list/Plugin/${this.t`Plugins`}`;
|
||||||
|
await this.$router.replace(route);
|
||||||
|
this.showReloadToast();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showReloadToast() {
|
||||||
|
showToast({
|
||||||
|
message: this.t`Changes will be visible on reload`,
|
||||||
|
action: () => ipc.reloadWindow(),
|
||||||
|
actionText: this.t`Reload Frappe Books?`,
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -19,7 +19,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return defineConfig({
|
return defineConfig({
|
||||||
server: { host, port, strictPort: true },
|
server: { host, port, strictPort: true, watch: { ignored: ['**/dbs/**'] } },
|
||||||
root: path.resolve(__dirname, './src'),
|
root: path.resolve(__dirname, './src'),
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
resolve: {
|
resolve: {
|
||||||
|
Loading…
Reference in New Issue
Block a user