diff options
Diffstat (limited to 'app/assets/javascripts')
27 files changed, 187 insertions, 109 deletions
diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js index c7a917457f3..dffabbfe1b8 100644 --- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js +++ b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js @@ -84,7 +84,7 @@ export default class AjaxVariableList { .catch(() => { loadingIcon.classList.toggle('hide', true); this.variableList.toggleEnableRow(true); - Flash(s__('CiVariable|Error occured while saving variables')); + Flash(s__('CiVariable|Error occurred while saving variables')); }); } diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js index 71fc2ac7d80..aff32d95db1 100644 --- a/app/assets/javascripts/clusters/clusters_bundle.js +++ b/app/assets/javascripts/clusters/clusters_bundle.js @@ -1,6 +1,6 @@ import Visibility from 'visibilityjs'; import Vue from 'vue'; -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '../persistent_user_callout'; import { s__, sprintf } from '../locale'; import Flash from '../flash'; import Poll from '../lib/utils/poll'; @@ -26,6 +26,7 @@ export default class Clusters { statusPath, installHelmPath, installIngressPath, + installCertManagerPath, installRunnerPath, installJupyterPath, installKnativePath, @@ -48,6 +49,7 @@ export default class Clusters { endpoint: statusPath, installHelmEndpoint: installHelmPath, installIngressEndpoint: installIngressPath, + installCertManagerEndpoint: installCertManagerPath, installRunnerEndpoint: installRunnerPath, installPrometheusEndpoint: installPrometheusPath, installJupyterEndpoint: installJupyterPath, @@ -65,7 +67,7 @@ export default class Clusters { this.showTokenButton = document.querySelector('.js-show-cluster-token'); this.tokenField = document.querySelector('.js-cluster-token'); - initDismissableCallout('.js-cluster-security-warning'); + Clusters.initDismissableCallout(); initSettingsPanels(); setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area')); this.initApplications(clusterType); @@ -106,6 +108,12 @@ export default class Clusters { }); } + static initDismissableCallout() { + const callout = document.querySelector('.js-cluster-security-warning'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new + } + addListeners() { if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken); eventHub.$on('installApplication', this.installApplication); diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 0d2e7c3e356..fcdbffbc8b8 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -7,6 +7,7 @@ import helmLogo from 'images/cluster_app_logos/helm.png'; import jeagerLogo from 'images/cluster_app_logos/jeager.png'; import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png'; import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png'; +import certManagerLogo from 'images/cluster_app_logos/cert_manager.png'; import knativeLogo from 'images/cluster_app_logos/knative.png'; import meltanoLogo from 'images/cluster_app_logos/meltano.png'; import prometheusLogo from 'images/cluster_app_logos/prometheus.png'; @@ -59,6 +60,7 @@ export default { jeagerLogo, jupyterhubLogo, kubernetesLogo, + certManagerLogo, knativeLogo, meltanoLogo, prometheusLogo, @@ -124,6 +126,23 @@ export default { </p> `; }, + certManagerDescription() { + return sprintf( + _.escape( + s__( + `ClusterIntegration|cert-manager is a native Kubernetes certificate management controller that helps with issuing certificates. + Installing cert-manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates + are valid and up to date.`, + ), + ), + { + letsEncrypt: `<a href="https://letsencrypt.org/" + target="_blank" rel="noopener noreferrer"> + ${_.escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`, + }, + false, + ); + }, prometheusDescription() { return sprintf( _.escape( @@ -266,6 +285,24 @@ export default { </div> </application-row> <application-row + id="cert_manager" + :logo-url="certManagerLogo" + :title="applications.cert_manager.title" + :status="applications.cert_manager.status" + :status-reason="applications.cert_manager.statusReason" + :request-status="applications.cert_manager.requestStatus" + :request-reason="applications.cert_manager.requestReason" + :disabled="!helmInstalled" + class="hide-bottom-border rounded-bottom" + title-link="https://cert-manager.readthedocs.io/en/latest/#" + > + <div + slot="description" + v-html="certManagerDescription" + > + </div> + </application-row> + <application-row v-if="isProjectCluster" id="prometheus" :logo-url="prometheusLogo" diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js index da562b09ee5..89dda4b7902 100644 --- a/app/assets/javascripts/clusters/services/clusters_service.js +++ b/app/assets/javascripts/clusters/services/clusters_service.js @@ -6,6 +6,7 @@ export default class ClusterService { this.appInstallEndpointMap = { helm: this.options.installHelmEndpoint, ingress: this.options.installIngressEndpoint, + cert_manager: this.options.installCertManagerEndpoint, runner: this.options.installRunnerEndpoint, prometheus: this.options.installPrometheusEndpoint, jupyter: this.options.installJupyterEndpoint, diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index e45da967392..3678be59d24 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -24,6 +24,13 @@ export default class ClusterStore { requestReason: null, externalIp: null, }, + cert_manager: { + title: s__('ClusterIntegration|Cert-Manager'), + status: null, + statusReason: null, + requestStatus: null, + requestReason: null, + }, runner: { title: s__('ClusterIntegration|GitLab Runner'), status: null, diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 0b7838292b2..22da38ce7a5 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -55,8 +55,6 @@ export default { diffViewType: state => state.diffs.diffViewType, mergeRequestDiffs: state => state.diffs.mergeRequestDiffs, mergeRequestDiff: state => state.diffs.mergeRequestDiff, - latestVersionPath: state => state.diffs.latestVersionPath, - startVersion: state => state.diffs.startVersion, commit: state => state.diffs.commit, targetBranchName: state => state.diffs.targetBranchName, renderOverflowWarning: state => state.diffs.renderOverflowWarning, @@ -75,24 +73,6 @@ export default { path: '', }; }, - notAllCommentsDisplayed() { - if (this.commit) { - return __('Only comments from the following commit are shown below'); - } else if (this.startVersion) { - return __( - "Not all comments are displayed because you're comparing two versions of the diff.", - ); - } - return __( - "Not all comments are displayed because you're viewing an old version of the diff.", - ); - }, - showLatestVersion() { - if (this.commit) { - return __('Show latest version of the diff'); - } - return __('Show latest version'); - }, canCurrentUserFork() { return this.currentUser.can_fork === true && this.currentUser.can_create_merge_request; }, @@ -184,10 +164,8 @@ export default { <div v-if="isLoading" class="loading"><gl-loading-icon /></div> <div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane"> <compare-versions - v-if="showCompareVersions" :merge-request-diffs="mergeRequestDiffs" :merge-request-diff="mergeRequestDiff" - :start-version="startVersion" :target-branch="targetBranch" /> @@ -200,33 +178,22 @@ export default { /> <div - v-if="commit || startVersion || (mergeRequestDiff && !mergeRequestDiff.latest)" - class="mr-version-controls" - > - <div class="content-block comments-disabled-notif clearfix"> - <i class="fa fa-info-circle"></i> {{ notAllCommentsDisplayed }} - <div class="pull-right"> - <a :href="latestVersionPath" class="btn btn-sm"> {{ showLatestVersion }} </a> - </div> - </div> - </div> - - <commit-widget v-if="commit" :commit="commit" /> - - <div :data-can-create-note="getNoteableData.current_user.can_create_note" class="files d-flex prepend-top-default" > <div v-show="showTreeList" class="diff-tree-list"><tree-list /></div> - <div v-if="diffFiles.length > 0" class="diff-files-holder"> - <diff-file - v-for="file in diffFiles" - :key="file.newPath" - :file="file" - :can-current-user-fork="canCurrentUserFork" - /> + <div class="diff-files-holder"> + <commit-widget v-if="commit" :commit="commit" /> + <template v-if="diffFiles.length > 0"> + <diff-file + v-for="file in diffFiles" + :key="file.newPath" + :file="file" + :can-current-user-fork="canCurrentUserFork" + /> + </template> + <no-changes v-else /> </div> - <no-changes v-else /> </div> </div> </div> diff --git a/app/assets/javascripts/diffs/components/commit_widget.vue b/app/assets/javascripts/diffs/components/commit_widget.vue index 3fb11813d68..d45f91c7023 100644 --- a/app/assets/javascripts/diffs/components/commit_widget.vue +++ b/app/assets/javascripts/diffs/components/commit_widget.vue @@ -28,7 +28,7 @@ export default { </script> <template> - <div class="info-well prepend-top-default"> + <div class="info-well w-100"> <div class="well-segment"> <ul class="blob-commit-info"> <commit-item :commit="commit" /> diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue index 3ccd111f1cb..f75345d31f8 100644 --- a/app/assets/javascripts/diffs/components/compare_versions.vue +++ b/app/assets/javascripts/diffs/components/compare_versions.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; -import { GlTooltipDirective } from '@gitlab/ui'; +import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui'; import { __ } from '~/locale'; import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility'; import Icon from '~/vue_shared/components/icon.vue'; @@ -10,6 +10,8 @@ export default { components: { CompareVersionsDropdown, Icon, + GlLink, + GlButton, }, directives: { GlTooltip: GlTooltipDirective, @@ -21,12 +23,8 @@ export default { }, mergeRequestDiff: { type: Object, - required: true, - }, - startVersion: { - type: Object, required: false, - default: null, + default: () => ({}), }, targetBranch: { type: Object, @@ -35,7 +33,7 @@ export default { }, }, computed: { - ...mapState('diffs', ['commit', 'showTreeList']), + ...mapState('diffs', ['commit', 'showTreeList', 'startVersion', 'latestVersionPath']), ...mapGetters('diffs', ['isInlineView', 'isParallelView', 'hasCollapsedFile']), comparableDiffs() { return this.mergeRequestDiffs.slice(1); @@ -102,7 +100,18 @@ export default { class="mr-version-compare-dropdown" /> </div> + <div v-else-if="commit"> + {{ __('Viewing commit') }} + <gl-link :href="commit.commit_url" class="monospace">{{ commit.short_id }}</gl-link> + </div> <div class="inline-parallel-buttons d-none d-md-flex ml-auto"> + <gl-button + v-if="commit || startVersion" + :href="latestVersionPath" + class="append-right-8 js-latest-version" + > + {{ __('Show latest version') }} + </gl-button> <a v-show="hasCollapsedFile" class="btn btn-default append-right-8" @click="expandAllFiles"> {{ __('Expand all') }} </a> diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue index 60b33e771b4..f75a01b023b 100644 --- a/app/assets/javascripts/diffs/components/diff_file_header.vue +++ b/app/assets/javascripts/diffs/components/diff_file_header.vue @@ -1,6 +1,7 @@ <script> import _ from 'underscore'; import { mapActions, mapGetters } from 'vuex'; +import { polyfillSticky } from '~/lib/utils/sticky'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import Icon from '~/vue_shared/components/icon.vue'; import FileIcon from '~/vue_shared/components/file_icon.vue'; @@ -116,6 +117,9 @@ export default { return `\`${this.diffFile.file_path}\``; }, }, + mounted() { + polyfillSticky(this.$refs.header); + }, methods: { ...mapActions('diffs', ['toggleFileDiscussions']), handleToggleFile(e, checkTarget) { diff --git a/app/assets/javascripts/dismissable_callout.js b/app/assets/javascripts/dismissable_callout.js deleted file mode 100644 index 5185b019376..00000000000 --- a/app/assets/javascripts/dismissable_callout.js +++ /dev/null @@ -1,27 +0,0 @@ -import $ from 'jquery'; -import axios from '~/lib/utils/axios_utils'; -import { __ } from '~/locale'; -import Flash from '~/flash'; - -export default function initDismissableCallout(alertSelector) { - const alertEl = document.querySelector(alertSelector); - if (!alertEl) { - return; - } - - const closeButtonEl = alertEl.getElementsByClassName('close')[0]; - const { dismissEndpoint, featureId } = closeButtonEl.dataset; - - closeButtonEl.addEventListener('click', () => { - axios - .post(dismissEndpoint, { - feature_name: featureId, - }) - .then(() => { - $(alertEl).alert('close'); - }) - .catch(() => { - Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.')); - }); - }); -} diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index 6f8b73564d0..c14eb936930 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -62,9 +62,11 @@ class GfmAutoComplete { skipMarkdownCharacterTest: true, data: GfmAutoComplete.defaultLoadingData, displayTpl(value) { + const cssClasses = []; + if (GfmAutoComplete.isLoading(value)) return GfmAutoComplete.Loading.template; // eslint-disable-next-line no-template-curly-in-string - let tpl = '<li><span class="name">/${name}</span>'; + let tpl = '<li class="<%- className %>"><span class="name">/${name}</span>'; if (value.aliases.length > 0) { tpl += ' <small class="aliases">(or /<%- aliases.join(", /") %>)</small>'; } @@ -72,10 +74,19 @@ class GfmAutoComplete { tpl += ' <small class="params"><%- params.join(" ") %></small>'; } if (value.description !== '') { - tpl += '<small class="description"><i><%- description %></i></small>'; + tpl += '<small class="description"><i><%- description %> <%- warningText %></i></small>'; } tpl += '</li>'; - return _.template(tpl)(value); + + if (value.warning) { + cssClasses.push('has-warning'); + } + + return _.template(tpl)({ + ...value, + className: cssClasses.join(' '), + warningText: value.warning ? `(${value.warning})` : '', + }); }, insertTpl(value) { // eslint-disable-next-line no-template-curly-in-string @@ -104,6 +115,7 @@ class GfmAutoComplete { aliases: c.aliases, params: c.params, description: c.description, + warning: c.warning, search, }; }); diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js index a297740bd5f..e74b880e02c 100644 --- a/app/assets/javascripts/ide/stores/actions/file.js +++ b/app/assets/javascripts/ide/stores/actions/file.js @@ -82,7 +82,7 @@ export const getFileData = ( .catch(() => { commit(types.TOGGLE_LOADING, { entry: file }); dispatch('setErrorMessage', { - text: __('An error occured whilst loading the file.'), + text: __('An error occurred whilst loading the file.'), action: payload => dispatch('getFileData', payload).then(() => dispatch('setErrorMessage', null)), actionText: __('Please try again'), @@ -124,7 +124,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) = }) .catch(() => { dispatch('setErrorMessage', { - text: __('An error occured whilst loading the file content.'), + text: __('An error occurred whilst loading the file content.'), action: payload => dispatch('getRawFileData', payload).then(() => dispatch('setErrorMessage', null)), actionText: __('Please try again'), diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js index 8404c6d4f72..18c24369996 100644 --- a/app/assets/javascripts/ide/stores/actions/merge_request.js +++ b/app/assets/javascripts/ide/stores/actions/merge_request.js @@ -25,7 +25,7 @@ export const getMergeRequestData = ( }) .catch(() => { dispatch('setErrorMessage', { - text: __('An error occured whilst loading the merge request.'), + text: __('An error occurred whilst loading the merge request.'), action: payload => dispatch('getMergeRequestData', payload).then(() => dispatch('setErrorMessage', null), @@ -58,7 +58,7 @@ export const getMergeRequestChanges = ( }) .catch(() => { dispatch('setErrorMessage', { - text: __('An error occured whilst loading the merge request changes.'), + text: __('An error occurred whilst loading the merge request changes.'), action: payload => dispatch('getMergeRequestChanges', payload).then(() => dispatch('setErrorMessage', null), @@ -92,7 +92,7 @@ export const getMergeRequestVersions = ( }) .catch(() => { dispatch('setErrorMessage', { - text: __('An error occured whilst loading the merge request version data.'), + text: __('An error occurred whilst loading the merge request version data.'), action: payload => dispatch('getMergeRequestVersions', payload).then(() => dispatch('setErrorMessage', null), diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js index 2cb08ab2945..b65f631c99c 100644 --- a/app/assets/javascripts/ide/stores/actions/project.js +++ b/app/assets/javascripts/ide/stores/actions/project.js @@ -103,7 +103,7 @@ export const createNewBranchFromDefault = ({ state, dispatch, getters }, branch) }) .catch(() => { dispatch('setErrorMessage', { - text: __('An error occured creating the new branch.'), + text: __('An error occurred creating the new branch.'), action: payload => dispatch('createNewBranchFromDefault', payload), actionText: __('Please try again'), actionPayload: branch, diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js index 9288bbe32f5..de5f6050074 100644 --- a/app/assets/javascripts/ide/stores/actions/tree.js +++ b/app/assets/javascripts/ide/stores/actions/tree.js @@ -76,7 +76,7 @@ export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } = dispatch('showBranchNotFoundError', branchId); } else { dispatch('setErrorMessage', { - text: __('An error occured whilst loading all the files.'), + text: __('An error occurred whilst loading all the files.'), action: payload => dispatch('getFiles', payload).then(() => dispatch('setErrorMessage', null)), actionText: __('Please try again'), diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js index ea2525a2f0e..51cf4dede42 100644 --- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js +++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js @@ -28,7 +28,7 @@ export const receiveLatestPipelineError = ({ commit, dispatch }, err) => { dispatch( 'setErrorMessage', { - text: __('An error occured whilst fetching the latest pipeline.'), + text: __('An error occurred whilst fetching the latest pipeline.'), action: () => dispatch('forcePipelineRequest').then(() => dispatch('setErrorMessage', null, { root: true }), @@ -84,7 +84,7 @@ export const receiveJobsError = ({ commit, dispatch }, stage) => { dispatch( 'setErrorMessage', { - text: __('An error occured whilst loading the pipelines jobs.'), + text: __('An error occurred whilst loading the pipelines jobs.'), action: payload => dispatch('fetchJobs', payload).then(() => dispatch('setErrorMessage', null, { root: true }), @@ -123,7 +123,7 @@ export const receiveJobTraceError = ({ commit, dispatch }) => { dispatch( 'setErrorMessage', { - text: __('An error occured whilst fetching the job trace.'), + text: __('An error occurred whilst fetching the job trace.'), action: () => dispatch('fetchJobTrace').then(() => dispatch('setErrorMessage', null, { root: true })), actionText: __('Please try again'), diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue index 0f590e077bf..934ecd0e3ec 100644 --- a/app/assets/javascripts/jobs/components/sidebar.vue +++ b/app/assets/javascripts/jobs/components/sidebar.vue @@ -199,7 +199,7 @@ export default { /> <p v-if="job.tags.length" class="build-detail-row js-job-tags"> <span class="build-light-text"> {{ __('Tags:') }} </span> - <span v-for="(tag, i) in job.tags" :key="i" class="label label-primary"> + <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary"> {{ tag }} </span> </p> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index f6842fa240e..29740ddf6ae 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -68,7 +68,7 @@ export default { isReplying: false, isResolving: false, resolveAsThread: true, - isRepliesCollapsed: (!this.discussion.diff_discussion && this.discussion.resolved) || false, + isRepliesToggledByUser: false, }; }, computed: { @@ -189,6 +189,15 @@ export default { return isExpanded || this.alwaysExpanded || isResolvedNonDiffDiscussion; }, + isRepliesCollapsed() { + const { discussion, isRepliesToggledByUser } = this; + const { resolved, notes } = discussion; + const hasReplies = notes.length > 1; + + return ( + (!discussion.diff_discussion && resolved && hasReplies && !isRepliesToggledByUser) || false + ); + }, }, watch: { isReplying() { @@ -233,7 +242,7 @@ export default { this.toggleDiscussion({ discussionId: this.discussion.id }); }, toggleReplies() { - this.isRepliesCollapsed = !this.isRepliesCollapsed; + this.isRepliesToggledByUser = !this.isRepliesToggledByUser; }, showReplyForm() { this.isReplying = true; diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue index e9d05c5cdcd..72a8ff28466 100644 --- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue +++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue @@ -42,7 +42,7 @@ export default { </script> <template> - <li :class="className" class="replies-toggle"> + <li :class="className" class="replies-toggle js-toggle-replies"> <template v-if="collapsed"> <icon name="chevron-right" @click.native="toggle" /> <div> diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js index 845a5f7042c..21efc4f6d00 100644 --- a/app/assets/javascripts/pages/groups/clusters/index/index.js +++ b/app/assets/javascripts/pages/groups/clusters/index/index.js @@ -1,5 +1,7 @@ -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '~/persistent_user_callout'; document.addEventListener('DOMContentLoaded', () => { - initDismissableCallout('.gcp-signup-offer'); + const callout = document.querySelector('.gcp-signup-offer'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new }); diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/index.js index bf80d8b8193..00e2d7fc998 100644 --- a/app/assets/javascripts/pages/groups/index.js +++ b/app/assets/javascripts/pages/groups/index.js @@ -1,6 +1,12 @@ -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '~/persistent_user_callout'; import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +function initCallout() { + const callout = document.querySelector('.gcp-signup-offer'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new +} + document.addEventListener('DOMContentLoaded', () => { const { page } = document.body.dataset; const newClusterViews = [ @@ -10,7 +16,7 @@ document.addEventListener('DOMContentLoaded', () => { ]; if (newClusterViews.indexOf(page) > -1) { - initDismissableCallout('.gcp-signup-offer'); + initCallout(); initGkeDropdowns(); } }); diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js index 845a5f7042c..21efc4f6d00 100644 --- a/app/assets/javascripts/pages/projects/clusters/index/index.js +++ b/app/assets/javascripts/pages/projects/clusters/index/index.js @@ -1,5 +1,7 @@ -import initDismissableCallout from '~/dismissable_callout'; +import PersistentUserCallout from '~/persistent_user_callout'; document.addEventListener('DOMContentLoaded', () => { - initDismissableCallout('.gcp-signup-offer'); + const callout = document.querySelector('.gcp-signup-offer'); + + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new }); diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js index 5659e13981a..b0345b4e50d 100644 --- a/app/assets/javascripts/pages/projects/index.js +++ b/app/assets/javascripts/pages/projects/index.js @@ -1,5 +1,5 @@ -import initDismissableCallout from '~/dismissable_callout'; import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import PersistentUserCallout from '../../persistent_user_callout'; import Project from './project'; import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation'; @@ -12,7 +12,9 @@ document.addEventListener('DOMContentLoaded', () => { ]; if (newClusterViews.indexOf(page) > -1) { - initDismissableCallout('.gcp-signup-offer'); + const callout = document.querySelector('.gcp-signup-offer'); + if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new + initGkeDropdowns(); } diff --git a/app/assets/javascripts/pages/root/index.js b/app/assets/javascripts/pages/root/index.js new file mode 100644 index 00000000000..09f8185d3b5 --- /dev/null +++ b/app/assets/javascripts/pages/root/index.js @@ -0,0 +1,5 @@ +// if the "projects dashboard" is a user's default dashboard, when they visit the +// instance root index, the dashboard will be served by the root controller instead +// of a dashboard controller. The root index redirects for all other default dashboards. + +import '../dashboard/projects/index'; diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js new file mode 100644 index 00000000000..1e34e74a152 --- /dev/null +++ b/app/assets/javascripts/persistent_user_callout.js @@ -0,0 +1,34 @@ +import axios from './lib/utils/axios_utils'; +import { __ } from './locale'; +import Flash from './flash'; + +export default class PersistentUserCallout { + constructor(container) { + const { dismissEndpoint, featureId } = container.dataset; + this.container = container; + this.dismissEndpoint = dismissEndpoint; + this.featureId = featureId; + + this.init(); + } + + init() { + const closeButton = this.container.querySelector('.js-close'); + closeButton.addEventListener('click', event => this.dismiss(event)); + } + + dismiss(event) { + event.preventDefault(); + + axios + .post(this.dismissEndpoint, { + feature_name: this.featureId, + }) + .then(() => { + this.container.remove(); + }) + .catch(() => { + Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.')); + }); + } +} diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue index 78f085e5312..21095fcba16 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue +++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue @@ -47,7 +47,7 @@ export default { errorMessage() { return sprintf( s__( - 'ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}', + 'ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}', ), { error: this.gapiError }, ); diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue index 8e51dd352c7..056584c8865 100644 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue +++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue @@ -93,7 +93,7 @@ export default { } return sprintf( - s__('ClusterIntegration|An error occured while trying to fetch your projects: %{error}'), + s__('ClusterIntegration|An error occurred while trying to fetch your projects: %{error}'), { error: this.gapiError }, ); }, |