Skip to content

Commit 559cede

Browse files
committed
Implement pinning functionality for configurations, allowing pinned items to be displayed separately and preventing their reordering
1 parent 085b3d2 commit 559cede

3 files changed

Lines changed: 107 additions & 59 deletions

File tree

‎packages/ui/src/components/editor/panel/Configurations/Configurations.module.scss‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@
4747

4848
&:hover {
4949
background-color: var(--vscode-list-hoverBackground);
50+
51+
.configurations__item__right {
52+
display: flex;
53+
}
5054
}
5155

5256
&--highlighted {
@@ -92,6 +96,12 @@
9296
}
9397
}
9498
}
99+
100+
&__right {
101+
display: none;
102+
align-items: center;
103+
cursor: default;
104+
}
95105
}
96106
}
97107

‎packages/ui/src/components/editor/panel/Configurations/Configurations.stories.tsx‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ const configurations: Configurations.Configuration[] = [
1515
id: '2',
1616
model: 'gpt-4o',
1717
provider: 'OpenAI',
18-
reasoning_effort: 'low'
18+
reasoning_effort: 'low',
19+
is_pinned: true
1920
},
2021
{
2122
id: '3',
@@ -30,12 +31,19 @@ export const Default = () => {
3031
<Configurations
3132
api_mode="edit-context"
3233
configurations={configurations}
33-
on_configuration_click={(index) => {
34-
console.log('on_configuration_click', index)
34+
on_configuration_click={(id) => {
35+
console.log('on_configuration_click', id)
3536
}}
3637
on_manage_configurations={() => {
3738
console.log('on_manage_configurations')
3839
}}
40+
on_toggle_pinned={(id) => {
41+
console.log('on_toggle_pinned', id)
42+
}}
43+
is_collapsed={false}
44+
on_toggle_collapsed={(is_collapsed) => {
45+
console.log('on_toggle_collapsed', is_collapsed)
46+
}}
3947
/>
4048
)
4149
}
@@ -44,11 +52,15 @@ export const Empty = () => (
4452
<Configurations
4553
api_mode="edit-context"
4654
configurations={[]}
47-
on_configuration_click={(index) => {
48-
console.log('on_configuration_click', index)
55+
on_configuration_click={(id) => {
56+
console.log('on_configuration_click', id)
4957
}}
5058
on_manage_configurations={() => {
5159
console.log('on_manage_configurations')
5260
}}
61+
is_collapsed={false}
62+
on_toggle_collapsed={(is_collapsed) => {
63+
console.log('on_toggle_collapsed', is_collapsed)
64+
}}
5365
/>
5466
)

‎packages/ui/src/components/editor/panel/Configurations/Configurations.tsx‎

Lines changed: 80 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ export namespace Configurations {
1212
temperature?: number
1313
reasoning_effort?: string
1414
cache_enabled?: boolean
15+
is_pinned?: boolean
1516
}
1617

1718
export type Props = {
1819
api_mode: 'edit-context' | 'code-completions'
1920
configurations: Configuration[]
2021
on_configuration_click: (id: string) => void
2122
on_reorder?: (configurations: Configuration[]) => void
23+
on_toggle_pinned?: (id: string) => void
2224
selected_configuration_id?: string
2325
on_manage_configurations: () => void
2426
is_collapsed: boolean
@@ -27,8 +29,83 @@ export namespace Configurations {
2729
}
2830

2931
export const Configurations: React.FC<Configurations.Props> = (props) => {
32+
const pinned_configurations = props.configurations.filter((c) => c.is_pinned)
33+
const unpinned_configurations = props.configurations.filter(
34+
(c) => !c.is_pinned
35+
)
36+
37+
const renderConfigurationItem = (
38+
configuration: Configurations.Configuration
39+
) => {
40+
const description_parts = [configuration.provider]
41+
if (configuration.reasoning_effort) {
42+
description_parts.push(`${configuration.reasoning_effort}`)
43+
}
44+
if (
45+
configuration.temperature &&
46+
configuration.temperature != DEFAULT_TEMPERATURE[props.api_mode]
47+
) {
48+
description_parts.push(`${configuration.temperature}`)
49+
}
50+
if (configuration.cache_enabled) {
51+
description_parts.push('cache-enabled')
52+
}
53+
54+
const description = description_parts.join(' · ')
55+
56+
return (
57+
<div
58+
key={configuration.id}
59+
className={cn(styles.configurations__item, {
60+
[styles['configurations__item--highlighted']]:
61+
props.selected_configuration_id == configuration.id
62+
})}
63+
onClick={() => {
64+
props.on_configuration_click(configuration.id)
65+
}}
66+
role="button"
67+
>
68+
<div className={styles.configurations__item__left}>
69+
<div
70+
className={cn(styles.configurations__item__left__drag_handle, {
71+
[styles['configurations__item__left__drag_handle--disabled']]:
72+
!props.on_reorder || configuration.is_pinned
73+
})}
74+
onClick={(e) => e.stopPropagation()}
75+
>
76+
<span className="codicon codicon-gripper" />
77+
</div>
78+
<div className={styles.configurations__item__left__text}>
79+
<span>{configuration.model}</span>
80+
<span>{description}</span>
81+
</div>
82+
</div>
83+
{props.on_toggle_pinned && (
84+
<div
85+
className={styles.configurations__item__right}
86+
onClick={(e) => e.stopPropagation()}
87+
>
88+
<IconButton
89+
codicon_icon={configuration.is_pinned ? 'pinned' : 'pin'}
90+
title={configuration.is_pinned ? 'Unpin' : 'Pin'}
91+
on_click={(e) => {
92+
e.stopPropagation()
93+
props.on_toggle_pinned?.(configuration.id)
94+
}}
95+
/>
96+
</div>
97+
)}
98+
</div>
99+
)
100+
}
101+
30102
return (
31103
<div className={styles.container}>
104+
{pinned_configurations.length > 0 && (
105+
<div className={styles.configurations}>
106+
{pinned_configurations.map(renderConfigurationItem)}
107+
</div>
108+
)}
32109
<div
33110
className={styles.header}
34111
onClick={() => props.on_toggle_collapsed(!props.is_collapsed)}
@@ -58,68 +135,17 @@ export const Configurations: React.FC<Configurations.Props> = (props) => {
58135
<>
59136
<div className={styles.configurations}>
60137
<ReactSortable
61-
list={props.configurations}
138+
list={unpinned_configurations}
62139
setList={(new_state) => {
63140
if (props.on_reorder) {
64-
props.on_reorder(new_state)
141+
props.on_reorder([...pinned_configurations, ...new_state])
65142
}
66143
}}
67144
animation={150}
68145
handle={`.${styles.configurations__item__left__drag_handle}`}
69146
disabled={!props.on_reorder}
70147
>
71-
{props.configurations.map((configuration) => {
72-
const description_parts = [configuration.provider]
73-
if (configuration.reasoning_effort) {
74-
description_parts.push(`${configuration.reasoning_effort}`)
75-
}
76-
if (
77-
configuration.temperature &&
78-
configuration.temperature !=
79-
DEFAULT_TEMPERATURE[props.api_mode]
80-
) {
81-
description_parts.push(`${configuration.temperature}`)
82-
}
83-
if (configuration.cache_enabled) {
84-
description_parts.push('cache-enabled')
85-
}
86-
87-
const description = description_parts.join(' · ')
88-
89-
return (
90-
<div
91-
key={configuration.id}
92-
className={cn(styles.configurations__item, {
93-
[styles['configurations__item--highlighted']]:
94-
props.selected_configuration_id == configuration.id
95-
})}
96-
onClick={() => {
97-
props.on_configuration_click(configuration.id)
98-
}}
99-
role="button"
100-
>
101-
<div className={styles.configurations__item__left}>
102-
<div
103-
className={cn(
104-
styles.configurations__item__left__drag_handle,
105-
{
106-
[styles[
107-
'configurations__item__left__drag_handle--disabled'
108-
]]: !props.on_reorder
109-
}
110-
)}
111-
onClick={(e) => e.stopPropagation()}
112-
>
113-
<span className="codicon codicon-gripper" />
114-
</div>
115-
<div className={styles.configurations__item__left__text}>
116-
<span>{configuration.model}</span>
117-
<span>{description}</span>
118-
</div>
119-
</div>
120-
</div>
121-
)
122-
})}
148+
{unpinned_configurations.map(renderConfigurationItem)}
123149
</ReactSortable>
124150
</div>
125151
</>

0 commit comments

Comments
 (0)