Skip to content

Commit 02054a8

Browse files
authored
Merge pull request #670 from amarie401/pf-cards-loading
feat(pfCard): Add a loading state to the pfCards
2 parents d3164e0 + c6b6f0f commit 02054a8

File tree

8 files changed

+352
-85
lines changed

8 files changed

+352
-85
lines changed

src/card/aggregate-status/aggregate-status-card.component.js

Lines changed: 122 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
* </ul>
3131
* </ul>
3232
* @param {boolean=} show-top-border Show/hide the top border, true shows top border, false (default) hides top border
33+
* @param {boolean=} showSpinner Show/Hide the spinner for loading state. True shows the spinner, false (default) hides the spinner
34+
* @param {string=} spinnerText Text for the card spinner
35+
* @param {string=} spinnerCardHeight Height to set for the card when data is loading and spinner is shown
3336
* @param {string=} layout Various alternative layouts the aggregate status card may have:<br/>
3437
* <ul style='list-style-type: none'>
3538
* <li>'mini' displays a mini aggregate status card. Note: when using 'mini' layout, only one notification can be specified in the status object
@@ -44,50 +47,75 @@
4447
<example module="patternfly.card">
4548
4649
<file name="index.html">
47-
<div ng-controller="CardDemoCtrl" style="display:inline-block;">
48-
<div class="col-md-10">
49-
<label>With Top Border</label>
50-
<pf-aggregate-status-card status="status" show-top-border="true"></pf-aggregate-status-card>
51-
<br/>
52-
<label>No Top Border</label>
53-
<pf-aggregate-status-card status="status"></pf-aggregate-status-card>
54-
<br/>
55-
<label>layout = "mini"</label>
56-
<pf-aggregate-status-card status="miniAggStatus" show-top-border="true" layout="mini"></pf-aggregate-status-card>
57-
<pf-aggregate-status-card status="miniAggStatus2" show-top-border="true" layout="mini"></pf-aggregate-status-card>
58-
<br/>
59-
<label>layout = "tall"</label>
60-
<pf-aggregate-status-card status="aggStatusAlt" show-top-border="true" layout="tall"></pf-aggregate-status-card>
61-
<br/>
62-
<label>Alternate Layout</label>
63-
<i>(depreciated, use layout = 'tall' instead)</i>
64-
</br></br>
65-
<pf-aggregate-status-card status="aggStatusAlt" show-top-border="true" alt-layout="true"></pf-aggregate-status-card>
50+
<div ng-controller="CardDemoCtrl" class="container-fluid">
51+
<div class="row">
52+
<div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
53+
<label>With Top Border</label>
54+
<pf-aggregate-status-card status="status" show-top-border="true" show-spinner="dataLoading" spinner-text="Loading" spinner-card-height="90"></pf-aggregate-status-card>
55+
</div>
56+
<div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
57+
<label>No Top Border</label>
58+
<pf-aggregate-status-card status="status2"></pf-aggregate-status-card>
59+
</div>
60+
</div>
61+
<div class="row">
62+
<div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
63+
<label>layout = "mini"</label>
64+
<pf-aggregate-status-card status="miniAggStatus" show-top-border="true" layout="mini"></pf-aggregate-status-card>
65+
<pf-aggregate-status-card status="miniAggStatus2" show-top-border="true" layout="mini"></pf-aggregate-status-card>
66+
</div>
67+
<div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
68+
<label>layout = "tall"</label>
69+
<pf-aggregate-status-card status="aggStatusAlt" show-top-border="true" layout="tall"></pf-aggregate-status-card>
70+
</div>
71+
</div>
72+
<div class="row">
73+
<div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
74+
<label>Alternate Layout</label>
75+
<br>
76+
<i>(depreciated, use layout = 'tall' instead)</i>
77+
<pf-aggregate-status-card status="aggStatusAlt" show-top-border="true" alt-layout="true"></pf-aggregate-status-card>
78+
</div>
79+
<div class="col-xs-12 col-sm-6 col-md-5 col-lg-4">
80+
<label>Loading State</label>
81+
<br>
82+
<br>
83+
<pf-aggregate-status-card status="aggStatusAlt2" spinner-card-height="140" show-top-border="true" show-spinner="dataLoading" spinner-text="Loading" layout="tall"></pf-aggregate-status-card>
84+
</div>
6685
</div>
6786
</div>
6887
</file>
6988
7089
<file name="script.js">
71-
angular.module( 'patternfly.card' ).controller( 'CardDemoCtrl', function( $scope, $window ) {
90+
angular.module( 'patternfly.card' ).controller( 'CardDemoCtrl', function( $scope, $window, $timeout ) {
7291
var imagePath = $window.IMAGE_PATH || "img";
92+
93+
$scope.dataLoading = true;
94+
7395
$scope.status = {
7496
"title":"Nodes",
75-
"count":793,
7697
"href":"#",
7798
"iconClass": "fa fa-shield",
78-
"notifications":[
79-
{
80-
"iconClass":"pficon pficon-error-circle-o",
81-
"count":4,
82-
"href":"#"
83-
},
84-
{
85-
"iconClass":"pficon pficon-warning-triangle-o",
86-
"count":1
87-
}
88-
]
99+
"notifications":[]
89100
};
90101
102+
$scope.status2 = {
103+
"title":"Nodes",
104+
"count":793,
105+
"href":"#",
106+
"iconClass": "fa fa-shield",
107+
"notifications":[
108+
{
109+
"iconClass":"pficon pficon-error-circle-o",
110+
"count":4,
111+
"href":"#"
112+
},
113+
{
114+
"iconClass":"pficon pficon-warning-triangle-o",
115+
"count":1
116+
}
117+
]
118+
};
91119
$scope.aggStatusAlt = {
92120
"title":"Providers",
93121
"count":3,
@@ -103,28 +131,72 @@
103131
"href":"#"
104132
}
105133
]
106-
};
134+
};
135+
136+
$scope.aggStatusAlt2 = {
137+
"title":"Providers",
138+
"notifications":[]
139+
};
140+
141+
$timeout(function () {
142+
$scope.dataLoading = false;
143+
144+
$scope.status = {
145+
"title":"Nodes",
146+
"count":793,
147+
"href":"#",
148+
"iconClass": "fa fa-shield",
149+
"notifications":[
150+
{
151+
"iconClass":"pficon pficon-error-circle-o",
152+
"count":4,
153+
"href":"#"
154+
},
155+
{
156+
"iconClass":"pficon pficon-warning-triangle-o",
157+
"count":1
158+
}
159+
]
160+
};
161+
162+
$scope.aggStatusAlt2 = {
163+
"title":"Providers",
164+
"count":3,
165+
"notifications":[
166+
{
167+
"iconImage": imagePath + "/kubernetes.svg",
168+
"count":1,
169+
"href":"#"
170+
},
171+
{
172+
"iconImage": imagePath + "/OpenShift-logo.svg",
173+
"count":2,
174+
"href":"#"
175+
}
176+
]
177+
};
178+
}, 6000 );
107179
108-
$scope.miniAggStatus = {
180+
$scope.miniAggStatus = {
109181
"iconClass":"pficon pficon-container-node",
110182
"title":"Nodes",
111183
"count":52,
112184
"href":"#",
113185
"notification": {
114-
"iconClass":"pficon pficon-error-circle-o",
115-
"count":3
116-
}
117-
};
186+
"iconClass":"pficon pficon-error-circle-o",
187+
"count":3
188+
}
189+
};
118190
119-
$scope.miniAggStatus2 = {
191+
$scope.miniAggStatus2 = {
120192
"iconClass":"pficon pficon-cluster",
121193
"title":"Adipiscing",
122194
"count":9,
123195
"href":"#",
124196
"notification":{
125-
"iconClass":"pficon pficon-ok"
126-
}
127-
};
197+
"iconClass":"pficon pficon-ok"
198+
}
199+
};
128200
});
129201
</file>
130202
@@ -135,6 +207,9 @@ angular.module( 'patternfly.card' ).component('pfAggregateStatusCard', {
135207
bindings: {
136208
status: '=',
137209
showTopBorder: '@?',
210+
showSpinner: '<?',
211+
spinnerText: '@?',
212+
spinnerCardHeight: '@?',
138213
altLayout: '@?',
139214
layout: '@?'
140215
},
@@ -146,6 +221,11 @@ angular.module( 'patternfly.card' ).component('pfAggregateStatusCard', {
146221
ctrl.shouldShowTopBorder = (ctrl.showTopBorder === 'true');
147222
ctrl.isAltLayout = (ctrl.altLayout === 'true' || ctrl.layout === 'tall');
148223
ctrl.isMiniLayout = (ctrl.layout === 'mini');
224+
ctrl.showSpinner = ctrl.showSpinner === true;
225+
226+
if (ctrl.spinnerCardHeight) {
227+
ctrl.spinnerHeight = {'height': ctrl.spinnerCardHeight};
228+
}
149229
};
150230
}
151231
});

src/card/aggregate-status/aggregate-status-card.html

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div ng-if="!$ctrl.isMiniLayout" class="card-pf card-pf-aggregate-status" ng-class="{'card-pf-accented': $ctrl.shouldShowTopBorder, 'card-pf-aggregate-status-alt': $ctrl.isAltLayout}">
1+
<div ng-if="!$ctrl.isMiniLayout" class="card-pf card-pf-aggregate-status" ng-class="{'card-pf-accented': $ctrl.shouldShowTopBorder, 'card-pf-aggregate-status-alt': $ctrl.isAltLayout}" ng-style="$ctrl.showSpinner ? $ctrl.spinnerHeight : {}">
22
<h2 class="card-pf-title">
33
<a href="{{$ctrl.status.href}}" ng-if="$ctrl.status.href">
44
<image ng-if="$ctrl.status.iconImage" ng-src="{{$ctrl.status.iconImage}}" alt="" class="card-pf-icon-image"></image>
@@ -13,8 +13,15 @@ <h2 class="card-pf-title">
1313
<span class="card-pf-aggregate-status-title">{{$ctrl.status.title}}</span>
1414
</span>
1515
</h2>
16-
<div class="card-pf-body">
17-
<p class="card-pf-aggregate-status-notifications">
16+
<div class="card-pf-body" ng-class="{'show-spinner': $ctrl.showSpinner}">
17+
<div ng-if="$ctrl.showSpinner" class="spinner-container">
18+
<div class="loading-indicator">
19+
<span class="spinner spinner-lg" aria-hidden="true"></span>
20+
<span ng-if="$ctrl.spinnerText" class="loading-text">{{$ctrl.spinnerText}}</span>
21+
<label ng-if="!$ctrl.spinnerText" class="sr-only">Loading</label>
22+
</div>
23+
</div>
24+
<p class="card-pf-aggregate-status-notifications" ng-class="{'hide-for-spinner': $ctrl.showSpinner}">
1825
<span class="card-pf-aggregate-status-notification" ng-repeat="notification in $ctrl.status.notifications">
1926
<a href="{{notification.href}}" ng-if="notification.href">
2027
<image ng-if="notification.iconImage" ng-src="{{notification.iconImage}}" alt="" class="card-pf-icon-image"></image>
@@ -28,7 +35,7 @@ <h2 class="card-pf-title">
2835
</p>
2936
</div>
3037
</div>
31-
<div ng-if="$ctrl.isMiniLayout" class="card-pf card-pf-aggregate-status card-pf-aggregate-status-mini" ng-class="{'card-pf-accented': $ctrl.shouldShowTopBorder}">
38+
<div ng-if="$ctrl.isMiniLayout" class="card-pf card-pf-aggregate-status card-pf-aggregate-status-mini" ng-class="{'card-pf-accented': $ctrl.shouldShowTopBorder}" ng-style="$ctrl.showSpinner ? $ctrl.spinnerHeight : {}">
3239
<h2 class="card-pf-title">
3340
<a ng-if="$ctrl.status.href" href="{{$ctrl.status.href}}">
3441
<image ng-if="$ctrl.status.iconImage" ng-src="{{$ctrl.status.iconImage}}" alt="" class="card-pf-icon-image"></image>
@@ -41,7 +48,14 @@ <h2 class="card-pf-title">
4148
{{$ctrl.status.title}}
4249
</span>
4350
</h2>
44-
<div class="card-pf-body">
51+
<div class="card-pf-body" ng-class="{'show-spinner': $ctrl.showSpinner}">
52+
<div ng-if="$ctrl.showSpinner" class="spinner-container">
53+
<div class="loading-indicator">
54+
<span class="spinner spinner-lg" aria-hidden="true"></span>
55+
<span ng-if="$ctrl.spinnerText" class="loading-text">{{$ctrl.spinnerText}}</span>
56+
<label ng-if="!$ctrl.spinnerText" class="sr-only">Loading</label>
57+
</div>
58+
</div>
4559
<p ng-if="$ctrl.status.notification.iconImage || $ctrl.status.notification.iconClass || $ctrl.status.notification.count" class="card-pf-aggregate-status-notifications">
4660
<span class="card-pf-aggregate-status-notification">
4761
<a ng-if="$ctrl.status.notification.href" href="{{$ctrl.status.notification.href}}">

