diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 6e78dc87c02..753245147d2 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -657,6 +657,24 @@ export const secondsToMilliseconds = seconds => seconds * 1000; */ export const secondsToDays = seconds => Math.round(seconds / 86400); +/** + * Converts a numeric utc offset in seconds to +/- hours + * ie -32400 => -9 hours + * ie -12600 => -3.5 hours + * + * @param {Number} offset UTC offset in seconds as a integer + * + * @return {String} the + or - offset in hours + */ +export const secondsToHours = offset => { + const parsed = parseInt(offset, 10); + if (Number.isNaN(parsed) || parsed === 0) { + return `0`; + } + const num = offset / 3600; + return parseInt(num, 10) !== num ? num.toFixed(1) : num; +}; + /** * Returns the date n days after the date provided * diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue index f6721f5a27b..3fa8efcd145 100644 --- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue +++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue @@ -2,6 +2,7 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; import { __ } from '~/locale'; import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; +import { secondsToHours } from '~/lib/utils/datetime_utility'; export default { name: 'TimezoneDropdown', @@ -58,16 +59,8 @@ export default { isSelected(timezone) { return this.value === timezone.formattedTimezone; }, - formatUtcOffset(offset) { - const parsed = parseInt(offset, 10); - if (Number.isNaN(parsed) || parsed === 0) { - return `0`; - } - const prefix = offset > 0 ? '+' : '-'; - return `${prefix}${Math.abs(offset / 3600)}`; - }, formatTimezone(item) { - return `[UTC ${this.formatUtcOffset(item.offset)}] ${item.name}`; + return `[UTC ${secondsToHours(item.offset)}] ${item.name}`; }, }, }; diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md index 2e535707723..34c0b112333 100644 --- a/doc/api/project_repository_storage_moves.md +++ b/doc/api/project_repository_storage_moves.md @@ -9,7 +9,7 @@ type: reference > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0. -Project repositories can be moved between storages. This can be useful when +Project repositories including wiki and design repositories can be moved between storages. This can be useful when [migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster), for example. @@ -194,6 +194,14 @@ Example response: ## Schedule a repository storage move for a project +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34119) in GitLab 13.1. +> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2618) in GitLab 13.3, original repository is automatically removed after successful move and integrity check. + +CAUTION: **Caution:** +Before GitLab 13.3, a repository move worked more like a repository copy as the +original repository was not deleted from the original storage disk location and +had to be manually cleaned up. + ```plaintext POST /projects/:project_id/repository_storage_moves ``` diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb index 8e9e47d4ec9..383847e8529 100644 --- a/qa/qa/page/component/issuable/sidebar.rb +++ b/qa/qa/page/component/issuable/sidebar.rb @@ -65,7 +65,9 @@ module QA def has_assignee?(username) within_element(:assignee_block) do - has_text?(username) + wait_until(reload: false) do + has_text?(username) + end end end diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js index 7c1a4ff1085..d1219627ca7 100644 --- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js +++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js @@ -1,6 +1,7 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import { GlDropdownItem, GlDropdown } from '@gitlab/ui'; +import { secondsToHours } from '~/lib/utils/datetime_utility'; import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue'; import createStore from '~/deploy_freeze/store'; @@ -12,6 +13,11 @@ describe('Deploy freeze timezone dropdown', () => { let store; const timezoneDataFixture = getJSONFixture('/api/freeze-periods/timezone_data.json'); + const findTzByName = (identifier = '') => + timezoneDataFixture.find(({ name }) => name.toLowerCase() === identifier.toLowerCase()); + + const formatTz = ({ offset, name }) => `[UTC ${secondsToHours(offset)}] ${name}`; + const createComponent = (searchTerm, selectedTimezone) => { store = createStore({ projectId: '8', @@ -63,8 +69,9 @@ describe('Deploy freeze timezone dropdown', () => { }); it('renders only the time zone searched for', () => { + const selectedTz = findTzByName('Alaska'); expect(findAllDropdownItems()).toHaveLength(1); - expect(findDropdownItemByIndex(0).text()).toBe('[UTC -8] Alaska'); + expect(findDropdownItemByIndex(0).text()).toBe(formatTz(selectedTz)); }); it('should not display empty results message', () => { @@ -72,13 +79,15 @@ describe('Deploy freeze timezone dropdown', () => { }); describe('Custom events', () => { + const selectedTz = findTzByName('Alaska'); + it('should emit input if a time zone is clicked', () => { findDropdownItemByIndex(0).vm.$emit('click'); expect(wrapper.emitted('input')).toEqual([ [ { - formattedTimezone: '[UTC -8] Alaska', - identifier: 'America/Juneau', + formattedTimezone: formatTz(selectedTz), + identifier: selectedTz.identifier, }, ], ]);