diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-20 10:00:54 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-20 10:00:54 +0000 |
commit | 3cccd102ba543e02725d247893729e5c73b38295 (patch) | |
tree | f36a04ec38517f5deaaacb5acc7d949688d1e187 /app/assets/javascripts/jobs/components/table/jobs_table_app.vue | |
parent | 205943281328046ef7b4528031b90fbda70c75ac (diff) | |
download | gitlab-ce-3cccd102ba543e02725d247893729e5c73b38295.tar.gz |
Add latest changes from gitlab-org/gitlab@14-10-stable-eev14.10.0-rc42
Diffstat (limited to 'app/assets/javascripts/jobs/components/table/jobs_table_app.vue')
-rw-r--r-- | app/assets/javascripts/jobs/components/table/jobs_table_app.vue | 92 |
1 files changed, 83 insertions, 9 deletions
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue index 864e322eecd..3ea50dfb7a3 100644 --- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue +++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue @@ -1,26 +1,34 @@ <script> import { GlAlert, GlSkeletonLoader, GlIntersectionObserver, GlLoadingIcon } from '@gitlab/ui'; import { __ } from '~/locale'; +import createFlash from '~/flash'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import JobsFilteredSearch from '../filtered_search/jobs_filtered_search.vue'; import eventHub from './event_hub'; import GetJobs from './graphql/queries/get_jobs.query.graphql'; import JobsTable from './jobs_table.vue'; import JobsTableEmptyState from './jobs_table_empty_state.vue'; import JobsTableTabs from './jobs_table_tabs.vue'; +import { RAW_TEXT_WARNING } from './constants'; export default { i18n: { errorMsg: __('There was an error fetching the jobs for your project.'), loadingAriaLabel: __('Loading'), }, + filterSearchBoxStyles: + 'gl-my-0 gl-p-5 gl-bg-gray-10 gl-text-gray-900 gl-border-gray-100 gl-border-b', components: { GlAlert, GlSkeletonLoader, + JobsFilteredSearch, JobsTable, JobsTableEmptyState, JobsTableTabs, GlIntersectionObserver, GlLoadingIcon, }, + mixins: [glFeatureFlagMixin()], inject: { fullPath: { default: '', @@ -35,10 +43,11 @@ export default { }; }, update(data) { - const { jobs: { nodes: list = [], pageInfo = {} } = {} } = data.project || {}; + const { jobs: { nodes: list = [], pageInfo = {}, count } = {} } = data.project || {}; return { list, pageInfo, + count, }; }, error() { @@ -54,19 +63,52 @@ export default { hasError: false, isAlertDismissed: false, scope: null, - firstLoad: true, + infiniteScrollingTriggered: false, + filterSearchTriggered: false, + count: 0, }; }, computed: { + loading() { + return this.$apollo.queries.jobs.loading; + }, shouldShowAlert() { return this.hasError && !this.isAlertDismissed; }, + // Show when on All tab with no jobs + // Show only when not loading and filtered search has not been triggered + // So we don't show empty state when results are empty on a filtered search showEmptyState() { - return this.jobs.list.length === 0 && !this.scope; + return ( + this.jobs.list.length === 0 && !this.scope && !this.loading && !this.filterSearchTriggered + ); }, hasNextPage() { return this.jobs?.pageInfo?.hasNextPage; }, + showLoadingSpinner() { + return this.loading && this.infiniteScrollingTriggered; + }, + showSkeletonLoader() { + return this.loading && !this.showLoadingSpinner; + }, + showFilteredSearch() { + return this.glFeatures?.jobsTableVueSearch && !this.scope; + }, + jobsCount() { + return this.jobs.count; + }, + }, + watch: { + // this watcher ensures that the count on the all tab + // is not updated when switching to the finished tab + jobsCount(newCount, oldCount) { + if (this.scope) { + this.count = oldCount; + } else { + this.count = newCount; + } + }, }, mounted() { eventHub.$on('jobActionPerformed', this.handleJobAction); @@ -79,16 +121,38 @@ export default { this.$apollo.queries.jobs.refetch({ statuses: this.scope }); }, fetchJobsByStatus(scope) { - this.firstLoad = true; + this.infiniteScrollingTriggered = false; this.scope = scope; this.$apollo.queries.jobs.refetch({ statuses: scope }); }, + filterJobsBySearch(filters) { + this.infiniteScrollingTriggered = false; + this.filterSearchTriggered = true; + + // Eventually there will be more tokens available + // this code is written to scale for those tokens + filters.forEach((filter) => { + // Raw text input in filtered search does not have a type + // when a user enters raw text we alert them that it is + // not supported and we do not make an additional API call + if (!filter.type) { + createFlash({ + message: RAW_TEXT_WARNING, + type: 'warning', + }); + } + + if (filter.type === 'status') { + this.$apollo.queries.jobs.refetch({ statuses: filter.value.data }); + } + }); + }, fetchMoreJobs() { - this.firstLoad = false; + if (!this.loading) { + this.infiniteScrollingTriggered = true; - if (!this.$apollo.queries.jobs.loading) { this.$apollo.queries.jobs.fetchMore({ variables: { fullPath: this.fullPath, @@ -113,9 +177,19 @@ export default { {{ $options.i18n.errorMsg }} </gl-alert> - <jobs-table-tabs @fetchJobsByStatus="fetchJobsByStatus" /> + <jobs-table-tabs + :all-jobs-count="count" + :loading="loading" + @fetchJobsByStatus="fetchJobsByStatus" + /> + + <jobs-filtered-search + v-if="showFilteredSearch" + :class="$options.filterSearchBoxStyles" + @filterJobsBySearch="filterJobsBySearch" + /> - <div v-if="$apollo.loading && firstLoad" class="gl-mt-5"> + <div v-if="showSkeletonLoader" class="gl-mt-5"> <gl-skeleton-loader :width="1248" :height="73"> <circle cx="748.031" cy="37.7193" r="15.0307" /> <circle cx="787.241" cy="37.7193" r="15.0307" /> @@ -138,7 +212,7 @@ export default { <gl-intersection-observer v-if="hasNextPage" @appear="fetchMoreJobs"> <gl-loading-icon - v-if="$apollo.loading" + v-if="showLoadingSpinner" size="md" :aria-label="$options.i18n.loadingAriaLabel" /> |