mirror of
https://github.com/frappe/books.git
synced 2025-02-08 23:18:31 +00:00
refactor: cleanup provide-injects
- type a bunch of form element .vue files
This commit is contained in:
parent
368714a84a
commit
b618340cec
@ -68,7 +68,7 @@ export interface Action {
|
|||||||
group?: string;
|
group?: string;
|
||||||
type?: 'primary' | 'secondary';
|
type?: 'primary' | 'secondary';
|
||||||
component?: {
|
component?: {
|
||||||
template?: string;
|
template: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +96,6 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
inject: {
|
|
||||||
doc: { default: null },
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const value = this.linkValue || this.value;
|
const value = this.linkValue || this.value;
|
||||||
this.setLinkValue(this.getLinkValue(value));
|
this.setLinkValue(this.getLinkValue(value));
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
:placeholder="inputPlaceholder"
|
:placeholder="inputPlaceholder"
|
||||||
:readonly="isReadOnly"
|
:readonly="isReadOnly"
|
||||||
:step="step"
|
:step="step"
|
||||||
:max="df.maxvalue"
|
:max="isNumeric(df) ? df.maxvalue : undefined"
|
||||||
:min="df.minvalue"
|
:min="isNumeric(df) ? df.minvalue : undefined"
|
||||||
:style="containerStyles"
|
:style="containerStyles"
|
||||||
@blur="(e) => !isReadOnly && triggerChange(e.target.value)"
|
@blur="onBlur"
|
||||||
@focus="(e) => !isReadOnly && $emit('focus', e)"
|
@focus="(e) => !isReadOnly && $emit('focus', e)"
|
||||||
@input="(e) => !isReadOnly && $emit('input', e)"
|
@input="(e) => !isReadOnly && $emit('input', e)"
|
||||||
:tabindex="isReadOnly ? '-1' : '0'"
|
:tabindex="isReadOnly ? '-1' : '0'"
|
||||||
@ -25,61 +25,71 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
<script>
|
import { Doc } from 'fyo/model/doc';
|
||||||
|
import { Field } from 'schemas/types';
|
||||||
import { isNumeric } from 'src/utils';
|
import { isNumeric } from 'src/utils';
|
||||||
import { evaluateReadOnly, evaluateRequired } from 'src/utils/doc';
|
import { evaluateReadOnly, evaluateRequired } from 'src/utils/doc';
|
||||||
import { getIsNullOrUndef } from 'utils/index';
|
import { getIsNullOrUndef } from 'utils/index';
|
||||||
|
import { defineComponent, PropType } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
name: 'Base',
|
name: 'Base',
|
||||||
props: {
|
props: {
|
||||||
df: Object,
|
df: { type: Object as PropType<Field>, required: true },
|
||||||
step: { type: Number, default: 1 },
|
step: { type: Number, default: 1 },
|
||||||
value: [String, Number, Boolean, Object],
|
value: [String, Number, Boolean, Object],
|
||||||
inputClass: [Function, String, Object],
|
inputClass: [String, Array] as PropType<string | string[]>,
|
||||||
border: { type: Boolean, default: false },
|
border: { type: Boolean, default: false },
|
||||||
|
size: { type: String, default: 'large' },
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
size: String,
|
showLabel: { type: Boolean, default: false },
|
||||||
showLabel: Boolean,
|
|
||||||
autofocus: Boolean,
|
|
||||||
containerStyles: { type: Object, default: () => ({}) },
|
containerStyles: { type: Object, default: () => ({}) },
|
||||||
textRight: { type: [null, Boolean], default: null },
|
textRight: {
|
||||||
readOnly: { type: [null, Boolean], default: null },
|
type: [null, Boolean] as PropType<boolean | null>,
|
||||||
required: { type: [null, Boolean], default: null },
|
default: null,
|
||||||
|
},
|
||||||
|
readOnly: {
|
||||||
|
type: [null, Boolean] as PropType<boolean | null>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: [null, Boolean] as PropType<boolean | null>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
emits: ['focus', 'input', 'change'],
|
emits: ['focus', 'input', 'change'],
|
||||||
inject: {
|
inject: {
|
||||||
schemaName: {
|
injectedDoc: {
|
||||||
default: null,
|
from: 'doc',
|
||||||
|
default: undefined,
|
||||||
},
|
},
|
||||||
name: {
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
doc: {
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.autofocus) {
|
|
||||||
this.focus();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
inputType() {
|
doc(): Doc | undefined {
|
||||||
|
// @ts-ignore
|
||||||
|
const doc = this.injectedDoc;
|
||||||
|
|
||||||
|
if (doc instanceof Doc) {
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
inputType(): string {
|
||||||
return 'text';
|
return 'text';
|
||||||
},
|
},
|
||||||
labelClasses() {
|
labelClasses(): string {
|
||||||
return 'text-gray-600 text-sm mb-1';
|
return 'text-gray-600 text-sm mb-1';
|
||||||
},
|
},
|
||||||
inputClasses() {
|
inputClasses(): string[] {
|
||||||
/**
|
/**
|
||||||
* These classes will be used by components that extend Base
|
* These classes will be used by components that extend Base
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const classes = [];
|
const classes: string[] = [];
|
||||||
|
|
||||||
classes.push(this.baseInputClasses);
|
classes.push(...this.baseInputClasses);
|
||||||
if (this.textRight ?? isNumeric(this.df)) {
|
if (this.textRight ?? isNumeric(this.df)) {
|
||||||
classes.push('text-end');
|
classes.push('text-end');
|
||||||
}
|
}
|
||||||
@ -89,7 +99,7 @@ export default {
|
|||||||
|
|
||||||
return this.getInputClassesFromProp(classes).filter(Boolean);
|
return this.getInputClassesFromProp(classes).filter(Boolean);
|
||||||
},
|
},
|
||||||
baseInputClasses() {
|
baseInputClasses(): string[] {
|
||||||
return [
|
return [
|
||||||
'text-base',
|
'text-base',
|
||||||
'focus:outline-none',
|
'focus:outline-none',
|
||||||
@ -97,41 +107,41 @@ export default {
|
|||||||
'placeholder-gray-500',
|
'placeholder-gray-500',
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
sizeClasses() {
|
sizeClasses(): string {
|
||||||
if (this.size === 'small') {
|
if (this.size === 'small') {
|
||||||
return 'px-2 py-1';
|
return 'px-2 py-1';
|
||||||
}
|
}
|
||||||
return 'px-3 py-2';
|
return 'px-3 py-2';
|
||||||
},
|
},
|
||||||
inputReadOnlyClasses() {
|
inputReadOnlyClasses(): string {
|
||||||
if (this.isReadOnly) {
|
if (this.isReadOnly) {
|
||||||
return 'text-gray-800 cursor-default';
|
return 'text-gray-800 cursor-default';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'text-gray-900';
|
return 'text-gray-900';
|
||||||
},
|
},
|
||||||
containerClasses() {
|
containerClasses(): string[] {
|
||||||
/**
|
/**
|
||||||
* Used to accomodate extending compoents where the input is contained in
|
* Used to accomodate extending compoents where the input is contained in
|
||||||
* a div eg AutoComplete
|
* a div eg AutoComplete
|
||||||
*/
|
*/
|
||||||
const classes = [];
|
const classes: string[] = [];
|
||||||
classes.push(this.baseContainerClasses);
|
classes.push(...this.baseContainerClasses);
|
||||||
classes.push(this.containerReadOnlyClasses);
|
classes.push(this.containerReadOnlyClasses);
|
||||||
classes.push(this.borderClasses);
|
classes.push(this.borderClasses);
|
||||||
return classes.filter(Boolean);
|
return classes.filter(Boolean);
|
||||||
},
|
},
|
||||||
baseContainerClasses() {
|
baseContainerClasses(): string[] {
|
||||||
return ['rounded'];
|
return ['rounded'];
|
||||||
},
|
},
|
||||||
containerReadOnlyClasses() {
|
containerReadOnlyClasses(): string {
|
||||||
if (!this.isReadOnly) {
|
if (!this.isReadOnly) {
|
||||||
return 'focus-within:bg-gray-100';
|
return 'focus-within:bg-gray-100';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
borderClasses() {
|
borderClasses(): string {
|
||||||
if (!this.border) {
|
if (!this.border) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@ -144,13 +154,13 @@ export default {
|
|||||||
|
|
||||||
return border + ' ' + background;
|
return border + ' ' + background;
|
||||||
},
|
},
|
||||||
inputPlaceholder() {
|
inputPlaceholder(): string {
|
||||||
return this.placeholder || this.df.placeholder || this.df.label;
|
return this.placeholder || this.df.placeholder || this.df.label;
|
||||||
},
|
},
|
||||||
showMandatory() {
|
showMandatory(): boolean {
|
||||||
return this.isEmpty && this.isRequired;
|
return this.isEmpty && this.isRequired;
|
||||||
},
|
},
|
||||||
isEmpty() {
|
isEmpty(): boolean {
|
||||||
if (Array.isArray(this.value) && !this.value.length) {
|
if (Array.isArray(this.value) && !this.value.length) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -165,14 +175,14 @@ export default {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
isReadOnly() {
|
isReadOnly(): boolean {
|
||||||
if (typeof this.readOnly === 'boolean') {
|
if (typeof this.readOnly === 'boolean') {
|
||||||
return this.readOnly;
|
return this.readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
return evaluateReadOnly(this.df, this.doc);
|
return evaluateReadOnly(this.df, this.doc);
|
||||||
},
|
},
|
||||||
isRequired() {
|
isRequired(): boolean {
|
||||||
if (typeof this.required === 'boolean') {
|
if (typeof this.required === 'boolean') {
|
||||||
return this.required;
|
return this.required;
|
||||||
}
|
}
|
||||||
@ -181,25 +191,40 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getInputClassesFromProp(classes) {
|
onBlur(e: FocusEvent) {
|
||||||
|
const target = e.target;
|
||||||
|
if (!(target instanceof HTMLInputElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isReadOnly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.triggerChange(target.value);
|
||||||
|
},
|
||||||
|
getInputClassesFromProp(classes: string[]) {
|
||||||
if (!this.inputClass) {
|
if (!this.inputClass) {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.inputClass === 'function') {
|
let inputClass = this.inputClass;
|
||||||
classes = this.inputClass(classes);
|
if (typeof inputClass === 'string') {
|
||||||
} else {
|
inputClass = [inputClass];
|
||||||
classes.push(this.inputClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return classes;
|
inputClass = inputClass.filter((i) => typeof i === 'string');
|
||||||
|
|
||||||
|
return [classes, inputClass].flat();
|
||||||
},
|
},
|
||||||
focus() {
|
focus(): void {
|
||||||
if (this.$refs.input && this.$refs.input.focus) {
|
const el = this.$refs.input;
|
||||||
this.$refs.input.focus();
|
|
||||||
|
if (el instanceof HTMLInputElement) {
|
||||||
|
el.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
triggerChange(value) {
|
triggerChange(value: unknown): void {
|
||||||
value = this.parse(value);
|
value = this.parse(value);
|
||||||
|
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
@ -208,10 +233,10 @@ export default {
|
|||||||
|
|
||||||
this.$emit('change', value);
|
this.$emit('change', value);
|
||||||
},
|
},
|
||||||
parse(value) {
|
parse(value: unknown): unknown {
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
isNumeric,
|
isNumeric,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
:class="isReadOnly ? 'cursor-default' : 'cursor-pointer'"
|
:class="isReadOnly ? 'cursor-default' : 'cursor-pointer'"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
v-if="checked"
|
v-if="value"
|
||||||
width="14"
|
width="14"
|
||||||
height="14"
|
height="14"
|
||||||
viewBox="0 0 14 14"
|
viewBox="0 0 14 14"
|
||||||
@ -60,10 +60,10 @@
|
|||||||
<input
|
<input
|
||||||
ref="input"
|
ref="input"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
:checked="value"
|
:checked="getChecked(value)"
|
||||||
:readonly="isReadOnly"
|
:readonly="isReadOnly"
|
||||||
:tabindex="isReadOnly ? '-1' : '0'"
|
:tabindex="isReadOnly ? '-1' : '0'"
|
||||||
@change="(e) => !isReadOnly && triggerChange(e.target.checked)"
|
@change="onChange"
|
||||||
@focus="(e) => $emit('focus', e)"
|
@focus="(e) => $emit('focus', e)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -73,10 +73,11 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Base from './Base';
|
import { defineComponent } from 'vue';
|
||||||
|
import Base from './Base.vue';
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
name: 'Check',
|
name: 'Check',
|
||||||
extends: Base,
|
extends: Base,
|
||||||
emits: ['focus'],
|
emits: ['focus'],
|
||||||
@ -106,11 +107,25 @@ export default {
|
|||||||
|
|
||||||
return 'text-gray-600 text-base';
|
return 'text-gray-600 text-base';
|
||||||
},
|
},
|
||||||
checked() {
|
},
|
||||||
return this.value;
|
methods: {
|
||||||
|
getChecked(value: unknown) {
|
||||||
|
return Boolean(value);
|
||||||
|
},
|
||||||
|
onChange(e: Event) {
|
||||||
|
if (this.isReadOnly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = e.target;
|
||||||
|
if (!(target instanceof HTMLInputElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.triggerChange(target.checked);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -30,11 +30,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// @ts-nocheck
|
|
||||||
import { isPesa } from 'fyo/utils';
|
import { isPesa } from 'fyo/utils';
|
||||||
import { Money } from 'pesa';
|
import { Money } from 'pesa';
|
||||||
import { fyo } from 'src/initFyo';
|
import { fyo } from 'src/initFyo';
|
||||||
import { safeParseFloat } from 'utils/index';
|
import { safeParsePesa } from 'utils/index';
|
||||||
import { defineComponent, nextTick } from 'vue';
|
import { defineComponent, nextTick } from 'vue';
|
||||||
import Float from './Float.vue';
|
import Float from './Float.vue';
|
||||||
|
|
||||||
@ -49,8 +48,13 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onFocus(e) {
|
onFocus(e: FocusEvent) {
|
||||||
e.target.select();
|
const target = e.target;
|
||||||
|
if (!(target instanceof HTMLInputElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.select();
|
||||||
this.showInput = true;
|
this.showInput = true;
|
||||||
this.$emit('focus', e);
|
this.$emit('focus', e);
|
||||||
},
|
},
|
||||||
@ -66,23 +70,7 @@ export default defineComponent({
|
|||||||
return fyo.pesa(0).round();
|
return fyo.pesa(0).round();
|
||||||
},
|
},
|
||||||
parse(value: unknown): Money {
|
parse(value: unknown): Money {
|
||||||
if (isPesa(value)) {
|
return safeParsePesa(value, this.fyo);
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
value = safeParseFloat(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value === 'number') {
|
|
||||||
return fyo.pesa(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value === 'bigint') {
|
|
||||||
return fyo.pesa(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fyo.pesa(0);
|
|
||||||
},
|
},
|
||||||
onBlur(e: FocusEvent) {
|
onBlur(e: FocusEvent) {
|
||||||
const target = e.target;
|
const target = e.target;
|
||||||
@ -106,7 +94,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
formattedValue() {
|
formattedValue() {
|
||||||
return fyo.format(this.value ?? fyo.pesa(0), this.df, this.doc);
|
const value = this.parse(this.value);
|
||||||
|
return fyo.format(value, this.df, this.doc);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -4,19 +4,17 @@
|
|||||||
:value="value"
|
:value="value"
|
||||||
@change="onChange"
|
@change="onChange"
|
||||||
:border="true"
|
:border="true"
|
||||||
:input-class="'rounded py-1.5'"
|
input-class="rounded py-1.5"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { DEFAULT_LANGUAGE } from 'fyo/utils/consts';
|
import { DEFAULT_LANGUAGE } from 'fyo/utils/consts';
|
||||||
import { fyo } from 'src/initFyo';
|
import { fyo } from 'src/initFyo';
|
||||||
import { languageCodeMap, setLanguageMap } from 'src/utils/language';
|
import { languageCodeMap, setLanguageMap } from 'src/utils/language';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
import FormControl from './FormControl.vue';
|
import FormControl from './FormControl.vue';
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
methods: {
|
|
||||||
setLanguageMap,
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
dontReload: {
|
dontReload: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -25,7 +23,11 @@ export default {
|
|||||||
},
|
},
|
||||||
components: { FormControl },
|
components: { FormControl },
|
||||||
methods: {
|
methods: {
|
||||||
onChange(value) {
|
onChange(value: unknown) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (languageCodeMap[value] === undefined) {
|
if (languageCodeMap[value] === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -48,5 +50,5 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
'text-gray-500': !value,
|
'text-gray-500': !value,
|
||||||
}"
|
}"
|
||||||
:value="value"
|
:value="value"
|
||||||
@change="(e) => triggerChange(e.target.value)"
|
@change="onChange"
|
||||||
@focus="(e) => $emit('focus', e)"
|
@focus="(e) => $emit('focus', e)"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
@ -61,31 +61,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Base from './Base';
|
import Base from './Base.vue';
|
||||||
|
|
||||||
export default {
|
import { defineComponent } from 'vue';
|
||||||
|
import { SelectOption } from 'schemas/types';
|
||||||
|
export default defineComponent({
|
||||||
name: 'Select',
|
name: 'Select',
|
||||||
extends: Base,
|
extends: Base,
|
||||||
emits: ['focus'],
|
emits: ['focus'],
|
||||||
methods: {
|
methods: {
|
||||||
map(v) {
|
onChange(e: Event) {
|
||||||
if (this.df.map) {
|
const target = e.target;
|
||||||
return this.df.map[v] ?? v;
|
if (!(target instanceof HTMLInputElement)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return v;
|
|
||||||
|
this.triggerChange(target.value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
options() {
|
options(): SelectOption[] {
|
||||||
let options = this.df.options;
|
if (this.df.fieldtype !== 'Select') {
|
||||||
return options.map((o) => {
|
return [];
|
||||||
if (typeof o === 'string') {
|
|
||||||
return { label: this.map(o), value: o };
|
|
||||||
}
|
}
|
||||||
return o;
|
|
||||||
|
return this.df.options;
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -116,9 +116,6 @@ export default {
|
|||||||
Row,
|
Row,
|
||||||
TableRow,
|
TableRow,
|
||||||
},
|
},
|
||||||
inject: {
|
|
||||||
doc: { default: null },
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
value() {
|
value() {
|
||||||
this.setMaxHeight();
|
this.setMaxHeight();
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
import { Doc } from 'fyo/model/doc';
|
import { Doc } from 'fyo/model/doc';
|
||||||
import Row from 'src/components/Row.vue';
|
import Row from 'src/components/Row.vue';
|
||||||
import { getErrorMessage } from 'src/utils';
|
import { getErrorMessage } from 'src/utils';
|
||||||
import { nextTick } from 'vue';
|
import { computed, nextTick } from 'vue';
|
||||||
import Button from '../Button.vue';
|
import Button from '../Button.vue';
|
||||||
import FormControl from './FormControl.vue';
|
import FormControl from './FormControl.vue';
|
||||||
|
|
||||||
@ -90,9 +90,7 @@ export default {
|
|||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
schemaName: this.row.schemaName,
|
doc: computed(() => this.row),
|
||||||
name: this.row.name,
|
|
||||||
doc: this.row,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -77,18 +77,10 @@
|
|||||||
import { Doc } from 'fyo/model/doc';
|
import { Doc } from 'fyo/model/doc';
|
||||||
import { Field } from 'schemas/types';
|
import { Field } from 'schemas/types';
|
||||||
import { fyo } from 'src/initFyo';
|
import { fyo } from 'src/initFyo';
|
||||||
|
import { DropdownItem } from 'src/utils/types';
|
||||||
import { defineComponent, PropType } from 'vue';
|
import { defineComponent, PropType } from 'vue';
|
||||||
import Popover from './Popover.vue';
|
import Popover from './Popover.vue';
|
||||||
|
|
||||||
type DropdownItem = {
|
|
||||||
label: string;
|
|
||||||
value?: string;
|
|
||||||
action?: Function;
|
|
||||||
group?: string;
|
|
||||||
component?: { template: string };
|
|
||||||
isGroup?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Dropdown',
|
name: 'Dropdown',
|
||||||
props: {
|
props: {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Dropdown
|
<Dropdown
|
||||||
v-if="actions && actions.length"
|
v-if="actions && actions.length"
|
||||||
class="text-xs"
|
class="text-xs"
|
||||||
:items="actions"
|
:items="items"
|
||||||
:doc="doc"
|
:doc="doc"
|
||||||
right
|
right
|
||||||
>
|
>
|
||||||
@ -16,23 +16,46 @@
|
|||||||
</Dropdown>
|
</Dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Button from 'src/components/Button';
|
import { Doc } from 'fyo/model/doc';
|
||||||
import Dropdown from 'src/components/Dropdown';
|
import { Action } from 'fyo/model/types';
|
||||||
|
import Button from 'src/components/Button.vue';
|
||||||
|
import Dropdown from 'src/components/Dropdown.vue';
|
||||||
|
import { DropdownItem } from 'src/utils/types';
|
||||||
|
import { defineComponent, PropType } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
name: 'DropdownWithActions',
|
name: 'DropdownWithActions',
|
||||||
props: {
|
props: {
|
||||||
actions: { default: [] },
|
actions: { type: Array as PropType<Action[]>, default: () => [] },
|
||||||
type: { type: String, default: 'secondary' },
|
type: { type: String, default: 'secondary' },
|
||||||
icon: { type: Boolean, default: true },
|
icon: { type: Boolean, default: true },
|
||||||
},
|
},
|
||||||
inject: {
|
inject: {
|
||||||
doc: { default: null },
|
injectedDoc: { from: 'doc' },
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Button,
|
Button,
|
||||||
},
|
},
|
||||||
};
|
computed: {
|
||||||
|
doc() {
|
||||||
|
// @ts-ignore
|
||||||
|
const doc = this.injectedDoc;
|
||||||
|
if (doc instanceof Doc) {
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
items(): DropdownItem[] {
|
||||||
|
return this.actions.map(({ label, group, component, action }) => ({
|
||||||
|
label,
|
||||||
|
group,
|
||||||
|
action,
|
||||||
|
component,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -81,13 +81,6 @@ export default {
|
|||||||
errors: {},
|
errors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
provide() {
|
|
||||||
return {
|
|
||||||
schemaName: this.doc.schemaName,
|
|
||||||
name: this.doc.name,
|
|
||||||
doc: this.doc,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
FormControl,
|
FormControl,
|
||||||
Table,
|
Table,
|
||||||
|
@ -163,8 +163,6 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
schemaName: computed(() => this.docOrNull?.schemaName),
|
|
||||||
name: computed(() => this.docOrNull?.name),
|
|
||||||
doc: computed(() => this.docOrNull),
|
doc: computed(() => this.docOrNull),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -362,8 +362,6 @@ export default {
|
|||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
schemaName: this.schemaName,
|
|
||||||
name: this.name,
|
|
||||||
doc: computed(() => this.doc),
|
doc: computed(() => this.doc),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -166,8 +166,6 @@ export default {
|
|||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
schemaName: this.schemaName,
|
|
||||||
name: this.name,
|
|
||||||
doc: computed(() => this.doc),
|
doc: computed(() => this.doc),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -98,8 +98,6 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
schemaName: computed(() => this.docOrNull?.schemaName),
|
|
||||||
name: computed(() => this.docOrNull?.name),
|
|
||||||
doc: computed(() => this.docOrNull),
|
doc: computed(() => this.docOrNull),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -9,8 +9,7 @@ import {
|
|||||||
DuplicateEntryError,
|
DuplicateEntryError,
|
||||||
LinkValidationError,
|
LinkValidationError,
|
||||||
} from 'fyo/utils/errors';
|
} from 'fyo/utils/errors';
|
||||||
import { Money } from 'pesa';
|
import { Field, FieldType, FieldTypeEnum, NumberField } from 'schemas/types';
|
||||||
import { Field, FieldType, FieldTypeEnum } from 'schemas/types';
|
|
||||||
import { fyo } from 'src/initFyo';
|
import { fyo } from 'src/initFyo';
|
||||||
|
|
||||||
export function stringifyCircular(
|
export function stringifyCircular(
|
||||||
@ -112,7 +111,13 @@ export function getErrorMessage(e: Error, doc?: Doc): string {
|
|||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNumeric(fieldtype: Field | FieldType): boolean {
|
export function isNumeric(
|
||||||
|
fieldtype: FieldType
|
||||||
|
): fieldtype is NumberField['fieldtype'];
|
||||||
|
export function isNumeric(fieldtype: Field): fieldtype is NumberField;
|
||||||
|
export function isNumeric(
|
||||||
|
fieldtype: Field | FieldType
|
||||||
|
): fieldtype is NumberField | NumberField['fieldtype'] {
|
||||||
if (typeof fieldtype !== 'string') {
|
if (typeof fieldtype !== 'string') {
|
||||||
fieldtype = fieldtype?.fieldtype;
|
fieldtype = fieldtype?.fieldtype;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,15 @@ export type ActionGroup = {
|
|||||||
actions: Action[];
|
actions: Action[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DropdownItem = {
|
||||||
|
label: string;
|
||||||
|
value?: string;
|
||||||
|
action?: Function;
|
||||||
|
group?: string;
|
||||||
|
component?: { template: string };
|
||||||
|
isGroup?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type UIGroupedFields = Map<string, Map<string, Field[]>>;
|
export type UIGroupedFields = Map<string, Map<string, Field[]>>;
|
||||||
export type ExportFormat = 'csv' | 'json';
|
export type ExportFormat = 'csv' | 'json';
|
||||||
export type PeriodKey = 'This Year' | 'This Quarter' | 'This Month';
|
export type PeriodKey = 'This Year' | 'This Quarter' | 'This Month';
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import type { Fyo } from 'fyo';
|
||||||
|
import { Money } from 'pesa';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* And so should not contain and platforma specific imports.
|
* And so should not contain and platforma specific imports.
|
||||||
*/
|
*/
|
||||||
@ -187,6 +190,30 @@ export function safeParseInt(value: unknown): number {
|
|||||||
return safeParseNumber(value, (v: string) => Math.trunc(Number(v)));
|
return safeParseNumber(value, (v: string) => Math.trunc(Number(v)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function safeParsePesa(value: unknown, fyo: Fyo): Money {
|
||||||
|
if (value instanceof Money) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return fyo.pesa(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'bigint') {
|
||||||
|
return fyo.pesa(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
return fyo.pesa(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return fyo.pesa(value);
|
||||||
|
} catch {
|
||||||
|
return fyo.pesa(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function joinMapLists<A, B>(
|
export function joinMapLists<A, B>(
|
||||||
listA: A[],
|
listA: A[],
|
||||||
listB: B[],
|
listB: B[],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user