Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F3010848
list.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
list.ts
View Options
import
{
Context
}
from
"koa"
;
import
{
Collection
,
CollectionItem
,
ItemFields
,
ItemList
}
from
"sealious"
;
import
{
Templatable
,
tempstream
,
FlatTemplatable
}
from
"tempstream"
;
import
{
peopleWhoCan
}
from
"./access-control"
;
import
{
Page
}
from
"./page"
;
import
{
ShapeToType
}
from
"@sealcode/ts-predicates"
;
import
{
FormFieldControl
}
from
"../forms/controls/controls"
;
import
{
FormField
,
NumberField
}
from
"../forms/fields/field"
;
import
{
naturalNumbers
,
UrlWithNewParams
}
from
"../utils/utils"
;
import
{
FormDataValue
}
from
".."
;
import
{
makeHiddenInputs
}
from
"../make-hidden-inputs"
;
export
const
BasePagePropsShape
=
<
const
>
{};
export
type
BasePageProps
=
ShapeToType
<
typeof
BasePagePropsShape
>
;
export
const
BaseListPageFields
=
<
const
>
{
page
:
new
NumberField
(
false
,
1
),
itemsPerPage
:
new
NumberField
(
false
,
12
),
};
export
abstract
class
ListPage
<
ItemType
,
F
extends
typeof
BaseListPageFields
>
extends
Page
<
F
>
{
abstract
getItems
(
ctx
:
Context
,
page
:
number
,
itemsPerPage
:
number
,
values
:
Record
<
string
,
FormDataValue
>
)
:
Promise
<
ItemType
[]
>
;
abstract
getTotalPages
(
ctx
:
Context
,
itemsPerPage
:
number
,
values
:
Record
<
string
,
FormDataValue
>
)
:
Promise
<
number
>
;
abstract
renderItem
(
ctx
:
Context
,
item
:
ItemType
)
:
Promise
<
FlatTemplatable
>
;
filterFields
:
Record
<
string
,
FormField
>
=
{};
filterControls
:
FormFieldControl
[]
=
[];
init
()
:
void
{
super
.
init
();
for
(
const
[
fieldname
,
field
]
of
Object
.
entries
(
this
.
filterFields
))
{
field
.
init
(
fieldname
);
}
}
renderListContainer
(
_
:
Context
,
content
:
Templatable
)
:
FlatTemplatable
{
return
tempstream
`<div>
${
content
}
</div>`
;
}
async
render
(
ctx
:
Context
)
:
Promise
<
FlatTemplatable
>
{
const
values
=
this
.
extractRawValues
(
ctx
);
const
{
parsed
:
page
}
=
await
this
.
fields
.
page
.
getValue
(
ctx
,
values
);
const
{
parsed
:
itemsPerPage
}
=
await
this
.
fields
.
itemsPerPage
.
getValue
(
ctx
,
values
);
const
items_promise
=
this
.
getItems
(
ctx
,
page
,
itemsPerPage
,
values
);
return
tempstream
`
${
this
.
renderPagination
(
ctx
,
values
)
}
${
this
.
renderFilters
(
ctx
)
}
${
items_promise
.
then
((
items
)
=>
this
.
renderListContainer
(
ctx
,
items
.
map
((
item
)
=>
this
.
renderItem
(
ctx
,
item
))
)
)
}
`
;
}
async
renderPagination
(
ctx
:
Context
,
values
:
Record
<
string
,
FormDataValue
>
)
:
Promise
<
FlatTemplatable
>
{
const
{
parsed
:
page
}
=
await
this
.
fields
.
page
.
getValue
(
ctx
,
values
);
const
{
parsed
:
itemsPerPage
}
=
await
this
.
fields
.
itemsPerPage
.
getValue
(
ctx
,
values
);
const
totalIems
=
await
this
.
getTotalPages
(
ctx
,
itemsPerPage
,
values
);
return
tempstream
/* HTML */
`<center>
${
page
>
1
?
this
.
renderPageButton
(
ctx
,
1
,
"Pierwsza strona"
)
:
""
}
${
page
>
1
?
this
.
renderPageButton
(
ctx
,
page
-
1
,
"Poprzednia strona"
)
:
""
}
<select onchange="if (this.value) Turbo.visit(this.value)">
${
Array
.
from
(
naturalNumbers
(
1
,
totalIems
)).
map
(
(
n
)
=>
/* HTML */
`<option
value="
${
UrlWithNewParams
(
ctx
,
//eslint-disable-next-line @typescript-eslint/consistent-type-assertions
this
.
propsParser
.
overwriteProp
(
ctx
,
{
page
:
n
,
}
as Partial<Record<string, unknown>>)
)}"
${
page
===
n
?
"selected"
:
""
}
>
${
n
}
</option>`
)
}
</select>
${
page
<
totalIems
?
this
.
renderPageButton
(
ctx
,
page
+
1
,
"Następna strona"
)
:
""
}
${
page
<
totalIems
?
this
.
renderPageButton
(
ctx
,
totalIems
,
"Ostatnia strona"
)
:
""
}
</center>`
;
}
private
renderPageButton
(
ctx
:
Context
,
page
:
number
,
text
:
string
)
{
return
/* HTML */
`<a
href="
${
UrlWithNewParams
(
ctx
,
//eslint-disable-next-line @typescript-eslint/consistent-type-assertions
this
.
propsParser
.
overwriteProp
(
ctx
,
{
page
,
}
as Partial<Record<string, unknown>>)
)}"
>
${
text
}
</a
>`
;
}
async
getFilterValues
(
ctx
:
Context
)
:
Promise
<
Record
<
string
,
unknown
>>
{
const
filter
=
{}
as
Record
<
string
,
unknown
>
;
const
raw_values
=
this
.
extractRawValues
(
ctx
);
for
(
const
[
fieldname
,
field
]
of
Object
.
entries
(
this
.
filterFields
))
{
// eslint-disable-next-line no-await-in-loop
const
{
parsed
}
=
await
field
.
getValue
(
ctx
,
raw_values
);
filter
[
fieldname
]
=
parsed
;
}
return
filter
;
}
renderFilters
(
ctx
:
Context
)
:
FlatTemplatable
{
const
values
=
this
.
extractRawValues
(
ctx
);
return
tempstream
/* HTML */
`<form method="GET">
${
makeHiddenInputs
(
ctx
,
this
.
fields
,
values
,
[
"page"
,
...
Object
.
values
(
this
.
filterFields
).
map
((
f
)
=>
f
.
name
),
])
}
${
this
.
filterControls
.
map
((
control
)
=>
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
control
.
render
(
ctx
,
values
)
)
}
</form>`
;
}
}
export
abstract
class
SealiousItemListPage
<
C
extends
Collection
,
F
extends
typeof
BaseListPageFields
>
extends
ListPage
<
CollectionItem
<
C
>
,
F
>
{
constructor
(
public
collection
:
C
)
{
super
();
}
async
getTotalPages
(
ctx
:
Context
,
itemsPerPage
:
number
)
:
Promise
<
number
>
{
const
query
=
this
.
collection
.
list
(
ctx
.
$context
);
await
this
.
addFilter
(
ctx
,
query
);
const
{
items
}
=
await
query
.
fetch
();
return
Math
.
ceil
(
items
.
length
/
itemsPerPage
);
}
protected
async
addFilter
(
ctx
:
Context
,
list
:
ItemList
<
C
>
)
:
Promise
<
void
>
{
const
filters
=
await
this
.
getFilterValues
(
ctx
);
if
(
Object
.
keys
(
filters
).
length
)
{
list
.
filter
(
filters
as
Partial
<
ItemFields
<
C
>>
);
}
}
async
getItems
(
ctx
:
Context
,
page
:
number
,
itemsPerPage
:
number
)
:
Promise
<
CollectionItem
<
C
>
[]
>
{
const
query
=
this
.
collection
.
list
(
ctx
.
$context
);
await
this
.
addFilter
(
ctx
,
query
);
const
{
items
}
=
await
query
.
paginate
({
items
:
itemsPerPage
,
page
})
.
fetch
();
return
items
;
}
async
renderItem
(
_
:
Context
,
item
:
CollectionItem
<
C
>
)
:
Promise
<
FlatTemplatable
>
{
return
`<div>
${
item
.
id
}
</div>`
;
}
canAccess
=
peopleWhoCan
(
"list"
,
this
.
collection
);
}
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Wed, May 7, 19:48 (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
664225
Default Alt Text
list.ts (5 KB)
Attached To
Mode
rSGEN sealgen
Attached
Detach File
Event Timeline
Log In to Comment