diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2017-05-10 15:52:09 +0000 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2017-05-10 15:52:09 +0000 |
commit | d1da5624d74b6ae6ea779df1485c661fa3014fd8 (patch) | |
tree | 36d60d37889a826bbdd020608c1bf10af09f6fe7 | |
parent | a8fb310cec6224b175d3b6152ad0943f06b29185 (diff) | |
download | gitlab-ce-d1da5624d74b6ae6ea779df1485c661fa3014fd8.tar.gz |
Tech debt: Creates vue component for loading icon
20 files changed, 187 insertions, 105 deletions
diff --git a/app/assets/javascripts/boards/components/board_list.js b/app/assets/javascripts/boards/components/board_list.js index 49a775002c3..7ee2696e720 100644 --- a/app/assets/javascripts/boards/components/board_list.js +++ b/app/assets/javascripts/boards/components/board_list.js @@ -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> diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js index a61cc7954a1..507f16f3f06 100644 --- a/app/assets/javascripts/boards/components/modal/index.js +++ b/app/assets/javascripts/boards/components/modal/index.js @@ -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> diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.js b/app/assets/javascripts/commit/pipelines/pipelines_table.js index ad9c600b499..b8be0d8a301 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_table.js +++ b/app/assets/javascripts/commit/pipelines/pipelines_table.js @@ -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" diff --git a/app/assets/javascripts/deploy_keys/components/action_btn.vue b/app/assets/javascripts/deploy_keys/components/action_btn.vue index 3ff3a9d977e..3f993213dd0 100644 --- a/app/assets/javascripts/deploy_keys/components/action_btn.vue +++ b/app/assets/javascripts/deploy_keys/components/action_btn.vue @@ -1,5 +1,6 @@ <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> diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue index 7315a9e11cb..5f6eed0c67c 100644 --- a/app/assets/javascripts/deploy_keys/components/app.vue +++ b/app/assets/javascripts/deploy_keys/components/app.vue @@ -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" diff --git a/app/assets/javascripts/environments/components/environment.vue b/app/assets/javascripts/environments/components/environment.vue index ed8df0f3a54..d4e13f3c84a 100644 --- a/app/assets/javascripts/environments/components/environment.vue +++ b/app/assets/javascripts/environments/components/environment.vue @@ -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" diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue index 63bffe8a998..a2448520a5f 100644 --- a/app/assets/javascripts/environments/components/environment_actions.vue +++ b/app/assets/javascripts/environments/components/environment_actions.vue @@ -1,6 +1,7 @@ <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> diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue index 44b8730fd09..2ba985bfe3e 100644 --- a/app/assets/javascripts/environments/components/environment_rollback.vue +++ b/app/assets/javascripts/environments/components/environment_rollback.vue @@ -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> diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue index f483ea7e937..a904453ffa9 100644 --- a/app/assets/javascripts/environments/components/environment_stop.vue +++ b/app/assets/javascripts/environments/components/environment_stop.vue @@ -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> diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue index 15eedaf76e1..5148a2ae79b 100644 --- a/app/assets/javascripts/environments/components/environments_table.vue +++ b/app/assets/javascripts/environments/components/environments_table.vue @@ -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> diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue index 1fc0ce818e9..bd161c8a379 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_view.vue +++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue @@ -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" diff --git a/app/assets/javascripts/pipelines/components/async_button.vue b/app/assets/javascripts/pipelines/components/async_button.vue index d1c60b570de..37a6f02d8fd 100644 --- a/app/assets/javascripts/pipelines/components/async_button.vue +++ b/app/assets/javascripts/pipelines/components/async_button.vue @@ -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> diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index 1f1b99ff401..14c98847d93 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -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 diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.js b/app/assets/javascripts/pipelines/components/pipelines_actions.js index ffda18d2e0f..b9e066c5db1 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_actions.js +++ b/app/assets/javascripts/pipelines/components/pipelines_actions.js @@ -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"> diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue index 310f44b06df..7fc19fce1ff 100644 --- a/app/assets/javascripts/pipelines/components/stage.vue +++ b/app/assets/javascripts/pipelines/components/stage.vue @@ -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 diff --git a/app/assets/javascripts/pipelines/pipelines.js b/app/assets/javascripts/pipelines/pipelines.js index 511f10b66f1..050551e5075 100644 --- a/app/assets/javascripts/pipelines/pipelines.js +++ b/app/assets/javascripts/pipelines/pipelines.js @@ -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" diff --git a/app/assets/javascripts/vue_shared/components/loading_icon.vue b/app/assets/javascripts/vue_shared/components/loading_icon.vue new file mode 100644 index 00000000000..41b1d0165b0 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/loading_icon.vue @@ -0,0 +1,33 @@ +<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> diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 026d35295d7..af991a128f3 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -5,11 +5,6 @@ } } -.environments-list-loading { - width: 100%; - font-size: 34px; -} - .environments-folder-name { font-weight: normal; padding-top: 20px; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 71fc6fad9b4..e7553c7a4bf 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -1,10 +1,4 @@ .pipelines { - .realtime-loading { - font-size: 40px; - text-align: center; - margin: 0 auto; - } - .stage { max-width: 90px; width: 90px; diff --git a/spec/javascripts/vue_shared/components/loading_icon_spec.js b/spec/javascripts/vue_shared/components/loading_icon_spec.js new file mode 100644 index 00000000000..1baf3537741 --- /dev/null +++ b/spec/javascripts/vue_shared/components/loading_icon_spec.js @@ -0,0 +1,53 @@ +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); + }); +}); |