Skip to content
Snippets Groups Projects
Commit 4720b569 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent cefe554b
No related branches found
No related tags found
No related merge requests found
Showing
with 175 additions and 71 deletions
Loading
Loading
@@ -48,8 +48,10 @@ rules:
no-jquery/no-serialize: error
promise/always-return: off
promise/no-callback-in-promise: off
# Make update to eslint@6 smoother:
prefer-object-spread: off
overrides:
files:
- '**/spec/**/*'
rules:
"@gitlab/i18n/no-non-i18n-strings": off
- files:
- '**/spec/**/*'
rules:
"@gitlab/i18n/no-non-i18n-strings": off
/* eslint-disable max-classes-per-file */
import $ from 'jquery';
import Pikaday from 'pikaday';
import dateFormat from 'dateformat';
Loading
Loading
/* eslint-disable one-var, consistent-return */
/* eslint-disable max-classes-per-file, one-var, consistent-return */
 
import $ from 'jquery';
import _ from 'underscore';
Loading
Loading
<script>
import _ from 'underscore';
import { escape as esc, isEmpty } from 'lodash';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import { sprintf, __ } from '../../locale';
 
Loading
Loading
@@ -43,7 +43,7 @@ export default {
'%{startLink}%{name}%{endLink}',
{
startLink: `<a href="${this.deploymentStatus.environment.environment_path}" class="js-environment-link">`,
name: _.escape(this.deploymentStatus.environment.name),
name: esc(this.deploymentStatus.environment.name),
endLink: '</a>',
},
false,
Loading
Loading
@@ -58,10 +58,10 @@ export default {
return this.hasLastDeployment ? this.deploymentStatus.environment.last_deployment : {};
},
hasEnvironment() {
return !_.isEmpty(this.deploymentStatus.environment);
return !isEmpty(this.deploymentStatus.environment);
},
lastDeploymentPath() {
return !_.isEmpty(this.lastDeployment.deployable)
return !isEmpty(this.lastDeployment.deployable)
? this.lastDeployment.deployable.build_path
: '';
},
Loading
Loading
@@ -74,8 +74,8 @@ export default {
}
 
const { name, path } = this.deploymentCluster;
const escapedName = _.escape(name);
const escapedPath = _.escape(path);
const escapedName = esc(name);
const escapedPath = esc(path);
 
if (!escapedPath) {
return escapedName;
Loading
Loading
<script>
import _ from 'underscore';
import { isEmpty } from 'lodash';
import { GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
 
Loading
Loading
@@ -21,7 +21,7 @@ export default {
},
computed: {
isErasedByUser() {
return !_.isEmpty(this.user);
return !isEmpty(this.user);
},
},
};
Loading
Loading
<script>
import _ from 'underscore';
import { throttle, isEmpty } from 'lodash';
import { mapGetters, mapState, mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
Loading
Loading
@@ -125,7 +125,7 @@ export default {
// Once the job log is loaded,
// fetch the stages for the dropdown on the sidebar
job(newVal, oldVal) {
if (_.isEmpty(oldVal) && !_.isEmpty(newVal.pipeline)) {
if (isEmpty(oldVal) && !isEmpty(newVal.pipeline)) {
const stages = this.job.pipeline.details.stages || [];
 
const defaultStage = stages.find(stage => stage && stage.name === this.selectedStage);
Loading
Loading
@@ -145,7 +145,7 @@ export default {
},
},
created() {
this.throttled = _.throttle(this.toggleScrollButtons, 100);
this.throttled = throttle(this.toggleScrollButtons, 100);
 
window.addEventListener('resize', this.onResize);
window.addEventListener('scroll', this.updateScroll);
Loading
Loading
<script>
import _ from 'underscore';
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
import { GlButton } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
Loading
Loading
@@ -19,7 +19,9 @@ export default {
validator(value) {
return (
value === null ||
(_.has(value, 'path') && _.has(value, 'method') && _.has(value, 'button_title'))
(Object.prototype.hasOwnProperty.call(value, 'path') &&
Object.prototype.hasOwnProperty.call(value, 'method') &&
Object.prototype.hasOwnProperty.call(value, 'button_title'))
);
},
},
Loading
Loading
@@ -78,7 +80,7 @@ export default {
const newVariable = {
key: this.key,
secret_value: this.secretValue,
id: _.uniqueId(),
id: uniqueId(),
};
 
this.variables.push(newVariable);
Loading
Loading
<script>
import _ from 'underscore';
import { isEmpty } from 'lodash';
import { mapActions, mapState } from 'vuex';
import { GlLink, GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
Loading
Loading
@@ -84,10 +84,10 @@ export default {
);
},
hasArtifact() {
return !_.isEmpty(this.job.artifact);
return !isEmpty(this.job.artifact);
},
hasTriggers() {
return !_.isEmpty(this.job.trigger);
return !isEmpty(this.job.trigger);
},
hasStages() {
return (
Loading
Loading
<script>
import _ from 'underscore';
import { isEmpty } from 'lodash';
import { GlLink } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
 
Loading
Loading
@@ -24,7 +24,7 @@ export default {
},
computed: {
hasRef() {
return !_.isEmpty(this.pipeline.ref);
return !isEmpty(this.pipeline.ref);
},
isTriggeredByMergeRequest() {
return Boolean(this.pipeline.merge_request);
Loading
Loading
import _ from 'underscore';
import { isEmpty, isString } from 'lodash';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
 
export const headerTime = state => (state.job.started ? state.job.started : state.job.created_at);
Loading
Loading
@@ -7,15 +7,15 @@ export const hasUnmetPrerequisitesFailure = state =>
state.job && state.job.failure_reason && state.job.failure_reason === 'unmet_prerequisites';
 
export const shouldRenderCalloutMessage = state =>
!_.isEmpty(state.job.status) && !_.isEmpty(state.job.callout_message);
!isEmpty(state.job.status) && !isEmpty(state.job.callout_message);
 
/**
* When job has not started the key will be null
* When job started the key will be a string with a date.
*/
export const shouldRenderTriggeredLabel = state => _.isString(state.job.started);
export const shouldRenderTriggeredLabel = state => isString(state.job.started);
 
export const hasEnvironment = state => !_.isEmpty(state.job.deployment_status);
export const hasEnvironment = state => !isEmpty(state.job.deployment_status);
 
/**
* Checks if it the job has trace.
Loading
Loading
@@ -23,7 +23,7 @@ export const hasEnvironment = state => !_.isEmpty(state.job.deployment_status);
* @returns {Boolean}
*/
export const hasTrace = state =>
state.job.has_trace || (!_.isEmpty(state.job.status) && state.job.status.group === 'running');
state.job.has_trace || (!isEmpty(state.job.status) && state.job.status.group === 'running');
 
export const emptyStateIllustration = state =>
(state.job && state.job.status && state.job.status.illustration) || {};
Loading
Loading
@@ -38,8 +38,8 @@ export const emptyStateAction = state =>
* @returns {Boolean}
*/
export const shouldRenderSharedRunnerLimitWarning = state =>
!_.isEmpty(state.job.runners) &&
!_.isEmpty(state.job.runners.quota) &&
!isEmpty(state.job.runners) &&
!isEmpty(state.job.runners.quota) &&
state.job.runners.quota.used >= state.job.runners.quota.limit;
 
export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete;
Loading
Loading
Loading
Loading
@@ -127,7 +127,6 @@ export default {
});
 
const yAxisWithOffset = {
name: this.yAxisLabel,
axisLabel: {
formatter: num => roundOffFloat(num - this.yOffset, 3).toString(),
},
Loading
Loading
@@ -162,6 +161,7 @@ export default {
}),
);
}
return { yAxis: yAxisWithOffset, series: boundarySeries };
},
},
Loading
Loading
Loading
Loading
@@ -162,7 +162,8 @@ export default {
);
},
chartOptions() {
const option = omit(this.option, 'series');
const { yAxis, xAxis } = this.option;
const option = omit(this.option, ['series', 'yAxis', 'xAxis']);
 
const dataYAxis = {
name: this.yAxisLabel,
Loading
Loading
@@ -173,7 +174,9 @@ export default {
axisLabel: {
formatter: num => roundOffFloat(num, 3).toString(),
},
...yAxis,
};
const deploymentsYAxis = {
show: false,
min: deploymentYAxisCoords.min,
Loading
Loading
@@ -184,18 +187,21 @@ export default {
},
};
 
const timeXAxis = {
name: __('Time'),
type: 'time',
axisLabel: {
formatter: date => dateFormat(date, dateFormats.timeOfDay),
},
axisPointer: {
snap: true,
},
...xAxis,
};
return {
series: this.chartOptionSeries,
xAxis: {
name: __('Time'),
type: 'time',
axisLabel: {
formatter: date => dateFormat(date, dateFormats.timeOfDay),
},
axisPointer: {
snap: true,
},
},
xAxis: timeXAxis,
yAxis: [dataYAxis, deploymentsYAxis],
dataZoom: [this.dataZoomConfig],
...option,
Loading
Loading
Loading
Loading
@@ -3,5 +3,7 @@ import registryExplorer from '~/registry/explorer/index';
 
document.addEventListener('DOMContentLoaded', () => {
initRegistryImages();
registryExplorer();
const { attachMainComponent, attachBreadcrumb } = registryExplorer();
attachBreadcrumb();
attachMainComponent();
});
Loading
Loading
@@ -3,5 +3,7 @@ import registryExplorer from '~/registry/explorer/index';
 
document.addEventListener('DOMContentLoaded', () => {
initRegistryImages();
registryExplorer();
const { attachMainComponent, attachBreadcrumb } = registryExplorer();
attachBreadcrumb();
attachMainComponent();
});
<script>
import { initial, first, last } from 'lodash';
export default {
props: {
crumbs: {
type: Array,
required: true,
},
},
computed: {
rootRoute() {
return this.$router.options.routes.find(r => r.meta.root);
},
isRootRoute() {
return this.$route.name === this.rootRoute.name;
},
rootCrumbs() {
return initial(this.crumbs);
},
divider() {
const { classList, tagName, innerHTML } = first(this.crumbs).querySelector('svg');
return { classList: [...classList], tagName, innerHTML };
},
lastCrumb() {
const { children } = last(this.crumbs);
const { tagName, classList } = first(children);
return {
tagName,
classList: [...classList],
text: this.$route.meta.nameGenerator(this.$route),
path: { to: this.$route.name },
};
},
},
};
</script>
<template>
<ul>
<li
v-for="(crumb, index) in rootCrumbs"
:key="index"
:class="crumb.classList"
v-html="crumb.innerHTML"
></li>
<li v-if="!isRootRoute">
<router-link ref="rootRouteLink" :to="rootRoute.path">
{{ rootRoute.meta.nameGenerator(rootRoute) }}
</router-link>
<component :is="divider.tagName" :class="divider.classList" v-html="divider.innerHTML" />
</li>
<li>
<component :is="lastCrumb.tagName" ref="lastCrumb" :class="lastCrumb.classList">
<router-link ref="childRouteLink" :to="lastCrumb.path">{{ lastCrumb.text }}</router-link>
</component>
</li>
</ul>
</template>
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import RegistryExplorer from './pages/index.vue';
import RegistryBreadcrumb from './components/registry_breadcrumb.vue';
import { createStore } from './stores';
import createRouter from './router';
 
Loading
Loading
@@ -19,15 +20,39 @@ export default () => {
const router = createRouter(endpoint, store);
store.dispatch('setInitialState', el.dataset);
 
return new Vue({
el,
store,
router,
components: {
RegistryExplorer,
},
render(createElement) {
return createElement('registry-explorer');
},
});
const attachMainComponent = () =>
new Vue({
el,
store,
router,
components: {
RegistryExplorer,
},
render(createElement) {
return createElement('registry-explorer');
},
});
const attachBreadcrumb = () => {
const breadCrumbEl = document.querySelector('nav .js-breadcrumbs-list');
const crumbs = [...document.querySelectorAll('.js-breadcrumbs-list li')];
return new Vue({
el: breadCrumbEl,
store,
router,
components: {
RegistryBreadcrumb,
},
render(createElement) {
return createElement('registry-breadcrumb', {
class: breadCrumbEl.className,
props: {
crumbs,
},
});
},
});
};
return { attachBreadcrumb, attachMainComponent };
};
Loading
Loading
@@ -19,6 +19,7 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import Tracking from '~/tracking';
import { decodeAndParse } from '../utils';
import {
LIST_KEY_TAG,
LIST_KEY_IMAGE_ID,
Loading
Loading
@@ -62,7 +63,7 @@ export default {
computed: {
...mapState(['tags', 'tagsPagination', 'isLoading', 'config']),
imageName() {
const { name } = JSON.parse(window.atob(this.$route.params.id));
const { name } = decodeAndParse(this.$route.params.id);
return name;
},
fields() {
Loading
Loading
@@ -169,7 +170,7 @@ export default {
},
handleSingleDelete(itemToDelete) {
this.itemsToBeDeleted = [];
this.requestDeleteTag({ tag: itemToDelete, imageId: this.$route.params.id });
this.requestDeleteTag({ tag: itemToDelete, params: this.$route.params.id });
},
handleMultipleDelete() {
const { itemsToBeDeleted } = this;
Loading
Loading
@@ -178,7 +179,7 @@ export default {
 
this.requestDeleteTags({
ids: itemsToBeDeleted.map(x => this.tags[x].name),
imageId: this.$route.params.id,
params: this.$route.params.id,
});
},
onDeletionConfirmed() {
Loading
Loading
Loading
Loading
@@ -70,7 +70,7 @@ export default {
this.itemToDelete = {};
},
encodeListItem(item) {
const params = JSON.stringify({ name: item.path, tags_path: item.tags_path });
const params = JSON.stringify({ name: item.path, tags_path: item.tags_path, id: item.id });
return window.btoa(params);
},
},
Loading
Loading
import Vue from 'vue';
import VueRouter from 'vue-router';
import { __ } from '~/locale';
import { s__ } from '~/locale';
import List from './pages/list.vue';
import Details from './pages/details.vue';
import { decodeAndParse } from './utils';
 
Vue.use(VueRouter);
 
Loading
Loading
@@ -16,7 +17,8 @@ export default function createRouter(base, store) {
path: '/',
component: List,
meta: {
name: __('Container Registry'),
nameGenerator: () => s__('ContainerRegistry|Container Registry'),
root: true,
},
beforeEnter: (to, from, next) => {
store.dispatch('requestImagesList');
Loading
Loading
@@ -28,10 +30,10 @@ export default function createRouter(base, store) {
path: '/:id',
component: Details,
meta: {
name: __('Tags'),
nameGenerator: route => decodeAndParse(route.params.id).name,
},
beforeEnter: (to, from, next) => {
store.dispatch('requestTagsList', { id: to.params.id });
store.dispatch('requestTagsList', { params: to.params.id });
next();
},
},
Loading
Loading
Loading
Loading
@@ -13,6 +13,7 @@ import {
DELETE_IMAGE_ERROR_MESSAGE,
DELETE_IMAGE_SUCCESS_MESSAGE,
} from '../constants';
import { decodeAndParse } from '../utils';
 
export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
 
Loading
Loading
@@ -43,9 +44,9 @@ export const requestImagesList = ({ commit, dispatch, state }, pagination = {})
});
};
 
export const requestTagsList = ({ commit, dispatch }, { pagination = {}, id }) => {
export const requestTagsList = ({ commit, dispatch }, { pagination = {}, params }) => {
commit(types.SET_MAIN_LOADING, true);
const { tags_path } = JSON.parse(window.atob(id));
const { tags_path } = decodeAndParse(params);
 
const { page = DEFAULT_PAGE, perPage = DEFAULT_PAGE_SIZE } = pagination;
return axios
Loading
Loading
@@ -61,13 +62,13 @@ export const requestTagsList = ({ commit, dispatch }, { pagination = {}, id }) =
});
};
 
export const requestDeleteTag = ({ commit, dispatch, state }, { tag, imageId }) => {
export const requestDeleteTag = ({ commit, dispatch, state }, { tag, params }) => {
commit(types.SET_MAIN_LOADING, true);
return axios
.delete(tag.destroy_path)
.then(() => {
createFlash(DELETE_TAG_SUCCESS_MESSAGE, 'success');
dispatch('requestTagsList', { pagination: state.tagsPagination, id: imageId });
dispatch('requestTagsList', { pagination: state.tagsPagination, params });
})
.catch(() => {
createFlash(DELETE_TAG_ERROR_MESSAGE);
Loading
Loading
@@ -77,15 +78,16 @@ export const requestDeleteTag = ({ commit, dispatch, state }, { tag, imageId })
});
};
 
export const requestDeleteTags = ({ commit, dispatch, state }, { ids, imageId }) => {
export const requestDeleteTags = ({ commit, dispatch, state }, { ids, params }) => {
commit(types.SET_MAIN_LOADING, true);
const url = `/${state.config.projectPath}/registry/repository/${imageId}/tags/bulk_destroy`;
const { id } = decodeAndParse(params);
const url = `/${state.config.projectPath}/registry/repository/${id}/tags/bulk_destroy`;
 
return axios
.delete(url, { params: { ids } })
.then(() => {
createFlash(DELETE_TAGS_SUCCESS_MESSAGE, 'success');
dispatch('requestTagsList', { pagination: state.tagsPagination, id: imageId });
dispatch('requestTagsList', { pagination: state.tagsPagination, params });
})
.catch(() => {
createFlash(DELETE_TAGS_ERROR_MESSAGE);
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment