diff options
Diffstat (limited to 'app/assets/javascripts/pages')
43 files changed, 427 insertions, 190 deletions
diff --git a/app/assets/javascripts/pages/abuse_reports/index.js b/app/assets/javascripts/pages/abuse_reports/index.js index feceeb0b10a..ea7c9042e6d 100644 --- a/app/assets/javascripts/pages/abuse_reports/index.js +++ b/app/assets/javascripts/pages/abuse_reports/index.js @@ -1,3 +1,5 @@ import { initLinkToSpam } from '~/abuse_reports'; +import initFilePickers from '~/file_pickers'; initLinkToSpam(); +initFilePickers(); diff --git a/app/assets/javascripts/pages/admin/applications/index.js b/app/assets/javascripts/pages/admin/applications/index.js index 3397b02aeba..df9e38431b0 100644 --- a/app/assets/javascripts/pages/admin/applications/index.js +++ b/app/assets/javascripts/pages/admin/applications/index.js @@ -1,3 +1,5 @@ import initApplicationDeleteButtons from '~/admin/applications'; +import { initOAuthApplicationSecret } from '~/oauth_application'; initApplicationDeleteButtons(); +initOAuthApplicationSecret(); diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/cancel_jobs.vue b/app/assets/javascripts/pages/admin/jobs/components/cancel_jobs.vue index 72cfc005782..72cfc005782 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/components/cancel_jobs.vue +++ b/app/assets/javascripts/pages/admin/jobs/components/cancel_jobs.vue diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/cancel_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/components/cancel_jobs_modal.vue index 3bc785ee1b6..3bc785ee1b6 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/components/cancel_jobs_modal.vue +++ b/app/assets/javascripts/pages/admin/jobs/components/cancel_jobs_modal.vue diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/constants.js b/app/assets/javascripts/pages/admin/jobs/components/constants.js index cfde1fc0a2b..84be895e194 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/components/constants.js +++ b/app/assets/javascripts/pages/admin/jobs/components/constants.js @@ -1,4 +1,5 @@ import { s__, __ } from '~/locale'; +import { DEFAULT_FIELDS } from '~/jobs/components/table/constants'; export const CANCEL_JOBS_MODAL_ID = 'cancel-jobs-modal'; export const CANCEL_JOBS_MODAL_TITLE = s__('AdminArea|Are you sure?'); @@ -10,3 +11,11 @@ export const PRIMARY_ACTION_TEXT = s__('AdminArea|Yes, proceed'); export const CANCEL_JOBS_WARNING = s__( "AdminArea|You're about to cancel all running and pending jobs across this instance. Do you want to proceed?", ); + +/* Admin Table constants */ +export const DEFAULT_FIELDS_ADMIN = [ + ...DEFAULT_FIELDS.slice(0, 2), + { key: 'project', label: __('Project'), columnClass: 'gl-w-20p' }, + { key: 'runner', label: __('Runner'), columnClass: 'gl-w-15p' }, + ...DEFAULT_FIELDS.slice(2), +]; diff --git a/app/assets/javascripts/pages/admin/jobs/components/table/admin_jobs_table_app.vue b/app/assets/javascripts/pages/admin/jobs/components/table/admin_jobs_table_app.vue new file mode 100644 index 00000000000..b89e311ff1d --- /dev/null +++ b/app/assets/javascripts/pages/admin/jobs/components/table/admin_jobs_table_app.vue @@ -0,0 +1,118 @@ +<script> +import { GlAlert } from '@gitlab/ui'; +import { __ } from '~/locale'; +import { queryToObject } from '~/lib/utils/url_utility'; +import { validateQueryString } from '~/jobs/components/filtered_search/utils'; +import JobsTable from '~/jobs/components/table/jobs_table.vue'; +import JobsTableTabs from '~/jobs/components/table/jobs_table_tabs.vue'; +import JobsTableEmptyState from '~/jobs/components/table/jobs_table_empty_state.vue'; +import { DEFAULT_FIELDS_ADMIN } from '../constants'; +import GetAllJobs from './graphql/queries/get_all_jobs.query.graphql'; + +export default { + i18n: { + jobsFetchErrorMsg: __('There was an error fetching the jobs.'), + }, + components: { + JobsTableEmptyState, + GlAlert, + JobsTable, + JobsTableTabs, + }, + inject: { + jobStatuses: { + default: null, + }, + url: { + default: '', + }, + emptyStateSvgPath: { + default: '', + }, + }, + apollo: { + jobs: { + query: GetAllJobs, + variables() { + return this.variables; + }, + update(data) { + const { jobs: { nodes: list = [], pageInfo = {}, count } = {} } = data || {}; + return { + list, + pageInfo, + count, + }; + }, + error() { + this.error = this.$options.i18n.jobsFetchErrorMsg; + }, + }, + }, + data() { + return { + jobs: { + list: [], + }, + error: '', + count: 0, + scope: null, + infiniteScrollingTriggered: false, + filterSearchTriggered: false, + DEFAULT_FIELDS_ADMIN, + }; + }, + computed: { + loading() { + return this.$apollo.queries.jobs.loading; + }, + // 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 && !this.loading && !this.filterSearchTriggered + ); + }, + variables() { + return { ...this.validatedQueryString }; + }, + validatedQueryString() { + const queryStringObject = queryToObject(window.location.search); + + return validateQueryString(queryStringObject); + }, + 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) { + if (this.scope) return; + + this.count = newCount; + }, + }, +}; +</script> + +<template> + <div> + <gl-alert v-if="error" class="gl-mt-2" variant="danger" dismissible @dismiss="error = ''"> + {{ error }} + </gl-alert> + + <jobs-table-tabs :all-jobs-count="count" :loading="loading" /> + + <jobs-table-empty-state v-if="showEmptyState" /> + + <jobs-table + v-else + :jobs="jobs.list" + :table-fields="DEFAULT_FIELDS_ADMIN" + class="gl-table-no-top-border" + /> + </div> +</template> diff --git a/app/assets/javascripts/pages/admin/jobs/components/table/graphql/cache_config.js b/app/assets/javascripts/pages/admin/jobs/components/table/graphql/cache_config.js new file mode 100644 index 00000000000..fd7ee2a6f8c --- /dev/null +++ b/app/assets/javascripts/pages/admin/jobs/components/table/graphql/cache_config.js @@ -0,0 +1,62 @@ +import { isEqual } from 'lodash'; + +export default { + typePolicies: { + Query: { + fields: { + jobs: { + keyArgs: ['statuses'], + }, + }, + }, + CiJobConnection: { + merge(existing = {}, incoming, { args = {} }) { + if (incoming.nodes) { + let nodes; + + const areNodesEqual = isEqual(existing.nodes, incoming.nodes); + const statuses = Array.isArray(args.statuses) ? [...args.statuses] : args.statuses; + const { pageInfo } = incoming; + + if (Object.keys(existing).length !== 0 && isEqual(existing?.statuses, args?.statuses)) { + if (areNodesEqual) { + if (incoming.pageInfo.hasNextPage) { + nodes = [...existing.nodes, ...incoming.nodes]; + } else { + nodes = [...incoming.nodes]; + } + } else { + if (!existing.pageInfo?.hasNextPage) { + nodes = [...incoming.nodes]; + + return { + nodes, + statuses, + pageInfo, + count: incoming.count, + }; + } + + nodes = [...existing.nodes, ...incoming.nodes]; + } + } else { + nodes = [...incoming.nodes]; + } + + return { + nodes, + statuses, + pageInfo, + count: incoming.count, + }; + } + + return { + nodes: existing.nodes, + pageInfo: existing.pageInfo, + statuses: args.statuses, + }; + }, + }, + }, +}; diff --git a/app/assets/javascripts/pages/admin/jobs/components/table/graphql/queries/get_all_jobs.query.graphql b/app/assets/javascripts/pages/admin/jobs/components/table/graphql/queries/get_all_jobs.query.graphql new file mode 100644 index 00000000000..374009efa15 --- /dev/null +++ b/app/assets/javascripts/pages/admin/jobs/components/table/graphql/queries/get_all_jobs.query.graphql @@ -0,0 +1,81 @@ +query getAllJobs($after: String, $first: Int = 50, $statuses: [CiJobStatus!]) { + jobs(after: $after, first: $first, statuses: $statuses) { + count + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + nodes { + artifacts { + nodes { + id + downloadPath + fileType + } + } + allowFailure + status + scheduledAt + manualJob + triggered + createdByTag + detailedStatus { + id + detailsPath + group + icon + label + text + tooltip + action { + id + buttonTitle + icon + method + path + title + } + } + id + refName + refPath + tags + shortSha + commitPath + pipeline { + id + project { + id + fullPath + webUrl + } + path + user { + id + webPath + avatarUrl + } + } + stage { + id + name + } + name + duration + finishedAt + coverage + retryable + playable + cancelable + active + stuck + userPermissions { + readBuild + readJobArtifacts + updateBuild + } + } + } +} diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue b/app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue deleted file mode 100644 index c5a0509b625..00000000000 --- a/app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue +++ /dev/null @@ -1,19 +0,0 @@ -<script> -export default { - inject: { - jobStatuses: { - default: null, - }, - url: { - default: '', - }, - emptyStateSvgPath: { - default: '', - }, - }, -}; -</script> - -<template> - <div>{{ __('Jobs') }}</div> -</template> diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js index 9df52557212..9c2a255a1a3 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/index.js +++ b/app/assets/javascripts/pages/admin/jobs/index/index.js @@ -1,11 +1,21 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; import { BV_SHOW_MODAL } from '~/lib/utils/constants'; import Translate from '~/vue_shared/translate'; -import { CANCEL_JOBS_MODAL_ID } from './components/constants'; -import CancelJobsModal from './components/cancel_jobs_modal.vue'; -import AdminJobsTableApp from './components/table/admin_jobs_table_app.vue'; +import createDefaultClient from '~/lib/graphql'; +import { CANCEL_JOBS_MODAL_ID } from '../components/constants'; +import CancelJobsModal from '../components/cancel_jobs_modal.vue'; +import AdminJobsTableApp from '../components/table/admin_jobs_table_app.vue'; +import cacheConfig from '../components/table/graphql/cache_config'; Vue.use(Translate); +Vue.use(VueApollo); + +const client = createDefaultClient({}, { cacheConfig }); + +const apolloProvider = new VueApollo({ + defaultClient: client, +}); function initJobs() { const buttonId = 'js-stop-jobs-button'; @@ -44,6 +54,7 @@ export function initAdminJobsApp() { return new Vue({ el: containerEl, + apolloProvider, provide: { url, emptyStateSvgPath, diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js index dec06fe6f4d..721168f6140 100644 --- a/app/assets/javascripts/pages/groups/edit/index.js +++ b/app/assets/javascripts/pages/groups/edit/index.js @@ -9,6 +9,7 @@ import mountBadgeSettings from '~/pages/shared/mount_badge_settings'; import initSearchSettings from '~/search_settings'; import initSettingsPanels from '~/settings_panels'; import initConfirmDanger from '~/init_confirm_danger'; +import { initGroupSettingsReadme } from '~/groups/settings/init_group_settings_readme'; initFilePickers(); initConfirmDanger(); @@ -27,3 +28,5 @@ initProjectSelects(); initSearchSettings(); initCascadingSettingsLockPopovers(); + +initGroupSettingsReadme(); diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js index 1b3c7ba5a52..2e71eced66f 100644 --- a/app/assets/javascripts/pages/groups/group_members/index.js +++ b/app/assets/javascripts/pages/groups/group_members/index.js @@ -23,7 +23,7 @@ const APP_OPTIONS = { requestFormatter: groupMemberRequestFormatter, filteredSearchBar: { show: true, - tokens: ['two_factor', 'with_inherited_permissions', 'enterprise'], + tokens: ['two_factor', 'with_inherited_permissions', 'enterprise', 'user_type'], searchParam: 'search', placeholder: s__('Members|Filter members'), recentSearchesStorageKey: 'group_members', diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue index 8b68cb5f3bf..513f4968dbd 100644 --- a/app/assets/javascripts/pages/groups/new/components/app.vue +++ b/app/assets/javascripts/pages/groups/new/components/app.vue @@ -11,6 +11,10 @@ export default { NewNamespacePage, }, props: { + rootPath: { + type: String, + required: true, + }, groupsUrl: { type: String, required: true, @@ -44,6 +48,7 @@ export default { { text: s__('GroupsNew|New subgroup'), href: '#' }, ] : [ + { text: s__('Navigation|Your work'), href: this.rootPath }, { text: s__('GroupsNew|Groups'), href: this.groupsUrl }, { text: s__('GroupsNew|New group'), href: '#' }, ]; diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js index b16c5f3da9f..6227d5ff880 100644 --- a/app/assets/javascripts/pages/groups/new/index.js +++ b/app/assets/javascripts/pages/groups/new/index.js @@ -22,6 +22,7 @@ initFilePickers(); function initNewGroupCreation(el) { const { hasErrors, + rootPath, groupsUrl, parentGroupUrl, parentGroupName, @@ -33,6 +34,7 @@ function initNewGroupCreation(el) { const props = { groupsUrl, + rootPath, parentGroupUrl, parentGroupName, importExistingGroupPath, diff --git a/app/assets/javascripts/pages/groups/runners/new/index.js b/app/assets/javascripts/pages/groups/runners/new/index.js new file mode 100644 index 00000000000..318643d95a4 --- /dev/null +++ b/app/assets/javascripts/pages/groups/runners/new/index.js @@ -0,0 +1,3 @@ +import { initGroupNewRunner } from '~/ci/runner/group_new_runner'; + +initGroupNewRunner(); diff --git a/app/assets/javascripts/pages/groups/runners/register/index.js b/app/assets/javascripts/pages/groups/runners/register/index.js new file mode 100644 index 00000000000..b02e33e21f2 --- /dev/null +++ b/app/assets/javascripts/pages/groups/runners/register/index.js @@ -0,0 +1,3 @@ +import { initGroupRegisterRunner } from '~/ci/runner/group_register_runner'; + +initGroupRegisterRunner(); diff --git a/app/assets/javascripts/pages/groups/settings/applications/index.js b/app/assets/javascripts/pages/groups/settings/applications/index.js new file mode 100644 index 00000000000..4dee5433ec9 --- /dev/null +++ b/app/assets/javascripts/pages/groups/settings/applications/index.js @@ -0,0 +1,3 @@ +import { initOAuthApplicationSecret } from '~/oauth_application'; + +initOAuthApplicationSecret(); diff --git a/app/assets/javascripts/pages/groups/shared/group_details.js b/app/assets/javascripts/pages/groups/shared/group_details.js index 52124865bcc..dba65c7e791 100644 --- a/app/assets/javascripts/pages/groups/shared/group_details.js +++ b/app/assets/javascripts/pages/groups/shared/group_details.js @@ -1,5 +1,3 @@ -/* eslint-disable no-new */ - import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import initInviteMembersBanner from '~/groups/init_invite_members_banner'; import initInviteMembersModal from '~/invite_members/init_invite_members_modal'; @@ -7,11 +5,11 @@ import initNotificationsDropdown from '~/notifications'; import ProjectsList from '~/projects_list'; export default function initGroupDetails() { - new ShortcutsNavigation(); + new ShortcutsNavigation(); // eslint-disable-line no-new initNotificationsDropdown(); - new ProjectsList(); + new ProjectsList(); // eslint-disable-line no-new initInviteMembersBanner(); initInviteMembersModal(); diff --git a/app/assets/javascripts/pages/groups/show/index.js b/app/assets/javascripts/pages/groups/show/index.js index 53bceb3a6f0..f6a4ca0f360 100644 --- a/app/assets/javascripts/pages/groups/show/index.js +++ b/app/assets/javascripts/pages/groups/show/index.js @@ -1,5 +1,6 @@ import leaveByUrl from '~/namespaces/leave_by_url'; import { initGroupOverviewTabs } from '~/groups/init_overview_tabs'; +import { initGroupReadme } from '~/groups/init_group_readme'; import initReadMore from '~/read_more'; import initGroupDetails from '../shared/group_details'; @@ -7,3 +8,4 @@ leaveByUrl('group'); initGroupDetails(); initGroupOverviewTabs(); initReadMore(); +initGroupReadme(); diff --git a/app/assets/javascripts/pages/import/github/details/index.js b/app/assets/javascripts/pages/import/github/details/index.js new file mode 100644 index 00000000000..44a85589c9d --- /dev/null +++ b/app/assets/javascripts/pages/import/github/details/index.js @@ -0,0 +1,3 @@ +import initImportDetails from '~/import/details'; + +initImportDetails(); diff --git a/app/assets/javascripts/pages/oauth/applications/index.js b/app/assets/javascripts/pages/oauth/applications/index.js new file mode 100644 index 00000000000..4dee5433ec9 --- /dev/null +++ b/app/assets/javascripts/pages/oauth/applications/index.js @@ -0,0 +1,3 @@ +import { initOAuthApplicationSecret } from '~/oauth_application'; + +initOAuthApplicationSecret(); diff --git a/app/assets/javascripts/pages/profiles/comment_templates/index.js b/app/assets/javascripts/pages/profiles/comment_templates/index.js new file mode 100644 index 00000000000..413816c29cc --- /dev/null +++ b/app/assets/javascripts/pages/profiles/comment_templates/index.js @@ -0,0 +1,3 @@ +import { initCommentTemplates } from '~/comment_templates'; + +initCommentTemplates(); diff --git a/app/assets/javascripts/pages/profiles/saved_replies/index.js b/app/assets/javascripts/pages/profiles/saved_replies/index.js deleted file mode 100644 index ef227b82172..00000000000 --- a/app/assets/javascripts/pages/profiles/saved_replies/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import { initSavedReplies } from '~/saved_replies'; - -initSavedReplies(); diff --git a/app/assets/javascripts/pages/projects/artifacts/index.js b/app/assets/javascripts/pages/projects/artifacts/index.js index 4aa9b225790..df8f110a60d 100644 --- a/app/assets/javascripts/pages/projects/artifacts/index.js +++ b/app/assets/javascripts/pages/projects/artifacts/index.js @@ -1,3 +1,3 @@ -import { initArtifactsTable } from '~/artifacts/index'; +import { initArtifactsTable } from '~/ci/artifacts/index'; initArtifactsTable(); diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js index 02fcc6ea940..ec894586803 100644 --- a/app/assets/javascripts/pages/projects/blob/show/index.js +++ b/app/assets/javascripts/pages/projects/blob/show/index.js @@ -8,6 +8,7 @@ import { BlobViewer, initAuxiliaryViewer } from '~/blob/viewer/index'; import GpgBadges from '~/gpg_badges'; import createDefaultClient from '~/lib/graphql'; import initBlob from '~/pages/projects/init_blob'; +import ForkInfo from '~/repository/components/fork_info.vue'; import initWebIdeLink from '~/pages/projects/shared/web_ide_link'; import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue'; import BlobContentViewer from '~/repository/components/blob_content_viewer.vue'; @@ -16,6 +17,7 @@ import createStore from '~/code_navigation/store'; import { generateRefDestinationPath } from '~/repository/utils/ref_switcher_utils'; import RefSelector from '~/ref/components/ref_selector.vue'; import { joinPaths, visitUrl } from '~/lib/utils/url_utility'; +import { parseBoolean } from '~/lib/utils/common_utils'; Vue.use(Vuex); Vue.use(VueApollo); @@ -44,6 +46,7 @@ const initRefSwitcher = () => { projectId, value: refType ? joinPaths('refs', refType, ref) : ref, useSymbolicRefNames: true, + queryParams: { sort: 'updated_desc' }, }, on: { input(selectedRef) { @@ -58,7 +61,15 @@ const initRefSwitcher = () => { initRefSwitcher(); if (viewBlobEl) { - const { blobPath, projectPath, targetBranch, originalBranch } = viewBlobEl.dataset; + const { + blobPath, + projectPath, + targetBranch, + originalBranch, + resourceId, + userId, + explainCodeAvailable, + } = viewBlobEl.dataset; // eslint-disable-next-line no-new new Vue({ @@ -69,6 +80,9 @@ if (viewBlobEl) { provide: { targetBranch, originalBranch, + resourceId, + userId, + explainCodeAvailable: parseBoolean(explainCodeAvailable), }, render(createElement) { return createElement(BlobContentViewer, { @@ -87,6 +101,47 @@ if (viewBlobEl) { initBlob(); } +const initForkInfo = () => { + const forkEl = document.getElementById('js-fork-info'); + if (!forkEl) { + return null; + } + const { + projectPath, + selectedBranch, + sourceName, + sourcePath, + sourceDefaultBranch, + canSyncBranch, + aheadComparePath, + behindComparePath, + canUserCreateMrInFork, + createMrPath, + } = forkEl.dataset; + return new Vue({ + el: forkEl, + apolloProvider, + render(h) { + return h(ForkInfo, { + props: { + canSyncBranch: parseBoolean(canSyncBranch), + projectPath, + selectedBranch, + sourceName, + sourcePath, + sourceDefaultBranch, + aheadComparePath, + behindComparePath, + canUserCreateMrInFork, + createMrPath, + }, + }); + }, + }); +}; + +initForkInfo(); + const CommitPipelineStatusEl = document.querySelector('.js-commit-pipeline-status'); const statusLink = document.querySelector('.commit-actions .ci-status-link'); if (statusLink) { diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js index f871cd804e7..9a47a720709 100644 --- a/app/assets/javascripts/pages/projects/commit/show/index.js +++ b/app/assets/javascripts/pages/projects/commit/show/index.js @@ -18,11 +18,7 @@ import '~/sourcegraph/load'; import DiffStats from '~/diffs/components/diff_stats.vue'; import { initReportAbuse } from '~/projects/report_abuse'; -const hasPerfBar = document.querySelector('.with-performance-bar'); -const performanceHeight = hasPerfBar ? 35 : 0; -initDiffStatsDropdown( - (document.querySelector('.navbar-gitlab')?.offsetHeight ?? 0) + performanceHeight, -); +initDiffStatsDropdown(true); new ZenMode(); new ShortcutsNavigation(); diff --git a/app/assets/javascripts/pages/projects/compare/show/index.js b/app/assets/javascripts/pages/projects/compare/show/index.js index 760bf3f7131..5bcdd34e258 100644 --- a/app/assets/javascripts/pages/projects/compare/show/index.js +++ b/app/assets/javascripts/pages/projects/compare/show/index.js @@ -7,8 +7,7 @@ import syntaxHighlight from '~/syntax_highlight'; initCompareSelector(); new Diff(); // eslint-disable-line no-new -const paddingTop = 16; -initDiffStatsDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop); +initDiffStatsDropdown(true); GpgBadges.fetch(); syntaxHighlight([document.querySelector('.files')]); diff --git a/app/assets/javascripts/pages/projects/cycle_analytics/show/index.js b/app/assets/javascripts/pages/projects/cycle_analytics/show/index.js index 05a1bbc69ed..fe9f0c7e69f 100644 --- a/app/assets/javascripts/pages/projects/cycle_analytics/show/index.js +++ b/app/assets/javascripts/pages/projects/cycle_analytics/show/index.js @@ -1,3 +1,3 @@ -import initCycleAnalytics from '~/analytics/cycle_analytics'; +import cycleAnalyticsAppBundle from 'ee_else_ce/analytics/cycle_analytics/bundle'; -initCycleAnalytics(); +cycleAnalyticsAppBundle(); diff --git a/app/assets/javascripts/pages/projects/issues/edit/index.js b/app/assets/javascripts/pages/projects/issues/edit/index.js index 06dcd2c2d94..c5b63b74c35 100644 --- a/app/assets/javascripts/pages/projects/issues/edit/index.js +++ b/app/assets/javascripts/pages/projects/issues/edit/index.js @@ -1,3 +1,8 @@ import { initForm } from 'ee_else_ce/issues'; +import { mountMarkdownEditor } from '~/vue_shared/components/markdown/mount_markdown_editor'; +import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors'; initForm(); + +// eslint-disable-next-line no-new +new IssuableTemplateSelectors({ warnTemplateOverride: true, editor: mountMarkdownEditor() }); diff --git a/app/assets/javascripts/pages/projects/issues/new/index.js b/app/assets/javascripts/pages/projects/issues/new/index.js index 06dcd2c2d94..c5b63b74c35 100644 --- a/app/assets/javascripts/pages/projects/issues/new/index.js +++ b/app/assets/javascripts/pages/projects/issues/new/index.js @@ -1,3 +1,8 @@ import { initForm } from 'ee_else_ce/issues'; +import { mountMarkdownEditor } from '~/vue_shared/components/markdown/mount_markdown_editor'; +import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors'; initForm(); + +// eslint-disable-next-line no-new +new IssuableTemplateSelectors({ warnTemplateOverride: true, editor: mountMarkdownEditor() }); diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js index 2718765ee23..3d81e77f879 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js +++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js @@ -3,6 +3,8 @@ import initPipelines from '~/commit/pipelines/pipelines_bundle'; import MergeRequest from '~/merge_request'; import CompareApp from '~/merge_requests/components/compare_app.vue'; import { __ } from '~/locale'; +import { mountMarkdownEditor } from '~/vue_shared/components/markdown/mount_markdown_editor'; +import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors'; const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare'); if (mrNewCompareNode) { @@ -82,4 +84,6 @@ if (mrNewCompareNode) { action: mrNewSubmitNode.dataset.mrSubmitAction, }); initPipelines(); + // eslint-disable-next-line no-new + new IssuableTemplateSelectors({ warnTemplateOverride: true, editor: mountMarkdownEditor() }); } diff --git a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js index f8cb8b30250..6127adc3584 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js +++ b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js @@ -1,10 +1,11 @@ import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; - +import { mountMarkdownEditor } from '~/vue_shared/components/markdown/mount_markdown_editor'; import { GitLabDropdown } from '~/deprecated_jquery_dropdown/gl_dropdown'; import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request'; +import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors'; import initCheckFormState from './check_form_state'; import initFormUpdate from './update_form'; @@ -72,3 +73,5 @@ initMergeRequest(); initFormUpdate(); initCheckFormState(); initTargetBranchSelector(); +// eslint-disable-next-line no-new +new IssuableTemplateSelectors({ warnTemplateOverride: true, editor: mountMarkdownEditor() }); diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js index d4734b8842d..599fd225de9 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js +++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js @@ -4,19 +4,13 @@ import $ from 'jquery'; import IssuableForm from 'ee_else_ce/issuable/issuable_form'; import IssuableLabelSelector from '~/issuable/issuable_label_selector'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; -import GLForm from '~/gl_form'; import LabelsSelect from '~/labels/labels_select'; -import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors'; import { mountMilestoneDropdown } from '~/sidebar/mount_sidebar'; export default () => { new ShortcutsNavigation(); - new GLForm($('.merge-request-form')); new IssuableForm($('.merge-request-form')); IssuableLabelSelector(); new LabelsSelect(); - new IssuableTemplateSelectors({ - warnTemplateOverride: true, - }); mountMilestoneDropdown('[name="merge_request[milestone_id]"]'); }; diff --git a/app/assets/javascripts/pages/projects/ml/experiments/show/index.js b/app/assets/javascripts/pages/projects/ml/experiments/show/index.js index a90cabb3c68..f50763151ef 100644 --- a/app/assets/javascripts/pages/projects/ml/experiments/show/index.js +++ b/app/assets/javascripts/pages/projects/ml/experiments/show/index.js @@ -9,6 +9,7 @@ const initShowExperiment = () => { } const props = { + experiment: JSON.parse(element.dataset.experiment), candidates: JSON.parse(element.dataset.candidates), metricNames: JSON.parse(element.dataset.metrics), paramNames: JSON.parse(element.dataset.params), diff --git a/app/assets/javascripts/pages/projects/network/show/index.js b/app/assets/javascripts/pages/projects/network/show/index.js index 414636f0a74..a669ea5baaf 100644 --- a/app/assets/javascripts/pages/projects/network/show/index.js +++ b/app/assets/javascripts/pages/projects/network/show/index.js @@ -24,7 +24,7 @@ const initRefSwitcher = () => { }, on: { input(selectedRef) { - visitUrl(joinPaths(networkRootPath, selectedRef)); + visitUrl(joinPaths(networkRootPath, encodeURIComponent(selectedRef))); }, }, }); diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue index 242c5a1a97b..eab4be4dcf1 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue @@ -176,7 +176,7 @@ export default { <gl-icon v-if="showDailyLimitMessage(option)" v-gl-tooltip.hover - name="question" + name="question-o" :title="scheduleDailyLimitMsg" /> </gl-form-radio> diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js index 5f15a11e708..e6ee6b702bb 100644 --- a/app/assets/javascripts/pages/projects/project.js +++ b/app/assets/javascripts/pages/projects/project.js @@ -3,28 +3,10 @@ import $ from 'jquery'; import { setCookie } from '~/lib/utils/common_utils'; import initClonePanel from '~/clone_panel'; -import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; -import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; -import { serializeForm } from '~/lib/utils/forms'; -import { mergeUrlParams } from '~/lib/utils/url_utility'; -import { __ } from '~/locale'; - -const BRANCH_REF_TYPE = 'heads'; -const TAG_REF_TYPE = 'tags'; -const BRANCH_GROUP_NAME = __('Branches'); -const TAG_GROUP_NAME = __('Tags'); export default class Project { constructor() { initClonePanel(); - // Ref switcher - if (document.querySelector('.js-project-refs-dropdown')) { - Project.initRefSwitcher(); - $('.project-refs-select').on('change', function () { - return $(this).parents('form').trigger('submit'); - }); - } $('.js-hide-no-ssh-message').on('click', function (e) { setCookie('hide_no_ssh_message', 'false'); @@ -48,125 +30,4 @@ export default class Project { static changeProject(url) { return (window.location = url); } - - static initRefSwitcher() { - const refListItem = document.createElement('li'); - const refLink = document.createElement('a'); - - refLink.href = '#'; - - return $('.js-project-refs-dropdown').each(function () { - const $dropdown = $(this); - const selected = $dropdown.data('selected'); - const refType = $dropdown.data('refType'); - const fieldName = $dropdown.data('fieldName'); - const shouldVisit = Boolean($dropdown.data('visit')); - const $form = $dropdown.closest('form'); - const path = $form.find('#path').val(); - const action = $form.attr('action'); - const linkTarget = mergeUrlParams(serializeForm($form[0]), action); - - return initDeprecatedJQueryDropdown($dropdown, { - data(term, callback) { - axios - .get($dropdown.data('refsUrl'), { - params: { - ref: $dropdown.data('ref'), - search: term, - }, - }) - .then(({ data }) => callback(data)) - .catch(() => - createAlert({ - message: __('An error occurred while getting projects'), - }), - ); - }, - selectable: true, - filterable: true, - filterRemote: true, - filterByText: true, - inputFieldName: $dropdown.data('inputFieldName'), - fieldName, - renderRow(ref, _, params) { - const li = refListItem.cloneNode(false); - - const link = refLink.cloneNode(false); - - if (ref === selected) { - // Check group and current ref type to avoid adding a class when tags and branches share the same name - if ( - (refType === BRANCH_REF_TYPE && params.group === BRANCH_GROUP_NAME) || - (refType === TAG_REF_TYPE && params.group === TAG_GROUP_NAME) || - !refType - ) { - link.className = 'is-active'; - } - } - - link.textContent = ref; - link.dataset.ref = ref; - if (ref.length > 0 && shouldVisit) { - const urlParams = { [fieldName]: ref }; - if (params.group === BRANCH_GROUP_NAME) { - urlParams.ref_type = BRANCH_REF_TYPE; - } else { - urlParams.ref_type = TAG_REF_TYPE; - } - link.href = mergeUrlParams(urlParams, linkTarget); - } - - li.appendChild(link); - - return li; - }, - id(obj, $el) { - return $el.attr('data-ref'); - }, - toggleLabel(obj, $el) { - return $el.text().trim(); - }, - clicked(options) { - const { e } = options; - - if (!shouldVisit) { - e.preventDefault(); - } - - // Some pages need to dynamically get the current path - // so they can opt-in to JS getting the path from the - // current URL by not setting a path in the dropdown form - if (shouldVisit && path === undefined) { - e.preventDefault(); - - const selectedUrl = new URL(e.target.href); - const loc = window.location.href; - - if (loc.includes('/-/')) { - const currentRef = $dropdown.data('ref'); - // The split and startWith is to ensure an exact word match - // and avoid partial match ie. currentRef is "dev" and loc is "development" - const splitPathAfterRefPortion = loc.split('/-/')[1].split(currentRef)[1]; - const doesPathContainRef = splitPathAfterRefPortion?.startsWith('/'); - - if (doesPathContainRef) { - // We are ignoring the url containing the ref portion - // and plucking the thereafter portion to reconstructure the url that is correct - const targetPath = splitPathAfterRefPortion?.slice(1).split('#')[0].split('?')[0]; - selectedUrl.searchParams.set('path', targetPath); - selectedUrl.hash = window.location.hash; - } - } - - // Open in new window if "meta" key is pressed - if (e.metaKey) { - window.open(selectedUrl.href, '_blank'); - } else { - window.location.href = selectedUrl.href; - } - } - }, - }); - }); - } } diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js index d2263fa815d..087808c33da 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js @@ -1,3 +1,4 @@ +import 'bootstrap/js/dist/collapse'; import MirrorRepos from '~/mirrors/mirror_repos'; import mountBranchRules from '~/projects/settings/repository/branch_rules/mount_branch_rules'; import mountDefaultBranchSelector from '~/projects/settings/mount_default_branch_selector'; diff --git a/app/assets/javascripts/pages/projects/usage_quotas/index.js b/app/assets/javascripts/pages/projects/usage_quotas/index.js index 885b8ca8e12..d907b8a470d 100644 --- a/app/assets/javascripts/pages/projects/usage_quotas/index.js +++ b/app/assets/javascripts/pages/projects/usage_quotas/index.js @@ -1,9 +1,21 @@ import initProjectStorage from '~/usage_quotas/storage/init_project_storage'; import initSearchSettings from '~/search_settings'; +import { GlTabsBehavior, HISTORY_TYPE_HASH } from '~/tabs'; + +const initGlTabs = () => { + const tabsEl = document.getElementById('js-project-usage-quotas-tabs'); + if (!tabsEl) { + return; + } + + // eslint-disable-next-line no-new + new GlTabsBehavior(tabsEl, { history: HISTORY_TYPE_HASH }); +}; const initVueApp = () => { initProjectStorage('js-project-storage-count-app'); }; +initGlTabs(); initVueApp(); initSearchSettings(); diff --git a/app/assets/javascripts/pages/registrations/new/index.js b/app/assets/javascripts/pages/registrations/new/index.js index b8de2757284..00f7c5d60d1 100644 --- a/app/assets/javascripts/pages/registrations/new/index.js +++ b/app/assets/javascripts/pages/registrations/new/index.js @@ -5,6 +5,7 @@ import LengthValidator from '~/validators/length_validator'; import UsernameValidator from '~/pages/sessions/new/username_validator'; import EmailFormatValidator from '~/pages/sessions/new/email_format_validator'; import { initLanguageSwitcher } from '~/language_switcher'; +import { initTogglePasswordVisibility } from '~/authentication/password'; import Tracking from '~/tracking'; new UsernameValidator(); // eslint-disable-line no-new @@ -19,3 +20,4 @@ Tracking.enableFormTracking({ }); initLanguageSwitcher(); +initTogglePasswordVisibility(); diff --git a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js index ee48543f0d2..bad8a7cedc6 100644 --- a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js +++ b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js @@ -14,7 +14,7 @@ export default class OAuthRememberMe { } bindEvents() { - $('#remember_me', this.container).on('click', this.toggleRememberMe); + $('#remember_me_omniauth', this.container).on('click', this.toggleRememberMe); } toggleRememberMe(event) { diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue index 549c964cce4..3b38d715ea5 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -128,6 +128,9 @@ export default { }; }, computed: { + autocompleteDataSources() { + return gl.GfmAutoComplete?.dataSources; + }, noContent() { return !this.content.trim(); }, @@ -351,6 +354,8 @@ export default { :enable-content-editor="isMarkdownFormat" :enable-preview="isMarkdownFormat" :autofocus="pageInfo.persisted" + :enable-autocomplete="true" + :autocomplete-data-sources="autocompleteDataSources" :drawio-enabled="true" @contentEditor="notifyContentEditorActive" @markdownField="notifyContentEditorInactive" diff --git a/app/assets/javascripts/pages/time_tracking/timelogs/index.js b/app/assets/javascripts/pages/time_tracking/timelogs/index.js new file mode 100644 index 00000000000..41c78fbe3a6 --- /dev/null +++ b/app/assets/javascripts/pages/time_tracking/timelogs/index.js @@ -0,0 +1,3 @@ +import initTimelogsApp from '~/time_tracking'; + +initTimelogsApp(); |