2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 19:09:01 +00:00

feat(ui/ux): add QuickView to AutoComplete

This commit is contained in:
18alantom 2023-04-18 09:31:15 +05:30
parent 32ca9e1c32
commit e05ef41cec
3 changed files with 122 additions and 10 deletions

View File

@ -41,6 +41,26 @@ export function isPesa(value: unknown): value is Money {
return value instanceof Money; return value instanceof Money;
} }
export function isFalsy(value: unknown): boolean {
if (!value) {
return true;
}
if (isPesa(value) && value.isZero()) {
return true;
}
if (Array.isArray(value) && value.length === 0) {
return true;
}
if (typeof value === 'object' && Object.keys(value).length === 0) {
return true;
}
return false;
}
export function getActions(doc: Doc): Action[] { export function getActions(doc: Doc): Action[] {
const Model = doc.fyo.models[doc.schemaName]; const Model = doc.fyo.models[doc.schemaName];
if (Model === undefined) { if (Model === undefined) {

View File

@ -54,14 +54,22 @@
stroke-linejoin="round" stroke-linejoin="round"
/> />
</svg> </svg>
<button <button
v-if="canLink" v-if="canLink"
class="p-0.5 rounded -me1 bg-transparent" class="p-0.5 rounded -me1 bg-transparent"
@mouseenter="showQuickView = true"
@mouseleave="showQuickView = false"
@click="routeToLinkedDoc" @click="routeToLinkedDoc"
> >
<FeatherIcon name="chevron-right" class="w-4 h-4 text-gray-600" /> <feather-icon name="chevron-right" class="w-4 h-4 text-gray-600" />
</button> </button>
</div> </div>
<Popover v-if="canLink" :show-popup="showQuickView" placement="bottom">
<template #content>
<QuickView :schema-name="linkSchemaName" :name="value" />
</template>
</Popover>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
@ -71,7 +79,9 @@ import { FieldTypeEnum } from 'schemas/types';
import Dropdown from 'src/components/Dropdown.vue'; import Dropdown from 'src/components/Dropdown.vue';
import { fuzzyMatch } from 'src/utils'; import { fuzzyMatch } from 'src/utils';
import { getFormRoute, routeTo } from 'src/utils/ui'; import { getFormRoute, routeTo } from 'src/utils/ui';
import Popover from '../Popover.vue';
import Base from './Base.vue'; import Base from './Base.vue';
import QuickView from '../QuickView.vue';
export default { export default {
name: 'AutoComplete', name: 'AutoComplete',
@ -79,9 +89,12 @@ export default {
extends: Base, extends: Base,
components: { components: {
Dropdown, Dropdown,
Popover,
QuickView,
}, },
data() { data() {
return { return {
showQuickView: false,
linkValue: '', linkValue: '',
isLoading: false, isLoading: false,
suggestions: [], suggestions: [],
@ -100,7 +113,23 @@ export default {
const value = this.linkValue || this.value; const value = this.linkValue || this.value;
this.setLinkValue(this.getLinkValue(value)); this.setLinkValue(this.getLinkValue(value));
}, },
unmounted() {
this.showQuickView = false;
},
deactivated() {
this.showQuickView = false;
},
computed: { computed: {
linkSchemaName() {
let schemaName = this.df?.target;
if (!schemaName) {
const references = this.df?.references ?? '';
schemaName = this.doc?.[references];
}
return schemaName;
},
options() { options() {
if (!this.df) { if (!this.df) {
return []; return [];
@ -139,19 +168,12 @@ export default {
}, },
methods: { methods: {
async routeToLinkedDoc() { async routeToLinkedDoc() {
let schemaName = this.df?.target;
const name = this.value; const name = this.value;
if (!this.linkSchemaName || !name) {
if (!schemaName) {
const references = this.df?.references ?? '';
schemaName = this.doc?.[references];
}
if (!schemaName || !name) {
return; return;
} }
const route = getFormRoute(schemaName, name); const route = getFormRoute(this.linkSchemaName, name);
await routeTo(route); await routeTo(route);
}, },
setLinkValue(value) { setLinkValue(value) {

View File

@ -0,0 +1,70 @@
<template>
<div style="min-width: 192px; max-width: 300px">
<div
class="p-2 flex justify-between"
:class="values.length ? 'border-b' : ''"
>
<p class="font-semibold text-base text-gray-900">{{ name }}</p>
<p class="font-semibold text-sm text-gray-600">
{{ schema?.label ?? '' }}
</p>
</div>
<div v-if="values.length" class="flex gap-2 p-2 flex-wrap">
<p v-for="v of values" :key="v.label" class="pill bg-gray-200">
<span class="text-gray-600">{{ v.label }}</span>
<span class="text-gray-800 ml-1.5">{{ v.value }}</span>
</p>
</div>
</div>
</template>
<script lang="ts">
import { isFalsy } from 'fyo/utils';
import { Field } from 'schemas/types';
import { defineComponent } from 'vue';
export default defineComponent({
props: {
schemaName: { type: String, required: true },
name: { type: String, required: true },
},
data() {
return { values: [] } as { values: { label: string; value: string }[] };
},
async mounted() {
const fields: Field[] = (this.schema?.fields ?? []).filter(
(f) =>
f &&
f.fieldtype !== 'Table' &&
f.fieldtype !== 'AttachImage' &&
f.fieldtype !== 'Attachment' &&
f.fieldname !== 'name' &&
!f.hidden &&
!f.meta &&
!f.abstract
);
const data = (
await this.fyo.db.getAll(this.schemaName, {
fields: fields.map((f) => f.fieldname),
filters: { name: this.name },
})
)[0];
this.values = fields
.map((f) => {
const value = data[f.fieldname];
if (isFalsy(value)) {
return { value: '', label: '' };
}
return { value: this.fyo.format(data[f.fieldname], f), label: f.label };
})
.filter((i) => !!i.value);
},
computed: {
schema() {
return this.fyo.schemaMap[this.schemaName];
},
},
});
</script>