Skip to content

Commit

Permalink
fix: improve UX for long-strings translation: autoconvert multiline/s…
Browse files Browse the repository at this point in the history
…ingle-line input, crop too long strings from table
  • Loading branch information
ivictbor committed Feb 1, 2025
1 parent 9c6e19e commit f6fd4e7
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
25 changes: 25 additions & 0 deletions custom/ListCell.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<div class="text-sm text-gray-900 dark:text-white min-w-32">
{{ limitedText }}
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { AdminForthResourceColumnCommon, AdminForthResourceCommon, AdminUser } from '@/types/Common';
const limitedText = computed(() => {
const text = props.record[props.column.name];
return text?.length > 50 ? text.slice(0, 50) + '...' : text;
});
const props = defineProps<{
column: AdminForthResourceColumnCommon;
record: any;
meta: any;
resource: AdminForthResourceCommon;
adminUser: AdminUser;
}>();
</script>
76 changes: 76 additions & 0 deletions custom/SingleMultiInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<Input
ref="input"
v-if="shortValue"
class="w-full"
:modelValue="props.record[props.column.name]"
:disabled="props.column.editReadonly"
@update:modelValue="($event) => emit('update:value', $event)" />
<textarea
v-else
ref="textarea"
:disabled="props.column.editReadonly"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5
dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary"
:value="props.record[props.column.name]"
@input="($event) => { autoResizeTextArea(); emit('update:value', $event.target.value) }" />

</template>

<script setup lang="ts">
import { Input } from "@/afcl";
import type {
AdminForthResourceColumnCommon,
AdminForthResourceCommon,
AdminUser,
} from "@/types/Common";
import { computed, defineProps, defineEmits, type Ref, watch, nextTick, ref, onMounted } from "vue";
const shortValue: Ref<boolean> = computed(() => (props.record[props.column.name]?.length || 0) < 50);
const props = defineProps<{
column: AdminForthResourceColumnCommon;
record: any;
meta: any;
resource: AdminForthResourceCommon;
adminUser: AdminUser;
}>();
const emit = defineEmits(["update:value"]);
const input: Ref<HTMLInputElement | HTMLTextAreaElement | null> = ref(null);
const textarea: Ref<HTMLInputElement | HTMLTextAreaElement | null> = ref(null);
// Auto resize function
const autoResizeTextArea = () => {
// Use nextTick to ensure the DOM update is done before measuring
nextTick(() => {
if (!textarea.value) return
// Reset the height to shrink if content is removed
textarea.value.style.height = 'auto'
// Set it to the scrollHeight to make it grow
textarea.value.style.height = textarea.value.scrollHeight + 3 + 'px'
})
}
watch(() => shortValue.value, async () => {
await nextTick();
if (shortValue.value) {
input.value?.focus();
} else {
textarea.value?.focus();
await nextTick();
autoResizeTextArea();
}
});
onMounted(async () => {
if (!shortValue.value) {
await nextTick();
autoResizeTextArea();
}
});
</script>

4 changes: 2 additions & 2 deletions custom/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"paths": {
"@/*": [
// "node_modules/adminforth/dist/spa/src/*"
"../../../spa/src/*"
"../../../adminforth/spa/src/*"
],
"*": [
// "node_modules/adminforth/dist/spa/node_modules/*"
"../../../spa/node_modules/*"
"../../../adminforth/spa/node_modules/*"
],
"@@/*": [
// "node_modules/adminforth/dist/spa/src/*"
Expand Down
25 changes: 25 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ export default class I18nPlugin extends AdminForthPlugin {
throw new Error(`Field ${this.trFieldNames[lang]} not found for storing translation for language ${lang}
in resource ${resourceConfig.resourceId}, consider adding it to columns or change trFieldNames option to remap it to existing column`);
}

column.components = column.components || {};

// set edit and create custom component - SingleMultiInput.vue
column.components.edit = {
file: this.componentPath('SingleMultiInput.vue'),
};
column.components.create = {
file: this.componentPath('SingleMultiInput.vue'),
};

// set ListCell for list
column.components.list = {
file: this.componentPath('ListCell.vue'),
};
}

this.enFieldName = this.trFieldNames['en'] || 'en_string';
Expand All @@ -186,6 +201,16 @@ export default class I18nPlugin extends AdminForthPlugin {
throw new Error(`Field ${this.enFieldName} not found column to store english original string in resource ${resourceConfig.resourceId}`);
}

enColumn.components = enColumn.components || {};
enColumn.components.edit = {
file: this.componentPath('SingleMultiInput.vue'),
};
enColumn.components.create = {
file: this.componentPath('SingleMultiInput.vue'),
};
enColumn.components.list = {
file: this.componentPath('ListCell.vue'),
};
enColumn.editReadonly = true;

// if sourceFieldName defined, check it exists
Expand Down

0 comments on commit f6fd4e7

Please sign in to comment.