mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 00:01:55 +00:00
fix: teams selector svelte5 (#7087)
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
channels?: ChannelItem[]
|
||||
teamId?: string
|
||||
onError?: (error: Error) => void
|
||||
onselectedchannelchange?: (channel: ChannelItem | undefined) => void
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -28,34 +29,56 @@
|
||||
minWidth = '160px',
|
||||
channels = undefined,
|
||||
teamId,
|
||||
onError
|
||||
onError,
|
||||
onselectedchannelchange
|
||||
}: Props = $props()
|
||||
|
||||
let isFetching = $state(false)
|
||||
let searchResults = $state<ChannelItem[]>([])
|
||||
|
||||
// Only enable search mode if no channels are provided AND teamId is provided
|
||||
let selectedChannelId = $state<string | undefined>(selectedChannel?.channel_id)
|
||||
|
||||
const searchMode = !channels && !!teamId
|
||||
|
||||
// Determine which channels to show: provided channels or search results
|
||||
// In search mode, include the selected channel if it exists
|
||||
let displayChannels = $derived(() => {
|
||||
const baseChannels = channels || searchResults;
|
||||
if (searchMode && selectedChannel && !baseChannels.find(c => c.channel_id === selectedChannel?.channel_id)) {
|
||||
return [selectedChannel, ...baseChannels];
|
||||
let displayChannels = $derived.by(() => {
|
||||
const baseChannels = channels || searchResults
|
||||
if (selectedChannel && !baseChannels.find(c => c.channel_id === selectedChannel?.channel_id)) {
|
||||
return [selectedChannel, ...baseChannels]
|
||||
}
|
||||
return baseChannels
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
const newChannel = selectedChannelId
|
||||
? displayChannels.find(c => c.channel_id === selectedChannelId)
|
||||
: undefined
|
||||
|
||||
if (newChannel?.channel_id !== selectedChannel?.channel_id) {
|
||||
selectedChannel = newChannel
|
||||
}
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if (selectedChannel?.channel_id !== selectedChannelId) {
|
||||
selectedChannelId = selectedChannel?.channel_id
|
||||
}
|
||||
})
|
||||
|
||||
let previousChannelId = $state<string | undefined>(undefined)
|
||||
|
||||
$effect(() => {
|
||||
if (selectedChannel?.channel_id !== previousChannelId) {
|
||||
previousChannelId = selectedChannel?.channel_id
|
||||
onselectedchannelchange?.(selectedChannel)
|
||||
}
|
||||
return baseChannels;
|
||||
})
|
||||
|
||||
// Create separate filter text for search mode
|
||||
let searchFilterText = $state('')
|
||||
|
||||
// Debounced search function
|
||||
const debouncedSearch = debounce(async (query: string) => {
|
||||
await searchChannels(query)
|
||||
}, 500)
|
||||
|
||||
// Watch for search filter text changes (only in search mode)
|
||||
$effect(() => {
|
||||
if (searchMode) {
|
||||
if (searchFilterText.length >= 1) {
|
||||
@@ -97,37 +120,27 @@
|
||||
{#if searchMode}
|
||||
<Select
|
||||
containerStyle={'min-width: ' + minWidth}
|
||||
items={searchFilterText.length >= 1 || (searchFilterText.length === 0 && selectedChannel) ? displayChannels().filter(channel => channel.channel_id && channel.channel_name).map((channel) => ({
|
||||
items={displayChannels.filter(channel => channel.channel_id && channel.channel_name).map((channel) => ({
|
||||
label: channel.channel_name ?? 'Unknown Channel',
|
||||
value: channel.channel_id ?? ''
|
||||
})) : []}
|
||||
}))}
|
||||
placeholder={isFetching ? "Searching..." : (teamId ? "Search channels..." : "Select a team first")}
|
||||
clearable
|
||||
disabled={disabled || isFetching || !teamId}
|
||||
bind:filterText={searchFilterText}
|
||||
bind:value={
|
||||
() => selectedChannel?.channel_id,
|
||||
(value) => {
|
||||
selectedChannel = value ? displayChannels().find((channel) => channel.channel_id === value) : undefined
|
||||
}
|
||||
}
|
||||
bind:value={selectedChannelId}
|
||||
/>
|
||||
{:else}
|
||||
<Select
|
||||
containerStyle={'min-width: ' + minWidth}
|
||||
items={displayChannels().filter(channel => channel.channel_id && channel.channel_name).map((channel) => ({
|
||||
items={displayChannels.filter(channel => channel.channel_id && channel.channel_name).map((channel) => ({
|
||||
label: channel.channel_name ?? 'Unknown Channel',
|
||||
value: channel.channel_id ?? ''
|
||||
}))}
|
||||
{placeholder}
|
||||
clearable
|
||||
disabled={disabled || displayChannels().length === 0}
|
||||
bind:value={
|
||||
() => selectedChannel?.channel_id,
|
||||
(value) => {
|
||||
selectedChannel = value ? displayChannels().find((channel) => channel.channel_id === value) : undefined
|
||||
}
|
||||
}
|
||||
disabled={disabled || displayChannels.length === 0}
|
||||
bind:value={selectedChannelId}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
hideConnectButton?: boolean
|
||||
} = $props()
|
||||
|
||||
let selectedTeam: TeamItem | undefined = undefined
|
||||
let selectedTeam: TeamItem | undefined = $state(undefined)
|
||||
|
||||
async function connectTeams() {
|
||||
if (!selectedTeam) return
|
||||
|
||||
@@ -496,19 +496,16 @@
|
||||
minWidth="200px"
|
||||
placeholder="Search Teams channels"
|
||||
teamId={teams_team_id}
|
||||
bind:selectedChannel={
|
||||
() =>
|
||||
handlerExtraArgs['channel']
|
||||
? {
|
||||
channel_id: handlerExtraArgs['channel'],
|
||||
channel_name: handlerExtraArgs['channel_name']
|
||||
}
|
||||
: undefined,
|
||||
(channel) => {
|
||||
handlerExtraArgs['channel'] = channel?.channel_id
|
||||
handlerExtraArgs['channel_name'] = channel?.channel_name
|
||||
}
|
||||
}
|
||||
selectedChannel={handlerExtraArgs['channel']
|
||||
? {
|
||||
channel_id: handlerExtraArgs['channel'],
|
||||
channel_name: handlerExtraArgs['channel_name']
|
||||
}
|
||||
: undefined}
|
||||
onselectedchannelchange={(channel) => {
|
||||
handlerExtraArgs['channel'] = channel?.channel_id
|
||||
handlerExtraArgs['channel_name'] = channel?.channel_name
|
||||
}}
|
||||
onError={(e) => sendUserToast('Failed to load channels: ' + e.message, true)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -163,13 +163,17 @@
|
||||
teamItem: { team_id: string; team_name: string } | undefined,
|
||||
i: number
|
||||
) {
|
||||
const currentTeamChannel = $values['critical_error_channels'][i]?.teams_channel
|
||||
const teamIdChanged = currentTeamChannel?.team_id !== teamItem?.team_id
|
||||
|
||||
$values['critical_error_channels'][i] = {
|
||||
teams_channel: teamItem
|
||||
? {
|
||||
team_id: teamItem.team_id,
|
||||
team_name: teamItem.team_name,
|
||||
channel_id: undefined, // Will be set when channel is selected
|
||||
channel_name: undefined
|
||||
// Preserve existing channel if team didn't actually change
|
||||
channel_id: teamIdChanged ? undefined : currentTeamChannel?.channel_id,
|
||||
channel_name: teamIdChanged ? undefined : currentTeamChannel?.channel_name
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
@@ -191,6 +195,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- {JSON.stringify($values, null, 2)} -->
|
||||
@@ -563,24 +568,25 @@
|
||||
value={v?.slack_channel ?? ''}
|
||||
/>
|
||||
{:else if v && 'teams_channel' in v}
|
||||
{@const currentTeam = $values['critical_error_channels'][i]?.teams_channel
|
||||
? {
|
||||
team_id: $values['critical_error_channels'][i]?.teams_channel?.team_id,
|
||||
team_name: $values['critical_error_channels'][i]?.teams_channel?.team_name
|
||||
}
|
||||
: undefined}
|
||||
{@const currentChannel = $values['critical_error_channels'][i]?.teams_channel?.channel_id
|
||||
? {
|
||||
channel_id: $values['critical_error_channels'][i]?.teams_channel?.channel_id,
|
||||
channel_name: $values['critical_error_channels'][i]?.teams_channel?.channel_name
|
||||
}
|
||||
: undefined}
|
||||
<div class="flex flex-row gap-2 w-full">
|
||||
<TeamSelector
|
||||
containerClass="w-44"
|
||||
minWidth="140px"
|
||||
showRefreshButton={false}
|
||||
bind:selectedTeam={
|
||||
() =>
|
||||
$values['critical_error_channels'][i]?.teams_channel
|
||||
? {
|
||||
team_id:
|
||||
$values['critical_error_channels'][i]?.teams_channel?.team_id,
|
||||
team_name:
|
||||
$values['critical_error_channels'][i]?.teams_channel
|
||||
?.team_name
|
||||
}
|
||||
: undefined,
|
||||
(team) => handleTeamChange(team, i)
|
||||
}
|
||||
selectedTeam={currentTeam}
|
||||
onselectedteamchange={(team) => handleTeamChange(team, i)}
|
||||
/>
|
||||
|
||||
{#if $values['critical_error_channels'][i]?.teams_channel?.team_id}
|
||||
@@ -588,20 +594,8 @@
|
||||
containerClass=""
|
||||
placeholder="Search channels"
|
||||
teamId={$values['critical_error_channels'][i]?.teams_channel?.team_id}
|
||||
bind:selectedChannel={
|
||||
() =>
|
||||
$values['critical_error_channels'][i]?.teams_channel?.channel_id
|
||||
? {
|
||||
channel_id:
|
||||
$values['critical_error_channels'][i]?.teams_channel
|
||||
?.channel_id,
|
||||
channel_name:
|
||||
$values['critical_error_channels'][i]?.teams_channel
|
||||
?.channel_name
|
||||
}
|
||||
: undefined,
|
||||
(channel) => handleChannelChange(channel, i)
|
||||
}
|
||||
selectedChannel={currentChannel}
|
||||
onselectedchannelchange={(channel) => handleChannelChange(channel, i)}
|
||||
onError={(e) =>
|
||||
sendUserToast('Failed to load channels: ' + e.message, true)}
|
||||
/>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
teams?: TeamItem[] | undefined
|
||||
minWidth?: string
|
||||
onError?: (error: Error) => void
|
||||
onselectedteamchange?: (team: TeamItem | undefined) => void
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -27,34 +28,56 @@
|
||||
showRefreshButton = true,
|
||||
teams = undefined,
|
||||
minWidth = '160px',
|
||||
onError
|
||||
onError,
|
||||
onselectedteamchange
|
||||
}: Props = $props()
|
||||
|
||||
let isFetching = $state(false)
|
||||
let searchResults = $state<TeamItem[]>([])
|
||||
|
||||
// Only enable search mode if no teams are provided
|
||||
let selectedTeamId = $state<string | undefined>(selectedTeam?.team_id)
|
||||
|
||||
const searchMode = !teams
|
||||
|
||||
// Determine which teams to show: provided teams or search results
|
||||
// In search mode, include the selected team if it exists
|
||||
let displayTeams = $derived(() => {
|
||||
const baseTeams = teams || searchResults;
|
||||
if (searchMode && selectedTeam && !baseTeams.find(t => t.team_id === selectedTeam?.team_id)) {
|
||||
return [selectedTeam, ...baseTeams];
|
||||
let displayTeams = $derived.by(() => {
|
||||
const baseTeams = teams || searchResults
|
||||
if (selectedTeam && !baseTeams.find(t => t.team_id === selectedTeam?.team_id)) {
|
||||
return [selectedTeam, ...baseTeams]
|
||||
}
|
||||
return baseTeams
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
const newTeam = selectedTeamId
|
||||
? displayTeams.find(t => t.team_id === selectedTeamId)
|
||||
: undefined
|
||||
|
||||
if (newTeam?.team_id !== selectedTeam?.team_id) {
|
||||
selectedTeam = newTeam
|
||||
}
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if (selectedTeam?.team_id !== selectedTeamId) {
|
||||
selectedTeamId = selectedTeam?.team_id
|
||||
}
|
||||
})
|
||||
|
||||
let previousTeamId = $state<string | undefined>(undefined)
|
||||
|
||||
$effect(() => {
|
||||
if (selectedTeam?.team_id !== previousTeamId) {
|
||||
previousTeamId = selectedTeam?.team_id
|
||||
onselectedteamchange?.(selectedTeam)
|
||||
}
|
||||
return baseTeams;
|
||||
})
|
||||
|
||||
// Create separate filter text for search mode
|
||||
let searchFilterText = $state('')
|
||||
|
||||
// Debounced search function
|
||||
const debouncedSearch = debounce(async (query: string) => {
|
||||
await searchTeams(query)
|
||||
}, 500)
|
||||
|
||||
// Watch for search filter text changes (only in search mode)
|
||||
$effect(() => {
|
||||
if (searchMode) {
|
||||
if (searchFilterText.length >= 1) {
|
||||
@@ -100,37 +123,27 @@
|
||||
{#if searchMode}
|
||||
<Select
|
||||
containerStyle={'min-width: ' + minWidth}
|
||||
items={searchFilterText.length >= 1 || (searchFilterText.length === 0 && selectedTeam) ? displayTeams().map((team) => ({
|
||||
items={displayTeams.map((team) => ({
|
||||
label: team.team_name,
|
||||
value: team.team_id
|
||||
})) : []}
|
||||
}))}
|
||||
placeholder={isFetching ? "Searching..." : "Search teams..."}
|
||||
clearable
|
||||
disabled={disabled || isFetching}
|
||||
bind:filterText={searchFilterText}
|
||||
bind:value={
|
||||
() => selectedTeam?.team_id,
|
||||
(value) => {
|
||||
selectedTeam = value ? displayTeams().find((team) => team.team_id === value) : undefined
|
||||
}
|
||||
}
|
||||
bind:value={selectedTeamId}
|
||||
/>
|
||||
{:else}
|
||||
<Select
|
||||
containerStyle={'min-width: ' + minWidth}
|
||||
items={displayTeams().map((team) => ({
|
||||
items={displayTeams.map((team) => ({
|
||||
label: team.team_name,
|
||||
value: team.team_id
|
||||
}))}
|
||||
placeholder="Select a team"
|
||||
clearable
|
||||
disabled={disabled || isFetching}
|
||||
bind:value={
|
||||
() => selectedTeam?.team_id,
|
||||
(value) => {
|
||||
selectedTeam = value ? displayTeams().find((team) => team.team_id === value) : undefined
|
||||
}
|
||||
}
|
||||
bind:value={selectedTeamId}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user