Skip to content

Commit 169487e

Browse files
Merge pull request #108 from gormurad/develop
Develop
2 parents bb9161b + 060aa15 commit 169487e

File tree

13 files changed

+4345
-94
lines changed

13 files changed

+4345
-94
lines changed

structures-frontend-next/package-lock.json

Lines changed: 4062 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

structures-frontend-next/src/components/CrudTable.vue

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ class CrudTable extends Vue {
5959
@Prop({ default: false }) enableViewSwitcher!: boolean
6060
@Prop({ default: 'No items yet' }) emptyStateText!: string
6161
@Prop({ default: '' }) search!: string
62+
@Prop({ default: true }) showPagination!: boolean
63+
@Prop({ default: true }) enableRowHover!: boolean;
64+
65+
getRowClass() {
66+
return {
67+
'dynamic-hover': this.enableRowHover,
68+
'transition-all': true,
69+
};
70+
}
71+
6272
6373
items: DescriptiveIdentifiable[] = []
6474
totalItems = 0
@@ -97,6 +107,8 @@ class CrudTable extends Vue {
97107
}
98108
99109
mounted() {
110+
console.log(this.showPagination, "VVVVVVVVVVVVVVVVV")
111+
console.log(this.items.length, "kasjdlsajdksajdl")
100112
const urlSearch = (this.$route.query.search as string) || ''
101113
this.loading = true
102114
this.initialSearchCompleted = false
@@ -205,7 +217,10 @@ class CrudTable extends Vue {
205217
this.totalItems = page.totalElements ?? 0
206218
this.items = page.content ?? []
207219
this.initialSearchCompleted = true
220+
221+
this.$emit('items-count', this.items.length)
208222
})
223+
209224
.catch((error: unknown) => {
210225
console.error('[CRUD Table Alert]:', error)
211226
this.loading = false
@@ -223,20 +238,21 @@ export default toNative(CrudTable)
223238
<template #start>
224239
<IconField class="w-full max-w-sm">
225240
<InputIcon class="pi pi-search" />
226-
<InputText v-model="searchText" placeholder="Search" @input="onSearchChange" @keyup.enter="find" />
241+
<InputText v-model="searchText" placeholder="Search" size="small" @input="onSearchChange"
242+
@keyup.enter="find" />
227243
</IconField>
228244
</template>
229245

230246
<template #end>
231247
<div class="flex items-center gap-2 h-[33px]">
232-
<SelectButton v-if="enableViewSwitcher" v-model="activeView" :options="viewOptions" optionValue="value"
233-
dataKey="value" class="h-[33px]">
248+
<SelectButton size="small" v-if="enableViewSwitcher" v-model="activeView" :options="viewOptions"
249+
optionValue="value" dataKey="value">
234250
<template #option="slotProps">
235251
<i :class="slotProps.option.icon"></i>
236252
</template>
237253
</SelectButton>
238-
<Button v-if="!disableModifications && isShowAddNew" @click="addItem" :label="createNewButtonText"
239-
icon="pi pi-plus" class="h-[33px]" />
254+
<Button size="small" v-if="!disableModifications && isShowAddNew" @click="addItem"
255+
:label="createNewButtonText" icon="pi pi-plus" />
240256
</div>
241257
</template>
242258
</Toolbar>
@@ -245,38 +261,56 @@ export default toNative(CrudTable)
245261
<div v-if="isColumnView">
246262
<div v-if="items.length > 0" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
247263
<Card v-for="(item, index) in items" :key="item.id || index"
248-
class="cursor-pointer hover:shadow-md transition-shadow h-[152px] flex flex-col justify-between"
264+
class="cursor-pointer relative hover:shadow-md transition-shadow h-[170px] flex flex-col justify-between"
249265
@click="handleCardClick(item, index)">
266+
<template #title>
267+
<h3 class="">{{ item?.id }}</h3>
268+
</template>
269+
250270
<template #content>
251-
<div>
252-
<h3 class="font-semibold text-[#101010] mb-1">{{ item?.id }}</h3>
253-
<p class="text-sm text-gray-500 truncate">{{ item?.description }}</p>
254-
</div>
255-
<div class="flex gap-2 mt-3">
256-
<Button severity="secondary" text class="p-2"
271+
<p class="truncate-multiline max-h-[46px]">{{ item?.description }}</p>
272+
273+
</template>
274+
275+
<template #footer>
276+
<div class="flex p-5 gap-4 absolute bottom-0 left-0">
277+
<Button severity="secondary" text class="!p-0"
257278
@click.stop="$router.push({ path: '/graphql', query: { namespace: item.id } })">
258279
<img src="@/assets/graphql.svg" alt="GraphQL" class="w-5 h-5" />
259280
</Button>
260-
<Button severity="secondary" text class="p-2"
281+
<Button severity="secondary" text class="!p-0"
261282
@click.stop="$router.push('/scalar-ui.html?namespace=' + item.id)">
262283
<img src="@/assets/scalar.svg" alt="OpenAPI" class="w-5 h-5" />
263284
</Button>
264285
</div>
265286
</template>
266287
</Card>
288+
267289
</div>
268290
<div v-else class="flex flex-col items-center justify-center text-gray-500 py-20 h-[calc(100vh-300px)]">
269291
<p class="text-sm">{{ emptyStateText }}</p>
270292
</div>
271293

272294
<Paginator :rows="options.rows" :totalRecords="totalItems" @page="onPaginatorPage" class="mt-4"
273-
v-if="items.length !== 0" />
295+
v-if="showPagination" />
274296
</div>
275297

276298
<div v-if="isBurgerView" class="p-4 border text-[color:var(--surface-200)] rounded-xl">
277-
<DataTable :value="items" :rows="options.rows" :totalRecords="totalItems" :loading="loading"
278-
:paginator="items.length > 0" :first="options.first" :rowsPerPageOptions="[5, 10, 20]" dataKey="id"
279-
@page="onDataTablePage" @row-click="onRowClick" sortMode="multiple" table>
299+
<DataTable
300+
:value="items"
301+
:rows="options.rows"
302+
:totalRecords="totalItems"
303+
:loading="loading"
304+
:paginator="showPagination"
305+
:first="options.first"
306+
:rowsPerPageOptions="[5, 10, 20]"
307+
dataKey="id"
308+
@page="onDataTablePage"
309+
@row-click="onRowClick"
310+
sortMode="multiple"
311+
:rowClass="getRowClass"
312+
313+
>
280314
<Column v-for="col in computedHeaders" :key="col.field" :field="col.field" :header="col.header"
281315
:sortable="col.sortable !== false">
282316
<template #body="slotProps">
@@ -316,4 +350,17 @@ export default toNative(CrudTable)
316350
border: none !important;
317351
box-shadow: none !important;
318352
}
353+
354+
.truncate-multiline {
355+
display: -webkit-box;
356+
-webkit-line-clamp: 2;
357+
-webkit-box-orient: vertical;
358+
overflow: hidden;
359+
}
360+
361+
.dynamic-hover:hover {
362+
cursor: pointer;
363+
background-color: var(--row-hover-color, #eff6ff) !important;
364+
transition: background-color 0.3s ease !important;
365+
}
319366
</style>

structures-frontend-next/src/components/ProjectList.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { IDataSource, Identifiable, IterablePage, Pageable } from '@kinotic
77
import { APPLICATION_STATE } from '@/states/IApplicationState'
88
import { Project, Structures } from '@kinotic/structures-api'
99
import type { CrudHeader } from '@/types/CrudHeader'
10+
import DatetimeUtil from "@/util/DatetimeUtil"
1011
1112
@Component({
1213
components: { CrudTable, NewProjectSidebar, ProjectStructuresTable }
@@ -63,7 +64,7 @@ export default class ProjectList extends Vue {
6364
get projectsCount() {
6465
return APPLICATION_STATE.projectsCount
6566
}
66-
67+
public DatetimeUtil = DatetimeUtil
6768
refreshTable(): void {
6869
this.crudTable?.find?.()
6970
}
@@ -140,11 +141,16 @@ export default class ProjectList extends Vue {
140141
createNewButtonText="New Project"
141142
emptyStateText="No projects yet"
142143
:isShowAddNew="true"
144+
class="!text-sm"
143145
>
144146
<template #item.id="{ item }">
145147
<span>{{ item.id }}</span>
146148
</template>
147-
149+
<template #item.updated="{ item }">
150+
<span>
151+
{{ DatetimeUtil.formatRelativeDate(item.updated) }}
152+
</span>
153+
</template>
148154
<template #additional-actions="{ item }">
149155
<Button text class="!text-[#334155] !bg-white" title="GraphQL">
150156
<RouterLink :to="{ path: '/graphql', query: { namespace: item.id } }">

structures-frontend-next/src/components/ProjectStructuresTable.vue

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Structure, Structures } from '@kinotic/structures-api'
66
import type { CrudHeader } from '@/types/CrudHeader'
77
import { APPLICATION_STATE } from '@/states/IApplicationState'
88
import type { Identifiable, IterablePage, Pageable } from '@kinotic/continuum-client'
9+
import DatetimeUtil from "@/util/DatetimeUtil"
910
1011
@Component({
1112
components: { CrudTable, StructureItemModal }
@@ -30,6 +31,7 @@ export default class ProjectStructuresTable extends Vue {
3031
showModal = false
3132
selectedStructure: Structure | null = null
3233
isInitialized = false
34+
public DatetimeUtil = DatetimeUtil
3335
3436
mounted() {
3537
this.searchText = (this.$route.query['search-structure'] as string) || ''
@@ -137,10 +139,21 @@ export default class ProjectStructuresTable extends Vue {
137139
@onRowClick="handleRowClick"
138140
createNewButtonText="New Structure"
139141
emptyStateText="No structures yet for this project"
142+
class="!text-sm"
140143
>
141144
<template #item.name="{ item }">
142145
<span class="font-semibold">{{ item.name }}</span>
143146
</template>
147+
<template #item.created="{ item }">
148+
<span>
149+
{{ DatetimeUtil.formatMonthDayYear(item.created) }}
150+
</span>
151+
</template>
152+
<template #item.updated="{ item }">
153+
<span>
154+
{{ DatetimeUtil.formatRelativeDate(item.updated) }}
155+
</span>
156+
</template>
144157
<template #item.description="{ item }">
145158
<span>{{ item.description }}</span>
146159
</template>

structures-frontend-next/src/components/SideBar.vue

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default class Sidebar extends Vue {
4646
4747
navigateTo(path: string) {
4848
if (this.route.path !== path) {
49-
this.router.push(path)
49+
this.router.push(path)
5050
}
5151
}
5252
@@ -70,38 +70,33 @@ export default class Sidebar extends Vue {
7070
})) as Array<{ icon: string; label: string; path: string }>
7171
}
7272
}
73+
74+
isActive(path: string): boolean {
75+
return this.route.path === path
76+
}
7377
}
7478
</script>
7579

7680
<template>
77-
<div
78-
:class="[
79-
'bg-surface-50 fixed top-[64px] left-0 z-40 flex flex-col justify-between px-4 py-4 h-[calc(100vh-64px)]',
80-
'transition-[width] duration-300 ease-in-out',
81-
collapsed ? 'w-[64px]' : 'w-[256px]'
82-
]"
83-
>
84-
<div class="flex flex-col gap-2 w-full">
85-
<SidebarItem
86-
v-for="item in sidebarItems"
87-
:key="item.path"
88-
:icon="item.icon"
89-
:label="item.label"
90-
:collapsed="collapsed"
91-
@click="navigateTo(item.path)"
92-
/>
93-
</div>
81+
<div class="p-2 fixed rounded-xl top-[64px] left-0 z-40 h-[calc(100vh-64px)]"
82+
:class="[collapsed ? 'w-[64px]' : 'w-[256px]']">
83+
<div :class="['bg-surface-50 rounded-xl flex flex-col justify-between px-4 py-4 h-full', 'transition-[width] duration-300 ease-in-out w-full']">
84+
<div class="flex flex-col w-full">
85+
<SidebarItem
86+
v-for="item in sidebarItems"
87+
:key="item.path"
88+
:icon="item.icon"
89+
:label="item.label"
90+
:collapsed="collapsed"
91+
:path="item.path"
92+
:isActive="isActive(item.path)"
93+
@click="navigateTo(item.path)"
94+
/>
95+
</div>
9496

95-
<div
96-
@click="toggleSidebar"
97-
class="cursor-pointer p-2 hover:bg-gray-200 rounded-lg transition max-w-max"
98-
>
99-
<img
100-
:src="collapsed ? strExpand : strCollapse"
101-
alt="Toggle Sidebar"
102-
class="w-5 h-5 transition-transform duration-300"
103-
:class="collapsed ? 'rotate-180' : ''"
104-
/>
97+
<div @click="toggleSidebar" class="cursor-pointer p-2 hover:bg-gray-200 rounded-lg transition max-w-max">
98+
<img :src="collapsed ? strExpand : strCollapse" alt="Toggle Sidebar" class="w-5 h-5 transition-transform duration-300" :class="collapsed ? 'rotate-180' : ''"/>
99+
</div>
105100
</div>
106101
</div>
107102
</template>

structures-frontend-next/src/components/SidebarItem.vue

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,42 @@
1-
<!-- SidebarItem.vue -->
21
<script setup lang="ts">
32
import { computed } from 'vue'
43
54
const props = defineProps<{
65
icon: string,
76
label: string,
87
collapsed: boolean,
9-
textColor?: string
8+
textColor?: string,
9+
path: string,
10+
isActive: boolean
1011
}>()
1112
12-
const textClass = computed(() => props.textColor ?? 'text-black')
13+
const textClass = computed(() => {
14+
return props.isActive ? 'text-surface-800' : 'text-surface-500';
15+
});
16+
17+
const iconClass = computed(() => {
18+
return props.isActive ? 'text-primary-500' : 'text-surface-500';
19+
});
1320
</script>
1421

1522
<template>
1623
<div
17-
class="flex items-center px-[10px] py-[9px] mb-[7px] cursor-pointer w-full rounded-md hover:bg-gray-200 transition-colors duration-200"
24+
:class="[
25+
'flex items-center py-[9px] cursor-pointer w-full rounded-md hover:bg-surface-200 p-2 transition-colors duration-200',
26+
props.isActive ? '' : 'bg-transparent'
27+
]"
28+
@click="$emit('click')"
1829
>
1930
<div class="min-w-[20px] flex justify-center">
20-
<i :class="['pi', icon, 'text-base']" />
31+
<i :class="['pi', icon, 'text-base', iconClass]" />
2132
</div>
2233
<div class="w-[8px]"></div>
2334
<div class="overflow-hidden">
2435
<span
25-
:class="[
26-
'inline-block whitespace-nowrap text-sm font-normal transform transition-all duration-300 origin-left',
27-
textClass,
28-
collapsed ? 'opacity-0 scale-x-0' : 'opacity-100 scale-x-100'
36+
:class="[
37+
'inline-block whitespace-nowrap text-sm font-normal transform transition-all duration-300 origin-left',
38+
textClass,
39+
props.collapsed ? 'opacity-0 scale-x-0' : 'opacity-100 scale-x-100'
2940
]"
3041
>
3142
{{ label }}

0 commit comments

Comments
 (0)