summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pages
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/pages')
-rw-r--r--app/assets/javascripts/pages/abuse_reports/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/applications/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/jobs/components/cancel_jobs.vue (renamed from app/assets/javascripts/pages/admin/jobs/index/components/cancel_jobs.vue)0
-rw-r--r--app/assets/javascripts/pages/admin/jobs/components/cancel_jobs_modal.vue (renamed from app/assets/javascripts/pages/admin/jobs/index/components/cancel_jobs_modal.vue)0
-rw-r--r--app/assets/javascripts/pages/admin/jobs/components/constants.js (renamed from app/assets/javascripts/pages/admin/jobs/index/components/constants.js)9
-rw-r--r--app/assets/javascripts/pages/admin/jobs/components/table/admin_jobs_table_app.vue118
-rw-r--r--app/assets/javascripts/pages/admin/jobs/components/table/graphql/cache_config.js62
-rw-r--r--app/assets/javascripts/pages/admin/jobs/components/table/graphql/queries/get_all_jobs.query.graphql81
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/table/admin_jobs_table_app.vue19
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/index.js17
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/new/components/app.vue5
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/runners/new/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/runners/register/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/settings/applications/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/shared/group_details.js6
-rw-r--r--app/assets/javascripts/pages/groups/show/index.js2
-rw-r--r--app/assets/javascripts/pages/import/github/details/index.js3
-rw-r--r--app/assets/javascripts/pages/oauth/applications/index.js3
-rw-r--r--app/assets/javascripts/pages/profiles/comment_templates/index.js3
-rw-r--r--app/assets/javascripts/pages/profiles/saved_replies/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/artifacts/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js57
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/compare/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/cycle_analytics/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/issues/edit/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/issues/new/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/edit/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js6
-rw-r--r--app/assets/javascripts/pages/projects/ml/experiments/show/index.js1
-rw-r--r--app/assets/javascripts/pages/projects/network/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue2
-rw-r--r--app/assets/javascripts/pages/projects/project.js139
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js1
-rw-r--r--app/assets/javascripts/pages/projects/usage_quotas/index.js12
-rw-r--r--app/assets/javascripts/pages/registrations/new/index.js2
-rw-r--r--app/assets/javascripts/pages/sessions/new/oauth_remember_me.js2
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue5
-rw-r--r--app/assets/javascripts/pages/time_tracking/timelogs/index.js3
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();