diff options
Diffstat (limited to 'app/assets/javascripts/pages')
41 files changed, 365 insertions, 199 deletions
diff --git a/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js b/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js index 8cecc1d3ef7..97fb64f9971 100644 --- a/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js +++ b/app/assets/javascripts/pages/admin/application_settings/payload_downloader.js @@ -1,4 +1,4 @@ -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; @@ -29,7 +29,7 @@ export default class PayloadDownloader { PayloadDownloader.downloadFile(data); }) .catch(() => { - createFlash({ + createAlert({ message: __('Error fetching payload data.'), }); }) diff --git a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js index 616005565c4..1cd19fc09a8 100644 --- a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js +++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js @@ -1,4 +1,4 @@ -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; @@ -43,7 +43,7 @@ export default class PayloadPreviewer { }) .catch(() => { this.spinner.classList.remove('gl-display-inline'); - createFlash({ + createAlert({ message: __('Error fetching payload data.'), }); }); diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js index 18ba89f8856..40348e0b18a 100644 --- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js +++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import { debounce } from 'lodash'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; import { __ } from '~/locale'; @@ -30,7 +30,7 @@ export default () => { $jsBroadcastMessagePreview.html(data); }) .catch(() => - createFlash({ + createAlert({ message: __('An error occurred while rendering preview broadcast message'), }), ); diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/index.js b/app/assets/javascripts/pages/admin/broadcast_messages/index.js index f687423594d..ffd976be8c6 100644 --- a/app/assets/javascripts/pages/admin/broadcast_messages/index.js +++ b/app/assets/javascripts/pages/admin/broadcast_messages/index.js @@ -1,5 +1,10 @@ +import initBroadcastMessages from '~/admin/broadcast_messages'; import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior'; import initBroadcastMessagesForm from './broadcast_message'; -initBroadcastMessagesForm(); -initDeprecatedRemoveRowBehavior(); +if (gon.features.vueBroadcastMessages) { + initBroadcastMessages(); +} else { + initBroadcastMessagesForm(); + initDeprecatedRemoveRowBehavior(); +} diff --git a/app/assets/javascripts/pages/admin/dashboard/index.js b/app/assets/javascripts/pages/admin/dashboard/index.js new file mode 100644 index 00000000000..b63e612be47 --- /dev/null +++ b/app/assets/javascripts/pages/admin/dashboard/index.js @@ -0,0 +1,3 @@ +import initGitlabVersionCheck from '~/gitlab_version_check'; + +initGitlabVersionCheck(); diff --git a/app/assets/javascripts/pages/admin/groups/show/index.js b/app/assets/javascripts/pages/admin/groups/show/index.js deleted file mode 100644 index 86b80a0ba5b..00000000000 --- a/app/assets/javascripts/pages/admin/groups/show/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import UsersSelect from '~/users_select'; - -new UsersSelect(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/admin/index.js b/app/assets/javascripts/pages/admin/index.js index a249864fa36..eaee625c047 100644 --- a/app/assets/javascripts/pages/admin/index.js +++ b/app/assets/javascripts/pages/admin/index.js @@ -1,10 +1,8 @@ -import initGitlabVersionCheck from '~/gitlab_version_check'; import initAdminStatisticsPanel from '~/admin/statistics_panel/index'; import initVueAlerts from '~/vue_alerts'; import initAdmin from './admin'; initVueAlerts(); -initGitlabVersionCheck(); const statisticsPanelContainer = document.getElementById('js-admin-statistics-container'); initAdmin(); diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue index 63b98f4143b..4f42ef2892d 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue +++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue @@ -1,6 +1,6 @@ <script> import { GlModal } from '@gitlab/ui'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { redirectTo } from '~/lib/utils/url_utility'; import { __, s__ } from '~/locale'; @@ -31,7 +31,7 @@ export default { redirectTo(response.request.responseURL); }) .catch((error) => { - createFlash({ + createAlert({ message: s__('AdminArea|Stopping jobs failed'), }); throw error; diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js index b6f42a27002..2a7619da8cc 100644 --- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js +++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js @@ -4,7 +4,7 @@ import $ from 'jquery'; import { getGroups } from '~/api/groups_api'; import { getProjects } from '~/api/projects_api'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { isMetaClick } from '~/lib/utils/common_utils'; import { addDelimiter } from '~/lib/utils/text_utility'; @@ -119,7 +119,7 @@ export default class Todos { }) .catch(() => { this.updateRowState(target, true); - return createFlash({ + return createAlert({ message: __('Error updating status of to-do item.'), }); }); @@ -168,7 +168,7 @@ export default class Todos { this.updateBadges(data); }) .catch(() => - createFlash({ + createAlert({ message: __('Error updating status for all to-do items.'), }), ); diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js index de28f027126..377ba0f13a9 100644 --- a/app/assets/javascripts/pages/groups/merge_requests/index.js +++ b/app/assets/javascripts/pages/groups/merge_requests/index.js @@ -1,6 +1,10 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; -import { initBulkUpdateSidebar } from '~/issuable/bulk_update_sidebar'; +import { + initBulkUpdateSidebar, + initStatusDropdown, + initSubscriptionsDropdown, +} from '~/issuable/bulk_update_sidebar'; import { FILTERED_SEARCH } from '~/filtered_search/constants'; import initFilteredSearch from '~/pages/search/init_filtered_search'; import projectSelect from '~/project_select'; @@ -9,6 +13,8 @@ const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_'; addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys); initBulkUpdateSidebar(ISSUABLE_BULK_UPDATE_PREFIX); +initStatusDropdown(); +initSubscriptionsDropdown(); initFilteredSearch({ page: FILTERED_SEARCH.MERGE_REQUESTS, diff --git a/app/assets/javascripts/pages/groups/new/group_path_validator.js b/app/assets/javascripts/pages/groups/new/group_path_validator.js index 8ce73be6e74..fa111032b2e 100644 --- a/app/assets/javascripts/pages/groups/new/group_path_validator.js +++ b/app/assets/javascripts/pages/groups/new/group_path_validator.js @@ -1,6 +1,6 @@ import { debounce } from 'lodash'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { __ } from '~/locale'; import InputValidator from '~/validators/input_validator'; import { getGroupPathAvailability } from '~/rest_api'; @@ -62,7 +62,7 @@ export default class GroupPathValidator extends InputValidator { } }) .catch(() => - createFlash({ + createAlert({ message: __('An error occurred while validating group path'), }), ); diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js index 7dab5258b24..a555038ed5c 100644 --- a/app/assets/javascripts/pages/groups/new/index.js +++ b/app/assets/javascripts/pages/groups/new/index.js @@ -1,4 +1,6 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; import BindInOut from '~/behaviors/bind_in_out'; import initFilePickers from '~/file_pickers'; import Group from '~/group'; @@ -8,6 +10,8 @@ import NewGroupCreationApp from './components/app.vue'; import GroupPathValidator from './group_path_validator'; import initToggleInviteMembers from './toggle_invite_members'; +Vue.use(VueApollo); + new GroupPathValidator(); // eslint-disable-line no-new new Group(); // eslint-disable-line no-new initGroupNameAndPath(); @@ -31,8 +35,13 @@ function initNewGroupCreation(el) { hasErrors: parseBoolean(hasErrors), }; + const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), + }); + return new Vue({ el, + apolloProvider, provide: { verificationRequired: parseBoolean(verificationRequired), verificationFormUrl, diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js index bf77d968e7d..b1a1cc21764 100644 --- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js @@ -2,9 +2,11 @@ import initStaleRunnerCleanupSetting from 'ee_else_ce/group_settings/stale_runne import initVariableList from '~/ci_variable_list'; import initSharedRunnersForm from '~/group_settings/mount_shared_runners'; import initSettingsPanels from '~/settings_panels'; +import initDeployTokens from '~/deploy_tokens'; // Initialize expandable settings panels initSettingsPanels(); +initDeployTokens(); initSharedRunnersForm(); initStaleRunnerCleanupSetting(); diff --git a/app/assets/javascripts/pages/groups/settings/index.js b/app/assets/javascripts/pages/groups/settings/index.js index cb787c60002..7e97cd865b7 100644 --- a/app/assets/javascripts/pages/groups/settings/index.js +++ b/app/assets/javascripts/pages/groups/settings/index.js @@ -1,5 +1,7 @@ import initRevokeButton from '~/deploy_tokens/init_revoke_button'; import initSearchSettings from '~/search_settings'; +import initDeployTokens from '~/deploy_tokens'; +initDeployTokens(); initSearchSettings(); initRevokeButton(); diff --git a/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue b/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue index 9cce6723bf7..6feb4c2188f 100644 --- a/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue +++ b/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue @@ -2,7 +2,7 @@ import { GlButton, GlEmptyState, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui'; import { s__, __ } from '~/locale'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils'; import { joinPaths } from '~/lib/utils/url_utility'; import { getBulkImportsHistory } from '~/rest_api'; @@ -107,7 +107,7 @@ export default { this.pageInfo = parseIntPagination(normalizeHeaders(headers)); this.historyItems = historyItems; } catch (e) { - createFlash({ message: DEFAULT_ERROR, captureError: true, error: e }); + createAlert({ message: DEFAULT_ERROR, captureError: true, error: e }); } finally { this.loading = false; } diff --git a/app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue b/app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue new file mode 100644 index 00000000000..20ce296bbec --- /dev/null +++ b/app/assets/javascripts/pages/import/fogbugz/new_user_map/components/user_select.vue @@ -0,0 +1,95 @@ +<script> +import { GlAvatarLabeled, GlListbox } from '@gitlab/ui'; +import { __ } from '~/locale'; +import searchUsersQuery from '~/graphql_shared/queries/users_search_all.query.graphql'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; + +import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; + +const USERS_PER_PAGE = 20; + +export default { + components: { + GlAvatarLabeled, + GlListbox, + }, + props: { + name: { + type: String, + required: true, + }, + }, + apollo: { + usersQuery: { + query: searchUsersQuery, + variables() { + return { + search: this.search, + first: USERS_PER_PAGE, + }; + }, + update(data) { + return data; + }, + debounce: DEFAULT_DEBOUNCE_AND_THROTTLE_MS, + }, + }, + data() { + return { + user: '', + search: '', + }; + }, + computed: { + userId() { + return getIdFromGraphQLId(this.user); + }, + users() { + return [ + { text: __('(no user)'), value: '' }, + ...(this.usersQuery?.users.nodes || []).map((u) => ({ + username: `@${u.username}`, + avatarUrl: u.avatarUrl, + text: u.name, + value: u.id, + })), + ]; + }, + }, + methods: { + clearTransform() { + // FIXME: workaround for listbox issue + // https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1986 + const { listbox } = this.$refs; + if (listbox.querySelector('.dropdown-menu')) { + listbox.querySelector('.dropdown-menu').style.transform = ''; + } + }, + }, +}; +</script> +<template> + <div> + <gl-listbox + ref="listbox" + v-model="user" + :items="users" + searchable + is-check-centered + :searching="$apollo.loading" + @click.capture.native="clearTransform" + @search="search = $event" + > + <template #list-item="{ item }"> + <gl-avatar-labeled + shape="circle" + :size="32" + :src="item.avatarUrl" + :label="item.text" + :sub-label="item.username" + /> + </template> + </gl-listbox> + <input type="hidden" :name="name" :value="userId" /> + </div> +</template> diff --git a/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js b/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js index 86b80a0ba5b..ef549f20cf3 100644 --- a/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js +++ b/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js @@ -1,3 +1,19 @@ -import UsersSelect from '~/users_select'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import UserSelect from './components/user_select.vue'; -new UsersSelect(); // eslint-disable-line no-new +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + +Array.from(document.querySelectorAll('.js-gitlab-user')).forEach( + (node) => + new Vue({ + el: node, + apolloProvider, + render: (h) => h(UserSelect, { props: { name: node.dataset.name } }), + }), +); diff --git a/app/assets/javascripts/pages/import/history/components/import_history_app.vue b/app/assets/javascripts/pages/import/history/components/import_history_app.vue index db6f0c23dbd..09b1b3a9c0f 100644 --- a/app/assets/javascripts/pages/import/history/components/import_history_app.vue +++ b/app/assets/javascripts/pages/import/history/components/import_history_app.vue @@ -1,7 +1,7 @@ <script> import { GlButton, GlEmptyState, GlIcon, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui'; import { s__, __ } from '~/locale'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils'; import { getProjects } from '~/rest_api'; import ImportStatus from '~/import_entities/components/import_status.vue'; @@ -104,7 +104,7 @@ export default { this.pageInfo = parseIntPagination(normalizeHeaders(headers)); this.historyItems = historyItems; } catch (e) { - createFlash({ message: DEFAULT_ERROR, captureError: true, error: e }); + createAlert({ message: DEFAULT_ERROR, captureError: true, error: e }); } finally { this.loading = false; } diff --git a/app/assets/javascripts/pages/profiles/index.js b/app/assets/javascripts/pages/profiles/index.js index 6afb3636998..91b20a05196 100644 --- a/app/assets/javascripts/pages/profiles/index.js +++ b/app/assets/javascripts/pages/profiles/index.js @@ -3,6 +3,7 @@ import '~/profile/gl_crop'; import Profile from '~/profile/profile'; import initSearchSettings from '~/search_settings'; import initPasswordPrompt from './password_prompt'; +import { initTimezoneDropdown } from './init_timezone_dropdown'; // eslint-disable-next-line func-names $(document).on('input.ssh_key', '#key_key', function () { @@ -21,3 +22,4 @@ new Profile(); // eslint-disable-line no-new initSearchSettings(); initPasswordPrompt(); +initTimezoneDropdown(); diff --git a/app/assets/javascripts/pages/profiles/init_timezone_dropdown.js b/app/assets/javascripts/pages/profiles/init_timezone_dropdown.js new file mode 100644 index 00000000000..80b911493a8 --- /dev/null +++ b/app/assets/javascripts/pages/profiles/init_timezone_dropdown.js @@ -0,0 +1,34 @@ +import Vue from 'vue'; +import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue'; + +export const initTimezoneDropdown = () => { + const el = document.querySelector('.js-timezone-dropdown'); + + if (!el) { + return null; + } + + const { timezoneData, initialValue } = el.dataset; + const timezones = JSON.parse(timezoneData); + + const timezoneDropdown = new Vue({ + el, + data() { + return { + value: initialValue, + }; + }, + render(h) { + return h(TimezoneDropdown, { + props: { + value: this.value, + timezoneData: timezones, + name: 'user[timezone]', + }, + class: 'gl-md-form-input-lg', + }); + }, + }); + + return timezoneDropdown; +}; diff --git a/app/assets/javascripts/pages/projects/blame/show/index.js b/app/assets/javascripts/pages/projects/blame/show/index.js index fa22c11d1d7..1e4b9de90f2 100644 --- a/app/assets/javascripts/pages/projects/blame/show/index.js +++ b/app/assets/javascripts/pages/projects/blame/show/index.js @@ -1,3 +1,5 @@ import initBlob from '~/pages/projects/init_blob'; +import redirectToCorrectPage from '~/blame/blame_redirect'; +redirectToCorrectPage(); initBlob(); diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js index eca3cf7ab13..af0097b415c 100644 --- a/app/assets/javascripts/pages/projects/commit/show/index.js +++ b/app/assets/javascripts/pages/projects/commit/show/index.js @@ -4,7 +4,7 @@ import Vue from 'vue'; import loadAwardsHandler from '~/awards_handler'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import Diff from '~/diff'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import initDeprecatedNotes from '~/init_deprecated_notes'; import { initDiffStatsDropdown } from '~/init_diff_stats_dropdown'; import axios from '~/lib/utils/axios_utils'; @@ -69,7 +69,7 @@ if (filesContainer.length) { loadDiffStats(); }) .catch(() => { - createFlash({ message: __('An error occurred while retrieving diff files') }); + createAlert({ message: __('An error occurred while retrieving diff files') }); }); } else { new Diff(); diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue index b415e36bf09..30cefa3d717 100644 --- a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue +++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue @@ -12,7 +12,7 @@ import { } from '@gitlab/ui'; import { kebabCase } from 'lodash'; import { buildApiUrl } from '~/api/api_utils'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import csrf from '~/lib/utils/csrf'; import { redirectTo } from '~/lib/utils/url_utility'; @@ -220,7 +220,7 @@ export default { redirectTo(data.web_url); return; } catch (error) { - createFlash({ + createAlert({ message: s__( 'ForkProject|An error occurred while forking the project. Please try again.', ), diff --git a/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue b/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue index 2b3055ecd66..00e0649deed 100644 --- a/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue +++ b/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue @@ -9,7 +9,7 @@ import { GlSearchBoxByType, GlTruncate, } from '@gitlab/ui'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants'; import { s__ } from '~/locale'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; @@ -41,7 +41,7 @@ export default { return length > 0 && length < MINIMUM_SEARCH_LENGTH; }, error(error) { - createFlash({ + createAlert({ message: s__( 'ForkProject|Something went wrong while loading data. Please refresh the page to try again.', ), diff --git a/app/assets/javascripts/pages/projects/hooks/index.js b/app/assets/javascripts/pages/projects/hooks/index.js index 2a120a690ef..ed476d25f8b 100644 --- a/app/assets/javascripts/pages/projects/hooks/index.js +++ b/app/assets/javascripts/pages/projects/hooks/index.js @@ -1,3 +1,5 @@ import initSearchSettings from '~/search_settings'; +import initWebhookForm from '~/webhooks'; initSearchSettings(); +initWebhookForm(); diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js index 9a38c2cc765..65942464e2b 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js +++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/compare_autocomplete.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; import { __ } from '~/locale'; @@ -39,7 +39,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = ( } }) .catch(() => - createFlash({ + createAlert({ message: __('Error fetching refs'), }), ); 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 5179d1b31ab..406959c80ea 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js +++ b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js @@ -1,4 +1,4 @@ -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; @@ -33,7 +33,7 @@ function initTargetBranchSelector() { callback(data); }) .catch(() => - createFlash({ + createAlert({ message: __('Error fetching branches'), }), ); diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js index e284e7b2c5e..2399aafc9b5 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js +++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js @@ -2,14 +2,19 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable'; -import { initBulkUpdateSidebar, initIssueStatusSelect } from '~/issuable/bulk_update_sidebar'; +import { + initBulkUpdateSidebar, + initStatusDropdown, + initSubscriptionsDropdown, +} from '~/issuable/bulk_update_sidebar'; import { FILTERED_SEARCH } from '~/filtered_search/constants'; import { ISSUABLE_INDEX } from '~/issuable/constants'; import initFilteredSearch from '~/pages/search/init_filtered_search'; import UsersSelect from '~/users_select'; initBulkUpdateSidebar(ISSUABLE_INDEX.MERGE_REQUEST); -initIssueStatusSelect(); +initStatusDropdown(); +initSubscriptionsDropdown(); addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys); IssuableFilteredSearchTokenKeys.removeTokensForKeys('iteration'); diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js index 6dd21380bec..0edce2db0a3 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js @@ -1,3 +1,8 @@ +import initPipelineSchedulesFormApp from '~/pipeline_schedules/mount_pipeline_schedules_form_app'; import initForm from '../shared/init_form'; -initForm(); +if (gon.features?.pipelineSchedulesVue) { + initPipelineSchedulesFormApp('#pipeline-schedules-form-edit'); +} else { + initForm(); +} diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js index 9513f42d9c9..7d0930f6424 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js @@ -1,9 +1,10 @@ import Vue from 'vue'; import { BV_SHOW_MODAL } from '~/lib/utils/constants'; +import initPipelineSchedulesApp from '~/pipeline_schedules/mount_pipeline_schedules_app'; import PipelineSchedulesTakeOwnershipModal from '~/pipeline_schedules/components/take_ownership_modal.vue'; import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue'; -function initPipelineSchedules() { +function initPipelineSchedulesCallout() { const el = document.getElementById('pipeline-schedules-callout'); if (!el) { @@ -15,6 +16,7 @@ function initPipelineSchedules() { // eslint-disable-next-line no-new new Vue({ el, + name: 'PipelineSchedulesCalloutRoot', provide: { docsUrl, illustrationUrl, @@ -25,6 +27,8 @@ function initPipelineSchedules() { }); } +// TODO: move take ownership feature into new Vue app +// located in directory app/assets/javascripts/pipeline_schedules/components function initTakeownershipModal() { const modalId = 'pipeline-take-ownership-modal'; const buttonSelector = 'js-take-ownership-button'; @@ -63,5 +67,10 @@ function initTakeownershipModal() { }); } -initPipelineSchedules(); -initTakeownershipModal(); +initPipelineSchedulesCallout(); + +if (gon.features?.pipelineSchedulesVue) { + initPipelineSchedulesApp(); +} else { + initTakeownershipModal(); +} diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js index 6dd21380bec..06084fa729b 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js @@ -1,3 +1,8 @@ +import initPipelineSchedulesFormApp from '~/pipeline_schedules/mount_pipeline_schedules_form_app'; import initForm from '../shared/init_form'; -initForm(); +if (gon.features?.pipelineSchedulesVue) { + initPipelineSchedulesFormApp('#pipeline-schedules-form-new'); +} else { + initForm(); +} diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js index 277d2e0d30a..bc467952551 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js @@ -1,4 +1,5 @@ import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; +import { formatTimezone } from '~/lib/utils/datetime_utility'; const defaultTimezone = { identifier: 'Etc/UTC', name: 'UTC', offset: 0 }; const defaults = { @@ -17,8 +18,6 @@ export const formatUtcOffset = (offset) => { return `${prefix} ${Math.abs(offset / 3600)}`; }; -export const formatTimezone = (item) => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`; - export const findTimezoneByIdentifier = (tzList = [], identifier = null) => { if (tzList && tzList.length && identifier && identifier.length) { return tzList.find((tz) => tz.identifier === identifier) || null; diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js index ccabaad5b2e..d177c67f133 100644 --- a/app/assets/javascripts/pages/projects/project.js +++ b/app/assets/javascripts/pages/projects/project.js @@ -4,7 +4,7 @@ import $ from 'jquery'; import { setCookie } from '~/lib/utils/common_utils'; import initClonePanel from '~/clone_panel'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { serializeForm } from '~/lib/utils/forms'; import { mergeUrlParams } from '~/lib/utils/url_utility'; @@ -80,7 +80,7 @@ export default class Project { }) .then(({ data }) => callback(data)) .catch(() => - createFlash({ + createAlert({ message: __('An error occurred while getting projects'), }), ); diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js index 6a9bd34db22..8909ff1f221 100644 --- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js @@ -10,6 +10,7 @@ import initSharedRunnersToggle from '~/projects/settings/mount_shared_runners_to import initSettingsPanels from '~/settings_panels'; import { initTokenAccess } from '~/token_access'; import { initCiSecureFiles } from '~/ci_secure_files'; +import initDeployTokens from '~/deploy_tokens'; // Initialize expandable settings panels initSettingsPanels(); @@ -34,6 +35,7 @@ document.querySelector('.js-toggle-extra-settings').addEventListener('click', (e }); registrySettingsApp(); +initDeployTokens(); initDeployFreeze(); initSettingsPipelinesTriggers(); diff --git a/app/assets/javascripts/pages/projects/settings/index.js b/app/assets/javascripts/pages/projects/settings/index.js index cb787c60002..7e97cd865b7 100644 --- a/app/assets/javascripts/pages/projects/settings/index.js +++ b/app/assets/javascripts/pages/projects/settings/index.js @@ -1,5 +1,7 @@ import initRevokeButton from '~/deploy_tokens/init_revoke_button'; import initSearchSettings from '~/search_settings'; +import initDeployTokens from '~/deploy_tokens'; +initDeployTokens(); initSearchSettings(); initRevokeButton(); 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 655243eee30..d2263fa815d 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js @@ -1,5 +1,7 @@ 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'; + import initForm from '../form'; initForm(); @@ -8,3 +10,4 @@ const mirrorReposContainer = document.querySelector('.js-mirror-settings'); if (mirrorReposContainer) new MirrorRepos(mirrorReposContainer).init(); mountBranchRules(document.getElementById('js-branch-rules')); +mountDefaultBranchSelector(document.querySelector('.js-select-default-branch')); diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index a82f485bf44..3e5c02bbf19 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -898,7 +898,9 @@ export default { :help-path="pagesHelpPath" :label="$options.i18n.pagesLabel" :help-text=" - s__('ProjectSettings|With GitLab Pages you can host your static websites on GitLab.') + s__( + 'ProjectSettings|With GitLab Pages you can host your static websites on GitLab. GitLab Pages uses a caching mechanism for efficiency. Your changes may not take effect until that cache is invalidated, which usually takes less than a minute.', + ) " > <project-feature-setting @@ -979,20 +981,20 @@ export default { name="project[project_feature_attributes][feature_flags_access_level]" /> </project-setting-row> - <project-setting-row - ref="releases-settings" - :label="$options.i18n.releasesLabel" - :help-text="$options.i18n.releasesHelpText" - :help-path="releasesHelpPath" - > - <project-feature-setting - v-model="releasesAccessLevel" - :label="$options.i18n.releasesLabel" - :options="featureAccessLevelOptions" - name="project[project_feature_attributes][releases_access_level]" - /> - </project-setting-row> </template> + <project-setting-row + ref="releases-settings" + :label="$options.i18n.releasesLabel" + :help-text="$options.i18n.releasesHelpText" + :help-path="releasesHelpPath" + > + <project-feature-setting + v-model="releasesAccessLevel" + :label="$options.i18n.releasesLabel" + :options="featureAccessLevelOptions" + name="project[project_feature_attributes][releases_access_level]" + /> + </project-setting-row> </div> <project-setting-row v-if="canDisableEmails" ref="email-settings" class="mb-3"> <label class="js-emails-disabled"> diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js index 7ea744a68a6..1848aa70cf0 100644 --- a/app/assets/javascripts/pages/sessions/new/username_validator.js +++ b/app/assets/javascripts/pages/sessions/new/username_validator.js @@ -1,6 +1,6 @@ import { debounce } from 'lodash'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; import InputValidator from '~/validators/input_validator'; @@ -51,7 +51,7 @@ export default class UsernameValidator extends InputValidator { ); }) .catch(() => - createFlash({ + createAlert({ message: __('An error occurred while validating username'), }), ); diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue index 10b95fd6f3c..b72579276e8 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue @@ -1,6 +1,6 @@ <script> import { GlSkeletonLoader, GlSafeHtmlDirective, GlAlert } from '@gitlab/ui'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { __ } from '~/locale'; import axios from '~/lib/utils/axios_utils'; import { handleLocationHash } from '~/lib/utils/common_utils'; @@ -47,7 +47,7 @@ export default { handleLocationHash(); }) .catch(() => - createFlash({ + createAlert({ message: this.$options.i18n.renderingContentFailed, }), ); 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 9acc1cb62a1..7b9656de362 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -8,21 +8,19 @@ import { GlFormGroup, GlFormInput, GlFormSelect, - GlSegmentedControl, } from '@gitlab/ui'; -import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; -import axios from '~/lib/utils/axios_utils'; +import { getDraft, clearDraft, updateDraft } from '~/lib/utils/autosave'; import csrf from '~/lib/utils/csrf'; import { setUrlFragment } from '~/lib/utils/url_utility'; import { s__, sprintf } from '~/locale'; import Tracking from '~/tracking'; -import MarkdownField from '~/vue_shared/components/markdown/field.vue'; +import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue'; import { - CONTENT_EDITOR_LOADED_ACTION, SAVED_USING_CONTENT_EDITOR_ACTION, WIKI_CONTENT_EDITOR_TRACKING_LABEL, WIKI_FORMAT_LABEL, WIKI_FORMAT_UPDATED_ACTION, + CONTENT_EDITOR_LOADED_ACTION, } from '../constants'; const trackingMixin = Tracking.mixin({ @@ -36,6 +34,29 @@ const MARKDOWN_LINK_TEXT = { org: '[[page-slug]]', }; +function getPagePath(pageInfo) { + return pageInfo.persisted ? pageInfo.path : pageInfo.createPath; +} + +const autosaveKey = (pageInfo, field) => { + const path = pageInfo.persisted ? pageInfo.path : pageInfo.createPath; + + return `${path}/${field}`; +}; + +const titleAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'title'); +const formatAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'format'); +const contentAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'content'); +const commitAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'commit'); + +const getTitle = (pageInfo) => getDraft(titleAutosaveKey(pageInfo)) || pageInfo.title?.trim() || ''; +const getFormat = (pageInfo) => + getDraft(formatAutosaveKey(pageInfo)) || pageInfo.format || 'markdown'; +const getContent = (pageInfo) => getDraft(contentAutosaveKey(pageInfo)) || pageInfo.content || ''; +const getCommitMessage = (pageInfo) => + getDraft(commitAutosaveKey(pageInfo)) || pageInfo.commitMessage || ''; +const getIsFormDirty = (pageInfo) => Boolean(getDraft(titleAutosaveKey(pageInfo))); + export default { i18n: { title: { @@ -74,10 +95,6 @@ export default { }, cancel: s__('WikiPage|Cancel'), }, - switchEditingControlOptions: [ - { text: s__('Wiki Page|Source'), value: 'source' }, - { text: s__('Wiki Page|Rich text'), value: 'richText' }, - ], components: { GlIcon, GlForm, @@ -87,26 +104,21 @@ export default { GlSprintf, GlLink, GlButton, - GlSegmentedControl, - MarkdownField, - LocalStorageSync, - ContentEditor: () => - import( - /* webpackChunkName: 'content_editor' */ '~/content_editor/components/content_editor.vue' - ), + MarkdownEditor, }, mixins: [trackingMixin], inject: ['formatOptions', 'pageInfo'], data() { return { editingMode: 'source', - title: this.pageInfo.title?.trim() || '', - format: this.pageInfo.format || 'markdown', - content: this.pageInfo.content || '', - commitMessage: '', - isDirty: false, + title: getTitle(this.pageInfo), + format: getFormat(this.pageInfo), + content: getContent(this.pageInfo), + commitMessage: getCommitMessage(this.pageInfo), contentEditorEmpty: false, + isContentEditorActive: false, switchEditingControlDisabled: false, + isFormDirty: getIsFormDirty(this.pageInfo), }; }, computed: { @@ -117,7 +129,7 @@ export default { return csrf.token; }, formAction() { - return this.pageInfo.persisted ? this.pageInfo.path : this.pageInfo.createPath; + return getPagePath(this.pageInfo); }, helpPath() { return setUrlFragment( @@ -162,15 +174,9 @@ export default { disableSubmitButton() { return this.noContent || !this.title; }, - isContentEditorActive() { - return this.isMarkdownFormat && this.useContentEditor; - }, - useContentEditor() { - return this.editingMode === 'richText'; - }, }, mounted() { - this.updateCommitMessage(); + if (!this.commitMessage) this.updateCommitMessage(); window.addEventListener('beforeunload', this.onPageUnload); }, @@ -178,51 +184,45 @@ export default { window.removeEventListener('beforeunload', this.onPageUnload); }, methods: { - renderMarkdown(content) { - return axios - .post(this.pageInfo.markdownPreviewPath, { text: content }) - .then(({ data }) => data.body); - }, - - setEditingMode(editingMode) { - this.editingMode = editingMode; - }, - async handleFormSubmit(e) { - e.preventDefault(); + this.isFormDirty = false; - if (this.useContentEditor) { - this.trackFormSubmit(); - } + e.preventDefault(); + this.trackFormSubmit(); this.trackWikiFormat(); // Wait until form field values are refreshed await this.$nextTick(); e.target.submit(); + }, - this.isDirty = false; + updateDrafts() { + updateDraft(titleAutosaveKey(this.pageInfo), this.title); + updateDraft(formatAutosaveKey(this.pageInfo), this.format); + updateDraft(contentAutosaveKey(this.pageInfo), this.content); + updateDraft(commitAutosaveKey(this.pageInfo), this.commitMessage); }, - handleContentChange() { - this.isDirty = true; + clearDrafts() { + clearDraft(titleAutosaveKey(this.pageInfo)); + clearDraft(formatAutosaveKey(this.pageInfo)); + clearDraft(contentAutosaveKey(this.pageInfo)); + clearDraft(commitAutosaveKey(this.pageInfo)); }, - handleContentEditorChange({ empty, markdown, changed }) { + handleContentEditorChange({ empty, markdown }) { this.contentEditorEmpty = empty; - this.isDirty = changed; this.content = markdown; }, - onPageUnload(event) { - if (!this.isDirty) return undefined; - - event.preventDefault(); - - // eslint-disable-next-line no-param-reassign - event.returnValue = ''; - return ''; + onPageUnload() { + if (this.isFormDirty) { + this.updateDrafts(); + } else { + this.clearDrafts(); + } }, updateCommitMessage() { @@ -235,8 +235,13 @@ export default { this.commitMessage = newCommitMessage; }, - trackContentEditorLoaded() { - this.track(CONTENT_EDITOR_LOADED_ACTION); + notifyContentEditorActive() { + this.isContentEditorActive = true; + this.trackContentEditorLoaded(); + }, + + notifyContentEditorInactive() { + this.isContentEditorActive = false; }, trackFormSubmit() { @@ -256,12 +261,12 @@ export default { }); }, - enableSwitchEditingControl() { - this.switchEditingControlDisabled = false; + trackContentEditorLoaded() { + this.track(CONTENT_EDITOR_LOADED_ACTION); }, - disableSwitchEditingControl() { - this.switchEditingControlDisabled = true; + submitFormWithShortcut() { + this.$refs.form.submit(); }, }, }; @@ -269,10 +274,12 @@ export default { <template> <gl-form + ref="form" :action="formAction" method="post" class="wiki-form common-note-form gl-mt-3 js-quick-submit" @submit="handleFormSubmit" + @input="isFormDirty = true" > <input :value="csrfToken" type="hidden" name="authenticity_token" /> <input v-if="pageInfo.persisted" type="hidden" name="_method" value="put" /> @@ -329,74 +336,23 @@ export default { <div class="row" data-testid="wiki-form-content-fieldset"> <div class="col-sm-12 row-sm-5"> <gl-form-group> - <div v-if="isMarkdownFormat" class="gl-display-flex gl-justify-content-start gl-mb-3"> - <gl-segmented-control - data-testid="toggle-editing-mode-button" - data-qa-selector="editing_mode_button" - class="gl-display-flex" - :checked="editingMode" - :options="$options.switchEditingControlOptions" - :disabled="switchEditingControlDisabled" - @input="setEditingMode" - /> - </div> - <local-storage-sync - storage-key="gl-wiki-content-editor-enabled" - :value="editingMode" - @input="setEditingMode" - /> - <markdown-field - v-if="!isContentEditorActive" - :markdown-preview-path="pageInfo.markdownPreviewPath" - :can-attach-file="true" - :enable-autocomplete="true" - :textarea-value="content" + <markdown-editor + v-model="content" + :render-markdown-path="pageInfo.markdownPreviewPath" :markdown-docs-path="pageInfo.markdownHelpPath" :uploads-path="pageInfo.uploadsPath" + :enable-content-editor="isMarkdownFormat" :enable-preview="isMarkdownFormat" - class="bordered-box" - > - <template #textarea> - <textarea - id="wiki_content" - ref="textarea" - v-model="content" - name="wiki[content]" - class="note-textarea js-gfm-input js-autosize markdown-area" - dir="auto" - data-supports-quick-actions="false" - data-qa-selector="wiki_content_textarea" - :autofocus="pageInfo.persisted" - :aria-label="$options.i18n.content.label" - :placeholder="$options.i18n.content.placeholder" - @input="handleContentChange" - > - </textarea> - </template> - </markdown-field> - <div v-if="isContentEditorActive"> - <content-editor - :render-markdown="renderMarkdown" - :uploads-path="pageInfo.uploadsPath" - :markdown="content" - @initialized="trackContentEditorLoaded" - @change="handleContentEditorChange" - @loading="disableSwitchEditingControl" - @loadingSuccess="enableSwitchEditingControl" - @loadingError="enableSwitchEditingControl" - /> - <input - id="wiki_content" - v-model.trim="content" - type="hidden" - name="wiki[content]" - data-qa-selector="wiki_hidden_content" - /> - </div> - - <div class="clearfix"></div> - <div class="error-alert"></div> - + :init-on-autofocus="pageInfo.persisted" + :form-field-placeholder="$options.i18n.content.placeholder" + :form-field-aria-label="$options.i18n.content.label" + form-field-id="wiki_content" + form-field-name="wiki[content]" + @contentEditor="notifyContentEditorActive" + @markdownField="notifyContentEditorInactive" + @keydown.ctrl.enter="submitFormShortcut" + @keydown.meta.enter="submitFormShortcut" + /> <div class="form-text gl-text-gray-600"> <gl-sprintf v-if="displayWikiSpecificMarkdownHelp" @@ -447,9 +403,14 @@ export default { :disabled="disableSubmitButton" >{{ submitButtonText }}</gl-button > - <gl-button data-testid="wiki-cancel-button" :href="cancelFormPath" class="float-right">{{ - $options.i18n.cancel - }}</gl-button> + <gl-button + data-testid="wiki-cancel-button" + :href="cancelFormPath" + class="float-right" + @click="isFormDirty = false" + > + {{ $options.i18n.cancel }}</gl-button + > </div> </gl-form> </template> diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js index 9e0af426f6e..fb761725c43 100644 --- a/app/assets/javascripts/pages/users/activity_calendar.js +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -1,7 +1,7 @@ import { select } from 'd3-selection'; import $ from 'jquery'; import { last } from 'lodash'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import dateFormat from '~/lib/dateformat'; import axios from '~/lib/utils/axios_utils'; import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility'; @@ -151,7 +151,7 @@ export default class ActivityCalendar { .select(container) .append('svg') .attr('width', width) - .attr('height', 167) + .attr('height', 169) .attr('class', 'contrib-calendar'); } @@ -302,7 +302,7 @@ export default class ActivityCalendar { }); }) .catch(() => - createFlash({ + createAlert({ message: __('An error occurred while retrieving calendar activity'), }), ); |