Bug 41214: Convert hideIn to a callback to allow total removal of fields via syspref

Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
Signed-off-by: Matt Blenkinsop <matt.blenkinsop@openfifth.co.uk>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 4c316e25cd)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
This commit is contained in:
Matt Blenkinsop 2025-11-19 10:26:51 +00:00 committed by Jacob O'Mara
parent 6d4b9b3e4e
commit 39036410b5
No known key found for this signature in database
3 changed files with 199 additions and 211 deletions

View File

@ -1,202 +1,200 @@
<template>
<template v-if="display">
<label
v-if="attr.label"
:for="getElementId"
:class="{ required: attr.required }"
:style="{ ...attr.style }"
>{{ attr.label }}:</label
>
<template v-if="attr.type == 'number'">
<InputNumber
:id="getElementId"
v-model="resource[attr.name]"
:placeholder="attr.placeholder || attr.label"
:required="attr.required ? true : false"
:size="attr.size"
:maxlength="attr.maxlength"
:disabled="disabled"
@update:modelValue="checkForInputError()"
/>
</template>
<template v-else-if="attr.type == 'text'">
<InputText
:id="getElementId"
v-model="resource[attr.name]"
:placeholder="attr.placeholder || attr.label"
:required="attr.required ? true : false"
:disabled="disabled"
@update:modelValue="checkForInputError()"
/>
</template>
<template v-else-if="attr.type == 'textarea'">
<TextArea
:id="getElementId"
v-model="resource[attr.name]"
:rows="attr.textAreaRows"
:cols="attr.textAreaCols"
:placeholder="attr.placeholder || attr.label"
:required="attr.required ? true : false"
:disabled="disabled"
@update:modelValue="checkForInputError()"
/>
</template>
<template v-else-if="attr.type == 'checkbox'">
<InputCheckbox
:id="getElementId"
type="checkbox"
v-model="resource[attr.name]"
:changeMethod="
attr.onChange && attr.onChange.bind(this, resource)
"
:disabled="disabled"
/>
</template>
<template v-else-if="attr.type == 'radio'">
<template
v-for="(option, index) in attr.options"
:key="`radio-option-${index}`"
>
<label
v-if="option.description"
:for="attr.name + '_' + option.value"
>{{ option.description }}:
<InputRadio
:name="attr.name"
:id="attr.name + '_' + option.value"
:value="option.value"
:checked="
(!Object.keys(resource).includes(attr.name) &&
attr.default == option.value) ||
(Object.keys(resource).includes(attr.name) &&
option.value == resource[attr.name])
"
v-model="resource[attr.name]"
@change="
attr.onChange && attr.onChange.bind(this, resource)
"
/>
</label>
</template>
</template>
<template v-else-if="attr.type == 'boolean'">
<label class="radio" :for="getElementId + '_yes'"
>{{ $__("Yes") }}:
<InputRadio
type="radio"
:name="attr.name"
:id="attr.name + '_yes'"
:value="true"
:checked="resource[attr.name] == true"
v-model="resource[attr.name]"
/>
</label>
<label class="radio" :for="getElementId + '_no'"
>{{ $__("No") }}:
<InputRadio
type="radio"
:name="attr.name"
:id="attr.name + '_no'"
:checked="resource[attr.name] == false"
:value="false"
v-model="resource[attr.name]"
/>
</label>
</template>
<template v-else-if="attr.type == 'select'">
<v-select
:id="getElementId"
v-model="resource[attr.name]"
:label="attr.selectLabel"
:reduce="av => selectRequiredKey(av)"
:options="selectOptions"
:required="!resource[attr.name] && attr.required"
:disabled="disabled"
:multiple="attr.allowMultipleChoices"
@option:selected="attr.onSelected && attr.onSelected(resource)"
>
<template v-if="attr.required" #search="{ attributes, events }">
<input
:required="!resource[attr.name]"
class="vs__search"
v-bind="attributes"
v-on="events"
/>
</template>
</v-select>
</template>
<template v-else-if="attr.type == 'vendor'">
<component
:is="requiredComponent"
:id="getElementId"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
v-model="resource[attr.name]"
></component>
</template>
<template v-else-if="attr.type == 'date'">
<component
:is="requiredComponent"
:id="getElementId"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
v-model="resource[attr.name]"
></component>
</template>
<template v-else-if="attr.type == 'component' && attr.componentPath">
<component
v-if="isVModelRequired(attr.componentPath)"
:is="requiredComponent"
v-bind="getComponentProps()"
v-model="resource[attr.name]"
v-on="getEventHandlers()"
></component>
<component
v-else
:is="requiredComponent"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
></component>
</template>
<template
v-else-if="attr.type == 'relationshipWidget' && attr.componentProps"
>
<component
:is="requiredComponent"
:title="attr.group ? null : attr.label"
:apiClient="attr.apiClient"
:name="attr.name"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
></component>
</template>
<template v-else-if="attr.type == 'relationshipSelect'">
<FormRelationshipSelect
v-bind="attr"
:resource="resource"
></FormRelationshipSelect>
</template>
<template v-else-if="attr.type == 'additional_fields'">
<AdditionalFieldsEntry
:resource="resource"
:additional_field_values="resource.extended_attributes"
:extended_attributes_resource_type="
attr.extended_attributes_resource_type
"
@additional-fields-changed="additionalFieldsChanged"
></AdditionalFieldsEntry>
</template>
<template v-else>
<span>{{
$__("Programming error: unknown type %s").format(attr.type)
}}</span>
</template>
<ToolTip v-if="attr.toolTip" :toolTip="attr.toolTip"></ToolTip>
<span v-if="attr.required" class="required">{{ $__("Required") }}</span>
<span style="margin-left: 5px" class="error" v-if="fieldInputError">
{{ attr.formErrorMessage }}
</span>
<label
v-if="attr.label"
:for="getElementId"
:class="{ required: attr.required }"
:style="{ ...attr.style }"
>{{ attr.label }}:</label
>
<template v-if="attr.type == 'number'">
<InputNumber
:id="getElementId"
v-model="resource[attr.name]"
:placeholder="attr.placeholder || attr.label"
:required="attr.required ? true : false"
:size="attr.size"
:maxlength="attr.maxlength"
:disabled="disabled"
@update:modelValue="checkForInputError()"
/>
</template>
<template v-else-if="attr.type == 'text'">
<InputText
:id="getElementId"
v-model="resource[attr.name]"
:placeholder="attr.placeholder || attr.label"
:required="attr.required ? true : false"
:disabled="disabled"
@update:modelValue="checkForInputError()"
/>
</template>
<template v-else-if="attr.type == 'textarea'">
<TextArea
:id="getElementId"
v-model="resource[attr.name]"
:rows="attr.textAreaRows"
:cols="attr.textAreaCols"
:placeholder="attr.placeholder || attr.label"
:required="attr.required ? true : false"
:disabled="disabled"
@update:modelValue="checkForInputError()"
/>
</template>
<template v-else-if="attr.type == 'checkbox'">
<InputCheckbox
:id="getElementId"
type="checkbox"
v-model="resource[attr.name]"
:changeMethod="
attr.onChange && attr.onChange.bind(this, resource)
"
:disabled="disabled"
/>
</template>
<template v-else-if="attr.type == 'radio'">
<template
v-for="(option, index) in attr.options"
:key="`radio-option-${index}`"
>
<label
v-if="option.description"
:for="attr.name + '_' + option.value"
>{{ option.description }}:
<InputRadio
:name="attr.name"
:id="attr.name + '_' + option.value"
:value="option.value"
:checked="
(!Object.keys(resource).includes(attr.name) &&
attr.default == option.value) ||
(Object.keys(resource).includes(attr.name) &&
option.value == resource[attr.name])
"
v-model="resource[attr.name]"
@change="
attr.onChange && attr.onChange.bind(this, resource)
"
/>
</label>
</template>
</template>
<template v-else-if="attr.type == 'boolean'">
<label class="radio" :for="getElementId + '_yes'"
>{{ $__("Yes") }}:
<InputRadio
type="radio"
:name="attr.name"
:id="attr.name + '_yes'"
:value="true"
:checked="resource[attr.name] == true"
v-model="resource[attr.name]"
/>
</label>
<label class="radio" :for="getElementId + '_no'"
>{{ $__("No") }}:
<InputRadio
type="radio"
:name="attr.name"
:id="attr.name + '_no'"
:checked="resource[attr.name] == false"
:value="false"
v-model="resource[attr.name]"
/>
</label>
</template>
<template v-else-if="attr.type == 'select'">
<v-select
:id="getElementId"
v-model="resource[attr.name]"
:label="attr.selectLabel"
:reduce="av => selectRequiredKey(av)"
:options="selectOptions"
:required="!resource[attr.name] && attr.required"
:disabled="disabled"
:multiple="attr.allowMultipleChoices"
@option:selected="attr.onSelected && attr.onSelected(resource)"
>
<template v-if="attr.required" #search="{ attributes, events }">
<input
:required="!resource[attr.name]"
class="vs__search"
v-bind="attributes"
v-on="events"
/>
</template>
</v-select>
</template>
<template v-else-if="attr.type == 'vendor'">
<component
:is="requiredComponent"
:id="getElementId"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
v-model="resource[attr.name]"
></component>
</template>
<template v-else-if="attr.type == 'date'">
<component
:is="requiredComponent"
:id="getElementId"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
v-model="resource[attr.name]"
></component>
</template>
<template v-else-if="attr.type == 'component' && attr.componentPath">
<component
v-if="isVModelRequired(attr.componentPath)"
:is="requiredComponent"
v-bind="getComponentProps()"
v-model="resource[attr.name]"
v-on="getEventHandlers()"
></component>
<component
v-else
:is="requiredComponent"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
></component>
</template>
<template
v-else-if="attr.type == 'relationshipWidget' && attr.componentProps"
>
<component
:is="requiredComponent"
:title="attr.group ? null : attr.label"
:apiClient="attr.apiClient"
:name="attr.name"
v-bind="getComponentProps()"
v-on="getEventHandlers()"
></component>
</template>
<template v-else-if="attr.type == 'relationshipSelect'">
<FormRelationshipSelect
v-bind="attr"
:resource="resource"
></FormRelationshipSelect>
</template>
<template v-else-if="attr.type == 'additional_fields'">
<AdditionalFieldsEntry
:resource="resource"
:additional_field_values="resource.extended_attributes"
:extended_attributes_resource_type="
attr.extended_attributes_resource_type
"
@additional-fields-changed="additionalFieldsChanged"
></AdditionalFieldsEntry>
</template>
<template v-else>
<span>{{
$__("Programming error: unknown type %s").format(attr.type)
}}</span>
</template>
<ToolTip v-if="attr.toolTip" :toolTip="attr.toolTip"></ToolTip>
<span v-if="attr.required" class="required">{{ $__("Required") }}</span>
<span style="margin-left: 5px" class="error" v-if="fieldInputError">
{{ attr.formErrorMessage }}
</span>
</template>
<script>
@ -277,14 +275,6 @@ export default {
return disabledAttr || false;
}
});
const display = computed(() => {
const displayAttr = props.display ?? props.attr.display ?? true;
if (typeof displayAttr === "function") {
return displayAttr(props.resource);
} else {
return displayAttr || false;
}
});
const fieldInputError = ref(false);
const checkForInputError = () => {
if (props.attr.formErrorHandler) {
@ -303,7 +293,6 @@ export default {
requiredComponent,
selectOptions,
disabled,
display,
fieldInputError,
checkForInputError,
};

View File

@ -422,8 +422,7 @@ export default {
relationshipAPIClient: APIClient.cash.cash_registers,
relationshipOptionLabelAttr: "name", // attr of the related resource used for display
relationshipRequiredKey: "cash_register_id",
hideIn: ["List"],
display: account => sysprefs.value.UseCashRegisters == 1,
hideIn: () => sysprefs.value.UseCashRegisters !== "0" ? ["List"] : ["Form", "Show", "List"],
group: "Details",
toolTip: __(
"Only required if system preference UseCashRegisters is enabled"

View File

@ -1,7 +1,6 @@
import { computed, inject, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { build_url } from "../composables/datatables";
import { isRef } from "vue";
import { storeToRefs } from "pinia";
import {
$__,
@ -419,10 +418,11 @@ export function useBaseResource(resourceConfig) {
relationshipField.relationshipName = ra.name;
});
}
if (ra.hideIn && !ra.hideIn.includes(component)) {
const shouldFieldBeHidden = ra.hideIn && typeof ra.hideIn === "function" ? ra.hideIn() : ra.hideIn
if (shouldFieldBeHidden && !shouldFieldBeHidden.includes(component)) {
return [...acc, ra];
}
if (ra.hideIn && ra.hideIn.includes(component)) {
if (shouldFieldBeHidden && shouldFieldBeHidden.includes(component)) {
return acc;
}
return [...acc, ra];