Merge remote-tracking branch 'origin/master' into deprecation-warning-for-dynamic-milestones
This commit is contained in:
commit
54a3514180
368 changed files with 3262 additions and 1776 deletions
26
.babelrc
26
.babelrc
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
"presets": [
|
||||
["latest", { "es2015": { "modules": false } }],
|
||||
"stage-2"
|
||||
],
|
||||
"presets": [["latest", { "es2015": { "modules": false } }], "stage-2"],
|
||||
"env": {
|
||||
"coverage": {
|
||||
"plugins": [
|
||||
["istanbul", {
|
||||
"exclude": [
|
||||
"spec/javascripts/**/*",
|
||||
"app/assets/javascripts/locale/**/app.js"
|
||||
]
|
||||
}],
|
||||
["transform-define", {
|
||||
"process.env.BABEL_ENV": "coverage"
|
||||
}]
|
||||
[
|
||||
"istanbul",
|
||||
{
|
||||
"exclude": ["spec/javascripts/**/*", "app/assets/javascripts/locale/**/app.js"]
|
||||
}
|
||||
],
|
||||
[
|
||||
"transform-define",
|
||||
{
|
||||
"process.env.BABEL_ENV": "coverage"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/app/assets/javascripts/locale/**/app.js
|
||||
/config/
|
||||
/builds/
|
||||
/coverage/
|
||||
/coverage-javascript/
|
||||
/node_modules/
|
||||
/public/
|
||||
/scripts/
|
||||
/tmp/
|
||||
/vendor/
|
||||
karma.config.js
|
||||
webpack.config.js
|
||||
svg.config.js
|
||||
/app/assets/javascripts/locale/**/app.js
|
||||
|
|
|
@ -544,7 +544,7 @@ migration:path-mysql:
|
|||
.db-rollback: &db-rollback
|
||||
<<: *dedicated-no-docs-pull-cache-job
|
||||
script:
|
||||
- bundle exec rake db:rollback STEP=119
|
||||
- bundle exec rake db:migrate VERSION=20170523121229
|
||||
- bundle exec rake db:migrate
|
||||
|
||||
db:rollback-pg:
|
||||
|
|
5
.prettierignore
Normal file
5
.prettierignore
Normal file
|
@ -0,0 +1,5 @@
|
|||
/app/assets/javascripts/locale/**/app.js
|
||||
/node_modules/
|
||||
/public/
|
||||
/vendor/
|
||||
/tmp/
|
11
.prettierrc
11
.prettierrc
|
@ -1,4 +1,13 @@
|
|||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
"trailingComma": "es5",
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/app/**/*", "**/spec/**/*"],
|
||||
"options": {
|
||||
"trailingComma": "all"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -118,6 +118,9 @@ Gitlab/ModuleWithInstanceVariables:
|
|||
- spec/support/**/*.rb
|
||||
- features/steps/**/*.rb
|
||||
|
||||
Gitlab/HTTParty:
|
||||
Enabled: true
|
||||
|
||||
GitlabSecurity/PublicSend:
|
||||
Enabled: true
|
||||
Exclude:
|
||||
|
|
209
CHANGELOG.md
209
CHANGELOG.md
|
@ -2,6 +2,198 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.6.0 (2018-03-22)
|
||||
|
||||
### Security (4 changes)
|
||||
|
||||
- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
|
||||
- Ensure that OTP backup codes are always invalidated.
|
||||
- Add verification for GitLab Pages custom domains.
|
||||
- Fix GitLab Auth0 integration signing in the wrong user.
|
||||
|
||||
### Fixed (75 changes, 17 of them are from the community)
|
||||
|
||||
- Ensure users cannot create environments with leading or trailing slashes (Fixes #39885). !15273
|
||||
- Fix new project path input overlapping. !16755 (George Tsiolis)
|
||||
- Respect description and visibility when creating project from template. !16820 (George Tsiolis)
|
||||
- Remove user notification settings for groups and projects when user leaves. !16906 (Jacopo Beschi @jacopo-beschi)
|
||||
- Fix Teleporting Emoji. !16963 (Jared Deckard <jared.deckard@gmail.com>)
|
||||
- Fix duplicate system notes when merging a merge request. !17035
|
||||
- Fix breadcrumb on labels page for groups. !17045 (Onuwa Nnachi Isaac)
|
||||
- Fix user avatar's vertical align on the issues and merge requests pages. !17072 (Laszlo Karpati)
|
||||
- Fix settings panels not expanding when fragment hash linked. !17074
|
||||
- Fix 404 when listing archived projects in a group where all projects have been archived. !17077 (Ashley Dumaine)
|
||||
- Allow to call PUT /projects/:id API with only ci_config_path specified. !17105 (Laszlo Karpati)
|
||||
- Fix long list of recipients on group request membership email. !17121 (Jacopo Beschi @jacopo-beschi)
|
||||
- Remove duplicated error message on duplicate variable validation. !17135
|
||||
- Keep "Import project" tab/form active when validation fails trying to import "Repo by URL". !17136
|
||||
- Fixed bug with unauthenticated requests through git ssh. !17149
|
||||
- Allows project rename after validation error. !17150
|
||||
- Fix "Remove source branch" button in Merge request widget during merge when pipeline succeeds state. !17192
|
||||
- Add missing pagination on the commit diff endpoint. !17203 (Maxime Roussin-Bélanger)
|
||||
- Fix get a single pages domain when project path contains a period. !17206 (Travis Miller)
|
||||
- remove avater underline. !17219 (Ken Ding)
|
||||
- Allows the usage of /milestone quick action for group milestones. !17239 (Jacopo Beschi @jacopo-beschi)
|
||||
- Encode branch name as binary before creating a RPC request to copy attributes. !17291
|
||||
- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
|
||||
- Do not persist Google Project verification flash errors after a page reload. !17299
|
||||
- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
|
||||
- Prevent trace artifact migration to incur data loss. !17313
|
||||
- Fixes gpg popover layout. !17323
|
||||
- Return a 404 instead of 403 if the repository does not exist on disk. !17341
|
||||
- Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes. !17345
|
||||
- Fix Group labels load failure when there are duplicate labels present. !17353
|
||||
- Allow Prometheus application to be installed from Cluster applications. !17372
|
||||
- Fixes Prometheus admin configuration page. !17377
|
||||
- Enable filtering MR list based on clicked label in MR sidebar. !17390
|
||||
- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
|
||||
- Count comments on diffs and discussions as contributions for the contributions calendar. !17418 (Riccardo Padovani)
|
||||
- Add Assignees vue component missing data container. !17426 (George Tsiolis)
|
||||
- Update tooltip on pipeline cancel to Stop (#42946). !17444
|
||||
- Removing the two factor check when the user sets a new password. !17457
|
||||
- Fix quick actions for users who cannot update issues and merge requests. !17482
|
||||
- Stop loading spinner on error of milestone update on issue. !17507 (Takuya Noguchi)
|
||||
- Set margins around dropdown dividers to 4px. !17517
|
||||
- Fix pages flaky failure by reloading stale object. !17522
|
||||
- Remove extra breadcrumb on tags. !17562 (Takuya Noguchi)
|
||||
- Fix missing uploads after group transfer. !17658
|
||||
- Fix markdown table showing extra column. !17669
|
||||
- Ensure the API returns https links when https is configured. !17681
|
||||
- Sanitize extra blank spaces used when uploading a SSH key. !40552
|
||||
- Render htmlentities correctly for links not supported by Rinku.
|
||||
- Keep link when redacting unauthorized object links.
|
||||
- Handle empty state in Pipelines page.
|
||||
- Revert Project.public_or_visible_to_user changes and only apply to snippets.
|
||||
- Release libgit2 cache and open file descriptors after `git gc` run.
|
||||
- Fix project dashboard showing the wrong timestamps.
|
||||
- Fix "Can't modify frozen hash" error when project is destroyed.
|
||||
- Fix Error 500 when viewing a commit with a GPG signature in Geo.
|
||||
- Don't error out in system hook if user has `nil` datetime columns.
|
||||
- Remove double caching of Repository#empty?.
|
||||
- Don't delete todos or unassign issues and MRs when a user leaves a project.
|
||||
- Don't cache a nil repository root ref to prevent caching issues.
|
||||
- Escape HTML entities in commit messages.
|
||||
- Verify project import status again before marking as failed.
|
||||
- [GitHub Import] Create an empty wiki if wiki import failed.
|
||||
- Create empty wiki when import from GitLab and wiki is not there.
|
||||
- Make sure wiki exists when it's enabled.
|
||||
- Fix broken loading state for close issue button.
|
||||
- Fix code and wiki search results when filename is non-ASCII.
|
||||
- Fix file upload on project show page.
|
||||
- Fix squashing when a file is renamed.
|
||||
- Show loading button inline in refresh button in MR widget.
|
||||
- Fix close button on issues not working on mobile.
|
||||
- Adds tooltip in environment names to increase readability.
|
||||
- Fixed issue edit shortcut not opening edit form.
|
||||
- Fix 500 error being shown when diff has context marker with invalid encoding.
|
||||
- Render modified icon for moved file in changes dropdown.
|
||||
- Remember assignee when moving an issue.
|
||||
|
||||
### Changed (16 changes, 9 of them are from the community)
|
||||
|
||||
- Allow including custom attributes in API responses. !16526 (Markus Koller)
|
||||
- Apply new default and inline label design. !16956 (George Tsiolis)
|
||||
- Remove whitespace from the username/email sign in form field. !17020 (Peter lauck)
|
||||
- CI charts now include the current day. !17032 (Dakkaron)
|
||||
- Hide CI secret variable values after saving. !17044
|
||||
- Add new modal Vue component. !17108
|
||||
- Asciidoc now support inter-document cross references between files in repository. !17125 (Turo Soisenniemi)
|
||||
- Update issue closing pattern to allow variations in punctuation. !17198 (Vicky Chijwani)
|
||||
- Add a button to deploy a runner to a Kubernetes cluster in the settings page. !17278
|
||||
- Pages custom domain: allow update of key/certificate. !17376 (rfwatson)
|
||||
- Clear the Labels dropdown search filter after a selection is made. !17393 (Andrew Torres)
|
||||
- Hook data for pipelines includes detailed_status. !17607
|
||||
- Avoid showing unnecessary Trigger checkboxes for project Integrations with only one event. !17607
|
||||
- Display a link to external issue tracker when enabled.
|
||||
- Allow token authentication on go-get request.
|
||||
- Update SSH key link to include existing keys. (Brendan O'Leary)
|
||||
|
||||
### Performance (24 changes, 5 of them are from the community)
|
||||
|
||||
- Add catch-up background migration to migrate pipeline stages. !15741
|
||||
- Move BoardNewIssue vue component. !16947 (George Tsiolis)
|
||||
- Move IssuableTimeTracker vue component. !16948 (George Tsiolis)
|
||||
- Move RecentSearchesDropdownContent vue component. !16951 (George Tsiolis)
|
||||
- Move Assignees vue component. !16952 (George Tsiolis)
|
||||
- Improve performance of pipeline page by reducing DB queries. !17168
|
||||
- Store sha256 checksum to job artifacts. !17354
|
||||
- Move SidebarAssignees vue component. !17398 (George Tsiolis)
|
||||
- Improve database response time for user activity listing. !17454
|
||||
- Use persisted/memoized value for MRs shas instead of doing git lookups. !17555
|
||||
- Cache MergeRequests can_be_resolved_in_ui? git operations. !17589
|
||||
- Prevent the graphs page from generating unnecessary Gitaly requests. !37602
|
||||
- Use a user object in ApplicationHelper#avatar_icon where possible to avoid N+1 queries. !42800
|
||||
- Submit a single batch blob RPC to Gitaly per HTTP request when viewing diffs.
|
||||
- Avoid re-fetching merge-base SHA from Gitaly unnecessarily.
|
||||
- Don't use ProjectsFinder in TodosFinder.
|
||||
- Adding missing indexes on taggings table.
|
||||
- Add index on section_name_id on ci_build_trace_sections table.
|
||||
- Cache column_exists? for application settings.
|
||||
- Cache table_exists?('application_settings') to reduce repeated schema reloads.
|
||||
- Make --prune a configurable parameter in fetching a git remote.
|
||||
- Fix timeouts loading /admin/projects page.
|
||||
- Add partial indexes on todos to handle users with many todos.
|
||||
- Optimize search queries on the search page by setting a limit for matching records in project scope.
|
||||
|
||||
### Added (30 changes, 9 of them are from the community)
|
||||
|
||||
- Add CommonMark markdown engine (experimental). !14835 (blackst0ne)
|
||||
- API: Get references a commit is pushed to. !15026 (Robert Schilling)
|
||||
- Add overview of branches and a filter for active/stale branches. !15402 (Takuya Noguchi)
|
||||
- Add project export API. !15860 (Travis Miller)
|
||||
- expose more metrics in merge requests api. !16589 (haseebeqx)
|
||||
- #28481: Display time tracking totals on milestone page. !16753 (Riccardo Padovani)
|
||||
- Add a button on the project page to set up a Kubernetes cluster and enable Auto DevOps. !16900
|
||||
- Include cycle time in usage ping data. !16973
|
||||
- Add ability to use external plugins as an alternative to system hooks. !17003
|
||||
- Add search param to Branches API. !17005 (bunufi)
|
||||
- API endpoint for importing a project export. !17025
|
||||
- Display ingress IP address in the Kubernetes page. !17052
|
||||
- Implemented badge API endpoints. !17082
|
||||
- Allow installation of GitLab Runner with a single click. !17134
|
||||
- Allow commits endpoint to work over all commits of a repository. !17182
|
||||
- Display Runner IP Address. !17286
|
||||
- Add archive feature to trace. !17314
|
||||
- Allow maintainers to push to forks of their projects when a merge request is open. !17395
|
||||
- Foreground verification of uploads and LFS objects. !17402
|
||||
- Adds updated_at filter to issues and merge_requests API. !17417 (Jacopo Beschi @jacopo-beschi)
|
||||
- Port /wip quick action command to Merge Request creation (on description). !17463 (Adam Pahlevi)
|
||||
- Add a paragraph about security implications on Cluster's page. !17486
|
||||
- Add plugins list to the system hooks page. !17518
|
||||
- Enable privileged mode for GitLab Runner. !17528
|
||||
- Expose GITLAB_FEATURES as CI/CD variable (fixes #40994).
|
||||
- Upgrade GitLab Workhorse to 4.0.0.
|
||||
- Allow CI/CD Jobs being grouped on version strings.
|
||||
- Add discussions API for Issues and Snippets.
|
||||
- Add one group board to Libre.
|
||||
- Add support for filtering by source and target branch to merge requests API.
|
||||
|
||||
### Other (14 changes, 3 of them are from the community)
|
||||
|
||||
- Update vue component naming guidelines. !17018 (George Tsiolis)
|
||||
- Added new design for promotion modals. !17197
|
||||
- Update to github-linguist 5.3.x. !17241 (Ken Ding)
|
||||
- update toml-rb to 1.0.0. !17259 (Ken Ding)
|
||||
- Keep track of projects a user interacted with. !17327
|
||||
- Enables eslint in codeclimate job. !17392
|
||||
- Port Labels Select dropdown to Vue. !17411
|
||||
- Add NOT NULL constraint to projects.namespace_id. !17448
|
||||
- Ensure foreign keys on clusters applications. !17488
|
||||
- Started translation into Turkish, Indonesian and Filipino. !17526
|
||||
- Add documentation for displayed K8s Ingress IP address (#44330). !17836
|
||||
- Move Ruby endpoints to OPT_OUT.
|
||||
- Upgrade Workhorse to version 3.8.0 to support structured logging.
|
||||
- Use host URL to build JIRA remote link icon.
|
||||
|
||||
|
||||
## 10.5.6 (2018-03-16)
|
||||
|
||||
### Security (2 changes)
|
||||
|
||||
- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
|
||||
- Fix GitLab Auth0 integration signing in the wrong user.
|
||||
|
||||
|
||||
## 10.5.5 (2018-03-15)
|
||||
|
||||
### Fixed (3 changes)
|
||||
|
@ -261,6 +453,14 @@ entry.
|
|||
- Adds empty state illustration for pending job.
|
||||
|
||||
|
||||
## 10.4.6 (2018-03-16)
|
||||
|
||||
### Security (2 changes)
|
||||
|
||||
- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
|
||||
- Fix GitLab Auth0 integration signing in the wrong user.
|
||||
|
||||
|
||||
## 10.4.5 (2018-03-01)
|
||||
|
||||
### Security (1 change)
|
||||
|
@ -492,6 +692,15 @@ entry.
|
|||
- Use a background migration for issues.closed_at.
|
||||
|
||||
|
||||
## 10.3.9 (2018-03-16)
|
||||
|
||||
### Security (3 changes)
|
||||
|
||||
- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
|
||||
- Update nokogiri to 1.8.2. !16807
|
||||
- Fix GitLab Auth0 integration signing in the wrong user.
|
||||
|
||||
|
||||
## 10.3.8 (2018-03-01)
|
||||
|
||||
### Security (1 change)
|
||||
|
|
|
@ -1 +1 @@
|
|||
7.1.0
|
||||
7.1.1
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -38,7 +38,7 @@ gem 'devise', '~> 4.2'
|
|||
gem 'doorkeeper', '~> 4.3'
|
||||
gem 'doorkeeper-openid_connect', '~> 1.3'
|
||||
gem 'omniauth', '~> 1.8'
|
||||
gem 'omniauth-auth0', '~> 1.4.1'
|
||||
gem 'omniauth-auth0', '~> 2.0.0'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.9'
|
||||
gem 'omniauth-cas3', '~> 1.1.4'
|
||||
gem 'omniauth-facebook', '~> 4.0.0'
|
||||
|
@ -231,7 +231,7 @@ gem 'sanitize', '~> 2.0'
|
|||
gem 'babosa', '~> 1.0.2'
|
||||
|
||||
# Sanitizes SVG input
|
||||
gem 'loofah', '~> 2.0.3'
|
||||
gem 'loofah', '~> 2.2'
|
||||
|
||||
# Working with license
|
||||
gem 'licensee', '~> 8.9'
|
||||
|
|
16
Gemfile.lock
16
Gemfile.lock
|
@ -143,6 +143,7 @@ GEM
|
|||
connection_pool (2.2.1)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
crass (1.0.3)
|
||||
creole (0.5.0)
|
||||
css_parser (1.5.0)
|
||||
addressable
|
||||
|
@ -485,7 +486,8 @@ GEM
|
|||
actionpack (>= 4, < 5.2)
|
||||
activesupport (>= 4, < 5.2)
|
||||
railties (>= 4, < 5.2)
|
||||
loofah (2.0.3)
|
||||
loofah (2.2.2)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.0)
|
||||
mini_mime (>= 0.1.1)
|
||||
|
@ -527,8 +529,8 @@ GEM
|
|||
omniauth (1.8.1)
|
||||
hashie (>= 3.4.6, < 3.6.0)
|
||||
rack (>= 1.6.2, < 3)
|
||||
omniauth-auth0 (1.4.1)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-auth0 (2.0.0)
|
||||
omniauth-oauth2 (~> 1.4)
|
||||
omniauth-authentiq (0.3.1)
|
||||
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
||||
omniauth-azure-oauth2 (0.0.9)
|
||||
|
@ -679,8 +681,8 @@ GEM
|
|||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
rails-html-sanitizer (1.0.4)
|
||||
loofah (~> 2.2, >= 2.2.2)
|
||||
rails-i18n (4.0.9)
|
||||
i18n (~> 0.7)
|
||||
railties (~> 4.0)
|
||||
|
@ -1093,7 +1095,7 @@ DEPENDENCIES
|
|||
license_finder (~> 3.1)
|
||||
licensee (~> 8.9)
|
||||
lograge (~> 0.5)
|
||||
loofah (~> 2.0.3)
|
||||
loofah (~> 2.2)
|
||||
mail_room (~> 0.9.1)
|
||||
method_source (~> 0.8)
|
||||
minitest (~> 5.7.0)
|
||||
|
@ -1105,7 +1107,7 @@ DEPENDENCIES
|
|||
oauth2 (~> 1.4)
|
||||
octokit (~> 4.8)
|
||||
omniauth (~> 1.8)
|
||||
omniauth-auth0 (~> 1.4.1)
|
||||
omniauth-auth0 (~> 2.0.0)
|
||||
omniauth-authentiq (~> 0.3.1)
|
||||
omniauth-azure-oauth2 (~> 0.0.9)
|
||||
omniauth-cas3 (~> 1.1.4)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
10.6.0-pre
|
||||
10.7.0-pre
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import eventHub from '../eventhub';
|
||||
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
@ -45,7 +45,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({
|
|||
};
|
||||
},
|
||||
components: {
|
||||
userAvatarLink,
|
||||
UserAvatarLink,
|
||||
},
|
||||
computed: {
|
||||
numberOverLimit() {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import $ from 'jquery';
|
||||
import { s__ } from '~/locale';
|
||||
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import { getParameterByName } from '~/lib/utils/common_utils';
|
||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||
|
||||
|
@ -15,7 +15,7 @@ import groupsComponent from './groups.vue';
|
|||
export default {
|
||||
components: {
|
||||
loadingIcon,
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
groupsComponent,
|
||||
},
|
||||
props: {
|
||||
|
@ -52,8 +52,9 @@ export default {
|
|||
},
|
||||
},
|
||||
created() {
|
||||
this.searchEmptyMessage = this.hideProjects ?
|
||||
COMMON_STR.GROUP_SEARCH_EMPTY : COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY;
|
||||
this.searchEmptyMessage = this.hideProjects
|
||||
? COMMON_STR.GROUP_SEARCH_EMPTY
|
||||
: COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY;
|
||||
|
||||
eventHub.$on('fetchPage', this.fetchPage);
|
||||
eventHub.$on('toggleChildren', this.toggleChildren);
|
||||
|
@ -72,22 +73,30 @@ export default {
|
|||
eventHub.$off('updateGroups', this.updateGroups);
|
||||
},
|
||||
methods: {
|
||||
fetchGroups({ parentId, page, filterGroupsBy, sortBy, archived, updatePagination }) {
|
||||
return this.service.getGroups(parentId, page, filterGroupsBy, sortBy, archived)
|
||||
.then((res) => {
|
||||
if (updatePagination) {
|
||||
this.updatePagination(res.headers);
|
||||
}
|
||||
fetchGroups({
|
||||
parentId,
|
||||
page,
|
||||
filterGroupsBy,
|
||||
sortBy,
|
||||
archived,
|
||||
updatePagination,
|
||||
}) {
|
||||
return this.service
|
||||
.getGroups(parentId, page, filterGroupsBy, sortBy, archived)
|
||||
.then(res => {
|
||||
if (updatePagination) {
|
||||
this.updatePagination(res.headers);
|
||||
}
|
||||
|
||||
return res;
|
||||
})
|
||||
.then(res => res.json())
|
||||
.catch(() => {
|
||||
this.isLoading = false;
|
||||
$.scrollTo(0);
|
||||
return res;
|
||||
})
|
||||
.then(res => res.json())
|
||||
.catch(() => {
|
||||
this.isLoading = false;
|
||||
$.scrollTo(0);
|
||||
|
||||
Flash(COMMON_STR.FAILURE);
|
||||
});
|
||||
Flash(COMMON_STR.FAILURE);
|
||||
});
|
||||
},
|
||||
fetchAllGroups() {
|
||||
const page = getParameterByName('page') || null;
|
||||
|
@ -103,7 +112,7 @@ export default {
|
|||
sortBy,
|
||||
archived,
|
||||
updatePagination: true,
|
||||
}).then((res) => {
|
||||
}).then(res => {
|
||||
this.isLoading = false;
|
||||
this.updateGroups(res, Boolean(filterGroupsBy));
|
||||
});
|
||||
|
@ -118,14 +127,18 @@ export default {
|
|||
sortBy,
|
||||
archived,
|
||||
updatePagination: true,
|
||||
}).then((res) => {
|
||||
}).then(res => {
|
||||
this.isLoading = false;
|
||||
$.scrollTo(0);
|
||||
|
||||
const currentPath = mergeUrlParams({ page }, window.location.href);
|
||||
window.history.replaceState({
|
||||
page: currentPath,
|
||||
}, document.title, currentPath);
|
||||
window.history.replaceState(
|
||||
{
|
||||
page: currentPath,
|
||||
},
|
||||
document.title,
|
||||
currentPath,
|
||||
);
|
||||
|
||||
this.updateGroups(res);
|
||||
});
|
||||
|
@ -138,11 +151,13 @@ export default {
|
|||
// eslint-disable-next-line promise/catch-or-return
|
||||
this.fetchGroups({
|
||||
parentId: parentGroup.id,
|
||||
}).then((res) => {
|
||||
this.store.setGroupChildren(parentGroup, res);
|
||||
}).catch(() => {
|
||||
parentGroup.isChildrenLoading = false;
|
||||
});
|
||||
})
|
||||
.then(res => {
|
||||
this.store.setGroupChildren(parentGroup, res);
|
||||
})
|
||||
.catch(() => {
|
||||
parentGroup.isChildrenLoading = false;
|
||||
});
|
||||
} else {
|
||||
parentGroup.isOpen = true;
|
||||
}
|
||||
|
@ -154,7 +169,11 @@ export default {
|
|||
this.targetGroup = group;
|
||||
this.targetParentGroup = parentGroup;
|
||||
this.showModal = true;
|
||||
this.groupLeaveConfirmationMessage = s__(`GroupsTree|Are you sure you want to leave the "${group.fullName}" group?`);
|
||||
this.groupLeaveConfirmationMessage = s__(
|
||||
`GroupsTree|Are you sure you want to leave the "${
|
||||
group.fullName
|
||||
}" group?`,
|
||||
);
|
||||
},
|
||||
hideLeaveGroupModal() {
|
||||
this.showModal = false;
|
||||
|
@ -162,14 +181,15 @@ export default {
|
|||
leaveGroup() {
|
||||
this.showModal = false;
|
||||
this.targetGroup.isBeingRemoved = true;
|
||||
this.service.leaveGroup(this.targetGroup.leavePath)
|
||||
this.service
|
||||
.leaveGroup(this.targetGroup.leavePath)
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
$.scrollTo(0);
|
||||
this.store.removeGroup(this.targetGroup, this.targetParentGroup);
|
||||
Flash(res.notice, 'notice');
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
let message = COMMON_STR.FAILURE;
|
||||
if (err.status === 403) {
|
||||
message = COMMON_STR.LEAVE_FORBIDDEN;
|
||||
|
@ -208,8 +228,8 @@ export default {
|
|||
:search-empty-message="searchEmptyMessage"
|
||||
:page-info="pageInfo"
|
||||
/>
|
||||
<modal
|
||||
v-if="showModal"
|
||||
<deprecated-modal
|
||||
v-show="showModal"
|
||||
kind="warning"
|
||||
:primary-button-label="__('Leave')"
|
||||
:title="__('Are you sure?')"
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
<script>
|
||||
import { __ } from '~/locale';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import { __ } from '~/locale';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
export default {
|
||||
components: {
|
||||
DeprecatedModal,
|
||||
},
|
||||
props: {
|
||||
branchId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
branchId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
entryName: this.path !== '' ? `${this.path}/` : '',
|
||||
};
|
||||
path: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
modalTitle() {
|
||||
if (this.type === 'tree') {
|
||||
return __('Create new directory');
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
entryName: this.path !== '' ? `${this.path}/` : '',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
modalTitle() {
|
||||
if (this.type === 'tree') {
|
||||
return __('Create new directory');
|
||||
}
|
||||
|
||||
return __('Create new file');
|
||||
},
|
||||
buttonLabel() {
|
||||
if (this.type === 'tree') {
|
||||
return __('Create directory');
|
||||
}
|
||||
|
||||
return __('Create file');
|
||||
},
|
||||
formLabelName() {
|
||||
if (this.type === 'tree') {
|
||||
return __('Directory name');
|
||||
}
|
||||
|
||||
return __('File name');
|
||||
},
|
||||
return __('Create new file');
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.fieldName.focus();
|
||||
},
|
||||
methods: {
|
||||
createEntryInStore() {
|
||||
this.$emit('create', {
|
||||
branchId: this.branchId,
|
||||
name: this.entryName,
|
||||
type: this.type,
|
||||
});
|
||||
buttonLabel() {
|
||||
if (this.type === 'tree') {
|
||||
return __('Create directory');
|
||||
}
|
||||
|
||||
this.hideModal();
|
||||
},
|
||||
hideModal() {
|
||||
this.$emit('hide');
|
||||
},
|
||||
return __('Create file');
|
||||
},
|
||||
};
|
||||
formLabelName() {
|
||||
if (this.type === 'tree') {
|
||||
return __('Directory name');
|
||||
}
|
||||
|
||||
return __('File name');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.fieldName.focus();
|
||||
},
|
||||
methods: {
|
||||
createEntryInStore() {
|
||||
this.$emit('create', {
|
||||
branchId: this.branchId,
|
||||
name: this.entryName,
|
||||
type: this.type,
|
||||
});
|
||||
|
||||
this.hideModal();
|
||||
},
|
||||
hideModal() {
|
||||
this.$emit('hide');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
:title="modalTitle"
|
||||
:primary-button-label="buttonLabel"
|
||||
kind="success"
|
||||
|
@ -95,5 +95,5 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</template>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { mapState, mapActions, mapGetters } from 'vuex';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import icon from '~/vue_shared/components/icon.vue';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import LoadingButton from '~/vue_shared/components/loading_button.vue';
|
||||
import commitFilesList from './commit_sidebar/list.vue';
|
||||
import * as consts from '../stores/modules/commit/constants';
|
||||
|
@ -10,7 +10,7 @@ import Actions from './commit_sidebar/actions.vue';
|
|||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
icon,
|
||||
commitFilesList,
|
||||
Actions,
|
||||
|
@ -37,23 +37,20 @@ export default {
|
|||
'lastCommitMsg',
|
||||
'changedFiles',
|
||||
]),
|
||||
...mapState('commit', [
|
||||
'commitMessage',
|
||||
'submitCommitLoading',
|
||||
]),
|
||||
...mapState('commit', ['commitMessage', 'submitCommitLoading']),
|
||||
...mapGetters('commit', [
|
||||
'commitButtonDisabled',
|
||||
'discardDraftButtonDisabled',
|
||||
'branchName',
|
||||
]),
|
||||
statusSvg() {
|
||||
return this.lastCommitMsg ? this.committedStateSvgPath : this.noChangesStateSvgPath;
|
||||
return this.lastCommitMsg
|
||||
? this.committedStateSvgPath
|
||||
: this.noChangesStateSvgPath;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'setPanelCollapsedStatus',
|
||||
]),
|
||||
...mapActions(['setPanelCollapsedStatus']),
|
||||
...mapActions('commit', [
|
||||
'updateCommitMessage',
|
||||
'discardDraft',
|
||||
|
@ -67,8 +64,9 @@ export default {
|
|||
});
|
||||
},
|
||||
forceCreateNewBranch() {
|
||||
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH)
|
||||
.then(() => this.commitChanges());
|
||||
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() =>
|
||||
this.commitChanges(),
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -81,7 +79,7 @@ export default {
|
|||
'multi-file-commit-empty-state-container': !changedFiles.length
|
||||
}"
|
||||
>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
id="ide-create-branch-modal"
|
||||
:primary-button-label="__('Create new branch')"
|
||||
kind="success"
|
||||
|
@ -92,7 +90,7 @@ export default {
|
|||
{{ __(`This branch has changed since you started editing.
|
||||
Would you like to create a new branch?`) }}
|
||||
</template>
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
<commit-files-list
|
||||
title="Staged"
|
||||
:file-list="changedFiles"
|
||||
|
|
|
@ -1727,6 +1727,7 @@ export default class Notes {
|
|||
|
||||
// Get Form metadata
|
||||
const $submitBtn = $(e.target);
|
||||
$submitBtn.prop('disabled', true);
|
||||
let $form = $submitBtn.parents('form');
|
||||
const $closeBtn = $form.find('.js-note-target-close');
|
||||
const isDiscussionNote =
|
||||
|
@ -1761,7 +1762,6 @@ export default class Notes {
|
|||
// If comment is to resolve discussion, disable submit buttons while
|
||||
// comment posting is finished.
|
||||
if (isDiscussionResolve) {
|
||||
$submitBtn.disable();
|
||||
$form.find('.js-comment-submit-button').disable();
|
||||
}
|
||||
|
||||
|
@ -1816,6 +1816,7 @@ export default class Notes {
|
|||
.then(res => {
|
||||
const note = res.data;
|
||||
|
||||
$submitBtn.prop('disabled', false);
|
||||
// Submission successful! remove placeholder
|
||||
$notesContainer.find(`#${noteUniqueId}`).remove();
|
||||
|
||||
|
@ -1899,7 +1900,7 @@ export default class Notes {
|
|||
.catch(() => {
|
||||
// Submission failed, remove placeholder note and show Flash error message
|
||||
$notesContainer.find(`#${noteUniqueId}`).remove();
|
||||
|
||||
$submitBtn.prop('disabled', false);
|
||||
const blurEvent = new CustomEvent('blur.imageDiff', {
|
||||
detail: e,
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
},
|
||||
props: {
|
||||
deleteProjectUrl: {
|
||||
|
@ -79,7 +79,7 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
id="delete-project-modal"
|
||||
:title="title"
|
||||
:text="text"
|
||||
|
@ -121,5 +121,5 @@
|
|||
/>
|
||||
</form>
|
||||
</template>
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</template>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
},
|
||||
props: {
|
||||
deleteUserUrl: {
|
||||
|
@ -113,7 +113,7 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
id="delete-user-modal"
|
||||
:title="title"
|
||||
:text="text"
|
||||
|
@ -170,5 +170,5 @@
|
|||
{{ secondaryButtonLabel }}
|
||||
</button>
|
||||
</template>
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</template>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
|
||||
import Flash from '~/flash';
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import { n__, s__, sprintf } from '~/locale';
|
||||
import { redirectTo } from '~/lib/utils/url_utility';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
},
|
||||
props: {
|
||||
issueCount: {
|
||||
|
@ -92,7 +92,7 @@ Once deleted, it cannot be undone or recovered.`),
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
id="delete-milestone-modal"
|
||||
:title="title"
|
||||
:text="text"
|
||||
|
@ -106,5 +106,5 @@ Once deleted, it cannot be undone or recovered.`),
|
|||
<p v-html="props.text"></p>
|
||||
</template>
|
||||
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</template>
|
||||
|
|
|
@ -27,12 +27,21 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
metricDetails() {
|
||||
return this.currentRequest.details[this.metric];
|
||||
},
|
||||
detailsList() {
|
||||
return this.metricDetails[this.details];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
:id="`peek-view-${metric}`"
|
||||
class="view"
|
||||
v-if="currentRequest.details"
|
||||
>
|
||||
<button
|
||||
:data-target="`#modal-peek-${metric}-details`"
|
||||
|
@ -40,34 +49,40 @@ export default {
|
|||
type="button"
|
||||
data-toggle="modal"
|
||||
>
|
||||
<span
|
||||
v-if="currentRequest.details"
|
||||
class="bold"
|
||||
>
|
||||
{{ currentRequest.details[metric].duration }}
|
||||
/
|
||||
{{ currentRequest.details[metric].calls }}
|
||||
</span>
|
||||
{{ metricDetails.duration }}
|
||||
/
|
||||
{{ metricDetails.calls }}
|
||||
</button>
|
||||
<gl-modal
|
||||
v-if="currentRequest.details"
|
||||
:id="`modal-peek-${metric}-details`"
|
||||
:header-title-text="header"
|
||||
class="performance-bar-modal"
|
||||
>
|
||||
<table class="table">
|
||||
<tr
|
||||
v-for="(item, index) in currentRequest.details[metric][details]"
|
||||
:key="index"
|
||||
>
|
||||
<td><strong>{{ item.duration }}ms</strong></td>
|
||||
<td
|
||||
v-for="key in keys"
|
||||
:key="key"
|
||||
<table
|
||||
class="table"
|
||||
>
|
||||
<template v-if="detailsList.length">
|
||||
<tr
|
||||
v-for="(item, index) in detailsList"
|
||||
:key="index"
|
||||
>
|
||||
{{ item[key] }}
|
||||
</td>
|
||||
</tr>
|
||||
<td><strong>{{ item.duration }}ms</strong></td>
|
||||
<td
|
||||
v-for="key in keys"
|
||||
:key="key"
|
||||
class="break-word"
|
||||
>
|
||||
{{ item[key] }}
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template v-else>
|
||||
<tr>
|
||||
<td>
|
||||
No {{ header.toLowerCase() }} for this request.
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</table>
|
||||
|
||||
<div slot="footer">
|
||||
|
|
|
@ -113,27 +113,21 @@ export default {
|
|||
id="js-peek"
|
||||
:class="env"
|
||||
>
|
||||
<request-selector
|
||||
v-if="currentRequest"
|
||||
:current-request="currentRequest"
|
||||
:requests="requests"
|
||||
@change-current-request="changeCurrentRequest"
|
||||
/>
|
||||
<div
|
||||
id="peek-view-host"
|
||||
class="view prepend-left-5"
|
||||
v-if="currentRequest"
|
||||
class="container-fluid container-limited"
|
||||
>
|
||||
<span
|
||||
v-if="currentRequest && currentRequest.details"
|
||||
class="current-host"
|
||||
<div
|
||||
id="peek-view-host"
|
||||
class="view"
|
||||
>
|
||||
{{ currentRequest.details.host.hostname }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="currentRequest"
|
||||
class="wrapper"
|
||||
>
|
||||
<span
|
||||
v-if="currentRequest.details"
|
||||
class="current-host"
|
||||
>
|
||||
{{ currentRequest.details.host.hostname }}
|
||||
</span>
|
||||
</div>
|
||||
<upstream-performance-bar
|
||||
v-if="initialRequest && currentRequest.details"
|
||||
/>
|
||||
|
@ -186,6 +180,12 @@ export default {
|
|||
gc
|
||||
</span>
|
||||
</div>
|
||||
<request-selector
|
||||
v-if="currentRequest"
|
||||
:current-request="currentRequest"
|
||||
:requests="requests"
|
||||
@change-current-request="changeCurrentRequest"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -37,7 +37,7 @@ export default {
|
|||
<template>
|
||||
<div
|
||||
id="peek-request-selector"
|
||||
class="append-right-5 pull-right"
|
||||
class="pull-right"
|
||||
>
|
||||
<select v-model="currentRequestId">
|
||||
<option
|
||||
|
|
|
@ -5,6 +5,8 @@ export default {
|
|||
.getElementById('peek-view-performance-bar')
|
||||
.cloneNode(true);
|
||||
|
||||
upstreamPerformanceBar.classList.remove('hidden');
|
||||
|
||||
this.$refs.wrapper.appendChild(upstreamPerformanceBar);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,9 +4,9 @@ import Vue from 'vue';
|
|||
import performanceBarApp from './components/performance_bar_app.vue';
|
||||
import PerformanceBarStore from './stores/performance_bar_store';
|
||||
|
||||
export default () =>
|
||||
export default ({ container }) =>
|
||||
new Vue({
|
||||
el: '#js-peek',
|
||||
el: container,
|
||||
components: {
|
||||
performanceBarApp,
|
||||
},
|
||||
|
|
|
@ -1,11 +1,28 @@
|
|||
import Vue from 'vue';
|
||||
import _ from 'underscore';
|
||||
import axios from '../../lib/utils/axios_utils';
|
||||
|
||||
let vueResourceInterceptor;
|
||||
|
||||
export default class PerformanceBarService {
|
||||
static fetchRequestDetails(peekUrl, requestId) {
|
||||
return axios.get(peekUrl, { params: { request_id: requestId } });
|
||||
}
|
||||
|
||||
static registerInterceptor(peekUrl, callback) {
|
||||
vueResourceInterceptor = (request, next) => {
|
||||
next(response => {
|
||||
const requestId = response.headers['x-request-id'];
|
||||
const requestUrl = response.url;
|
||||
|
||||
if (requestUrl !== peekUrl && requestId) {
|
||||
callback(requestId, requestUrl);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Vue.http.interceptors.push(vueResourceInterceptor);
|
||||
|
||||
return axios.interceptors.response.use(response => {
|
||||
const requestId = response.headers['x-request-id'];
|
||||
const requestUrl = response.config.url;
|
||||
|
@ -20,5 +37,9 @@ export default class PerformanceBarService {
|
|||
|
||||
static removeInterceptor(interceptor) {
|
||||
axios.interceptors.response.eject(interceptor);
|
||||
Vue.http.interceptors = _.without(
|
||||
Vue.http.interceptors,
|
||||
vueResourceInterceptor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import pipelinesTableRowComponent from './pipelines_table_row.vue';
|
||||
import eventHub from '../event_hub';
|
||||
|
@ -12,7 +12,7 @@
|
|||
export default {
|
||||
components: {
|
||||
pipelinesTableRowComponent,
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
},
|
||||
props: {
|
||||
pipelines: {
|
||||
|
@ -120,7 +120,7 @@
|
|||
:auto-devops-help-path="autoDevopsHelpPath"
|
||||
:view-type="viewType"
|
||||
/>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
id="confirmation-modal"
|
||||
:title="modalTitle"
|
||||
:text="modalText"
|
||||
|
@ -134,6 +134,6 @@
|
|||
>
|
||||
<p v-html="props.text"></p>
|
||||
</template>
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script>
|
||||
import modal from '~/vue_shared/components/modal.vue';
|
||||
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
},
|
||||
props: {
|
||||
actionUrl: {
|
||||
|
@ -76,7 +76,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
id="delete-account-modal"
|
||||
:title="s__('Profiles|Delete your account?')"
|
||||
:text="text"
|
||||
|
@ -131,5 +131,5 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
|
|||
</form>
|
||||
</template>
|
||||
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script>
|
||||
import { sprintf, s__ } from '~/locale';
|
||||
import statusCodes from '../../lib/utils/http_status';
|
||||
import { bytesToMiB } from '../../lib/utils/number_utils';
|
||||
import { backOff } from '../../lib/utils/common_utils';
|
||||
|
@ -45,17 +46,28 @@ export default {
|
|||
shouldShowMetricsUnavailable() {
|
||||
return !this.loadingMetrics && !this.hasMetrics && !this.loadFailed;
|
||||
},
|
||||
memoryChangeType() {
|
||||
memoryChangeMessage() {
|
||||
const messageProps = {
|
||||
memoryFrom: this.memoryFrom,
|
||||
memoryTo: this.memoryTo,
|
||||
metricsLinkStart: `<a href="${this.metricsMonitoringUrl}">`,
|
||||
metricsLinkEnd: '</a>',
|
||||
emphasisStart: '<b>',
|
||||
emphasisEnd: '</b>',
|
||||
};
|
||||
const memoryTo = Number(this.memoryTo);
|
||||
const memoryFrom = Number(this.memoryFrom);
|
||||
let memoryUsageMsg = '';
|
||||
|
||||
if (memoryTo > memoryFrom) {
|
||||
return 'increased';
|
||||
memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB'), messageProps, false);
|
||||
} else if (memoryTo < memoryFrom) {
|
||||
return 'decreased';
|
||||
memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB'), messageProps, false);
|
||||
} else {
|
||||
memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB'), messageProps, false);
|
||||
}
|
||||
|
||||
return 'unchanged';
|
||||
return memoryUsageMsg;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
@ -130,24 +142,22 @@ export default {
|
|||
<i
|
||||
class="fa fa-spinner fa-spin usage-info-load-spinner"
|
||||
aria-hidden="true">
|
||||
</i>Loading deployment statistics
|
||||
</i>{{ s__('mrWidget|Loading deployment statistics') }}
|
||||
</p>
|
||||
<p
|
||||
v-if="shouldShowMemoryGraph"
|
||||
class="usage-info js-usage-info">
|
||||
<a
|
||||
:href="metricsMonitoringUrl"
|
||||
>Memory</a> usage <b>{{ memoryChangeType }}</b> from {{ memoryFrom }}MB to {{ memoryTo }}MB
|
||||
{{ memoryChangeMessage }}
|
||||
</p>
|
||||
<p
|
||||
v-if="shouldShowLoadFailure"
|
||||
class="usage-info js-usage-info usage-info-failed">
|
||||
Failed to load deployment statistics
|
||||
{{ s__('mrWidget|Failed to load deployment statistics') }}
|
||||
</p>
|
||||
<p
|
||||
v-if="shouldShowMetricsUnavailable"
|
||||
class="usage-info js-usage-info usage-info-unavailable">
|
||||
Deployment statistics are not available currently
|
||||
{{ s__('mrWidget|Deployment statistics are not available currently') }}
|
||||
</p>
|
||||
<memory-graph
|
||||
v-if="shouldShowMemoryGraph"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
/* eslint-disable vue/require-default-prop */
|
||||
export default {
|
||||
name: 'Modal',
|
||||
name: 'DeprecatedModal', // use GlModal instead
|
||||
|
||||
props: {
|
||||
id: {
|
|
@ -1,11 +1,11 @@
|
|||
<script>
|
||||
import modal from './modal.vue';
|
||||
import DeprecatedModal from './deprecated_modal.vue';
|
||||
|
||||
export default {
|
||||
name: 'RecaptchaModal',
|
||||
|
||||
components: {
|
||||
modal,
|
||||
DeprecatedModal,
|
||||
},
|
||||
|
||||
props: {
|
||||
|
@ -65,7 +65,7 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<modal
|
||||
<deprecated-modal
|
||||
kind="warning"
|
||||
class="recaptcha-modal js-recaptcha-modal"
|
||||
:hide-footer="true"
|
||||
|
@ -82,5 +82,5 @@
|
|||
>
|
||||
</div>
|
||||
</div>
|
||||
</modal>
|
||||
</deprecated-modal>
|
||||
</template>
|
||||
|
|
|
@ -446,6 +446,10 @@ img.emoji {
|
|||
opacity: .5;
|
||||
}
|
||||
|
||||
.break-word {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/** COMMON CLASSES **/
|
||||
.prepend-top-0 { margin-top: 0; }
|
||||
.prepend-top-5 { margin-top: 5px; }
|
||||
|
|
|
@ -622,7 +622,7 @@
|
|||
}
|
||||
|
||||
.dropdown-content {
|
||||
max-height: $dropdown-max-height;
|
||||
max-height: 252px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
@ -699,6 +699,31 @@
|
|||
border-radius: $border-radius-base;
|
||||
}
|
||||
|
||||
.git-revision-dropdown {
|
||||
.dropdown-content {
|
||||
max-height: 215px;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-move-issue-dropdown {
|
||||
.dropdown-content {
|
||||
max-height: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-author {
|
||||
.dropdown-content {
|
||||
max-height: 215px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-labels {
|
||||
.dropdown-content {
|
||||
max-height: 128px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dropdown-menu-due-date {
|
||||
.dropdown-content {
|
||||
max-height: 230px;
|
||||
|
|
|
@ -152,3 +152,4 @@
|
|||
.sidebar-collapsed-icon .sidebar-collapsed-value {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,12 @@
|
|||
.dropdown-menu-issues-board-new {
|
||||
width: 320px;
|
||||
|
||||
.open & {
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
max-height: 150px;
|
||||
max-height: 162px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
.content-list > .branch-item,
|
||||
.branch-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.branch-info {
|
||||
flex: auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.divergence-graph {
|
||||
padding: 12px 12px 0 0;
|
||||
float: right;
|
||||
padding: 0 6px;
|
||||
|
||||
.graph-side {
|
||||
position: relative;
|
||||
|
@ -53,3 +64,9 @@
|
|||
background-color: $divergence-graph-separator-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.divergence-graph,
|
||||
.branch-item .controls {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
@ -162,17 +162,14 @@
|
|||
* Last push widget
|
||||
*/
|
||||
.event-last-push {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.event-last-push-text {
|
||||
@include str-truncated(100%);
|
||||
padding: 4px 0;
|
||||
font-size: 13px;
|
||||
float: left;
|
||||
margin-right: -150px;
|
||||
padding-right: 150px;
|
||||
line-height: 20px;
|
||||
margin-right: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-labels {
|
||||
.dropdown-content {
|
||||
max-height: 135px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-new-label {
|
||||
.dropdown-content {
|
||||
max-height: 260px;
|
||||
max-height: 136px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
.new_project,
|
||||
.edit-project,
|
||||
.import-project {
|
||||
|
||||
.help-block {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
@ -18,18 +17,25 @@
|
|||
border-radius: $border-radius-base;
|
||||
}
|
||||
|
||||
.input-group > div {
|
||||
.input-group {
|
||||
display: flex;
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
.select2-container {
|
||||
display: unset;
|
||||
max-width: unset;
|
||||
width: unset !important;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
> div {
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
.input-group > div {
|
||||
|
||||
margin-bottom: 14px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -41,17 +47,24 @@
|
|||
}
|
||||
|
||||
.input-group-addon {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: unset;
|
||||
width: unset;
|
||||
max-width: 50%;
|
||||
text-align: left;
|
||||
|
||||
&.static-namespace {
|
||||
height: 35px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid $border-color;
|
||||
max-width: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
+ .select2 a,
|
||||
+ .btn-default {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-radius: 0 $border-radius-base $border-radius-base 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +303,7 @@
|
|||
font-size: 13px;
|
||||
font-weight: $gl-font-weight-bold;
|
||||
line-height: 13px;
|
||||
letter-spacing: .4px;
|
||||
letter-spacing: 0.4px;
|
||||
padding: 6px 14px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
@ -443,7 +456,7 @@ a.deploy-project-label {
|
|||
text-decoration: none;
|
||||
|
||||
&.disabled {
|
||||
opacity: .3;
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
@ -600,26 +613,26 @@ a.deploy-project-label {
|
|||
}
|
||||
|
||||
.first-column {
|
||||
@media(min-width: $screen-xs-min) {
|
||||
@media (min-width: $screen-xs-min) {
|
||||
max-width: 50%;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
@media(max-width: $screen-xs-max) {
|
||||
@media (max-width: $screen-xs-max) {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.second-column {
|
||||
@media(min-width: $screen-xs-min) {
|
||||
@media (min-width: $screen-xs-min) {
|
||||
width: 50%;
|
||||
flex: 1;
|
||||
padding-left: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media(max-width: $screen-xs-max) {
|
||||
@media (max-width: $screen-xs-max) {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
padding-left: 0;
|
||||
|
@ -632,7 +645,7 @@ a.deploy-project-label {
|
|||
}
|
||||
|
||||
&::before {
|
||||
content: "OR";
|
||||
content: 'OR';
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: 50%;
|
||||
|
@ -656,7 +669,7 @@ a.deploy-project-label {
|
|||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: $border-color;
|
||||
bottom: 0;
|
||||
|
@ -921,10 +934,7 @@ pre.light-well {
|
|||
border-right: solid 1px transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.protected-tags-list,
|
||||
.protected-branches-list {
|
||||
.dropdown-menu-toggle {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
|
|
|
@ -112,7 +112,7 @@ input[type="checkbox"]:hover {
|
|||
}
|
||||
|
||||
.dropdown-content {
|
||||
max-height: 350px;
|
||||
max-height: 302px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
line-height: $performance-bar-height;
|
||||
color: $perf-bar-text;
|
||||
|
||||
select {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
@ -43,12 +47,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 80%;
|
||||
height: $performance-bar-height;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
// UI Elements
|
||||
.bucket {
|
||||
background: $perf-bar-bucket-bg;
|
||||
|
@ -108,8 +106,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
.performance-bar-modal .modal-footer {
|
||||
display: none;
|
||||
.performance-bar-modal {
|
||||
.modal-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 860px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,23 +3,9 @@
|
|||
# Automatically sets the layout and ensures an administrator is logged in
|
||||
class Admin::ApplicationController < ApplicationController
|
||||
before_action :authenticate_admin!
|
||||
before_action :display_read_only_information
|
||||
layout 'admin'
|
||||
|
||||
def authenticate_admin!
|
||||
render_404 unless current_user.admin?
|
||||
end
|
||||
|
||||
def display_read_only_information
|
||||
return unless Gitlab::Database.read_only?
|
||||
|
||||
flash.now[:notice] = read_only_message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Overridden in EE
|
||||
def read_only_message
|
||||
_('You are on a read-only GitLab instance.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,6 +18,18 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
end
|
||||
end
|
||||
|
||||
# Extend the standard implementation to also increment
|
||||
# the number of failed sign in attempts
|
||||
def failure
|
||||
if params[:username].present? && AuthHelper.form_based_provider?(failed_strategy.name)
|
||||
user = User.by_login(params[:username])
|
||||
|
||||
user&.increment_failed_attempts!
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
# Extend the standard message generation to accept our custom exception
|
||||
def failure_message
|
||||
exception = env["omniauth.error"]
|
||||
|
@ -95,6 +107,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
handle_omniauth
|
||||
end
|
||||
|
||||
def auth0
|
||||
if oauth['uid'].blank?
|
||||
fail_auth0_login
|
||||
else
|
||||
handle_omniauth
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_omniauth
|
||||
|
@ -170,6 +190,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
def fail_auth0_login
|
||||
flash[:alert] = 'Wrong extern UID provided. Make sure Auth0 is configured correctly.'
|
||||
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
def handle_disabled_provider
|
||||
label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider'])
|
||||
flash[:alert] = "Signing in using #{label} has been disabled"
|
||||
|
|
|
@ -21,4 +21,26 @@ class Projects::PagesController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
result = Projects::UpdateService.new(@project, current_user, project_params).execute
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if result[:status] == :success
|
||||
flash[:notice] = 'Your changes have been saved'
|
||||
else
|
||||
flash[:alert] = 'Something went wrong on our end'
|
||||
end
|
||||
|
||||
redirect_to project_pages_path(@project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def project_params
|
||||
params.require(:project).permit(:pages_https_only)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,10 +10,7 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController
|
|||
if service.execute
|
||||
flash[:notice] = "Pipelines settings for '#{@project.name}' were successfully updated."
|
||||
|
||||
if service.run_auto_devops_pipeline?
|
||||
CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false)
|
||||
flash[:success] = "A new Auto DevOps pipeline has been created, go to <a href=\"#{project_pipelines_path(@project)}\">Pipelines page</a> for details".html_safe
|
||||
end
|
||||
run_autodevops_pipeline(service)
|
||||
|
||||
redirect_to project_settings_ci_cd_path(@project)
|
||||
else
|
||||
|
@ -24,6 +21,18 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def run_autodevops_pipeline(service)
|
||||
return unless service.run_auto_devops_pipeline?
|
||||
|
||||
if @project.empty_repo?
|
||||
flash[:warning] = "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
|
||||
return
|
||||
end
|
||||
|
||||
CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false)
|
||||
flash[:success] = "A new Auto DevOps pipeline has been created, go to <a href=\"#{project_pipelines_path(@project)}\">Pipelines page</a> for details".html_safe
|
||||
end
|
||||
|
||||
def update_params
|
||||
params.require(:project).permit(
|
||||
:runners_token, :builds_enabled, :build_allow_git_fetch,
|
||||
|
|
|
@ -323,4 +323,11 @@ module ApplicationHelper
|
|||
def locale_path
|
||||
asset_path("locale/#{Gitlab::I18n.locale}/app.js")
|
||||
end
|
||||
|
||||
# Overridden in EE
|
||||
def read_only_message
|
||||
return unless Gitlab::Database.read_only?
|
||||
|
||||
_('You are on a read-only GitLab instance.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -96,7 +96,7 @@ module ApplicationSettingsHelper
|
|||
|
||||
def repository_storages_options_for_select(selected)
|
||||
options = Gitlab.config.repositories.storages.map do |name, storage|
|
||||
["#{name} - #{storage['path']}", name]
|
||||
["#{name} - #{storage['gitaly_address']}", name]
|
||||
end
|
||||
|
||||
options_for_select(options, selected)
|
||||
|
@ -245,7 +245,8 @@ module ApplicationSettingsHelper
|
|||
:usage_ping_enabled,
|
||||
:user_default_external,
|
||||
:user_oauth_applications,
|
||||
:version_check_enabled
|
||||
:version_check_enabled,
|
||||
:allow_local_requests_from_hooks_and_services
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -531,4 +531,22 @@ module ProjectsHelper
|
|||
def can_show_last_commit_in_list?(project)
|
||||
can?(current_user, :read_cross_project) && project.commit
|
||||
end
|
||||
|
||||
def pages_https_only_disabled?
|
||||
!@project.pages_domains.all?(&:https?)
|
||||
end
|
||||
|
||||
def pages_https_only_title
|
||||
return unless pages_https_only_disabled?
|
||||
|
||||
"You must enable HTTPS for all your domains first"
|
||||
end
|
||||
|
||||
def pages_https_only_label_class
|
||||
if pages_https_only_disabled?
|
||||
"list-label disabled"
|
||||
else
|
||||
"list-label"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -330,7 +330,8 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
usage_ping_enabled: Settings.gitlab['usage_ping_enabled'],
|
||||
gitaly_timeout_fast: 10,
|
||||
gitaly_timeout_medium: 30,
|
||||
gitaly_timeout_default: 55
|
||||
gitaly_timeout_default: 55,
|
||||
allow_local_requests_from_hooks_and_services: false
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ module Ci
|
|||
|
||||
has_many :stages
|
||||
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
|
||||
has_many :builds, foreign_key: :commit_id
|
||||
has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
|
||||
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
|
||||
has_many :variables, class_name: 'Ci::PipelineVariable'
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ module Avatarable
|
|||
|
||||
def avatar_type
|
||||
unless self.avatar.image?
|
||||
self.errors.add :avatar, "only images allowed"
|
||||
errors.add :avatar, "file format is not supported. Please try one of the following supported formats: #{AvatarUploader::IMAGE_EXT.join(', ')}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -189,12 +189,6 @@ class Group < Namespace
|
|||
owners.include?(user) && owners.size == 1
|
||||
end
|
||||
|
||||
def avatar_type
|
||||
unless self.avatar.image?
|
||||
self.errors.add :avatar, "only images allowed"
|
||||
end
|
||||
end
|
||||
|
||||
def post_create_hook
|
||||
Gitlab::AppLogger.info("Group \"#{name}\" was created")
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ class PagesDomain < ActiveRecord::Base
|
|||
|
||||
validates :domain, hostname: { allow_numeric_hostname: true }
|
||||
validates :domain, uniqueness: { case_sensitive: false }
|
||||
validates :certificate, certificate: true, allow_nil: true, allow_blank: true
|
||||
validates :key, certificate_key: true, allow_nil: true, allow_blank: true
|
||||
validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? }
|
||||
validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? }
|
||||
validates :key, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? }
|
||||
validates :key, certificate_key: true, if: ->(domain) { domain.key.present? }
|
||||
validates :verification_code, presence: true, allow_blank: false
|
||||
|
||||
validate :validate_pages_domain
|
||||
|
@ -46,6 +48,10 @@ class PagesDomain < ActiveRecord::Base
|
|||
!Gitlab::CurrentSettings.pages_domain_verification_enabled? || enabled_until.present?
|
||||
end
|
||||
|
||||
def https?
|
||||
certificate.present?
|
||||
end
|
||||
|
||||
def to_param
|
||||
domain
|
||||
end
|
||||
|
|
|
@ -38,6 +38,9 @@ class Project < ActiveRecord::Base
|
|||
attachments: 2
|
||||
}.freeze
|
||||
|
||||
# Valids ports to import from
|
||||
VALID_IMPORT_PORTS = [22, 80, 443].freeze
|
||||
|
||||
cache_markdown_field :description, pipeline: :description
|
||||
|
||||
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
|
||||
|
@ -264,6 +267,7 @@ class Project < ActiveRecord::Base
|
|||
validate :visibility_level_allowed_by_group
|
||||
validate :visibility_level_allowed_as_fork
|
||||
validate :check_wiki_path_conflict
|
||||
validate :validate_pages_https_only, if: -> { changes.has_key?(:pages_https_only) }
|
||||
validates :repository_storage,
|
||||
presence: true,
|
||||
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
|
||||
|
@ -500,7 +504,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def repository_storage_path
|
||||
Gitlab.config.repositories.storages[repository_storage].try(:[], 'path')
|
||||
Gitlab.config.repositories.storages[repository_storage]&.legacy_disk_path
|
||||
end
|
||||
|
||||
def team
|
||||
|
@ -734,6 +738,26 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def pages_https_only
|
||||
return false unless Gitlab.config.pages.external_https
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def pages_https_only?
|
||||
return false unless Gitlab.config.pages.external_https
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def validate_pages_https_only
|
||||
return unless pages_https_only?
|
||||
|
||||
unless pages_domains.all?(&:https?)
|
||||
errors.add(:pages_https_only, "cannot be enabled unless all domains have TLS certificates")
|
||||
end
|
||||
end
|
||||
|
||||
def to_param
|
||||
if persisted? && errors.include?(:path)
|
||||
path_was
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class AssemblaService < Service
|
||||
include HTTParty
|
||||
|
||||
prop_accessor :token, :subdomain
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
|
@ -31,6 +29,6 @@ class AssemblaService < Service
|
|||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}"
|
||||
AssemblaService.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
Gitlab::HTTP.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -117,14 +117,14 @@ class BambooService < CiService
|
|||
url = build_url(path)
|
||||
|
||||
if username.blank? && password.blank?
|
||||
HTTParty.get(url, verify: false)
|
||||
Gitlab::HTTP.get(url, verify: false)
|
||||
else
|
||||
url << '&os_authType=basic'
|
||||
HTTParty.get(url, verify: false,
|
||||
basic_auth: {
|
||||
username: username,
|
||||
password: password
|
||||
})
|
||||
Gitlab::HTTP.get(url, verify: false,
|
||||
basic_auth: {
|
||||
username: username,
|
||||
password: password
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -71,7 +71,7 @@ class BuildkiteService < CiService
|
|||
end
|
||||
|
||||
def calculate_reactive_cache(sha, ref)
|
||||
response = HTTParty.get(commit_status_path(sha), verify: false)
|
||||
response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
|
||||
|
||||
status =
|
||||
if response.code == 200 && response['status']
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class CampfireService < Service
|
||||
include HTTParty
|
||||
|
||||
prop_accessor :token, :subdomain, :room
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
|
@ -31,7 +29,6 @@ class CampfireService < Service
|
|||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
self.class.base_uri base_uri
|
||||
message = build_message(data)
|
||||
speak(self.room, message, auth)
|
||||
end
|
||||
|
@ -69,14 +66,14 @@ class CampfireService < Service
|
|||
}
|
||||
}
|
||||
}
|
||||
res = self.class.post(path, auth.merge(body))
|
||||
res = Gitlab::HTTP.post(path, base_uri: base_uri, **auth.merge(body))
|
||||
res.code == 201 ? res : nil
|
||||
end
|
||||
|
||||
# Returns a list of rooms, or [].
|
||||
# https://github.com/basecamp/campfire-api/blob/master/sections/rooms.md#get-rooms
|
||||
def rooms(auth)
|
||||
res = self.class.get("/rooms.json", auth)
|
||||
res = Gitlab::HTTP.get("/rooms.json", base_uri: base_uri, **auth)
|
||||
res.code == 200 ? res["rooms"] : []
|
||||
end
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ class DroneCiService < CiService
|
|||
end
|
||||
|
||||
def calculate_reactive_cache(sha, ref)
|
||||
response = HTTParty.get(commit_status_path(sha, ref), verify: enable_ssl_verification)
|
||||
response = Gitlab::HTTP.get(commit_status_path(sha, ref), verify: enable_ssl_verification)
|
||||
|
||||
status =
|
||||
if response.code == 200 && response['status']
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class ExternalWikiService < Service
|
||||
include HTTParty
|
||||
|
||||
prop_accessor :external_wiki_url
|
||||
|
||||
validates :external_wiki_url, presence: true, url: true, if: :activated?
|
||||
|
@ -24,7 +22,7 @@ class ExternalWikiService < Service
|
|||
end
|
||||
|
||||
def execute(_data)
|
||||
@response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil
|
||||
@response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true) rescue nil
|
||||
if @response != 200
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -77,13 +77,13 @@ class IssueTrackerService < Service
|
|||
result = false
|
||||
|
||||
begin
|
||||
response = HTTParty.head(self.project_url, verify: true)
|
||||
response = Gitlab::HTTP.head(self.project_url, verify: true)
|
||||
|
||||
if response
|
||||
message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
|
||||
result = true
|
||||
end
|
||||
rescue HTTParty::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
|
||||
rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
|
||||
message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}"
|
||||
end
|
||||
Rails.logger.info(message)
|
||||
|
|
|
@ -52,7 +52,7 @@ class MockCiService < CiService
|
|||
#
|
||||
#
|
||||
def commit_status(sha, ref)
|
||||
response = HTTParty.get(commit_status_path(sha), verify: false)
|
||||
response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
|
||||
read_commit_status(response)
|
||||
rescue Errno::ECONNREFUSED
|
||||
:error
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class PackagistService < Service
|
||||
include HTTParty
|
||||
|
||||
prop_accessor :username, :token, :server
|
||||
|
||||
validates :username, presence: true, if: :activated?
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class PivotaltrackerService < Service
|
||||
include HTTParty
|
||||
|
||||
API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'.freeze
|
||||
|
||||
prop_accessor :token, :restrict_to_branch
|
||||
|
@ -52,7 +50,7 @@ class PivotaltrackerService < Service
|
|||
'message' => commit[:message]
|
||||
}
|
||||
}
|
||||
PivotaltrackerService.post(
|
||||
Gitlab::HTTP.post(
|
||||
API_ENDPOINT,
|
||||
body: message.to_json,
|
||||
headers: {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
class PushoverService < Service
|
||||
include HTTParty
|
||||
base_uri 'https://api.pushover.net/1'
|
||||
BASE_URI = 'https://api.pushover.net/1'.freeze
|
||||
|
||||
prop_accessor :api_key, :user_key, :device, :priority, :sound
|
||||
validates :api_key, :user_key, :priority, presence: true, if: :activated?
|
||||
|
@ -99,6 +98,6 @@ class PushoverService < Service
|
|||
pushover_data[:sound] = sound
|
||||
end
|
||||
|
||||
PushoverService.post('/messages.json', body: pushover_data)
|
||||
Gitlab::HTTP.post('/messages.json', base_uri: BASE_URI, body: pushover_data)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -83,7 +83,7 @@ class TeamcityService < CiService
|
|||
|
||||
branch = Gitlab::Git.ref_name(data[:ref])
|
||||
|
||||
HTTParty.post(
|
||||
Gitlab::HTTP.post(
|
||||
build_url('httpAuth/app/rest/buildQueue'),
|
||||
body: "<build branchName=\"#{branch}\">"\
|
||||
"<buildType id=\"#{build_type}\"/>"\
|
||||
|
@ -134,10 +134,10 @@ class TeamcityService < CiService
|
|||
end
|
||||
|
||||
def get_path(path)
|
||||
HTTParty.get(build_url(path), verify: false,
|
||||
basic_auth: {
|
||||
username: username,
|
||||
password: password
|
||||
})
|
||||
Gitlab::HTTP.get(build_url(path), verify: false,
|
||||
basic_auth: {
|
||||
username: username,
|
||||
password: password
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -65,7 +65,7 @@ module Ci
|
|||
project.pipelines
|
||||
.where(ref: pipeline.ref)
|
||||
.where.not(id: pipeline.id)
|
||||
.where.not(sha: project.repository.sha_from_ref(pipeline.ref))
|
||||
.where.not(sha: project.commit(pipeline.ref).try(:id))
|
||||
.created_or_pending
|
||||
end
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ module Projects
|
|||
|
||||
def add_repository_to_project
|
||||
if project.external_import? && !unknown_url?
|
||||
raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url)
|
||||
raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url, valid_ports: Project::VALID_IMPORT_PORTS)
|
||||
end
|
||||
|
||||
# We should skip the repository for a GitHub import or GitLab project import,
|
||||
|
|
|
@ -18,7 +18,8 @@ module Projects
|
|||
|
||||
def pages_config
|
||||
{
|
||||
domains: pages_domains_config
|
||||
domains: pages_domains_config,
|
||||
https_only: project.pages_https_only?
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -27,7 +28,8 @@ module Projects
|
|||
{
|
||||
domain: domain.domain,
|
||||
certificate: domain.certificate,
|
||||
key: domain.key
|
||||
key: domain.key,
|
||||
https_only: project.pages_https_only? && domain.https?
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,6 +24,8 @@ module Projects
|
|||
system_hook_service.execute_hooks_for(project, :update)
|
||||
end
|
||||
|
||||
update_pages_config if changing_pages_https_only?
|
||||
|
||||
success
|
||||
else
|
||||
model_errors = project.errors.full_messages.to_sentence
|
||||
|
@ -67,5 +69,13 @@ module Projects
|
|||
log_error("Could not create wiki for #{project.full_name}")
|
||||
Gitlab::Metrics.counter(:wiki_can_not_be_created_total, 'Counts the times we failed to create a wiki')
|
||||
end
|
||||
|
||||
def update_pages_config
|
||||
Projects::UpdatePagesConfigurationService.new(project).execute
|
||||
end
|
||||
|
||||
def changing_pages_https_only?
|
||||
project.previous_changes.include?(:pages_https_only)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,16 +14,17 @@ class SubmitUsagePingService
|
|||
def execute
|
||||
return false unless Gitlab::CurrentSettings.usage_ping_enabled?
|
||||
|
||||
response = HTTParty.post(
|
||||
response = Gitlab::HTTP.post(
|
||||
URL,
|
||||
body: Gitlab::UsageData.to_json(force_refresh: true),
|
||||
allow_local_requests: true,
|
||||
headers: { 'Content-type' => 'application/json' }
|
||||
)
|
||||
|
||||
store_metrics(response)
|
||||
|
||||
true
|
||||
rescue HTTParty::Error => e
|
||||
rescue Gitlab::HTTP::Error => e
|
||||
Rails.logger.info "Unable to contact GitLab, Inc.: #{e}"
|
||||
|
||||
false
|
||||
|
|
|
@ -3,23 +3,20 @@ class WebHookService
|
|||
attr_reader :body, :headers, :code
|
||||
|
||||
def initialize
|
||||
@headers = HTTParty::Response::Headers.new({})
|
||||
@headers = Gitlab::HTTP::Response::Headers.new({})
|
||||
@body = ''
|
||||
@code = 'internal error'
|
||||
end
|
||||
end
|
||||
|
||||
include HTTParty
|
||||
|
||||
# HTTParty timeout
|
||||
default_timeout Gitlab.config.gitlab.webhook_timeout
|
||||
|
||||
attr_accessor :hook, :data, :hook_name
|
||||
attr_accessor :hook, :data, :hook_name, :request_options
|
||||
|
||||
def initialize(hook, data, hook_name)
|
||||
@hook = hook
|
||||
@data = data
|
||||
@hook_name = hook_name.to_s
|
||||
@request_options = { timeout: Gitlab.config.gitlab.webhook_timeout }
|
||||
@request_options.merge!(allow_local_requests: true) if @hook.is_a?(SystemHook)
|
||||
end
|
||||
|
||||
def execute
|
||||
|
@ -73,11 +70,12 @@ class WebHookService
|
|||
end
|
||||
|
||||
def make_request(url, basic_auth = false)
|
||||
self.class.post(url,
|
||||
Gitlab::HTTP.post(url,
|
||||
body: data.to_json,
|
||||
headers: build_headers(hook_name),
|
||||
verify: hook.enable_ssl_verification,
|
||||
basic_auth: basic_auth)
|
||||
basic_auth: basic_auth,
|
||||
**request_options)
|
||||
end
|
||||
|
||||
def make_request_with_auth
|
||||
|
|
|
@ -16,8 +16,6 @@ class CertificateValidator < ActiveModel::EachValidator
|
|||
private
|
||||
|
||||
def valid_certificate_pem?(value)
|
||||
return false unless value
|
||||
|
||||
OpenSSL::X509::Certificate.new(value).present?
|
||||
rescue OpenSSL::X509::CertificateError
|
||||
false
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# protect against Server-side Request Forgery (SSRF).
|
||||
class ImportableUrlValidator < ActiveModel::EachValidator
|
||||
def validate_each(record, attribute, value)
|
||||
if Gitlab::UrlBlocker.blocked_url?(value)
|
||||
if Gitlab::UrlBlocker.blocked_url?(value, valid_ports: Project::VALID_IMPORT_PORTS)
|
||||
record.errors.add(attribute, "imports are not allowed from that URL")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -860,5 +860,14 @@
|
|||
.col-sm-10
|
||||
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control'
|
||||
|
||||
%fieldset
|
||||
%legend Outbound requests
|
||||
.form-group
|
||||
.col-sm-offset-2.col-sm-10
|
||||
.checkbox
|
||||
= f.label :allow_local_requests_from_hooks_and_services do
|
||||
= f.check_box :allow_local_requests_from_hooks_and_services
|
||||
Allow requests to the local network from hooks and services
|
||||
|
||||
.form-actions
|
||||
= f.submit 'Save', class: 'btn btn-save'
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
.form-group
|
||||
.input-group
|
||||
- if current_user.can_select_namespace?
|
||||
.input-group-addon
|
||||
.input-group-addon.has-tooltip{ title: root_url }
|
||||
= root_url
|
||||
= select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace', tabindex: 1
|
||||
|
||||
- else
|
||||
.input-group-addon.static-namespace
|
||||
#{root_url}#{current_user.username}/
|
||||
.input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
|
||||
#{user_url(current_user.username)}/
|
||||
= hidden_field_tag :namespace_id, value: current_user.namespace_id
|
||||
.form-group.col-xs-12.col-sm-6.project-path
|
||||
= label_tag :path, 'Project name', class: 'label-light'
|
||||
|
|
|
@ -67,12 +67,8 @@
|
|||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%img{ alt: "GitLab", height: "33", src: image_url('mailers/gitlab_footer_logo.gif'), style: "display:block;margin:0 auto 1em;", width: "90" }/
|
||||
%div
|
||||
%a{ href: profile_notifications_url, style: "color:#3777b0;text-decoration:none;" } Manage all notifications
|
||||
·
|
||||
%a{ href: help_url, style: "color:#3777b0;text-decoration:none;" } Help
|
||||
%div
|
||||
You're receiving this email because of your account on
|
||||
= succeed "." do
|
||||
%a{ href: root_url, style: "color:#3777b0;text-decoration:none;" }= Gitlab.config.gitlab.host
|
||||
- manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, style: "color:#3777b0;text-decoration:none;")
|
||||
- help_link = link_to(_("Help"), help_url, style: "color:#3777b0;text-decoration:none;")
|
||||
= _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} · %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
|
||||
|
||||
= yield :additional_footer
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
.mobile-overlay
|
||||
.alert-wrapper
|
||||
= render "layouts/broadcast"
|
||||
= render 'layouts/header/read_only_banner'
|
||||
= yield :flash_message
|
||||
- unless @hide_breadcrumbs
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
|
|
7
app/views/layouts/header/_read_only_banner.html.haml
Normal file
7
app/views/layouts/header/_read_only_banner.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
- message = read_only_message
|
||||
- if message
|
||||
.flash-container.flash-container-page
|
||||
.flash-notice
|
||||
%div{ class: (container_class) }
|
||||
%span
|
||||
= message
|
|
@ -6,7 +6,7 @@
|
|||
profile_url: url_for(params.merge(lineprofiler: 'true')) },
|
||||
class: Peek.env }
|
||||
|
||||
#peek-view-performance-bar
|
||||
#peek-view-performance-bar.hidden
|
||||
= render_server_response_time
|
||||
%span#serverstats
|
||||
%ul.performance-bar
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
|
||||
#{time_ago_with_tooltip(event.created_at)}
|
||||
|
||||
.pull-right
|
||||
.flex-right
|
||||
= link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm qa-create-merge-request" do
|
||||
#{ _('Create merge request') }
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
Project path
|
||||
.input-group
|
||||
- if current_user.can_select_namespace?
|
||||
.input-group-addon
|
||||
.input-group-addon.has-tooltip{ title: root_url }
|
||||
= root_url
|
||||
= f.select :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), {}, { class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1}
|
||||
|
||||
- else
|
||||
.input-group-addon.static-namespace
|
||||
.input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
|
||||
#{user_url(current_user.username)}/
|
||||
= f.hidden_field :namespace_id, value: current_user.namespace_id
|
||||
.form-group.project-path.col-sm-6
|
||||
|
|
|
@ -5,81 +5,82 @@
|
|||
- number_commits_behind = diverging_commit_counts[:behind]
|
||||
- number_commits_ahead = diverging_commit_counts[:ahead]
|
||||
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
|
||||
%li{ class: "js-branch-#{branch.name}" }
|
||||
%div
|
||||
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated ref-name' do
|
||||
= sprite_icon('fork', size: 12)
|
||||
= branch.name
|
||||
|
||||
- if branch.name == @repository.root_ref
|
||||
%span.label.label-primary default
|
||||
- elsif merged
|
||||
%span.label.label-info.has-tooltip{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
|
||||
= s_('Branches|merged')
|
||||
%li{ class: "branch-item js-branch-#{branch.name}" }
|
||||
.branch-info
|
||||
.branch-title
|
||||
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name' do
|
||||
= sprite_icon('fork', size: 12)
|
||||
= branch.name
|
||||
|
||||
- if branch.name == @repository.root_ref
|
||||
%span.label.label-primary default
|
||||
- elsif merged
|
||||
%span.label.label-info.has-tooltip{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
|
||||
= s_('Branches|merged')
|
||||
|
||||
- if protected_branch?(@project, branch)
|
||||
%span.label.label-success
|
||||
= s_('Branches|protected')
|
||||
.controls.hidden-xs<
|
||||
- if merge_project && create_mr_button?(@repository.root_ref, branch.name)
|
||||
= link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
|
||||
= _('Merge request')
|
||||
- if protected_branch?(@project, branch)
|
||||
%span.label.label-success
|
||||
= s_('Branches|protected')
|
||||
|
||||
- if branch.name != @repository.root_ref
|
||||
= link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
|
||||
class: "btn btn-default #{'prepend-left-10' unless merge_project}",
|
||||
method: :post,
|
||||
title: s_('Branches|Compare') do
|
||||
= s_('Branches|Compare')
|
||||
.block-truncated
|
||||
- if commit
|
||||
= render 'projects/branches/commit', commit: commit, project: @project
|
||||
- else
|
||||
= s_('Branches|Cant find HEAD commit for this branch')
|
||||
|
||||
= render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name]
|
||||
- if branch.name != @repository.root_ref
|
||||
.divergence-graph{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind),
|
||||
default_branch: @repository.root_ref,
|
||||
number_commits_ahead: diverging_count_label(number_commits_ahead) } }
|
||||
.graph-side
|
||||
.bar.bar-behind{ style: "width: #{number_commits_behind * bar_graph_width_factor}%" }
|
||||
%span.count.count-behind= diverging_count_label(number_commits_behind)
|
||||
.graph-separator
|
||||
.graph-side
|
||||
.bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" }
|
||||
%span.count.count-ahead= diverging_count_label(number_commits_ahead)
|
||||
|
||||
- if can?(current_user, :push_code, @project)
|
||||
- if branch.name == @project.repository.root_ref
|
||||
%button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
|
||||
disabled: true,
|
||||
title: s_('Branches|The default branch cannot be deleted') }
|
||||
= icon("trash-o")
|
||||
- elsif protected_branch?(@project, branch)
|
||||
- if can?(current_user, :delete_protected_branch, @project)
|
||||
%button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
|
||||
title: s_('Branches|Delete protected branch'),
|
||||
data: { toggle: "modal",
|
||||
target: "#modal-delete-branch",
|
||||
delete_path: project_branch_path(@project, branch.name),
|
||||
branch_name: branch.name,
|
||||
is_merged: ("true" if merged) } }
|
||||
= icon("trash-o")
|
||||
- else
|
||||
%button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
|
||||
disabled: true,
|
||||
title: s_('Branches|Only a project master or owner can delete a protected branch') }
|
||||
= icon("trash-o")
|
||||
- else
|
||||
= link_to project_branch_path(@project, branch.name),
|
||||
class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
|
||||
title: s_('Branches|Delete branch'),
|
||||
method: :delete,
|
||||
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
|
||||
remote: true,
|
||||
'aria-label' => s_('Branches|Delete branch') do
|
||||
= icon("trash-o")
|
||||
.controls.hidden-xs<
|
||||
- if merge_project && create_mr_button?(@repository.root_ref, branch.name)
|
||||
= link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
|
||||
= _('Merge request')
|
||||
|
||||
- if branch.name != @repository.root_ref
|
||||
.divergence-graph{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind),
|
||||
default_branch: @repository.root_ref,
|
||||
number_commits_ahead: diverging_count_label(number_commits_ahead) } }
|
||||
.graph-side
|
||||
.bar.bar-behind{ style: "width: #{number_commits_behind * bar_graph_width_factor}%" }
|
||||
%span.count.count-behind= diverging_count_label(number_commits_behind)
|
||||
.graph-separator
|
||||
.graph-side
|
||||
.bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" }
|
||||
%span.count.count-ahead= diverging_count_label(number_commits_ahead)
|
||||
= link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
|
||||
class: "btn btn-default #{'prepend-left-10' unless merge_project}",
|
||||
method: :post,
|
||||
title: s_('Branches|Compare') do
|
||||
= s_('Branches|Compare')
|
||||
|
||||
= render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name]
|
||||
|
||||
- if commit
|
||||
= render 'projects/branches/commit', commit: commit, project: @project
|
||||
- else
|
||||
%p
|
||||
= s_('Branches|Cant find HEAD commit for this branch')
|
||||
- if can?(current_user, :push_code, @project)
|
||||
- if branch.name == @project.repository.root_ref
|
||||
%button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
|
||||
disabled: true,
|
||||
title: s_('Branches|The default branch cannot be deleted') }
|
||||
= icon("trash-o")
|
||||
- elsif protected_branch?(@project, branch)
|
||||
- if can?(current_user, :delete_protected_branch, @project)
|
||||
%button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
|
||||
title: s_('Branches|Delete protected branch'),
|
||||
data: { toggle: "modal",
|
||||
target: "#modal-delete-branch",
|
||||
delete_path: project_branch_path(@project, branch.name),
|
||||
branch_name: branch.name,
|
||||
is_merged: ("true" if merged) } }
|
||||
= icon("trash-o")
|
||||
- else
|
||||
%button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
|
||||
disabled: true,
|
||||
title: s_('Branches|Only a project master or owner can delete a protected branch') }
|
||||
= icon("trash-o")
|
||||
- else
|
||||
= link_to project_branch_path(@project, branch.name),
|
||||
class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
|
||||
title: s_('Branches|Delete branch'),
|
||||
method: :delete,
|
||||
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
|
||||
remote: true,
|
||||
'aria-label' => s_('Branches|Delete branch') do
|
||||
= icon("trash-o")
|
||||
|
|
10
app/views/projects/pages/_https_only.html.haml
Normal file
10
app/views/projects/pages/_https_only.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
= form_for @project, url: namespace_project_pages_path(@project.namespace.becomes(Namespace), @project), html: { class: 'inline', title: pages_https_only_title } do |f|
|
||||
= f.check_box :pages_https_only, class: 'pull-left', disabled: pages_https_only_disabled?
|
||||
|
||||
.prepend-left-20
|
||||
= f.label :pages_https_only, class: pages_https_only_label_class do
|
||||
%strong Force domains with SSL certificates to use HTTPS
|
||||
|
||||
- unless pages_https_only_disabled?
|
||||
.prepend-top-10
|
||||
= f.submit 'Save', class: 'btn btn-success'
|
|
@ -13,6 +13,9 @@
|
|||
Combined with the power of GitLab CI and the help of GitLab Runner
|
||||
you can deploy static pages for your individual projects, your user or your group.
|
||||
|
||||
- if Gitlab.config.pages.external_https
|
||||
= render 'https_only'
|
||||
|
||||
%hr.clearfix
|
||||
|
||||
= render 'access'
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Add missing pagination on the commit diff endpoint
|
||||
merge_request: 17203
|
||||
author: Maxime Roussin-Bélanger
|
||||
type: fixed
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Moved o_auth/saml/ldap modules under gitlab/auth
|
||||
merge_request: 17359
|
||||
author: Horatiu Eugen Vlad
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Update issue closing pattern to allow variations in punctuation
|
||||
merge_request: 17198
|
||||
author: Vicky Chijwani
|
||||
type: changed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Clear the Labels dropdown search filter after a selection is made
|
||||
merge_request: 17393
|
||||
author: Andrew Torres
|
||||
type: changed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Update to github-linguist 5.3.x
|
||||
merge_request: 17241
|
||||
author: Ken Ding
|
||||
type: other
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Group MRs on issue page by project and namespace.
|
||||
merge_request: 8494
|
||||
author: Jeff Stubler
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Add project export API
|
||||
merge_request: 15860
|
||||
author: Travis Miller
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Add verification for GitLab Pages custom domains
|
||||
merge_request:
|
||||
author:
|
||||
type: security
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Add email button to new issue by email
|
||||
merge_request: 10942
|
||||
author: Islam Wazery
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix duplicate system notes when merging a merge request.
|
||||
merge_request: 17035
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Allow installation of GitLab Runner with a single click
|
||||
merge_request: 17134
|
||||
author:
|
||||
type: added
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes
|
||||
merge_request: 17345
|
||||
author:
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: remove avater underline
|
||||
merge_request: 17219
|
||||
author: Ken Ding
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Fix Teleporting Emoji
|
||||
merge_request: 16963
|
||||
author: Jared Deckard <jared.deckard@gmail.com>
|
||||
type: fixed
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: update toml-rb to 1.0.0
|
||||
merge_request: 17259
|
||||
author: Ken Ding
|
||||
type: other
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Display a link to external issue tracker when enabled
|
||||
merge_request:
|
||||
author:
|
||||
type: changed
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue