Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F969493
collection.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
collection.ts
View Options
import
{
useState
,
useEffect
}
from
"./react-api/api"
;
import
axios
from
"axios"
;
import
EventEmitter
from
"eventemitter3"
;
import
{
SealiousItem
,
SealiousCollectionResponse
,
CollectionParams
,
ComplexFilterParam
,
}
from
"./types"
;
import
{
CollectionItem
,
ExtractItemFields
}
from
"./item"
;
import
url
from
"./url"
;
const
DEFAULT_ITEMS_PER_PAGE
=
10
;
export
type
ExtractCollectionItemClass
<
C
extends
CollectionClient
<
any
>
>
=
InstanceType
<
C
[
"item_constructor"
]
>
;
export
type
ExtractCollectionFields
<
C
extends
CollectionClient
<
any
>
>
=
ExtractItemFields
<
ExtractCollectionItemClass
<
C
>>
;
export
function
useCollection
<
TCollection
extends
CollectionClient
<
any
>
,
Fields
=
ExtractCollectionFields
<
TCollection
>
,
ItemClass
=
ExtractCollectionItemClass
<
TCollection
>
>
(
CollectionClass
:
CollectionClass
<
TCollection
>
,
params
:
Fields
)
:
[
TCollection
,
ItemClass
[],
CollectionParams
<
Fields
>
,
number
]
{
const
[
collectionClient
]
=
useState
<
TCollection
>
(
()
=>
new
CollectionClass
(
params
)
);
const
[
version
,
setVersion
]
=
useState
(
0
);
const
[
items
,
setItems
]
=
useState
<
ItemClass
[]
>
([]);
useEffect
(()
=>
{
const
callback
=
()
=>
collectionClient
.
refresh
()
.
then
(()
=>
setItems
(
collectionClient
.
items
));
collectionClient
.
on
(
"change"
,
callback
);
collectionClient
.
on
(
"state-change"
,
()
=>
{
setVersion
((
v
)
=>
v
+
1
);
});
callback
();
return
()
=>
{
collectionClient
.
removeListener
(
"change"
,
callback
);
};
},
[]);
return
[
collectionClient
,
items
,
collectionClient
.
params
,
version
];
}
export
type
CollectionClass
<
TCollection
extends
CollectionClient
<
any
>>
=
new
(
params
:
CollectionParams
<
ExtractItemFields
<
ExtractCollectionItemClass
<
TCollection
>>
>
)
=>
TCollection
;
export
default
class
CollectionClient
<
ItemClass
extends
CollectionItem
<
any
>
>
extends
EventEmitter
{
items
:
ItemClass
[];
collection_name
:
string
;
item_constructor
:
new
(
id
:
string
,
body
:
ExtractItemFields
<
ItemClass
>
&
SealiousItem
,
attachments
?:
{
[
id
:
string
]
:
SealiousItem
}
)
=>
ItemClass
;
params
:
CollectionParams
<
ExtractItemFields
<
ItemClass
>>
;
needs_saving
:
boolean
=
false
;
has_next_page
:
boolean
|
null
=
null
;
loading
:
boolean
=
false
;
constructor
(
params
:
CollectionParams
<
ExtractItemFields
<
ItemClass
>>
)
{
super
();
this
.
params
=
params
;
this
.
save
=
this
.
save
.
bind
(
this
);
this
.
setPage
=
this
.
setPage
.
bind
(
this
);
this
.
getPage
=
this
.
getPage
.
bind
(
this
);
this
.
nextPage
=
this
.
nextPage
.
bind
(
this
);
this
.
prevPage
=
this
.
prevPage
.
bind
(
this
);
}
setFilter
<
Field
extends
keyof
ExtractItemFields
<
ItemClass
>>
(
field_name
:
Field
,
value
:
|
ComplexFilterParam
<
ExtractItemFields
<
ItemClass
>
[
Field
]
>
|
ExtractItemFields
<
ItemClass
>
[
Field
],
replace
:
boolean
=
false
)
{
if
(
!
this
.
params
.
filter
)
{
this
.
params
.
filter
=
{};
}
if
(
replace
)
{
this
.
params
.
filter
[
field_name
]
=
value
;
}
else
{
if
(
typeof
value
==
"object"
)
{
this
.
params
.
filter
[
field_name
]
=
{
...
this
.
params
.
filter
[
field_name
],
...
value
,
};
}
else
{
this
.
params
.
filter
=
{
...
this
.
params
.
filter
,
[
field_name
]
:
value
,
};
}
}
if
(
this
.
isPaginated
())
{
this
.
setPage
(
1
);
}
this
.
emit
(
"change"
);
}
isPaginated
()
:
boolean
{
return
typeof
this
.
params
.
pagination
==
"object"
;
}
setPage
(
page
:
number
)
{
if
(
!
this
.
isPaginated
())
{
throw
new
Error
(
"This client does not use pagination"
);
}
this
.
params
.
pagination
=
{
items
:
this
?
.
params
?
.
pagination
?
.
items
||
DEFAULT_ITEMS_PER_PAGE
,
page
:
page
,
};
this
.
emit
(
"change"
);
}
getPage
()
:
number
{
if
(
!
this
.
isPaginated
())
{
throw
new
Error
(
"This client does not use pagination"
);
}
return
this
.
params
?
.
pagination
?
.
page
||
1
;
}
nextPage
()
{
if
(
this
.
has_next_page
)
{
this
.
setPage
(
this
.
getPage
()
+
1
);
}
}
prevPage
()
{
if
(
this
.
getPage
()
>
0
)
{
this
.
setPage
(
this
.
getPage
()
-
1
);
}
}
async
refresh
()
:
Promise
<
void
>
{
this
.
loading
=
true
;
this
.
emit
(
"state-change"
);
const
response
=
(
await
axios
.
get
(
url
(
`/api/v1/collections/
${
this
.
collection_name
}
`
,
this
.
params
)
))
as
{
data
:
SealiousCollectionResponse
<
SealiousItem
&
ExtractItemFields
<
ItemClass
>
>
;
};
this
.
needs_saving
=
false
;
const
attachments
=
response
.
data
.
attachments
;
if
(
this
.
isPaginated
())
{
this
.
has_next_page
=
response
.
data
.
items
.
length
===
this
.
params
?
.
pagination
?
.
items
;
}
this
.
items
=
response
.
data
.
items
.
map
((
item
)
=>
{
const
entry
=
new
this
.
item_constructor
(
item
.
id
,
item
,
attachments
);
entry
.
on
(
"change"
,
()
=>
this
.
emit
(
"change"
));
entry
.
on
(
"temp-change"
,
()
=>
(
this
.
needs_saving
=
true
));
return
entry
;
});
this
.
loading
=
false
;
this
.
emit
(
"state-change"
);
}
async
create
(
body
:
ExtractItemFields
<
ItemClass
>
)
{
const
response
=
await
axios
.
post
(
`/api/v1/collections/
${
this
.
collection_name
}
`
,
body
);
this
.
emit
(
"change"
);
return
response
.
data
.
items
;
}
async
save
()
{
const
promises
=
[];
for
(
const
item
of
this
.
items
)
{
if
(
item
.
needs_saving
)
{
promises
.
push
(
item
.
save
());
}
}
await
Promise
.
all
(
promises
);
this
.
needs_saving
=
false
;
this
.
emit
(
"change"
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Sat, Nov 23, 04:12 (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
547830
Default Alt Text
collection.ts (4 KB)
Attached To
Mode
rCOS Cosealious
Attached
Detach File
Event Timeline
Log In to Comment