1
1
import { A , useNavigate } from '@solidjs/router'
2
2
import { Copy , Plus , Trash } from 'lucide-solid'
3
- import { Component , createSignal , For , onMount , Show } from 'solid-js'
3
+ import { Component , createMemo , createSignal , For , onMount , Show } from 'solid-js'
4
4
import Button from '../../shared/Button'
5
5
import { ConfirmModal } from '../../shared/Modal'
6
6
import PageHeader from '../../shared/PageHeader'
@@ -10,7 +10,7 @@ import { getServiceName, sortByLabel } from '/web/shared/adapter'
10
10
import Divider from '/web/shared/Divider'
11
11
import { Pill , SolidCard } from '/web/shared/Card'
12
12
import { Page } from '/web/Layout'
13
- import { SubscriptionModelLevel } from '/common/types/presets'
13
+ import { SubscriptionModel , SubscriptionModelLevel } from '/common/types/presets'
14
14
15
15
const SubscriptionList : Component = ( ) => {
16
16
setComponentPageTitle ( 'Subscriptions' )
@@ -31,6 +31,38 @@ const SubscriptionList: Component = () => {
31
31
const cfg = userStore ( )
32
32
33
33
const [ deleting , setDeleting ] = createSignal < string > ( )
34
+ const subCats = createMemo ( ( ) => {
35
+ const cats = new Map < number , Array < SubscriptionModel & { label : string } > > ( )
36
+
37
+ for ( const sub of state . enabled ) {
38
+ let level = sub . levels . reduce < number | null > (
39
+ ( prev , curr ) => ( prev === null ? curr . level : curr . level < prev ? curr . level : prev ) ,
40
+ null
41
+ )
42
+
43
+ if ( level === null ) {
44
+ level = sub . subLevel
45
+ }
46
+
47
+ if ( ! cats . has ( level ) ) {
48
+ cats . set ( level , [ ] )
49
+ }
50
+
51
+ const list = cats . get ( level )
52
+ list ! . push ( sub )
53
+ cats . set ( level , list ! )
54
+ }
55
+
56
+ const all = Array . from ( cats . entries ( ) )
57
+ . sort ( ( l , r ) => l [ 0 ] - r [ 0 ] )
58
+ . map ( ( [ level , list ] ) => ( {
59
+ name : `Tier ${ level } ` ,
60
+ list : list . sort ( ( l , r ) => l . name . localeCompare ( r . name ) ) ,
61
+ } ) )
62
+
63
+ all . push ( { name : 'Disabled' , list : state . disabled } )
64
+ return all
65
+ } )
34
66
35
67
const deleteSub = ( ) => {
36
68
const presetId = deleting ( )
@@ -122,62 +154,69 @@ const SubscriptionList: Component = () => {
122
154
</ Show >
123
155
< Divider />
124
156
< div class = "flex justify-center font-bold" > Models</ div >
125
- < For each = { state . enabled . concat ( state . disabled ) } >
126
- { ( sub ) => (
127
- < div class = "flex w-full items-center gap-2" >
128
- < A
129
- href = { `/admin/subscriptions/${ sub . _id } ` }
130
- class = "flex h-12 w-full gap-2 rounded-xl hover:bg-[var(--bg-600)]"
131
- classList = { {
132
- 'bg-red-900' : sub . subDisabled && ! sub . isDefaultSub ,
133
- 'text-500' : sub . subDisabled && ! sub . isDefaultSub ,
134
- 'bg-800' : ! sub . subDisabled && ! sub . isDefaultSub ,
135
- 'bg-[var(--hl-800)]' : sub . isDefaultSub ,
136
- } }
137
- >
138
- < div class = "ml-4 flex w-full items-center" >
139
- < div class = "flex gap-1" >
140
- < span class = "mr-1 text-xs italic text-[var(--text-600)]" >
141
- [Level: { sub . subLevel } ] { getServiceName ( sub . service ) }
142
- </ span >
143
- { sub . name }
144
- < Show when = { sub . description } >
145
- < span class = "text-500 ml-1 text-xs" > { sub . description } </ span >
146
- </ Show >
147
- < span class = "mr-1 text-xs italic text-[var(--text-600)]" >
148
- { sub . isDefaultSub ? ' default' : '' }
149
- { sub . subDisabled ? ' (disabled)' : '' }
150
- </ span >
151
- < Contexts
152
- levels = { [
153
- {
154
- level : sub . subLevel ,
155
- maxContextLength : sub . maxContextLength ! ,
156
- maxTokens : sub . maxTokens ! ,
157
- } ,
158
- ] }
159
- />
160
- < Contexts levels = { sub . levels || [ ] } />
157
+ < For each = { subCats ( ) } >
158
+ { ( item ) => (
159
+ < >
160
+ < div class = "bold flex justify-start" > { item . name } </ div >
161
+ < For each = { item . list } >
162
+ { ( sub ) => (
163
+ < div class = "flex w-full items-center gap-2" >
164
+ < A
165
+ href = { `/admin/subscriptions/${ sub . _id } ` }
166
+ class = "flex h-12 w-full gap-2 rounded-xl hover:bg-[var(--bg-600)]"
167
+ classList = { {
168
+ 'bg-red-900' : sub . subDisabled && ! sub . isDefaultSub ,
169
+ 'text-500' : sub . subDisabled && ! sub . isDefaultSub ,
170
+ 'bg-800' : ! sub . subDisabled && ! sub . isDefaultSub ,
171
+ 'bg-[var(--hl-800)]' : sub . isDefaultSub ,
172
+ } }
173
+ >
174
+ < div class = "ml-4 flex w-full items-center" >
175
+ < div class = "flex gap-1" >
176
+ < span class = "mr-1 text-xs italic text-[var(--text-600)]" >
177
+ [Level: { sub . subLevel } ] { getServiceName ( sub . service ) }
178
+ </ span >
179
+ { sub . name }
180
+ < Show when = { sub . description } >
181
+ < span class = "text-500 ml-1 text-xs" > { sub . description } </ span >
182
+ </ Show >
183
+ < span class = "mr-1 text-xs italic text-[var(--text-600)]" >
184
+ { sub . isDefaultSub ? ' default' : '' }
185
+ { sub . subDisabled ? ' (disabled)' : '' }
186
+ </ span >
187
+ < Contexts
188
+ levels = { [
189
+ {
190
+ level : sub . subLevel ,
191
+ maxContextLength : sub . maxContextLength ! ,
192
+ maxTokens : sub . maxTokens ! ,
193
+ } ,
194
+ ] }
195
+ />
196
+ < Contexts levels = { sub . levels || [ ] } />
197
+ </ div >
198
+ </ div >
199
+ </ A >
200
+ < Button
201
+ schema = "clear"
202
+ size = "sm"
203
+ onClick = { ( ) => nav ( `/admin/subscriptions/new?preset=${ sub . _id } ` ) }
204
+ class = "icon-button"
205
+ >
206
+ < Copy />
207
+ </ Button >
208
+ < Button
209
+ schema = "clear"
210
+ size = "sm"
211
+ onClick = { ( ) => setDeleting ( sub . _id ) }
212
+ class = "icon-button"
213
+ >
214
+ < Trash />
215
+ </ Button >
161
216
</ div >
162
- </ div >
163
- </ A >
164
- < Button
165
- schema = "clear"
166
- size = "sm"
167
- onClick = { ( ) => nav ( `/admin/subscriptions/new?preset=${ sub . _id } ` ) }
168
- class = "icon-button"
169
- >
170
- < Copy />
171
- </ Button >
172
- < Button
173
- schema = "clear"
174
- size = "sm"
175
- onClick = { ( ) => setDeleting ( sub . _id ) }
176
- class = "icon-button"
177
- >
178
- < Trash />
179
- </ Button >
180
- </ div >
217
+ ) }
218
+ </ For >
219
+ </ >
181
220
) }
182
221
</ For >
183
222
</ div >
0 commit comments