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