mirror of
https://github.com/frappe/books.git
synced 2024-12-23 03:19:01 +00:00
commit
9592ec4bc7
@ -1,15 +1,11 @@
|
||||
<template>
|
||||
<div
|
||||
class="
|
||||
relative
|
||||
bg-white
|
||||
border
|
||||
rounded-full
|
||||
flex-center
|
||||
overflow-hidden
|
||||
cursor-pointer
|
||||
"
|
||||
:class="{ 'w-20 h-20': size !== 'small', 'w-12 h-12': size === 'small' }"
|
||||
class="relative bg-white border rounded-full flex-center overflow-hidden"
|
||||
:class="{
|
||||
'w-20 h-20': size !== 'small',
|
||||
'w-12 h-12': size === 'small',
|
||||
'cursor-pointer': !isReadOnly,
|
||||
}"
|
||||
@mouseover="showEdit = true"
|
||||
@mouseleave="showEdit = false"
|
||||
@click="openFileSelector"
|
||||
@ -48,9 +44,16 @@
|
||||
</div>
|
||||
<div
|
||||
v-show="showEdit"
|
||||
class="absolute bottom-0 text-gray-500 text-center text-xs pt-3 pb-1"
|
||||
class="
|
||||
absolute
|
||||
bottom-0
|
||||
text-gray-500 text-center text-xs
|
||||
pt-3
|
||||
pb-1
|
||||
select-none
|
||||
"
|
||||
>
|
||||
{{ t`Edit` }}
|
||||
{{ !isReadOnly ? t`Edit` : '' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -72,6 +75,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async openFileSelector() {
|
||||
if (this.isReadOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options = {
|
||||
title: fyo.t`Select Image`,
|
||||
properties: ['openFile'],
|
||||
|
@ -8,17 +8,18 @@
|
||||
selectHighlightedItem,
|
||||
}"
|
||||
>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-between pr-2 rounded"
|
||||
:class="isReadOnly ? '' : 'focus-within:bg-gray-200'"
|
||||
:class="containerClasses"
|
||||
>
|
||||
<input
|
||||
ref="input"
|
||||
spellcheck="false"
|
||||
:class="inputClasses"
|
||||
class="bg-transparent"
|
||||
type="text"
|
||||
:value="linkValue"
|
||||
:placeholder="inputPlaceholder"
|
||||
@ -38,10 +39,12 @@
|
||||
style="background: inherit; margin-right: -3px"
|
||||
viewBox="0 0 5 10"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@click="(e) => !isReadOnly && onFocus(e, toggleDropdown)"
|
||||
>
|
||||
<path
|
||||
d="M1 2.636L2.636 1l1.637 1.636M1 7.364L2.636 9l1.637-1.636"
|
||||
stroke="#404040"
|
||||
class="stroke-current"
|
||||
:class="showMandatory ? 'text-red-500' : 'text-gray-500'"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="round"
|
||||
|
@ -1,27 +1,32 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<input
|
||||
spellcheck="false"
|
||||
ref="input"
|
||||
:class="inputClasses"
|
||||
:type="inputType"
|
||||
:value="value"
|
||||
:placeholder="inputPlaceholder"
|
||||
:readonly="isReadOnly"
|
||||
:max="df.maxvalue"
|
||||
:min="df.minvalue"
|
||||
@blur="(e) => !isReadOnly && triggerChange(e.target.value)"
|
||||
@focus="(e) => !isReadOnly && $emit('focus', e)"
|
||||
@input="(e) => !isReadOnly && $emit('input', e)"
|
||||
/>
|
||||
<div :class="showMandatory ? 'show-mandatory' : ''">
|
||||
<input
|
||||
spellcheck="false"
|
||||
ref="input"
|
||||
class="bg-transparent"
|
||||
:class="[inputClasses, containerClasses]"
|
||||
:type="inputType"
|
||||
:value="value"
|
||||
:placeholder="inputPlaceholder"
|
||||
:readonly="isReadOnly"
|
||||
:max="df.maxvalue"
|
||||
:min="df.minvalue"
|
||||
@blur="(e) => !isReadOnly && triggerChange(e.target.value)"
|
||||
@focus="(e) => !isReadOnly && $emit('focus', e)"
|
||||
@input="(e) => !isReadOnly && $emit('input', e)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isNumeric } from 'src/utils';
|
||||
import { evaluateReadOnly, evaluateRequired } from 'src/utils/doc';
|
||||
import { getIsNullOrUndef } from 'utils/index';
|
||||
|
||||
export default {
|
||||
name: 'Base',
|
||||
@ -29,11 +34,13 @@ export default {
|
||||
df: Object,
|
||||
value: [String, Number, Boolean, Object],
|
||||
inputClass: [Function, String, Object],
|
||||
border: { type: Boolean, default: false },
|
||||
placeholder: String,
|
||||
size: String,
|
||||
showLabel: Boolean,
|
||||
readOnly: Boolean,
|
||||
autofocus: Boolean,
|
||||
readOnly: { type: [null, Boolean], default: null },
|
||||
required: { type: [null, Boolean], default: null },
|
||||
},
|
||||
emits: ['focus', 'input', 'change'],
|
||||
inject: {
|
||||
@ -56,28 +63,89 @@ export default {
|
||||
inputType() {
|
||||
return 'text';
|
||||
},
|
||||
labelClasses() {
|
||||
return 'text-gray-600 text-sm mb-1';
|
||||
},
|
||||
inputClasses() {
|
||||
let classes = [
|
||||
{
|
||||
'px-3 py-2': this.size !== 'small',
|
||||
'px-2 py-1': this.size === 'small',
|
||||
},
|
||||
'focus:outline-none rounded w-full placeholder-gray-500',
|
||||
this.isReadOnly
|
||||
? 'text-gray-800 focus:bg-transparent'
|
||||
: 'text-gray-900 focus:bg-gray-200',
|
||||
/**
|
||||
* These classes will be used by components that extend Base
|
||||
*/
|
||||
|
||||
const classes = [
|
||||
'text-base',
|
||||
'focus:outline-none',
|
||||
'w-full',
|
||||
'placeholder-gray-500',
|
||||
];
|
||||
|
||||
if (isNumeric(this.df)) {
|
||||
classes.push('text-right');
|
||||
}
|
||||
|
||||
if (this.size === 'small') {
|
||||
classes.push('px-2 py-1');
|
||||
} else {
|
||||
classes.push('px-3 py-2');
|
||||
}
|
||||
|
||||
if (this.isReadOnly) {
|
||||
classes.push('text-gray-800 cursor-default');
|
||||
} else {
|
||||
classes.push('text-gray-900');
|
||||
}
|
||||
|
||||
return this.getInputClassesFromProp(classes);
|
||||
},
|
||||
containerClasses() {
|
||||
/**
|
||||
* Used to accomodate extending compoents where the input is contained in
|
||||
* a div eg AutoComplete
|
||||
*/
|
||||
const classes = ['rounded'];
|
||||
if (!this.isReadOnly) {
|
||||
classes.push('focus-within:bg-gray-100');
|
||||
}
|
||||
|
||||
if (this.border) {
|
||||
classes.push('bg-gray-50 border border-gray-200');
|
||||
}
|
||||
|
||||
return classes;
|
||||
},
|
||||
inputPlaceholder() {
|
||||
return this.placeholder || this.df.placeholder || this.df.label;
|
||||
},
|
||||
showMandatory() {
|
||||
return this.isEmpty && this.isRequired;
|
||||
},
|
||||
isEmpty() {
|
||||
if (Array.isArray(this.value) && !this.value.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof this.value === 'string' && !this.value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getIsNullOrUndef(this.value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
isReadOnly() {
|
||||
if (this.readOnly != null) {
|
||||
if (typeof this.readOnly === 'boolean') {
|
||||
return this.readOnly;
|
||||
}
|
||||
return this.df.readOnly;
|
||||
|
||||
return evaluateReadOnly(this.df, this.doc);
|
||||
},
|
||||
isRequired() {
|
||||
if (typeof this.required === 'boolean') {
|
||||
return this.required;
|
||||
}
|
||||
|
||||
return evaluateRequired(this.df, this.doc);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@ -112,9 +180,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
input[type='number']::-webkit-inner-spin-button {
|
||||
appearance: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :class="[inputClasses, containerClasses]">
|
||||
<label class="flex items-center">
|
||||
<div class="mr-3 text-gray-600 text-sm" v-if="showLabel && !labelRight">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<div style="width: 14px; height: 14px; overflow: hidden; cursor: pointer">
|
||||
<div
|
||||
style="width: 14px; height: 14px; overflow: hidden"
|
||||
:class="isReadOnly ? 'cursor-default' : 'cursor-pointer'"
|
||||
>
|
||||
<svg
|
||||
v-if="checked"
|
||||
width="14"
|
||||
@ -54,7 +57,6 @@
|
||||
<input
|
||||
ref="input"
|
||||
type="checkbox"
|
||||
:class="inputClasses"
|
||||
:checked="value"
|
||||
:readonly="isReadOnly"
|
||||
@change="(e) => !isReadOnly && triggerChange(e.target.checked)"
|
||||
@ -88,9 +90,11 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/*
|
||||
inputClasses() {
|
||||
return this.getInputClassesFromProp([]);
|
||||
},
|
||||
*/
|
||||
checked() {
|
||||
return this.value;
|
||||
},
|
||||
|
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<Popover placement="bottom-end">
|
||||
<template #target="{ togglePopover }">
|
||||
<div
|
||||
tabindex="0"
|
||||
:class="inputClasses"
|
||||
:class="[inputClasses, containerClasses]"
|
||||
@click="!isReadOnly && togglePopover()"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="text-sm py-3 px-2 text-center">
|
||||
<div class="text-sm p-2 text-center">
|
||||
<div>
|
||||
<Row class="border-none" :column-count="5" gap="0.5rem">
|
||||
<div
|
||||
@ -42,10 +42,9 @@
|
||||
<input
|
||||
type="text"
|
||||
:placeholder="t`Custom Hex`"
|
||||
:class="inputClasses"
|
||||
:class="[inputClasses, containerClasses]"
|
||||
:value="value"
|
||||
@change="(e) => setColorValue(e.target.value)"
|
||||
class="bg-gray-100"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<input
|
||||
v-show="showInput"
|
||||
ref="input"
|
||||
:class="inputClasses"
|
||||
class="text-right"
|
||||
:class="[inputClasses, containerClasses]"
|
||||
:type="inputType"
|
||||
:value="value?.round()"
|
||||
:placeholder="inputPlaceholder"
|
||||
@ -17,7 +18,8 @@
|
||||
/>
|
||||
<div
|
||||
v-show="!showInput"
|
||||
:class="[inputClasses, 'cursor-text whitespace-nowrap overflow-x-auto']"
|
||||
class="whitespace-nowrap overflow-x-auto"
|
||||
:class="[inputClasses, containerClasses, ,]"
|
||||
@click="activateInput"
|
||||
@focus="activateInput"
|
||||
tabindex="0"
|
||||
@ -61,6 +63,10 @@ export default {
|
||||
this.triggerChange(value);
|
||||
},
|
||||
activateInput() {
|
||||
if (this.isReadOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.showInput = true;
|
||||
nextTick(() => {
|
||||
this.focus();
|
||||
|
@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
|
||||
<DatePicker
|
||||
ref="input"
|
||||
:input-class="[inputClasses, 'cursor-text']"
|
||||
:show-mandatory="showMandatory"
|
||||
:input-class="['bg-transparent', inputClasses, containerClasses]"
|
||||
:value="value"
|
||||
:placeholder="inputPlaceholder"
|
||||
:readonly="isReadOnly"
|
||||
|
@ -3,7 +3,8 @@
|
||||
:df="languageDf"
|
||||
:value="value"
|
||||
@change="onChange"
|
||||
:input-class="'focus:outline-none rounded ' + inputClass"
|
||||
:border="true"
|
||||
:input-class="'rounded py-1.5'"
|
||||
/>
|
||||
</template>
|
||||
<script>
|
||||
@ -17,11 +18,6 @@ export default {
|
||||
setLanguageMap,
|
||||
},
|
||||
props: {
|
||||
inputClass: {
|
||||
type: String,
|
||||
default:
|
||||
'px-3 py-2 text-base',
|
||||
},
|
||||
dontReload: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-between focus-within:bg-gray-200"
|
||||
:class="inputClasses"
|
||||
class="flex items-center justify-between"
|
||||
:class="[inputClasses, containerClasses]"
|
||||
>
|
||||
<select
|
||||
class="
|
||||
@ -17,7 +17,7 @@
|
||||
"
|
||||
:class="{
|
||||
'pointer-events-none': isReadOnly,
|
||||
'text-gray-400': !value,
|
||||
'text-gray-500': !value,
|
||||
}"
|
||||
:value="value"
|
||||
@change="(e) => triggerChange(e.target.value)"
|
||||
@ -44,7 +44,8 @@
|
||||
>
|
||||
<path
|
||||
d="M1 2.636L2.636 1l1.637 1.636M1 7.364L2.636 9l1.637-1.636"
|
||||
stroke="#404040"
|
||||
class="stroke-current"
|
||||
:class="showMandatory ? 'text-red-500' : 'text-gray-500'"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="round"
|
||||
|
@ -5,7 +5,7 @@
|
||||
w-full
|
||||
px-2
|
||||
border-b
|
||||
hover:bg-gray-50
|
||||
hover:bg-gray-25
|
||||
group
|
||||
flex
|
||||
items-center
|
||||
@ -32,8 +32,6 @@
|
||||
<FormControl
|
||||
v-for="df in tableFields"
|
||||
:size="size"
|
||||
:read-only="readOnly"
|
||||
:input-class="{ 'text-right': isNumeric(df), 'bg-transparent': true }"
|
||||
:key="df.fieldname"
|
||||
:df="df"
|
||||
:value="row[df.fieldname]"
|
||||
|
@ -1,20 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||
<div :class="labelClasses" v-if="showLabel">
|
||||
{{ df.label }}
|
||||
</div>
|
||||
<textarea
|
||||
ref="input"
|
||||
rows="3"
|
||||
:class="['resize-none', inputClasses]"
|
||||
:value="value"
|
||||
:placeholder="inputPlaceholder"
|
||||
style="vertical-align: top"
|
||||
:readonly="isReadOnly"
|
||||
@blur="(e) => triggerChange(e.target.value)"
|
||||
@focus="(e) => $emit('focus', e)"
|
||||
@input="(e) => $emit('input', e)"
|
||||
></textarea>
|
||||
<div :class="showMandatory ? 'show-mandatory' : ''">
|
||||
<textarea
|
||||
ref="input"
|
||||
rows="3"
|
||||
:class="['resize-none', inputClasses, containerClasses]"
|
||||
:value="value"
|
||||
:placeholder="inputPlaceholder"
|
||||
style="vertical-align: top"
|
||||
:readonly="isReadOnly"
|
||||
@blur="(e) => triggerChange(e.target.value)"
|
||||
@focus="(e) => $emit('focus', e)"
|
||||
@input="(e) => $emit('input', e)"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
<Popover @open="selectCurrentMonthYear">
|
||||
<template #target="{ togglePopover, handleBlur }">
|
||||
<input
|
||||
type="text"
|
||||
:class="inputClass"
|
||||
:value="value && formatValue ? formatValue(value) : value || ''"
|
||||
:placeholder="placeholder"
|
||||
readonly
|
||||
@focus="!readonly ? togglePopover() : null"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
<div :class="showMandatory ? 'show-mandatory' : ''">
|
||||
<input
|
||||
type="text"
|
||||
:class="inputClass"
|
||||
:value="value && formatValue ? formatValue(value) : value || ''"
|
||||
:placeholder="placeholder"
|
||||
readonly
|
||||
@focus="!readonly ? togglePopover() : null"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #content="{ togglePopover }">
|
||||
<div class="text-left p-3 select-none">
|
||||
@ -63,7 +65,11 @@
|
||||
{{ d }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="(week, i) in datesAsWeeks" :key="`${i}-${Math.random().toString(36)}`" class="mt-1">
|
||||
<div
|
||||
v-for="(week, i) in datesAsWeeks"
|
||||
:key="`${i}-${Math.random().toString(36)}`"
|
||||
class="mt-1"
|
||||
>
|
||||
<div class="flex w-full">
|
||||
<div
|
||||
v-for="date in week"
|
||||
@ -123,7 +129,14 @@ import Popover from '../Popover';
|
||||
|
||||
export default {
|
||||
name: 'DatePicker',
|
||||
props: ['value', 'placeholder', 'readonly', 'formatValue', 'inputClass'],
|
||||
props: [
|
||||
'value',
|
||||
'placeholder',
|
||||
'readonly',
|
||||
'formatValue',
|
||||
'inputClass',
|
||||
'showMandatory',
|
||||
],
|
||||
emits: ['change'],
|
||||
components: {
|
||||
Popover,
|
||||
@ -256,7 +269,7 @@ export default {
|
||||
return '';
|
||||
}
|
||||
|
||||
return DateTime.fromJSDate(date).toISODate()
|
||||
return DateTime.fromJSDate(date).toISODate();
|
||||
},
|
||||
|
||||
getDate(...args) {
|
||||
|
@ -56,9 +56,9 @@
|
||||
</span>
|
||||
</div>
|
||||
<FormControl
|
||||
:border="true"
|
||||
size="small"
|
||||
class="w-24"
|
||||
input-class="bg-gray-100"
|
||||
:df="{
|
||||
placeholder: t`Field`,
|
||||
fieldname: 'fieldname',
|
||||
@ -69,9 +69,9 @@
|
||||
@change="(value) => (filter.fieldname = value)"
|
||||
/>
|
||||
<FormControl
|
||||
:border="true"
|
||||
size="small"
|
||||
class="w-24"
|
||||
input-class="bg-gray-100"
|
||||
:df="{
|
||||
placeholder: t`Condition`,
|
||||
fieldname: 'condition',
|
||||
@ -82,9 +82,9 @@
|
||||
@change="(value) => (filter.condition = value)"
|
||||
/>
|
||||
<FormControl
|
||||
:border="true"
|
||||
size="small"
|
||||
class="w-24"
|
||||
input-class="bg-gray-100"
|
||||
:df="{
|
||||
placeholder: t`Value`,
|
||||
fieldname: 'value',
|
||||
@ -124,9 +124,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { t } from 'fyo';
|
||||
import { FieldTypeEnum } from 'schemas/types';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { getRandomString } from 'utils';
|
||||
import Button from './Button';
|
||||
import FormControl from './Controls/FormControl.vue';
|
||||
|
@ -9,8 +9,8 @@
|
||||
size="small"
|
||||
:df="df"
|
||||
:value="doc[df.fieldname]"
|
||||
:read-only="evaluateReadOnly(df)"
|
||||
@change="async (value) => await onChange(df, value)"
|
||||
:read-only="readOnly"
|
||||
/>
|
||||
|
||||
<!-- Inline Field Form (Eg: Address) -->
|
||||
@ -29,6 +29,7 @@
|
||||
:no-border="true"
|
||||
:focus-first-input="true"
|
||||
:autosave="false"
|
||||
:read-only="readOnly"
|
||||
@error="(msg) => $emit('error', msg)"
|
||||
/>
|
||||
<div
|
||||
@ -79,8 +80,7 @@
|
||||
:df="df"
|
||||
:value="getRegularValue(df)"
|
||||
:class="{ 'p-2': df.fieldtype === 'Check' }"
|
||||
:read-only="evaluateReadOnly(df)"
|
||||
input-class="bg-transparent"
|
||||
:read-only="readOnly"
|
||||
@change="async (value) => await onChange(df, value)"
|
||||
@focus="activateInlineEditing(df)"
|
||||
@new-doc="async (newdoc) => await onChange(df, newdoc.name)"
|
||||
@ -103,7 +103,7 @@ import FormControl from 'src/components/Controls/FormControl.vue';
|
||||
import { handleErrorWithDialog } from 'src/errorHandling';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { getErrorMessage } from 'src/utils';
|
||||
import { evaluateHidden, evaluateReadOnly } from 'src/utils/doc';
|
||||
import { evaluateHidden } from 'src/utils/doc';
|
||||
|
||||
export default {
|
||||
name: 'TwoColumnForm',
|
||||
@ -122,6 +122,7 @@ export default {
|
||||
},
|
||||
noBorder: Boolean,
|
||||
focusFirstInput: Boolean,
|
||||
readOnly: { type: [null, Boolean], default: null },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -183,9 +184,6 @@ export default {
|
||||
this.inlineEditField?.fieldname === df?.fieldname && this.inlineEditDoc
|
||||
);
|
||||
},
|
||||
evaluateReadOnly(df) {
|
||||
return evaluateReadOnly(df, this.doc);
|
||||
},
|
||||
async onChange(df, value) {
|
||||
if (df.inline) {
|
||||
return;
|
||||
|
@ -137,17 +137,13 @@
|
||||
"
|
||||
style="top: 100%; transform: translateY(-100%)"
|
||||
>
|
||||
<LanguageSelector
|
||||
v-show="!creatingDemo"
|
||||
class="text-sm w-28 bg-gray-100 rounded-md"
|
||||
input-class="py-1.5 bg-transparent"
|
||||
/>
|
||||
<LanguageSelector v-show="!creatingDemo" class="text-sm w-28" />
|
||||
<button
|
||||
class="
|
||||
text-sm
|
||||
bg-gray-100
|
||||
hover:bg-gray-200
|
||||
rounded-md
|
||||
rounded
|
||||
px-4
|
||||
py-1.5
|
||||
w-28
|
||||
|
@ -63,8 +63,8 @@
|
||||
<!-- Invoice Form Data Entry -->
|
||||
<div class="m-4 grid grid-cols-3 gap-4">
|
||||
<FormControl
|
||||
class="bg-gray-100 rounded text-base"
|
||||
input-class="text-lg font-semibold bg-transparent"
|
||||
input-class="font-semibold"
|
||||
:border="true"
|
||||
:df="getField('party')"
|
||||
:value="doc.party"
|
||||
@change="(value) => doc.set('party', value)"
|
||||
@ -72,67 +72,28 @@
|
||||
:read-only="doc?.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
input-class="bg-gray-100 px-3 py-2 text-base text-right"
|
||||
input-class="text-right"
|
||||
:border="true"
|
||||
:df="getField('date')"
|
||||
:value="doc.date"
|
||||
@change="(value) => doc.set('date', value)"
|
||||
:read-only="doc?.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
class="text-base bg-gray-100 rounded"
|
||||
input-class="bg-transparent px-3 py-2 text-base text-right"
|
||||
input-class="text-right"
|
||||
:border="true"
|
||||
:df="getField('numberSeries')"
|
||||
:value="doc.numberSeries"
|
||||
@change="(value) => doc.set('numberSeries', value)"
|
||||
:read-only="!doc.notInserted || doc?.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
class="text-base bg-gray-100 rounded"
|
||||
input-class="px-3 py-2 text-base bg-transparent"
|
||||
:border="true"
|
||||
:df="getField('account')"
|
||||
:value="doc.account"
|
||||
@change="(value) => doc.set('account', value)"
|
||||
:read-only="doc?.submitted"
|
||||
/>
|
||||
<!--
|
||||
<FormControl
|
||||
v-if="doc.enableDiscounting"
|
||||
:show-label="true"
|
||||
:label-right="false"
|
||||
class="
|
||||
text-base
|
||||
bg-gray-100
|
||||
rounded
|
||||
flex
|
||||
items-center
|
||||
justify-center
|
||||
w-ful
|
||||
"
|
||||
input-class="px-3 py-2 text-base bg-transparent text-right"
|
||||
:df="getField('setDiscountAmount')"
|
||||
:value="doc.setDiscountAmount"
|
||||
@change="(value) => doc.set('setDiscountAmount', value)"
|
||||
:read-only="doc?.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
v-if="doc.enableDiscounting && !doc.setDiscountAmount"
|
||||
class="text-base bg-gray-100 rounded"
|
||||
input-class="px-3 py-2 text-base bg-transparent text-right"
|
||||
:df="getField('discountPercent')"
|
||||
:value="doc.discountPercent"
|
||||
@change="(value) => doc.set('discountPercent', value)"
|
||||
:read-only="doc?.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
v-if="doc.enableDiscounting && doc.setDiscountAmount"
|
||||
class="text-base bg-gray-100 rounded"
|
||||
input-class="px-3 py-2 text-base bg-transparent text-right"
|
||||
:df="getField('discountAmount')"
|
||||
:value="doc.discountAmount"
|
||||
@change="(value) => doc.set('discountAmount', value)"
|
||||
:read-only="doc?.submitted"
|
||||
/>
|
||||
-->
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
@ -161,10 +122,10 @@
|
||||
</p>
|
||||
<!-- Form Terms-->
|
||||
<FormControl
|
||||
:border="true"
|
||||
v-if="!doc?.submitted || doc.terms"
|
||||
:df="getField('terms')"
|
||||
:value="doc.terms"
|
||||
input-class="bg-gray-100"
|
||||
class="mt-auto"
|
||||
@change="(value) => doc.set('terms', value)"
|
||||
:read-only="doc?.submitted"
|
||||
|
@ -47,43 +47,42 @@
|
||||
<div class="m-4 grid grid-cols-3 gap-y-4 gap-x-4">
|
||||
<!-- First Column of Fields -->
|
||||
<FormControl
|
||||
:border="true"
|
||||
:df="getField('numberSeries')"
|
||||
:value="doc.numberSeries"
|
||||
@change="(value) => doc.set('numberSeries', value)"
|
||||
class="bg-gray-100 rounded"
|
||||
input-class="p-2 text-base bg-transparent"
|
||||
:read-only="!doc.notInserted || doc.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
:border="true"
|
||||
:df="getField('date')"
|
||||
:value="doc.date"
|
||||
:placeholder="'Date'"
|
||||
@change="(value) => doc.set('date', value)"
|
||||
input-class="bg-gray-100 px-3 py-2 text-base"
|
||||
:read-only="doc.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
:border="true"
|
||||
:df="getField('entryType')"
|
||||
:value="doc.entryType"
|
||||
placeholder="Entry Type"
|
||||
@change="(value) => doc.set('entryType', value)"
|
||||
input-class="bg-gray-100 px-3 py-2 text-base"
|
||||
:read-only="doc.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
:border="true"
|
||||
:df="getField('referenceNumber')"
|
||||
:value="doc.referenceNumber"
|
||||
:placeholder="'Reference Number'"
|
||||
@change="(value) => doc.set('referenceNumber', value)"
|
||||
input-class="bg-gray-100 p-2 text-base"
|
||||
:read-only="doc.submitted"
|
||||
/>
|
||||
<FormControl
|
||||
:border="true"
|
||||
:df="getField('referenceDate')"
|
||||
:value="doc.referenceDate"
|
||||
:placeholder="'Reference Date'"
|
||||
@change="(value) => doc.set('referenceDate', value)"
|
||||
input-class="bg-gray-100 px-3 py-2 text-base"
|
||||
:read-only="doc.submitted"
|
||||
/>
|
||||
</div>
|
||||
@ -106,9 +105,9 @@
|
||||
<div class="flex justify-between text-base m-4 gap-12">
|
||||
<!-- User Remark -->
|
||||
<FormControl
|
||||
:border="true"
|
||||
v-if="!doc.submitted || doc.userRemark"
|
||||
class="w-1/2 self-end"
|
||||
input-class="bg-gray-100"
|
||||
:df="getField('userRemark')"
|
||||
:value="doc.userRemark"
|
||||
@change="(value) => doc.set('userRemark', value)"
|
||||
|
@ -14,15 +14,13 @@
|
||||
</PageHeader>
|
||||
|
||||
<!-- Filters -->
|
||||
<div v-if="report" class="grid grid-cols-5 gap-2 p-4 border-b">
|
||||
<div v-if="report" class="grid grid-cols-5 gap-4 p-4 border-b">
|
||||
<FormControl
|
||||
v-for="field in report.filters"
|
||||
:border="true"
|
||||
size="small"
|
||||
:show-label="field.fieldtype === 'Check'"
|
||||
:key="field.fieldname + '-filter'"
|
||||
class="bg-gray-100 rounded"
|
||||
:class="field.fieldtype === 'Check' ? 'flex pl-2 py-1' : ''"
|
||||
input-class="bg-transparent text-sm"
|
||||
:df="field"
|
||||
:value="report.get(field.fieldname)"
|
||||
:read-only="loading"
|
||||
|
@ -9,10 +9,7 @@
|
||||
@change="forwardChangeEvent"
|
||||
/>
|
||||
<div class="flex p-4 justify-between">
|
||||
<LanguageSelector
|
||||
class="text-sm w-28 bg-gray-100 rounded-md"
|
||||
input-class="py-1.5 bg-transparent"
|
||||
/>
|
||||
<LanguageSelector class="text-sm w-28" />
|
||||
<p class="mt-auto text-gray-600 text-base select-none">
|
||||
{{ `v${fyo.store.appVersion}` }}
|
||||
</p>
|
||||
|
@ -6,8 +6,9 @@
|
||||
<!-- Setup Wizard Slide -->
|
||||
<Slide
|
||||
:primary-disabled="!valuesFilled || loading"
|
||||
@primary-clicked="handlePrimary"
|
||||
@secondary-clicked="handleSecondary"
|
||||
:secondary-disabled="loading"
|
||||
@primary-clicked="submit()"
|
||||
@secondary-clicked="$emit('setup-canceled')"
|
||||
:class="{ 'window-no-drag': platform !== 'Windows' }"
|
||||
>
|
||||
<template #title>
|
||||
@ -21,6 +22,7 @@
|
||||
<FormControl
|
||||
:df="getField('logo')"
|
||||
:value="doc.logo"
|
||||
:read-only="loading"
|
||||
@change="(value) => setValue('logo', value)"
|
||||
/>
|
||||
<div>
|
||||
@ -28,9 +30,9 @@
|
||||
ref="companyField"
|
||||
:df="getField('companyName')"
|
||||
:value="doc.companyName"
|
||||
:read-only="loading"
|
||||
@change="(value) => setValue('companyName', value)"
|
||||
input-class="
|
||||
bg-transparent
|
||||
font-semibold
|
||||
text-xl
|
||||
"
|
||||
@ -39,11 +41,8 @@
|
||||
<FormControl
|
||||
:df="getField('email')"
|
||||
:value="doc.email"
|
||||
:read-only="loading"
|
||||
@change="(value) => setValue('email', value)"
|
||||
input-class="
|
||||
text-base
|
||||
bg-transparent
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -56,11 +55,13 @@
|
||||
{{ emailError }}
|
||||
</p>
|
||||
|
||||
<TwoColumnForm :doc="doc" />
|
||||
<TwoColumnForm :doc="doc" :read-only="loading" />
|
||||
</div>
|
||||
</template>
|
||||
<template #secondaryButton>{{ t`Cancel` }}</template>
|
||||
<template #primaryButton>{{ t`Submit` }}</template>
|
||||
<template #primaryButton>{{
|
||||
loading ? t`Setting up...` : t`Submit`
|
||||
}}</template>
|
||||
</Slide>
|
||||
</div>
|
||||
</template>
|
||||
@ -69,7 +70,6 @@
|
||||
import FormControl from 'src/components/Controls/FormControl.vue';
|
||||
import TwoColumnForm from 'src/components/TwoColumnForm.vue';
|
||||
import { getErrorMessage } from 'src/utils';
|
||||
import { openLink } from 'src/utils/ipcCalls';
|
||||
import { getSetupWizardDoc } from 'src/utils/misc';
|
||||
import { showMessageDialog } from 'src/utils/ui';
|
||||
import Slide from './Slide.vue';
|
||||
@ -106,17 +106,6 @@ export default {
|
||||
getField(fieldname) {
|
||||
return this.doc.schema?.fields.find((f) => f.fieldname === fieldname);
|
||||
},
|
||||
openContributingTranslations() {
|
||||
openLink(
|
||||
'https://github.com/frappe/books/wiki/Contributing-Translations'
|
||||
);
|
||||
},
|
||||
handlePrimary() {
|
||||
this.submit();
|
||||
},
|
||||
handleSecondary() {
|
||||
this.$emit('setup-canceled');
|
||||
},
|
||||
setValue(fieldname, value) {
|
||||
this.emailError = null;
|
||||
this.doc.set(fieldname, value).catch((e) => {
|
||||
@ -142,14 +131,5 @@ export default {
|
||||
this.$emit('setup-complete', this.doc.getValidDict());
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
buttonText() {
|
||||
if (this.loading) {
|
||||
return this.t`Submit`;
|
||||
}
|
||||
|
||||
return this.t`Setting Up...`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="w-form shadow-lg rounded-lg border relative bg-white" style="height: 700px">
|
||||
<div
|
||||
class="w-form shadow-lg rounded-lg border relative bg-white"
|
||||
style="height: 700px"
|
||||
>
|
||||
<!-- Slide Title -->
|
||||
<div class="p-4">
|
||||
<h1 class="text-2xl font-semibold select-none">
|
||||
@ -19,15 +22,16 @@
|
||||
style="top: 100%; transform: translateY(-100%)"
|
||||
>
|
||||
<Button
|
||||
class="text-sm text-grey-900 w-28"
|
||||
class="text-sm text-grey-900 min-w-28"
|
||||
@click="$emit('secondary-clicked')"
|
||||
:disabled="secondaryDisabled"
|
||||
>
|
||||
<slot name="secondaryButton"></slot>
|
||||
</Button>
|
||||
<Button
|
||||
@click="$emit('primary-clicked')"
|
||||
type="primary"
|
||||
class="text-sm text-white w-28"
|
||||
class="text-sm text-white min-w-28"
|
||||
:disabled="primaryDisabled"
|
||||
>
|
||||
<slot name="primaryButton"></slot>
|
||||
@ -45,6 +49,7 @@ export default {
|
||||
props: {
|
||||
usePrimary: { type: Boolean, default: true },
|
||||
primaryDisabled: { type: Boolean, default: false },
|
||||
secondaryDisabled: { type: Boolean, default: false },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -23,6 +23,10 @@ html {
|
||||
color: theme('colors.black');
|
||||
}
|
||||
|
||||
input[type='number']::-webkit-inner-spin-button {
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.window-drag {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
@ -75,7 +79,7 @@ html {
|
||||
}
|
||||
|
||||
.w-quick-edit {
|
||||
width: var(--w-quick-edit)
|
||||
width: var(--w-quick-edit);
|
||||
}
|
||||
|
||||
.h-form {
|
||||
@ -109,3 +113,13 @@ html {
|
||||
.w-desk {
|
||||
width: var(--w-desk);
|
||||
}
|
||||
|
||||
.show-mandatory::after {
|
||||
content: '*';
|
||||
display: inline-block;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
margin-left: -0.875rem;
|
||||
vertical-align: -3px;
|
||||
@apply text-red-500;
|
||||
}
|
||||
|
@ -1,40 +1,49 @@
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { Field } from 'schemas/types';
|
||||
|
||||
export function evaluateReadOnly(field: Field, doc: Doc) {
|
||||
if (field.readOnly !== undefined) {
|
||||
return field.readOnly;
|
||||
}
|
||||
|
||||
if (field.fieldname === 'numberSeries' && !doc.notInserted) {
|
||||
export function evaluateReadOnly(field: Field, doc?: Doc) {
|
||||
if (field.fieldname === 'numberSeries' && !doc?.notInserted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (doc.isSubmitted || doc.parentdoc?.isSubmitted) {
|
||||
if (doc?.isSubmitted || doc?.parentdoc?.isSubmitted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (doc.isCancelled || doc.parentdoc?.isCancelled) {
|
||||
if (doc?.isCancelled || doc?.parentdoc?.isCancelled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const readOnlyFunc = doc.readOnly[field.fieldname];
|
||||
if (readOnlyFunc !== undefined) {
|
||||
return readOnlyFunc();
|
||||
}
|
||||
|
||||
return false;
|
||||
return evaluateFieldMeta(field, doc, 'readOnly');
|
||||
}
|
||||
|
||||
export function evaluateHidden(field: Field, doc: Doc) {
|
||||
if (field.hidden !== undefined) {
|
||||
return field.hidden;
|
||||
export function evaluateHidden(field: Field, doc?: Doc) {
|
||||
return evaluateFieldMeta(field, doc, 'hidden');
|
||||
}
|
||||
|
||||
export function evaluateRequired(field: Field, doc?: Doc) {
|
||||
return evaluateFieldMeta(field, doc, 'required');
|
||||
}
|
||||
|
||||
function evaluateFieldMeta(
|
||||
field: Field,
|
||||
doc?: Doc,
|
||||
meta?: 'required' | 'hidden' | 'readOnly',
|
||||
defaultValue: boolean = false
|
||||
) {
|
||||
if (meta === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
const hiddenFunction = doc.hidden[field.fieldname];
|
||||
const value = field[meta];
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const hiddenFunction = doc?.[meta]?.[field.fieldname];
|
||||
if (hiddenFunction !== undefined) {
|
||||
return hiddenFunction();
|
||||
}
|
||||
|
||||
return false;
|
||||
return defaultValue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user