Skip to content
Snippets Groups Projects
Commit af28cb8a authored by Jacques Erasmus's avatar Jacques Erasmus
Browse files

Merge branch 'master' into 51306-fix-inaccessible-dropdown-for-codeless-projects

parents 16cd5967 28d412e5
No related branches found
No related tags found
No related merge requests found
Showing
with 287 additions and 147 deletions
Loading
Loading
@@ -115,7 +115,7 @@ export default {
<span>
{{ selectedVersionName }}
</span>
<Icon
<icon
:size="12"
name="angle-down"
class="position-absolute"
Loading
Loading
Loading
Loading
@@ -46,10 +46,10 @@ export default {
showExpandMessage() {
return (
this.isCollapsed ||
!this.file.highlightedDiffLines &&
!this.isLoadingCollapsedDiff &&
!this.file.tooLarge &&
this.file.text
(!this.file.highlightedDiffLines &&
!this.isLoadingCollapsedDiff &&
!this.file.tooLarge &&
this.file.text)
);
},
showLoadingIcon() {
Loading
Loading
import DirtySubmitForm from './dirty_submit_form';
class DirtySubmitCollection {
constructor(forms) {
this.forms = forms;
this.dirtySubmits = [];
this.forms.forEach(form => this.dirtySubmits.push(new DirtySubmitForm(form)));
}
}
export default DirtySubmitCollection;
import DirtySubmitCollection from './dirty_submit_collection';
import DirtySubmitForm from './dirty_submit_form';
export default function dirtySubmitFactory(formOrForms) {
const isCollection = formOrForms instanceof NodeList || formOrForms instanceof Array;
const DirtySubmitClass = isCollection ? DirtySubmitCollection : DirtySubmitForm;
return new DirtySubmitClass(formOrForms);
}
import _ from 'underscore';
class DirtySubmitForm {
constructor(form) {
this.form = form;
this.dirtyInputs = [];
this.isDisabled = true;
this.init();
}
init() {
this.inputs = this.form.querySelectorAll('input, textarea, select');
this.submits = this.form.querySelectorAll('input[type=submit], button[type=submit]');
this.inputs.forEach(DirtySubmitForm.initInput);
this.toggleSubmission();
this.registerListeners();
}
registerListeners() {
const throttledUpdateDirtyInput = _.throttle(
event => this.updateDirtyInput(event),
DirtySubmitForm.THROTTLE_DURATION,
);
this.form.addEventListener('input', throttledUpdateDirtyInput);
this.form.addEventListener('submit', event => this.formSubmit(event));
}
updateDirtyInput(event) {
const input = event.target;
if (!input.dataset.dirtySubmitOriginalValue) return;
this.updateDirtyInputs(input);
this.toggleSubmission();
}
updateDirtyInputs(input) {
const { name } = input;
const isDirty =
input.dataset.dirtySubmitOriginalValue !== DirtySubmitForm.inputCurrentValue(input);
const indexOfInputName = this.dirtyInputs.indexOf(name);
const isExisting = indexOfInputName !== -1;
if (isDirty && !isExisting) this.dirtyInputs.push(name);
if (!isDirty && isExisting) this.dirtyInputs.splice(indexOfInputName, 1);
}
toggleSubmission() {
this.isDisabled = this.dirtyInputs.length === 0;
this.submits.forEach(element => {
element.disabled = this.isDisabled;
});
}
formSubmit(event) {
if (this.isDisabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
return !this.isDisabled;
}
static initInput(element) {
element.dataset.dirtySubmitOriginalValue = DirtySubmitForm.inputCurrentValue(element);
}
static isInputCheckable(input) {
return input.type === 'checkbox' || input.type === 'radio';
}
static inputCurrentValue(input) {
return DirtySubmitForm.isInputCheckable(input) ? input.checked.toString() : input.value;
}
}
DirtySubmitForm.THROTTLE_DURATION = 500;
export default DirtySubmitForm;
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import Flash from '~/flash';
export default function initDismissableCallout(alertSelector) {
const alertEl = document.querySelector(alertSelector);
if (!alertEl) {
return;
}
const closeButtonEl = alertEl.getElementsByClassName('close')[0];
const { dismissEndpoint, featureId } = closeButtonEl.dataset;
closeButtonEl.addEventListener('click', () => {
axios
.post(dismissEndpoint, {
feature_name: featureId,
})
.then(() => {
$(alertEl).alert('close');
})
.catch(() => {
Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
});
});
}
Loading
Loading
@@ -6,11 +6,4 @@ const IGNORE_CLASS = 'droplab-item-ignore';
// Matches `{{anything}}` and `{{ everything }}`.
const TEMPLATE_REGEX = /\{\{(.+?)\}\}/g;
 
export {
DATA_TRIGGER,
DATA_DROPDOWN,
SELECTED_CLASS,
ACTIVE_CLASS,
TEMPLATE_REGEX,
IGNORE_CLASS,
};
export { DATA_TRIGGER, DATA_DROPDOWN, SELECTED_CLASS, ACTIVE_CLASS, TEMPLATE_REGEX, IGNORE_CLASS };
Loading
Loading
@@ -2,7 +2,7 @@ import utils from './utils';
import { SELECTED_CLASS, IGNORE_CLASS } from './constants';
 
class DropDown {
constructor(list, config = { }) {
constructor(list, config = {}) {
this.currentIndex = 0;
this.hidden = true;
this.list = typeof list === 'string' ? document.querySelector(list) : list;
Loading
Loading
@@ -157,7 +157,7 @@ class DropDown {
static setImagesSrc(template) {
const images = [...template.querySelectorAll('img[data-src]')];
 
images.forEach((image) => {
images.forEach(image => {
const img = image;
 
img.src = img.getAttribute('data-src');
Loading
Loading
Loading
Loading
@@ -51,7 +51,7 @@ class DropLab {
}
 
processData(trigger, data, methodName) {
this.hooks.forEach((hook) => {
this.hooks.forEach(hook => {
if (Array.isArray(trigger)) hook.list[methodName](trigger);
 
if (hook.trigger.id === trigger) hook.list[methodName](data);
Loading
Loading
@@ -78,7 +78,8 @@ class DropLab {
}
 
changeHookList(trigger, list, plugins, config) {
const availableTrigger = typeof trigger === 'string' ? document.getElementById(trigger) : trigger;
const availableTrigger =
typeof trigger === 'string' ? document.getElementById(trigger) : trigger;
 
this.hooks.forEach((hook, i) => {
const aHook = hook;
Loading
Loading
Loading
Loading
@@ -2,15 +2,18 @@
 
import { ACTIVE_CLASS } from './constants';
 
const Keyboard = function () {
const Keyboard = function() {
var currentKey;
var currentFocus;
var isUpArrow = false;
var isDownArrow = false;
var removeHighlight = function removeHighlight(list) {
var itemElements = Array.prototype.slice.call(list.list.querySelectorAll('li:not(.divider):not(.hidden)'), 0);
var itemElements = Array.prototype.slice.call(
list.list.querySelectorAll('li:not(.divider):not(.hidden)'),
0,
);
var listItems = [];
for(var i = 0; i < itemElements.length; i++) {
for (var i = 0; i < itemElements.length; i++) {
var listItem = itemElements[i];
listItem.classList.remove(ACTIVE_CLASS);
 
Loading
Loading
@@ -23,13 +26,13 @@ const Keyboard = function () {
 
var setMenuForArrows = function setMenuForArrows(list) {
var listItems = removeHighlight(list);
if(list.currentIndex>0){
if(!listItems[list.currentIndex-1]){
list.currentIndex = list.currentIndex-1;
if (list.currentIndex > 0) {
if (!listItems[list.currentIndex - 1]) {
list.currentIndex = list.currentIndex - 1;
}
 
if (listItems[list.currentIndex-1]) {
var el = listItems[list.currentIndex-1];
if (listItems[list.currentIndex - 1]) {
var el = listItems[list.currentIndex - 1];
var filterDropdownEl = el.closest('.filter-dropdown');
el.classList.add(ACTIVE_CLASS);
 
Loading
Loading
@@ -55,7 +58,7 @@ const Keyboard = function () {
};
var selectItem = function selectItem(list) {
var listItems = removeHighlight(list);
var currentItem = listItems[list.currentIndex-1];
var currentItem = listItems[list.currentIndex - 1];
var listEvent = new CustomEvent('click.dl', {
detail: {
list: list,
Loading
Loading
@@ -65,43 +68,49 @@ const Keyboard = function () {
});
list.list.dispatchEvent(listEvent);
list.hide();
}
};
 
var keydown = function keydown(e){
var keydown = function keydown(e) {
var typedOn = e.target;
var list = e.detail.hook.list;
var currentIndex = list.currentIndex;
isUpArrow = false;
isDownArrow = false;
 
if(e.detail.which){
if (e.detail.which) {
currentKey = e.detail.which;
if(currentKey === 13){
if (currentKey === 13) {
selectItem(e.detail.hook.list);
return;
}
if(currentKey === 38) {
if (currentKey === 38) {
isUpArrow = true;
}
if(currentKey === 40) {
if (currentKey === 40) {
isDownArrow = true;
}
} else if(e.detail.key) {
} else if (e.detail.key) {
currentKey = e.detail.key;
if(currentKey === 'Enter'){
if (currentKey === 'Enter') {
selectItem(e.detail.hook.list);
return;
}
if(currentKey === 'ArrowUp') {
if (currentKey === 'ArrowUp') {
isUpArrow = true;
}
if(currentKey === 'ArrowDown') {
if (currentKey === 'ArrowDown') {
isDownArrow = true;
}
}
if(isUpArrow){ currentIndex--; }
if(isDownArrow){ currentIndex++; }
if(currentIndex < 0){ currentIndex = 0; }
if (isUpArrow) {
currentIndex--;
}
if (isDownArrow) {
currentIndex++;
}
if (currentIndex < 0) {
currentIndex = 0;
}
list.currentIndex = currentIndex;
setMenuForArrows(e.detail.hook.list);
};
Loading
Loading
Loading
Loading
@@ -43,12 +43,12 @@ const Ajax = {
 
return AjaxCache.retrieve(config.endpoint)
.then(self.preprocessing.bind(null, config))
.then((data) => self._loadData(data, config, self))
.then(data => self._loadData(data, config, self))
.catch(config.onError);
},
destroy: function() {
this.destroyed = true;
}
},
};
 
export default Ajax;
Loading
Loading
@@ -41,8 +41,10 @@ const AjaxFilter = {
if (config.searchValueFunction) {
searchValue = config.searchValueFunction();
}
if (config.loadingTemplate && this.hook.list.data === undefined ||
this.hook.list.data.length === 0) {
if (
(config.loadingTemplate && this.hook.list.data === undefined) ||
this.hook.list.data.length === 0
) {
var dynamicList = this.hook.list.list.querySelector('[data-dynamic]');
var loadingTemplate = document.createElement('div');
loadingTemplate.innerHTML = config.loadingTemplate;
Loading
Loading
@@ -61,7 +63,7 @@ const AjaxFilter = {
params[config.searchKey] = searchValue;
var url = config.endpoint + this.buildParams(params);
return AjaxCache.retrieve(url)
.then((data) => {
.then(data => {
this._loadData(data, config);
if (config.onLoadingFinished) {
config.onLoadingFinished(data);
Loading
Loading
@@ -72,8 +74,7 @@ const AjaxFilter = {
 
_loadData(data, config) {
const list = this.hook.list;
if (config.loadingTemplate && list.data === undefined ||
list.data.length === 0) {
if ((config.loadingTemplate && list.data === undefined) || list.data.length === 0) {
const dataLoadingTemplate = list.list.querySelector('[data-loading-template]');
if (dataLoadingTemplate) {
dataLoadingTemplate.outerHTML = this.listTemplate;
Loading
Loading
@@ -81,7 +82,8 @@ const AjaxFilter = {
}
if (!this.destroyed) {
var hookListChildren = list.list.children;
var onlyDynamicList = hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
var onlyDynamicList =
hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
if (onlyDynamicList && data.length === 0) {
list.hide();
}
Loading
Loading
@@ -100,12 +102,12 @@ const AjaxFilter = {
},
 
destroy: function destroy() {
if (this.timeout)clearTimeout(this.timeout);
if (this.timeout) clearTimeout(this.timeout);
this.destroyed = true;
 
this.hook.trigger.removeEventListener('keydown.dl', this.eventWrapper.debounceTrigger);
this.hook.trigger.removeEventListener('focus', this.eventWrapper.debounceTrigger);
}
},
};
 
export default AjaxFilter;
/* eslint-disable */
 
const Filter = {
keydown: function(e){
keydown: function(e) {
if (this.destroyed) return;
 
var hiddenCount = 0;
Loading
Loading
@@ -14,14 +14,14 @@ const Filter = {
var matches = [];
var filterFunction;
// will only work on dynamically set data
if(!data){
if (!data) {
return;
}
 
if (config && config.filterFunction && typeof config.filterFunction === 'function') {
filterFunction = config.filterFunction;
} else {
filterFunction = function(o){
filterFunction = function(o) {
// cheap string search
o.droplab_hidden = o[config.template].toLowerCase().indexOf(value) === -1;
return o;
Loading
Loading
@@ -47,20 +47,23 @@ const Filter = {
},
 
debounceKeydown: function debounceKeydown(e) {
if ([
13, // enter
16, // shift
17, // ctrl
18, // alt
20, // caps lock
37, // left arrow
38, // up arrow
39, // right arrow
40, // down arrow
91, // left window
92, // right window
93, // select
].indexOf(e.detail.which || e.detail.keyCode) > -1) return;
if (
[
13, // enter
16, // shift
17, // ctrl
18, // alt
20, // caps lock
37, // left arrow
38, // up arrow
39, // right arrow
40, // down arrow
91, // left window
92, // right window
93, // select
].indexOf(e.detail.which || e.detail.keyCode) > -1
)
return;
 
if (this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(this.keydown.bind(this, e), 200);
Loading
Loading
@@ -87,7 +90,7 @@ const Filter = {
 
this.hook.trigger.removeEventListener('keydown.dl', this.eventWrapper.debounceKeydown);
this.hook.trigger.removeEventListener('mousedown.dl', this.eventWrapper.debounceKeydown);
}
},
};
 
export default Filter;
Loading
Loading
@@ -36,8 +36,8 @@ const InputSetter = {
const inputAttribute = config.inputAttribute;
 
if (input.hasAttribute(inputAttribute)) return input.setAttribute(inputAttribute, newValue);
if (input.tagName === 'INPUT') return input.value = newValue;
return input.textContent = newValue;
if (input.tagName === 'INPUT') return (input.value = newValue);
return (input.textContent = newValue);
},
 
destroy() {
Loading
Loading
Loading
Loading
@@ -5,7 +5,12 @@ import { DATA_TRIGGER, DATA_DROPDOWN, TEMPLATE_REGEX } from './constants';
 
const utils = {
toCamelCase(attr) {
return this.camelize(attr.split('-').slice(1).join(' '));
return this.camelize(
attr
.split('-')
.slice(1)
.join(' '),
);
},
 
template(templateString, data) {
Loading
Loading
@@ -17,9 +22,11 @@ const utils = {
},
 
camelize(str) {
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
}).replace(/\s+/g, '');
return str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
})
.replace(/\s+/g, '');
},
 
closest(thisTag, stopTag) {
Loading
Loading
<script>
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import environmentTable from '../components/environments_table.vue';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import environmentTable from '../components/environments_table.vue';
 
export default {
components: {
environmentTable,
tablePagination,
export default {
components: {
environmentTable,
tablePagination,
},
props: {
isLoading: {
type: Boolean,
required: true,
},
props: {
isLoading: {
type: Boolean,
required: true,
},
environments: {
type: Array,
required: true,
},
pagination: {
type: Object,
required: true,
},
canCreateDeployment: {
type: Boolean,
required: true,
},
canReadEnvironment: {
type: Boolean,
required: true,
},
environments: {
type: Array,
required: true,
},
methods: {
onChangePage(page) {
this.$emit('onChangePage', page);
},
pagination: {
type: Object,
required: true,
},
};
canCreateDeployment: {
type: Boolean,
required: true,
},
canReadEnvironment: {
type: Boolean,
required: true,
},
},
methods: {
onChangePage(page) {
this.$emit('onChangePage', page);
},
},
};
</script>
 
<template>
Loading
Loading
<script>
export default {
name: 'EnvironmentsEmptyState',
props: {
newPath: {
type: String,
required: true,
},
canCreateEnvironment: {
type: Boolean,
required: true,
},
helpPath: {
type: String,
required: true,
},
export default {
name: 'EnvironmentsEmptyState',
props: {
newPath: {
type: String,
required: true,
},
};
canCreateEnvironment: {
type: Boolean,
required: true,
},
helpPath: {
type: String,
required: true,
},
},
};
</script>
<template>
<div class="blank-state-row">
Loading
Loading
Loading
Loading
@@ -60,11 +60,9 @@ export default {
>
<span>
<icon name="play" />
<i
class="fa fa-caret-down"
aria-hidden="true"
>
</i>
<icon
name="chevron-down"
/>
<gl-loading-icon v-if="isLoading" />
</span>
</button>
Loading
Loading
Loading
Loading
@@ -4,6 +4,7 @@ import _ from 'underscore';
import tooltip from '~/vue_shared/directives/tooltip';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { humanize } from '~/lib/utils/text_utility';
import Icon from '~/vue_shared/components/icon.vue';
import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import StopComponent from './environment_stop.vue';
Loading
Loading
@@ -24,6 +25,7 @@ export default {
components: {
UserAvatarLink,
CommitComponent,
Icon,
ActionsComponent,
ExternalUrlComponent,
StopComponent,
Loading
Loading
@@ -448,6 +450,10 @@ export default {
this.canRetry
);
},
folderIconName() {
return this.model.isOpen ? 'chevron-down' : 'chevron-right';
},
},
 
methods: {
Loading
Loading
@@ -494,27 +500,15 @@ export default {
role="button"
@click="onClickFolder">
 
<span class="folder-icon">
<i
v-show="model.isOpen"
class="fa fa-caret-down"
aria-hidden="true"
>
</i>
<i
v-show="!model.isOpen"
class="fa fa-caret-right"
aria-hidden="true"
>
</i>
</span>
<icon
:name="folderIconName"
class="folder-icon"
/>
 
<span class="folder-icon">
<i
class="fa fa-folder"
aria-hidden="true">
</i>
</span>
<icon
name="folder"
class="folder-icon"
/>
 
<span>
{{ model.folderName }}
Loading
Loading
Loading
Loading
@@ -38,7 +38,9 @@ export default {
 
computed: {
title() {
return this.isLastDeployment ? s__('Environments|Re-deploy to environment') : s__('Environments|Rollback environment');
return this.isLastDeployment
? s__('Environments|Re-deploy to environment')
: s__('Environments|Rollback environment');
},
},
 
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