mirror of
https://github.com/frappe/books.git
synced 2024-12-22 10:58:59 +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;
|
||||
version?: string;
|
||||
info?: string;
|
||||
data?: string;
|
||||
|
||||
/*
|
||||
override get canDelete(): boolean {
|
||||
|
@ -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 = '/';
|
||||
}
|
||||
|
||||
try {
|
||||
await routeTo(route);
|
||||
} catch {
|
||||
await routeTo(fallback);
|
||||
}
|
||||
},
|
||||
async showDbSelector(): Promise<void> {
|
||||
localStorage.clear();
|
||||
|
@ -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) {
|
||||
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>
|
||||
|
@ -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: {
|
||||
|
Loading…
Reference in New Issue
Block a user