mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-21 13:23:14 +01:00
Merge pull request #234 from tonyaellie/add-char-counts-with-max-to-lots-of-inputs
Add char counters to inputs
This commit is contained in:
@@ -2,16 +2,30 @@
|
|||||||
<div v-if="!inline" class="form-control w-full">
|
<div v-if="!inline" class="form-control w-full">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">{{ label }}</span>
|
<span class="label-text">{{ label }}</span>
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
'text-red-600':
|
||||||
|
typeof value === 'string' &&
|
||||||
|
((maxLength && value.length > maxLength) || (minLength && value.length < minLength)),
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ typeof value === "string" && (maxLength || minLength) ? `${value.length}/${maxLength}` : "" }}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<textarea ref="el" v-model="value" class="textarea textarea-bordered h-28 w-full" :placeholder="placeholder" />
|
<textarea ref="el" v-model="value" class="textarea textarea-bordered h-28 w-full" :placeholder="placeholder" />
|
||||||
<label v-if="limit" class="label">
|
|
||||||
<span class="label-text-alt"></span>
|
|
||||||
<span class="label-text-alt"> {{ valueLen }}/{{ limit }}</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
|
<div v-else class="sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">{{ label }}</span>
|
<span class="label-text">{{ label }}</span>
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
'text-red-600':
|
||||||
|
typeof value === 'string' &&
|
||||||
|
((maxLength && value.length > maxLength) || (minLength && value.length < minLength)),
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ typeof value === "string" && (maxLength || minLength) ? `${value.length}/${maxLength}` : "" }}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
ref="el"
|
ref="el"
|
||||||
@@ -39,10 +53,6 @@
|
|||||||
type: String,
|
type: String,
|
||||||
default: "text",
|
default: "text",
|
||||||
},
|
},
|
||||||
limit: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
@@ -51,6 +61,14 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
maxLength: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
minLength: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const el = ref();
|
const el = ref();
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="!inline" class="form-control w-full">
|
<div v-if="!inline" class="form-control w-full">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">{{ label }}</span>
|
<span class="label-text"> {{ label }} </span>
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
'text-red-600':
|
||||||
|
typeof value === 'string' &&
|
||||||
|
((maxLength && value.length > maxLength) || (minLength && value.length < minLength)),
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ typeof value === "string" && (maxLength || minLength) ? `${value.length}/${maxLength}` : "" }}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
ref="input"
|
ref="input"
|
||||||
@@ -14,7 +23,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else class="sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
|
<div v-else class="sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">{{ label }}</span>
|
<span class="label-text"> {{ label }} </span>
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
'text-red-600':
|
||||||
|
typeof value === 'string' &&
|
||||||
|
((maxLength && value.length > maxLength) || (minLength && value.length < minLength)),
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ typeof value === "string" && (maxLength || minLength) ? `${value.length}/${maxLength}` : "" }}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<input v-model="value" :placeholder="placeholder" class="input input-bordered col-span-3 mt-2 w-full" />
|
<input v-model="value" :placeholder="placeholder" class="input input-bordered col-span-3 mt-2 w-full" />
|
||||||
</div>
|
</div>
|
||||||
@@ -50,6 +68,14 @@
|
|||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
|
maxLength: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
minLength: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const input = ref<HTMLElement | null>(null);
|
const input = ref<HTMLElement | null>(null);
|
||||||
|
|||||||
@@ -3,8 +3,16 @@
|
|||||||
<template #title> {{ $t("components.item.create_modal.title") }} </template>
|
<template #title> {{ $t("components.item.create_modal.title") }} </template>
|
||||||
<form @submit.prevent="create()">
|
<form @submit.prevent="create()">
|
||||||
<LocationSelector v-model="form.location" />
|
<LocationSelector v-model="form.location" />
|
||||||
<FormTextField ref="nameInput" v-model="form.name" :trigger-focus="focused" :autofocus="true" label="Item Name" />
|
<FormTextField
|
||||||
<FormTextArea v-model="form.description" label="Item Description" />
|
ref="nameInput"
|
||||||
|
v-model="form.name"
|
||||||
|
:trigger-focus="focused"
|
||||||
|
:autofocus="true"
|
||||||
|
label="Item Name"
|
||||||
|
:max-length="255"
|
||||||
|
:min-length="1"
|
||||||
|
/>
|
||||||
|
<FormTextArea v-model="form.description" label="Item Description" :max-length="1000" />
|
||||||
<FormMultiselect v-model="form.labels" label="Labels" :items="labels ?? []" />
|
<FormMultiselect v-model="form.labels" label="Labels" :items="labels ?? []" />
|
||||||
|
|
||||||
<div class="modal-action mb-6">
|
<div class="modal-action mb-6">
|
||||||
|
|||||||
@@ -8,8 +8,10 @@
|
|||||||
:trigger-focus="focused"
|
:trigger-focus="focused"
|
||||||
:autofocus="true"
|
:autofocus="true"
|
||||||
label="Label Name"
|
label="Label Name"
|
||||||
|
:max-length="255"
|
||||||
|
:min-length="1"
|
||||||
/>
|
/>
|
||||||
<FormTextArea v-model="form.description" label="Label Description" />
|
<FormTextArea v-model="form.description" label="Label Description" :max-length="255" />
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<BaseButton class="rounded-r-none" :loading="loading" type="submit"> {{ $t("global.create") }} </BaseButton>
|
<BaseButton class="rounded-r-none" :loading="loading" type="submit"> {{ $t("global.create") }} </BaseButton>
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
:autofocus="true"
|
:autofocus="true"
|
||||||
:required="true"
|
:required="true"
|
||||||
label="Location Name"
|
label="Location Name"
|
||||||
|
:max-length="255"
|
||||||
|
:min-length="1"
|
||||||
/>
|
/>
|
||||||
<FormTextArea v-model="form.description" label="Location Description" />
|
<FormTextArea v-model="form.description" label="Location Description" :max-length="1000" />
|
||||||
<LocationSelector v-model="form.parent" />
|
<LocationSelector v-model="form.parent" />
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
|
|||||||
@@ -96,6 +96,8 @@
|
|||||||
label: string;
|
label: string;
|
||||||
// key of ItemOut where the value is a string
|
// key of ItemOut where the value is a string
|
||||||
ref: keyof OnlyString<NoUndefinedField<ItemOut>>;
|
ref: keyof OnlyString<NoUndefinedField<ItemOut>>;
|
||||||
|
maxLength?: number;
|
||||||
|
minLength?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type NumberFormField = {
|
type NumberFormField = {
|
||||||
@@ -131,6 +133,8 @@
|
|||||||
type: "text",
|
type: "text",
|
||||||
label: "Name",
|
label: "Name",
|
||||||
ref: "name",
|
ref: "name",
|
||||||
|
maxLength: 255,
|
||||||
|
minLength: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "number",
|
type: "number",
|
||||||
@@ -141,26 +145,31 @@
|
|||||||
type: "textarea",
|
type: "textarea",
|
||||||
label: "Description",
|
label: "Description",
|
||||||
ref: "description",
|
ref: "description",
|
||||||
|
maxLength: 1000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
label: "Serial Number",
|
label: "Serial Number",
|
||||||
ref: "serialNumber",
|
ref: "serialNumber",
|
||||||
|
maxLength: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
label: "Model Number",
|
label: "Model Number",
|
||||||
ref: "modelNumber",
|
ref: "modelNumber",
|
||||||
|
maxLength: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
label: "Manufacturer",
|
label: "Manufacturer",
|
||||||
ref: "manufacturer",
|
ref: "manufacturer",
|
||||||
|
maxLength: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "textarea",
|
type: "textarea",
|
||||||
label: "Notes",
|
label: "Notes",
|
||||||
ref: "notes",
|
ref: "notes",
|
||||||
|
maxLength: 1000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
@@ -184,6 +193,7 @@
|
|||||||
type: "text",
|
type: "text",
|
||||||
label: "Purchased From",
|
label: "Purchased From",
|
||||||
ref: "purchaseFrom",
|
ref: "purchaseFrom",
|
||||||
|
maxLength: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
@@ -214,6 +224,7 @@
|
|||||||
type: "textarea",
|
type: "textarea",
|
||||||
label: "Warranty Notes",
|
label: "Warranty Notes",
|
||||||
ref: "warrantyDetails",
|
ref: "warrantyDetails",
|
||||||
|
maxLength: 1000,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -222,6 +233,7 @@
|
|||||||
type: "text",
|
type: "text",
|
||||||
label: "Sold To",
|
label: "Sold To",
|
||||||
ref: "soldTo",
|
ref: "soldTo",
|
||||||
|
maxLength: 255,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
@@ -480,12 +492,21 @@
|
|||||||
<div class="border-t border-gray-300 sm:p-0">
|
<div class="border-t border-gray-300 sm:p-0">
|
||||||
<div v-for="field in mainFields" :key="field.ref" class="grid grid-cols-1 sm:divide-y sm:divide-gray-300">
|
<div v-for="field in mainFields" :key="field.ref" class="grid grid-cols-1 sm:divide-y sm:divide-gray-300">
|
||||||
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
||||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
<FormTextArea
|
||||||
|
v-if="field.type === 'textarea'"
|
||||||
|
v-model="item[field.ref]"
|
||||||
|
:label="field.label"
|
||||||
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'text'"
|
v-else-if="field.type === 'text'"
|
||||||
v-model="item[field.ref]"
|
v-model="item[field.ref]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
inline
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
/>
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'number'"
|
v-else-if="field.type === 'number'"
|
||||||
@@ -522,7 +543,7 @@
|
|||||||
<!-- <FormSelect v-model:value="field.type" label="Field Type" :items="fieldTypes" value-key="value" /> -->
|
<!-- <FormSelect v-model:value="field.type" label="Field Type" :items="fieldTypes" value-key="value" /> -->
|
||||||
<FormTextField v-model="field.name" label="Name" />
|
<FormTextField v-model="field.name" label="Name" />
|
||||||
<div class="col-span-3 flex items-end">
|
<div class="col-span-3 flex items-end">
|
||||||
<FormTextField v-model="field.textValue" label="Value" />
|
<FormTextField v-model="field.textValue" label="Value" :max-length="500" />
|
||||||
<div class="tooltip" data-tip="Delete">
|
<div class="tooltip" data-tip="Delete">
|
||||||
<button class="btn btn-square btn-sm mb-2 ml-2" @click="item.fields.splice(idx, 1)">
|
<button class="btn btn-square btn-sm mb-2 ml-2" @click="item.fields.splice(idx, 1)">
|
||||||
<MdiDelete />
|
<MdiDelete />
|
||||||
@@ -604,12 +625,21 @@
|
|||||||
class="grid grid-cols-1 sm:divide-y sm:divide-gray-300"
|
class="grid grid-cols-1 sm:divide-y sm:divide-gray-300"
|
||||||
>
|
>
|
||||||
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
||||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
<FormTextArea
|
||||||
|
v-if="field.type === 'textarea'"
|
||||||
|
v-model="item[field.ref]"
|
||||||
|
:label="field.label"
|
||||||
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'text'"
|
v-else-if="field.type === 'text'"
|
||||||
v-model="item[field.ref]"
|
v-model="item[field.ref]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
inline
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
/>
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'number'"
|
v-else-if="field.type === 'number'"
|
||||||
@@ -646,12 +676,21 @@
|
|||||||
class="grid grid-cols-1 sm:divide-y sm:divide-gray-300"
|
class="grid grid-cols-1 sm:divide-y sm:divide-gray-300"
|
||||||
>
|
>
|
||||||
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
||||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
<FormTextArea
|
||||||
|
v-if="field.type === 'textarea'"
|
||||||
|
v-model="item[field.ref]"
|
||||||
|
:label="field.label"
|
||||||
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'text'"
|
v-else-if="field.type === 'text'"
|
||||||
v-model="item[field.ref]"
|
v-model="item[field.ref]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
inline
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
/>
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'number'"
|
v-else-if="field.type === 'number'"
|
||||||
@@ -684,12 +723,21 @@
|
|||||||
<div class="border-t border-gray-300 sm:p-0">
|
<div class="border-t border-gray-300 sm:p-0">
|
||||||
<div v-for="field in soldFields" :key="field.ref" class="grid grid-cols-1 sm:divide-y sm:divide-gray-300">
|
<div v-for="field in soldFields" :key="field.ref" class="grid grid-cols-1 sm:divide-y sm:divide-gray-300">
|
||||||
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
<div class="border-b border-gray-300 px-4 pb-4 pt-2 sm:px-6">
|
||||||
<FormTextArea v-if="field.type === 'textarea'" v-model="item[field.ref]" :label="field.label" inline />
|
<FormTextArea
|
||||||
|
v-if="field.type === 'textarea'"
|
||||||
|
v-model="item[field.ref]"
|
||||||
|
:label="field.label"
|
||||||
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'text'"
|
v-else-if="field.type === 'text'"
|
||||||
v-model="item[field.ref]"
|
v-model="item[field.ref]"
|
||||||
:label="field.label"
|
:label="field.label"
|
||||||
inline
|
inline
|
||||||
|
:max-length="field.maxLength"
|
||||||
|
:min-length="field.minLength"
|
||||||
/>
|
/>
|
||||||
<FormTextField
|
<FormTextField
|
||||||
v-else-if="field.type === 'number'"
|
v-else-if="field.type === 'number'"
|
||||||
|
|||||||
@@ -97,8 +97,14 @@
|
|||||||
<BaseModal v-model="updateModal">
|
<BaseModal v-model="updateModal">
|
||||||
<template #title> Update Label </template>
|
<template #title> Update Label </template>
|
||||||
<form v-if="label" @submit.prevent="update">
|
<form v-if="label" @submit.prevent="update">
|
||||||
<FormTextField v-model="updateData.name" :autofocus="true" label="Label Name" />
|
<FormTextField
|
||||||
<FormTextArea v-model="updateData.description" label="Label Description" />
|
v-model="updateData.name"
|
||||||
|
:autofocus="true"
|
||||||
|
label="Label Name"
|
||||||
|
:max-length="255"
|
||||||
|
:min-length="1"
|
||||||
|
/>
|
||||||
|
<FormTextArea v-model="updateData.description" label="Label Description" :max-length="255" />
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -111,8 +111,8 @@
|
|||||||
<BaseModal v-model="updateModal">
|
<BaseModal v-model="updateModal">
|
||||||
<template #title> Update Location </template>
|
<template #title> Update Location </template>
|
||||||
<form v-if="location" @submit.prevent="update">
|
<form v-if="location" @submit.prevent="update">
|
||||||
<FormTextField v-model="updateData.name" :autofocus="true" label="Location Name" />
|
<FormTextField v-model="updateData.name" :autofocus="true" label="Location Name" :max-length="255" :min-length="1" />
|
||||||
<FormTextArea v-model="updateData.description" label="Location Description" />
|
<FormTextArea v-model="updateData.description" label="Location Description" :max-length="1000" />
|
||||||
<LocationSelector v-model="parent" />
|
<LocationSelector v-model="parent" />
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
||||||
|
|||||||
Reference in New Issue
Block a user