|
11 | 11 | </div> |
12 | 12 | </div> |
13 | 13 |
|
14 | | - <div v-for="i in 5" :key="i" |
15 | | - class="flex items-center bg-lightForm dark:bg-darkForm border-b border-gray-100 dark:border-darkFormBorder" |
16 | | - :style="{ height: i === 2 ? '95px' : '75px' }" |
17 | | - > |
18 | | - <div class="w-[208px] flex-shrink-0 px-6 flex items-center gap-1"> |
| 14 | + <template v-for="column in visibleColumns" :key="column.name"> |
| 15 | + <div |
| 16 | + v-if="isMarkdownEditor(column)" |
| 17 | + class="flex items-start bg-lightForm dark:bg-darkForm border-b border-gray-100 dark:border-darkFormBorder" |
| 18 | + > |
| 19 | + <div class="w-[208px] flex-shrink-0 px-6 pt-7"> |
19 | 20 | <Skeleton class="w-24 h-[10px]" /> |
20 | 21 | </div> |
21 | | - |
22 | | - <div class="flex-1 px-6"> |
23 | | - <div v-if="i === 2"> |
24 | | - <Skeleton type="input" class="h-[42px] w-[160px]" /> |
25 | | - <Skeleton class="mt-1 h-[12px] w-20" /> |
26 | | - </div> |
27 | | - <Skeleton type="input" v-else-if="i === 4 || i === 5" class="h-[42px] w-[160px]" /> |
28 | | - <Skeleton v-else type="input" class="h-[42px] w-full" /> |
| 22 | + |
| 23 | + <div class="flex-1 px-6 pt-4 flex flex-col pb-6"> |
| 24 | + <div class="flex flex-wrap items-center gap-3 p-1.5 border border-gray-300 dark:border-gray-600 rounded-t-lg bg-gray-50 dark:bg-gray-800 w-full h-[46px]"> |
| 25 | + <template v-for="btn in skeletonButtons" :key="btn.id"> |
| 26 | + <div class="animate-pulse flex items-center justify-center h-8 px-1 text-gray-300 dark:text-gray-600"> |
| 27 | + <component :is="btn.icon" class="w-5 h-5" /> |
| 28 | + </div> |
| 29 | + <div v-if="btn.sep" class="w-px h-4 bg-gray-300 dark:bg-gray-600 mx-1"></div> |
| 30 | + </template> |
29 | 31 | </div> |
30 | | - </div> |
31 | 32 |
|
32 | | - <div class="flex items-start bg-lightForm dark:bg-darkForm" style="height: 759px;"> |
33 | | - <div class="w-[208px] flex-shrink-0 px-6 pt-7"> |
34 | | - <Skeleton class="w-24 h-[10px]" /> |
| 33 | + <div class="animate-pulse bg-white dark:bg-gray-950 border-x border-b border-gray-200 dark:border-gray-700 rounded-b-lg w-full h-[670px]"></div> |
| 34 | + </div> |
35 | 35 | </div> |
36 | | - |
37 | | - <div class="flex-1 px-6 pt-4 h-full flex flex-col"> |
38 | | - <div class="flex flex-wrap items-center gap-3 p-1.5 border border-gray-300 dark:border-gray-600 rounded-t-lg bg-gray-50 dark:bg-gray-800 w-full box-border h-[44px]"> |
39 | | - <template v-for="btn in skeletonButtons" :key="btn.id"> |
40 | | - <div class=" animate-pulse flex items-center justify-center h-8 px-1 text-gray-300 dark:text-gray-600"> |
41 | | - <component :is="btn.icon" class="w-5 h-5" /> |
42 | | - </div> |
43 | | - <div v-if="btn.sep" class="w-px h-4 bg-gray-300 dark:bg-gray-600 mx-1"></div> |
44 | | - </template> |
| 36 | + |
| 37 | + <div |
| 38 | + v-else |
| 39 | + class="flex items-center bg-lightForm dark:bg-darkForm border-b border-gray-100 dark:border-darkFormBorder" |
| 40 | + :style="{ height: getFieldHeight(column) }" |
| 41 | + > |
| 42 | + <div class="w-[208px] flex-shrink-0 px-6 flex items-center"> |
| 43 | + <Skeleton class="w-24 h-[10px]" /> |
| 44 | + </div> |
| 45 | + |
| 46 | + <div class="flex-1 px-6"> |
| 47 | + <Skeleton type="input" :class="getSkeletonInputClass(column)" /> |
| 48 | + |
| 49 | + <div v-if="hasEditingNote(column)" class="mt-1"> |
| 50 | + <Skeleton class="h-[12px] w-20" /> |
| 51 | + </div> |
45 | 52 | </div> |
46 | | - <div class="flex-1 animate-pulse bg-white dark:bg-gray-950 border-x border-b border-gray-200 dark:border-gray-700 rounded-b-lg w-full shadow-inner"></div> |
47 | | - <div class="h-10"></div> |
48 | 53 | </div> |
49 | | - </div> |
| 54 | + |
| 55 | + </template> |
50 | 56 | </div> |
51 | 57 | </div> |
52 | 58 | </template> |
53 | 59 |
|
54 | 60 | <script setup lang="ts"> |
55 | | -import { markRaw } from 'vue'; |
56 | | -import { IconExclamationCircleSolid } from '@iconify-prerendered/vue-flowbite'; |
57 | | -import { |
| 61 | +import { computed, markRaw } from 'vue'; |
| 62 | +import { |
58 | 63 | IconLinkOutline, IconCodeOutline, IconRectangleListOutline, |
59 | 64 | IconOrderedListOutline, IconLetterBoldOutline, IconLetterUnderlineOutline, |
60 | 65 | IconLetterItalicOutline, IconTextSlashOutline |
61 | 66 | } from '@iconify-prerendered/vue-flowbite'; |
62 | 67 | import { IconH116Solid, IconH216Solid, IconH316Solid } from '@iconify-prerendered/vue-heroicons'; |
63 | 68 | import { Skeleton } from '@/afcl'; |
64 | 69 |
|
| 70 | +interface Props { |
| 71 | + resource?: any; |
| 72 | + page?: string;} |
| 73 | +
|
| 74 | +const props = withDefaults(defineProps<Props>(), { |
| 75 | + page: 'edit' |
| 76 | +}); |
| 77 | +
|
| 78 | +const visibleColumns = computed(() => { |
| 79 | + if (!props.resource?.columns) return []; |
| 80 | +
|
| 81 | + return props.resource.columns.filter((col: any) => { |
| 82 | + if (col.virtual) return false; |
| 83 | + if (col.primaryKey) return false; |
| 84 | + if (col.backendOnly) return false; |
| 85 | + if (col.showIn?.[props.page] === false) return false; |
| 86 | + return true; |
| 87 | + }); |
| 88 | +}); |
| 89 | +
|
| 90 | +const isMarkdownEditor = (column: any) => column.name === 'description'; |
| 91 | +
|
| 92 | +const hasEditingNote = (column: any) => !!column.editingNote; |
| 93 | +
|
| 94 | +const getFieldHeight = (column: any) => |
| 95 | + hasEditingNote(column) ? '95px' : '75px'; |
| 96 | +
|
| 97 | +const getSkeletonInputClass = (column: any) => { |
| 98 | + if (['integer', 'decimal', 'float'].includes(column.type)) { |
| 99 | + return 'h-[42px] w-[160px]'; |
| 100 | + } |
| 101 | + return 'h-[42px] w-full'; |
| 102 | +}; |
| 103 | +
|
65 | 104 | const skeletonButtons = [ |
66 | 105 | { id: 'bold', icon: markRaw(IconLetterBoldOutline), sep: false }, |
67 | 106 | { id: 'italic', icon: markRaw(IconLetterItalicOutline), sep: false }, |
|
0 commit comments