@@ -16,6 +16,7 @@ import Pagination from "../components/Pagination";
16
16
import Header from "../components/Header" ;
17
17
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error" ;
18
18
import { FeatureFlagContext } from "../contexts/FeatureFlagContext" ;
19
+ import { ReactComponent as CreditsSvg } from "../images/credits.svg" ;
19
20
20
21
function TeamUsage ( ) {
21
22
const { teams } = useContext ( TeamsContext ) ;
@@ -28,8 +29,9 @@ function TeamUsage() {
28
29
const [ errorMessage , setErrorMessage ] = useState ( "" ) ;
29
30
const today = new Date ( ) ;
30
31
const startOfCurrentMonth = new Date ( today . getFullYear ( ) , today . getMonth ( ) , 1 ) ;
31
- const timestampOfStart = startOfCurrentMonth . getTime ( ) ;
32
- const [ startDateOfBillMonth ] = useState ( timestampOfStart ) ;
32
+ const timestampStartOfCurrentMonth = startOfCurrentMonth . getTime ( ) ;
33
+ const [ startDateOfBillMonth , setStartDateOfBillMonth ] = useState ( timestampStartOfCurrentMonth ) ;
34
+ const [ endDateOfBillMonth , setEndDateOfBillMonth ] = useState ( Date . now ( ) ) ;
33
35
34
36
useEffect ( ( ) => {
35
37
if ( ! team ) {
@@ -40,8 +42,8 @@ function TeamUsage() {
40
42
try {
41
43
const billedUsageResult = await getGitpodService ( ) . server . listBilledUsage (
42
44
attributionId ,
43
- startDateOfBillMonth , // TODO: set based on selected month
44
- Date . now ( ) , // TODO: set based on selected month
45
+ startDateOfBillMonth ,
46
+ endDateOfBillMonth ,
45
47
) ;
46
48
setBilledUsage ( billedUsageResult ) ;
47
49
} catch ( error ) {
@@ -50,7 +52,7 @@ function TeamUsage() {
50
52
}
51
53
}
52
54
} ) ( ) ;
53
- } , [ team ] ) ;
55
+ } , [ team , startDateOfBillMonth , endDateOfBillMonth ] ) ;
54
56
55
57
if ( ! showUsageBasedPricingUI ) {
56
58
return < Redirect to = "/" /> ;
@@ -79,7 +81,34 @@ function TeamUsage() {
79
81
const calculateTotalUsage = ( ) => {
80
82
let totalCredits = 0 ;
81
83
billedUsage . forEach ( ( session ) => ( totalCredits += session . credits ) ) ;
82
- return totalCredits ;
84
+ return totalCredits . toFixed ( 2 ) ;
85
+ } ;
86
+
87
+ const handleMonthClick = ( start : any , end : any ) => {
88
+ setStartDateOfBillMonth ( start ) ;
89
+ setEndDateOfBillMonth ( end ) ;
90
+ } ;
91
+
92
+ const getBillingHistory = ( ) => {
93
+ let rows = [ ] ;
94
+ // This goes back 6 months from the current month
95
+ for ( let i = 1 ; i < 7 ; i ++ ) {
96
+ const endDateVar = i - 1 ;
97
+ const startDate = new Date ( today . getFullYear ( ) , today . getMonth ( ) - i ) ;
98
+ const endDate = new Date ( today . getFullYear ( ) , today . getMonth ( ) - endDateVar , 0 ) ;
99
+ const timeStampOfStartDate = startDate . getTime ( ) ;
100
+ const timeStampOfEndDate = endDate . getTime ( ) ;
101
+ rows . push (
102
+ < div
103
+ key = { `billing${ i } ` }
104
+ className = "text-sm text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-500 truncate cursor-pointer gp-link"
105
+ onClick = { ( ) => handleMonthClick ( timeStampOfStartDate , timeStampOfEndDate ) }
106
+ >
107
+ { startDate . toLocaleString ( "default" , { month : "long" } ) } { startDate . getFullYear ( ) }
108
+ </ div > ,
109
+ ) ;
110
+ }
111
+ return rows ;
83
112
} ;
84
113
85
114
const lastResultOnCurrentPage = currentPage * resultsPerPage ;
@@ -90,50 +119,29 @@ function TeamUsage() {
90
119
return (
91
120
< >
92
121
< Header title = "Usage" subtitle = "Manage team usage." />
93
- < div className = "app-container pt-9 " >
122
+ < div className = "app-container pt-5 " >
94
123
{ errorMessage && < p className = "text-base" > { errorMessage } </ p > }
95
124
{ ! errorMessage && (
96
125
< div className = "flex space-x-16" >
97
126
< div className = "flex" >
98
127
< div className = "space-y-8 mb-6" style = { { width : "max-content" } } >
99
128
< div className = "flex flex-col truncate" >
100
- < div className = "text-base text-gray-500 truncate" > Period</ div >
101
- < div className = "text-lg text-gray-600 font-semibold truncate" >
129
+ < div className = "text-base text-gray-500 truncate" > Current Month</ div >
130
+ < div
131
+ className = "text-sm text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-500 truncate cursor-pointer mb-5"
132
+ onClick = { ( ) => handleMonthClick ( timestampStartOfCurrentMonth , Date . now ( ) ) }
133
+ >
102
134
{ startOfCurrentMonth . toLocaleString ( "default" , { month : "long" } ) } { " " }
103
135
{ startOfCurrentMonth . getFullYear ( ) }
104
136
</ div >
137
+ < div className = "text-base text-gray-500 truncate" > Previous Months</ div >
138
+ { getBillingHistory ( ) }
105
139
</ div >
106
140
< div className = "flex flex-col truncate" >
107
141
< div className = "text-base text-gray-500" > Total usage</ div >
108
142
< div className = "flex text-lg text-gray-600 font-semibold" >
109
- < svg
110
- className = "my-auto mr-1"
111
- width = "20"
112
- height = "20"
113
- fill = "none"
114
- xmlns = "http://www.w3.org/2000/svg"
115
- >
116
- < path
117
- fill-rule = "evenodd"
118
- clip-rule = "evenodd"
119
- d = "M5 2a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3H5Zm5.2 11.4a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4Z"
120
- fill = "url(#a)"
121
- />
122
- < defs >
123
- < linearGradient
124
- id = "a"
125
- x1 = "4.3"
126
- y1 = "4.3"
127
- x2 = "16.071"
128
- y2 = "17.107"
129
- gradientUnits = "userSpaceOnUse"
130
- >
131
- < stop stop-color = "#FFAD33" />
132
- < stop offset = "1" stop-color = "#FF8A00" />
133
- </ linearGradient >
134
- </ defs >
135
- </ svg >
136
- < span > { calculateTotalUsage ( ) } Total Credits</ span >
143
+ < CreditsSvg className = "my-auto mr-1" />
144
+ < span > { calculateTotalUsage ( ) } Credits</ span >
137
145
</ div >
138
146
</ div >
139
147
</ div >
@@ -147,14 +155,16 @@ function TeamUsage() {
147
155
{ " " }
148
156
workspaces
149
157
</ a > { " " }
150
- or checked your other teams?
158
+ in{ " " }
159
+ { new Date ( startDateOfBillMonth ) . toLocaleString ( "default" , {
160
+ month : "long" ,
161
+ } ) } { " " }
162
+ { new Date ( startDateOfBillMonth ) . getFullYear ( ) } or checked your other teams?
151
163
</ p >
152
164
</ div >
153
165
) }
154
166
{ billedUsage . length > 0 && (
155
167
< div className = "flex flex-col w-full mb-8" >
156
- < h3 > All Usage</ h3 >
157
- < span className = "text-gray-500 mb-5" > View usage details of all team members.</ span >
158
168
< ItemsList className = "mt-2 text-gray-500" >
159
169
< Item header = { false } className = "grid grid-cols-5 bg-gray-100 mb-5" >
160
170
< ItemField className = "my-auto" >
@@ -167,33 +177,7 @@ function TeamUsage() {
167
177
< span > Usage</ span >
168
178
</ ItemField >
169
179
< ItemField className = "flex my-auto" >
170
- < svg
171
- className = "my-auto mr-1"
172
- width = "20"
173
- height = "20"
174
- fill = "none"
175
- xmlns = "http://www.w3.org/2000/svg"
176
- >
177
- < path
178
- fill-rule = "evenodd"
179
- clip-rule = "evenodd"
180
- d = "M5 2a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3H5Zm5.2 11.4a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4Z"
181
- fill = "url(#a)"
182
- />
183
- < defs >
184
- < linearGradient
185
- id = "a"
186
- x1 = "4.3"
187
- y1 = "4.3"
188
- x2 = "16.071"
189
- y2 = "17.107"
190
- gradientUnits = "userSpaceOnUse"
191
- >
192
- < stop stop-color = "#FFAD33" />
193
- < stop offset = "1" stop-color = "#FF8A00" />
194
- </ linearGradient >
195
- </ defs >
196
- </ svg >
180
+ < CreditsSvg className = "my-auto mr-1" />
197
181
< span > Credits</ span >
198
182
</ ItemField >
199
183
< ItemField className = "my-auto" />
0 commit comments