Merge pull request #21761 from shariquerik/separate-fetch-from-control
This commit is contained in:
commit
319da422f9
9 changed files with 111 additions and 110 deletions
|
|
@ -18,6 +18,10 @@ let docfield_df = computed(() => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (df.fieldname === "fetch_from") {
|
||||||
|
df.fieldtype = "Fetch From";
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
in_list(["fetch_from", "fetch_if_empty"], df.fieldname) &&
|
in_list(["fetch_from", "fetch_if_empty"], df.fieldname) &&
|
||||||
in_list(frappe.model.no_value_type, store.form.selected_field.fieldtype)
|
in_list(frappe.model.no_value_type, store.form.selected_field.fieldtype)
|
||||||
|
|
@ -69,6 +73,7 @@ let docfield_df = computed(() => {
|
||||||
:is="df.fieldtype.replace(' ', '') + 'Control'"
|
:is="df.fieldtype.replace(' ', '') + 'Control'"
|
||||||
:args="args"
|
:args="args"
|
||||||
:df="df"
|
:df="df"
|
||||||
|
:read_only="store.read_only"
|
||||||
:value="store.form.selected_field[df.fieldname]"
|
:value="store.form.selected_field[df.fieldname]"
|
||||||
v-model="store.form.selected_field[df.fieldname]"
|
v-model="store.form.selected_field[df.fieldname]"
|
||||||
:data-fieldname="df.fieldname"
|
:data-fieldname="df.fieldname"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStore } from "../../store";
|
|
||||||
import { useSlots } from "vue";
|
import { useSlots } from "vue";
|
||||||
|
|
||||||
let store = useStore();
|
const props = defineProps(["df", "value", "read_only"]);
|
||||||
const props = defineProps(["df", "value"]);
|
|
||||||
let slots = useSlots();
|
let slots = useSlots();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -21,7 +19,7 @@ let slots = useSlots();
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
:checked="value"
|
:checked="value"
|
||||||
:disabled="store.read_only || df.read_only"
|
:disabled="read_only"
|
||||||
@change="event => $emit('update:modelValue', event.target.checked)"
|
@change="event => $emit('update:modelValue', event.target.checked)"
|
||||||
/>
|
/>
|
||||||
<span class="label-area" :class="{ reqd: df.reqd }">{{ df.label }}</span>
|
<span class="label-area" :class="{ reqd: df.reqd }">{{ df.label }}</span>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
<!-- Used as Code, HTML Editor, Markdown Editor & JSON Control -->
|
<!-- Used as Code, HTML Editor, Markdown Editor & JSON Control -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref, useSlots, watch } from "vue";
|
import { computed, onMounted, ref, useSlots, watch } from "vue";
|
||||||
import { useStore } from "../../store";
|
|
||||||
|
|
||||||
let store = useStore();
|
const props = defineProps(["df", "read_only", "modelValue"]);
|
||||||
const props = defineProps(["df", "modelValue"]);
|
|
||||||
let emit = defineEmits(["update:modelValue"]);
|
let emit = defineEmits(["update:modelValue"]);
|
||||||
let slots = useSlots();
|
let slots = useSlots();
|
||||||
|
|
||||||
|
|
@ -25,7 +23,7 @@ onMounted(() => {
|
||||||
...props.df,
|
...props.df,
|
||||||
fieldtype: "Code",
|
fieldtype: "Code",
|
||||||
hidden: 0,
|
hidden: 0,
|
||||||
read_only: store.read_only,
|
read_only: props.read_only,
|
||||||
change: () => {
|
change: () => {
|
||||||
if (update_control.value) {
|
if (update_control.value) {
|
||||||
content.value = code_control.value.get_value();
|
content.value = code_control.value.get_value();
|
||||||
|
|
@ -34,7 +32,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
value: content.value,
|
value: content.value,
|
||||||
disabled: Boolean(slots.label) || store.read_only,
|
disabled: Boolean(slots.label) || props.read_only,
|
||||||
render_input: true,
|
render_input: true,
|
||||||
only_input: Boolean(slots.label),
|
only_input: Boolean(slots.label),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
<!-- Used as Autocomplete, Barcode, Color, Currency, Data, Date, Duration, Link, Dynamic Link, Float, Int, Password, Percent, Time, Read Only, HTML Control -->
|
<!-- Used as Autocomplete, Barcode, Color, Currency, Data, Date, Duration, Link, Dynamic Link, Float, Int, Password, Percent, Time, Read Only, HTML Control -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStore } from "../../store";
|
|
||||||
import { ref, useSlots } from "vue";
|
import { ref, useSlots } from "vue";
|
||||||
|
|
||||||
let store = useStore();
|
const props = defineProps(["df", "value", "read_only"]);
|
||||||
const props = defineProps(["df", "value"]);
|
|
||||||
let slots = useSlots();
|
let slots = useSlots();
|
||||||
let time_zone = ref("");
|
let time_zone = ref("");
|
||||||
let placeholder = ref("");
|
let placeholder = ref("");
|
||||||
|
|
@ -50,7 +48,7 @@ if (props.df.fieldtype === "Icon") {
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
:value="value"
|
:value="value"
|
||||||
:disabled="store.read_only || df.read_only"
|
:disabled="read_only"
|
||||||
@input="event => $emit('update:modelValue', event.target.value)"
|
@input="event => $emit('update:modelValue', event.target.value)"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<!-- Used as Fetch From Control -->
|
||||||
|
<script setup>
|
||||||
|
import { useStore } from "../../store";
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { computedAsync } from "@vueuse/core";
|
||||||
|
|
||||||
|
let store = useStore();
|
||||||
|
const props = defineProps(["df", "value", "read_only", "modelValue"]);
|
||||||
|
let emit = defineEmits(["update:modelValue"]);
|
||||||
|
|
||||||
|
let doctype = ref("");
|
||||||
|
let fieldname = ref("");
|
||||||
|
let doctypes = ref("");
|
||||||
|
|
||||||
|
let doctype_df = computed(() => {
|
||||||
|
doctypes.value = store
|
||||||
|
.get_updated_fields()
|
||||||
|
.filter((df) => df.fieldtype == "Link")
|
||||||
|
.filter((df) => df.options && df.fieldname != store.form.selected_field.fieldname)
|
||||||
|
.sort((a, b) => a.options.localeCompare(b.options))
|
||||||
|
.map((df) => ({
|
||||||
|
label: `${df.options} (${df.fieldname})`,
|
||||||
|
value: df.fieldname,
|
||||||
|
doctype_name: df.options,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let options = [{ label: __("Select DocType"), value: "" }, ...doctypes.value];
|
||||||
|
return { fieldtype: "Select", label: __("Fetch From"), options };
|
||||||
|
});
|
||||||
|
|
||||||
|
let field_df = computedAsync(async () => {
|
||||||
|
let options = [{ label: __("Select Field"), value: "" }];
|
||||||
|
let df = { fieldtype: "Select", label: __("Fetch From"), options };
|
||||||
|
if (!doctype.value) return df;
|
||||||
|
let doctype_name = doctypes.value?.find((df) => df.value == doctype.value).doctype_name;
|
||||||
|
if (!doctype_name) return df;
|
||||||
|
|
||||||
|
if (props.value.split(".")[0] != doctype.value) {
|
||||||
|
fieldname.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
await frappe.model.with_doctype(doctype_name);
|
||||||
|
|
||||||
|
let fields = frappe.meta
|
||||||
|
.get_docfields(doctype_name, null, {
|
||||||
|
fieldtype: ["not in", frappe.model.no_value_type],
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (a.label && b.label) {
|
||||||
|
return a.label.localeCompare(b.label);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map((df) => ({
|
||||||
|
label: `${df.label || __("No Label")} (${df.fieldtype})`,
|
||||||
|
value: df.fieldname,
|
||||||
|
}));
|
||||||
|
|
||||||
|
df.options = df.options.concat(fields);
|
||||||
|
return df;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(value) => {
|
||||||
|
[doctype.value, fieldname.value] = value?.split(".") || ["", ""];
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
watch([() => doctype.value, () => fieldname.value], ([doctype_value, fieldname_value]) => {
|
||||||
|
let [doctype_name, field_name] = props.value?.split(".") || ["", ""];
|
||||||
|
if (doctype_value != doctype_name || fieldname_value != field_name) {
|
||||||
|
emit("update:modelValue", `${doctype_value}.${fieldname_value}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<SelectControl :df="doctype_df" :value="doctype" :read_only="read_only" v-model="doctype" />
|
||||||
|
<SelectControl
|
||||||
|
v-if="doctype"
|
||||||
|
:df="field_df"
|
||||||
|
:read_only="read_only"
|
||||||
|
:value="fieldname"
|
||||||
|
v-model="fieldname"
|
||||||
|
:no_label="true"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
<!-- Used as Link Control -->
|
<!-- Used as Link Control -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, useSlots, computed, watch } from "vue";
|
import { onMounted, ref, useSlots, computed, watch } from "vue";
|
||||||
import { useStore } from "../../store";
|
|
||||||
|
|
||||||
let store = useStore();
|
const props = defineProps(["args", "df", "read_only", "modelValue"]);
|
||||||
const props = defineProps(["args", "df", "modelValue"]);
|
|
||||||
let emit = defineEmits(["update:modelValue"]);
|
let emit = defineEmits(["update:modelValue"]);
|
||||||
let slots = useSlots();
|
let slots = useSlots();
|
||||||
|
|
||||||
|
|
@ -39,7 +37,7 @@ onMounted(() => {
|
||||||
df: {
|
df: {
|
||||||
...props.df,
|
...props.df,
|
||||||
hidden: 0,
|
hidden: 0,
|
||||||
read_only: Boolean(slots.label) || store.read_only,
|
read_only: Boolean(slots.label) || props.read_only,
|
||||||
change: () => {
|
change: () => {
|
||||||
if (update_control.value) {
|
if (update_control.value) {
|
||||||
content.value = link_control.value.get_value();
|
content.value = link_control.value.get_value();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStore } from "../../store";
|
|
||||||
import { useSlots, onMounted, ref, computed, watch } from "vue";
|
import { useSlots, onMounted, ref, computed, watch } from "vue";
|
||||||
|
|
||||||
let store = useStore();
|
const props = defineProps(["df", "read_only", "modelValue", "no_label"]);
|
||||||
const props = defineProps(["df", "modelValue", "no_label"]);
|
|
||||||
let emit = defineEmits(["update:modelValue"]);
|
let emit = defineEmits(["update:modelValue"]);
|
||||||
let slots = useSlots();
|
let slots = useSlots();
|
||||||
|
|
||||||
|
|
@ -48,7 +46,7 @@ let select_control = computed(() => {
|
||||||
fieldtype: "Select",
|
fieldtype: "Select",
|
||||||
hidden: 0,
|
hidden: 0,
|
||||||
options: get_options(),
|
options: get_options(),
|
||||||
read_only: Boolean(slots.label) || store.read_only,
|
read_only: Boolean(slots.label) || props.read_only,
|
||||||
change: () => {
|
change: () => {
|
||||||
if (update_control.value) {
|
if (update_control.value) {
|
||||||
content.value = select_control.value.get_value();
|
content.value = select_control.value.get_value();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
<!-- Used as Text, Small Text & Long Text Control -->
|
<!-- Used as Text, Small Text & Long Text Control -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStore } from "../../store";
|
import { useSlots, computed } from "vue";
|
||||||
import { useSlots, ref, computed, watch } from "vue";
|
|
||||||
import { computedAsync } from "@vueuse/core";
|
|
||||||
|
|
||||||
let store = useStore();
|
const props = defineProps(["df", "value", "read_only", "modelValue"]);
|
||||||
const props = defineProps(["df", "value", "modelValue"]);
|
|
||||||
let emit = defineEmits(["update:modelValue"]);
|
let emit = defineEmits(["update:modelValue"]);
|
||||||
let slots = useSlots();
|
let slots = useSlots();
|
||||||
|
|
||||||
|
|
@ -15,91 +12,10 @@ let height = computed(() => {
|
||||||
}
|
}
|
||||||
return "300px";
|
return "300px";
|
||||||
});
|
});
|
||||||
|
|
||||||
let doctype = ref("");
|
|
||||||
let fieldname = ref("");
|
|
||||||
let doctypes = ref("");
|
|
||||||
|
|
||||||
let doctype_df = computed(() => {
|
|
||||||
doctypes.value = store
|
|
||||||
.get_updated_fields()
|
|
||||||
.filter(df => df.fieldtype == "Link")
|
|
||||||
.filter(df => df.options && df.fieldname != store.form.selected_field.fieldname)
|
|
||||||
.sort((a, b) => a.options.localeCompare(b.options))
|
|
||||||
.map(df => ({
|
|
||||||
label: `${df.options} (${df.fieldname})`,
|
|
||||||
value: df.fieldname,
|
|
||||||
doctype_name: df.options
|
|
||||||
}));
|
|
||||||
|
|
||||||
let options = [{ label: __("Select DocType"), value: "" }, ...doctypes.value];
|
|
||||||
return { fieldtype: "Select", label: __("Fetch From"), options };
|
|
||||||
});
|
|
||||||
|
|
||||||
let field_df = computedAsync(async () => {
|
|
||||||
let options = [{ label: __("Select Field"), value: "" }];
|
|
||||||
let df = { fieldtype: "Select", label: __("Fetch From"), options };
|
|
||||||
if (!doctype.value) return df;
|
|
||||||
let doctype_name = doctypes.value?.find(df => df.value == doctype.value).doctype_name;
|
|
||||||
if (!doctype_name) return df;
|
|
||||||
|
|
||||||
if (props.value.split(".")[0] != doctype.value) {
|
|
||||||
fieldname.value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
await frappe.model.with_doctype(doctype_name);
|
|
||||||
|
|
||||||
let fields = frappe.meta
|
|
||||||
.get_docfields(doctype_name, null, {
|
|
||||||
fieldtype: ["not in", frappe.model.no_value_type]
|
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (a.label && b.label) {
|
|
||||||
return a.label.localeCompare(b.label);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(df => ({
|
|
||||||
label: `${df.label || __("No Label")} (${df.fieldtype})`,
|
|
||||||
value: df.fieldname
|
|
||||||
}));
|
|
||||||
|
|
||||||
df.options = df.options.concat(fields);
|
|
||||||
return df;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.value,
|
|
||||||
value => {
|
|
||||||
if (props.df.fieldname == "fetch_from") {
|
|
||||||
[doctype.value, fieldname.value] = value?.split(".") || ["", ""];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
watch([() => doctype.value, () => fieldname.value], ([doctype_value, fieldname_value]) => {
|
|
||||||
let [doctype_name, field_name] = props.value?.split(".") || ["", ""];
|
|
||||||
if (
|
|
||||||
props.df.fieldname == "fetch_from" &&
|
|
||||||
(doctype_value != doctype_name || fieldname_value != field_name)
|
|
||||||
) {
|
|
||||||
emit("update:modelValue", `${doctype_value}.${fieldname_value}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="df.fieldname == 'fetch_from'">
|
<div class="control" :class="{ editable: slots.label }">
|
||||||
<SelectControl :df="doctype_df" :value="doctype" v-model="doctype" />
|
|
||||||
<SelectControl
|
|
||||||
v-if="doctype"
|
|
||||||
:df="field_df"
|
|
||||||
:value="fieldname"
|
|
||||||
v-model="fieldname"
|
|
||||||
:no_label="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-else class="control" :class="{ editable: slots.label }">
|
|
||||||
<!-- label -->
|
<!-- label -->
|
||||||
<div v-if="slots.label" class="field-controls">
|
<div v-if="slots.label" class="field-controls">
|
||||||
<slot name="label" />
|
<slot name="label" />
|
||||||
|
|
@ -121,7 +37,7 @@ watch([() => doctype.value, () => fieldname.value], ([doctype_value, fieldname_v
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
:value="value"
|
:value="value"
|
||||||
:disabled="store.read_only || df.read_only"
|
:disabled="read_only || df.read_only"
|
||||||
@input="event => $emit('update:modelValue', event.target.value)"
|
@input="event => $emit('update:modelValue', event.target.value)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import SignatureControl from "./components/controls/SignatureControl.vue";
|
||||||
import TableControl from "./components/controls/TableControl.vue";
|
import TableControl from "./components/controls/TableControl.vue";
|
||||||
import TextControl from "./components/controls/TextControl.vue";
|
import TextControl from "./components/controls/TextControl.vue";
|
||||||
import TextEditorControl from "./components/controls/TextEditorControl.vue";
|
import TextEditorControl from "./components/controls/TextEditorControl.vue";
|
||||||
|
import FetchFromControl from "./components/controls/FetchFromControl.vue";
|
||||||
|
|
||||||
export function registerGlobalComponents(app) {
|
export function registerGlobalComponents(app) {
|
||||||
app.component("AttachControl", AttachControl)
|
app.component("AttachControl", AttachControl)
|
||||||
|
|
@ -52,5 +53,6 @@ export function registerGlobalComponents(app) {
|
||||||
.component("TableMultiSelectControl", DataControl)
|
.component("TableMultiSelectControl", DataControl)
|
||||||
.component("TextControl", TextControl)
|
.component("TextControl", TextControl)
|
||||||
.component("TextEditorControl", TextEditorControl)
|
.component("TextEditorControl", TextEditorControl)
|
||||||
.component("TimeControl", DataControl);
|
.component("TimeControl", DataControl)
|
||||||
|
.component("FetchFromControl", FetchFromControl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue