11<template >
2- <div class =" text-sm text-gray-900 dark:text-white min-w-32" >
3- {{ limitedText }}
2+ <div class =" relative group flex items-center" @click.stop >
3+ <!-- Normal value display -->
4+ <div v-if =" !isEditing" class =" flex items-center" :class =" limitedText?.length > 50 ? 'min-w-48 max-w-full' : 'min-w-32'" >
5+ {{ limitedText? limitedText : '-' }}
6+
7+ <span v-if =" meta?.reviewedCheckboxesFieldName && limitedText" class =" flex items-center ml-2" >
8+ <Tooltip
9+ >
10+ <template #tooltip >
11+ {{ record[meta?.reviewedCheckboxesFieldName]?.[props.column.name] ? t('Translation is reviewed') : t('Translation is not reviewed') }}
12+ </template >
13+ <IconCheckOutline
14+ v-if =" record[meta?.reviewedCheckboxesFieldName]?.[props.column.name]"
15+ class =" w-5 h-5 text-green-500"
16+ />
17+ <IconQuestionCircleSolid
18+ v-else
19+ class =" w-5 h-5 text-yellow-500"
20+ />
21+ </Tooltip >
22+ </span >
23+
24+ <button
25+ v-if =" !column.editReadonly"
26+ @click =" startEdit"
27+ class =" ml-2 opacity-0 group-hover:opacity-100 transition-opacity"
28+ >
29+ <IconPenSolid class =" w-5 h-5 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300" />
30+ </button >
31+ </div >
32+
33+ <!-- Edit mode -->
34+ <div v-else class =" flex flex-col gap-2" >
35+ <div class =" flex items-center max-w-full gap-2"
36+ :class =" limitedText?.length > 50 ? 'min-w-72' : 'min-w-64'"
37+ ref =" inputHolder"
38+ >
39+ <ColumnValueInputWrapper
40+ class =" flex-grow"
41+ ref =" input"
42+ :source =" 'edit'"
43+ :column =" column"
44+ :currentValues =" currentValues"
45+ :mode =" mode"
46+ :columnOptions =" columnOptions"
47+ :unmasked =" unmasked"
48+ :setCurrentValue =" setCurrentValue"
49+ />
50+ <div class =" flex gap-1" >
51+ <button
52+ @click =" saveEdit"
53+ :disabled =" saving || (originalReviewed === reviewed && originalValue === currentValues[props.column.name])"
54+ class =" text-green-600 hover:text-green-700 dark:text-green-500 dark:hover:text-green-400 disabled:opacity-50"
55+
56+ >
57+ <IconCheckOutline class =" w-5 h-5" />
58+ </button >
59+ <button
60+ @click =" cancelEdit"
61+ :disabled =" saving"
62+ class =" text-red-600 hover:text-red-700 dark:text-red-500 dark:hover:text-red-400"
63+ >
64+ <IconXOutline class =" w-5 h-5" />
65+ </button >
66+ </div >
67+ </div >
68+ <div v-if =" meta?.reviewedCheckboxesFieldName" >
69+ <label class =" text-sm text-gray-500 dark:text-gray-400 flex items-center gap-0 cursor-pointer select-none" >
70+ <Checkbox
71+ v-model =" reviewed"
72+ :disabled =" saving"
73+ />
74+ {{ t('Translation is reviewed') }}
75+ </label >
76+
77+ </div >
78+ </div >
79+
480 </div >
581</template >
682
783<script setup lang="ts">
8- import { computed } from ' vue' ;
9- import { AdminForthResourceColumnCommon , AdminForthResourceCommon , AdminUser } from ' @/types/Common' ;
84+ import { ref , Ref , computed , nextTick } from ' vue' ;
85+ import { IconPenSolid , IconCheckOutline , IconXOutline , IconQuestionCircleSolid } from ' @iconify-prerendered/vue-flowbite' ;
86+ import { callAdminForthApi } from ' @/utils' ;
87+ import { showErrorTost , showSuccesTost } from ' @/composables/useFrontendApi' ;
88+ import ColumnValueInputWrapper from ' @/components/ColumnValueInputWrapper.vue' ;
89+ import { useI18n } from ' vue-i18n' ;
90+ import Tooltip from ' @/afcl/Tooltip.vue' ;
91+ import Checkbox from ' @/afcl/Checkbox.vue' ;
1092
93+ const { t } = useI18n ();
94+ const props = defineProps ([' column' , ' record' , ' resource' , ' adminUser' , ' meta' ]);
95+ const isEditing = ref (false );
96+ const editValue = ref (null );
97+ const saving = ref (false );
98+ const input = ref (null );
99+ const columnOptions = ref ({});
100+ const mode = ref (' edit' );
101+ const currentValues = ref ({});
102+ const unmasked = ref ({});
103+
104+ const inputHolder = ref (null );
11105
12106const limitedText = computed (() => {
13107 const text = props .record [props .column .name ];
14108 return text ?.length > 50 ? text .slice (0 , 50 ) + ' ...' : text ;
15109});
16110
17- const props = defineProps <{
18- column: AdminForthResourceColumnCommon ;
19- record: any ;
20- meta: any ;
21- resource: AdminForthResourceCommon ;
22- adminUser: AdminUser ;
23- }>();
111+ const reviewed: Ref <boolean > = ref (false );
112+
113+
114+ const originalReviewed = ref (false );
115+ const originalValue = ref (null );
116+
117+ async function startEdit() {
118+ const value = props .record [props .column .name ];
119+ currentValues .value = {
120+ [props .column .name ]: props .column .isArray ?.enabled
121+ ? (Array .isArray (value ) ? value : [value ]).filter (v => v !== null && v !== undefined )
122+ : value ,
123+ };
124+ reviewed .value = props .record [props .meta ?.reviewedCheckboxesFieldName ]?.[props .column .name ] || false ;
125+ originalReviewed .value = reviewed .value ;
126+ originalValue .value = value ;
127+ isEditing .value = true ;
128+ await nextTick ();
129+ if (inputHolder .value ) {
130+ inputHolder .value .querySelector (' input, textarea, select' )?.focus ();
131+ }
132+ }
133+
134+ function cancelEdit() {
135+ isEditing .value = false ;
136+ editValue .value = null ;
137+ }
138+
139+ function setCurrentValue(field , value , arrayIndex = undefined ) {
140+ if (arrayIndex !== undefined && props .column .isArray ?.enabled ) {
141+ // Handle array updates
142+ if (! Array .isArray (currentValues .value [field ])) {
143+ currentValues .value [field ] = [];
144+ }
145+
146+ const newArray = [... currentValues .value [field ]];
147+
148+ if (arrayIndex >= newArray .length ) {
149+ // When adding a new item, always add null
150+ newArray .push (null );
151+ } else {
152+ // For existing items, handle type conversion
153+ if (props .column .isArray ?.itemType && [' integer' , ' float' , ' decimal' ].includes (props .column .isArray .itemType )) {
154+ newArray [arrayIndex ] = value !== null && value !== ' ' ? + value : null ;
155+ } else {
156+ newArray [arrayIndex ] = value ;
157+ }
158+ }
159+
160+ // Assign the new array
161+ currentValues .value [field ] = newArray ;
162+ editValue .value = newArray ;
163+ } else {
164+ // Handle non-array updates
165+ currentValues .value [field ] = value ;
166+ editValue .value = value ;
167+ }
168+ }
169+
170+ async function saveEdit() {
171+ saving .value = true ;
172+ try {
173+ const result = await callAdminForthApi ({
174+ method: ' POST' ,
175+ path: ` /plugin/${props .meta .pluginInstanceId }/update-field ` ,
176+ body: {
177+ resourceId: props .resource .resourceId ,
178+ recordId: props .record ._primaryKeyValue ,
179+ field: props .column .name ,
180+ value: currentValues .value [props .column .name ],
181+ reviewed: reviewed .value ,
182+ }
183+ });
184+
185+ if (result .error ) {
186+ showErrorTost (result .error );
187+ return ;
188+ }
24189
25- </script >
190+ showSuccesTost (t (' Field updated successfully' ));
191+ props .record [props .column .name ] = result .record [props .column .name ];
192+ if (props .meta ?.reviewedCheckboxesFieldName ) {
193+ props .record [props .meta ?.reviewedCheckboxesFieldName ] = result .record [props .meta ?.reviewedCheckboxesFieldName ];
194+ }
195+ isEditing .value = false ;
196+ } finally {
197+ saving .value = false ;
198+ }
199+ }
200+ </script >
0 commit comments