22import { ref , computed } from " vue" ;
33import { useRouter } from " vue-router" ;
44import FAIcon from " @/components/FAIcon.vue" ;
5- import { type IconDefinition , faCircle , faTimes } from " @fortawesome/free-solid-svg-icons" ;
5+ import { faCircle , faTimes } from " @fortawesome/free-solid-svg-icons" ;
66import type { StatusIndicator , WizardPage } from " @/components/platformcapabilities/types" ;
77import { Capability , CapabilityStatus } from " @/components/platformcapabilities/constants" ;
88import WizardDialog from " ./WizardDialog.vue" ;
@@ -15,7 +15,6 @@ const emit = defineEmits<{
1515
1616const props = defineProps <{
1717 status: CapabilityStatus ;
18- icon: IconDefinition ;
1918 title: Capability ;
2019 subtitle: string ;
2120 helpButtonText: string ;
@@ -32,6 +31,8 @@ const shouldShowWizard = computed(() => {
3231 return props .wizardPages && props .wizardPages .length > 0 && (props .status === CapabilityStatus .EndpointsNotConfigured || props .status === CapabilityStatus .InstanceNotConfigured );
3332});
3433
34+ const dataStatus = computed (() => (props .isLoading ? " loading" : props .status .toLowerCase ().replace (/ / g , " -" )));
35+
3536function isExternalUrl(url : string ): boolean {
3637 return url .startsWith (" http://" ) || url .startsWith (" https://" );
3738}
@@ -48,73 +49,52 @@ function handleButtonClick() {
4849 </script >
4950
5051<template >
51- <div
52- class =" capability-card"
53- data-testid =" capability-card"
54- :class =" {
55- 'capability-available': !props.isLoading && props.status === CapabilityStatus.Available,
56- 'capability-unavailable': !props.isLoading && props.status === CapabilityStatus.Unavailable,
57- 'capability-partially-unavailable': !props.isLoading && props.status === CapabilityStatus.PartiallyUnavailable,
58- 'capability-loading': props.isLoading,
59- 'capability-notconfigured': !props.isLoading && (props.status === CapabilityStatus.EndpointsNotConfigured || props.status === CapabilityStatus.InstanceNotConfigured),
60- }"
61- >
52+ <div class =" capability-card" data-testid =" capability-card" :data-status =" dataStatus" >
6253 <div v-if =" props.isLoading" class =" loading-overlay" >
6354 <div class =" loading-spinner" ></div >
6455 <div class =" loading-text" >Loading {{ props.title }} capability status...</div >
6556 </div >
66- <button class =" hide-card-btn" @click =" emit('hide')" v-tippy =" 'Hide this card'" >
67- <FAIcon :icon =" faTimes " />
68- </button >
6957 <div v-if =" !props.isLoading" class =" capability-header" >
70- <FAIcon
71- :icon =" props .icon "
72- class="capability-icon"
73- :class =" {
74- ' text-success' : props .status === CapabilityStatus .Available ,
75- ' text-danger' : props .status === CapabilityStatus .Unavailable ,
76- ' text-warning' : props .status === CapabilityStatus .PartiallyUnavailable ,
77- ' text-info' : props .status === CapabilityStatus .EndpointsNotConfigured || props .status === CapabilityStatus .InstanceNotConfigured ,
78- } "
79- />
80- <div class =" capability-info" >
81- <div class =" capability-title-row" >
82- <h6 class =" capability-title" >{{ props.title }}</h6 >
83- <div v-if =" props.indicators" class =" status-indicators" >
84- <div v-for =" indicator in props.indicators" :key =" indicator.label" class =" indicator-item" data-testid =" status-indicator" v-tippy =" indicator.tooltip" >
85- <FAIcon
86- :icon =" faCircle "
87- class="indicator-light"
88- :class =" {
89- ' light-success' : indicator .status === CapabilityStatus .Available ,
90- ' light-warning' : indicator .status === CapabilityStatus .EndpointsNotConfigured || indicator .status === CapabilityStatus .PartiallyUnavailable ,
91- ' light-danger' : indicator .status === CapabilityStatus .Unavailable ,
92- } "
93- />
94- <span class =" indicator-label" >{{ indicator.label }}</span >
95- </div >
58+ <div class =" capability-title-row" >
59+ <h6 class =" capability-title" >{{ props.title }}</h6 >
60+ <div v-if =" props.indicators" class =" status-indicators" >
61+ <div v-for =" indicator in props.indicators" :key =" indicator.label" class =" indicator-item" data-testid =" status-indicator" v-tippy =" indicator.tooltip" >
62+ <FAIcon
63+ :icon =" faCircle "
64+ class="indicator-light"
65+ :class =" {
66+ ' light-success' : indicator .status === CapabilityStatus .Available ,
67+ ' light-warning' : indicator .status === CapabilityStatus .EndpointsNotConfigured || indicator .status === CapabilityStatus .PartiallyUnavailable ,
68+ ' light-danger' : indicator .status === CapabilityStatus .Unavailable ,
69+ } "
70+ />
71+ <span class =" indicator-label" >{{ indicator.label }}</span >
9672 </div >
9773 </div >
98- <div class =" capability-subtitle" >{{ props.subtitle }}</div >
99- </div >
100- <div v-if =" props.status !== CapabilityStatus.EndpointsNotConfigured && props.status !== CapabilityStatus.InstanceNotConfigured" class =" capability-status" >
101- <span
102- class =" status-badge"
103- :class =" {
104- 'status-available': props.status === CapabilityStatus.Available,
105- 'status-unavailable': props.status === CapabilityStatus.Unavailable,
106- 'status-partially-unavailable': props.status === CapabilityStatus.PartiallyUnavailable,
107- }"
108- >
109- {{ props.status }}
110- </span >
74+ <div class =" title-row-actions" >
75+ <span
76+ v-if =" props.status !== CapabilityStatus.EndpointsNotConfigured && props.status !== CapabilityStatus.InstanceNotConfigured"
77+ class =" status-badge"
78+ :class =" {
79+ 'status-available': props.status === CapabilityStatus.Available,
80+ 'status-unavailable': props.status === CapabilityStatus.Unavailable,
81+ 'status-partially-unavailable': props.status === CapabilityStatus.PartiallyUnavailable,
82+ }"
83+ >
84+ {{ props.status }}
85+ </span >
86+ <button class =" hide-card-btn" @click =" emit('hide')" v-tippy =" 'Hide this card'" >
87+ <FAIcon :icon =" faTimes " />
88+ </button >
89+ </div >
11190 </div >
91+ <div class =" capability-subtitle" >{{ props.subtitle }}</div >
11292 </div >
11393 <div v-if =" !props.isLoading" class =" capability-footer" >
11494 <div class =" capability-description" >
11595 {{ props.description }}
11696 </div >
117- <button class =" btn-primary learn-more- btn" @click =" handleButtonClick" >
97+ <button class =" btn btn-primary " @click =" handleButtonClick" >
11898 {{ props.helpButtonText }}
11999 </button >
120100 </div >
@@ -125,69 +105,30 @@ function handleButtonClick() {
125105
126106<style scoped>
127107.capability-card {
128- background : var (--card-bg , #fff );
129- border : 1px solid var (--border-color , #e0e0e0 );
130- border-radius : 8px ;
108+ background : #fff ;
109+ border-top : 1px solid #eee ;
110+ border-right : 1px solid #fff ;
111+ border-bottom : 1px solid #eee ;
112+ border-left : 1px solid #fff ;
131113 padding : 20px ;
132- margin-bottom : 16px ;
133- transition : all 0.2s ease ;
134114 position : relative ;
135115 min-height : 150px ;
136116}
137117
138118.hide-card-btn {
139- position : absolute ;
140- top : 8px ;
141- right : 8px ;
142119 background : none ;
143120 border : none ;
144- color : var ( --text-secondary , #999 ) ;
121+ color : #999 ;
145122 cursor : pointer ;
146123 padding : 4px 6px ;
147124 border-radius : 4px ;
148- opacity : 0 ;
149- transition : all 0.2s ease ;
150125 font-size : 12px ;
151- z-index : 5 ;
152- }
153-
154- .capability-card :hover .hide-card-btn {
155- opacity : 1 ;
126+ flex-shrink : 0 ;
156127}
157128
158129.hide-card-btn :hover {
159- background-color : var (--hover-bg , #f0f0f0 );
160- color : var (--text-primary , #333 );
161- }
162-
163- .capability-available {
164- border-left : 4px solid var (--success-color , #28a745 );
165- }
166-
167- .capability-unavailable {
168- border-left : 4px solid var (--danger-color , #dc3545 );
169- }
170-
171- .capability-partially-unavailable {
172- border-left : 4px solid var (--warning-color , #ffc107 );
173- }
174-
175- .capability-loading {
176- border-left : 4px solid var (--border-color , #e0e0e0 );
177- }
178-
179- .capability-notconfigured {
180- background : linear-gradient (135deg , #f6f9fc 0% , #e9f2f9 100% );
181- border : 1px solid #c3ddf5 ;
182- border-left : 4px solid #007bff ;
183- }
184-
185- .text-info {
186- color : #007bff ;
187- }
188-
189- .text-warning {
190- color : var (--warning-color , #ffc107 );
130+ background-color : #f0f0f0 ;
131+ color : #333 ;
191132}
192133
193134.loading-overlay {
@@ -201,15 +142,14 @@ function handleButtonClick() {
201142 flex-direction : column ;
202143 align-items : center ;
203144 justify-content : center ;
204- border-radius : 8px ;
205145 z-index : 10 ;
206146}
207147
208148.loading-spinner {
209149 width : 40px ;
210150 height : 40px ;
211- border : 3px solid var ( --border-color , #e0e0e0 ) ;
212- border-top-color : var (--primary-color , #007bff );
151+ border : 3px solid #e0e0e0 ;
152+ border-top-color : var (--sp-blue );
213153 border-radius : 50% ;
214154 animation : spin 0.8s linear infinite ;
215155}
@@ -222,39 +162,27 @@ function handleButtonClick() {
222162
223163.loading-text {
224164 margin-top : 12px ;
225- color : var ( --text-secondary , #666 ) ;
165+ color : #666 ;
226166 font-size : 14px ;
227167}
228168
229169.capability-header {
230- display : flex ;
231- align-items : flex-start ;
232- gap : 16px ;
233170 margin-bottom : 12px ;
234171}
235172
236- .capability-icon {
237- font-size : 24px ;
238- flex-shrink : 0 ;
239- margin-top : 2px ;
240- }
241-
242- .capability-info {
243- flex : 1 ;
244- min-width : 0 ;
245- }
246-
247173.capability-title-row {
248174 display : flex ;
249175 align-items : center ;
250- gap : 12px ;
176+ flex-wrap : wrap ;
177+ gap : 8px ;
251178 margin-bottom : 4px ;
252179}
253180
254181.capability-title {
255182 font-size : 18px ;
256183 font-weight : 600 ;
257- color : var (--text-primary , #333 );
184+ color : #333 ;
185+ margin : 0 ;
258186}
259187
260188.status-indicators {
@@ -275,37 +203,39 @@ function handleButtonClick() {
275203}
276204
277205.light-success {
278- color : var ( --success-color , #28a745 ) ;
206+ color : #28a745 ;
279207}
280208
281209.light-warning {
282- color : var ( --warning-color , #ffc107 ) ;
210+ color : #ffc107 ;
283211}
284212
285213.light-danger {
286- color : var ( --danger-color , #dc3545 ) ;
214+ color : #dc3545 ;
287215}
288216
289217.indicator-label {
290218 font-size : 12px ;
291- color : var ( --text-secondary , #666 ) ;
219+ color : #666 ;
292220 white-space : nowrap ;
293221}
294222
295223.capability-subtitle {
296224 font-size : 14px ;
297- color : var ( --text-secondary , #666 ) ;
225+ color : #666 ;
298226 line-height : 1.4 ;
299227}
300228
301- .capability-status {
229+ .title-row-actions {
302230 display : flex ;
303- flex-direction : column ;
304- align-items : flex-end ;
305- gap : 4px ;
231+ align-items : center ;
232+ gap : 8px ;
233+ margin-left : auto ;
234+ flex-shrink : 0 ;
306235}
307236
308237.status-badge {
238+ white-space : nowrap ;
309239 padding : 4px 12px ;
310240 border-radius : 12px ;
311241 font-size : 12px ;
@@ -332,68 +262,17 @@ function handleButtonClick() {
332262.capability-footer {
333263 display : flex ;
334264 justify-content : space-between ;
335- align-items : center ;
265+ align-items : flex-start ;
336266 gap : 16px ;
337267 margin-top : 12px ;
338268 padding-top : 12px ;
339- border-top : 1px solid var ( --border-color , #e0e0e0 ) ;
269+ border-top : 1px solid #eee ;
340270}
341271
342272.capability-description {
343273 flex : 1 ;
344274 font-size : 13px ;
345- color : var ( --text-secondary , #666 ) ;
275+ color : #666 ;
346276 line-height : 1.5 ;
347- overflow : hidden ;
348- text-overflow : ellipsis ;
349- display : -webkit-box ;
350- -webkit-line-clamp : 2 ;
351- line-clamp : 2 ;
352- -webkit-box-orient : vertical ;
353- }
354-
355- .learn-more-btn {
356- padding : 8px 16px ;
357- border-radius : 4px ;
358- text-decoration : none ;
359- font-size : 14px ;
360- font-weight : 500 ;
361- transition : all 0.2s ease ;
362- white-space : nowrap ;
363- border : 1px solid transparent ;
364- }
365-
366- .learn-more-btn.btn-primary {
367- background-color : var (--primary-color , #007bff );
368- color : white ;
369- border-color : var (--primary-color , #007bff );
370- }
371-
372- .learn-more-btn.btn-primary :hover {
373- background-color : var (--primary-hover-color , #0056b3 );
374- border-color : var (--primary-hover-color , #0056b3 );
375- }
376-
377- /* Responsive adjustments */
378- @media (max-width : 768px ) {
379- .capability-header {
380- flex-direction : column ;
381- }
382-
383- .capability-status {
384- align-items : flex-start ;
385- flex-direction : row ;
386- gap : 8px ;
387- }
388-
389- .capability-footer {
390- flex-direction : column ;
391- align-items : flex-start ;
392- }
393-
394- .learn-more-btn {
395- width : 100% ;
396- text-align : center ;
397- }
398277}
399278 </style >
0 commit comments