Merge branch 'master' into 'boards-bundle-refactor'
# Conflicts: # config/webpack.config.js
This commit is contained in:
commit
a90a22a774
196
CHANGELOG.md
196
CHANGELOG.md
|
@ -2,6 +2,202 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.5.1 (2018-02-22)
|
||||
|
||||
- No changes.
|
||||
|
||||
## 10.5.0 (2018-02-22)
|
||||
|
||||
### Security (3 changes, 1 of them is from the community)
|
||||
|
||||
- Update marked from 0.3.6 to 0.3.12. !16480 (Takuya Noguchi)
|
||||
- Update nokogiri to 1.8.2. !16807
|
||||
- Add verification for GitLab Pages custom domains.
|
||||
|
||||
### Fixed (77 changes, 25 of them are from the community)
|
||||
|
||||
- Fix the Projects API with_issues_enabled filter behaving incorrectly any user. !12724 (Jan Christophersen)
|
||||
- Hide pipeline schedule take ownership for current owner. !12986
|
||||
- Handle special characters on API request of issuable templates. !15323 (Takuya Noguchi)
|
||||
- Shows signin tab after new user email confirmation. !16174 (Jacopo Beschi @jacopo-beschi)
|
||||
- Make project README containers wider on fixed layout. !16181 (Takuya Noguchi)
|
||||
- Fix dashboard projects nav links height. !16204 (George Tsiolis)
|
||||
- Fix error on empty query for Members API. !16235
|
||||
- Issue board: fix for dragging an issue to the very bottom in long lists. !16250 (David Kuri)
|
||||
- Make rich blob viewer wider for PC. !16262 (Takuya Noguchi)
|
||||
- Substitute deprecated ui_charcoal with new default ui_indigo. !16271 (Takuya Noguchi)
|
||||
- Generate HTTP URLs for custom Pages domains when appropriate. !16279
|
||||
- Make modal dialog common for Groups tree app. !16311
|
||||
- Allow moving wiki pages from the UI. !16313
|
||||
- Filter groups and projects dropdowns of search page on backend. !16336
|
||||
- Adjust layout width for fixed layout. !16337 (George Tsiolis)
|
||||
- Fix custom header logo design nitpick: Remove unneeded margin on empty logo text. !16383 (Markus Doits)
|
||||
- File Upload UI can create LFS pointers based on .gitattributes. !16412
|
||||
- Fix Ctrl+Enter keyboard shortcut saving comment/note edit. !16415
|
||||
- Fix file search results when they match file contents with a number between two colons. !16462
|
||||
- Fix tooltip displayed for running manual actions. !16489
|
||||
- Allow trailing + on labels in board filters. !16490
|
||||
- Prevent JIRA issue identifier from being humanized. !16491 (Andrew McCallum)
|
||||
- Add horizontal scroll to wiki tables. !16527 (George Tsiolis)
|
||||
- Fix a bug calculating artifact size for project statistics. !16539
|
||||
- Stop loading spinner on error of issuable templates. !16600 (Takuya Noguchi)
|
||||
- Allows html text in commits atom feed. !16603 (Jacopo Beschi @jacopo-beschi)
|
||||
- Disable MR check out button when source branch is deleted. !16631 (Jacopo Beschi @jacopo-beschi)
|
||||
- Fix export removal for hashed-storage projects within a renamed or deleted namespace. !16658
|
||||
- Default to HTTPS for all Gravatar URLs. !16666
|
||||
- Login via OAuth now only marks new users as external. !16672
|
||||
- Fix default avatar icon missing when Gravatar is disabled. !16681 (Felix Geyer)
|
||||
- Change button group width on mobile. !16726 (George Tsiolis)
|
||||
- Fix version information not showing on help page if commercial content display was disabled. !16743
|
||||
- Adds spacing between edit and delete tag btn in tag list. !16757 (Jacopo Beschi @jacopo-beschi)
|
||||
- Fix 500 error when loading a merge request with an invalid comment. !16795
|
||||
- Deleting an upload will correctly clean up the filesystem. !16799
|
||||
- Cleanup new branch/merge request form in issues. !16854
|
||||
- Fix GitLab import leaving group_id on ProjectLabel. !16877
|
||||
- Fix forking projects when no restricted visibility levels are defined applicationwide. !16881
|
||||
- Trigger change event on filename input when file template is applied. !16911 (Sebastian Klingler)
|
||||
- Fixes different margins between buttons in tag list. !16927 (Jacopo Beschi @jacopo-beschi)
|
||||
- Close low level rugged repository in project cache worker. !16930 (Bastian Blank)
|
||||
- Override group sidebar links. !16942 (George Tsiolis)
|
||||
- Avoid running `PopulateForkNetworksRange`-migration multiple times. !16988
|
||||
- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
|
||||
- Fix monaco editor features which were incompatable with GitLab CDN settings. !17021
|
||||
- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
|
||||
- Fix cnacel edit note button reverting changes. !42462
|
||||
- For issues display time of last edit of title or description instead of time of any attribute change.
|
||||
- Handle all Psych YAML parser exceptions (fixes #41209).
|
||||
- Fix validation of environment scope of variables.
|
||||
- Display user friendly error message if rebase fails.
|
||||
- Hide new branch and tag links for projects with an empty repo.
|
||||
- Fix protected branches API to accept name parameter with dot.
|
||||
- Closes #38540 - Remove .ssh/environment file that now breaks the gitlab:check rake task.
|
||||
- Keep subscribers when promoting labels to group labels.
|
||||
- Replace verified badge icons and uniform colors.
|
||||
- Fix error on changes tab when merge request cannot be created.
|
||||
- Ignore leading slashes when searching for files within context of repository. (Andrew McCallum)
|
||||
- Close and do not reload MR diffs when source branch is deleted.
|
||||
- Bypass commits title markdown on notes.
|
||||
- Reload MRs memoization after diffs creation.
|
||||
- Return more consistent values for merge_status on MR APIs.
|
||||
- Contribution calendar label was cut off. (Branka Martinovic)
|
||||
- LDAP Person no longer throws exception on invalid entry.
|
||||
- Fix bug where award emojis would be lost when moving issues between projects.
|
||||
- Fix not all events being shown in group dashboard.
|
||||
- Fix JIRA not working when a trailing slash is included.
|
||||
- Fix squash not working when diff contained non-ASCII data.
|
||||
- Remove erroneous text in shared runners page that suggested more runners available.
|
||||
- Execute system hooks after-commit when executing project hooks.
|
||||
- Makes forking protect default branch on completion.
|
||||
- Validate user, group and project paths consistently, and only once.
|
||||
- Validate user namespace before saving so that errors persist on model.
|
||||
- Permits 'password_authentication_enabled_for_git' parameter for ApplicationSettingsController.
|
||||
- Fix duplicate item in protected branch/tag dropdown.
|
||||
- Open visibility level help in a new tab. (Jussi Räsänen)
|
||||
|
||||
### Deprecated (1 change)
|
||||
|
||||
- Add note within ux documentation that further changes should be made within the design.gitlab project.
|
||||
|
||||
### Changed (20 changes, 7 of them are from the community)
|
||||
|
||||
- Show coverage to two decimal points in coverage badge. !10083 (Jeff Stubler)
|
||||
- Update 'removed assignee' note to include old assignee reference. !16301 (Maurizio De Santis)
|
||||
- Move row containing Projects, Users and Groups count to the top in admin dashboard. !16421
|
||||
- Add Auto DevOps Domain application setting. !16604
|
||||
- Changes Revert this merge request text. !16611 (Jacopo Beschi @jacopo-beschi)
|
||||
- Link Auto DevOps settings to Clusters page. !16641
|
||||
- Internationalize charts page. !16687 (selrahman)
|
||||
- Internationalize graph page selrahman. !16688 (Shah El-Rahman)
|
||||
- Save traces as artifacts. !16702
|
||||
- Hide variable values on pipeline schedule edit page. !16729
|
||||
- Update runner info on all authenticated requests. !16756
|
||||
- Improve issue note dropdown and mr button. !16758 (George Tsiolis)
|
||||
- Replace "cluster" with "Kubernetes cluster". !16778
|
||||
- Enable Prometheus metrics for deployed Ingresses. !16866 (joshlambert)
|
||||
- Rename button to enable CI/CD configuration to "Set up CI/CD". !16870
|
||||
- Double padding for file-content wiki class on larger screens.
|
||||
- Improve wording about additional costs for Ingress on custom clusters.
|
||||
- Last push widget will show banner for new pushes to previously merged branch.
|
||||
- Save user ID and username in Grape API log (api_json.log).
|
||||
- Include subgroup issues and merge requests on the group page.
|
||||
|
||||
### Performance (14 changes, 1 of them is from the community)
|
||||
|
||||
- Fix double query execution on groups page. !16314
|
||||
- Speed up loading merged merge requests when they contained a lot of commits before merging. !16320
|
||||
- Properly memoize some predicate methods. !16329
|
||||
- Reduce the number of Prometheus metrics. !16443
|
||||
- Only highlight search results under the highlighting size limit. !16462
|
||||
- Add fast-blank. !16468
|
||||
- Move BoardList vue component to vue file. !16888 (George Tsiolis)
|
||||
- Fix N+1 query problem for snippets dashboard. !16944
|
||||
- Optimize search queries on the search page by setting a limit for matching records.
|
||||
- Store number of commits in merge_request_diffs table.
|
||||
- Improve performance of target branch dropdown.
|
||||
- Remove duplicate calls of MergeRequest#can_be_reverted?.
|
||||
- Stop checking if discussions are in a mergeable state if the MR isn't.
|
||||
- Remove N+1 queries with /projects/:project_id/{access_requests,members} API endpoints.
|
||||
|
||||
### Added (28 changes, 10 of them are from the community)
|
||||
|
||||
- Add link on commit page to merge request that introduced that commit. !13713 (Hiroyuki Sato)
|
||||
- System hooks for Merge Requests. !14387 (Alexis Reigel)
|
||||
- Add `pipelines` endpoint to merge requests API. !15454 (Tony Rom <thetonyrom@gmail.com>)
|
||||
- Adds Rubocop rule for line break around conditionals. !15739 (Jacopo Beschi @jacopo-beschi)
|
||||
- Add Colors to GitLab Flavored Markdown. !16095 (Tony Rom <thetonyrom@gmail.com>)
|
||||
- Initial work to add notification reason to emails. !16160 (Mario de la Ossa)
|
||||
- Implement multi server support and use kube proxy to connect to Prometheus servers inside K8S cluster. !16182
|
||||
- Add ability to transfer a group into another group. !16302
|
||||
- Add blue dot feature highlight to make GKE Clusters more visible to users. !16379
|
||||
- Add section headers to plus button dropdown. !16394 (George Tsiolis)
|
||||
- Support PostgreSQL 10. !16471
|
||||
- Enables Project Milestone Deletion via the API. !16478 (Jacopo Beschi @jacopo-beschi)
|
||||
- Add realtime ci status for the repository -> files view. !16523
|
||||
- User can now git push to create a new project. !16547
|
||||
- Improve empty project overview. !16617 (George Tsiolis)
|
||||
- Added uploader metadata to the uploads. !16779
|
||||
- Added ldap config setting to lower case the username. !16791
|
||||
- Add search support into the API. !16878
|
||||
- Backport of LFS File Locking API. !16935
|
||||
- Add a link to documentation on how to get external ip in the Kubernetes cluster details page. !16937
|
||||
- Add sorting options for /users API (admin only). !16945
|
||||
- Adds sorting to deployments API. (Jacopo Beschi @jacopo-beschi)
|
||||
- Add rake task to check integrity of uploaded files.
|
||||
- Add backend for persistently dismissably callouts.
|
||||
- Track and act upon the number of executed queries.
|
||||
- Add a gRPC health check to ensure Gitaly is up.
|
||||
- Log and send a system hook if a blocked user attempts to login.
|
||||
- Add Gitaly Servers admin dashboard.
|
||||
|
||||
### Other (25 changes, 7 of them are from the community)
|
||||
|
||||
- Updated the katex library. !15864
|
||||
- Add modal for deleting a milestone. !16229
|
||||
- Remove unused CSS selectors for Cycle Analytics. !16270 (Takuya Noguchi)
|
||||
- Add reason to keep postgresql 9.2 for CI. !16277 (Takuya Noguchi)
|
||||
- Adjust modal style to new design. !16310
|
||||
- Default to Gitaly for 'git push' HTTP/SSH, and make Gitaly mandatory for SSH pull. !16586
|
||||
- Set timezone for karma to UTC. !16602 (Takuya Noguchi)
|
||||
- Make Gitaly RepositoryExists opt-out. !16680
|
||||
- Update minimum git version to 2.9.5. !16683
|
||||
- Disable throwOnError in KaTeX to reveal user where is the problem. !16684 (Jakub Jirutka)
|
||||
- fix documentation about node version. !16720 (Tobias Gurtzick)
|
||||
- Enable RuboCop Style/RegexpLiteral. !16752 (Takuya Noguchi)
|
||||
- Add confirmation-input component. !16816
|
||||
- Add unique constraint to trending_projects#project_id. !16846
|
||||
- Add foreign key and NOT NULL constraints to todos table. !16849
|
||||
- Include branch in mobile view for pipelines. !16910 (George Tsiolis)
|
||||
- Downgrade google-protobuf gem. !16941
|
||||
- Refactors mr widget components into vue files and adds i18n.
|
||||
- increase-readability-of-colored-text-in-job-output-log.
|
||||
- Finish any remaining jobs for issues.closed_at.
|
||||
- Translate issuable sidebar.
|
||||
- Set standard disabled state for all buttons.
|
||||
- Upgrade GitLab Workhorse to v3.6.0.
|
||||
- Improve readability of underlined links for dyslexic users.
|
||||
- Adds empty state illustration for pending job.
|
||||
|
||||
|
||||
## 10.4.4 (2018-02-16)
|
||||
|
||||
### Security (1 change)
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.81.0
|
||||
0.82.0
|
||||
|
|
|
@ -9,7 +9,7 @@ const Api = {
|
|||
projectsPath: '/api/:version/projects.json',
|
||||
projectPath: '/api/:version/projects/:id',
|
||||
projectLabelsPath: '/:namespace_path/:project_path/labels',
|
||||
groupLabelsPath: '/groups/:namespace_path/labels',
|
||||
groupLabelsPath: '/groups/:namespace_path/-/labels',
|
||||
licensePath: '/api/:version/templates/licenses/:key',
|
||||
gitignorePath: '/api/:version/templates/gitignores/:key',
|
||||
gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key',
|
||||
|
@ -32,7 +32,7 @@ const Api = {
|
|||
},
|
||||
|
||||
// Return groups list. Filtered by query
|
||||
groups(query, options, callback) {
|
||||
groups(query, options, callback = $.noop) {
|
||||
const url = Api.buildUrl(Api.groupsPath);
|
||||
return axios.get(url, {
|
||||
params: Object.assign({
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
mixins: [
|
||||
pipelinesMixin,
|
||||
],
|
||||
|
||||
props: {
|
||||
endpoint: {
|
||||
type: String,
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
>
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl" />
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Vue from 'vue';
|
||||
import deployKeysApp from './components/app.vue';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => new Vue({
|
||||
export default () => new Vue({
|
||||
el: document.getElementById('js-deploy-keys'),
|
||||
components: {
|
||||
deployKeysApp,
|
||||
|
@ -18,4 +18,4 @@ document.addEventListener('DOMContentLoaded', () => new Vue({
|
|||
},
|
||||
});
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -71,7 +71,7 @@ export default () => {
|
|||
el: '#resolve-count-app',
|
||||
components: {
|
||||
'resolve-count': ResolveCount
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
$(window).trigger('resize.nav');
|
||||
|
|
|
@ -42,190 +42,34 @@ var Dispatcher;
|
|||
});
|
||||
});
|
||||
|
||||
switch (page) {
|
||||
case 'projects:merge_requests:index':
|
||||
case 'projects:issues:index':
|
||||
case 'projects:issues:show':
|
||||
case 'projects:issues:new':
|
||||
case 'projects:issues:edit':
|
||||
case 'projects:merge_requests:creations:new':
|
||||
case 'projects:merge_requests:creations:diffs':
|
||||
case 'projects:merge_requests:edit':
|
||||
case 'projects:merge_requests:show':
|
||||
case 'projects:commit:show':
|
||||
case 'projects:activity':
|
||||
case 'projects:commits:show':
|
||||
case 'projects:show':
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'groups:activity':
|
||||
import('./pages/groups/activity')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'groups:show':
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'groups:group_members:index':
|
||||
import('./pages/groups/group_members/index')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:project_members:index':
|
||||
import('./pages/projects/project_members')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'groups:create':
|
||||
case 'groups:new':
|
||||
import('./pages/groups/new')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'groups:edit':
|
||||
import('./pages/groups/edit')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'admin:groups:create':
|
||||
case 'admin:groups:new':
|
||||
import('./pages/admin/groups/new')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'admin:groups:edit':
|
||||
import('./pages/admin/groups/edit')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:tree:show':
|
||||
import('./pages/projects/tree/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'projects:find_file:show':
|
||||
import('./pages/projects/find_file/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'projects:blob:show':
|
||||
import('./pages/projects/blob/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'projects:blame:show':
|
||||
import('./pages/projects/blame/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'groups:labels:new':
|
||||
import('./pages/groups/labels/new')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'groups:labels:edit':
|
||||
import('./pages/groups/labels/edit')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:labels:new':
|
||||
import('./pages/projects/labels/new')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:labels:edit':
|
||||
import('./pages/projects/labels/edit')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'groups:labels:index':
|
||||
import('./pages/groups/labels/index')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:labels:index':
|
||||
import('./pages/projects/labels/index')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:network:show':
|
||||
// Ensure we don't create a particular shortcut handler here. This is
|
||||
// already created, where the network graph is created.
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'projects:forks:new':
|
||||
import('./pages/projects/forks/new')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:artifacts:browse':
|
||||
import('./pages/projects/artifacts/browse')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'projects:artifacts:file':
|
||||
import('./pages/projects/artifacts/file')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
shortcut_handler = true;
|
||||
break;
|
||||
case 'search:show':
|
||||
import('./pages/search/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:settings:repository:show':
|
||||
import('./pages/projects/settings/repository/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'projects:settings:ci_cd:show':
|
||||
import('./pages/projects/settings/ci_cd/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'groups:settings:ci_cd:show':
|
||||
import('./pages/groups/settings/ci_cd/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'ci:lints:create':
|
||||
case 'ci:lints:show':
|
||||
import('./pages/ci/lints')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'admin:conversational_development_index:show':
|
||||
import('./pages/admin/conversational_development_index/show')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'import:fogbugz:new_user_map':
|
||||
import('./pages/import/fogbugz/new_user_map')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'profiles:personal_access_tokens:index':
|
||||
import('./pages/profiles/personal_access_tokens')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'admin:impersonation_tokens:index':
|
||||
import('./pages/admin/impersonation_tokens')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
case 'dashboard:groups:index':
|
||||
import('./pages/dashboard/groups/index')
|
||||
.then(callDefault)
|
||||
.catch(fail);
|
||||
break;
|
||||
const shortcutHandlerPages = [
|
||||
'projects:activity',
|
||||
'projects:artifacts:browse',
|
||||
'projects:artifacts:file',
|
||||
'projects:blame:show',
|
||||
'projects:blob:show',
|
||||
'projects:commit:show',
|
||||
'projects:commits:show',
|
||||
'projects:find_file:show',
|
||||
'projects:issues:edit',
|
||||
'projects:issues:index',
|
||||
'projects:issues:new',
|
||||
'projects:issues:show',
|
||||
'projects:merge_requests:creations:diffs',
|
||||
'projects:merge_requests:creations:new',
|
||||
'projects:merge_requests:edit',
|
||||
'projects:merge_requests:index',
|
||||
'projects:merge_requests:show',
|
||||
'projects:network:show',
|
||||
'projects:show',
|
||||
'projects:tree:show',
|
||||
'groups:show',
|
||||
];
|
||||
|
||||
if (shortcutHandlerPages.indexOf(page) !== -1) {
|
||||
shortcut_handler = true;
|
||||
}
|
||||
|
||||
switch (path[0]) {
|
||||
case 'admin':
|
||||
switch (path[1]) {
|
||||
|
|
|
@ -14,7 +14,6 @@ export default class DropdownUser extends FilteredSearchDropdown {
|
|||
endpoint: `${gon.relative_url_root || ''}/autocomplete/users.json`,
|
||||
searchKey: 'search',
|
||||
params: {
|
||||
per_page: 20,
|
||||
active: true,
|
||||
group_id: this.getGroupId(),
|
||||
project_id: this.getProjectId(),
|
||||
|
|
|
@ -111,6 +111,9 @@ export default class FilteredSearchDropdown {
|
|||
|
||||
if (hook) {
|
||||
const data = hook.list.data || [];
|
||||
|
||||
if (!data) return;
|
||||
|
||||
const results = data.map((o) => {
|
||||
const updated = o;
|
||||
updated.droplab_hidden = false;
|
||||
|
|
|
@ -607,7 +607,20 @@ GitLabDropdown = (function() {
|
|||
};
|
||||
|
||||
GitLabDropdown.prototype.renderItem = function(data, group, index) {
|
||||
var field, fieldName, html, selected, text, url, value;
|
||||
var field, fieldName, html, selected, text, url, value, rowHidden;
|
||||
|
||||
if (!this.options.renderRow) {
|
||||
value = this.options.id ? this.options.id(data) : data.id;
|
||||
|
||||
if (value) {
|
||||
value = value.toString().replace(/'/g, '\\\'');
|
||||
}
|
||||
}
|
||||
|
||||
// Hide element
|
||||
if (this.options.hideRow && this.options.hideRow(value)) {
|
||||
rowHidden = true;
|
||||
}
|
||||
if (group == null) {
|
||||
group = false;
|
||||
}
|
||||
|
@ -616,6 +629,7 @@ GitLabDropdown = (function() {
|
|||
index = false;
|
||||
}
|
||||
html = document.createElement('li');
|
||||
|
||||
if (data === 'divider' || data === 'separator') {
|
||||
html.className = data;
|
||||
return html;
|
||||
|
@ -631,11 +645,9 @@ GitLabDropdown = (function() {
|
|||
html = this.options.renderRow.call(this.options, data, this);
|
||||
} else {
|
||||
if (!selected) {
|
||||
value = this.options.id ? this.options.id(data) : data.id;
|
||||
fieldName = this.options.fieldName;
|
||||
|
||||
if (value) {
|
||||
value = value.toString().replace(/'/g, '\\\'');
|
||||
field = this.dropdown.parent().find(`input[name='${fieldName}'][value='${value}']`);
|
||||
if (field.length) {
|
||||
selected = true;
|
||||
|
|
|
@ -30,11 +30,11 @@
|
|||
default: 'bottom',
|
||||
},
|
||||
/**
|
||||
* value could either be number or string
|
||||
* as `memberCount` is always passed as string
|
||||
* while `subgroupCount` & `projectCount`
|
||||
* are always number
|
||||
*/
|
||||
* value could either be number or string
|
||||
* as `memberCount` is always passed as string
|
||||
* while `subgroupCount` & `projectCount`
|
||||
* are always number
|
||||
*/
|
||||
value: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
|
|
|
@ -316,9 +316,9 @@ export default class LabelsSelect {
|
|||
},
|
||||
multiSelect: $dropdown.hasClass('js-multiselect'),
|
||||
vue: $dropdown.hasClass('js-issue-board-sidebar'),
|
||||
clicked: function(options) {
|
||||
const { $el, e, isMarking } = options;
|
||||
const label = options.selectedObj;
|
||||
clicked: function (clickEvent) {
|
||||
const { $el, e, isMarking } = clickEvent;
|
||||
const label = clickEvent.selectedObj;
|
||||
|
||||
var isIssueIndex, isMRIndex, page, boardsModel;
|
||||
var fadeOutLoader = () => {
|
||||
|
|
|
@ -418,6 +418,16 @@ export const convertObjectPropsToCamelCase = (obj = {}) => {
|
|||
|
||||
export const imagePath = imgUrl => `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/${imgUrl}`;
|
||||
|
||||
export const addSelectOnFocusBehaviour = (selector = '.js-select-on-focus') => {
|
||||
// Click a .js-select-on-focus field, select the contents
|
||||
// Prevent a mouseup event from deselecting the input
|
||||
$(selector).on('focusin', function selectOnFocusCallback() {
|
||||
$(this).select().one('mouseup', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
window.gl = window.gl || {};
|
||||
window.gl.utils = {
|
||||
...(window.gl.utils || {}),
|
||||
|
|
|
@ -10,7 +10,7 @@ window.jQuery = jQuery;
|
|||
window.$ = jQuery;
|
||||
|
||||
// lib/utils
|
||||
import { handleLocationHash } from './lib/utils/common_utils';
|
||||
import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils';
|
||||
import { localTimeAgo } from './lib/utils/datetime_utility';
|
||||
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
|
||||
|
||||
|
@ -104,13 +104,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
return true;
|
||||
});
|
||||
|
||||
// Click a .js-select-on-focus field, select the contents
|
||||
// Prevent a mouseup event from deselecting the input
|
||||
$('.js-select-on-focus').on('focusin', function selectOnFocusCallback() {
|
||||
$(this).select().one('mouseup', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
addSelectOnFocusBehaviour('.js-select-on-focus');
|
||||
|
||||
$('.remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() {
|
||||
$(this).tooltip('destroy')
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import UserCallout from '../../../../user_callout';
|
||||
import UserCallout from '~/user_callout';
|
||||
|
||||
export default () => new UserCallout();
|
||||
document.addEventListener('DOMContentLoaded', () => new UserCallout());
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import groupAvatar from '../../../../group_avatar';
|
||||
import groupAvatar from '~/group_avatar';
|
||||
|
||||
export default () => groupAvatar();
|
||||
document.addEventListener('DOMContentLoaded', groupAvatar);
|
||||
|
|
|
@ -2,8 +2,8 @@ import BindInOut from '../../../../behaviors/bind_in_out';
|
|||
import Group from '../../../../group';
|
||||
import groupAvatar from '../../../../group_avatar';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
BindInOut.initAll();
|
||||
new Group(); // eslint-disable-line no-new
|
||||
groupAvatar();
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import DueDateSelectors from '../../../due_date_select';
|
||||
import DueDateSelectors from '~/due_date_select';
|
||||
|
||||
export default () => new DueDateSelectors();
|
||||
document.addEventListener('DOMContentLoaded', () => new DueDateSelectors());
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import CILintEditor from '../ci_lint_editor';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => new CILintEditor());
|
|
@ -1,3 +0,0 @@
|
|||
import CILintEditor from './ci_lint_editor';
|
||||
|
||||
export default () => new CILintEditor();
|
|
@ -0,0 +1,3 @@
|
|||
import CILintEditor from '../ci_lint_editor';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => new CILintEditor());
|
|
@ -1,3 +1,3 @@
|
|||
import initGroupsList from '~/groups';
|
||||
|
||||
export default initGroupsList;
|
||||
document.addEventListener('DOMContentLoaded', initGroupsList);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Activities from '~/activities';
|
||||
|
||||
export default () => new Activities();
|
||||
document.addEventListener('DOMContentLoaded', () => new Activities());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import groupAvatar from '~/group_avatar';
|
||||
import TransferDropdown from '~/groups/transfer_dropdown';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
groupAvatar();
|
||||
new TransferDropdown(); // eslint-disable-line no-new
|
||||
};
|
||||
});
|
||||
|
|
|
@ -4,8 +4,8 @@ import memberExpirationDate from '~/member_expiration_date';
|
|||
import Members from '~/members';
|
||||
import UsersSelect from '~/users_select';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
memberExpirationDate();
|
||||
new Members();
|
||||
new UsersSelect();
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Labels from '~/labels';
|
||||
|
||||
export default () => new Labels();
|
||||
document.addEventListener('DOMContentLoaded', () => new Labels());
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import initLabels from '~/init_labels';
|
||||
|
||||
export default initLabels;
|
||||
document.addEventListener('DOMContentLoaded', initLabels);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Labels from '~/labels';
|
||||
|
||||
export default () => new Labels();
|
||||
document.addEventListener('DOMContentLoaded', () => new Labels());
|
||||
|
|
|
@ -2,8 +2,8 @@ import BindInOut from '~/behaviors/bind_in_out';
|
|||
import Group from '~/group';
|
||||
import groupAvatar from '~/group_avatar';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
BindInOut.initAll();
|
||||
new Group(); // eslint-disable-line no-new
|
||||
groupAvatar();
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const variableListEl = document.querySelector('.js-ci-variable-list-section');
|
||||
// eslint-disable-next-line no-new
|
||||
new AjaxVariableList({
|
||||
|
@ -9,4 +9,4 @@ export default () => {
|
|||
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
|
||||
saveEndpoint: variableListEl.dataset.saveEndpoint,
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import UsersSelect from '../../../../users_select';
|
||||
import UsersSelect from '~/users_select';
|
||||
|
||||
export default () => new UsersSelect();
|
||||
document.addEventListener('DOMContentLoaded', () => new UsersSelect());
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import DueDateSelectors from '../../../due_date_select';
|
||||
import DueDateSelectors from '~/due_date_select';
|
||||
|
||||
export default () => new DueDateSelectors();
|
||||
document.addEventListener('DOMContentLoaded', () => new DueDateSelectors());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import BuildArtifacts from '~/build_artifacts';
|
||||
import ShortcutsNavigation from '~/shortcuts_navigation';
|
||||
|
||||
export default function () {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new ShortcutsNavigation(); // eslint-disable-line no-new
|
||||
new BuildArtifacts(); // eslint-disable-line no-new
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import BlobViewer from '~/blob/viewer/index';
|
||||
import ShortcutsNavigation from '~/shortcuts_navigation';
|
||||
|
||||
export default function () {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new ShortcutsNavigation(); // eslint-disable-line no-new
|
||||
new BlobViewer(); // eslint-disable-line no-new
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import initBlob from '~/pages/projects/init_blob';
|
||||
|
||||
export default initBlob;
|
||||
document.addEventListener('DOMContentLoaded', initBlob);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import BlobViewer from '~/blob/viewer/index';
|
||||
import initBlob from '~/pages/projects/init_blob';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new BlobViewer(); // eslint-disable-line no-new
|
||||
initBlob();
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ProjectFindFile from '~/project_find_file';
|
||||
import ShortcutsFindFile from '~/shortcuts_find_file';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const findElement = document.querySelector('.js-file-finder');
|
||||
const projectFindFile = new ProjectFindFile($('.file-finder-holder'), {
|
||||
url: findElement.dataset.fileFindUrl,
|
||||
|
@ -9,4 +9,4 @@ export default () => {
|
|||
blobUrlTemplate: findElement.dataset.blobUrlTemplate,
|
||||
});
|
||||
new ShortcutsFindFile(projectFindFile); // eslint-disable-line no-new
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import ProjectFork from '~/project_fork';
|
||||
|
||||
export default () => {
|
||||
new ProjectFork(); // eslint-disable-line no-new
|
||||
};
|
||||
document.addEventListener('DOMContentLoaded', () => new ProjectFork());
|
||||
|
|
|
@ -3,6 +3,7 @@ import Issue from '~/issue';
|
|||
import ShortcutsIssuable from '~/shortcuts_issuable';
|
||||
import ZenMode from '~/zen_mode';
|
||||
import '~/notes/index';
|
||||
import '~/issue_show/index';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new Issue(); // eslint-disable-line no-new
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Labels from '~/labels';
|
||||
|
||||
export default () => new Labels();
|
||||
document.addEventListener('DOMContentLoaded', () => new Labels());
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import initLabels from '~/init_labels';
|
||||
|
||||
export default initLabels;
|
||||
document.addEventListener('DOMContentLoaded', initLabels);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Labels from '~/labels';
|
||||
|
||||
export default () => new Labels();
|
||||
document.addEventListener('DOMContentLoaded', () => new Labels());
|
||||
|
|
|
@ -50,7 +50,7 @@ export default class Project {
|
|||
Project.projectSelectDropdown();
|
||||
}
|
||||
|
||||
static projectSelectDropdown () {
|
||||
static projectSelectDropdown() {
|
||||
projectSelect();
|
||||
$('.project-item-select').on('click', e => Project.changeProject($(e.currentTarget).val()));
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ import UsersSelect from '../../../users_select';
|
|||
import groupsSelect from '../../../groups_select';
|
||||
import Members from '../../../members';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
memberExpirationDate('.js-access-expiration-date-groups');
|
||||
groupsSelect();
|
||||
memberExpirationDate();
|
||||
new Members(); // eslint-disable-line no-new
|
||||
new UsersSelect(); // eslint-disable-line no-new
|
||||
};
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import initSettingsPanels from '~/settings_panels';
|
|||
import SecretValues from '~/behaviors/secret_values';
|
||||
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
|
||||
|
||||
export default function () {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Initialize expandable settings panels
|
||||
initSettingsPanels();
|
||||
|
||||
|
@ -22,4 +22,4 @@ export default function () {
|
|||
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
|
||||
saveEndpoint: variableListEl.dataset.saveEndpoint,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import initSettingsPanels from '~/settings_panels';
|
||||
import initDeployKeys from '~/deploy_keys';
|
||||
|
||||
export default initSettingsPanels;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initDeployKeys();
|
||||
initSettingsPanels();
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ import BlobViewer from '../../../../blob/viewer';
|
|||
import NewCommitForm from '../../../../new_commit_form';
|
||||
import { ajaxGet } from '../../../../lib/utils/common_utils';
|
||||
|
||||
export default () => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new ShortcutsNavigation(); // eslint-disable-line no-new
|
||||
new TreeView(); // eslint-disable-line no-new
|
||||
new BlobViewer(); // eslint-disable-line no-new
|
||||
|
@ -35,5 +35,4 @@ export default () => {
|
|||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import Search from './search';
|
||||
|
||||
export default () => new Search();
|
||||
document.addEventListener('DOMContentLoaded', () => new Search());
|
||||
|
|
|
@ -31,10 +31,14 @@
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
pipelineId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -46,17 +50,27 @@
|
|||
return `btn ${this.cssClass}`;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// We're using eventHub to listen to the modal here instead of
|
||||
// using props because it would would make the parent components
|
||||
// much more complex to keep track of the loading state of each button
|
||||
eventHub.$on('postAction', this.setLoading);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('postAction', this.setLoading);
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
eventHub.$emit('actionConfirmationModal', {
|
||||
id: this.id,
|
||||
callback: this.makeRequest,
|
||||
eventHub.$emit('openConfirmationModal', {
|
||||
pipelineId: this.pipelineId,
|
||||
endpoint: this.endpoint,
|
||||
type: this.type,
|
||||
});
|
||||
},
|
||||
makeRequest() {
|
||||
this.isLoading = true;
|
||||
|
||||
eventHub.$emit('postAction', this.endpoint);
|
||||
setLoading(endpoint) {
|
||||
if (endpoint === this.endpoint) {
|
||||
this.isLoading = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
jobComponent,
|
||||
dropdownJobComponent,
|
||||
},
|
||||
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script>
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import pipelinesTableRowComponent from './pipelines_table_row.vue';
|
||||
import stopConfirmationModal from './stop_confirmation_modal.vue';
|
||||
import retryConfirmationModal from './retry_confirmation_modal.vue';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
/**
|
||||
* Pipelines Table Component.
|
||||
|
@ -11,8 +12,7 @@
|
|||
export default {
|
||||
components: {
|
||||
pipelinesTableRowComponent,
|
||||
stopConfirmationModal,
|
||||
retryConfirmationModal,
|
||||
modal,
|
||||
},
|
||||
props: {
|
||||
pipelines: {
|
||||
|
@ -33,6 +33,52 @@
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pipelineId: '',
|
||||
endpoint: '',
|
||||
type: '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
modalTitle() {
|
||||
return this.type === 'stop' ?
|
||||
sprintf(s__('Pipeline|Stop pipeline #%{pipelineId}?'), {
|
||||
pipelineId: `'${this.pipelineId}'`,
|
||||
}, false) :
|
||||
sprintf(s__('Pipeline|Retry pipeline #%{pipelineId}?'), {
|
||||
pipelineId: `'${this.pipelineId}'`,
|
||||
}, false);
|
||||
},
|
||||
modalText() {
|
||||
return this.type === 'stop' ?
|
||||
sprintf(s__('Pipeline|You’re about to stop pipeline %{pipelineId}.'), {
|
||||
pipelineId: `<strong>#${this.pipelineId}</strong>`,
|
||||
}, false) :
|
||||
sprintf(s__('Pipeline|You’re about to retry pipeline %{pipelineId}.'), {
|
||||
pipelineId: `<strong>#${this.pipelineId}</strong>`,
|
||||
}, false);
|
||||
},
|
||||
primaryButtonLabel() {
|
||||
return this.type === 'stop' ? s__('Pipeline|Stop pipeline') : s__('Pipeline|Retry pipeline');
|
||||
},
|
||||
},
|
||||
created() {
|
||||
eventHub.$on('openConfirmationModal', this.setModalData);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('openConfirmationModal', this.setModalData);
|
||||
},
|
||||
methods: {
|
||||
setModalData(data) {
|
||||
this.pipelineId = data.pipelineId;
|
||||
this.endpoint = data.endpoint;
|
||||
this.type = data.type;
|
||||
},
|
||||
onSubmit() {
|
||||
eventHub.$emit('postAction', this.endpoint);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
@ -74,7 +120,20 @@
|
|||
:auto-devops-help-path="autoDevopsHelpPath"
|
||||
:view-type="viewType"
|
||||
/>
|
||||
<stop-confirmation-modal />
|
||||
<retry-confirmation-modal />
|
||||
<modal
|
||||
id="confirmation-modal"
|
||||
:title="modalTitle"
|
||||
:text="modalText"
|
||||
kind="danger"
|
||||
:primary-button-label="primaryButtonLabel"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<template
|
||||
slot="body"
|
||||
slot-scope="props"
|
||||
>
|
||||
<p v-html="props.text"></p>
|
||||
</template>
|
||||
</modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -223,7 +223,8 @@
|
|||
<div class="table-section section-10 commit-link">
|
||||
<div
|
||||
class="table-mobile-header"
|
||||
role="rowheader">
|
||||
role="rowheader"
|
||||
>
|
||||
Status
|
||||
</div>
|
||||
<div class="table-mobile-content">
|
||||
|
@ -305,9 +306,10 @@
|
|||
css-class="js-pipelines-retry-button btn-default btn-retry"
|
||||
title="Retry"
|
||||
icon="repeat"
|
||||
:id="pipeline.id"
|
||||
:pipeline-id="pipeline.id"
|
||||
data-toggle="modal"
|
||||
data-target="#retry-confirmation-modal"
|
||||
data-target="#confirmation-modal"
|
||||
type="retry"
|
||||
/>
|
||||
|
||||
<async-button-component
|
||||
|
@ -316,9 +318,10 @@
|
|||
css-class="js-pipelines-cancel-button btn-remove"
|
||||
title="Cancel"
|
||||
icon="close"
|
||||
:id="pipeline.id"
|
||||
:pipeline-id="pipeline.id"
|
||||
data-toggle="modal"
|
||||
data-target="#stop-confirmation-modal"
|
||||
data-target="#confirmation-modal"
|
||||
type="stop"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
<script>
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: '',
|
||||
callback: () => {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return sprintf(s__('Pipeline|Retry pipeline #%{id}?'), {
|
||||
id: `'${this.id}'`,
|
||||
}, false);
|
||||
},
|
||||
text() {
|
||||
return sprintf(s__('Pipeline|You’re about to retry pipeline %{id}.'), {
|
||||
id: `<strong>#${this.id}</strong>`,
|
||||
}, false);
|
||||
},
|
||||
primaryButtonLabel() {
|
||||
return s__('Pipeline|Retry pipeline');
|
||||
},
|
||||
},
|
||||
created() {
|
||||
eventHub.$on('actionConfirmationModal', this.updateModal);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('actionConfirmationModal', this.updateModal);
|
||||
},
|
||||
methods: {
|
||||
updateModal(action) {
|
||||
this.id = action.id;
|
||||
this.callback = action.callback;
|
||||
},
|
||||
onSubmit() {
|
||||
this.callback();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
id="retry-confirmation-modal"
|
||||
:title="title"
|
||||
:text="text"
|
||||
kind="danger"
|
||||
:primary-button-label="primaryButtonLabel"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<template
|
||||
slot="body"
|
||||
slot-scope="props"
|
||||
>
|
||||
<p v-html="props.text"></p>
|
||||
</template>
|
||||
</modal>
|
||||
</template>
|
|
@ -50,9 +50,7 @@
|
|||
|
||||
computed: {
|
||||
dropdownClass() {
|
||||
return this.dropdownContent.length > 0 ?
|
||||
'js-builds-dropdown-container' :
|
||||
'js-builds-dropdown-loading';
|
||||
return this.dropdownContent.length > 0 ? 'js-builds-dropdown-container' : 'js-builds-dropdown-loading';
|
||||
},
|
||||
|
||||
triggerButtonClass() {
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
<script>
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: '',
|
||||
callback: () => {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return sprintf(s__('Pipeline|Stop pipeline #%{id}?'), {
|
||||
id: `'${this.id}'`,
|
||||
}, false);
|
||||
},
|
||||
text() {
|
||||
return sprintf(s__('Pipeline|You’re about to stop pipeline %{id}.'), {
|
||||
id: `<strong>#${this.id}</strong>`,
|
||||
}, false);
|
||||
},
|
||||
primaryButtonLabel() {
|
||||
return s__('Pipeline|Stop pipeline');
|
||||
},
|
||||
},
|
||||
created() {
|
||||
eventHub.$on('actionConfirmationModal', this.updateModal);
|
||||
},
|
||||
beforeDestroy() {
|
||||
eventHub.$off('actionConfirmationModal', this.updateModal);
|
||||
},
|
||||
methods: {
|
||||
updateModal(action) {
|
||||
this.id = action.id;
|
||||
this.callback = action.callback;
|
||||
},
|
||||
onSubmit() {
|
||||
this.callback();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
id="stop-confirmation-modal"
|
||||
:title="title"
|
||||
:text="text"
|
||||
kind="danger"
|
||||
:primary-button-label="primaryButtonLabel"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<template
|
||||
slot="body"
|
||||
slot-scope="props"
|
||||
>
|
||||
<p v-html="props.text"></p>
|
||||
</template>
|
||||
</modal>
|
||||
</template>
|
|
@ -73,7 +73,7 @@ export default class ProjectFindFile {
|
|||
// find file
|
||||
}
|
||||
|
||||
// files pathes load
|
||||
// files pathes load
|
||||
load(url) {
|
||||
axios.get(url)
|
||||
.then(({ data }) => {
|
||||
|
@ -85,7 +85,7 @@ export default class ProjectFindFile {
|
|||
.catch(() => flash(__('An error occurred while loading filenames')));
|
||||
}
|
||||
|
||||
// render result
|
||||
// render result
|
||||
renderList(filePaths, searchText) {
|
||||
var blobItemUrl, filePath, html, i, j, len, matches, results;
|
||||
this.element.find(".tree-table > tbody").empty();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { addSelectOnFocusBehaviour } from '../lib/utils/common_utils';
|
||||
|
||||
let hasUserDefinedProjectPath = false;
|
||||
|
||||
const deriveProjectPathFromUrl = ($projectImportUrl) => {
|
||||
|
@ -36,6 +38,7 @@ const bindEvents = () => {
|
|||
const $changeTemplateBtn = $('.change-template');
|
||||
const $selectedIcon = $('.selected-icon svg');
|
||||
const $templateProjectNameInput = $('#template-project-name #project_path');
|
||||
const $pushNewProjectTipTrigger = $('.push-new-project-tip');
|
||||
|
||||
if ($newProjectForm.length !== 1) {
|
||||
return;
|
||||
|
@ -55,6 +58,34 @@ const bindEvents = () => {
|
|||
$('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$projectPath.val()}`);
|
||||
});
|
||||
|
||||
if ($pushNewProjectTipTrigger) {
|
||||
$pushNewProjectTipTrigger
|
||||
.removeAttr('rel')
|
||||
.removeAttr('target')
|
||||
.on('click', (e) => { e.preventDefault(); })
|
||||
.popover({
|
||||
title: $pushNewProjectTipTrigger.data('title'),
|
||||
placement: 'auto bottom',
|
||||
html: 'true',
|
||||
content: $('.push-new-project-tip-template').html(),
|
||||
})
|
||||
.on('shown.bs.popover', () => {
|
||||
$(document).on('click.popover touchstart.popover', (event) => {
|
||||
if ($(event.target).closest('.popover').length === 0) {
|
||||
$pushNewProjectTipTrigger.trigger('click');
|
||||
}
|
||||
});
|
||||
|
||||
const target = $(`#${$pushNewProjectTipTrigger.attr('aria-describedby')}`).find('.js-select-on-focus');
|
||||
addSelectOnFocusBehaviour(target);
|
||||
|
||||
target.focus();
|
||||
})
|
||||
.on('hide.bs.popover', () => {
|
||||
$(document).off('click.popover touchstart.popover');
|
||||
});
|
||||
}
|
||||
|
||||
function chooseTemplate() {
|
||||
$('.template-option').hide();
|
||||
$projectFieldsForm.addClass('selected');
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import renderMath from './render_math';
|
||||
import renderMermaid from './render_mermaid';
|
||||
import syntaxHighlight from './syntax_highlight';
|
||||
|
||||
// Render Gitlab flavoured Markdown
|
||||
//
|
||||
// Delegates to syntax highlight and render math & mermaid diagrams.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import Flash from '../../../flash';
|
||||
import Flash from '~/flash';
|
||||
import editForm from './edit_form.vue';
|
||||
import issuableMixin from '../../../vue_shared/mixins/issuable';
|
||||
import Icon from '../../../vue_shared/components/icon.vue';
|
||||
|
@ -53,8 +53,7 @@
|
|||
discussion_locked: locked,
|
||||
})
|
||||
.then(() => location.reload())
|
||||
.catch(() => Flash(this.__(`Something went wrong trying to
|
||||
change the locked state of this ${this.issuableDisplayName}`)));
|
||||
.catch(() => Flash(this.__(`Something went wrong trying to change the locked state of this ${this.issuableDisplayName}`)));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -39,7 +39,6 @@ function UsersSelect(currentUser, els, options = {}) {
|
|||
options.showCurrentUser = $dropdown.data('currentUser');
|
||||
options.todoFilter = $dropdown.data('todoFilter');
|
||||
options.todoStateFilter = $dropdown.data('todoStateFilter');
|
||||
options.perPage = $dropdown.data('perPage');
|
||||
showNullUser = $dropdown.data('nullUser');
|
||||
defaultNullUser = $dropdown.data('nullUserDefault');
|
||||
showMenuAbove = $dropdown.data('showMenuAbove');
|
||||
|
@ -669,7 +668,6 @@ UsersSelect.prototype.users = function(query, options, callback) {
|
|||
const url = this.buildUrl(this.usersPath);
|
||||
const params = {
|
||||
search: query,
|
||||
per_page: options.perPage || 20,
|
||||
active: true,
|
||||
project_id: options.projectId || null,
|
||||
group_id: options.groupId || null,
|
||||
|
|
|
@ -107,7 +107,8 @@
|
|||
<template v-if="!mr.rebaseInProgress && mr.canPushToSourceBranch && !isMakingRequest">
|
||||
<div
|
||||
class="accept-merge-holder clearfix
|
||||
js-toggle-container accept-action media space-children">
|
||||
js-toggle-container accept-action media space-children"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-reopen btn-success"
|
||||
|
|
|
@ -96,9 +96,7 @@ export default {
|
|||
cb.call(null, data);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
new Flash('Something went wrong. Please try again.'); // eslint-disable-line
|
||||
});
|
||||
.catch(() => new Flash('Something went wrong. Please try again.'));
|
||||
},
|
||||
initPolling() {
|
||||
this.pollingInterval = new SmartInterval({
|
||||
|
@ -146,9 +144,7 @@ export default {
|
|||
Project.initRefSwitcher();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
new Flash('Something went wrong. Please try again.'); // eslint-disable-line
|
||||
});
|
||||
.catch(() => new Flash('Something went wrong. Please try again.'));
|
||||
},
|
||||
handleNotification(data) {
|
||||
if (data.ci_status === this.mr.ciStatus) return;
|
||||
|
|
|
@ -4,7 +4,6 @@ import { stateKey } from './state_maps';
|
|||
import { formatDate } from '../../lib/utils/datetime_utility';
|
||||
|
||||
export default class MergeRequestStore {
|
||||
|
||||
constructor(data) {
|
||||
this.sha = data.diff_head_sha;
|
||||
this.gitlabLogo = data.gitlabLogo;
|
||||
|
@ -169,5 +168,4 @@ export default class MergeRequestStore {
|
|||
|
||||
return timeagoInstance.format(date);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
import userAvatarImage from './user_avatar/user_avatar_image.vue';
|
||||
|
||||
/**
|
||||
* Renders header component for job and pipeline page based on UI mockups
|
||||
*
|
||||
* Used in:
|
||||
* - job show page
|
||||
* - pipeline show page
|
||||
*/
|
||||
* Renders header component for job and pipeline page based on UI mockups
|
||||
*
|
||||
* Used in:
|
||||
* - job show page
|
||||
* - pipeline show page
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
ciIconBadge,
|
||||
|
@ -118,7 +118,8 @@
|
|||
|
||||
<section
|
||||
class="header-action-buttons"
|
||||
v-if="actions.length">
|
||||
v-if="actions.length"
|
||||
>
|
||||
<template
|
||||
v-for="(action, i) in actions"
|
||||
>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
/* eslint-disable vue/require-default-prop */
|
||||
|
||||
/* This is a re-usable vue component for rendering a button
|
||||
that will probably be sending off ajax requests and need
|
||||
to show the loading status by setting the `loading` option.
|
||||
|
|
|
@ -65,7 +65,8 @@
|
|||
</li>
|
||||
<li
|
||||
class="md-header-tab"
|
||||
:class="{ active: previewMarkdown }">
|
||||
:class="{ active: previewMarkdown }"
|
||||
>
|
||||
<a
|
||||
class="js-preview-link"
|
||||
href="#md-preview-holder"
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
props: {
|
||||
/**
|
||||
This function will take the information given by the pagination component
|
||||
|
||||
Here is an example `change` method:
|
||||
|
||||
change(pagenum) {
|
||||
gl.utils.visitUrl(`?page=${pagenum}`);
|
||||
},
|
||||
*/
|
||||
change: {
|
||||
type: Function,
|
||||
|
|
|
@ -444,6 +444,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
.btn-missing {
|
||||
color: $notes-light-color;
|
||||
border: 1px dashed $border-gray-normal-dashed;
|
||||
border-radius: $border-radius-default;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: $notes-light-color;
|
||||
background-color: $white-normal;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-svg svg {
|
||||
@include btn-svg;
|
||||
}
|
||||
|
|
|
@ -63,10 +63,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.project-stats {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.group-buttons {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
transition: padding $sidebar-transition-duration;
|
||||
|
||||
.container-fluid {
|
||||
background: $white-light;
|
||||
padding: 0 $gl-padding;
|
||||
|
||||
&.container-blank {
|
||||
|
|
|
@ -296,7 +296,7 @@ body {
|
|||
line-height: 1.3;
|
||||
font-size: 1.25em;
|
||||
font-weight: $gl-font-weight-bold;
|
||||
margin: 12px 7px;
|
||||
margin: 12px 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
|
@ -333,6 +333,10 @@ a > code {
|
|||
font-family: $monospace_font;
|
||||
}
|
||||
|
||||
.weight-normal {
|
||||
font-weight: $gl-font-weight-normal;
|
||||
}
|
||||
|
||||
.commit-sha,
|
||||
.ref-name {
|
||||
@extend .monospace;
|
||||
|
|
|
@ -215,8 +215,8 @@ $tooltip-font-size: 12px;
|
|||
*/
|
||||
$gl-padding: 16px;
|
||||
$gl-padding-8: 8px;
|
||||
$gl-padding-4: 4px;
|
||||
$gl-col-padding: 15px;
|
||||
$gl-btn-padding: 10px;
|
||||
$gl-input-padding: 10px;
|
||||
$gl-vert-padding: 6px;
|
||||
$gl-padding-top: 10px;
|
||||
|
@ -377,6 +377,10 @@ $inactive-badge-background: rgba(0, 0, 0, .08);
|
|||
$btn-active-gray: #ececec;
|
||||
$btn-active-gray-light: e4e7ed;
|
||||
$btn-white-active: #848484;
|
||||
$gl-btn-padding: 10px;
|
||||
$gl-btn-line-height: 16px;
|
||||
$gl-btn-vert-padding: 8px;
|
||||
$gl-btn-horz-padding: 12px;
|
||||
|
||||
/*
|
||||
* Badges
|
||||
|
|
|
@ -678,6 +678,9 @@ a.deploy-project-label {
|
|||
}
|
||||
}
|
||||
|
||||
.project-empty-note-panel {
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
|
||||
.project-stats {
|
||||
font-size: 0;
|
||||
|
@ -686,11 +689,13 @@ a.deploy-project-label {
|
|||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.nav {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
margin-top: $gl-padding-8;
|
||||
margin-bottom: $gl-padding-8;
|
||||
|
||||
> li {
|
||||
display: inline-block;
|
||||
margin-top: $gl-padding-4;
|
||||
margin-bottom: $gl-padding-4;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: $gl-padding;
|
||||
|
@ -704,36 +709,32 @@ a.deploy-project-label {
|
|||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
font-size: 14px;
|
||||
line-height: 29px;
|
||||
color: $notes-light-color;
|
||||
.stat-text,
|
||||
.stat-link {
|
||||
padding: $gl-btn-vert-padding 0;
|
||||
background-color: transparent;
|
||||
font-size: $gl-font-size;
|
||||
line-height: $gl-btn-line-height;
|
||||
color: $notes-light-color;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $gl-text-color;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.stat-link {
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $gl-text-color;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li.missing {
|
||||
border: 1px dashed $border-gray-normal-dashed;
|
||||
border-radius: $border-radius-default;
|
||||
|
||||
a {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: $notes-light-color;
|
||||
display: block;
|
||||
.btn {
|
||||
padding: $gl-btn-vert-padding $gl-btn-horz-padding;
|
||||
line-height: $gl-btn-line-height;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $gray-normal;
|
||||
.btn-missing {
|
||||
@extend .btn-missing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -743,7 +744,7 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.git-empty {
|
||||
margin: 0 7px 7px;
|
||||
margin-bottom: 7px;
|
||||
|
||||
h5 {
|
||||
color: $gl-text-color;
|
||||
|
@ -895,6 +896,12 @@ pre.light-well {
|
|||
}
|
||||
}
|
||||
|
||||
.project-tip-command {
|
||||
> .input-group-btn:first-child {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.protected-branches-list,
|
||||
.protected-tags-list {
|
||||
margin-bottom: 30px;
|
||||
|
|
|
@ -126,10 +126,15 @@ class ApplicationController < ActionController::Base
|
|||
Ability.allowed?(object, action, subject)
|
||||
end
|
||||
|
||||
def access_denied!
|
||||
def access_denied!(message = nil)
|
||||
respond_to do |format|
|
||||
format.json { head :not_found }
|
||||
format.any { render "errors/access_denied", layout: "errors", status: 404 }
|
||||
format.any { head :not_found }
|
||||
format.html do
|
||||
render "errors/access_denied",
|
||||
layout: "errors",
|
||||
status: 404,
|
||||
locals: { message: message }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module Boards
|
|||
end
|
||||
|
||||
def issue
|
||||
@issue ||= issues_finder.execute.find(params[:id])
|
||||
@issue ||= issues_finder.find(params[:id])
|
||||
end
|
||||
|
||||
def filter_params
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
module ControllerWithCrossProjectAccessCheck
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
extend Gitlab::CrossProjectAccess::ClassMethods
|
||||
before_action :cross_project_check
|
||||
end
|
||||
|
||||
def cross_project_check
|
||||
if Gitlab::CrossProjectAccess.find_check(self)&.should_run?(self)
|
||||
authorize_cross_project_page!
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_cross_project_page!
|
||||
return if can?(current_user, :read_cross_project)
|
||||
|
||||
rejection_message = _(
|
||||
"This page is unavailable because you are not allowed to read information "\
|
||||
"across multiple projects."
|
||||
)
|
||||
access_denied!(rejection_message)
|
||||
end
|
||||
end
|
|
@ -3,16 +3,20 @@ module RoutableActions
|
|||
|
||||
def find_routable!(routable_klass, requested_full_path, extra_authorization_proc: nil)
|
||||
routable = routable_klass.find_by_full_path(requested_full_path, follow_redirects: request.get?)
|
||||
|
||||
if routable_authorized?(routable, extra_authorization_proc)
|
||||
ensure_canonical_path(routable, requested_full_path)
|
||||
routable
|
||||
else
|
||||
route_not_found
|
||||
handle_not_found_or_authorized(routable)
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# This is overridden in gitlab-ee.
|
||||
def handle_not_found_or_authorized(_routable)
|
||||
route_not_found
|
||||
end
|
||||
|
||||
def routable_authorized?(routable, extra_authorization_proc)
|
||||
action = :"read_#{routable.class.to_s.underscore}"
|
||||
return false unless can?(current_user, action, routable)
|
||||
|
|
|
@ -24,7 +24,7 @@ module UploadsActions
|
|||
# - or redirect to its URL
|
||||
#
|
||||
def show
|
||||
return render_404 unless uploader.exists?
|
||||
return render_404 unless uploader&.exists?
|
||||
|
||||
if uploader.file_storage?
|
||||
disposition = uploader.image_or_video? ? 'inline' : 'attachment'
|
||||
|
@ -71,6 +71,9 @@ module UploadsActions
|
|||
|
||||
def build_uploader_from_params
|
||||
uploader = uploader_class.new(model, secret: params[:secret])
|
||||
|
||||
return nil unless uploader.model_valid?
|
||||
|
||||
uploader.retrieve_from_store!(params[:filename])
|
||||
uploader
|
||||
end
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
class Dashboard::ApplicationController < ApplicationController
|
||||
include ControllerWithCrossProjectAccessCheck
|
||||
|
||||
layout 'dashboard'
|
||||
|
||||
requires_cross_project_access
|
||||
|
||||
private
|
||||
|
||||
def projects
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class Dashboard::GroupsController < Dashboard::ApplicationController
|
||||
include GroupTree
|
||||
|
||||
skip_cross_project_access_check :index
|
||||
|
||||
def index
|
||||
groups = GroupsFinder.new(current_user, all_available: false).execute
|
||||
render_group_tree(groups)
|
||||
|
|
|
@ -4,6 +4,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
|
||||
before_action :set_non_archived_param
|
||||
before_action :default_sorting
|
||||
skip_cross_project_access_check :index, :starred
|
||||
|
||||
def index
|
||||
@projects = load_projects(params.merge(non_public: true)).page(params[:page])
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Dashboard::SnippetsController < Dashboard::ApplicationController
|
||||
skip_cross_project_access_check :index
|
||||
|
||||
def index
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
class Groups::ApplicationController < ApplicationController
|
||||
include RoutableActions
|
||||
include ControllerWithCrossProjectAccessCheck
|
||||
|
||||
layout 'group'
|
||||
|
||||
skip_before_action :authenticate_user!
|
||||
before_action :group
|
||||
requires_cross_project_access
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class Groups::AvatarsController < Groups::ApplicationController
|
||||
before_action :authorize_admin_group!
|
||||
|
||||
skip_cross_project_access_check :destroy
|
||||
|
||||
def destroy
|
||||
@group.remove_avatar!
|
||||
@group.save
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Groups
|
||||
class ChildrenController < Groups::ApplicationController
|
||||
before_action :group
|
||||
skip_cross_project_access_check :index
|
||||
|
||||
def index
|
||||
parent = if params[:parent_id].present?
|
||||
|
|
|
@ -6,6 +6,10 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
# Authorize
|
||||
before_action :authorize_admin_group_member!, except: [:index, :leave, :request_access]
|
||||
|
||||
skip_cross_project_access_check :index, :create, :update, :destroy, :request_access,
|
||||
:approve_access_request, :leave, :resend_invite,
|
||||
:override
|
||||
|
||||
def index
|
||||
@sort = params[:sort].presence || sort_value_name
|
||||
@project = @group.projects.find(params[:project_id]) if params[:project_id]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Groups
|
||||
module Settings
|
||||
class CiCdController < Groups::ApplicationController
|
||||
skip_cross_project_access_check :show
|
||||
before_action :authorize_admin_pipeline!
|
||||
|
||||
def show
|
||||
|
|
|
@ -2,6 +2,8 @@ module Groups
|
|||
class VariablesController < Groups::ApplicationController
|
||||
before_action :authorize_admin_build!
|
||||
|
||||
skip_cross_project_access_check :show, :update
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
|
|
|
@ -19,6 +19,12 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
before_action :user_actions, only: [:show, :subgroups]
|
||||
|
||||
skip_cross_project_access_check :index, :new, :create, :edit, :update,
|
||||
:destroy, :projects
|
||||
# When loading show as an atom feed, we render events that could leak cross
|
||||
# project information
|
||||
skip_cross_project_access_check :show, if: -> { request.format.html? }
|
||||
|
||||
layout :determine_layout
|
||||
|
||||
def index
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
||||
include Gitlab::GonHelper
|
||||
include Gitlab::Allowable
|
||||
include PageLayoutHelper
|
||||
include OauthApplications
|
||||
|
||||
|
@ -8,6 +9,8 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
|||
before_action :add_gon_variables
|
||||
before_action :load_scopes, only: [:index, :create, :edit]
|
||||
|
||||
helper_method :can?
|
||||
|
||||
layout 'profile'
|
||||
|
||||
def index
|
||||
|
|
|
@ -34,9 +34,9 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
|
|||
def target
|
||||
case params[:type]&.downcase
|
||||
when 'issue'
|
||||
IssuesFinder.new(current_user, project_id: @project.id).execute.find_by(iid: params[:type_id])
|
||||
IssuesFinder.new(current_user, project_id: @project.id).find_by(iid: params[:type_id])
|
||||
when 'mergerequest'
|
||||
MergeRequestsFinder.new(current_user, project_id: @project.id).execute.find_by(iid: params[:type_id])
|
||||
MergeRequestsFinder.new(current_user, project_id: @project.id).find_by(iid: params[:type_id])
|
||||
when 'commit'
|
||||
@project.commit(params[:type_id])
|
||||
end
|
||||
|
|
|
@ -133,7 +133,7 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def after_edit_path
|
||||
from_merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.find_by(iid: params[:from_merge_request_iid])
|
||||
from_merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).find_by(iid: params[:from_merge_request_iid])
|
||||
if from_merge_request && @branch_name == @ref
|
||||
diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) +
|
||||
"##{hexdigest(@path)}"
|
||||
|
|
|
@ -40,9 +40,9 @@ class Projects::Clusters::GcpController < Projects::ApplicationController
|
|||
def verify_billing
|
||||
case google_project_billing_status
|
||||
when nil
|
||||
flash[:alert] = _('We could not verify that one of your projects on GCP has billing enabled. Please try again.')
|
||||
flash.now[:alert] = _('We could not verify that one of your projects on GCP has billing enabled. Please try again.')
|
||||
when false
|
||||
flash[:alert] = _('Please <a href=%{link_to_billing} target="_blank" rel="noopener noreferrer">enable billing for one of your projects to be able to create a Kubernetes cluster</a>, then try again.').html_safe % { link_to_billing: "https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral" }
|
||||
flash.now[:alert] = _('Please <a href=%{link_to_billing} target="_blank" rel="noopener noreferrer">enable billing for one of your projects to be able to create a Kubernetes cluster</a>, then try again.').html_safe % { link_to_billing: "https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral" }
|
||||
when true
|
||||
return
|
||||
end
|
||||
|
|
|
@ -75,7 +75,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
|
|||
def branch_to
|
||||
@target_project = selected_target_project
|
||||
|
||||
if params[:ref].present?
|
||||
if @target_project && params[:ref].present?
|
||||
@ref = params[:ref]
|
||||
@commit = @target_project.commit(Gitlab::Git::BRANCH_REF_PREFIX + @ref)
|
||||
end
|
||||
|
@ -85,7 +85,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
|
|||
|
||||
def update_branches
|
||||
@target_project = selected_target_project
|
||||
@target_branches = @target_project.repository.branch_names
|
||||
@target_branches = @target_project ? @target_project.repository.branch_names : []
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
@ -121,7 +121,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
|
|||
@project
|
||||
elsif params[:target_project_id].present?
|
||||
MergeRequestTargetProjectFinder.new(current_user: current_user, source_project: @project)
|
||||
.execute.find(params[:target_project_id])
|
||||
.find_by(id: params[:target_project_id])
|
||||
else
|
||||
@project.forked_from_project
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
|
||||
before_action :require_pages_enabled!
|
||||
before_action :authorize_update_pages!, except: [:show]
|
||||
before_action :domain, only: [:show, :destroy]
|
||||
before_action :domain, only: [:show, :destroy, :verify]
|
||||
|
||||
def show
|
||||
end
|
||||
|
@ -12,11 +12,23 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
@domain = @project.pages_domains.new
|
||||
end
|
||||
|
||||
def verify
|
||||
result = VerifyPagesDomainService.new(@domain).execute
|
||||
|
||||
if result[:status] == :success
|
||||
flash[:notice] = 'Successfully verified domain ownership'
|
||||
else
|
||||
flash[:alert] = 'Failed to verify domain ownership'
|
||||
end
|
||||
|
||||
redirect_to project_pages_domain_path(@project, @domain)
|
||||
end
|
||||
|
||||
def create
|
||||
@domain = @project.pages_domains.create(pages_domain_params)
|
||||
|
||||
if @domain.valid?
|
||||
redirect_to project_pages_path(@project)
|
||||
redirect_to project_pages_domain_path(@project, @domain)
|
||||
else
|
||||
render 'new'
|
||||
end
|
||||
|
@ -46,6 +58,6 @@ class Projects::PagesDomainsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def domain
|
||||
@domain ||= @project.pages_domains.find_by(domain: params[:id].to_s)
|
||||
@domain ||= @project.pages_domains.find_by!(domain: params[:id].to_s)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
module Projects
|
||||
module Prometheus
|
||||
class MetricsController < Projects::ApplicationController
|
||||
before_action :authorize_admin_project!
|
||||
|
||||
def active_common
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
matched_metrics = prometheus_service.matched_metrics || {}
|
||||
|
||||
if matched_metrics.any?
|
||||
render json: matched_metrics
|
||||
else
|
||||
head :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def prometheus_service
|
||||
@prometheus_service ||= project.find_or_initialize_service('prometheus')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,24 +0,0 @@
|
|||
class Projects::PrometheusController < Projects::ApplicationController
|
||||
before_action :authorize_read_project!
|
||||
before_action :require_prometheus_metrics!
|
||||
|
||||
def active_metrics
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
matched_metrics = project.prometheus_service.matched_metrics || {}
|
||||
|
||||
if matched_metrics.any?
|
||||
render json: matched_metrics
|
||||
else
|
||||
head :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def require_prometheus_metrics!
|
||||
render_404 unless project.prometheus_service.present?
|
||||
end
|
||||
end
|
|
@ -45,7 +45,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
notice: _("Project '%{project_name}' was successfully created.") % { project_name: @project.name }
|
||||
)
|
||||
else
|
||||
render 'new'
|
||||
render 'new', locals: { active_tab: ('import' if project_params[:import_url].present?) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -114,6 +114,8 @@ class ProjectsController < Projects::ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
@notification_setting = current_user.notification_settings_for(@project) if current_user
|
||||
@project = @project.present(current_user: current_user)
|
||||
|
||||
render_landing_page
|
||||
end
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue