Commit 1daa133c authored by Phil Hughes's avatar Phil Hughes

Merge branch '30286-vue-loadin-icon' into 'master'

Tech debt: Creates vue component for loading icon

Closes #31328

See merge request !11167
parents a8fb310c d1da5624
......@@ -2,6 +2,7 @@
import boardNewIssue from './board_new_issue';
import boardCard from './board_card';
import eventHub from '../eventhub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
const Store = gl.issueBoards.BoardsStore;
......@@ -44,6 +45,7 @@ export default {
components: {
boardCard,
boardNewIssue,
loadingIcon,
},
methods: {
listHeight() {
......@@ -156,10 +158,7 @@ export default {
class="board-list-loading text-center"
aria-label="Loading issues"
v-if="loading">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true">
</i>
<loading-icon />
</div>
<board-new-issue
:list="list"
......@@ -184,12 +183,12 @@ export default {
class="board-list-count text-center"
v-if="showCount"
data-id="-1">
<i
class="fa fa-spinner fa-spin"
aria-label="Loading more issues"
aria-hidden="true"
v-show="list.loadingMore">
</i>
<loading-icon
v-show="list.loadingMore"
label="Loading more issues"
/>
<span v-if="list.issues.length === list.issuesSize">
Showing all issues
</span>
......
......@@ -2,6 +2,7 @@
import Vue from 'vue';
import queryData from '../../utils/query_data';
import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
require('./header');
require('./list');
......@@ -137,6 +138,7 @@ gl.issueBoards.IssuesModal = Vue.extend({
'modal-list': gl.issueBoards.ModalList,
'modal-footer': gl.issueBoards.ModalFooter,
'empty-state': gl.issueBoards.ModalEmptyState,
loadingIcon,
},
template: `
<div
......@@ -161,7 +163,7 @@ gl.issueBoards.IssuesModal = Vue.extend({
class="add-issues-list text-center"
v-if="loading || filterLoading">
<div class="add-issues-list-loading">
<i class="fa fa-spinner fa-spin"></i>
<loading-icon />
</div>
</section>
<modal-footer></modal-footer>
......
......@@ -6,6 +6,7 @@ import PipelineStore from '../../pipelines/stores/pipelines_store';
import eventHub from '../../pipelines/event_hub';
import EmptyState from '../../pipelines/components/empty_state.vue';
import ErrorState from '../../pipelines/components/error_state.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import '../../lib/utils/common_utils';
import '../../vue_shared/vue_resource_interceptor';
import Poll from '../../lib/utils/poll';
......@@ -17,8 +18,6 @@ import Poll from '../../lib/utils/poll';
* We need a store to store the received environemnts.
* We need a service to communicate with the server.
*
* Necessary SVG in the table are provided as props. This should be refactored
* as soon as we have Webpack and can load them directly into JS files.
*/
export default Vue.component('pipelines-table', {
......@@ -27,6 +26,7 @@ export default Vue.component('pipelines-table', {
'pipelines-table-component': PipelinesTableComponent,
'error-state': ErrorState,
'empty-state': EmptyState,
loadingIcon,
},
/**
......@@ -151,13 +151,12 @@ export default Vue.component('pipelines-table', {
template: `
<div class="content-list pipelines">
<div
class="realtime-loading"
v-if="isLoading">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true" />
</div>
<loading-icon
label="Loading pipelines"
size="3"
v-if="isLoading"
/>
<empty-state
v-if="shouldRenderEmptyState"
......
<script>
import eventHub from '../eventhub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
data() {
......@@ -22,6 +23,11 @@
default: 'btn-default',
},
},
components: {
loadingIcon,
},
methods: {
doAction() {
this.isLoading = true;
......@@ -44,11 +50,6 @@
:disabled="isLoading"
@click="doAction">
{{ text }}
<i
v-if="isLoading"
class="fa fa-spinner fa-spin"
aria-hidden="true"
aria-label="Loading">
</i>
<loading-icon v-if="isLoading" />
</button>
</template>
......@@ -4,6 +4,7 @@
import DeployKeysService from '../service';
import DeployKeysStore from '../store';
import keysPanel from './keys_panel.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
data() {
......@@ -28,6 +29,7 @@
},
components: {
keysPanel,
loadingIcon,
},
methods: {
fetchKeys() {
......@@ -74,15 +76,11 @@
<template>
<div class="col-lg-9 col-lg-offset-3 append-bottom-default deploy-keys">
<div
class="text-center"
v-if="isLoading && !hasKeys">
<i
class="fa fa-spinner fa-spin fa-2x"
aria-hidden="true"
aria-label="Loading deploy keys">
</i>
</div>
<loading-icon
v-if="isLoading && !hasKeys"
size="2"
label="Loading deploy keys"
/>
<div v-else-if="hasKeys">
<keys-panel
title="Enabled deploy keys for this project"
......
......@@ -3,6 +3,7 @@
import EnvironmentsService from '../services/environments_service';
import environmentTable from './environments_table.vue';
import EnvironmentsStore from '../stores/environments_store';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import '../../lib/utils/common_utils';
import eventHub from '../event_hub';
......@@ -12,6 +13,7 @@ export default {
components: {
environmentTable,
tablePagination,
loadingIcon,
},
data() {
......@@ -186,14 +188,11 @@ export default {
</div>
<div class="content-list environments-container">
<div
class="environments-list-loading text-center"
v-if="isLoading">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true" />
</div>
<loading-icon
label="Loading environments"
size="3"
v-if="isLoading"
/>
<div
class="blank-state blank-state-no-icon"
......
<script>
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
......@@ -11,6 +12,10 @@ export default {
},
},
components: {
loadingIcon,
},
data() {
return {
playIconSvg,
......@@ -61,10 +66,7 @@ export default {
<i
class="fa fa-caret-down"
aria-hidden="true"/>
<i
v-if="isLoading"
class="fa fa-spinner fa-spin"
aria-hidden="true"/>
<loading-icon v-if="isLoading" />
</span>
</button>
......
......@@ -6,6 +6,7 @@
* Makes a post request when the button is clicked.
*/
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
......@@ -20,6 +21,10 @@ export default {
},
},
components: {
loadingIcon,
},
data() {
return {
isLoading: false,
......@@ -49,9 +54,6 @@ export default {
Rollback
</span>
<i
v-if="isLoading"
class="fa fa-spinner fa-spin"
aria-hidden="true" />
<loading-icon v-if="isLoading" />
</button>
</template>
......@@ -4,6 +4,7 @@
* Used in environments table.
*/
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
......@@ -19,6 +20,10 @@ export default {
};
},
components: {
loadingIcon,
},
computed: {
title() {
return 'Stop';
......@@ -51,9 +56,6 @@ export default {
<i
class="fa fa-stop stop-env-icon"
aria-hidden="true" />
<i
v-if="isLoading"
class="fa fa-spinner fa-spin"
aria-hidden="true" />
<loading-icon v-if="isLoading" />
</button>
</template>
......@@ -3,10 +3,12 @@
* Render environments table.
*/
import EnvironmentTableRowComponent from './environment_item.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
components: {
'environment-item': EnvironmentTableRowComponent,
loadingIcon,
},
props: {
......@@ -77,10 +79,8 @@ export default {
<template v-if="model.isFolder && model.isOpen && model.children && model.children.length > 0">
<tr v-if="isLoadingFolderContent">
<td colspan="6" class="text-center">
<i
class="fa fa-spin fa-spinner fa-2x"
aria-hidden="true" />
<td colspan="6">
<loading-icon size="2" />
</td>
</tr>
......
......@@ -3,6 +3,7 @@
import EnvironmentsService from '../services/environments_service';
import environmentTable from '../components/environments_table.vue';
import EnvironmentsStore from '../stores/environments_store';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import '../../lib/utils/common_utils';
import '../../vue_shared/vue_resource_interceptor';
......@@ -11,6 +12,7 @@ export default {
components: {
environmentTable,
tablePagination,
loadingIcon,
},
data() {
......@@ -153,13 +155,12 @@ export default {
</div>
<div class="environments-container">
<div
class="environments-list-loading text-center"
v-if="isLoading">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true"/>
</div>
<loading-icon
label="Loading environments"
v-if="isLoading"
size="3"
/>
<div
class="table-holder"
......
......@@ -3,6 +3,7 @@
/* global Flash */
import '~/flash';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
......@@ -37,6 +38,10 @@ export default {
},
},
components: {
loadingIcon,
},
data() {
return {
isLoading: false,
......@@ -94,9 +99,6 @@ export default {
<i
:class="iconClass"
aria-hidden="true" />
<i
class="fa fa-spinner fa-spin"
aria-hidden="true"
v-if="isLoading" />
<loading-icon v-if="isLoading" />
</button>
</template>
......@@ -5,11 +5,13 @@
import PipelineService from '../../services/pipeline_service';
import PipelineStore from '../../stores/pipeline_store';
import stageColumnComponent from './stage_column_component.vue';
import loadingIcon from '../../../vue_shared/components/loading_icon.vue';
import '../../../flash';
export default {
components: {
stageColumnComponent,
loadingIcon,
},
data() {
......@@ -89,11 +91,10 @@
<div class="build-content middle-block js-pipeline-graph">
<div class="pipeline-visualization pipeline-graph">
<div class="text-center">
<i
<loading-icon
v-if="isLoading"
class="loading-icon fa fa-spin fa-spinner fa-3x"
aria-label="Loading"
aria-hidden="true" />
size="3"
/>
</div>
<ul
......
......@@ -3,6 +3,7 @@
import '~/flash';
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIconComponent from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
......@@ -17,6 +18,10 @@ export default {
},
},
components: {
loadingIconComponent,
},
data() {
return {
playIconSvg,
......@@ -65,10 +70,7 @@ export default {
<i
class="fa fa-caret-down"
aria-hidden="true" />
<i
v-if="isLoading"
class="fa fa-spinner fa-spin"
aria-hidden="true" />
<loading-icon v-if="isLoading" />
</button>
<ul class="dropdown-menu dropdown-menu-align-right">
......
......@@ -15,6 +15,7 @@
/* global Flash */
import { borderlessStatusIconEntityMap } from '../../vue_shared/ci_status_icons';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
export default {
props: {
......@@ -38,6 +39,10 @@ export default {
};
},
components: {
loadingIcon,
},
updated() {
if (this.dropdownContent.length > 0) {
this.stopDropdownClickPropagation();
......@@ -153,15 +158,7 @@ export default {
:class="dropdownClass"
class="js-builds-dropdown-list scrollable-menu">
<div
class="text-center"
v-if="isLoading">
<i
class="fa fa-spin fa-spinner"
aria-hidden="true"
aria-label="Loading">
</i>
</div>
<loading-icon v-if="isLoading"/>
<ul
v-else
......
......@@ -7,6 +7,7 @@ import EmptyState from './components/empty_state.vue';
import ErrorState from './components/error_state.vue';
import NavigationTabs from './components/navigation_tabs';
import NavigationControls from './components/nav_controls';
import loadingIcon from '../vue_shared/components/loading_icon.vue';
import Poll from '../lib/utils/poll';
export default {
......@@ -24,6 +25,7 @@ export default {
'error-state': ErrorState,
'navigation-tabs': NavigationTabs,
'navigation-controls': NavigationControls,
loadingIcon,
},
data() {
......@@ -244,13 +246,11 @@ export default {
<div class="content-list pipelines">
<div
class="realtime-loading"
v-if="isLoading">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true" />
</div>
<loading-icon
label="Loading Pipelines"
size="3"
v-if="isLoading"
/>
<empty-state
v-if="shouldRenderEmptyState"
......
<script>
export default {
props: {
label: {
type: String,
required: false,
default: 'Loading',
},
size: {
type: String,
required: false,
default: '1',
},
},
computed: {
cssClass() {
return `fa-${this.size}x`;
},
},
};
</script>
<template>
<div class="text-center">
<i
class="fa fa-spin fa-spinner"
:class="cssClass"
aria-hidden="true"
:aria-label="label">
</i>
</div>
</template>
......@@ -5,11 +5,6 @@
}
}
.environments-list-loading {
width: 100%;
font-size: 34px;
}
.environments-folder-name {
font-weight: normal;
padding-top: 20px;
......
.pipelines {
.realtime-loading {
font-size: 40px;
text-align: center;
margin: 0 auto;
}
.stage {
max-width: 90px;
width: 90px;
......
import Vue from 'vue';
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
describe('Loading Icon Component', () => {
let LoadingIconComponent;
beforeEach(() => {
LoadingIconComponent = Vue.extend(loadingIcon);
});
it('should render a spinner font awesome icon', () => {
const component = new LoadingIconComponent().$mount();
expect(
component.$el.querySelector('i').getAttribute('class'),
).toEqual('fa fa-spin fa-spinner fa-1x');
expect(component.$el.tagName).toEqual('DIV');
expect(component.$el.classList.contains('text-center')).toEqual(true);
});
it('should render accessibility attributes', () => {
const component = new LoadingIconComponent().$mount();
const icon = component.$el.querySelector('i');
expect(icon.getAttribute('aria-hidden')).toEqual('true');
expect(icon.getAttribute('aria-label')).toEqual('Loading');
});
it('should render the provided label', () => {
const component = new LoadingIconComponent({
propsData: {
label: 'This is a loading icon',
},
}).$mount();
expect(
component.$el.querySelector('i').getAttribute('aria-label'),
).toEqual('This is a loading icon');
});
it('should render the provided size', () => {
const component = new LoadingIconComponent({
propsData: {
size: '2',
},
}).$mount();
expect(
component.$el.querySelector('i').classList.contains('fa-2x'),
).toEqual(true);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment