diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-15 15:10:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-15 15:10:11 +0300 |
commit | 96acc69fae1ee7d559ba7eaa4e8304c8261525e3 (patch) | |
tree | b1ed433da35a415cab8ed544d85ac4c939efab0e /app | |
parent | a1498861799d1695682d72870580a6c3fb5ca3cf (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
54 files changed, 304 insertions, 517 deletions
diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue index bc1e401d373..77ec1f1af47 100644 --- a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue +++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue @@ -93,7 +93,7 @@ export default { placement="top" class="trigger-description gl-display-flex" > - <div class="gl-flex-fill-1 gl-text-truncate">{{ item.description }}</div> + <div class="gl-flex-grow-1 gl-text-truncate">{{ item.description }}</div> </tooltip-on-truncate> </template> <template #cell(owner)="{ item }"> diff --git a/app/assets/javascripts/emoji/components/picker.vue b/app/assets/javascripts/emoji/components/picker.vue index 78ba2aabcf8..dc3eac0cd0c 100644 --- a/app/assets/javascripts/emoji/components/picker.vue +++ b/app/assets/javascripts/emoji/components/picker.vue @@ -111,7 +111,7 @@ export default { 'gl-text-body! emoji-picker-category-active': index === currentCategory, }" type="button" - class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-fill-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab" + class="gl-border-0 gl-border-b-2 gl-border-b-solid gl-flex-grow-1 gl-text-gray-300 gl-pt-3 gl-pb-3 gl-bg-transparent emoji-picker-category-tab" :aria-label="category.name" @click="scrollToCategory(category.name)" > diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue index 8911380290a..542b8c9219d 100644 --- a/app/assets/javascripts/environments/components/environment_actions.vue +++ b/app/assets/javascripts/environments/components/environment_actions.vue @@ -89,7 +89,7 @@ export default { data-testid="manual-action-link" @click="onClickAction(action)" > - <span class="gl-flex-fill-1">{{ action.name }}</span> + <span class="gl-flex-grow-1">{{ action.name }}</span> <span v-if="action.scheduledAt" class="gl-text-gray-500 float-right"> <gl-icon name="clock" /> {{ remainingTime(action) }} diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index 602639f09a6..8bd71db957c 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -121,7 +121,7 @@ export default { variant="info" category="secondary" type="button" - class="gl-mb-3 gl-flex-fill-1" + class="gl-mb-3 gl-flex-grow-1" >{{ $options.i18n.reviewAppButtonLabel }}</gl-button > <gl-button diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue index 828a7098b36..7a9233048a9 100644 --- a/app/assets/javascripts/environments/components/stop_environment_modal.vue +++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue @@ -58,7 +58,7 @@ export default { <span v-gl-tooltip :title="environment.name" - class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-fill" + class="gl-text-truncate gl-ml-2 gl-mr-2 gl-flex-grow-1" > {{ environment.name }}? </span> diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue index 0f564fc3c60..2e27f51b71f 100644 --- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue +++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue @@ -260,7 +260,7 @@ export default { </template> <div v-else class="px-3">{{ __("You don't have any recent searches") }}</div> </gl-dropdown> - <div class="filtered-search-input-container gl-flex-fill-1"> + <div class="filtered-search-input-container gl-flex-grow-1"> <gl-form-input v-model="errorSearchQuery" class="pl-2 filtered-search" diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue index e86c418f216..63c18f4d78e 100644 --- a/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue +++ b/app/assets/javascripts/import_entities/import_groups/components/import_table_row.vue @@ -157,7 +157,7 @@ export default { :text="importTarget.target_namespace" :disabled="isAlreadyImported" toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!" - class="import-entities-namespace-dropdown gl-h-7 gl-flex-fill-1" + class="import-entities-namespace-dropdown gl-h-7 gl-flex-grow-1" data-qa-selector="target_namespace_selector_dropdown" > <gl-dropdown-item @click="$emit('update-target-namespace', '')">{{ @@ -184,7 +184,7 @@ export default { > / </div> - <div class="gl-flex-fill-1"> + <div class="gl-flex-grow-1"> <gl-form-input class="gl-rounded-top-left-none gl-rounded-bottom-left-none" :class="{ 'is-invalid': isInvalid && !isAlreadyImported }" diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue index dfe158ae2b0..977d03e62be 100644 --- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue +++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue @@ -36,7 +36,7 @@ export default { <template> <div class="top-area"> <gl-tabs - class="gl-display-flex gl-flex-fill-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters" + class="gl-display-flex gl-flex-grow-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters" nav-class="gl-border-b-0" > <gl-tab diff --git a/app/assets/javascripts/packages/details/components/package_files.vue b/app/assets/javascripts/packages/details/components/package_files.vue index 3c71ac5137e..0563b612d04 100644 --- a/app/assets/javascripts/packages/details/components/package_files.vue +++ b/app/assets/javascripts/packages/details/components/package_files.vue @@ -148,7 +148,7 @@ export default { <template #row-details="{ item }"> <div - class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100" + class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100" > <file-sha v-if="item.file_sha256" diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue index c110c1d4d62..9fb8be3fdb9 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue @@ -91,7 +91,7 @@ export default { label-position="hidden" @change="toggleFeature" /> - <div class="select-wrapper gl-flex-fill-1"> + <div class="select-wrapper gl-flex-grow-1"> <select :disabled="displaySelectInput" class="form-control project-repo-select select-control" 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 0b7b4c0ded1..11e6b4577e0 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 @@ -381,7 +381,7 @@ export default { :label="s__('ProjectSettings|Project visibility')" > <div class="project-feature-controls gl-display-flex gl-align-items-center gl-my-3 gl-mx-0"> - <div class="select-wrapper gl-flex-fill-1"> + <div class="select-wrapper gl-flex-grow-1"> <select v-model="visibilityLevel" :disabled="!canChangeVisibilityLevel" diff --git a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue index dabfb623f43..736c8668a34 100644 --- a/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue +++ b/app/assets/javascripts/reports/codequality_report/components/codequality_issue_body.vue @@ -61,7 +61,7 @@ export default { <span :class="severityClass" class="gl-mr-5" data-testid="codequality-severity-icon"> <gl-icon v-tooltip="severityLabel" :name="severityIcon" :size="12" /> </span> - <div class="gl-flex-fill-1"> + <div class="gl-flex-grow-1"> <div> <strong v-if="isStatusSuccess">{{ s__('ciReport|Fixed:') }}</strong> {{ issueName }} diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js index d47efc85eff..a57d18ba745 100644 --- a/app/assets/javascripts/runner/constants.js +++ b/app/assets/javascripts/runner/constants.js @@ -10,6 +10,7 @@ export const RUNNER_ENTITY_TYPE = 'Ci::Runner'; // - Used for URL params names // - GlFilteredSearch tokens type +export const PARAM_KEY_SEARCH = 'search'; export const PARAM_KEY_STATUS = 'status'; export const PARAM_KEY_RUNNER_TYPE = 'runner_type'; export const PARAM_KEY_SORT = 'sort'; diff --git a/app/assets/javascripts/runner/graphql/get_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_runners.query.graphql index 84b7e2547f5..45df9c625a6 100644 --- a/app/assets/javascripts/runner/graphql/get_runners.query.graphql +++ b/app/assets/javascripts/runner/graphql/get_runners.query.graphql @@ -6,6 +6,7 @@ query getRunners( $after: String $first: Int $last: Int + $search: String $status: CiRunnerStatus $type: CiRunnerType $sort: CiRunnerSort @@ -15,6 +16,7 @@ query getRunners( after: $after first: $first last: $last + search: $search status: $status type: $type sort: $sort diff --git a/app/assets/javascripts/runner/runner_list/runner_list_app.vue b/app/assets/javascripts/runner/runner_list/runner_list_app.vue index d53774709ba..b4eacb911a2 100644 --- a/app/assets/javascripts/runner/runner_list/runner_list_app.vue +++ b/app/assets/javascripts/runner/runner_list/runner_list_app.vue @@ -12,7 +12,7 @@ import { fromUrlQueryToSearch, fromSearchToUrl, fromSearchToVariables, -} from './filtered_search_utils'; +} from './runner_search_utils'; export default { components: { diff --git a/app/assets/javascripts/runner/runner_list/filtered_search_utils.js b/app/assets/javascripts/runner/runner_list/runner_search_utils.js index 2303dd587e1..e45972b81db 100644 --- a/app/assets/javascripts/runner/runner_list/filtered_search_utils.js +++ b/app/assets/javascripts/runner/runner_list/runner_search_utils.js @@ -1,5 +1,12 @@ import { queryToObject, setUrlParams } from '~/lib/utils/url_utility'; import { + filterToQueryObject, + processFilters, + urlQueryToFilter, + prepareTokens, +} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils'; +import { + PARAM_KEY_SEARCH, PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE, PARAM_KEY_SORT, @@ -10,30 +17,6 @@ import { RUNNER_PAGE_SIZE, } from '../constants'; -const getValuesFromFilters = (paramKey, filters) => { - return filters - .filter(({ type, value }) => type === paramKey && value.operator === '=') - .map(({ value }) => value.data); -}; - -const getFilterFromParams = (paramKey, params) => { - const value = params[paramKey]; - if (!value) { - return []; - } - - const values = Array.isArray(value) ? value : [value]; - return values.map((data) => { - return { - type: paramKey, - value: { - data, - operator: '=', - }, - }; - }); -}; - const getPaginationFromParams = (params) => { const page = parseInt(params[PARAM_KEY_PAGE], 10); const after = params[PARAM_KEY_AFTER]; @@ -55,10 +38,13 @@ export const fromUrlQueryToSearch = (query = window.location.search) => { const params = queryToObject(query, { gatherArrays: true }); return { - filters: [ - ...getFilterFromParams(PARAM_KEY_STATUS, params), - ...getFilterFromParams(PARAM_KEY_RUNNER_TYPE, params), - ], + filters: prepareTokens( + urlQueryToFilter(query, { + filterNamesAllowList: [PARAM_KEY_STATUS, PARAM_KEY_RUNNER_TYPE], + filteredSearchTermKey: PARAM_KEY_SEARCH, + legacySpacesDecode: false, + }), + ), sort: params[PARAM_KEY_SORT] || DEFAULT_SORT, pagination: getPaginationFromParams(params), }; @@ -68,37 +54,44 @@ export const fromSearchToUrl = ( { filters = [], sort = null, pagination = {} }, url = window.location.href, ) => { - const urlParams = { - [PARAM_KEY_STATUS]: getValuesFromFilters(PARAM_KEY_STATUS, filters), - [PARAM_KEY_RUNNER_TYPE]: getValuesFromFilters(PARAM_KEY_RUNNER_TYPE, filters), + const filterParams = { + // Defaults + [PARAM_KEY_SEARCH]: null, + [PARAM_KEY_STATUS]: [], + [PARAM_KEY_RUNNER_TYPE]: [], + // Current filters + ...filterToQueryObject(processFilters(filters), { + filteredSearchTermKey: PARAM_KEY_SEARCH, + }), }; - if (sort && sort !== DEFAULT_SORT) { - urlParams[PARAM_KEY_SORT] = sort; - } - - // Remove pagination params for first page - if (pagination?.page === 1) { - urlParams[PARAM_KEY_PAGE] = null; - urlParams[PARAM_KEY_BEFORE] = null; - urlParams[PARAM_KEY_AFTER] = null; - } else { - urlParams[PARAM_KEY_PAGE] = pagination.page; - urlParams[PARAM_KEY_BEFORE] = pagination.before; - urlParams[PARAM_KEY_AFTER] = pagination.after; - } + const isDefaultSort = sort !== DEFAULT_SORT; + const isFirstPage = pagination?.page === 1; + const otherParams = { + // Sorting & Pagination + [PARAM_KEY_SORT]: isDefaultSort ? sort : null, + [PARAM_KEY_PAGE]: isFirstPage ? null : pagination.page, + [PARAM_KEY_BEFORE]: isFirstPage ? null : pagination.before, + [PARAM_KEY_AFTER]: isFirstPage ? null : pagination.after, + }; - return setUrlParams(urlParams, url, false, true, true); + return setUrlParams({ ...filterParams, ...otherParams }, url, false, true, true); }; export const fromSearchToVariables = ({ filters = [], sort = null, pagination = {} } = {}) => { const variables = {}; + const queryObj = filterToQueryObject(processFilters(filters), { + filteredSearchTermKey: PARAM_KEY_SEARCH, + }); + + variables.search = queryObj[PARAM_KEY_SEARCH]; + // TODO Get more than one value when GraphQL API supports OR for "status" - [variables.status] = getValuesFromFilters(PARAM_KEY_STATUS, filters); + [variables.status] = queryObj[PARAM_KEY_STATUS] || []; // TODO Get more than one value when GraphQL API supports OR for "runner type" - [variables.type] = getValuesFromFilters(PARAM_KEY_RUNNER_TYPE, filters); + [variables.type] = queryObj[PARAM_KEY_RUNNER_TYPE] || []; if (sort) { variables.sort = sort; diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue index 2439ab55923..a490adbc11a 100644 --- a/app/assets/javascripts/search/topbar/components/app.vue +++ b/app/assets/javascripts/search/topbar/components/app.vue @@ -48,7 +48,7 @@ export default { <template> <gl-form class="search-page-form" @submit.prevent="applyQuery"> <section class="gl-lg-display-flex gl-align-items-flex-end"> - <div class="gl-flex-fill-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2"> + <div class="gl-flex-grow-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2"> <label>{{ __('What are you searching for?') }}</label> <gl-search-box-by-type id="dashboard_search" diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue index 6a6300dcde0..592cfea5e32 100644 --- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue +++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue @@ -148,7 +148,9 @@ export default { </div> <div class="hide-collapsed"> - <p class="title gl-display-flex gl-justify-content-space-between"> + <p + class="gl-line-height-20 gl-mb-0 gl-text-gray-900 gl-display-flex gl-justify-content-space-between" + > {{ $options.i18n.SEVERITY }} <gl-link data-testid="editButton" diff --git a/app/assets/javascripts/user_lists/components/user_list_form.vue b/app/assets/javascripts/user_lists/components/user_list_form.vue index a0364089d68..b53aaf46ace 100644 --- a/app/assets/javascripts/user_lists/components/user_list_form.vue +++ b/app/assets/javascripts/user_lists/components/user_list_form.vue @@ -75,7 +75,7 @@ export default { </template> </gl-sprintf> </div> - <div class="gl-flex-fill-1 gl-ml-7"> + <div class="gl-flex-grow-1 gl-ml-7"> <gl-form-group label-for="user-list-name" :label="$options.translations.nameLabel" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue index c368399ed6f..f8c4ad69e39 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_expandable_section.vue @@ -51,7 +51,7 @@ export default { <gl-icon :name="iconName" :size="24" /> </span> - <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column gl-md-flex-direction-row"> + <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column gl-md-flex-direction-row"> <slot name="header"></slot> <div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index fa46b4b1364..6c162a06161 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -160,7 +160,7 @@ export default { <div class="ci-widget media"> <template v-if="hasCIError"> <gl-icon name="status_failed" class="gl-text-red-500" :size="24" /> - <p class="gl-flex-fill-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message"> + <p class="gl-flex-grow-1 gl-ml-5 gl-mb-0" data-testid="ci-error-message"> <gl-sprintf :message="$options.errorText"> <template #link="{ content }"> <gl-link :href="mrTroubleshootingDocsPath">{{ content }}</gl-link> @@ -171,7 +171,7 @@ export default { <template v-else-if="!hasPipeline"> <gl-loading-icon size="md" /> <p - class="gl-flex-fill-1 gl-display-flex gl-ml-5 gl-mb-0" + class="gl-flex-grow-1 gl-display-flex gl-ml-5 gl-mb-0" data-testid="monitoring-pipeline-message" > {{ $options.monitoringPipelineText }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue index 25f339b362f..2ba945a3ecf 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue @@ -107,7 +107,7 @@ export default { <template #header> <div data-testid="terraform-header-text" - class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column" + class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column" > <p v-if="validPlanCountText" class="gl-m-0"> <gl-sprintf :message="validPlanCountText"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue index 25e3dae92e8..427ab0842ea 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue @@ -71,8 +71,8 @@ export default { <gl-icon :name="iconType" :size="16" data-testid="change-type-icon" /> </span> - <div class="gl-display-flex gl-flex-fill-1 gl-flex-direction-column flex-md-row gl-pl-3"> - <div class="gl-flex-fill-1 gl-display-flex gl-flex-direction-column gl-pr-3"> + <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column flex-md-row gl-pl-3"> + <div class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-pr-3"> <p class="gl-mb-3 gl-line-height-normal"> <gl-sprintf :message="reportHeaderText"> <template #name> diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js index 4b1b09adcfd..37436de907f 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js @@ -2,7 +2,7 @@ import { isEmpty, uniqWith, isEqual } from 'lodash'; import AccessorUtilities from '~/lib/utils/accessor'; import { queryToObject } from '~/lib/utils/url_utility'; -import { MAX_RECENT_TOKENS_SIZE } from './constants'; +import { MAX_RECENT_TOKENS_SIZE, FILTERED_SEARCH_TERM } from './constants'; /** * Strips enclosing quotations from a string if it has one. @@ -23,7 +23,7 @@ export const stripQuotes = (value) => value.replace(/^('|")(.*)('|")$/, '$2'); export const uniqueTokens = (tokens) => { const knownTokens = []; return tokens.reduce((uniques, token) => { - if (typeof token === 'object' && token.type !== 'filtered-search-term') { + if (typeof token === 'object' && token.type !== FILTERED_SEARCH_TERM) { const tokenString = `${token.type}${token.value.operator}${token.value.data}`; if (!knownTokens.includes(tokenString)) { uniques.push(token); @@ -86,21 +86,37 @@ export function processFilters(filters) { }, {}); } +function filteredSearchQueryParam(filter) { + return filter + .map(({ value }) => value) + .join(' ') + .trim(); +} + /** * This function takes a filter object and maps it into a query object. Example filter: - * { myFilterName: { value: 'foo', operator: '=' } } + * { myFilterName: { value: 'foo', operator: '=' }, search: [{ value: 'my' }, { value: 'search' }] } * gets translated into: - * { myFilterName: 'foo', 'not[myFilterName]': null } + * { myFilterName: 'foo', 'not[myFilterName]': null, search: 'my search' } * @param {Object} filters - * @param {Object.myFilterName} a single filter value or an array of filters + * @param {Object} filters.myFilterName a single filter value or an array of filters + * @param {Object} options + * @param {Object} [options.filteredSearchTermKey] if set, 'filtered-search-term' filters are assigned to this key, 'search' is suggested * @return {Object} query object with both filter name and not-name with values */ -export function filterToQueryObject(filters = {}) { +export function filterToQueryObject(filters = {}, options = {}) { + const { filteredSearchTermKey } = options; + return Object.keys(filters).reduce((memo, key) => { const filter = filters[key]; + if (typeof filteredSearchTermKey === 'string' && key === FILTERED_SEARCH_TERM) { + return { ...memo, [filteredSearchTermKey]: filteredSearchQueryParam(filter) }; + } + let selected; let unselected; + if (Array.isArray(filter)) { selected = filter.filter((item) => item.operator === '=').map((item) => item.value); unselected = filter.filter((item) => item.operator === '!=').map((item) => item.value); @@ -125,7 +141,7 @@ export function filterToQueryObject(filters = {}) { * and returns the operator with it depending on the filter name * @param {String} filterName from url * @return {Object} - * @return {Object.filterName} extracted filtern ame + * @return {Object.filterName} extracted filter name * @return {Object.operator} `=` or `!=` */ function extractNameAndOperator(filterName) { @@ -138,21 +154,52 @@ function extractNameAndOperator(filterName) { } /** + * Gathers search term as values + * @param {String|Array} value + * @returns {Array} List of search terms split by word + */ +function filteredSearchTermValue(value) { + const values = Array.isArray(value) ? value : [value]; + return values + .filter((term) => term) + .join(' ') + .split(' ') + .map((term) => ({ value: term })); +} + +/** * This function takes a URL query string and maps it into a filter object. Example query string: * '?myFilterName=foo' * gets translated into: * { myFilterName: { value: 'foo', operator: '=' } } * @param {String} query URL query string, e.g. from `window.location.search` + * @param {Object} options + * @param {Object} options + * @param {String} [options.filteredSearchTermKey] if set, a FILTERED_SEARCH_TERM filter is created to this parameter. `'search'` is suggested + * @param {String[]} [options.filterNamesAllowList] if set, only this list of filters names is mapped + * @param {Boolean} [options.legacySpacesDecode] if set, plus symbols (+) are not encoded as spaces. `false` is suggested * @return {Object} filter object with filter names and their values */ -export function urlQueryToFilter(query = '') { - const filters = queryToObject(query, { gatherArrays: true, legacySpacesDecode: true }); +export function urlQueryToFilter(query = '', options = {}) { + const { filteredSearchTermKey, filterNamesAllowList, legacySpacesDecode = true } = options; + + const filters = queryToObject(query, { gatherArrays: true, legacySpacesDecode }); return Object.keys(filters).reduce((memo, key) => { const value = filters[key]; if (!value) { return memo; } + if (key === filteredSearchTermKey) { + return { + ...memo, + [FILTERED_SEARCH_TERM]: filteredSearchTermValue(value), + }; + } + const { filterName, operator } = extractNameAndOperator(key); + if (filterNamesAllowList && !filterNamesAllowList.includes(filterName)) { + return memo; + } let previousValues = []; if (Array.isArray(memo[filterName])) { previousValues = memo[filterName]; diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue index b9e916bc199..933a215112b 100644 --- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue +++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue @@ -62,7 +62,7 @@ export default { <slot name="left-action"></slot> </div> <div - class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1" + class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1" > <div class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"> <div @@ -81,7 +81,7 @@ export default { </div> <div v-if="$slots['left-secondary']" - class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-fill-1" + class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1" > <slot name="left-secondary"></slot> </div> @@ -114,7 +114,7 @@ export default { <div class="gl-w-7"></div> <div v-if="isDetailsShown" - class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3" + class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3" > <div v-for="(row, detailIndex) in detailsSlots" diff --git a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue index 0825c3a76ea..767a108dde5 100644 --- a/app/assets/javascripts/vue_shared/components/registry/registry_search.vue +++ b/app/assets/javascripts/vue_shared/components/registry/registry_search.vue @@ -109,7 +109,7 @@ export default { <div class="gl-display-flex gl-p-5 gl-bg-gray-10 gl-border-solid gl-border-1 gl-border-gray-100"> <gl-filtered-search v-model="internalFilter" - class="gl-mr-4 gl-flex-fill-1" + class="gl-mr-4 gl-flex-grow-1" :placeholder="__('Filter results')" :available-tokens="tokens" @submit="submitSearch" diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue index 1f70644eb2c..580e1668f41 100644 --- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions_modal.vue @@ -225,7 +225,7 @@ export default { <template v-if="!instructionsEmpty"> <div class="gl-display-flex"> <pre - class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line" + class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line" data-testid="binary-instructions" >{{ instructions.installInstructions }}</pre > @@ -241,7 +241,7 @@ export default { <h5 class="gl-mb-3">{{ $options.i18n.registerRunnerCommand }}</h5> <div class="gl-display-flex"> <pre - class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line" + class="gl-bg-gray gl-flex-grow-1 gl-white-space-pre-line" data-testid="register-command" >{{ instructions.registerInstructions }}</pre > diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 603747aa490..2fbdaaaf467 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -47,6 +47,7 @@ @import 'framework/toggle'; @import 'framework/typography'; @import 'framework/zen'; +@import 'framework/blank'; @import 'framework/wells'; @import 'framework/page_header'; @import 'framework/page_title'; diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss new file mode 100644 index 00000000000..7dd7ab339dd --- /dev/null +++ b/app/assets/stylesheets/framework/blank.scss @@ -0,0 +1,118 @@ +.blank-state-parent-container { + .section-container { + padding: 10px; + } + + .section-body { + width: 100%; + height: 100%; + padding-bottom: 25px; + border-radius: $border-radius-default; + } +} + +.blank-state-row { + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +.blank-state-welcome { + text-align: center; + padding: $gl-padding 0 ($gl-padding * 2); + + .blank-state-welcome-title { + font-size: 24px; + } + + .blank-state-text { + margin-bottom: 0; + } +} + +.blank-state-link { + color: $gl-text-color; + margin-bottom: 15px; + + &:hover { + background-color: $gray-light; + text-decoration: none; + color: $gl-text-color; + } +} + +.blank-state-center { + padding-top: 20px; + padding-bottom: 20px; + text-align: center; +} + +.blank-state { + display: flex; + align-items: center; + padding: 20px 50px; + border: 1px solid $border-color; + border-radius: $border-radius-default; + min-height: 240px; + margin-bottom: $gl-padding; + width: calc(50% - #{$gl-padding-8}); + + @include media-breakpoint-down(sm) { + width: 100%; + flex-direction: column; + justify-content: center; + padding: 50px 20px; + + .column-small & { + width: 100%; + } + + } +} + +.blank-state, +.blank-state-center { + .blank-state-icon { + svg { + display: block; + margin: auto; + } + } + + .blank-state-title { + margin-top: 0; + font-size: 18px; + } + + .blank-state-body { + @include media-breakpoint-down(sm) { + text-align: center; + margin-top: 20px; + } + + @include media-breakpoint-up(sm) { + padding-left: 20px; + } + } +} + +@include media-breakpoint-up(lg) { + .column-large { + flex: 2; + } + + .column-small { + flex: 1; + margin-bottom: 15px; + + .blank-state { + max-width: 400px; + flex-wrap: wrap; + margin-left: 15px; + } + + .blank-state-icon { + margin-bottom: 30px; + } + } +} diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb index 5c1d85f4374..91003e9580d 100644 --- a/app/controllers/clusters/applications_controller.rb +++ b/app/controllers/clusters/applications_controller.rb @@ -47,7 +47,7 @@ class Clusters::ApplicationsController < Clusters::BaseController end def cluster_application_params - params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :host, :port, :protocol, :cilium_log_enabled) + params.permit(:application, :hostname, :pages_domain_id, :email, :stack, :host, :port, :protocol) end def cluster_application_destroy_params diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index 565484495ba..8fd4e98d557 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -140,39 +140,15 @@ module MembershipActions end def root_params_key - case membershipable - when Namespace - :group_member - when Project - :project_member - else - raise "Unknown membershipable type: #{membershipable}!" - end + raise NotImplementedError end def members_page_url - case membershipable - when Namespace - polymorphic_url([membershipable, :members]) - when Project - project_project_members_path(membershipable) - else - raise "Unknown membershipable type: #{membershipable}!" - end + raise NotImplementedError end def source_type - @source_type ||= - begin - case membershipable - when Namespace - _("group") - when Project - _("project") - else - raise "Unknown membershipable type: #{membershipable}!" - end - end + raise NotImplementedError end def plain_source_type diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index f3b1d71d06e..8d9059d271f 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -82,6 +82,18 @@ class Groups::GroupMembersController < Groups::ApplicationController def plain_source_type 'group' end + + def source_type + _("group") + end + + def members_page_url + polymorphic_url([group, :members]) + end + + def root_params_key + :group_member + end end Groups::GroupMembersController.prepend_mod_with('Groups::GroupMembersController') diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb index 03561e73828..a59824b1085 100644 --- a/app/controllers/projects/feature_flags_controller.rb +++ b/app/controllers/projects/feature_flags_controller.rb @@ -11,6 +11,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController before_action :feature_flag, only: [:edit, :update, :destroy] before_action :ensure_flag_writable!, only: [:update] + before_action :exclude_legacy_flags_check, only: [:edit] before_action do push_frontend_feature_flag(:feature_flag_permissions) @@ -63,7 +64,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController end def edit - exclude_legacy_flags_check end def update @@ -108,6 +108,12 @@ class Projects::FeatureFlagsController < Projects::ApplicationController end end + def exclude_legacy_flags_check + if feature_flag.legacy_flag? + not_found + end + end + def create_params params.require(:operations_feature_flag) .permit(:name, :description, :active, :version, @@ -159,12 +165,4 @@ class Projects::FeatureFlagsController < Projects::ApplicationController render json: { message: messages }, status: status end - - def exclude_legacy_flags_check - if Feature.enabled?(:remove_legacy_flags, project, default_enabled: :yaml) && - Feature.disabled?(:remove_legacy_flags_override, project, default_enabled: :yaml) && - feature_flag.legacy_flag? - not_found - end - end end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index 4f342980bf0..370cd2b02a1 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -66,6 +66,18 @@ class Projects::ProjectMembersController < Projects::ApplicationController def plain_source_type 'project' end + + def source_type + _("project") + end + + def members_page_url + project_project_members_path(project) + end + + def root_params_key + :project_member + end end Projects::ProjectMembersController.prepend_mod_with('Projects::ProjectMembersController') diff --git a/app/finders/feature_flags_finder.rb b/app/finders/feature_flags_finder.rb index 0ab65d3630e..20b18c62f7a 100644 --- a/app/finders/feature_flags_finder.rb +++ b/app/finders/feature_flags_finder.rb @@ -24,11 +24,7 @@ class FeatureFlagsFinder private def feature_flags - if exclude_legacy_flags? - project.operations_feature_flags.new_version_only - else - project.operations_feature_flags - end + project.operations_feature_flags.new_version_only end def by_scope(items) @@ -41,9 +37,4 @@ class FeatureFlagsFinder items end end - - def exclude_legacy_flags? - Feature.enabled?(:remove_legacy_flags, project, default_enabled: :yaml) && - Feature.disabled?(:remove_legacy_flags_override, project, default_enabled: :yaml) - end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 1f4c98d6f28..e07ee22339a 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -9,7 +9,8 @@ module SearchHelper :repository_ref, :snippets, :sort, - :force_search_results + :force_search_results, + :project_ids ].freeze def search_autocomplete_opts(term) diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index 586142a7646..6a7a2b3f6bd 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -43,7 +43,7 @@ module Ci dotenv: '.env', cobertura: 'cobertura-coverage.xml', terraform: 'tfplan.json', - cluster_applications: 'gl-cluster-applications.json', + cluster_applications: 'gl-cluster-applications.json', # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/333441 requirements: 'requirements.json', coverage_fuzzing: 'gl-coverage-fuzzing.json', api_fuzzing: 'gl-api-fuzzing-report.json' diff --git a/app/models/clusters/applications/fluentd.rb b/app/models/clusters/applications/fluentd.rb deleted file mode 100644 index c5d674c1908..00000000000 --- a/app/models/clusters/applications/fluentd.rb +++ /dev/null @@ -1,121 +0,0 @@ -# frozen_string_literal: true - -module Clusters - module Applications - class Fluentd < ApplicationRecord - VERSION = '2.4.0' - CILIUM_CONTAINER_NAME = 'cilium-monitor' - - self.table_name = 'clusters_applications_fluentd' - - include ::Clusters::Concerns::ApplicationCore - include ::Clusters::Concerns::ApplicationStatus - include ::Clusters::Concerns::ApplicationVersion - include ::Clusters::Concerns::ApplicationData - include IgnorableColumns - - default_value_for :version, VERSION - default_value_for :port, 514 - default_value_for :protocol, :tcp - - ignore_column :waf_log_enabled, remove_with: '14.2', remove_after: '2021-07-22' - - enum protocol: { tcp: 0, udp: 1 } - - validate :has_at_least_one_log_enabled? - - def chart - 'fluentd/fluentd' - end - - def repository - 'https://gitlab-org.gitlab.io/cluster-integration/helm-stable-archive' - end - - def install_command - helm_command_module::InstallCommand.new( - name: 'fluentd', - repository: repository, - version: VERSION, - rbac: cluster.platform_kubernetes_rbac?, - chart: chart, - files: files - ) - end - - def values - content_values.to_yaml - end - - private - - def has_at_least_one_log_enabled? - errors.add(:base, _("At least one logging option is required to be enabled")) unless cilium_log_enabled - end - - def content_values - YAML.load_file(chart_values_file).deep_merge!(specification) - end - - def specification - { - "configMaps" => { - "output.conf" => output_configuration_content, - "general.conf" => general_configuration_content - } - } - end - - def output_configuration_content - <<~EOF - <match kubernetes.**> - @type remote_syslog - @id out_kube_remote_syslog - host #{host} - port #{port} - program fluentd - hostname ${kubernetes_host} - protocol #{protocol} - packet_size 131072 - <buffer kubernetes_host> - </buffer> - <format> - @type ltsv - </format> - </match> - EOF - end - - def general_configuration_content - <<~EOF - <match fluent.**> - @type null - </match> - <source> - @type http - port 9880 - bind 0.0.0.0 - </source> - <source> - @type tail - @id in_tail_container_logs - path #{path_to_logs} - pos_file /var/log/fluentd-containers.log.pos - tag kubernetes.* - read_from_head true - <parse> - @type json - time_format %Y-%m-%dT%H:%M:%S.%NZ - </parse> - </source> - EOF - end - - def path_to_logs - path = [] - path << "/var/log/containers/*#{CILIUM_CONTAINER_NAME}*.log" if cilium_log_enabled - path.join(',') - end - end - end -end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index aeebd2b368e..13ec8953353 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -21,7 +21,6 @@ module Clusters Clusters::Applications::Jupyter.application_name => Clusters::Applications::Jupyter, Clusters::Applications::Knative.application_name => Clusters::Applications::Knative, Clusters::Applications::ElasticStack.application_name => Clusters::Applications::ElasticStack, - Clusters::Applications::Fluentd.application_name => Clusters::Applications::Fluentd, Clusters::Applications::Cilium.application_name => Clusters::Applications::Cilium }.freeze DEFAULT_ENVIRONMENT = '*' @@ -68,7 +67,6 @@ module Clusters has_one_cluster_application :jupyter has_one_cluster_application :knative has_one_cluster_application :elastic_stack - has_one_cluster_application :fluentd has_one_cluster_application :cilium has_many :kubernetes_namespaces diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb index fab590dbe09..f57ac4af113 100644 --- a/app/serializers/cluster_application_entity.rb +++ b/app/serializers/cluster_application_entity.rb @@ -17,5 +17,4 @@ class ClusterApplicationEntity < Grape::Entity expose :host, if: -> (e, _) { e.respond_to?(:host) } expose :port, if: -> (e, _) { e.respond_to?(:port) } expose :protocol, if: -> (e, _) { e.respond_to?(:protocol) } - expose :cilium_log_enabled, if: -> (e, _) { e.respond_to?(:cilium_log_enabled) } end diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb index a22ac87f660..9fc7c3b4d40 100644 --- a/app/services/ci/job_artifacts/create_service.rb +++ b/app/services/ci/job_artifacts/create_service.rb @@ -115,7 +115,6 @@ module Ci case artifact.file_type when 'dotenv' then parse_dotenv_artifact(artifact) - when 'cluster_applications' then parse_cluster_applications_artifact(artifact) else success end end @@ -165,10 +164,6 @@ module Ci def parse_dotenv_artifact(artifact) Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact) end - - def parse_cluster_applications_artifact(artifact) - Clusters::ParseClusterApplicationsArtifactService.new(job, job.user).execute(artifact) - end end end end diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb index 47d6fbbeda2..c6f22cfa04c 100644 --- a/app/services/clusters/applications/base_service.rb +++ b/app/services/clusters/applications/base_service.rb @@ -5,8 +5,6 @@ module Clusters class BaseService InvalidApplicationError = Class.new(StandardError) - FLUENTD_KNOWN_ATTRS = %i[host protocol port cilium_log_enabled].freeze - attr_reader :cluster, :current_user, :params def initialize(cluster, user, params = {}) @@ -29,8 +27,6 @@ module Clusters application.stack = params[:stack] end - apply_fluentd_related_attributes(application) - if application.respond_to?(:oauth_application) application.oauth_application = create_oauth_application(application, request) end @@ -95,12 +91,6 @@ module Clusters ::Applications::CreateService.new(current_user, oauth_application_params).execute(request) end - - def apply_fluentd_related_attributes(application) - FLUENTD_KNOWN_ATTRS.each do |attr| - application[attr] = params[attr] if application.has_attribute?(attr) - end - end end end end diff --git a/app/services/clusters/parse_cluster_applications_artifact_service.rb b/app/services/clusters/parse_cluster_applications_artifact_service.rb deleted file mode 100644 index b9b2953b6bd..00000000000 --- a/app/services/clusters/parse_cluster_applications_artifact_service.rb +++ /dev/null @@ -1,94 +0,0 @@ -# frozen_string_literal: true - -module Clusters - class ParseClusterApplicationsArtifactService < ::BaseService - include Gitlab::Utils::StrongMemoize - - MAX_ACCEPTABLE_ARTIFACT_SIZE = 5.kilobytes - RELEASE_NAMES = %w[cilium].freeze - - def initialize(job, current_user) - @job = job - - super(job.project, current_user) - end - - def execute(artifact) - raise ArgumentError, 'Artifact is not cluster_applications file type' unless artifact&.cluster_applications? - - return error(too_big_error_message, :bad_request) unless artifact.file.size < MAX_ACCEPTABLE_ARTIFACT_SIZE - return error(no_deployment_message, :bad_request) unless job.deployment - return error(no_deployment_cluster_message, :bad_request) unless cluster - - parse!(artifact) - - success - rescue Gitlab::Kubernetes::Helm::Parsers::ListV2::ParserError, ActiveRecord::RecordInvalid => error - Gitlab::ErrorTracking.track_exception(error, job_id: artifact.job_id) - error(error.message, :bad_request) - end - - private - - attr_reader :job - - def cluster - strong_memoize(:cluster) do - deployment_cluster = job.deployment&.cluster - - deployment_cluster if Ability.allowed?(current_user, :admin_cluster, deployment_cluster) - end - end - - def parse!(artifact) - releases = [] - - artifact.each_blob do |blob| - next if blob.empty? - - releases.concat(Gitlab::Kubernetes::Helm::Parsers::ListV2.new(blob).releases) - end - - update_cluster_application_statuses!(releases) - end - - def update_cluster_application_statuses!(releases) - release_by_name = releases.index_by { |release| release['Name'] } - - Clusters::Cluster.transaction do - RELEASE_NAMES.each do |release_name| - application_class = Clusters::Cluster::APPLICATIONS[release_name] - application = cluster.find_or_build_application(application_class) - - release = release_by_name[release_name] - - if release - case release['Status'] - when 'DEPLOYED' - application.make_externally_installed! - when 'FAILED' - application.make_errored!(s_('ClusterIntegration|Helm release failed to install')) - end - else - # missing, so by definition, we consider this uninstalled - application.make_externally_uninstalled! if application.persisted? - end - end - end - end - - def too_big_error_message - human_size = ActiveSupport::NumberHelper.number_to_human_size(MAX_ACCEPTABLE_ARTIFACT_SIZE) - - s_('ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}') % { human_size: human_size } - end - - def no_deployment_message - s_('ClusterIntegration|No deployment found for this job') - end - - def no_deployment_cluster_message - s_('ClusterIntegration|No deployment cluster found for this job') - end - end -end diff --git a/app/services/feature_flags/disable_service.rb b/app/services/feature_flags/disable_service.rb deleted file mode 100644 index 8a443ac1795..00000000000 --- a/app/services/feature_flags/disable_service.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -module FeatureFlags - class DisableService < BaseService - def execute - return error('Feature Flag not found', 404) unless feature_flag_by_name - return error('Feature Flag Scope not found', 404) unless feature_flag_scope_by_environment_scope - return error('Strategy not found', 404) unless strategy_exist_in_persisted_data? - - ::FeatureFlags::UpdateService - .new(project, current_user, update_params) - .execute(feature_flag_by_name) - end - - private - - def update_params - if remaining_strategies.empty? - params_to_destroy_scope - else - params_to_update_scope - end - end - - def remaining_strategies - strong_memoize(:remaining_strategies) do - feature_flag_scope_by_environment_scope.strategies.reject do |strategy| - strategy['name'] == params[:strategy]['name'] && - strategy['parameters'] == params[:strategy]['parameters'] - end - end - end - - def strategy_exist_in_persisted_data? - feature_flag_scope_by_environment_scope.strategies != remaining_strategies - end - - def params_to_destroy_scope - { scopes_attributes: [{ id: feature_flag_scope_by_environment_scope.id, _destroy: true }] } - end - - def params_to_update_scope - { scopes_attributes: [{ id: feature_flag_scope_by_environment_scope.id, strategies: remaining_strategies }] } - end - end -end diff --git a/app/services/feature_flags/enable_service.rb b/app/services/feature_flags/enable_service.rb deleted file mode 100644 index b4cbb32e003..00000000000 --- a/app/services/feature_flags/enable_service.rb +++ /dev/null @@ -1,93 +0,0 @@ -# frozen_string_literal: true - -module FeatureFlags - class EnableService < BaseService - def execute - if feature_flag_by_name - update_feature_flag - else - create_feature_flag - end - end - - private - - def create_feature_flag - ::FeatureFlags::CreateService - .new(project, current_user, create_params) - .execute - end - - def update_feature_flag - ::FeatureFlags::UpdateService - .new(project, current_user, update_params) - .execute(feature_flag_by_name) - end - - def create_params - if params[:environment_scope] == '*' - params_to_create_flag_with_default_scope - else - params_to_create_flag_with_additional_scope - end - end - - def update_params - if feature_flag_scope_by_environment_scope - params_to_update_scope - else - params_to_create_scope - end - end - - def params_to_create_flag_with_default_scope - { - name: params[:name], - scopes_attributes: [ - { - active: true, - environment_scope: '*', - strategies: [params[:strategy]] - } - ] - } - end - - def params_to_create_flag_with_additional_scope - { - name: params[:name], - scopes_attributes: [ - { - active: false, - environment_scope: '*' - }, - { - active: true, - environment_scope: params[:environment_scope], - strategies: [params[:strategy]] - } - ] - } - end - - def params_to_create_scope - { - scopes_attributes: [{ - active: true, - environment_scope: params[:environment_scope], - strategies: [params[:strategy]] - }] - } - end - - def params_to_update_scope - { - scopes_attributes: [{ - id: feature_flag_scope_by_environment_scope.id, - active: true, - strategies: feature_flag_scope_by_environment_scope.strategies | [params[:strategy]] - }] - } - end - end -end diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb index 3181c0098cc..3e93346bfdf 100644 --- a/app/services/search/project_service.rb +++ b/app/services/search/project_service.rb @@ -8,8 +8,8 @@ module Search attr_accessor :project, :current_user, :params - def initialize(project, user, params) - @project = project + def initialize(project_or_projects, user, params) + @project = project_or_projects @current_user = user @params = params.dup end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 389cf17e115..cce7821a226 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -41,6 +41,10 @@ class SearchService end # rubocop: enable CodeReuse/ActiveRecord + def projects + # overridden in EE + end + def show_snippets? return @show_snippets if defined?(@show_snippets) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 52e41946ed1..ca10861115b 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -37,7 +37,7 @@ .todos-filters .issues-details-filters.row-content-block.second-block = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row' do - .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-fill-1.gl-flex-wrap.gl-mx-n2 + .filter-categories.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-grow-1.gl-flex-wrap.gl-mx-n2 .filter-item.gl-m-2 - if params[:group_id].present? = hidden_field_tag(:group_id, params[:group_id]) diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml index b2536090520..2a865aeda40 100644 --- a/app/views/layouts/fullscreen.html.haml +++ b/app/views/layouts/fullscreen.html.haml @@ -13,5 +13,5 @@ = render "layouts/flash" .content-wrapper.hide-when-top-nav-responsive-open{ id: "content-body", class: "d-flex flex-column align-items-stretch" } = yield - = render "layouts/nav/top_nav_responsive", class: "gl-flex-fill-1 gl-overflow-y-auto" + = render "layouts/nav/top_nav_responsive", class: "gl-flex-grow-1 gl-overflow-y-auto" = footer_message diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 365f9fb46fa..027b81d6c68 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -44,6 +44,7 @@ :preserve git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} cd #{h @project.path} + git switch -c #{default_branch_name} touch README.md git add README.md git commit -m "add README" @@ -56,7 +57,7 @@ %pre.bg-light :preserve cd existing_folder - git init + git init --initial-branch=#{default_branch_name} git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} git add . git commit -m "Initial commit" diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index d5fbee34fa0..4ba906dd02f 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -4,7 +4,7 @@ .gl-md-display-flex - if %w(issues merge_requests).include?(@scope) #js-search-sidebar{ class: search_bar_classes } - .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden + .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden = render partial: "search/results/empty" = render_if_exists 'shared/promotions/promote_advanced_search' - else @@ -14,7 +14,7 @@ .results.gl-md-display-flex.gl-mt-3 - if %w(issues merge_requests).include?(@scope) #js-search-sidebar{ class: search_bar_classes } - .gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden + .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden - if @scope == 'commits' %ul.content-list.commit-list = render partial: "search/results/commit", collection: @search_objects diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml index 19167f04855..0eeceac28c8 100644 --- a/app/views/shared/wikis/diff.html.haml +++ b/app/views/shared/wikis/diff.html.haml @@ -5,7 +5,7 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - %h3.page-title.gl-flex-fill-1 + %h3.page-title.gl-flex-grow-1 = link_to_wiki_page @page %span.light · diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml index 4bdeee3996f..729646c2731 100644 --- a/app/views/shared/wikis/edit.html.haml +++ b/app/views/shared/wikis/edit.html.haml @@ -7,7 +7,7 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - %h3.page-title.gl-flex-fill-1 + %h3.page-title.gl-flex-grow-1 - if @page.persisted? = link_to_wiki_page @page %span.light diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml index 1889b6501c9..c1918198594 100644 --- a/app/views/shared/wikis/pages.html.haml +++ b/app/views/shared/wikis/pages.html.haml @@ -5,7 +5,7 @@ - add_page_specific_style 'page_bundles/wiki' .wiki-page-header.top-area.flex-column.flex-lg-row - %h3.page-title.gl-flex-fill-1 + %h3.page-title.gl-flex-grow-1 = s_("Wiki|Wiki Pages") .nav-controls.pb-md-3.pb-lg-0 |