Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-20 18:09:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-20 18:09:16 +0300
commit8738992b79824278b090f08e16945affc923ff6f (patch)
tree5581bd02d1d860f023f6d4e8fae743ccc9757d43 /app/assets/javascripts/registry
parentaa874f42425bf3b8fdb4d86de591a06f719ecb7e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/registry')
-rw-r--r--app/assets/javascripts/registry/explorer/pages/index.vue4
-rw-r--r--app/assets/javascripts/registry/settings/components/expiration_dropdown.vue50
-rw-r--r--app/assets/javascripts/registry/settings/components/expiration_run_text.vue31
-rw-r--r--app/assets/javascripts/registry/settings/components/expiration_textarea.vue109
-rw-r--r--app/assets/javascripts/registry/settings/components/expiration_toggle.vue55
-rw-r--r--app/assets/javascripts/registry/settings/constants.js45
-rw-r--r--app/assets/javascripts/registry/settings/graphql/fragments/container_expiration_policy.fragment.graphql1
-rw-r--r--app/assets/javascripts/registry/settings/registry_settings_bundle.js13
8 files changed, 300 insertions, 8 deletions
diff --git a/app/assets/javascripts/registry/explorer/pages/index.vue b/app/assets/javascripts/registry/explorer/pages/index.vue
index 4ac0bca84c1..dca63e1a569 100644
--- a/app/assets/javascripts/registry/explorer/pages/index.vue
+++ b/app/assets/javascripts/registry/explorer/pages/index.vue
@@ -1,7 +1,3 @@
-<script>
-export default {};
-</script>
-
<template>
<div>
<router-view ref="router-view" />
diff --git a/app/assets/javascripts/registry/settings/components/expiration_dropdown.vue b/app/assets/javascripts/registry/settings/components/expiration_dropdown.vue
new file mode 100644
index 00000000000..d75fb31fd98
--- /dev/null
+++ b/app/assets/javascripts/registry/settings/components/expiration_dropdown.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlFormGroup, GlFormSelect } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlFormSelect,
+ },
+ props: {
+ formOptions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ label: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group :id="`${name}-form-group`" :label-for="name" :label="label">
+ <gl-form-select :id="name" :value="value" :disabled="disabled" @input="$emit('input', $event)">
+ <option
+ v-for="option in formOptions"
+ :key="option.key"
+ :value="option.key"
+ data-testid="option"
+ >
+ {{ option.label }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/registry/settings/components/expiration_run_text.vue b/app/assets/javascripts/registry/settings/components/expiration_run_text.vue
new file mode 100644
index 00000000000..186ad2f34b9
--- /dev/null
+++ b/app/assets/javascripts/registry/settings/components/expiration_run_text.vue
@@ -0,0 +1,31 @@
+<script>
+import { GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { NEXT_CLEANUP_LABEL, NOT_SCHEDULED_POLICY_TEXT } from '~/registry/settings/constants';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlFormInput,
+ },
+ props: {
+ value: {
+ type: String,
+ required: false,
+ default: NOT_SCHEDULED_POLICY_TEXT,
+ },
+ },
+ i18n: {
+ NEXT_CLEANUP_LABEL,
+ },
+};
+</script>
+
+<template>
+ <gl-form-group
+ id="expiration-policy-info-text-group"
+ :label="$options.i18n.NEXT_CLEANUP_LABEL"
+ label-for="expiration-policy-info-text"
+ >
+ <gl-form-input id="expiration-policy-info-text" class="gl-pl-0!" plaintext :value="value" />
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/registry/settings/components/expiration_textarea.vue b/app/assets/javascripts/registry/settings/components/expiration_textarea.vue
new file mode 100644
index 00000000000..1e1194ebb5c
--- /dev/null
+++ b/app/assets/javascripts/registry/settings/components/expiration_textarea.vue
@@ -0,0 +1,109 @@
+<script>
+import { GlFormGroup, GlFormTextarea, GlSprintf, GlLink } from '@gitlab/ui';
+import { NAME_REGEX_LENGTH, TEXT_AREA_INVALID_FEEDBACK } from '../constants';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlFormTextarea,
+ GlSprintf,
+ GlLink,
+ },
+ inject: ['tagsRegexHelpPagePath'],
+ props: {
+ error: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ name: {
+ type: String,
+ required: true,
+ },
+ label: {
+ type: String,
+ required: true,
+ },
+ placeholder: {
+ type: String,
+ required: true,
+ },
+ description: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ textAreaLengthErrorMessage() {
+ return this.isInputValid(this.value) ? '' : TEXT_AREA_INVALID_FEEDBACK;
+ },
+ textAreaValidation() {
+ const nameRegexErrors = this.error || this.textAreaLengthErrorMessage;
+ return {
+ state: nameRegexErrors === null ? null : !nameRegexErrors,
+ message: nameRegexErrors,
+ };
+ },
+ internalValue: {
+ get() {
+ return this.value;
+ },
+ set(value) {
+ this.$emit('input', value);
+ this.$emit('validation', this.isInputValid(value));
+ },
+ },
+ },
+ methods: {
+ isInputValid(value) {
+ return !value || value.length <= NAME_REGEX_LENGTH;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group
+ :id="`${name}-form-group`"
+ :label-for="name"
+ :state="textAreaValidation.state"
+ :invalid-feedback="textAreaValidation.message"
+ >
+ <template #label>
+ <span data-testid="label">
+ <gl-sprintf :message="label">
+ <template #italic="{content}">
+ <i>{{ content }}</i>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ <gl-form-textarea
+ :id="name"
+ v-model="internalValue"
+ :placeholder="placeholder"
+ :state="textAreaValidation.state"
+ :disabled="disabled"
+ trim
+ />
+ <template #description>
+ <span data-testid="description" class="gl-text-gray-400">
+ <gl-sprintf :message="description">
+ <template #link="{content}">
+ <gl-link :href="tagsRegexHelpPagePath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/registry/settings/components/expiration_toggle.vue b/app/assets/javascripts/registry/settings/components/expiration_toggle.vue
new file mode 100644
index 00000000000..9dabe8ac51a
--- /dev/null
+++ b/app/assets/javascripts/registry/settings/components/expiration_toggle.vue
@@ -0,0 +1,55 @@
+<script>
+import { GlFormGroup, GlToggle, GlSprintf } from '@gitlab/ui';
+import { ENABLED_TEXT, DISABLED_TEXT, ENABLE_TOGGLE_DESCRIPTION } from '../constants';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlToggle,
+ GlSprintf,
+ },
+ props: {
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ value: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ i18n: {
+ ENABLE_TOGGLE_DESCRIPTION,
+ },
+ computed: {
+ enabled: {
+ get() {
+ return this.value;
+ },
+ set(value) {
+ this.$emit('input', value);
+ },
+ },
+ toggleStatusText() {
+ return this.enabled ? ENABLED_TEXT : DISABLED_TEXT;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group id="expiration-policy-toggle-group" label-for="expiration-policy-toggle">
+ <div class="gl-display-flex">
+ <gl-toggle id="expiration-policy-toggle" v-model="enabled" :disabled="disabled" />
+ <span class="gl-ml-5 gl-line-height-24" data-testid="description">
+ <gl-sprintf :message="$options.i18n.ENABLE_TOGGLE_DESCRIPTION">
+ <template #toggleStatus>
+ <strong>{{ toggleStatusText }}</strong>
+ </template>
+ </gl-sprintf>
+ </span>
+ </div>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/registry/settings/constants.js b/app/assets/javascripts/registry/settings/constants.js
index e790658f491..bc3ec3104ad 100644
--- a/app/assets/javascripts/registry/settings/constants.js
+++ b/app/assets/javascripts/registry/settings/constants.js
@@ -1,6 +1,6 @@
import { s__, __ } from '~/locale';
-export const SET_CLEANUP_POLICY_BUTTON = s__('ContainerRegistry|Set cleanup policy');
+export const SET_CLEANUP_POLICY_BUTTON = __('Save');
export const CLEANUP_POLICY_CARD_HEADER = s__('ContainerRegistry|Tag expiration policy');
export const UNAVAILABLE_FEATURE_TITLE = s__(
`ContainerRegistry|Cleanup policy for tags is disabled`,
@@ -12,3 +12,46 @@ export const UNAVAILABLE_USER_FEATURE_TEXT = __(`Please contact your administrat
export const UNAVAILABLE_ADMIN_FEATURE_TEXT = s__(
`ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature.`,
);
+
+export const TEXT_AREA_INVALID_FEEDBACK = s__(
+ 'ContainerRegistry|The value of this input should be less than 256 characters',
+);
+
+export const KEEP_HEADER_TEXT = s__('ContainerRegistry|Keep these tags');
+export const KEEP_INFO_TEXT = s__(
+ 'ContainerRegistry|Tags that match these rules will always be %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag will always be kept.',
+);
+export const KEEP_N_LABEL = s__('ContainerRegistry|Keep the most recent:');
+export const NAME_REGEX_KEEP_LABEL = s__('ContainerRegistry|Keep tags matching:');
+export const NAME_REGEX_KEEP_PLACEHOLDER = 'production-v.*';
+export const NAME_REGEX_KEEP_DESCRIPTION = s__(
+ 'ContainerRegistry|Tags with names matching this regex pattern will be kept. %{linkStart}More information%{linkEnd}',
+);
+
+export const REMOVE_HEADER_TEXT = s__('ContainerRegistry|Remove these tags');
+export const REMOVE_INFO_TEXT = s__(
+ 'ContainerRegistry|Tags that match these rules will be %{strongStart}removed%{strongEnd}, unless kept by a rule above.',
+);
+export const EXPIRATION_SCHEDULE_LABEL = s__('ContainerRegistry|Remove tags older than:');
+export const NAME_REGEX_LABEL = s__('ContainerRegistry|Remove tags matching:');
+export const NAME_REGEX_PLACEHOLDER = '.*';
+export const NAME_REGEX_DESCRIPTION = s__(
+ 'ContainerRegistry|Tags with names matching this regex pattern will be removed. %{linkStart}More information%{linkEnd}',
+);
+
+export const ENABLED_TEXT = __('Enabled');
+export const DISABLED_TEXT = __('Disabled');
+
+export const ENABLE_TOGGLE_DESCRIPTION = s__(
+ 'ContainerRegistry|%{toggleStatus} - Tags matching the rules defined below will be automatically scheduled for deletion.',
+);
+
+export const CADENCE_LABEL = s__('ContainerRegistry|Run cleanup every:');
+
+export const NEXT_CLEANUP_LABEL = s__('ContainerRegistry|Next cleanup scheduled to run on:');
+export const NOT_SCHEDULED_POLICY_TEXT = s__('ContainerRegistry|Not yet scheduled');
+export const EXPIRATION_POLICY_FOOTER_NOTE = s__(
+ 'ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time',
+);
+
+export const NAME_REGEX_LENGTH = 255;
diff --git a/app/assets/javascripts/registry/settings/graphql/fragments/container_expiration_policy.fragment.graphql b/app/assets/javascripts/registry/settings/graphql/fragments/container_expiration_policy.fragment.graphql
index 224e0ed9472..1d6c89133af 100644
--- a/app/assets/javascripts/registry/settings/graphql/fragments/container_expiration_policy.fragment.graphql
+++ b/app/assets/javascripts/registry/settings/graphql/fragments/container_expiration_policy.fragment.graphql
@@ -5,4 +5,5 @@ fragment ContainerExpirationPolicyFields on ContainerExpirationPolicy {
nameRegex
nameRegexKeep
olderThan
+ nextRunAt
}
diff --git a/app/assets/javascripts/registry/settings/registry_settings_bundle.js b/app/assets/javascripts/registry/settings/registry_settings_bundle.js
index f7b1c5abd3a..6a4584b1b28 100644
--- a/app/assets/javascripts/registry/settings/registry_settings_bundle.js
+++ b/app/assets/javascripts/registry/settings/registry_settings_bundle.js
@@ -13,7 +13,13 @@ export default () => {
if (!el) {
return null;
}
- const { projectPath, isAdmin, adminSettingsPath, enableHistoricEntries } = el.dataset;
+ const {
+ isAdmin,
+ enableHistoricEntries,
+ projectPath,
+ adminSettingsPath,
+ tagsRegexHelpPagePath,
+ } = el.dataset;
return new Vue({
el,
apolloProvider,
@@ -21,10 +27,11 @@ export default () => {
RegistrySettingsApp,
},
provide: {
- projectPath,
isAdmin: parseBoolean(isAdmin),
- adminSettingsPath,
enableHistoricEntries: parseBoolean(enableHistoricEntries),
+ projectPath,
+ adminSettingsPath,
+ tagsRegexHelpPagePath,
},
render(createElement) {
return createElement('registry-settings-app', {});