@blueprint-ts/core 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/docs/vue/requests/route-resource-binding.md +193 -25
- package/package.json +1 -1
- package/src/service/pagination/BasePaginator.ts +36 -0
- package/src/service/pagination/InfiniteScroller.ts +2 -2
- package/src/service/pagination/PageAwarePaginator.ts +124 -0
- package/src/service/pagination/Paginator.ts +9 -147
- package/src/service/pagination/StatePaginator.ts +92 -0
- package/src/service/pagination/contracts/BaseViewDriverContract.ts +6 -0
- package/src/service/pagination/contracts/BaseViewDriverFactoryContract.ts +5 -0
- package/src/service/pagination/contracts/StatePaginationDataDriverContract.ts +5 -0
- package/src/service/pagination/contracts/ViewDriverContract.ts +3 -5
- package/src/service/pagination/dtos/StatePaginationDataDto.ts +19 -0
- package/src/service/pagination/factories/VueBaseViewDriverFactory.ts +9 -0
- package/src/service/pagination/frontendDrivers/VueBaseViewDriver.ts +28 -0
- package/src/service/pagination/index.ts +34 -2
- package/src/vue/router/routeResourceBinding/RouteResourceBoundView.ts +145 -0
- package/src/vue/router/routeResourceBinding/defineRoute.ts +29 -1
- package/src/vue/router/routeResourceBinding/index.ts +2 -1
- package/src/vue/router/routeResourceBinding/installRouteInjection.ts +86 -15
- package/src/vue/router/routeResourceBinding/types.ts +6 -1
- package/src/vue/router/routeResourceBinding/useRouteResource.ts +17 -7
- package/tests/vue/router/routeResourceBinding/RouteResourceBoundView.test.ts +344 -0
- package/tests/vue/router/routeResourceBinding/installRouteInjection.test.ts +450 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## v2.0.0 - 2026-02-18
|
|
2
|
+
|
|
3
|
+
# [2.0.0](/compare/v1.2.0...v2.0.0) (2026-02-18)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Cache resolved route resources for child routes db70b77
|
|
9
|
+
## v1.2.0 - 2026-01-25
|
|
10
|
+
|
|
11
|
+
# [1.2.0](/compare/v1.1.2...v1.2.0) (2026-01-25)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* Added state paginator feature 87a9466
|
|
1
17
|
## v1.1.2 - 2026-01-09
|
|
2
18
|
|
|
3
19
|
## [1.1.2](/compare/v1.1.1...v1.1.2) (2026-01-09)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Route
|
|
1
|
+
# Route Resource Binding
|
|
2
2
|
|
|
3
3
|
When using `vue-router`, you can automatically bind route parameters to resources, similar to how Laravel's route model binding works.
|
|
4
4
|
|
|
@@ -7,60 +7,228 @@ When using `vue-router`, you can automatically bind route parameters to resource
|
|
|
7
7
|
To enable the router to load resources automatically, install the route injection plugin when initializing your router:
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
+
import { installRouteInjection } from '@blueprint-ts/core'
|
|
11
|
+
|
|
10
12
|
installRouteInjection(router)
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## Defining Routes
|
|
14
16
|
|
|
15
17
|
Use the `defineRoute` helper to define your routes and specify which parameters should be resolved into resources:
|
|
16
18
|
|
|
17
19
|
```ts
|
|
18
|
-
defineRoute
|
|
20
|
+
import { defineRoute, RouteResourceRequestResolver } from '@blueprint-ts/core'
|
|
21
|
+
import ProductDetailPage from '@/pages/ProductDetailPage.vue'
|
|
22
|
+
|
|
23
|
+
export default defineRoute<{
|
|
19
24
|
product: ProductResource
|
|
20
25
|
}>()({
|
|
21
26
|
path: ':productId',
|
|
22
27
|
name: 'products.show',
|
|
23
28
|
component: ProductDetailPage,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
32
|
-
}
|
|
29
|
+
inject: {
|
|
30
|
+
product: {
|
|
31
|
+
from: 'productId',
|
|
32
|
+
resolve: (productId: string) => {
|
|
33
|
+
return new RouteResourceRequestResolver(
|
|
34
|
+
new ProductShowRequest(productId)
|
|
35
|
+
)
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
})
|
|
37
40
|
```
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
Navigation is **non-blocking** — the route navigates immediately while resources resolve in the background. Cached values are reused when navigating between child routes with unchanged parameters.
|
|
40
43
|
|
|
41
44
|
## Usage in Components
|
|
42
45
|
|
|
43
|
-
Your component can
|
|
46
|
+
Your component can directly access the resolved resource via props:
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<script setup lang="ts">
|
|
50
|
+
const props = defineProps<{
|
|
51
|
+
product: ProductResource
|
|
52
|
+
}>()
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Handling Loading & Error States
|
|
57
|
+
|
|
58
|
+
### Using `RouteResourceBoundView`
|
|
59
|
+
|
|
60
|
+
`RouteResourceBoundView` is a drop-in replacement for `<RouterView>` that automatically handles loading and error states. Define error and loading components directly in the route:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { defineRoute, RouteResourceRequestResolver } from '@blueprint-ts/core'
|
|
64
|
+
import ProductDetailPage from '@/pages/ProductDetailPage.vue'
|
|
65
|
+
import GenericErrorPage from '@/pages/GenericErrorPage.vue'
|
|
66
|
+
import LoadingSpinner from '@/components/LoadingSpinner.vue'
|
|
67
|
+
|
|
68
|
+
export default defineRoute<{
|
|
69
|
+
product: ProductResource
|
|
70
|
+
}>()({
|
|
71
|
+
path: ':productId',
|
|
72
|
+
name: 'products.show',
|
|
73
|
+
component: ProductDetailPage,
|
|
74
|
+
errorComponent: GenericErrorPage,
|
|
75
|
+
loadingComponent: LoadingSpinner,
|
|
76
|
+
inject: {
|
|
77
|
+
product: {
|
|
78
|
+
from: 'productId',
|
|
79
|
+
resolve: (productId: string) => {
|
|
80
|
+
return new RouteResourceRequestResolver(
|
|
81
|
+
new ProductShowRequest(productId)
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Then replace `<RouterView>` with `<RouteResourceBoundView>` in your layout:
|
|
90
|
+
|
|
91
|
+
```vue
|
|
92
|
+
<template>
|
|
93
|
+
<RouteResourceBoundView />
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<script setup lang="ts">
|
|
97
|
+
import { RouteResourceBoundView } from '@blueprint-ts/core'
|
|
98
|
+
</script>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The `errorComponent` receives `error` and `refresh` as props. The `refresh` function retries all failed resources:
|
|
102
|
+
|
|
103
|
+
```vue
|
|
104
|
+
<!-- GenericErrorPage.vue -->
|
|
105
|
+
<template>
|
|
106
|
+
<div>
|
|
107
|
+
<p>{{ error.message }}</p>
|
|
108
|
+
<button @click="refresh">Try Again</button>
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<script setup lang="ts">
|
|
113
|
+
defineProps<{
|
|
114
|
+
error: Error
|
|
115
|
+
refresh: () => Promise<void>
|
|
116
|
+
}>()
|
|
117
|
+
</script>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Using Scoped Slots
|
|
121
|
+
|
|
122
|
+
`RouteResourceBoundView` supports the same `v-slot` pattern as `<RouterView>`:
|
|
123
|
+
|
|
124
|
+
```vue
|
|
125
|
+
<RouteResourceBoundView v-slot="{ Component, route }">
|
|
126
|
+
<component
|
|
127
|
+
:is="Component"
|
|
128
|
+
v-if="Component"
|
|
129
|
+
/>
|
|
130
|
+
<EmptyState v-else />
|
|
131
|
+
</RouteResourceBoundView>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
When no `errorComponent` or `loadingComponent` is defined on the route, you can use named slots as fallbacks:
|
|
44
135
|
|
|
45
136
|
```vue
|
|
137
|
+
<RouteResourceBoundView>
|
|
138
|
+
<template #default="{ Component, route }">
|
|
139
|
+
<component :is="Component" v-if="Component" />
|
|
140
|
+
</template>
|
|
141
|
+
|
|
142
|
+
<template #loading>
|
|
143
|
+
<LoadingSpinner />
|
|
144
|
+
</template>
|
|
145
|
+
|
|
146
|
+
<template #error="{ error, refresh }">
|
|
147
|
+
<div>
|
|
148
|
+
<p>{{ error.message }}</p>
|
|
149
|
+
<button @click="refresh">Retry</button>
|
|
150
|
+
</div>
|
|
151
|
+
</template>
|
|
152
|
+
</RouteResourceBoundView>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Using `useRouteResource` (Manual Handling)
|
|
156
|
+
|
|
157
|
+
If you prefer to handle loading and error states inside the component itself, set `lazy: false` on the route. This renders the component immediately while resources resolve in the background:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
export default defineRoute<{
|
|
161
|
+
product: ProductResource
|
|
162
|
+
}>()({
|
|
163
|
+
path: ':productId',
|
|
164
|
+
name: 'products.show',
|
|
165
|
+
component: ProductDetailPage,
|
|
166
|
+
lazy: false,
|
|
167
|
+
inject: {
|
|
168
|
+
product: {
|
|
169
|
+
from: 'productId',
|
|
170
|
+
resolve: (productId: string) => {
|
|
171
|
+
return new RouteResourceRequestResolver(
|
|
172
|
+
new ProductShowRequest(productId)
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Then use the `useRouteResource` composable inside your component:
|
|
181
|
+
|
|
182
|
+
```vue
|
|
183
|
+
<template>
|
|
184
|
+
<div v-if="isLoading">Loading...</div>
|
|
185
|
+
<div v-else-if="error">
|
|
186
|
+
<p>{{ error.message }}</p>
|
|
187
|
+
<button @click="refresh">Retry</button>
|
|
188
|
+
</div>
|
|
189
|
+
<div v-else>
|
|
190
|
+
<h1>{{ product.name }}</h1>
|
|
191
|
+
</div>
|
|
192
|
+
</template>
|
|
193
|
+
|
|
46
194
|
<script setup lang="ts">
|
|
195
|
+
import { useRouteResource } from '@blueprint-ts/core'
|
|
196
|
+
|
|
47
197
|
const props = defineProps<{
|
|
48
198
|
product: ProductResource
|
|
49
199
|
}>()
|
|
200
|
+
|
|
201
|
+
const { refresh, isLoading, error } = useRouteResource('product')
|
|
50
202
|
</script>
|
|
51
203
|
```
|
|
52
204
|
|
|
53
|
-
|
|
205
|
+
`useRouteResource` returns:
|
|
206
|
+
|
|
207
|
+
| Property | Type | Description |
|
|
208
|
+
|-------------|---------------------------|------------------------------------------|
|
|
209
|
+
| `isLoading` | `ComputedRef<boolean>` | `true` while the resource is resolving |
|
|
210
|
+
| `error` | `ComputedRef<Error\|null>` | The error if resolution failed, else `null` |
|
|
211
|
+
| `refresh` | `(options?: { silent?: boolean }) => Promise<void>` | Re-fetches the resource. Pass `{ silent: true }` to suppress the loading state. |
|
|
212
|
+
|
|
213
|
+
#### Silent Refresh
|
|
54
214
|
|
|
55
|
-
|
|
215
|
+
By default, calling `refresh()` sets `isLoading` to `true` while the resource is being re-fetched, which causes `RouteResourceBoundView` to show the loading component. If you want to refresh the resource in the background without triggering the loading state (e.g. polling or optimistic updates), pass `{ silent: true }`:
|
|
56
216
|
|
|
57
217
|
```ts
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
218
|
+
const { refresh } = useRouteResource('product')
|
|
219
|
+
|
|
220
|
+
// Normal refresh — triggers loading state
|
|
221
|
+
await refresh()
|
|
222
|
+
|
|
223
|
+
// Silent refresh — does not trigger loading state
|
|
224
|
+
await refresh({ silent: true })
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
A silent refresh still updates the `error` state if the request fails.
|
|
228
|
+
|
|
229
|
+
### Lazy vs Non-Lazy
|
|
230
|
+
|
|
231
|
+
| Option | Behavior |
|
|
232
|
+
|-----------------|-----------------------------------------------------------------------------------------------|
|
|
233
|
+
| `lazy: true` (default) | `RouteResourceBoundView` intercepts loading/error states and shows the appropriate component |
|
|
234
|
+
| `lazy: false` | The target component renders immediately; use `useRouteResource()` for manual state handling |
|
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PaginationDataDto } from './dtos/PaginationDataDto'
|
|
2
|
+
import { type BaseViewDriverContract } from './contracts/BaseViewDriverContract'
|
|
3
|
+
import { type PaginatorLoadDataOptions } from './contracts/PaginatorLoadDataOptions'
|
|
4
|
+
|
|
5
|
+
export abstract class BasePaginator<ResourceInterface, ViewDriver extends BaseViewDriverContract<ResourceInterface[]>> {
|
|
6
|
+
protected initialized: boolean = false
|
|
7
|
+
|
|
8
|
+
protected abstract viewDriver: ViewDriver
|
|
9
|
+
|
|
10
|
+
public constructor(protected dataDriver: unknown) {}
|
|
11
|
+
|
|
12
|
+
public isInitialized(): boolean {
|
|
13
|
+
return this.initialized
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public flush(): void {
|
|
17
|
+
this.viewDriver.setData([])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public getPageData(): ResourceInterface[] {
|
|
21
|
+
return this.viewDriver.getData()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public getTotal(): number {
|
|
25
|
+
return this.viewDriver.getTotal()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected passDataToViewDriver(dto: PaginationDataDto<ResourceInterface[]>, options?: PaginatorLoadDataOptions): void {
|
|
29
|
+
if (options?.flush) {
|
|
30
|
+
this.flush()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.viewDriver.setData(dto.getData())
|
|
34
|
+
this.viewDriver.setTotal(dto.getTotal())
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PageAwarePaginator } from './PageAwarePaginator'
|
|
2
2
|
import { PaginationDataDto } from './dtos/PaginationDataDto'
|
|
3
3
|
import { type PaginatorLoadDataOptions } from './contracts/PaginatorLoadDataOptions'
|
|
4
4
|
|
|
5
|
-
export class InfiniteScroller<ResourceInterface> extends
|
|
5
|
+
export class InfiniteScroller<ResourceInterface> extends PageAwarePaginator<ResourceInterface> {
|
|
6
6
|
protected override passDataToViewDriver(dto: PaginationDataDto<ResourceInterface[]>, options: PaginatorLoadDataOptions = {}) {
|
|
7
7
|
const { flush = false, replace = false } = options
|
|
8
8
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { PaginationDataDto } from './dtos/PaginationDataDto'
|
|
2
|
+
import { type ViewDriverContract } from './contracts/ViewDriverContract'
|
|
3
|
+
import { type ViewDriverFactoryContract } from './contracts/ViewDriverFactoryContract'
|
|
4
|
+
import { type PaginatorLoadDataOptions } from './contracts/PaginatorLoadDataOptions'
|
|
5
|
+
import { type PaginationDataDriverContract } from './contracts/PaginationDataDriverContract'
|
|
6
|
+
import { BasePaginator } from './BasePaginator'
|
|
7
|
+
|
|
8
|
+
export interface PageAwarePaginatorOptions {
|
|
9
|
+
viewDriverFactory?: ViewDriverFactoryContract
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class PageAwarePaginator<ResourceInterface> extends BasePaginator<ResourceInterface, ViewDriverContract<ResourceInterface[]>> {
|
|
13
|
+
protected static viewDriverFactory: ViewDriverFactoryContract
|
|
14
|
+
|
|
15
|
+
protected override viewDriver: ViewDriverContract<ResourceInterface[]>
|
|
16
|
+
|
|
17
|
+
public static setViewDriverFactory(value: ViewDriverFactoryContract): void {
|
|
18
|
+
PageAwarePaginator.viewDriverFactory = value
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public constructor(
|
|
22
|
+
protected override dataDriver: PaginationDataDriverContract<ResourceInterface[]>,
|
|
23
|
+
pageNumber: number = 1,
|
|
24
|
+
pageSize: number = 10,
|
|
25
|
+
options?: PageAwarePaginatorOptions
|
|
26
|
+
) {
|
|
27
|
+
super(dataDriver)
|
|
28
|
+
this.viewDriver = options?.viewDriverFactory
|
|
29
|
+
? options.viewDriverFactory.make<ResourceInterface>(pageNumber, pageSize)
|
|
30
|
+
: PageAwarePaginator.viewDriverFactory.make<ResourceInterface>(pageNumber, pageSize)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public setDataDriver(dataDriver: PaginationDataDriverContract<ResourceInterface[]>): this {
|
|
34
|
+
this.dataDriver = dataDriver
|
|
35
|
+
|
|
36
|
+
return this
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public getDataDriver(): PaginationDataDriverContract<ResourceInterface[]> {
|
|
40
|
+
return this.dataDriver
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public init(pageNumber: number, pageSize: number): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
44
|
+
this.initialized = true
|
|
45
|
+
|
|
46
|
+
if (pageNumber && pageSize) {
|
|
47
|
+
return this.loadData(pageNumber, pageSize)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return this.loadData(this.getCurrentPage(), this.getPageSize())
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public refresh(pageNumber?: number, options?: PaginatorLoadDataOptions): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
54
|
+
if (pageNumber !== undefined) {
|
|
55
|
+
return this.setPage(pageNumber, options)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return this.loadData(this.getCurrentPage(), this.getPageSize(), options)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public setPage(pageNumber: number, options?: PaginatorLoadDataOptions): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
62
|
+
this.viewDriver.setPage(pageNumber)
|
|
63
|
+
|
|
64
|
+
return this.loadData(this.viewDriver.getCurrentPage(), this.viewDriver.getPageSize(), options)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public getLastPage(): number {
|
|
68
|
+
return this.viewDriver.getLastPage()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public toNextPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
72
|
+
return this.setPage(this.getCurrentPage() + 1)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public toFirstPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
76
|
+
return this.setPage(1)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public toLastPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
80
|
+
return this.setPage(this.viewDriver.getLastPage())
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public toPreviousPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
84
|
+
return this.setPage(this.getCurrentPage() - 1)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public getCurrentPage(): number {
|
|
88
|
+
return this.viewDriver.getCurrentPage()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public getFromItemNumber(): number {
|
|
92
|
+
return (this.getCurrentPage() - 1) * this.getPageSize() + 1
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public getToItemNumber(): number {
|
|
96
|
+
return this.getCurrentPage() * this.getPageSize()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public getPageSize(): number {
|
|
100
|
+
return this.viewDriver.getPageSize()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public setPageSize(pageSize: number): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
104
|
+
this.viewDriver.setPageSize(pageSize)
|
|
105
|
+
|
|
106
|
+
if (this.getCurrentPage() * pageSize > this.getTotal()) {
|
|
107
|
+
return this.setPage(1)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return this.loadData(this.viewDriver.getCurrentPage(), this.viewDriver.getPageSize())
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public getPages(): number[] {
|
|
114
|
+
return this.viewDriver.getPages()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
protected loadData(pageNumber: number, pageSize: number, options?: PaginatorLoadDataOptions): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
118
|
+
return this.dataDriver.get(pageNumber, pageSize).then((value: PaginationDataDto<ResourceInterface[]>) => {
|
|
119
|
+
this.passDataToViewDriver(value, options)
|
|
120
|
+
|
|
121
|
+
return value
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -1,149 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type ViewDriverContract } from './contracts/ViewDriverContract'
|
|
3
|
-
import { type ViewDriverFactoryContract } from './contracts/ViewDriverFactoryContract'
|
|
4
|
-
import { type PaginatorLoadDataOptions } from './contracts/PaginatorLoadDataOptions'
|
|
5
|
-
import { type PaginationDataDriverContract } from './contracts/PaginationDataDriverContract'
|
|
1
|
+
import { PageAwarePaginator, type PageAwarePaginatorOptions } from './PageAwarePaginator'
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated Use PageAwarePaginator instead. This alias is kept for backward compatibility.
|
|
5
|
+
*/
|
|
6
|
+
export const Paginator = PageAwarePaginator
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
protected viewDriver: ViewDriverContract<ResourceInterface[]>
|
|
17
|
-
|
|
18
|
-
public static setViewDriverFactory(value: ViewDriverFactoryContract): void {
|
|
19
|
-
Paginator.viewDriverFactory = value
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public constructor(
|
|
23
|
-
protected dataDriver: PaginationDataDriverContract<ResourceInterface[]>,
|
|
24
|
-
pageNumber: number = 1,
|
|
25
|
-
pageSize: number = 10,
|
|
26
|
-
options?: PaginatorOptions
|
|
27
|
-
) {
|
|
28
|
-
this.viewDriver = options?.viewDriverFactory
|
|
29
|
-
? options.viewDriverFactory.make<ResourceInterface>(pageNumber, pageSize)
|
|
30
|
-
: Paginator.viewDriverFactory.make<ResourceInterface>(pageNumber, pageSize)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public setDataDriver(dataDriver: PaginationDataDriverContract<ResourceInterface[]>): this {
|
|
34
|
-
this.dataDriver = dataDriver
|
|
35
|
-
|
|
36
|
-
return this
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public getDataDriver(): PaginationDataDriverContract<ResourceInterface[]> {
|
|
40
|
-
return this.dataDriver
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public init(pageNumber: number, pageSize: number): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
44
|
-
this.initialized = true
|
|
45
|
-
|
|
46
|
-
if (pageNumber && pageSize) {
|
|
47
|
-
return this.loadData(pageNumber, pageSize)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return this.loadData(this.getCurrentPage(), this.getPageSize())
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public refresh(pageNumber?: number, options?: PaginatorLoadDataOptions): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
54
|
-
if (pageNumber !== undefined) {
|
|
55
|
-
return this.setPage(pageNumber, options)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return this.loadData(this.getCurrentPage(), this.getPageSize(), options)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public flush(): void {
|
|
62
|
-
this.viewDriver.setData([])
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
public setPage(pageNumber: number, options?: PaginatorLoadDataOptions): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
66
|
-
this.viewDriver.setPage(pageNumber)
|
|
67
|
-
|
|
68
|
-
return this.loadData(this.viewDriver.getCurrentPage(), this.viewDriver.getPageSize(), options)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public isInitialized(): boolean {
|
|
72
|
-
return this.initialized
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public getLastPage(): number {
|
|
76
|
-
return this.viewDriver.getLastPage()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public toNextPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
80
|
-
return this.setPage(this.getCurrentPage() + 1)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public toFirstPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
84
|
-
return this.setPage(1)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public toLastPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
88
|
-
return this.setPage(this.viewDriver.getLastPage())
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public toPreviousPage(): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
92
|
-
return this.setPage(this.getCurrentPage() - 1)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
public getPageData(): ResourceInterface[] {
|
|
96
|
-
return this.viewDriver.getData()
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
public getCurrentPage(): number {
|
|
100
|
-
return this.viewDriver.getCurrentPage()
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
public getFromItemNumber(): number {
|
|
104
|
-
return (this.getCurrentPage() - 1) * this.getPageSize() + 1
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
public getToItemNumber(): number {
|
|
108
|
-
return this.getCurrentPage() * this.getPageSize()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public getTotal(): number {
|
|
112
|
-
return this.viewDriver.getTotal()
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
public getPageSize(): number {
|
|
116
|
-
return this.viewDriver.getPageSize()
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
public setPageSize(pageSize: number): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
120
|
-
this.viewDriver.setPageSize(pageSize)
|
|
121
|
-
|
|
122
|
-
if (this.getCurrentPage() * pageSize > this.getTotal()) {
|
|
123
|
-
return this.setPage(1)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return this.loadData(this.viewDriver.getCurrentPage(), this.viewDriver.getPageSize())
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
public getPages(): number[] {
|
|
130
|
-
return this.viewDriver.getPages()
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
protected loadData(pageNumber: number, pageSize: number, options?: PaginatorLoadDataOptions): Promise<PaginationDataDto<ResourceInterface[]>> {
|
|
134
|
-
return this.dataDriver.get(pageNumber, pageSize).then((value: PaginationDataDto<ResourceInterface[]>) => {
|
|
135
|
-
this.passDataToViewDriver(value, options)
|
|
136
|
-
|
|
137
|
-
return value
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
protected passDataToViewDriver(dto: PaginationDataDto<ResourceInterface[]>, options?: PaginatorLoadDataOptions): void {
|
|
142
|
-
if (options?.flush) {
|
|
143
|
-
this.flush()
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
this.viewDriver.setData(dto.getData())
|
|
147
|
-
this.viewDriver.setTotal(dto.getTotal())
|
|
148
|
-
}
|
|
149
|
-
}
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use PageAwarePaginatorOptions instead. This alias is kept for backward compatibility.
|
|
10
|
+
*/
|
|
11
|
+
export type PaginatorOptions = PageAwarePaginatorOptions
|