2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 02:49:03 +00:00

incr: update plugin page with delete and update

This commit is contained in:
18alantom 2023-07-25 13:40:49 +05:30
parent 31b1eed124
commit 94ee5cda35
4 changed files with 159 additions and 16 deletions

View File

@ -5,6 +5,7 @@ export class Plugin extends Doc {
name?: string;
version?: string;
info?: string;
data?: string;
/*
override get canDelete(): boolean {

View File

@ -230,12 +230,18 @@ export default defineComponent({
const { onboardingComplete } = await fyo.doc.get('GetStarted');
const { hideGetStarted } = await fyo.doc.get('SystemSettings');
let route = '/get-started';
let fallback, route;
fallback = route = '/get-started';
if (hideGetStarted || onboardingComplete) {
route = localStorage.getItem('lastRoute') || '/';
fallback = '/';
}
await routeTo(route);
try {
await routeTo(route);
} catch {
await routeTo(fallback);
}
},
async showDbSelector(): Promise<void> {
localStorage.clear();

View File

@ -1,36 +1,75 @@
<template>
<div>
<PageHeader :title="doc && doc.inserted ? doc.name : ''">
<Button @click="selectPluginFile">{{ t`Select Plugin` }}</Button>
<PageHeader :title="title">
<Button v-if="!doc?.info" @click="selectPluginFile">{{
t`Select Plugin`
}}</Button>
<Button
v-if="doc?.canSave && doc.data"
v-if="doc?.canSave && doc.data && !exists"
type="primary"
@click="doc.sync()"
@click="installPlugin()"
>
{{ t`Save` }}
{{ t`Install` }}
</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>
<div class="p-4 text-sm">
<pre>{{ JSON.stringify(JSON.parse(doc?.info || '{}'), null, 2) }}</pre>
<div v-if="info" class="p-4 text-sm">
<pre>{{ JSON.stringify(info, null, 2) }}</pre>
</div>
</div>
</template>
<script lang="ts">
import { ModelNameEnum } from 'models/types';
import PageHeader from 'src/components/PageHeader.vue';
import Button from 'src/components/Button.vue';
import { defineComponent } from 'vue';
import { Doc } from 'fyo/model/doc';
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({
components: { PageHeader, Button },
props: { name: { type: String, required: true } },
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() {
if (this.name) {
this.doc = await this.fyo.doc.get(ModelNameEnum.Plugin, this.name);
try {
this.doc = await this.fyo.doc.get(ModelNameEnum.Plugin, this.name);
} catch {
this.doc = this.fyo.doc.new(ModelNameEnum.Plugin);
}
} else {
this.doc = this.fyo.doc.new(ModelNameEnum.Plugin);
}
@ -38,8 +77,18 @@ export default defineComponent({
// @ts-ignore
window.p = this;
}
this.setInfo();
},
methods: {
setInfo(info?: string) {
info ??= this.doc?.info;
if (!info) {
return;
}
this.info = JSON.parse(info) as PluginInfo;
},
async selectPluginFile() {
const { filePath } = await ipc.selectFile({
title: this.t`Select Plugin File`,
@ -53,8 +102,95 @@ export default defineComponent({
}
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);
},
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>

View File

@ -19,7 +19,7 @@ export default () => {
}
return defineConfig({
server: { host, port, strictPort: true },
server: { host, port, strictPort: true, watch: { ignored: ['**/dbs/**'] } },
root: path.resolve(__dirname, './src'),
plugins: [vue()],
resolve: {