src/card/card.less

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
}
3030
}
3131

32+
.card-pf.card-pf-aggregate-status .card-pf-body .spinner-container {
33+
position: static;
34+
}
35+
3236
.card-pf {
3337
.hide-for-spinner {
3438
opacity: 0;
@@ -64,6 +68,25 @@
6468
}
6569
}
6670

71+
.card-pf-info-status .card-pf-body .spinner-container{
72+
top: 0px;
73+
height: 100%;
74+
&.with-title {
75+
top: 12px;
76+
}
77+
}
78+
79+
.card-pf-aggregate-status-mini {
80+
.card-pf-body {
81+
&.show-spinner {
82+
height: 40px;
83+
}
84+
.spinner-container {
85+
top: -22px;
86+
}
87+
}
88+
}
89+
6790
.card-pf-heading-no-bottom {
6891
margin: 0 -20px 0px;
6992
padding: 0 20px 0;
@@ -112,7 +135,6 @@
112135

113136
.card-pf-info-status {
114137
display: flex;
115-
margin: 0 10px;
116138
.card-pf-info-image {
117139
display: flex;
118140
align-items: center;
@@ -133,4 +155,7 @@
133155
margin-bottom: 15px;
134156
}
135157
}
158+
.show-spinner {
159+
width: 100%;
160+
}
136161
}

