Merge branch 'master' into 46971-extra-whitespace
* master: (32 commits) Update CHANGELOG.md for 10.8.3 Update "col-xs" usage to bootstrap4 Add missing usage_ping_enabled to API settings Make Repository#blob_data_at a public method Fix UI broken in line profiling modal due to Bootstrap 4 Only preload member records for the relevant projects/groups/user in projects API Fix after sign-in with Google button Fix a wrong link reference in docs Simplify spec: `2.times.each` -> `2.times` Replace grape-route-helpers with our own grape-path-helpers Add archived param to the json response Consider we might have prefix for stable branches Convert spec/javascripts/.eslintrc to yml format as well Remove version lock on awesome_print dependency Fix import project by url layout Fix missing timeout value in object storage pre-authorization call fix last lints disable no-multi-assign fix `spaced-comment` remove unused createComponentWithMixin from vue spec helpers ...
This commit is contained in:
commit
25cc1dde9d
78 changed files with 892 additions and 993 deletions
56
.eslintrc
56
.eslintrc
|
@ -1,56 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-base",
|
||||
"plugin:vue/recommended"
|
||||
],
|
||||
"globals": {
|
||||
"__webpack_public_path__": true,
|
||||
"gl": false,
|
||||
"gon": false,
|
||||
"localStorage": false
|
||||
},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
},
|
||||
"plugins": [
|
||||
"filenames",
|
||||
"import",
|
||||
"html",
|
||||
"promise"
|
||||
],
|
||||
"settings": {
|
||||
"html/html-extensions": [".html", ".html.raw"],
|
||||
"import/resolver": {
|
||||
"webpack": {
|
||||
"config": "./config/webpack.config.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"filenames/match-regex": [2, "^[a-z0-9_]+$"],
|
||||
"import/no-commonjs": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 1 }],
|
||||
"promise/catch-or-return": "error",
|
||||
"no-underscore-dangle": ["error", { "allow": ["__", "_links"] }],
|
||||
"no-mixed-operators": 0,
|
||||
"space-before-function-paren": 0,
|
||||
"curly": 0,
|
||||
"arrow-parens": 0,
|
||||
"vue/html-self-closing": [
|
||||
"error",
|
||||
{
|
||||
"html": {
|
||||
"void": "always",
|
||||
"normal": "never",
|
||||
"component": "always"
|
||||
},
|
||||
"svg": "always",
|
||||
"math": "always"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
77
.eslintrc.yml
Normal file
77
.eslintrc.yml
Normal file
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
env:
|
||||
browser: true
|
||||
es6: true
|
||||
extends:
|
||||
- airbnb-base
|
||||
- plugin:vue/recommended
|
||||
globals:
|
||||
__webpack_public_path__: true
|
||||
gl: false
|
||||
gon: false
|
||||
localStorage: false
|
||||
parserOptions:
|
||||
parser: babel-eslint
|
||||
plugins:
|
||||
- filenames
|
||||
- import
|
||||
- html
|
||||
- promise
|
||||
settings:
|
||||
html/html-extensions:
|
||||
- ".html"
|
||||
- ".html.raw"
|
||||
import/resolver:
|
||||
webpack:
|
||||
config: "./config/webpack.config.js"
|
||||
rules:
|
||||
filenames/match-regex:
|
||||
- error
|
||||
- "^[a-z0-9_]+$"
|
||||
import/no-commonjs: error
|
||||
no-multiple-empty-lines:
|
||||
- error
|
||||
- max: 1
|
||||
promise/catch-or-return: error
|
||||
no-underscore-dangle:
|
||||
- error
|
||||
- allow:
|
||||
- __
|
||||
- _links
|
||||
no-mixed-operators: off
|
||||
vue/html-self-closing:
|
||||
- error
|
||||
- html:
|
||||
void: always
|
||||
normal: never
|
||||
component: always
|
||||
svg: always
|
||||
math: always
|
||||
## Conflicting rules with prettier:
|
||||
space-before-function-paren: off
|
||||
curly: off
|
||||
arrow-parens: off
|
||||
function-paren-newline: off
|
||||
object-curly-newline: off
|
||||
padded-blocks: off
|
||||
# Disabled for now, to make the eslint 3 -> eslint 4 update smoother
|
||||
## Indent rule. We are using the old for now: https://eslint.org/docs/user-guide/migrating-to-4.0.0#indent-rewrite
|
||||
indent: off
|
||||
indent-legacy:
|
||||
- error
|
||||
- 2
|
||||
- SwitchCase: 1
|
||||
VariableDeclarator: 1
|
||||
outerIIFEBody: 1
|
||||
FunctionDeclaration:
|
||||
parameters: 1
|
||||
body: 1
|
||||
FunctionExpression:
|
||||
parameters: 1
|
||||
body: 1
|
||||
## Destructuring: https://eslint.org/docs/rules/prefer-destructuring
|
||||
prefer-destructuring: off
|
||||
## no-restricted-globals: https://eslint.org/docs/rules/no-restricted-globals
|
||||
no-restricted-globals: off
|
||||
## no-multi-assign: https://eslint.org/docs/rules/no-multi-assign
|
||||
no-multi-assign: off
|
|
@ -591,7 +591,7 @@ ee_compat_check:
|
|||
except:
|
||||
- master
|
||||
- tags
|
||||
- /^[\d-]+-stable(-ee)?/
|
||||
- /[\d-]+-stable(-ee)?/
|
||||
- /^security-/
|
||||
- branches@gitlab-org/gitlab-ee
|
||||
- branches@gitlab/gitlab-ee
|
||||
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -2,6 +2,20 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.8.3 (2018-05-30)
|
||||
|
||||
### Fixed (4 changes)
|
||||
|
||||
- Replace Gitlab::REVISION with Gitlab.revision and handle installations without a .git directory. !19125
|
||||
- Fix encoding of branch names on compare and new merge request page. !19143
|
||||
- Fix remote mirror database inconsistencies when upgrading from EE to CE. !19196
|
||||
- Fix local storage not being cleared after creating a new issue.
|
||||
|
||||
### Performance (1 change)
|
||||
|
||||
- Memoize Gitlab::Database.version.
|
||||
|
||||
|
||||
## 10.8.2 (2018-05-28)
|
||||
|
||||
### Security (3 changes)
|
||||
|
|
6
Gemfile
6
Gemfile
|
@ -28,7 +28,7 @@ gem 'mysql2', '~> 0.4.10', group: :mysql
|
|||
gem 'pg', '~> 0.18.2', group: :postgres
|
||||
|
||||
gem 'rugged', '~> 0.27'
|
||||
gem 'grape-route-helpers', '~> 2.1.0'
|
||||
gem 'grape-path-helpers', '~> 1.0'
|
||||
|
||||
gem 'faraday', '~> 0.12'
|
||||
|
||||
|
@ -219,7 +219,7 @@ gem 'asana', '~> 0.6.0'
|
|||
gem 'ruby-fogbugz', '~> 0.2.1'
|
||||
|
||||
# Kubernetes integration
|
||||
gem 'kubeclient', '~> 3.0'
|
||||
gem 'kubeclient', '~> 3.1.0'
|
||||
|
||||
# Sanitize user input
|
||||
gem 'sanitize', '~> 2.0'
|
||||
|
@ -320,7 +320,7 @@ group :development, :test do
|
|||
gem 'pry-byebug', '~> 3.4.1', platform: :mri
|
||||
gem 'pry-rails', '~> 0.3.4'
|
||||
|
||||
gem 'awesome_print', '~> 1.8.0', require: false
|
||||
gem 'awesome_print', require: false
|
||||
gem 'fuubar', '~> 2.2.0'
|
||||
|
||||
gem 'database_cleaner', '~> 1.5.0'
|
||||
|
|
24
Gemfile.lock
24
Gemfile.lock
|
@ -168,7 +168,7 @@ GEM
|
|||
diff-lcs (1.3)
|
||||
diffy (3.1.0)
|
||||
docile (1.1.5)
|
||||
domain_name (0.5.20170404)
|
||||
domain_name (0.5.20180417)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (4.3.2)
|
||||
railties (>= 4.2)
|
||||
|
@ -348,7 +348,7 @@ GEM
|
|||
signet (~> 0.7)
|
||||
gpgme (2.0.13)
|
||||
mini_portile2 (~> 2.1)
|
||||
grape (1.0.2)
|
||||
grape (1.0.3)
|
||||
activesupport
|
||||
builder
|
||||
mustermann-grape (~> 1.0.0)
|
||||
|
@ -358,10 +358,10 @@ GEM
|
|||
grape-entity (0.7.1)
|
||||
activesupport (>= 4.0)
|
||||
multi_json (>= 1.3.2)
|
||||
grape-route-helpers (2.1.0)
|
||||
activesupport
|
||||
grape (>= 0.16.0)
|
||||
rake
|
||||
grape-path-helpers (1.0.1)
|
||||
activesupport (~> 4)
|
||||
grape (~> 1.0)
|
||||
rake (~> 12)
|
||||
grape_logging (1.7.0)
|
||||
grape
|
||||
grpc (1.11.0)
|
||||
|
@ -446,9 +446,9 @@ GEM
|
|||
knapsack (1.16.0)
|
||||
rake
|
||||
timecop (>= 0.1.0)
|
||||
kubeclient (3.0.0)
|
||||
kubeclient (3.1.0)
|
||||
http (~> 2.2.2)
|
||||
recursive-open-struct (~> 1.0.4)
|
||||
recursive-open-struct (~> 1.0, >= 1.0.4)
|
||||
rest-client (~> 2.0)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
|
@ -698,7 +698,7 @@ GEM
|
|||
re2 (1.1.1)
|
||||
recaptcha (3.0.0)
|
||||
json
|
||||
recursive-open-struct (1.0.5)
|
||||
recursive-open-struct (1.1.0)
|
||||
redcarpet (3.4.0)
|
||||
redis (3.3.5)
|
||||
redis-actionpack (5.0.2)
|
||||
|
@ -977,7 +977,7 @@ DEPENDENCIES
|
|||
asciidoctor-plantuml (= 0.0.8)
|
||||
asset_sync (~> 2.4)
|
||||
attr_encrypted (~> 3.1.0)
|
||||
awesome_print (~> 1.8.0)
|
||||
awesome_print
|
||||
babosa (~> 1.0.2)
|
||||
base32 (~> 0.3.0)
|
||||
batch-loader (~> 1.2.1)
|
||||
|
@ -1049,7 +1049,7 @@ DEPENDENCIES
|
|||
gpgme
|
||||
grape (~> 1.0)
|
||||
grape-entity (~> 0.7.1)
|
||||
grape-route-helpers (~> 2.1.0)
|
||||
grape-path-helpers (~> 1.0)
|
||||
grape_logging (~> 1.7)
|
||||
grpc (~> 1.11.0)
|
||||
haml_lint (~> 0.26.0)
|
||||
|
@ -1067,7 +1067,7 @@ DEPENDENCIES
|
|||
jwt (~> 1.5.6)
|
||||
kaminari (~> 1.0)
|
||||
knapsack (~> 1.16)
|
||||
kubeclient (~> 3.0)
|
||||
kubeclient (~> 3.1.0)
|
||||
letter_opener_web (~> 1.3.0)
|
||||
license_finder (~> 3.1)
|
||||
licensee (~> 8.9)
|
||||
|
|
|
@ -41,10 +41,10 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
|
|||
template: `
|
||||
<section class="empty-state">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 order-sm-last">
|
||||
<div class="col-12 col-md-6 order-md-last">
|
||||
<aside class="svg-content"><img :src="emptyStateSvg"/></aside>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 order-sm-first">
|
||||
<div class="col-12 col-md-6 order-md-first">
|
||||
<div class="text-content">
|
||||
<h4>{{ contents.title }}</h4>
|
||||
<p v-html="contents.content"></p>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* global ListIssue */
|
||||
|
||||
import Vue from 'vue';
|
||||
import bp from '../../../breakpoints';
|
||||
import ModalStore from '../../stores/modal_store';
|
||||
|
@ -56,8 +54,11 @@ gl.issueBoards.ModalList = Vue.extend({
|
|||
scrollHandler() {
|
||||
const currentPage = Math.floor(this.issues.length / this.perPage);
|
||||
|
||||
if ((this.scrollTop() > this.scrollHeight() - 100) && !this.loadingNewPage
|
||||
&& currentPage === this.page) {
|
||||
if (
|
||||
this.scrollTop() > this.scrollHeight() - 100 &&
|
||||
!this.loadingNewPage &&
|
||||
currentPage === this.page
|
||||
) {
|
||||
this.loadingNewPage = true;
|
||||
this.page += 1;
|
||||
}
|
||||
|
|
|
@ -1,71 +1,69 @@
|
|||
<script>
|
||||
/* global ListIssue */
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import eventHub from '../eventhub';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
import Api from '../../api';
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import eventHub from '../eventhub';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
import Api from '../../api';
|
||||
|
||||
export default {
|
||||
name: 'BoardProjectSelect',
|
||||
components: {
|
||||
loadingIcon,
|
||||
export default {
|
||||
name: 'BoardProjectSelect',
|
||||
components: {
|
||||
loadingIcon,
|
||||
},
|
||||
props: {
|
||||
groupId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
props: {
|
||||
groupId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
selectedProject: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
selectedProjectName() {
|
||||
return this.selectedProject.name || 'Select a project';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
$(this.$refs.projectsDropdown).glDropdown({
|
||||
filterable: true,
|
||||
filterRemote: true,
|
||||
search: {
|
||||
fields: ['name_with_namespace'],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
selectedProject: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
selectedProjectName() {
|
||||
return this.selectedProject.name || 'Select a project';
|
||||
clicked: ({ $el, e }) => {
|
||||
e.preventDefault();
|
||||
this.selectedProject = {
|
||||
id: $el.data('project-id'),
|
||||
name: $el.data('project-name'),
|
||||
};
|
||||
eventHub.$emit('setSelectedProject', this.selectedProject);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
$(this.$refs.projectsDropdown).glDropdown({
|
||||
filterable: true,
|
||||
filterRemote: true,
|
||||
search: {
|
||||
fields: ['name_with_namespace'],
|
||||
},
|
||||
clicked: ({ $el, e }) => {
|
||||
e.preventDefault();
|
||||
this.selectedProject = {
|
||||
id: $el.data('project-id'),
|
||||
name: $el.data('project-name'),
|
||||
};
|
||||
eventHub.$emit('setSelectedProject', this.selectedProject);
|
||||
},
|
||||
selectable: true,
|
||||
data: (term, callback) => {
|
||||
this.loading = true;
|
||||
return Api.groupProjects(this.groupId, term, (projects) => {
|
||||
this.loading = false;
|
||||
callback(projects);
|
||||
});
|
||||
},
|
||||
renderRow(project) {
|
||||
return `
|
||||
selectable: true,
|
||||
data: (term, callback) => {
|
||||
this.loading = true;
|
||||
return Api.groupProjects(this.groupId, term, projects => {
|
||||
this.loading = false;
|
||||
callback(projects);
|
||||
});
|
||||
},
|
||||
renderRow(project) {
|
||||
return `
|
||||
<li>
|
||||
<a href='#' class='dropdown-menu-link' data-project-id="${project.id}" data-project-name="${project.name}">
|
||||
${_.escape(project.name)}
|
||||
</a>
|
||||
</li>
|
||||
`;
|
||||
},
|
||||
text: project => project.name,
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
text: project => project.name,
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* global monaco */
|
||||
import Disposable from './disposable';
|
||||
import eventHub from '../../eventhub';
|
||||
|
||||
|
|
|
@ -84,11 +84,11 @@ export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive
|
|||
});
|
||||
};
|
||||
|
||||
export const setFileMrChange = ({ state, commit }, { file, mrChange }) => {
|
||||
export const setFileMrChange = ({ commit }, { file, mrChange }) => {
|
||||
commit(types.SET_FILE_MERGE_REQUEST_CHANGE, { file, mrChange });
|
||||
};
|
||||
|
||||
export const getRawFileData = ({ state, commit, dispatch }, { path, baseSha }) => {
|
||||
export const getRawFileData = ({ state, commit }, { path, baseSha }) => {
|
||||
const file = state.entries[path];
|
||||
return new Promise((resolve, reject) => {
|
||||
service
|
||||
|
@ -156,7 +156,7 @@ export const setEditorPosition = ({ getters, commit }, { editorRow, editorColumn
|
|||
}
|
||||
};
|
||||
|
||||
export const setFileViewMode = ({ state, commit }, { file, viewMode }) => {
|
||||
export const setFileViewMode = ({ commit }, { file, viewMode }) => {
|
||||
commit(types.SET_FILE_VIEWMODE, { file, viewMode });
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import service from '../../services';
|
|||
import * as types from '../mutation_types';
|
||||
|
||||
export const getMergeRequestData = (
|
||||
{ commit, state, dispatch },
|
||||
{ commit, state },
|
||||
{ projectId, mergeRequestId, force = false } = {},
|
||||
) =>
|
||||
new Promise((resolve, reject) => {
|
||||
|
@ -32,7 +32,7 @@ export const getMergeRequestData = (
|
|||
});
|
||||
|
||||
export const getMergeRequestChanges = (
|
||||
{ commit, state, dispatch },
|
||||
{ commit, state },
|
||||
{ projectId, mergeRequestId, force = false } = {},
|
||||
) =>
|
||||
new Promise((resolve, reject) => {
|
||||
|
@ -58,7 +58,7 @@ export const getMergeRequestChanges = (
|
|||
});
|
||||
|
||||
export const getMergeRequestVersions = (
|
||||
{ commit, state, dispatch },
|
||||
{ commit, state },
|
||||
{ projectId, mergeRequestId, force = false } = {},
|
||||
) =>
|
||||
new Promise((resolve, reject) => {
|
||||
|
|
|
@ -7,10 +7,7 @@ import Poll from '../../../lib/utils/poll';
|
|||
|
||||
let eTagPoll;
|
||||
|
||||
export const getProjectData = (
|
||||
{ commit, state, dispatch },
|
||||
{ namespace, projectId, force = false } = {},
|
||||
) =>
|
||||
export const getProjectData = ({ commit, state }, { namespace, projectId, force = false } = {}) =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (!state.projects[`${namespace}/${projectId}`] || force) {
|
||||
commit(types.TOGGLE_LOADING, { entry: state });
|
||||
|
@ -40,10 +37,7 @@ export const getProjectData = (
|
|||
}
|
||||
});
|
||||
|
||||
export const getBranchData = (
|
||||
{ commit, state, dispatch },
|
||||
{ projectId, branchId, force = false } = {},
|
||||
) =>
|
||||
export const getBranchData = ({ commit, state }, { projectId, branchId, force = false } = {}) =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (
|
||||
typeof state.projects[`${projectId}`] === 'undefined' ||
|
||||
|
@ -78,7 +72,7 @@ export const getBranchData = (
|
|||
}
|
||||
});
|
||||
|
||||
export const refreshLastCommitData = ({ commit, state, dispatch }, { projectId, branchId } = {}) =>
|
||||
export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {}) =>
|
||||
service
|
||||
.getBranchData(projectId, branchId)
|
||||
.then(({ data }) => {
|
||||
|
@ -92,7 +86,7 @@ export const refreshLastCommitData = ({ commit, state, dispatch }, { projectId,
|
|||
flash(__('Error loading last commit.'), 'alert', document, null, false, true);
|
||||
});
|
||||
|
||||
export const pollSuccessCallBack = ({ commit, state, dispatch }, { data }) => {
|
||||
export const pollSuccessCallBack = ({ commit, state }, { data }) => {
|
||||
if (data.pipelines && data.pipelines.length) {
|
||||
const lastCommitHash =
|
||||
state.projects[state.currentProjectId].branches[state.currentBranchId].commit.id;
|
||||
|
|
|
@ -5,7 +5,7 @@ import * as types from '../mutation_types';
|
|||
import { findEntry } from '../utils';
|
||||
import FilesDecoratorWorker from '../workers/files_decorator_worker';
|
||||
|
||||
export const toggleTreeOpen = ({ commit, dispatch }, path) => {
|
||||
export const toggleTreeOpen = ({ commit }, path) => {
|
||||
commit(types.TOGGLE_TREE_OPEN, path);
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@ export const handleTreeEntryAction = ({ commit, dispatch }, row) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = state) => {
|
||||
export const getLastCommitData = ({ state, commit, dispatch }, tree = state) => {
|
||||
if (!tree || tree.lastCommitPath === null || !tree.lastCommitPath) return;
|
||||
|
||||
service
|
||||
|
@ -49,7 +49,7 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s
|
|||
.catch(() => flash('Error fetching log data.', 'alert', document, null, false, true));
|
||||
};
|
||||
|
||||
export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } = {}) =>
|
||||
export const getFiles = ({ state, commit }, { projectId, branchId } = {}) =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (!state.trees[`${projectId}/${branchId}`]) {
|
||||
const selectedProject = state.projects[projectId];
|
||||
|
|
|
@ -31,9 +31,9 @@ export const setLastCommitMessage = ({ rootState, commit }, data) => {
|
|||
const currentProject = rootState.projects[rootState.currentProjectId];
|
||||
const commitStats = data.stats
|
||||
? sprintf(__('with %{additions} additions, %{deletions} deletions.'), {
|
||||
additions: data.stats.additions, // eslint-disable-line indent
|
||||
deletions: data.stats.deletions, // eslint-disable-line indent
|
||||
}) // eslint-disable-line indent
|
||||
additions: data.stats.additions, // eslint-disable-line indent-legacy
|
||||
deletions: data.stats.deletions, // eslint-disable-line indent-legacy
|
||||
}) // eslint-disable-line indent-legacy
|
||||
: '';
|
||||
const commitMsg = sprintf(
|
||||
__('Your changes have been committed. Commit %{commitId} %{commitStats}'),
|
||||
|
@ -74,10 +74,7 @@ export const checkCommitStatus = ({ rootState }) =>
|
|||
),
|
||||
);
|
||||
|
||||
export const updateFilesAfterCommit = (
|
||||
{ commit, dispatch, state, rootState, rootGetters },
|
||||
{ data },
|
||||
) => {
|
||||
export const updateFilesAfterCommit = ({ commit, dispatch, rootState }, { data }) => {
|
||||
const selectedProject = rootState.projects[rootState.currentProjectId];
|
||||
const lastCommit = {
|
||||
commit_path: `${selectedProject.web_url}/commit/${data.id}`,
|
||||
|
|
|
@ -84,7 +84,7 @@ export default class Job {
|
|||
If the browser does not support position sticky, it returns the position as static.
|
||||
If the browser does support sticky, then we allow the browser to handle it, if not
|
||||
then we use a polyfill
|
||||
**/
|
||||
*/
|
||||
if (this.$topBar.css('position') !== 'static') return;
|
||||
|
||||
StickyFill.add(this.$topBar);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* global Build */
|
||||
|
||||
import Visibility from 'visibilityjs';
|
||||
import Flash from '../flash';
|
||||
import Poll from '../lib/utils/poll';
|
||||
|
@ -50,7 +48,8 @@ export default class JobMediator {
|
|||
}
|
||||
|
||||
getJob() {
|
||||
return this.service.getJob()
|
||||
return this.service
|
||||
.getJob()
|
||||
.then(response => this.successCallback(response))
|
||||
.catch(() => this.errorCallback());
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ delete window.translations;
|
|||
Translates `text`
|
||||
@param text The text to be translated
|
||||
@returns {String} The translated text
|
||||
**/
|
||||
*/
|
||||
const gettext = locale.gettext.bind(locale);
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ const gettext = locale.gettext.bind(locale);
|
|||
@param pluralText Plural text to translate (eg. '%d days')
|
||||
@param count Number to decide which translation to use (eg. 2)
|
||||
@returns {String} Translated text with the number replaced (eg. '2 days')
|
||||
**/
|
||||
*/
|
||||
const ngettext = (text, pluralText, count) => {
|
||||
const translated = locale.ngettext(text, pluralText, count).replace(/%d/g, count).split('|');
|
||||
|
||||
|
@ -38,7 +38,7 @@ const ngettext = (text, pluralText, count) => {
|
|||
(eg. 'Context')
|
||||
@param key Is the dynamic variable you want to be translated
|
||||
@returns {String} Translated context based text
|
||||
**/
|
||||
*/
|
||||
const pgettext = (keyOrContext, key) => {
|
||||
const normalizedKey = key ? `${keyOrContext}|${key}` : keyOrContext;
|
||||
const translated = gettext(normalizedKey).split('|');
|
||||
|
|
|
@ -10,7 +10,7 @@ import _ from 'underscore';
|
|||
|
||||
@see https://ruby-doc.org/core-2.3.3/Kernel.html#method-i-sprintf
|
||||
@see https://gitlab.com/gitlab-org/gitlab-ce/issues/37992
|
||||
**/
|
||||
*/
|
||||
export default (input, parameters, escapeParameters = true) => {
|
||||
let output = input;
|
||||
|
||||
|
|
|
@ -427,7 +427,7 @@ export default class MergeRequestTabs {
|
|||
If the browser does not support position sticky, it returns the position as static.
|
||||
If the browser does support sticky, then we allow the browser to handle it, if not
|
||||
then we default back to Bootstraps affix
|
||||
**/
|
||||
*/
|
||||
if ($tabs.css('position') !== 'static') return;
|
||||
|
||||
const $diffTabs = $('#diff-notes-app');
|
||||
|
|
|
@ -12,20 +12,13 @@ import { isInViewport, scrollToElement } from '../../lib/utils/common_utils';
|
|||
|
||||
let eTagPoll;
|
||||
|
||||
export const setNotesData = ({ commit }, data) =>
|
||||
commit(types.SET_NOTES_DATA, data);
|
||||
export const setNoteableData = ({ commit }, data) =>
|
||||
commit(types.SET_NOTEABLE_DATA, data);
|
||||
export const setUserData = ({ commit }, data) =>
|
||||
commit(types.SET_USER_DATA, data);
|
||||
export const setLastFetchedAt = ({ commit }, data) =>
|
||||
commit(types.SET_LAST_FETCHED_AT, data);
|
||||
export const setInitialNotes = ({ commit }, data) =>
|
||||
commit(types.SET_INITIAL_NOTES, data);
|
||||
export const setTargetNoteHash = ({ commit }, data) =>
|
||||
commit(types.SET_TARGET_NOTE_HASH, data);
|
||||
export const toggleDiscussion = ({ commit }, data) =>
|
||||
commit(types.TOGGLE_DISCUSSION, data);
|
||||
export const setNotesData = ({ commit }, data) => commit(types.SET_NOTES_DATA, data);
|
||||
export const setNoteableData = ({ commit }, data) => commit(types.SET_NOTEABLE_DATA, data);
|
||||
export const setUserData = ({ commit }, data) => commit(types.SET_USER_DATA, data);
|
||||
export const setLastFetchedAt = ({ commit }, data) => commit(types.SET_LAST_FETCHED_AT, data);
|
||||
export const setInitialNotes = ({ commit }, data) => commit(types.SET_INITIAL_NOTES, data);
|
||||
export const setTargetNoteHash = ({ commit }, data) => commit(types.SET_TARGET_NOTE_HASH, data);
|
||||
export const toggleDiscussion = ({ commit }, data) => commit(types.TOGGLE_DISCUSSION, data);
|
||||
|
||||
export const fetchNotes = ({ commit }, path) =>
|
||||
service
|
||||
|
@ -69,20 +62,14 @@ export const createNewNote = ({ commit }, { endpoint, data }) =>
|
|||
return res;
|
||||
});
|
||||
|
||||
export const removePlaceholderNotes = ({ commit }) =>
|
||||
commit(types.REMOVE_PLACEHOLDER_NOTES);
|
||||
export const removePlaceholderNotes = ({ commit }) => commit(types.REMOVE_PLACEHOLDER_NOTES);
|
||||
|
||||
export const toggleResolveNote = (
|
||||
{ commit },
|
||||
{ endpoint, isResolved, discussion },
|
||||
) =>
|
||||
export const toggleResolveNote = ({ commit }, { endpoint, isResolved, discussion }) =>
|
||||
service
|
||||
.toggleResolveNote(endpoint, isResolved)
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
const mutationType = discussion
|
||||
? types.UPDATE_DISCUSSION
|
||||
: types.UPDATE_NOTE;
|
||||
const mutationType = discussion ? types.UPDATE_DISCUSSION : types.UPDATE_NOTE;
|
||||
|
||||
commit(mutationType, res);
|
||||
});
|
||||
|
@ -114,7 +101,7 @@ export const reopenIssue = ({ commit, dispatch, state }) => {
|
|||
export const toggleStateButtonLoading = ({ commit }, value) =>
|
||||
commit(types.TOGGLE_STATE_BUTTON_LOADING, value);
|
||||
|
||||
export const emitStateChangedEvent = ({ commit, getters }, data) => {
|
||||
export const emitStateChangedEvent = ({ getters }, data) => {
|
||||
const event = new CustomEvent('issuable_vue_app:change', {
|
||||
detail: {
|
||||
data,
|
||||
|
@ -179,10 +166,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
|
|||
|
||||
loadAwardsHandler()
|
||||
.then(awardsHandler => {
|
||||
awardsHandler.addAwardToEmojiBar(
|
||||
votesBlock,
|
||||
commandsChanges.emoji_award,
|
||||
);
|
||||
awardsHandler.addAwardToEmojiBar(votesBlock, commandsChanges.emoji_award);
|
||||
awardsHandler.scrollToAwards();
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -194,10 +178,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
|
|||
});
|
||||
}
|
||||
|
||||
if (
|
||||
commandsChanges.spend_time != null ||
|
||||
commandsChanges.time_estimate != null
|
||||
) {
|
||||
if (commandsChanges.spend_time != null || commandsChanges.time_estimate != null) {
|
||||
sidebarTimeTrackingEventHub.$emit('timeTrackingUpdated', res);
|
||||
}
|
||||
}
|
||||
|
@ -218,14 +199,8 @@ const pollSuccessCallBack = (resp, commit, state, getters) => {
|
|||
resp.notes.forEach(note => {
|
||||
if (notesById[note.id]) {
|
||||
commit(types.UPDATE_NOTE, note);
|
||||
} else if (
|
||||
note.type === constants.DISCUSSION_NOTE ||
|
||||
note.type === constants.DIFF_NOTE
|
||||
) {
|
||||
const discussion = utils.findNoteObjectById(
|
||||
state.notes,
|
||||
note.discussion_id,
|
||||
);
|
||||
} else if (note.type === constants.DISCUSSION_NOTE || note.type === constants.DIFF_NOTE) {
|
||||
const discussion = utils.findNoteObjectById(state.notes, note.discussion_id);
|
||||
|
||||
if (discussion) {
|
||||
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
|
||||
|
@ -249,11 +224,8 @@ export const poll = ({ commit, state, getters }) => {
|
|||
method: 'poll',
|
||||
data: state,
|
||||
successCallback: resp =>
|
||||
resp
|
||||
.json()
|
||||
.then(data => pollSuccessCallBack(data, commit, state, getters)),
|
||||
errorCallback: () =>
|
||||
Flash('Something went wrong while fetching latest comments.'),
|
||||
resp.json().then(data => pollSuccessCallBack(data, commit, state, getters)),
|
||||
errorCallback: () => Flash('Something went wrong while fetching latest comments.'),
|
||||
});
|
||||
|
||||
if (!Visibility.hidden()) {
|
||||
|
@ -292,14 +264,11 @@ export const fetchData = ({ commit, state, getters }) => {
|
|||
.catch(() => Flash('Something went wrong while fetching latest comments.'));
|
||||
};
|
||||
|
||||
export const toggleAward = (
|
||||
{ commit, state, getters, dispatch },
|
||||
{ awardName, noteId },
|
||||
) => {
|
||||
export const toggleAward = ({ commit, getters }, { awardName, noteId }) => {
|
||||
commit(types.TOGGLE_AWARD, { awardName, note: getters.notesById[noteId] });
|
||||
};
|
||||
|
||||
export const toggleAwardRequest = ({ commit, getters, dispatch }, data) => {
|
||||
export const toggleAwardRequest = ({ dispatch }, data) => {
|
||||
const { endpoint, awardName } = data;
|
||||
|
||||
return service
|
||||
|
|
|
@ -5,7 +5,7 @@ import $ from 'jquery';
|
|||
*
|
||||
* Toggling this checkbox adds/removes a `remember_me` parameter to the
|
||||
* login buttons' href, which is passed on to the omniauth callback.
|
||||
**/
|
||||
*/
|
||||
|
||||
export default class OAuthRememberMe {
|
||||
constructor(opts = {}) {
|
||||
|
|
|
@ -37,7 +37,7 @@ const IGNORE_URLS = [
|
|||
/extensions\//i,
|
||||
/^chrome:\/\//i,
|
||||
// Other plugins
|
||||
/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
|
||||
/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
|
||||
/webappstoolbarba\.texthelp\.com\//i,
|
||||
/metrics\.itunes\.apple\.com\.edgesuite\.net\//i,
|
||||
];
|
||||
|
|
|
@ -7,9 +7,10 @@ Vue.use(VueResource);
|
|||
export const fetchRepos = ({ commit, state }) => {
|
||||
commit(types.TOGGLE_MAIN_LOADING);
|
||||
|
||||
return Vue.http.get(state.endpoint)
|
||||
return Vue.http
|
||||
.get(state.endpoint)
|
||||
.then(res => res.json())
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
commit(types.TOGGLE_MAIN_LOADING);
|
||||
commit(types.SET_REPOS_LIST, response);
|
||||
});
|
||||
|
@ -18,19 +19,20 @@ export const fetchRepos = ({ commit, state }) => {
|
|||
export const fetchList = ({ commit }, { repo, page }) => {
|
||||
commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
|
||||
|
||||
return Vue.http.get(repo.tagsPath, { params: { page } })
|
||||
.then((response) => {
|
||||
const headers = response.headers;
|
||||
return Vue.http.get(repo.tagsPath, { params: { page } }).then(response => {
|
||||
const headers = response.headers;
|
||||
|
||||
return response.json().then((resp) => {
|
||||
commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
|
||||
commit(types.SET_REGISTRY_LIST, { repo, resp, headers });
|
||||
});
|
||||
return response.json().then(resp => {
|
||||
commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
|
||||
commit(types.SET_REGISTRY_LIST, { repo, resp, headers });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export const deleteRepo = ({ commit }, repo) => Vue.http.delete(repo.destroyPath);
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export const deleteRegistry = ({ commit }, image) => Vue.http.delete(image.destroyPath);
|
||||
|
||||
export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
|
||||
|
|
|
@ -13,7 +13,7 @@ export default (Vue) => {
|
|||
|
||||
@param text The text to be translated
|
||||
@returns {String} The translated text
|
||||
**/
|
||||
*/
|
||||
__,
|
||||
/**
|
||||
Translate the text with a number
|
||||
|
@ -24,7 +24,7 @@ export default (Vue) => {
|
|||
@param pluralText Plural text to translate (eg. '%d days')
|
||||
@param count Number to decide which translation to use (eg. 2)
|
||||
@returns {String} Translated text with the number replaced (eg. '2 days')
|
||||
**/
|
||||
*/
|
||||
n__,
|
||||
/**
|
||||
Translate context based text
|
||||
|
@ -36,7 +36,7 @@ export default (Vue) => {
|
|||
(eg. 'Context')
|
||||
@param key Is the dynamic variable you want to be translated
|
||||
@returns {String} Translated context based text
|
||||
**/
|
||||
*/
|
||||
s__,
|
||||
sprintf,
|
||||
},
|
||||
|
|
|
@ -74,12 +74,6 @@ body.modal-open {
|
|||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
.modal-full {
|
||||
width: 98%;
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
background-color: $black-transparent;
|
||||
z-index: 2100;
|
||||
|
|
31
app/controllers/groups/shared_projects_controller.rb
Normal file
31
app/controllers/groups/shared_projects_controller.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
module Groups
|
||||
class SharedProjectsController < Groups::ApplicationController
|
||||
respond_to :json
|
||||
before_action :group
|
||||
skip_cross_project_access_check :index
|
||||
|
||||
def index
|
||||
shared_projects = GroupProjectsFinder.new(
|
||||
group: group,
|
||||
current_user: current_user,
|
||||
params: finder_params,
|
||||
options: { only_shared: true }
|
||||
).execute
|
||||
serializer = GroupChildSerializer.new(current_user: current_user)
|
||||
.with_pagination(request, response)
|
||||
|
||||
render json: serializer.represent(shared_projects)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def finder_params
|
||||
@finder_params ||= begin
|
||||
# Make the `search` param consistent for the frontend,
|
||||
# which will be using `filter`.
|
||||
params[:search] ||= params[:filter] if params[:filter]
|
||||
params.permit(:sort, :search)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -957,6 +957,14 @@ class Repository
|
|||
remote_branch: merge_request.target_branch)
|
||||
end
|
||||
|
||||
def blob_data_at(sha, path)
|
||||
blob = blob_at(sha, path)
|
||||
return unless blob
|
||||
|
||||
blob.load_all_data!
|
||||
blob.data
|
||||
end
|
||||
|
||||
def squash(user, merge_request)
|
||||
raw.squash(user, merge_request.id, branch: merge_request.target_branch,
|
||||
start_sha: merge_request.diff_start_sha,
|
||||
|
@ -979,14 +987,6 @@ class Repository
|
|||
::Commit.new(commit, @project) if commit
|
||||
end
|
||||
|
||||
def blob_data_at(sha, path)
|
||||
blob = blob_at(sha, path)
|
||||
return unless blob
|
||||
|
||||
blob.load_all_data!
|
||||
blob.data
|
||||
end
|
||||
|
||||
def cache
|
||||
@cache ||= Gitlab::RepositoryCache.new(self)
|
||||
end
|
||||
|
|
|
@ -206,10 +206,11 @@ class Service < ActiveRecord::Base
|
|||
args.each do |arg|
|
||||
class_eval %{
|
||||
def #{arg}?
|
||||
# '!!' is used because nil or empty string is converted to nil
|
||||
if Gitlab.rails5?
|
||||
!ActiveModel::Type::Boolean::FALSE_VALUES.include?(#{arg})
|
||||
!!ActiveRecord::Type::Boolean.new.cast(#{arg})
|
||||
else
|
||||
ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(#{arg})
|
||||
!!ActiveRecord::Type::Boolean.new.type_cast_from_database(#{arg})
|
||||
end
|
||||
end
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class GroupChildEntity < Grape::Entity
|
|||
end
|
||||
|
||||
# Project only attributes
|
||||
expose :star_count,
|
||||
expose :star_count, :archived,
|
||||
if: lambda { |_instance, _options| project? }
|
||||
|
||||
# Group only attributes
|
||||
|
|
|
@ -11,6 +11,7 @@ module ObjectStorage
|
|||
ObjectStorageUnavailable = Class.new(StandardError)
|
||||
|
||||
DIRECT_UPLOAD_TIMEOUT = 4.hours
|
||||
DIRECT_UPLOAD_EXPIRE_OFFSET = 15.minutes
|
||||
TMP_UPLOAD_PATH = 'tmp/uploads'.freeze
|
||||
|
||||
module Store
|
||||
|
@ -174,11 +175,12 @@ module ObjectStorage
|
|||
id = [CarrierWave.generate_cache_id, SecureRandom.hex].join('-')
|
||||
upload_path = File.join(TMP_UPLOAD_PATH, id)
|
||||
connection = ::Fog::Storage.new(self.object_store_credentials)
|
||||
expire_at = Time.now + DIRECT_UPLOAD_TIMEOUT
|
||||
expire_at = Time.now + DIRECT_UPLOAD_TIMEOUT + DIRECT_UPLOAD_EXPIRE_OFFSET
|
||||
options = { 'Content-Type' => 'application/octet-stream' }
|
||||
|
||||
{
|
||||
ID: id,
|
||||
Timeout: DIRECT_UPLOAD_TIMEOUT,
|
||||
GetURL: connection.get_object_url(remote_store_path, upload_path, expire_at),
|
||||
DeleteURL: connection.delete_object_url(remote_store_path, upload_path, expire_at),
|
||||
StoreURL: connection.put_object_url(remote_store_path, upload_path, expire_at, options)
|
||||
|
|
|
@ -1,51 +1,49 @@
|
|||
- active_tab = local_assigns.fetch(:active_tab, 'blank')
|
||||
- f = local_assigns.fetch(:f)
|
||||
|
||||
.project-import.row
|
||||
.col-lg-12
|
||||
.form-group.import-btn-container.clearfix
|
||||
= f.label :visibility_level, class: 'label-light' do #the label here seems wrong
|
||||
Import project from
|
||||
.import-buttons
|
||||
- if gitlab_project_import_enabled?
|
||||
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
|
||||
= link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
|
||||
= icon('gitlab', text: 'GitLab export')
|
||||
%div
|
||||
- if github_import_enabled?
|
||||
= link_to new_import_github_path, class: 'btn js-import-github' do
|
||||
= icon('github', text: 'GitHub')
|
||||
%div
|
||||
- if bitbucket_import_enabled?
|
||||
= link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}" do
|
||||
= icon('bitbucket', text: 'Bitbucket')
|
||||
- unless bitbucket_import_configured?
|
||||
= render 'bitbucket_import_modal'
|
||||
%div
|
||||
- if gitlab_import_enabled?
|
||||
= link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do
|
||||
= icon('gitlab', text: 'GitLab.com')
|
||||
- unless gitlab_import_configured?
|
||||
= render 'gitlab_import_modal'
|
||||
%div
|
||||
- if google_code_import_enabled?
|
||||
= link_to new_import_google_code_path, class: 'btn import_google_code' do
|
||||
= icon('google', text: 'Google Code')
|
||||
%div
|
||||
- if fogbugz_import_enabled?
|
||||
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
|
||||
= icon('bug', text: 'Fogbugz')
|
||||
%div
|
||||
- if gitea_import_enabled?
|
||||
= link_to new_import_gitea_path, class: 'btn import_gitea' do
|
||||
= custom_icon('go_logo')
|
||||
Gitea
|
||||
%div
|
||||
- if git_import_enabled?
|
||||
%button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' } }
|
||||
= icon('git', text: 'Repo by URL')
|
||||
.col-lg-12
|
||||
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
|
||||
%hr
|
||||
= render "shared/import_form", f: f
|
||||
= render 'new_project_fields', f: f, project_name_id: "import-url-name"
|
||||
.project-import
|
||||
.form-group.import-btn-container.clearfix
|
||||
= f.label :visibility_level, class: 'label-light' do #the label here seems wrong
|
||||
Import project from
|
||||
.import-buttons
|
||||
- if gitlab_project_import_enabled?
|
||||
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
|
||||
= link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
|
||||
= icon('gitlab', text: 'GitLab export')
|
||||
%div
|
||||
- if github_import_enabled?
|
||||
= link_to new_import_github_path, class: 'btn js-import-github' do
|
||||
= icon('github', text: 'GitHub')
|
||||
%div
|
||||
- if bitbucket_import_enabled?
|
||||
= link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}" do
|
||||
= icon('bitbucket', text: 'Bitbucket')
|
||||
- unless bitbucket_import_configured?
|
||||
= render 'bitbucket_import_modal'
|
||||
%div
|
||||
- if gitlab_import_enabled?
|
||||
= link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do
|
||||
= icon('gitlab', text: 'GitLab.com')
|
||||
- unless gitlab_import_configured?
|
||||
= render 'gitlab_import_modal'
|
||||
%div
|
||||
- if google_code_import_enabled?
|
||||
= link_to new_import_google_code_path, class: 'btn import_google_code' do
|
||||
= icon('google', text: 'Google Code')
|
||||
%div
|
||||
- if fogbugz_import_enabled?
|
||||
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
|
||||
= icon('bug', text: 'Fogbugz')
|
||||
%div
|
||||
- if gitea_import_enabled?
|
||||
= link_to new_import_gitea_path, class: 'btn import_gitea' do
|
||||
= custom_icon('go_logo')
|
||||
Gitea
|
||||
%div
|
||||
- if git_import_enabled?
|
||||
%button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' } }
|
||||
= icon('git', text: 'Repo by URL')
|
||||
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
|
||||
%hr
|
||||
= render "shared/import_form", f: f
|
||||
= render 'new_project_fields', f: f, project_name_id: "import-url-name"
|
||||
|
|
|
@ -35,11 +35,10 @@
|
|||
%span (optional)
|
||||
= f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250
|
||||
|
||||
.form-group.visibility-level-setting
|
||||
= f.label :visibility_level, class: 'label-light' do
|
||||
Visibility Level
|
||||
= link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: 'Documentation for Visibility Level' }, target: '_blank', rel: 'noopener noreferrer'
|
||||
= render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false
|
||||
= f.label :visibility_level, class: 'label-light' do
|
||||
Visibility Level
|
||||
= link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: 'Documentation for Visibility Level' }, target: '_blank', rel: 'noopener noreferrer'
|
||||
= render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false
|
||||
|
||||
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
|
||||
= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel'
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
.row
|
||||
.col-sm-8.offset-sm-4.signin-with-google
|
||||
- if @authorize_url
|
||||
= link_to @authorize_url do
|
||||
= image_tag('auth_buttons/signin_with_google.png', width: '191px')
|
||||
= link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px'), @authorize_url)
|
||||
= _('or')
|
||||
= link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer')
|
||||
- else
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
|
||||
|
||||
.form-group.row.import-url-data
|
||||
.form-group.import-url-data
|
||||
= f.label :import_url, class: 'label-light' do
|
||||
%span
|
||||
= _('Git repository URL')
|
||||
|
||||
= f.text_field :import_url, autocomplete: 'off', class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git', required: true
|
||||
|
||||
.card.prepend-top-20
|
||||
%ul
|
||||
%li
|
||||
= _('The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>.').html_safe
|
||||
%li
|
||||
= _('If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.').html_safe
|
||||
%li
|
||||
= import_will_timeout_message(ci_cd_only)
|
||||
%li
|
||||
= import_svn_message(ci_cd_only)
|
||||
.info-well.prepend-top-20
|
||||
.well-segment
|
||||
%ul
|
||||
%li
|
||||
= _('The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>.').html_safe
|
||||
%li
|
||||
= _('If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.').html_safe
|
||||
%li
|
||||
= import_will_timeout_message(ci_cd_only)
|
||||
%li
|
||||
= import_svn_message(ci_cd_only)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- with_label = local_assigns.fetch(:with_label, true)
|
||||
|
||||
.form-group.row.visibility-level-setting
|
||||
.form-group.visibility-level-setting
|
||||
- if with_label
|
||||
= f.label :visibility_level, class: 'col-form-label col-sm-2' do
|
||||
Visibility Level
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.row.empty-state.text-center
|
||||
.col-xs-12
|
||||
.col-12
|
||||
.svg-130.prepend-top-default
|
||||
= image_tag 'illustrations/issue-dashboard_results-without-filter.svg'
|
||||
.col-xs-12
|
||||
.col-12
|
||||
.text-content
|
||||
%h4
|
||||
= _("Please select at least one filter to see results")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.row.empty-state
|
||||
.col-xs-12
|
||||
.col-12
|
||||
.svg-content
|
||||
= image_tag image_path
|
||||
.col-xs-12
|
||||
.col-12
|
||||
.text-content.text-center
|
||||
= yield
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: Replace Gitlab::REVISION with Gitlab.revision and handle installations without
|
||||
a .git directory
|
||||
merge_request: 19125
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix UI broken in line profiling modal due to Bootstrap 4
|
||||
merge_request: 19253
|
||||
author: Takuya Noguchi
|
||||
type: other
|
5
changelogs/unreleased/bump-kubeclient-version-3-1-0.yml
Normal file
5
changelogs/unreleased/bump-kubeclient-version-3-1-0.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Updates the version of kubeclient from 3.0 to 3.1.0
|
||||
merge_request: 19199
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Only preload member records for the relevant projects/groups/user in projects
|
||||
API
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix remote mirror database inconsistencies when upgrading from EE to CE
|
||||
merge_request: 19196
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/fix-missing-timeout.yml
Normal file
5
changelogs/unreleased/fix-missing-timeout.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Missing timeout value in object storage pre-authorization
|
||||
merge_request: 19201
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix after sign-in with Google button
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Memoize Gitlab::Database.version
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix local storage not being cleared after creating a new issue
|
||||
merge_request:
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/sh-use-grape-path-helpers.yml
Normal file
5
changelogs/unreleased/sh-use-grape-path-helpers.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Replace grape-route-helpers with our own grape-path-helpers
|
||||
merge_request:
|
||||
author:
|
||||
type: performance
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix encoding of branch names on compare and new merge request page
|
||||
merge_request: 19143
|
||||
author:
|
||||
type: fixed
|
|
@ -1,51 +0,0 @@
|
|||
if defined?(GrapeRouteHelpers)
|
||||
module GrapeRouteHelpers
|
||||
module AllRoutes
|
||||
# Bringing in PR https://github.com/reprah/grape-route-helpers/pull/21 due to abandonment.
|
||||
#
|
||||
# Without the following fix, when two helper methods are the same, but have different arguments
|
||||
# (for example: api_v1_cats_owners_path(id: 1) vs api_v1_cats_owners_path(id: 1, owner_id: 2))
|
||||
# if the helper method with the least number of arguments is defined first (because the route was defined first)
|
||||
# then it will shadow the longer route.
|
||||
#
|
||||
# The fix is to sort descending by amount of arguments
|
||||
def decorated_routes
|
||||
@decorated_routes ||= all_routes
|
||||
.map { |r| DecoratedRoute.new(r) }
|
||||
.sort_by { |r| -r.dynamic_path_segments.count }
|
||||
end
|
||||
end
|
||||
|
||||
class DecoratedRoute
|
||||
# GrapeRouteHelpers gem tries to parse the versions
|
||||
# from a string, not supporting Grape `version` array definition.
|
||||
#
|
||||
# Without the following fix, we get this on route helpers generation:
|
||||
#
|
||||
# => undefined method `scan' for ["v3", "v4"]
|
||||
#
|
||||
# 2.0.0 implementation of this method:
|
||||
#
|
||||
# ```
|
||||
# def route_versions
|
||||
# version_pattern = /[^\[",\]\s]+/
|
||||
# if route_version
|
||||
# route_version.scan(version_pattern)
|
||||
# else
|
||||
# [nil]
|
||||
# end
|
||||
# end
|
||||
# ```
|
||||
def route_versions
|
||||
return [nil] if route_version.nil? || route_version.empty?
|
||||
|
||||
if route_version.is_a?(String)
|
||||
version_pattern = /[^\[",\]\s]+/
|
||||
route_version.scan(version_pattern)
|
||||
else
|
||||
route_version
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -30,6 +30,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
|
|||
resource :variables, only: [:show, :update]
|
||||
|
||||
resources :children, only: [:index]
|
||||
resources :shared_projects, only: [:index]
|
||||
|
||||
resources :labels, except: [:show] do
|
||||
post :toggle_subscription, on: :member
|
||||
|
|
|
@ -80,7 +80,7 @@ STDERR takes precedence over STDOUT.
|
|||
|
||||
![Custom message from custom Git hook](img/custom_hooks_error_msg.png)
|
||||
|
||||
[CI]: ../ci/readme.md
|
||||
[CI]: ../ci/README.md
|
||||
[hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#Server-Side-Hooks
|
||||
[webhooks]: ../user/project/integrations/webhooks.md
|
||||
[5073]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5073
|
||||
|
|
|
@ -832,8 +832,8 @@ module API
|
|||
class ProjectWithAccess < Project
|
||||
expose :permissions do
|
||||
expose :project_access, using: Entities::ProjectAccess do |project, options|
|
||||
if options.key?(:project_members)
|
||||
(options[:project_members] || []).find { |member| member.source_id == project.id }
|
||||
if options[:project_members]
|
||||
options[:project_members].find { |member| member.source_id == project.id }
|
||||
else
|
||||
project.project_member(options[:current_user])
|
||||
end
|
||||
|
@ -841,8 +841,8 @@ module API
|
|||
|
||||
expose :group_access, using: Entities::GroupAccess do |project, options|
|
||||
if project.group
|
||||
if options.key?(:group_members)
|
||||
(options[:group_members] || []).find { |member| member.source_id == project.namespace_id }
|
||||
if options[:group_members]
|
||||
options[:group_members].find { |member| member.source_id == project.namespace_id }
|
||||
else
|
||||
project.group.group_member(options[:current_user])
|
||||
end
|
||||
|
@ -853,13 +853,24 @@ module API
|
|||
def self.preload_relation(projects_relation, options = {})
|
||||
relation = super(projects_relation, options)
|
||||
|
||||
unless options.key?(:group_members)
|
||||
relation = relation.preload(group: [group_members: [:source, user: [notification_settings: :source]]])
|
||||
# MySQL doesn't support LIMIT inside an IN subquery
|
||||
if Gitlab::Database.mysql?
|
||||
project_ids = relation.pluck('projects.id')
|
||||
namespace_ids = relation.pluck(:namespace_id)
|
||||
else
|
||||
project_ids = relation.select('projects.id')
|
||||
namespace_ids = relation.select(:namespace_id)
|
||||
end
|
||||
|
||||
unless options.key?(:project_members)
|
||||
relation = relation.preload(project_members: [:source, user: [notification_settings: :source]])
|
||||
end
|
||||
options[:project_members] = options[:current_user]
|
||||
.project_members
|
||||
.where(source_id: project_ids)
|
||||
.preload(:source, user: [notification_settings: :source])
|
||||
|
||||
options[:group_members] = options[:current_user]
|
||||
.group_members
|
||||
.where(source_id: namespace_ids)
|
||||
.preload(:source, user: [notification_settings: :source])
|
||||
|
||||
relation
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module API
|
||||
module Helpers
|
||||
module RelatedResourcesHelpers
|
||||
include GrapeRouteHelpers::NamedRouteMatcher
|
||||
include GrapePathHelpers::NamedRouteMatcher
|
||||
|
||||
def issues_available?(project, options)
|
||||
available?(:issues, project, options[:current_user])
|
||||
|
|
|
@ -58,16 +58,9 @@ module API
|
|||
projects = paginate(projects)
|
||||
projects, options = with_custom_attributes(projects, options)
|
||||
|
||||
if current_user
|
||||
project_members = current_user.project_members.preload(:source, user: [notification_settings: :source])
|
||||
group_members = current_user.group_members.preload(:source, user: [notification_settings: :source])
|
||||
end
|
||||
|
||||
options = options.reverse_merge(
|
||||
with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails,
|
||||
statistics: params[:statistics],
|
||||
project_members: project_members,
|
||||
group_members: group_members,
|
||||
current_user: current_user
|
||||
)
|
||||
options[:with] = Entities::BasicProjectDetails if params[:simple]
|
||||
|
|
|
@ -129,6 +129,7 @@ module API
|
|||
optional :gitaly_timeout_default, type: Integer, desc: 'Default Gitaly timeout, in seconds. Set to 0 to disable timeouts.'
|
||||
optional :gitaly_timeout_medium, type: Integer, desc: 'Medium Gitaly timeout, in seconds. Set to 0 to disable timeouts.'
|
||||
optional :gitaly_timeout_fast, type: Integer, desc: 'Gitaly fast operation timeout, in seconds. Set to 0 to disable timeouts.'
|
||||
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
|
||||
|
||||
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
|
||||
optional :"#{type}_key_restriction",
|
||||
|
|
|
@ -41,10 +41,10 @@ module Peek
|
|||
]
|
||||
end.sort_by{ |a,b,c,d,e,f| -f }
|
||||
|
||||
output = "<div class='modal-dialog modal-full'><div class='modal-content'>"
|
||||
output = "<div class='modal-dialog modal-lg'><div class='modal-content'>"
|
||||
output << "<div class='modal-header'>"
|
||||
output << "<button class='close btn btn-link btn-sm' type='button' data-dismiss='modal'>X</button>"
|
||||
output << "<h4>Line profiling: #{human_description(params[:lineprofiler])}</h4>"
|
||||
output << "<button class='close' type='button' data-dismiss='modal' aria-label='close'><span aria-hidden='true'>×</span></button>"
|
||||
output << "</div>"
|
||||
output << "<div class='modal-body'>"
|
||||
|
||||
|
|
16
package.json
16
package.json
|
@ -100,21 +100,21 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"axios-mock-adapter": "^1.15.0",
|
||||
"babel-eslint": "^8.0.2",
|
||||
"babel-eslint": "^8.2.3",
|
||||
"babel-plugin-istanbul": "^4.1.6",
|
||||
"babel-plugin-rewire": "^1.1.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"chalk": "^2.4.1",
|
||||
"commander": "^2.15.1",
|
||||
"eslint": "^3.18.0",
|
||||
"eslint-config-airbnb-base": "^10.0.1",
|
||||
"eslint-import-resolver-webpack": "^0.8.3",
|
||||
"eslint-plugin-filenames": "^1.1.0",
|
||||
"eslint-plugin-html": "2.0.1",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint": "~4.12.1",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint-import-resolver-webpack": "^0.10.0",
|
||||
"eslint-plugin-filenames": "^1.2.0",
|
||||
"eslint-plugin-html": "4.0.3",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-jasmine": "^2.1.0",
|
||||
"eslint-plugin-promise": "^3.5.0",
|
||||
"eslint-plugin-promise": "^3.8.0",
|
||||
"eslint-plugin-vue": "^4.0.1",
|
||||
"ignore": "^3.3.7",
|
||||
"istanbul": "^0.4.5",
|
||||
|
|
59
spec/controllers/groups/shared_projects_controller_spec.rb
Normal file
59
spec/controllers/groups/shared_projects_controller_spec.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Groups::SharedProjectsController do
|
||||
def get_shared_projects(params = {})
|
||||
get :index, params.reverse_merge(format: :json, group_id: group.full_path)
|
||||
end
|
||||
|
||||
def share_project(project)
|
||||
Projects::GroupLinks::CreateService.new(
|
||||
project,
|
||||
user,
|
||||
link_group_access: ProjectGroupLink::DEVELOPER
|
||||
).execute(group)
|
||||
end
|
||||
|
||||
set(:group) { create(:group) }
|
||||
set(:user) { create(:user) }
|
||||
set(:shared_project) do
|
||||
shared_project = create(:project, namespace: user.namespace)
|
||||
share_project(shared_project)
|
||||
|
||||
shared_project
|
||||
end
|
||||
|
||||
let(:json_project_ids) { json_response.map { |project_info| project_info['id'] } }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns only projects shared with the group' do
|
||||
create(:project, namespace: group)
|
||||
|
||||
get_shared_projects
|
||||
|
||||
expect(json_project_ids).to contain_exactly(shared_project.id)
|
||||
end
|
||||
|
||||
it 'allows filtering shared projects' do
|
||||
project = create(:project, :archived, namespace: user.namespace, name: "Searching for")
|
||||
share_project(project)
|
||||
|
||||
get_shared_projects(filter: 'search')
|
||||
|
||||
expect(json_project_ids).to contain_exactly(project.id)
|
||||
end
|
||||
|
||||
it 'allows sorting projects' do
|
||||
shared_project.update!(name: 'bbb')
|
||||
second_project = create(:project, namespace: user.namespace, name: 'aaaa')
|
||||
share_project(second_project)
|
||||
|
||||
get_shared_projects(sort: 'name_asc')
|
||||
|
||||
expect(json_project_ids).to eq([second_project.id, shared_project.id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -592,7 +592,7 @@ describe 'Issues' do
|
|||
end
|
||||
|
||||
it 'clears local storage after creating a new issue', :js do
|
||||
2.times.each do
|
||||
2.times do
|
||||
visit new_project_issue_path(project)
|
||||
wait_for_requests
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
require 'spec_helper'
|
||||
require_relative '../../config/initializers/grape_route_helpers_fix'
|
||||
|
||||
describe 'route shadowing' do
|
||||
include GrapeRouteHelpers::NamedRouteMatcher
|
||||
|
||||
it 'does not occur' do
|
||||
path = api_v4_projects_merge_requests_path(id: 1)
|
||||
expect(path).to eq('/api/v4/projects/1/merge_requests')
|
||||
|
||||
path = api_v4_projects_merge_requests_path(id: 1, merge_request_iid: 3)
|
||||
expect(path).to eq('/api/v4/projects/1/merge_requests/3')
|
||||
end
|
||||
end
|
|
@ -1,33 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"jasmine": true
|
||||
},
|
||||
"extends": "plugin:jasmine/recommended",
|
||||
"globals": {
|
||||
"appendLoadFixtures": false,
|
||||
"appendLoadStyleFixtures": false,
|
||||
"appendSetFixtures": false,
|
||||
"appendSetStyleFixtures": false,
|
||||
"getJSONFixture": false,
|
||||
"loadFixtures": false,
|
||||
"loadJSONFixtures": false,
|
||||
"loadStyleFixtures": false,
|
||||
"preloadFixtures": false,
|
||||
"preloadStyleFixtures": false,
|
||||
"readFixtures": false,
|
||||
"sandbox": false,
|
||||
"setFixtures": false,
|
||||
"setStyleFixtures": false,
|
||||
"spyOnDependency": false,
|
||||
"spyOnEvent": false,
|
||||
"ClassSpecHelper": false
|
||||
},
|
||||
"plugins": ["jasmine"],
|
||||
"rules": {
|
||||
"func-names": 0,
|
||||
"jasmine/no-suite-dupes": [1, "branch"],
|
||||
"jasmine/no-spec-dupes": [1, "branch"],
|
||||
"no-console": 0,
|
||||
"prefer-arrow-callback": 0
|
||||
}
|
||||
}
|
34
spec/javascripts/.eslintrc.yml
Normal file
34
spec/javascripts/.eslintrc.yml
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
env:
|
||||
jasmine: true
|
||||
extends: plugin:jasmine/recommended
|
||||
globals:
|
||||
appendLoadFixtures: false
|
||||
appendLoadStyleFixtures: false
|
||||
appendSetFixtures: false
|
||||
appendSetStyleFixtures: false
|
||||
getJSONFixture: false
|
||||
loadFixtures: false
|
||||
loadJSONFixtures: false
|
||||
loadStyleFixtures: false
|
||||
preloadFixtures: false
|
||||
preloadStyleFixtures: false
|
||||
readFixtures: false
|
||||
sandbox: false
|
||||
setFixtures: false
|
||||
setStyleFixtures: false
|
||||
spyOnDependency: false
|
||||
spyOnEvent: false
|
||||
ClassSpecHelper: false
|
||||
plugins:
|
||||
- jasmine
|
||||
rules:
|
||||
func-names: off
|
||||
jasmine/no-suite-dupes:
|
||||
- warn
|
||||
- branch
|
||||
jasmine/no-spec-dupes:
|
||||
- warn
|
||||
- branch
|
||||
no-console: off
|
||||
prefer-arrow-callback: off
|
|
@ -84,9 +84,14 @@ describe('iPython notebook renderer', () => {
|
|||
describe('error in JSON response', () => {
|
||||
let mock;
|
||||
|
||||
beforeEach((done) => {
|
||||
beforeEach(done => {
|
||||
mock = new MockAdapter(axios);
|
||||
mock.onGet('/test').reply(() => Promise.reject({ status: 200, data: '{ "cells": [{"cell_type": "markdown"} }' }));
|
||||
mock
|
||||
.onGet('/test')
|
||||
.reply(() =>
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
Promise.reject({ status: 200, data: '{ "cells": [{"cell_type": "markdown"} }' }),
|
||||
);
|
||||
|
||||
renderNotebook();
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* global BoardService */
|
||||
import Vue from 'vue';
|
||||
import '~/boards/stores/boards_store';
|
||||
import BoardBlankState from '~/boards/components/board_blank_state.vue';
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* global List */
|
||||
/* global ListAssignee */
|
||||
/* global ListLabel */
|
||||
/* global BoardService */
|
||||
|
||||
import Vue from 'vue';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* global BoardService */
|
||||
/* global List */
|
||||
/* global ListIssue */
|
||||
import Vue from 'vue';
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* global BoardService */
|
||||
/* global List */
|
||||
|
||||
import Vue from 'vue';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-disable comma-dangle, one-var, no-unused-vars */
|
||||
/* global BoardService */
|
||||
/* global ListIssue */
|
||||
|
||||
import Vue from 'vue';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-disable comma-dangle */
|
||||
/* global BoardService */
|
||||
/* global ListIssue */
|
||||
|
||||
import Vue from 'vue';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-disable comma-dangle */
|
||||
/* global BoardService */
|
||||
/* global List */
|
||||
/* global ListIssue */
|
||||
|
||||
|
|
|
@ -75,10 +75,7 @@ describe('Commit pipeline status component', () => {
|
|||
describe('When polling data was not succesful', () => {
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
mock.onGet('/dummy/endpoint').reply(() => {
|
||||
const res = Promise.reject([502, { }]);
|
||||
return res;
|
||||
});
|
||||
mock.onGet('/dummy/endpoint').reply(502, {});
|
||||
vm = new Component({
|
||||
props: {
|
||||
endpoint: '/dummy/endpoint',
|
||||
|
|
|
@ -1,30 +1,18 @@
|
|||
import Vue from 'vue';
|
||||
const mountComponent = (Component, props = {}, el = null) =>
|
||||
new Component({
|
||||
propsData: props,
|
||||
}).$mount(el);
|
||||
|
||||
const mountComponent = (Component, props = {}, el = null) => new Component({
|
||||
propsData: props,
|
||||
}).$mount(el);
|
||||
|
||||
export const createComponentWithStore = (Component, store, propsData = {}) => new Component({
|
||||
store,
|
||||
propsData,
|
||||
});
|
||||
|
||||
export const createComponentWithMixin = (mixins = [], state = {}, props = {}, template = '<div></div>') => {
|
||||
const Component = Vue.extend({
|
||||
template,
|
||||
mixins,
|
||||
data() {
|
||||
return props;
|
||||
},
|
||||
export const createComponentWithStore = (Component, store, propsData = {}) =>
|
||||
new Component({
|
||||
store,
|
||||
propsData,
|
||||
});
|
||||
|
||||
return mountComponent(Component, props);
|
||||
};
|
||||
|
||||
export const mountComponentWithStore = (Component, { el, props, store }) =>
|
||||
new Component({
|
||||
store,
|
||||
propsData: props || { },
|
||||
propsData: props || {},
|
||||
}).$mount(el);
|
||||
|
||||
export default mountComponent;
|
||||
|
|
|
@ -8,10 +8,7 @@ describe('Confidential Issue Sidebar Block', () => {
|
|||
beforeEach(() => {
|
||||
const Component = Vue.extend(confidentialIssueSidebar);
|
||||
const service = {
|
||||
update: () => new Promise((resolve, reject) => {
|
||||
resolve(true);
|
||||
reject('failed!');
|
||||
}),
|
||||
update: () => Promise.resolve(true),
|
||||
};
|
||||
|
||||
vm1 = new Component({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable prefer-rest-params, wrap-iife,
|
||||
no-unused-expressions, no-return-assign, no-param-reassign*/
|
||||
no-unused-expressions, no-return-assign, no-param-reassign */
|
||||
|
||||
export default class MockU2FDevice {
|
||||
constructor() {
|
||||
|
|
|
@ -29,6 +29,18 @@ describe API::MergeRequests do
|
|||
project.add_reporter(user)
|
||||
end
|
||||
|
||||
describe 'route shadowing' do
|
||||
include GrapePathHelpers::NamedRouteMatcher
|
||||
|
||||
it 'does not occur' do
|
||||
path = api_v4_projects_merge_requests_path(id: 1)
|
||||
expect(path).to eq('/api/v4/projects/1/merge_requests')
|
||||
|
||||
path = api_v4_projects_merge_requests_path(id: 1, merge_request_iid: 3)
|
||||
expect(path).to eq('/api/v4/projects/1/merge_requests/3')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /merge_requests' do
|
||||
context 'when unauthenticated' do
|
||||
it 'returns an array of all merge requests' do
|
||||
|
|
|
@ -382,6 +382,8 @@ describe ObjectStorage do
|
|||
is_expected.to have_key(:RemoteObject)
|
||||
|
||||
expect(subject[:RemoteObject]).to have_key(:ID)
|
||||
expect(subject[:RemoteObject]).to include(Timeout: a_kind_of(Integer))
|
||||
expect(subject[:RemoteObject][:Timeout]).to be(ObjectStorage::DIRECT_UPLOAD_TIMEOUT)
|
||||
expect(subject[:RemoteObject]).to have_key(:GetURL)
|
||||
expect(subject[:RemoteObject]).to have_key(:DeleteURL)
|
||||
expect(subject[:RemoteObject]).to have_key(:StoreURL)
|
||||
|
|
Loading…
Reference in a new issue