5
5
*/
6
6
7
7
import { GitpodHostUrl } from "@gitpod/gitpod-protocol/lib/util/gitpod-host-url" ;
8
- import { FunctionComponent , useMemo , useState } from "react" ;
9
- import { Item , ItemField , ItemFieldIcon } from "../components/ItemsList" ;
8
+ import { FunctionComponent , useCallback , useMemo , useState } from "react" ;
9
+ import { Item , ItemFieldIcon } from "../components/ItemsList" ;
10
10
import PendingChangesDropdown from "../components/PendingChangesDropdown" ;
11
11
import Tooltip from "../components/Tooltip" ;
12
12
import dayjs from "dayjs" ;
13
13
import { WorkspaceEntryOverflowMenu } from "./WorkspaceOverflowMenu" ;
14
14
import { WorkspaceStatusIndicator } from "./WorkspaceStatusIndicator" ;
15
15
import { Workspace } from "@gitpod/public-api/lib/gitpod/v1/workspace_pb" ;
16
+ import { GitBranchIcon , PinIcon } from "lucide-react" ;
17
+ import { useUpdateWorkspaceMutation } from "../data/workspaces/update-workspace-mutation" ;
16
18
17
19
type Props = {
18
20
info : Workspace ;
@@ -21,19 +23,27 @@ type Props = {
21
23
22
24
export const WorkspaceEntry : FunctionComponent < Props > = ( { info, shortVersion } ) => {
23
25
const [ menuActive , setMenuActive ] = useState ( false ) ;
26
+ const updateWorkspace = useUpdateWorkspaceMutation ( ) ;
24
27
25
28
const gitStatus = info . status ?. gitStatus ;
26
29
27
30
const workspace = info ;
28
31
const currentBranch = gitStatus ?. branch || "<unknown>" ;
29
32
const project = getProjectPath ( workspace ) ;
30
- const normalizedContextUrl = workspace . metadata ! . originalContextUrl ;
31
- const normalizedContextUrlDescription = workspace . metadata ! . originalContextUrl ; // Instead of showing nothing, we prefer to show the raw content instead
32
33
33
34
const changeMenuState = ( state : boolean ) => {
34
35
setMenuActive ( state ) ;
35
36
} ;
36
37
38
+ const togglePinned = useCallback ( ( ) => {
39
+ updateWorkspace . mutate ( {
40
+ workspaceId : workspace . id ,
41
+ metadata : {
42
+ pinned : ! workspace . metadata ?. pinned ,
43
+ } ,
44
+ } ) ;
45
+ } , [ updateWorkspace , workspace . id , workspace . metadata ?. pinned ] ) ;
46
+
37
47
// Could this be `/start#${workspace.id}` instead?
38
48
const startUrl = useMemo (
39
49
( ) =>
@@ -47,11 +57,11 @@ export const WorkspaceEntry: FunctionComponent<Props> = ({ info, shortVersion })
47
57
) ;
48
58
49
59
return (
50
- < Item className = "whitespace-nowrap py-6 px-6 " solid = { menuActive } >
60
+ < Item className = "whitespace-nowrap py-6" solid = { menuActive } >
51
61
< ItemFieldIcon >
52
62
< WorkspaceStatusIndicator status = { workspace ?. status } />
53
63
</ ItemFieldIcon >
54
- < ItemField className = "w-3/12 flex flex-col my -auto" >
64
+ < div className = "flex-grow flex flex-col h-full py -auto" >
55
65
< a href = { startUrl } >
56
66
< div className = "font-medium text-gray-800 dark:text-gray-200 truncate hover:text-blue-600 dark:hover:text-blue-400" >
57
67
{ info . id }
@@ -64,28 +74,19 @@ export const WorkspaceEntry: FunctionComponent<Props> = ({ info, shortVersion })
64
74
</ div >
65
75
</ a >
66
76
</ Tooltip >
67
- </ ItemField >
77
+ </ div >
68
78
{ ! shortVersion && (
69
79
< >
70
- < ItemField className = "w-4/12 flex flex-col my-auto" >
71
- < div className = "text-gray-500 dark:text-gray-400 overflow-ellipsis truncate" >
72
- { workspace . metadata ! . name }
73
- </ div >
74
- < a href = { normalizedContextUrl } >
75
- < div className = "text-sm text-gray-400 dark:text-gray-500 overflow-ellipsis truncate hover:text-blue-600 dark:hover:text-blue-400" >
76
- { normalizedContextUrlDescription }
77
- </ div >
78
- </ a >
79
- </ ItemField >
80
- < ItemField className = "w-2/12 flex flex-col my-auto" >
81
- < div className = "text-gray-500 dark:text-gray-400 overflow-ellipsis truncate" >
80
+ < div className = "w-3/12 flex flex-col lg:flex-row lg:items-center lg:gap-6 justify-between px-3" >
81
+ < div className = "text-gray-500 dark:text-gray-400 overflow-ellipsis truncate flex flex-row gap-1 items-center" >
82
+ < GitBranchIcon className = "h-4 w-4" />
82
83
< Tooltip content = { currentBranch } > { currentBranch } </ Tooltip >
83
84
</ div >
84
85
< div className = "mr-auto" >
85
86
< PendingChangesDropdown gitStatus = { gitStatus } />
86
87
</ div >
87
- </ ItemField >
88
- < ItemField className = "w-2/12 flex my-auto " >
88
+ </ div >
89
+ < div className = "w-2/12 px-3 flex items-center min-w " >
89
90
< Tooltip
90
91
content = { `Last Activate ${ dayjs (
91
92
info . status ! . phase ! . lastTransitionTime ! . toDate ( ) ,
@@ -95,7 +96,26 @@ export const WorkspaceEntry: FunctionComponent<Props> = ({ info, shortVersion })
95
96
{ dayjs ( info . status ?. phase ?. lastTransitionTime ?. toDate ( ) ?? new Date ( ) ) . fromNow ( ) }
96
97
</ div >
97
98
</ Tooltip >
98
- </ ItemField >
99
+ </ div >
100
+ < div className = "px-3 flex items-center" >
101
+ < div
102
+ className = {
103
+ "px-2 flex items-center hover:bg-gray-200 dark:hover:bg-gray-700 rounded-md cursor-pointer h-8 w-8"
104
+ }
105
+ >
106
+ < Tooltip content = { workspace . metadata ?. pinned ? "Unpin" : "Pin" } >
107
+ < PinIcon
108
+ onClick = { togglePinned }
109
+ className = {
110
+ "w-4 h-4 self-center " +
111
+ ( workspace . metadata ?. pinned
112
+ ? "text-gray-600 dark:text-gray-300"
113
+ : "text-gray-300 dark:text-500 hover:text-gray-600 dark:hover:text-gray-300" )
114
+ }
115
+ />
116
+ </ Tooltip >
117
+ </ div >
118
+ </ div >
99
119
< WorkspaceEntryOverflowMenu changeMenuState = { changeMenuState } info = { info } />
100
120
</ >
101
121
) }
0 commit comments