src/card/examples/card-trend.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
*
66
* @param {string} headTitle Title for the card
77
* @param {string=} subTitle Sub-Title for the card
8+
* @param {string=} spinnerText Text for the card spinner
9+
* @param {string=} spinnerCardHeight Height to set for the card when data is loading and spinner is shown
810
* @param {boolean=} showTopBorder Show/Hide the blue top border. True shows top border, false (default) hides top border
11+
* @param {boolean=} showSpinner Show/Hide the spinner for loading state. True shows the spinner, false (default) hides the spinner
912
* @param {boolean=} showTitlesSeparator Show/Hide the grey line between the title and sub-title.
1013
* True (default) shows the line, false hides the line
1114
* @param {object=} footer footer configuration properties:<br/>
@@ -38,21 +41,26 @@
3841
<pf-card head-title="Cluster Utilization" show-top-border="true" footer="footerConfig" filter="filterConfig" style="width: 50%">
3942
<pf-trends-chart config="configSingle" chart-data="dataSingle"></pf-trends-chart>
4043
</pf-card>
41-
<pf-card head-title="Cluster Utilization" show-top-border="true" footer="footerConfig" filter="filterConfig" style="width: 50%">
42-
<pf-trends-chart config="configRightLabel" chart-data="dataSingle"></pf-trends-chart>
43-
</pf-card>
44+
<pf-card head-title="Cluster Utilization" show-top-border="true" show-spinner="dataLoading" spinner-text="Loading" footer="footerConfig" filter="filterConfig" style="width: 50%">
45+
<pf-trends-chart config="configRightLabel" chart-data="dataSingle"></pf-trends-chart>
46+
</pf-card>
4447
<label class="label-title">Card with Multiple Trends</label>
45-
<pf-card head-title="Performance" sub-title="Last 30 Days" show-top-border="false"
46-
show-titles-separator="false" style="width: 65%" footer="actionBarConfig">
48+
<pf-card head-title="Performance" sub-title="Last 30 Days" show-top-border="false" show-titles-separator="false" style="width: 65%" footer="actionBarConfig">
4749
<pf-trends-chart config="configVirtual" chart-data="dataVirtual"></pf-trends-chart>
4850
<pf-trends-chart config="configPhysical" chart-data="dataPhysical"></pf-trends-chart>
4951
<pf-trends-chart config="configMemory" chart-data="dataMemory"></pf-trends-chart>
5052
</pf-card>
51-
</div>
5253
</div>
54+
</div>
5355
</file>
5456
<file name="script.js">
55-
angular.module( 'demo', ['patternfly.charts', 'patternfly.card'] ).controller( 'ChartCtrl', function( $scope ) {
57+
angular.module( 'demo', ['patternfly.charts', 'patternfly.card'] ).controller( 'ChartCtrl', function( $scope, $timeout ) {
58+
59+
$scope.dataLoading = true;
60+
61+
$timeout(function () {
62+
$scope.dataLoading = false;
63+
}, 3000 );
5664
5765
$scope.footerConfig = {
5866
'iconClass' : 'fa fa-flag',

0 commit comments

Comments
 (0)