Commit bfeb5f25 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'ps-remove-unused-environments-modules' into 'master'

Clean up unused environments modules

See merge request gitlab-org/gitlab!82647
parents 289e5ac0 734f5b43
<script>
import { GlBadge, GlPagination, GlTab, GlTabs } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import { updateHistory, setUrlParams, queryToObject } from '~/lib/utils/url_utility';
import environmentAppQuery from '../graphql/queries/environment_app.query.graphql';
import pollIntervalQuery from '../graphql/queries/poll_interval.query.graphql';
import pageInfoQuery from '../graphql/queries/page_info.query.graphql';
import environmentToDeleteQuery from '../graphql/queries/environment_to_delete.query.graphql';
import environmentToRollbackQuery from '../graphql/queries/environment_to_rollback.query.graphql';
import environmentToStopQuery from '../graphql/queries/environment_to_stop.query.graphql';
import environmentToChangeCanaryQuery from '../graphql/queries/environment_to_change_canary.query.graphql';
import { ENVIRONMENTS_SCOPE } from '../constants';
import EnvironmentFolder from './new_environment_folder.vue';
import EnableReviewAppModal from './enable_review_app_modal.vue';
import StopEnvironmentModal from './stop_environment_modal.vue';
import EnvironmentItem from './new_environment_item.vue';
import ConfirmRollbackModal from './confirm_rollback_modal.vue';
import DeleteEnvironmentModal from './delete_environment_modal.vue';
import CanaryUpdateModal from './canary_update_modal.vue';
import EmptyState from './empty_state.vue';
export default {
components: {
DeleteEnvironmentModal,
CanaryUpdateModal,
ConfirmRollbackModal,
EmptyState,
EnvironmentFolder,
EnableReviewAppModal,
EnvironmentItem,
StopEnvironmentModal,
GlBadge,
GlPagination,
GlTab,
GlTabs,
},
apollo: {
environmentApp: {
query: environmentAppQuery,
variables() {
return {
scope: this.scope,
page: this.page ?? 1,
};
},
pollInterval() {
return this.interval;
},
},
interval: {
query: pollIntervalQuery,
},
pageInfo: {
query: pageInfoQuery,
},
environmentToDelete: {
query: environmentToDeleteQuery,
},
environmentToRollback: {
query: environmentToRollbackQuery,
},
environmentToStop: {
query: environmentToStopQuery,
},
environmentToChangeCanary: {
query: environmentToChangeCanaryQuery,
},
weight: {
query: environmentToChangeCanaryQuery,
},
},
inject: ['newEnvironmentPath', 'canCreateEnvironment', 'helpPagePath'],
i18n: {
newEnvironmentButtonLabel: s__('Environments|New environment'),
reviewAppButtonLabel: s__('Environments|Enable review app'),
available: __('Available'),
stopped: __('Stopped'),
prevPage: __('Go to previous page'),
nextPage: __('Go to next page'),
next: __('Next'),
prev: __('Prev'),
goto: (page) => sprintf(__('Go to page %{page}'), { page }),
},
modalId: 'enable-review-app-info',
data() {
const { page = '1', scope } = queryToObject(window.location.search);
return {
interval: undefined,
isReviewAppModalVisible: false,
page: parseInt(page, 10),
scope: Object.values(ENVIRONMENTS_SCOPE).includes(scope)
? scope
: ENVIRONMENTS_SCOPE.AVAILABLE,
environmentToDelete: {},
environmentToRollback: {},
environmentToStop: {},
environmentToChangeCanary: {},
weight: 0,
};
},
computed: {
canSetupReviewApp() {
return this.environmentApp?.reviewApp?.canSetupReviewApp;
},
folders() {
return this.environmentApp?.environments?.filter((e) => e.size > 1) ?? [];
},
environments() {
return this.environmentApp?.environments?.filter((e) => e.size === 1) ?? [];
},
hasEnvironments() {
return this.environments.length > 0 || this.folders.length > 0;
},
availableCount() {
return this.environmentApp?.availableCount;
},
addEnvironment() {
if (!this.canCreateEnvironment) {
return null;
}
return {
text: this.$options.i18n.newEnvironmentButtonLabel,
attributes: {
href: this.newEnvironmentPath,
category: 'primary',
variant: 'confirm',
},
};
},
openReviewAppModal() {
if (!this.canSetupReviewApp) {
return null;
}
return {
text: this.$options.i18n.reviewAppButtonLabel,
attributes: {
category: 'secondary',
variant: 'confirm',
},
};
},
stoppedCount() {
return this.environmentApp?.stoppedCount;
},
totalItems() {
return this.pageInfo?.total;
},
itemsPerPage() {
return this.pageInfo?.perPage;
},
},
mounted() {
window.addEventListener('popstate', this.syncPageFromQueryParams);
},
destroyed() {
window.removeEventListener('popstate', this.syncPageFromQueryParams);
this.$apollo.queries.environmentApp.stopPolling();
},
methods: {
showReviewAppModal() {
this.isReviewAppModalVisible = true;
},
setScope(scope) {
this.scope = scope;
this.moveToPage(1);
},
movePage(direction) {
this.moveToPage(this.pageInfo[`${direction}Page`]);
},
moveToPage(page) {
this.page = page;
updateHistory({
url: setUrlParams({ page: this.page }),
title: document.title,
});
this.resetPolling();
},
syncPageFromQueryParams() {
const { page = '1' } = queryToObject(window.location.search);
this.page = parseInt(page, 10);
},
resetPolling() {
this.$apollo.queries.environmentApp.stopPolling();
this.$apollo.queries.environmentApp.refetch();
this.$nextTick(() => {
if (this.interval) {
this.$apollo.queries.environmentApp.startPolling(this.interval);
}
});
},
},
ENVIRONMENTS_SCOPE,
};
</script>
<template>
<div>
<enable-review-app-modal
v-if="canSetupReviewApp"
v-model="isReviewAppModalVisible"
:modal-id="$options.modalId"
data-testid="enable-review-app-modal"
/>
<delete-environment-modal :environment="environmentToDelete" graphql />
<stop-environment-modal :environment="environmentToStop" graphql />
<confirm-rollback-modal :environment="environmentToRollback" graphql />
<canary-update-modal :environment="environmentToChangeCanary" :weight="weight" />
<gl-tabs
:action-secondary="addEnvironment"
:action-primary="openReviewAppModal"
sync-active-tab-with-query-params
query-param-name="scope"
@primary="showReviewAppModal"
>
<gl-tab
:query-param-value="$options.ENVIRONMENTS_SCOPE.AVAILABLE"
@click="setScope($options.ENVIRONMENTS_SCOPE.AVAILABLE)"
>
<template #title>
<span>{{ $options.i18n.available }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">
{{ availableCount }}
</gl-badge>
</template>
</gl-tab>
<gl-tab
:query-param-value="$options.ENVIRONMENTS_SCOPE.STOPPED"
@click="setScope($options.ENVIRONMENTS_SCOPE.STOPPED)"
>
<template #title>
<span>{{ $options.i18n.stopped }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">
{{ stoppedCount }}
</gl-badge>
</template>
</gl-tab>
</gl-tabs>
<template v-if="hasEnvironments">
<environment-folder
v-for="folder in folders"
:key="folder.name"
class="gl-mb-3"
:scope="scope"
:nested-environment="folder"
/>
<environment-item
v-for="environment in environments"
:key="environment.name"
class="gl-mb-3 gl-border-gray-100 gl-border-1 gl-border-b-solid"
:environment="environment.latest"
@change="resetPolling"
/>
</template>
<empty-state v-else :help-path="helpPagePath" />
<gl-pagination
align="center"
:total-items="totalItems"
:per-page="itemsPerPage"
:value="page"
:next="$options.i18n.next"
:prev="$options.i18n.prev"
:label-previous-page="$options.prevPage"
:label-next-page="$options.nextPage"
:label-page="$options.goto"
@next="movePage('next')"
@previous="movePage('previous')"
@input="moveToPage"
/>
</div>
</template>
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '../lib/utils/common_utils';
import Translate from '../vue_shared/translate';
import environmentsComponent from './components/environments_app.vue';
import { apolloProvider } from './graphql/client';
import EnvironmentsApp from './components/environments_app.vue';
Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
export default (el) => {
if (el) {
const {
canCreateEnvironment,
endpoint,
newEnvironmentPath,
helpPagePath,
projectPath,
defaultBranchName,
projectId,
} = el.dataset;
return new Vue({
el,
components: {
environmentsComponent,
},
apolloProvider,
apolloProvider: apolloProvider(endpoint),
provide: {
projectPath: el.dataset.projectPath,
projectId: el.dataset.projectId,
defaultBranchName: el.dataset.defaultBranchName,
},
data() {
const environmentsData = el.dataset;
return {
endpoint: environmentsData.environmentsDataEndpoint,
newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath,
canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
};
projectPath,
defaultBranchName,
endpoint,
newEnvironmentPath,
helpPagePath,
projectId,
canCreateEnvironment: parseBoolean(canCreateEnvironment),
},
render(createElement) {
return createElement('environments-component', {
props: {
endpoint: this.endpoint,
newEnvironmentPath: this.newEnvironmentPath,
helpPagePath: this.helpPagePath,
canCreateEnvironment: this.canCreateEnvironment,
},
});
render(h) {
return h(EnvironmentsApp);
},
});
}
......
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { parseBoolean } from '../lib/utils/common_utils';
import { apolloProvider } from './graphql/client';
import EnvironmentsApp from './components/new_environments_app.vue';
Vue.use(VueApollo);
export default (el) => {
if (el) {
const {
canCreateEnvironment,
endpoint,
newEnvironmentPath,
helpPagePath,
projectPath,
defaultBranchName,
projectId,
} = el.dataset;
return new Vue({
el,
apolloProvider: apolloProvider(endpoint),
provide: {
projectPath,
defaultBranchName,
endpoint,
newEnvironmentPath,
helpPagePath,
projectId,
canCreateEnvironment: parseBoolean(canCreateEnvironment),
},
render(h) {
return h(EnvironmentsApp);
},
});
}
return null;
};
import initEnvironments from '~/environments/';
import initNewEnvironments from '~/environments/new_index';
import initEnvironments from '~/environments/index';
let el = document.getElementById('environments-list-view');
const el = document.getElementById('environments-table');
if (el) {
initEnvironments(el);
} else {
el = document.getElementById('environments-table');
initNewEnvironments(el);
}
initEnvironments(el);
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import DeployBoard from '~/environments/components/deploy_board.vue';
import EnvironmentsComponent from '~/environments/components/environments_app.vue';
import axios from '~/lib/utils/axios_utils';
import { environment } from './mock_data';
describe('Environment', () => {
let mock;
let wrapper;
const mockData = {
canCreateEnvironment: true,
endpoint: 'environments.json',
helpCanaryDeploymentsPath: 'help/canary-deployments',
helpPagePath: 'help',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
newEnvironmentPath: 'environments/new',
userCalloutsPath: '/callouts',
};
const createWrapper = () => {
wrapper = mount(EnvironmentsComponent, { propsData: mockData });
return axios.waitForAll();
};
const mockRequest = (environmentList) => {
mock.onGet(mockData.endpoint).reply(
200,
{
environments: environmentList,
stopped_count: 1,
available_count: 0,
},
{
'X-nExt-pAge': '2',
'x-page': '1',
'X-Per-Page': '1',
'X-Prev-Page': '',
'X-TOTAL': '37',
'X-Total-Pages': '2',
},
);
};
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
wrapper.destroy();
mock.restore();
});
describe('with paginated environments', () => {
beforeEach(() => {
mockRequest([environment]);
return createWrapper();
});
describe('deploy boards', () => {
beforeEach(() => {
const deployEnvironment = {
...environment,
rollout_status: {
status: 'found',
},
};
mockRequest([environment, deployEnvironment]);
return createWrapper();
});
it('should render deploy boards', () => {
expect(wrapper.findComponent(DeployBoard).exists()).toBe(true);
});
it('should render arrow to open deploy boards', () => {
expect(wrapper.find('.deploy-board-icon [data-testid="chevron-down-icon"]').exists()).toBe(
true,
);
});
});
});
});
......@@ -6,13 +6,13 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubTransition } from 'helpers/stub_transition';
import { __, s__ } from '~/locale';
import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
import EnvironmentsFolder from '~/environments/components/environment_folder.vue';
import EnvironmentItem from '~/environments/components/new_environment_item.vue';
import { resolvedEnvironmentsApp, resolvedFolder } from './graphql/mock_data';
Vue.use(VueApollo);
describe('~/environments/components/new_environments_folder.vue', () => {
describe('~/environments/components/environments_folder.vue', () => {
let wrapper;
let environmentFolderMock;
let nestedEnvironment;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment