2021-02-22 17:27:13 +05:30
|
|
|
<script>
|
2021-04-17 20:07:23 +05:30
|
|
|
import {
|
|
|
|
GlButton,
|
|
|
|
GlDropdownDivider,
|
|
|
|
GlDropdownItem,
|
|
|
|
GlDropdownSectionHeader,
|
|
|
|
GlIcon,
|
|
|
|
GlLink,
|
|
|
|
GlFormInput,
|
|
|
|
} from '@gitlab/ui';
|
2021-02-22 17:27:13 +05:30
|
|
|
import { joinPaths } from '~/lib/utils/url_utility';
|
2021-06-08 01:23:25 +05:30
|
|
|
import { s__ } from '~/locale';
|
2021-09-30 23:02:18 +05:30
|
|
|
import ImportGroupDropdown from '../../components/group_dropdown.vue';
|
2021-02-22 17:27:13 +05:30
|
|
|
import ImportStatus from '../../components/import_status.vue';
|
|
|
|
import { STATUSES } from '../../constants';
|
2021-06-08 01:23:25 +05:30
|
|
|
import addValidationErrorMutation from '../graphql/mutations/add_validation_error.mutation.graphql';
|
|
|
|
import removeValidationErrorMutation from '../graphql/mutations/remove_validation_error.mutation.graphql';
|
2021-09-04 01:27:46 +05:30
|
|
|
import groupAndProjectQuery from '../graphql/queries/groupAndProject.query.graphql';
|
2021-04-17 20:07:23 +05:30
|
|
|
|
|
|
|
const DEBOUNCE_INTERVAL = 300;
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
export default {
|
|
|
|
components: {
|
|
|
|
ImportStatus,
|
2021-09-30 23:02:18 +05:30
|
|
|
ImportGroupDropdown,
|
2021-02-22 17:27:13 +05:30
|
|
|
GlButton,
|
2021-04-17 20:07:23 +05:30
|
|
|
GlDropdownDivider,
|
|
|
|
GlDropdownItem,
|
|
|
|
GlDropdownSectionHeader,
|
2021-02-22 17:27:13 +05:30
|
|
|
GlLink,
|
|
|
|
GlIcon,
|
|
|
|
GlFormInput,
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
group: {
|
|
|
|
type: Object,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
availableNamespaces: {
|
|
|
|
type: Array,
|
|
|
|
required: true,
|
|
|
|
},
|
2021-04-17 20:07:23 +05:30
|
|
|
groupPathRegex: {
|
|
|
|
type: RegExp,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
apollo: {
|
2021-09-04 01:27:46 +05:30
|
|
|
existingGroupAndProject: {
|
|
|
|
query: groupAndProjectQuery,
|
2021-04-17 20:07:23 +05:30
|
|
|
debounce: DEBOUNCE_INTERVAL,
|
|
|
|
variables() {
|
|
|
|
return {
|
|
|
|
fullPath: this.fullPath,
|
|
|
|
};
|
|
|
|
},
|
2021-09-04 01:27:46 +05:30
|
|
|
update({ existingGroup, existingProject }) {
|
2021-06-08 01:23:25 +05:30
|
|
|
const variables = {
|
|
|
|
field: 'new_name',
|
|
|
|
sourceGroupId: this.group.id,
|
|
|
|
};
|
|
|
|
|
2021-09-04 01:27:46 +05:30
|
|
|
if (!existingGroup && !existingProject) {
|
2021-06-08 01:23:25 +05:30
|
|
|
this.$apollo.mutate({
|
|
|
|
mutation: removeValidationErrorMutation,
|
|
|
|
variables,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.$apollo.mutate({
|
|
|
|
mutation: addValidationErrorMutation,
|
|
|
|
variables: {
|
|
|
|
...variables,
|
2021-09-04 01:27:46 +05:30
|
|
|
message: this.$options.i18n.NAME_ALREADY_EXISTS,
|
2021-06-08 01:23:25 +05:30
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2021-04-17 20:07:23 +05:30
|
|
|
skip() {
|
|
|
|
return !this.isNameValid || this.isAlreadyImported;
|
|
|
|
},
|
|
|
|
},
|
2021-02-22 17:27:13 +05:30
|
|
|
},
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2021-02-22 17:27:13 +05:30
|
|
|
computed: {
|
2021-09-30 23:02:18 +05:30
|
|
|
availableNamespaceNames() {
|
|
|
|
return this.availableNamespaces.map((ns) => ns.full_path);
|
|
|
|
},
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
importTarget() {
|
|
|
|
return this.group.import_target;
|
|
|
|
},
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
invalidNameValidationMessage() {
|
|
|
|
return this.group.validation_errors.find(({ field }) => field === 'new_name')?.message;
|
|
|
|
},
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
isInvalid() {
|
2021-06-08 01:23:25 +05:30
|
|
|
return Boolean(!this.isNameValid || this.invalidNameValidationMessage);
|
2021-04-17 20:07:23 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
isNameValid() {
|
|
|
|
return this.groupPathRegex.test(this.importTarget.new_name);
|
|
|
|
},
|
|
|
|
|
|
|
|
isAlreadyImported() {
|
2021-06-08 01:23:25 +05:30
|
|
|
return this.group.progress.status !== STATUSES.NONE;
|
2021-02-22 17:27:13 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
isFinished() {
|
2021-06-08 01:23:25 +05:30
|
|
|
return this.group.progress.status === STATUSES.FINISHED;
|
2021-02-22 17:27:13 +05:30
|
|
|
},
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
fullPath() {
|
|
|
|
return `${this.importTarget.target_namespace}/${this.importTarget.new_name}`;
|
2021-02-22 17:27:13 +05:30
|
|
|
},
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
absolutePath() {
|
|
|
|
return joinPaths(gon.relative_url_root || '/', this.fullPath);
|
2021-02-22 17:27:13 +05:30
|
|
|
},
|
|
|
|
},
|
2021-09-04 01:27:46 +05:30
|
|
|
|
|
|
|
i18n: {
|
|
|
|
NAME_ALREADY_EXISTS: s__('BulkImport|Name already exists.'),
|
|
|
|
},
|
2021-02-22 17:27:13 +05:30
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2021-06-08 01:23:25 +05:30
|
|
|
<tr
|
|
|
|
class="gl-border-gray-200 gl-border-0 gl-border-b-1 gl-border-solid"
|
|
|
|
data-qa-selector="import_item"
|
|
|
|
:data-qa-source-group="group.full_path"
|
|
|
|
>
|
2021-02-22 17:27:13 +05:30
|
|
|
<td class="gl-p-4">
|
2021-04-17 20:07:23 +05:30
|
|
|
<gl-link
|
|
|
|
:href="group.web_url"
|
|
|
|
target="_blank"
|
|
|
|
class="gl-display-flex gl-align-items-center gl-h-7"
|
|
|
|
>
|
2021-02-22 17:27:13 +05:30
|
|
|
{{ group.full_path }} <gl-icon name="external-link" />
|
|
|
|
</gl-link>
|
|
|
|
</td>
|
|
|
|
<td class="gl-p-4">
|
2021-04-17 20:07:23 +05:30
|
|
|
<gl-link
|
|
|
|
v-if="isFinished"
|
|
|
|
class="gl-display-flex gl-align-items-center gl-h-7"
|
|
|
|
:href="absolutePath"
|
|
|
|
>
|
|
|
|
{{ fullPath }}
|
|
|
|
</gl-link>
|
2021-02-22 17:27:13 +05:30
|
|
|
|
|
|
|
<div
|
|
|
|
v-else
|
|
|
|
class="import-entities-target-select gl-display-flex gl-align-items-stretch"
|
|
|
|
:class="{
|
2021-04-17 20:07:23 +05:30
|
|
|
disabled: isAlreadyImported,
|
2021-02-22 17:27:13 +05:30
|
|
|
}"
|
|
|
|
>
|
2021-09-30 23:02:18 +05:30
|
|
|
<import-group-dropdown
|
|
|
|
#default="{ namespaces }"
|
2021-04-17 20:07:23 +05:30
|
|
|
:text="importTarget.target_namespace"
|
|
|
|
:disabled="isAlreadyImported"
|
2021-09-30 23:02:18 +05:30
|
|
|
:namespaces="availableNamespaceNames"
|
2021-04-17 20:07:23 +05:30
|
|
|
toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
|
2021-09-04 01:27:46 +05:30
|
|
|
class="import-entities-namespace-dropdown gl-h-7 gl-flex-grow-1"
|
2021-06-08 01:23:25 +05:30
|
|
|
data-qa-selector="target_namespace_selector_dropdown"
|
2021-04-17 20:07:23 +05:30
|
|
|
>
|
|
|
|
<gl-dropdown-item @click="$emit('update-target-namespace', '')">{{
|
|
|
|
s__('BulkImport|No parent')
|
|
|
|
}}</gl-dropdown-item>
|
2021-09-30 23:02:18 +05:30
|
|
|
<template v-if="namespaces.length">
|
2021-04-17 20:07:23 +05:30
|
|
|
<gl-dropdown-divider />
|
|
|
|
<gl-dropdown-section-header>
|
|
|
|
{{ s__('BulkImport|Existing groups') }}
|
|
|
|
</gl-dropdown-section-header>
|
|
|
|
<gl-dropdown-item
|
2021-09-30 23:02:18 +05:30
|
|
|
v-for="ns in namespaces"
|
|
|
|
:key="ns"
|
2021-06-08 01:23:25 +05:30
|
|
|
data-qa-selector="target_group_dropdown_item"
|
2021-09-30 23:02:18 +05:30
|
|
|
:data-qa-group-name="ns"
|
|
|
|
@click="$emit('update-target-namespace', ns)"
|
2021-04-17 20:07:23 +05:30
|
|
|
>
|
2021-09-30 23:02:18 +05:30
|
|
|
{{ ns }}
|
2021-04-17 20:07:23 +05:30
|
|
|
</gl-dropdown-item>
|
|
|
|
</template>
|
2021-09-30 23:02:18 +05:30
|
|
|
</import-group-dropdown>
|
2021-02-22 17:27:13 +05:30
|
|
|
<div
|
2021-04-17 20:07:23 +05:30
|
|
|
class="import-entities-target-select-separator gl-h-7 gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1"
|
2021-02-22 17:27:13 +05:30
|
|
|
>
|
|
|
|
/
|
|
|
|
</div>
|
2021-09-04 01:27:46 +05:30
|
|
|
<div class="gl-flex-grow-1">
|
2021-04-17 20:07:23 +05:30
|
|
|
<gl-form-input
|
|
|
|
class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
|
|
|
|
:class="{ 'is-invalid': isInvalid && !isAlreadyImported }"
|
|
|
|
:disabled="isAlreadyImported"
|
|
|
|
:value="importTarget.new_name"
|
|
|
|
@input="$emit('update-new-name', $event)"
|
|
|
|
/>
|
|
|
|
<p v-if="isInvalid" class="gl-text-red-500 gl-m-0 gl-mt-2">
|
|
|
|
<template v-if="!isNameValid">
|
|
|
|
{{ __('Please choose a group URL with no special characters.') }}
|
|
|
|
</template>
|
2021-06-08 01:23:25 +05:30
|
|
|
<template v-else-if="invalidNameValidationMessage">
|
|
|
|
{{ invalidNameValidationMessage }}
|
2021-04-17 20:07:23 +05:30
|
|
|
</template>
|
|
|
|
</p>
|
|
|
|
</div>
|
2021-02-22 17:27:13 +05:30
|
|
|
</div>
|
|
|
|
</td>
|
2021-06-08 01:23:25 +05:30
|
|
|
<td class="gl-p-4 gl-white-space-nowrap" data-qa-selector="import_status_indicator">
|
|
|
|
<import-status :status="group.progress.status" class="gl-mt-2" />
|
2021-02-22 17:27:13 +05:30
|
|
|
</td>
|
|
|
|
<td class="gl-p-4">
|
|
|
|
<gl-button
|
2021-04-17 20:07:23 +05:30
|
|
|
v-if="!isAlreadyImported"
|
|
|
|
:disabled="isInvalid"
|
2021-06-08 01:23:25 +05:30
|
|
|
variant="confirm"
|
2021-02-22 17:27:13 +05:30
|
|
|
category="secondary"
|
2021-06-08 01:23:25 +05:30
|
|
|
data-qa-selector="import_group_button"
|
2021-02-22 17:27:13 +05:30
|
|
|
@click="$emit('import-group')"
|
|
|
|
>{{ __('Import') }}</gl-button
|
|
|
|
>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</template>
|