diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-30 14:02:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-30 14:02:35 +0300 |
commit | 434a0ce52d75e13d48eac9ce83774954c7c5d48d (patch) | |
tree | de3b7a7cf1ce8b07555f28df592297c76894c90f /app/assets/javascripts/registry | |
parent | 0a0d9493ca481c56b739a3df27c31262283150fe (diff) |
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc2
Diffstat (limited to 'app/assets/javascripts/registry')
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', {}); |