1+ import { consume } from "@lit/context" ;
12import { localized , msg } from "@lit/localize" ;
23import { type SlSelect } from "@shoelace-style/shoelace" ;
3- import { html , type PropertyValues } from "lit" ;
4- import { customElement , property , state } from "lit/decorators.js" ;
4+ import { html , nothing } from "lit" ;
5+ import { customElement , property } from "lit/decorators.js" ;
56import { ifDefined } from "lit/directives/if-defined.js" ;
67import capitalize from "lodash/fp/capitalize" ;
78
9+ import {
10+ orgCrawlerChannelsContext ,
11+ type OrgCrawlerChannelsContext ,
12+ } from "@/context/org-crawler-channels" ;
813import { CrawlerChannelImage , type CrawlerChannel } from "@/pages/org/types" ;
914import LiteElement from "@/utils/LiteElement" ;
1015
@@ -20,167 +25,96 @@ type SelectCrawlerUpdateDetail = {
2025
2126export type SelectCrawlerUpdateEvent = CustomEvent < SelectCrawlerUpdateDetail > ;
2227
23- type CrawlerChannelsAPIResponse = {
24- channels : CrawlerChannel [ ] ;
25- } ;
26-
2728/**
2829 * Crawler channel select dropdown
2930 *
31+ * @TODO Convert to form control
32+ *
3033 * Usage example:
3134 * ```ts
3235 * <btrix-select-crawler
3336 * on-change=${({value}) => selectedCrawler = value}
3437 * ></btrix-select-crawler>
3538 * ```
3639 *
37- * @event on-change
40+ * @fires on-change
3841 */
3942@customElement ( "btrix-select-crawler" )
4043@localized ( )
4144export class SelectCrawler extends LiteElement {
45+ @consume ( { context : orgCrawlerChannelsContext , subscribe : true } )
46+ private readonly crawlerChannels ?: OrgCrawlerChannelsContext ;
47+
4248 @property ( { type : String } )
4349 size ?: SlSelect [ "size" ] ;
4450
4551 @property ( { type : String } )
46- crawlerChannel ?: string ;
47-
48- @state ( )
49- private selectedCrawler ?: CrawlerChannel ;
50-
51- @state ( )
52- private crawlerChannels ?: CrawlerChannel [ ] ;
53-
54- willUpdate ( changedProperties : PropertyValues < this> ) {
55- if ( changedProperties . has ( "crawlerChannel" ) ) {
56- void this . updateSelectedCrawlerChannel ( ) ;
57- }
58- }
59-
60- protected firstUpdated ( ) {
61- void this . updateSelectedCrawlerChannel ( ) ;
62- }
52+ crawlerChannel ?: CrawlerChannel [ "id" ] ;
6353
6454 render ( ) {
65- if ( this . crawlerChannels && this . crawlerChannels . length < 2 ) {
66- return html `` ;
67- }
55+ const selectedCrawler = this . getSelectedChannel ( ) ;
6856
6957 return html `
7058 < sl-select
7159 name ="crawlerChannel "
7260 label =${ msg ( "Crawler Release Channel" ) }
73- value =${ this . selectedCrawler ?. id || "" }
61+ value =${ selectedCrawler ?. id || "" }
7462 placeholder=${ msg ( "Latest" ) }
7563 size=${ ifDefined ( this . size ) }
7664 hoist
7765 @sl-change=${ this . onChange }
78- @sl-focus=${ ( ) => {
79- // Refetch to keep list up to date
80- void this . fetchCrawlerChannels ( ) ;
81- } }
8266 @sl-hide=${ this . stopProp }
8367 @sl-after-hide=${ this . stopProp }
68+ ?disabled=${ ! this . crawlerChannels || this . crawlerChannels . length === 1 }
8469 >
8570 ${ this . crawlerChannels ?. map (
8671 ( crawler ) =>
8772 html ` < sl-option value =${ crawler . id } >
8873 ${ capitalize ( crawler . id ) }
8974 </ sl-option > ` ,
9075 ) }
91- ${ this . selectedCrawler
92- ? html `
93- < div slot ="help-text ">
94- ${ msg ( "Version:" ) }
95- < span class ="font-monospace "
96- > ${ this . selectedCrawler . image } </ span
97- >
98- </ div >
99- `
100- : `` }
76+ < div slot ="help-text ">
77+ ${ msg ( "Version:" ) }
78+ ${ selectedCrawler
79+ ? html `
80+ < span class ="font-monospace "> ${ selectedCrawler . image } </ span >
81+ `
82+ : nothing }
83+ </ div >
10184 </ sl-select >
10285 ` ;
10386 }
10487
105- private onChange ( e : Event ) {
106- this . stopProp ( e ) ;
88+ private getSelectedChannel ( ) {
89+ if ( ! this . crawlerChannels || ! this . crawlerChannel ) return null ;
10790
108- this . selectedCrawler = this . crawlerChannels ?. find (
109- ( { id } ) => id === ( e . target as SlSelect ) . value ,
110- ) ;
91+ if ( this . crawlerChannel ) {
92+ return this . crawlerChannels . find ( ( { id } ) => id === this . crawlerChannel ) ;
93+ }
11194
112- this . dispatchEvent (
113- new CustomEvent < SelectCrawlerChangeDetail > ( "on-change" , {
114- detail : {
115- value : this . selectedCrawler ?. id ,
116- } ,
117- } ) ,
95+ return (
96+ this . crawlerChannels . find (
97+ ( { id } ) => id === CrawlerChannelImage . Default ,
98+ ) ?? null
11899 ) ;
119100 }
120101
121- private async updateSelectedCrawlerChannel ( ) {
122- await this . fetchCrawlerChannels ( ) ;
123- await this . updateComplete ;
124-
125- if ( ! this . crawlerChannels ) return ;
126-
127- if ( this . crawlerChannel && ! this . selectedCrawler ) {
128- this . selectedCrawler = this . crawlerChannels . find (
129- ( { id } ) => id === this . crawlerChannel ,
130- ) ;
131- }
132-
133- if ( ! this . selectedCrawler ) {
134- this . crawlerChannel = CrawlerChannelImage . Default ;
135- this . dispatchEvent (
136- new CustomEvent ( "on-change" , {
137- detail : {
138- value : CrawlerChannelImage . Default ,
139- } ,
140- } ) ,
141- ) ;
142- this . selectedCrawler = this . crawlerChannels . find (
143- ( { id } ) => id === this . crawlerChannel ,
144- ) ;
145- }
102+ private onChange ( e : Event ) {
103+ this . stopProp ( e ) ;
146104
147- await this . updateComplete ;
105+ const selectedCrawler = this . crawlerChannels ?. find (
106+ ( { id } ) => id === ( e . target as SlSelect ) . value ,
107+ ) ;
148108
149109 this . dispatchEvent (
150- new CustomEvent < SelectCrawlerUpdateDetail > ( "on-update " , {
110+ new CustomEvent < SelectCrawlerChangeDetail > ( "on-change " , {
151111 detail : {
152- show : this . crawlerChannels . length > 1 ,
112+ value : selectedCrawler ?. id ,
153113 } ,
154114 } ) ,
155115 ) ;
156116 }
157117
158- /**
159- * Fetch crawler channels and update internal state
160- */
161- private async fetchCrawlerChannels ( ) : Promise < void > {
162- try {
163- const channels = await this . getCrawlerChannels ( ) ;
164- this . crawlerChannels = channels ;
165- } catch ( e ) {
166- this . notify ( {
167- message : msg ( "Sorry, couldn't retrieve crawler channels at this time." ) ,
168- variant : "danger" ,
169- icon : "exclamation-octagon" ,
170- id : "crawler-channel-retrieve-error" ,
171- } ) ;
172- }
173- }
174-
175- private async getCrawlerChannels ( ) : Promise < CrawlerChannel [ ] > {
176- const data : CrawlerChannelsAPIResponse =
177- await this . apiFetch < CrawlerChannelsAPIResponse > (
178- `/orgs/${ this . orgId } /crawlconfigs/crawler-channels` ,
179- ) ;
180-
181- return data . channels ;
182- }
183-
184118 /**
185119 * Stop propgation of sl-select events.
186120 * Prevents bug where sl-dialog closes when dropdown closes
0 commit comments