merge master and fix application.rb conflict
This commit is contained in:
commit
71d731a21b
217
CHANGELOG.md
217
CHANGELOG.md
|
@ -2,6 +2,223 @@
|
||||||
documentation](doc/development/changelog.md) for instructions on adding your own
|
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||||
entry.
|
entry.
|
||||||
|
|
||||||
|
## 8.15.1 (2016-12-23)
|
||||||
|
|
||||||
|
- Push payloads schedule at most 100 commits, instead of all commits.
|
||||||
|
- Fix Mattermost command creation by specifying username.
|
||||||
|
- Do not override incoming webhook for mattermost and slack.
|
||||||
|
- Adds background color for disabled state to merge when succeeds dropdown. !8222
|
||||||
|
- Standardises font-size for titles in Issues, Merge Requests and Merge Request widget. !8235
|
||||||
|
- Fix Pipeline builds list blank on MR. !8255
|
||||||
|
- Do not show retried builds in pipeline stage dropdown. !8260
|
||||||
|
|
||||||
|
## 8.15.0 (2016-12-22)
|
||||||
|
|
||||||
|
- Whitelist next project names: notes, services.
|
||||||
|
- Use Grape's new Route methods.
|
||||||
|
- Fixed issue boards scrolling with a lot of lists & issues.
|
||||||
|
- Remove unnecessary sentences for status codes in the API documentation. (Luis Alonso Chavez Armendariz)
|
||||||
|
- Allow unauthenticated access to Repositories Files API GET endpoints.
|
||||||
|
- Add note to the invite page when the logged in user email is not the same as the invitation.
|
||||||
|
- Don't accidentally mark unsafe diff lines as HTML safe.
|
||||||
|
- Add git diff context to notifications of new notes on merge requests. (Heidi Hoopes)
|
||||||
|
- Shows group members in project members list.
|
||||||
|
- Gem update: Update grape to 0.18.0. (Robert Schilling)
|
||||||
|
- API: Expose merge status for branch API. (Robert Schilling)
|
||||||
|
- Displays milestone remaining days only when it's present.
|
||||||
|
- API: Expose committer details for commits. (Robert Schilling)
|
||||||
|
- API: Ability to set 'should_remove_source_branch' on merge requests. (Robert Schilling)
|
||||||
|
- Fix project import label priorities error.
|
||||||
|
- Fix Import/Export merge requests error while importing.
|
||||||
|
- Refactor Bitbucket importer to use BitBucket API Version 2.
|
||||||
|
- Fix Import/Export duplicated builds error.
|
||||||
|
- Ci::Builds have same ref as Ci::Pipeline in dev fixtures. (twonegatives)
|
||||||
|
- For single line git commit messages, the close quote should be on the same line as the open quote.
|
||||||
|
- Use authorized projects in ProjectTeam.
|
||||||
|
- Destroy a user's session when they delete their own account.
|
||||||
|
- Edit help text to clarify annotated tag creation. (Liz Lam)
|
||||||
|
- Fixed file template dropdown for the "New File" editor for smaller/zoomed screens.
|
||||||
|
- Fix Route#rename_children behavior.
|
||||||
|
- Add nested groups support on data level.
|
||||||
|
- Allow projects with 'dashboard' as path.
|
||||||
|
- Disabled emoji buttons when user is not logged in.
|
||||||
|
- Remove unused and void services from the database.
|
||||||
|
- Add issue search slash command.
|
||||||
|
- Accept issue new as command to create an issue.
|
||||||
|
- Non members cannot create labels through the API.
|
||||||
|
- API: expose pipeline coverage.
|
||||||
|
- Validate state param when filtering issuables.
|
||||||
|
- Username exists check respects relative root path.
|
||||||
|
- Bump Git version requirement to 2.8.4.
|
||||||
|
- Updates the font weight of button styles because of the change to system fonts.
|
||||||
|
- Update API spec files to describe the correct class. (Livier)
|
||||||
|
- Fixed timeago re-rendering every timeago.
|
||||||
|
- Enable ColorVariable in scss-lint. (Sam Rose)
|
||||||
|
- Various small emoji positioning adjustments.
|
||||||
|
- Add shortcuts for adding users to a project team with a specific role. (Nikolay Ponomarev and Dino M)
|
||||||
|
- Additional rounded label fixes.
|
||||||
|
- Remove unnecessary database indices.
|
||||||
|
- 24726 Remove Across GitLab from side navigation.
|
||||||
|
- Changed cursor icon to pointer when mousing over stages on the Cycle Analytics pages. (Ryan Harris)
|
||||||
|
- Add focus state to dropdown items.
|
||||||
|
- Fixes Environments displaying incorrect date since 8.14 upgrade.
|
||||||
|
- Improve bulk assignment for issuables.
|
||||||
|
- Stop supporting Google and Azure as backup strategies.
|
||||||
|
- Fix broken README.md UX guide link.
|
||||||
|
- Allow public access to some Tag API endpoints.
|
||||||
|
- Encode input when migrating ProcessCommitWorker jobs to prevent migration errors.
|
||||||
|
- Adjust the width of project avatars to fix alignment within their container. (Ryan Harris)
|
||||||
|
- Sentence cased the nav tab headers on the project dashboard page. (Ryan Harris)
|
||||||
|
- Adds hoverstates for collapsed Issue/Merge Request sidebar.
|
||||||
|
- Make CI badge hitboxes match parent.
|
||||||
|
- Add a starting date to milestones.
|
||||||
|
- Adjusted margins for Build Status and Coverage Report rows to match those of the CI/CD Pipeline row. (Ryan Harris)
|
||||||
|
- Updated members dropdowns.
|
||||||
|
- Move all action buttons to project header.
|
||||||
|
- Replace issue access checks with use of IssuableFinder.
|
||||||
|
- Fix missing Note access checks by moving Note#search to updated NoteFinder.
|
||||||
|
- Centered Accept Merge Request button within MR widget and added padding for viewports smaller than 768px. (Ryan Harris)
|
||||||
|
- Fix missing access checks on issue lookup using IssuableFinder.
|
||||||
|
- Added top margin to Build status page header for mobile views. (Ryan Harris)
|
||||||
|
- Fixes "ActionView::Template::Error: undefined method `text?` for nil:NilClass" on MR pages.
|
||||||
|
- Issue#visible_to_user moved to IssuesFinder to prevent accidental use.
|
||||||
|
- Replace MR access checks with use of MergeRequestsFinder.
|
||||||
|
- Fix information disclosure in `Projects::BlobController#update`.
|
||||||
|
- Allow branch names with dots on API endpoint.
|
||||||
|
- Changed Housekeeping button on project settings page to default styling. (Ryan Harris)
|
||||||
|
- Ensure issuable state changes only fire webhooks once.
|
||||||
|
- Fix bad selection on dropdown menu for tags filter. (Luis Alonso Chavez Armendariz)
|
||||||
|
- Fix title case to sentence case. (Luis Alonso Chavez Armendariz)
|
||||||
|
- Fix appearance in error pages. (Luis Alonso Chavez Armendariz)
|
||||||
|
- Create mattermost service.
|
||||||
|
- 25617 Fix placeholder color of todo filters.
|
||||||
|
- Made the padding on the plus button in the breadcrumb menu even. (Ryan Harris)
|
||||||
|
- Allow to delete tag release note.
|
||||||
|
- Ensure nil User-Agent doesn't break the CI API.
|
||||||
|
- Replace Rack::Multipart with GitLab-Workhorse based solution. !5867
|
||||||
|
- Add scopes for personal access tokens and OAuth tokens. !5951
|
||||||
|
- API: Endpoint to expose personal snippets as /snippets. !6373 (Bernard Guyzmo Pratz)
|
||||||
|
- New `gitlab:workhorse:install` rake task. !6574
|
||||||
|
- Filter protocol-relative URLs in ExternalLinkFilter. Fixes issue #22742. !6635 (Makoto Scott-Hinkle)
|
||||||
|
- Add support for setting the GitLab Runners Registration Token during initial database seeding. !6642
|
||||||
|
- Guests can read builds when public. !6842
|
||||||
|
- Made comment autocomplete more performant and removed some loading bugs. !6856
|
||||||
|
- Add GitLab host to 2FA QR code and manual info. !6941
|
||||||
|
- Add sorting functionality for group/project members. !7032
|
||||||
|
- Rename Merge When Build Succeeds to Merge When Pipeline Succeeds. !7135
|
||||||
|
- Resolve all discussions in a merge request by creating an issue collecting them. !7180 (Bob Van Landuyt)
|
||||||
|
- Add Human Readable format for rake backup. !7188 (David Gerő)
|
||||||
|
- post_receive: accept any user email from last commit. !7225 (Elan Ruusamäe)
|
||||||
|
- Add support for Dockerfile templates. !7247
|
||||||
|
- Add shorthand support to gitlab markdown references. !7255 (Oswaldo Ferreira)
|
||||||
|
- Display error code for U2F errors. !7305 (winniehell)
|
||||||
|
- Fix wrong tab selected when loggin fails and multiple login tabs exists. !7314 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Clean up common_utils.js. !7318 (winniehell)
|
||||||
|
- Show commit status from latest pipeline. !7333
|
||||||
|
- Remove the help text under the sidebar subscribe button and style it inline. !7389
|
||||||
|
- Update wiki page design. !7429
|
||||||
|
- Add nested groups support to the routing. !7459
|
||||||
|
- Changed eslint airbnb config to the base airbnb config and corrected eslintrc plugins and envs. !7470 (Luke "Jared" Bennett)
|
||||||
|
- Fix cancelling created or external pipelines. !7508
|
||||||
|
- Allow admins to stop impersonating users without e-mail addresses. !7550 (Oren Kanner)
|
||||||
|
- Remove unnecessary self from user model. !7551 (Semyon Pupkov)
|
||||||
|
- Homogenize filter and sort dropdown look'n'feel. !7583 (David Wagner)
|
||||||
|
- Create dynamic fixture for build_spec. !7589 (winniehell)
|
||||||
|
- Moved Leave Project and Leave Group buttons to access_request_buttons from the settings dropdown. !7600
|
||||||
|
- Remove unnecessary require_relative calls from service classes. !7601 (Semyon Pupkov)
|
||||||
|
- Simplify copy on "Create a new list" dropdown in Issue Boards. !7605 (Victor Rodrigues)
|
||||||
|
- Refactor create service spec. !7609 (Semyon Pupkov)
|
||||||
|
- Shows unconfirmed email status in profile. !7611
|
||||||
|
- The admin user projects view now has a clickable group link. !7620 (James Gregory)
|
||||||
|
- Prevent DOM ID collisions resulting from user-generated content anchors. !7631
|
||||||
|
- Replace static fixture for abuse_reports_spec. !7644 (winniehell)
|
||||||
|
- Define common helper for describe pagination params in api. !7646 (Semyon Pupkov)
|
||||||
|
- Move abuse report spinach test to rspec. !7659 (Semyon Pupkov)
|
||||||
|
- Replace static fixture for awards_handler_spec. !7661 (winniehell)
|
||||||
|
- API: Add ability to unshare a project from a group. !7662 (Robert Schilling)
|
||||||
|
- Replace references to MergeRequestDiff#commits with st_commits when we care only about the number of commits. !7668
|
||||||
|
- Add issue events filter and make all really show all events. !7673 (Oxan van Leeuwen)
|
||||||
|
- Replace static fixture for notes_spec. !7683 (winniehell)
|
||||||
|
- Replace static fixture for shortcuts_issuable_spec. !7685 (winniehell)
|
||||||
|
- Replace static fixture for zen_mode_spec. !7686 (winniehell)
|
||||||
|
- Replace static fixture for right_sidebar_spec. !7687 (winniehell)
|
||||||
|
- Add online terminal support for Kubernetes. !7690
|
||||||
|
- Move admin abuse report spinach test to rspec. !7691 (Semyon Pupkov)
|
||||||
|
- Move admin spam spinach test to Rspec. !7708 (Semyon Pupkov)
|
||||||
|
- Make API::Helpers find a project with only one query. !7714
|
||||||
|
- Create builds in transaction to avoid empty pipelines. !7742
|
||||||
|
- Render SVG images in diffs and notes. !7747 (andrebsguedes)
|
||||||
|
- Add setting to enable/disable HTML emails. !7749
|
||||||
|
- Use SmartInterval for MR widget and improve visibilitychange functionality. !7762
|
||||||
|
- Resolve "Remove Builds tab from Merge Requests and Commits". !7763
|
||||||
|
- Moved new projects button below new group button on the welcome screen. !7770
|
||||||
|
- fix display hook error message. !7775 (basyura)
|
||||||
|
- Refactor issuable_filters_present to reduce duplications. !7776 (Semyon Pupkov)
|
||||||
|
- Redirect to sign-in page when unauthenticated user tries to create a snippet. !7786
|
||||||
|
- Fix Archived project merge requests add to group's Merge Requests. !7790 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Update generic/external build status to match normal build status template. !7811
|
||||||
|
- Enable AsciiDoctor admonition icons. !7812 (Horacio Sanson)
|
||||||
|
- Do not raise error in AutocompleteController#users when not authorized. !7817 (Semyon Pupkov)
|
||||||
|
- fix: 24982- Remove'Signed in successfully' message After this change the sign-in-success flash message will not be shown. !7837 (jnoortheen)
|
||||||
|
- Fix Latest deployment link is broken. !7839
|
||||||
|
- Don't display prompt to add SSH keys if SSH protocol is disabled. !7840 (Andrew Smith (EspadaV8))
|
||||||
|
- Allow unauthenticated access to some Project API GET endpoints. !7843
|
||||||
|
- Refactor presenters ChatCommands. !7846
|
||||||
|
- Improve help message for issue create slash command. !7850
|
||||||
|
- change text around timestamps to make it clear which timestamp is displayed. !7860 (BM5k)
|
||||||
|
- Improve Build Log scrolling experience. !7895
|
||||||
|
- Change ref property to commitRef in vue commit component. !7901
|
||||||
|
- Prevent user creating issue or MR without signing in for a group. !7902
|
||||||
|
- Provides a sensible default message when adding a README to a project. !7903
|
||||||
|
- Bump ruby version to 2.3.3. !7904
|
||||||
|
- Fix comments activity tab visibility condition. !7913 (Rydkin Maxim)
|
||||||
|
- Remove unnecessary target branch link from MR page in case of deleted target branch. !7916 (Rydkin Maxim)
|
||||||
|
- Add image controls to MR diffs. !7919
|
||||||
|
- Remove wrong '.builds-feature' class from the MR settings fieldset. !7930
|
||||||
|
- Resolve "Manual actions on pipeline graph". !7931
|
||||||
|
- Avoid escaping relative links in Markdown twice. !7940 (winniehell)
|
||||||
|
- Move admin hooks spinach to rspec. !7942 (Semyon Pupkov)
|
||||||
|
- Move admin logs spinach test to rspec. !7945 (Semyon Pupkov)
|
||||||
|
- fix: removed signed_out notification. !7958 (jnoortheen)
|
||||||
|
- Accept environment variables from the `pre-receive` script. !7967
|
||||||
|
- Do not reload diff for merge request made from fork when target branch in fork is updated. !7973
|
||||||
|
- Fixes left align issue for long system notes. !7982
|
||||||
|
- Add a slug to environments. !7983
|
||||||
|
- Fix lookup of project by unknown ref when caching is enabled. !7988
|
||||||
|
- Resolve "Provide SVG as a prop instead of hiding and copy them in environments table". !7992
|
||||||
|
- Introduce deployment services, starting with a KubernetesService. !7994
|
||||||
|
- Adds tests for custom event polyfill. !7996
|
||||||
|
- Allow all alphanumeric characters in file names. !8002 (winniehell)
|
||||||
|
- Added support for math rendering, using KaTeX, in Markdown and asciidoc. !8003 (Munken)
|
||||||
|
- Remove unnecessary commits order message. !8004
|
||||||
|
- API: Memoize the current_user so that sudo can work properly. !8017
|
||||||
|
- group authors in contribution graph with case insensitive email handle comparison. !8021
|
||||||
|
- Move admin active tab spinach tests to rspec. !8037 (Semyon Pupkov)
|
||||||
|
- Add Authentiq as Oauth provider. !8038 (Alexandros Keramidas)
|
||||||
|
- API: Ability to cherry pick a commit. !8047 (Robert Schilling)
|
||||||
|
- Fix Slack pipeline message from pipelines made by API. !8059
|
||||||
|
- API: Simple representation of group's projects. !8060 (Robert Schilling)
|
||||||
|
- Prevent overflow with vertical scroll when we have space to show content. !8061
|
||||||
|
- Allow to auto-configure Mattermost. !8070
|
||||||
|
- Introduce $CI_BUILD_REF_SLUG. !8072
|
||||||
|
- Added go back anchor on error pages. !8087
|
||||||
|
- Convert CI YAML variables keys into strings. !8088
|
||||||
|
- Adds Direct link from pipeline list to builds. !8097
|
||||||
|
- Cache last commit id for path. !8098 (Hiroyuki Sato)
|
||||||
|
- Pass variables from deployment project services to CI runner. !8107
|
||||||
|
- New Gitea importer. !8116
|
||||||
|
- Introduce "Set up autodeploy" button to help configure GitLab CI for deployment. !8135
|
||||||
|
- Prevent enviroment table to overflow when name has underscores. !8142
|
||||||
|
- Fix missing service error importing from EE to CE. !8144
|
||||||
|
- Milestoneish SQL performance partially improved and memoized. !8146
|
||||||
|
- Allow unauthenticated access to Repositories API GET endpoints. !8148
|
||||||
|
- fix colors and margins for adjacent alert banners. !8151
|
||||||
|
- Hides new issue button for non loggedin user. !8175
|
||||||
|
- Fix N+1 queries on milestone show pages. !8185
|
||||||
|
- Rename groups with .git in the end of the path. !8199
|
||||||
|
- Whitelist next project names: help, ci, admin, search. !8227
|
||||||
|
- Adds back CSS for progress-bars. !8237
|
||||||
|
|
||||||
## 8.14.5 (2016-12-14)
|
## 8.14.5 (2016-12-14)
|
||||||
|
|
||||||
- Moved Leave Project and Leave Group buttons to access_request_buttons from the settings dropdown. !7600
|
- Moved Leave Project and Leave Group buttons to access_request_buttons from the settings dropdown. !7600
|
||||||
|
|
1
Gemfile
1
Gemfile
|
@ -32,6 +32,7 @@ gem 'omniauth-saml', '~> 1.7.0'
|
||||||
gem 'omniauth-shibboleth', '~> 1.2.0'
|
gem 'omniauth-shibboleth', '~> 1.2.0'
|
||||||
gem 'omniauth-twitter', '~> 1.2.0'
|
gem 'omniauth-twitter', '~> 1.2.0'
|
||||||
gem 'omniauth_crowd', '~> 2.2.0'
|
gem 'omniauth_crowd', '~> 2.2.0'
|
||||||
|
gem 'omniauth-authentiq', '~> 0.2.0'
|
||||||
gem 'rack-oauth2', '~> 1.2.1'
|
gem 'rack-oauth2', '~> 1.2.1'
|
||||||
gem 'jwt'
|
gem 'jwt'
|
||||||
|
|
||||||
|
|
|
@ -428,6 +428,8 @@ GEM
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
omniauth-auth0 (1.4.1)
|
omniauth-auth0 (1.4.1)
|
||||||
omniauth-oauth2 (~> 1.1)
|
omniauth-oauth2 (~> 1.1)
|
||||||
|
omniauth-authentiq (0.2.2)
|
||||||
|
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
||||||
omniauth-azure-oauth2 (0.0.6)
|
omniauth-azure-oauth2 (0.0.6)
|
||||||
jwt (~> 1.0)
|
jwt (~> 1.0)
|
||||||
omniauth (~> 1.0)
|
omniauth (~> 1.0)
|
||||||
|
@ -897,6 +899,7 @@ DEPENDENCIES
|
||||||
oj (~> 2.17.4)
|
oj (~> 2.17.4)
|
||||||
omniauth (~> 1.3.1)
|
omniauth (~> 1.3.1)
|
||||||
omniauth-auth0 (~> 1.4.1)
|
omniauth-auth0 (~> 1.4.1)
|
||||||
|
omniauth-authentiq (~> 0.2.0)
|
||||||
omniauth-azure-oauth2 (~> 0.0.6)
|
omniauth-azure-oauth2 (~> 0.0.6)
|
||||||
omniauth-cas3 (~> 1.1.2)
|
omniauth-cas3 (~> 1.1.2)
|
||||||
omniauth-facebook (~> 4.0.0)
|
omniauth-facebook (~> 4.0.0)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
var AUTO_SCROLL_OFFSET = 75;
|
||||||
|
|
||||||
this.Build = (function() {
|
this.Build = (function() {
|
||||||
Build.interval = null;
|
Build.interval = null;
|
||||||
|
@ -19,6 +20,17 @@
|
||||||
this.buildStage = options.buildStage;
|
this.buildStage = options.buildStage;
|
||||||
this.updateDropdown = bind(this.updateDropdown, this);
|
this.updateDropdown = bind(this.updateDropdown, this);
|
||||||
this.$document = $(document);
|
this.$document = $(document);
|
||||||
|
this.$body = $('body');
|
||||||
|
this.$buildTrace = $('#build-trace');
|
||||||
|
this.$autoScrollContainer = $('.autoscroll-container');
|
||||||
|
this.$autoScrollStatus = $('#autoscroll-status');
|
||||||
|
this.$autoScrollStatusText = this.$autoScrollStatus.find('.status-text');
|
||||||
|
this.$upBuildTrace = $('#up-build-trace');
|
||||||
|
this.$downBuildTrace = $('#down-build-trace');
|
||||||
|
this.$scrollTopBtn = $('#scroll-top');
|
||||||
|
this.$scrollBottomBtn = $('#scroll-bottom');
|
||||||
|
this.$buildRefreshAnimation = $('.js-build-refresh');
|
||||||
|
|
||||||
clearInterval(Build.interval);
|
clearInterval(Build.interval);
|
||||||
// Init breakpoint checker
|
// Init breakpoint checker
|
||||||
this.bp = Breakpoints.get();
|
this.bp = Breakpoints.get();
|
||||||
|
@ -32,6 +44,7 @@
|
||||||
|
|
||||||
this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
|
this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
|
||||||
this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
|
this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
|
||||||
|
this.$document.on('scroll', this.initScrollMonitor.bind(this));
|
||||||
$(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this));
|
$(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this));
|
||||||
$('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace);
|
$('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace);
|
||||||
this.updateArtifactRemoveDate();
|
this.updateArtifactRemoveDate();
|
||||||
|
@ -40,18 +53,6 @@
|
||||||
this.initScrollButtonAffix();
|
this.initScrollButtonAffix();
|
||||||
}
|
}
|
||||||
if (this.buildStatus === "running" || this.buildStatus === "pending") {
|
if (this.buildStatus === "running" || this.buildStatus === "pending") {
|
||||||
// Bind autoscroll button to follow build output
|
|
||||||
$('#autoscroll-button').on('click', function() {
|
|
||||||
var state;
|
|
||||||
state = $(this).data("state");
|
|
||||||
if ("enabled" === state) {
|
|
||||||
$(this).data("state", "disabled");
|
|
||||||
return $(this).text("Enable autoscroll");
|
|
||||||
} else {
|
|
||||||
$(this).data("state", "enabled");
|
|
||||||
return $(this).text("Disable autoscroll");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Build.interval = setInterval((function(_this) {
|
Build.interval = setInterval((function(_this) {
|
||||||
// Check for new build output if user still watching build page
|
// Check for new build output if user still watching build page
|
||||||
// Only valid for runnig build when output changes during time
|
// Only valid for runnig build when output changes during time
|
||||||
|
@ -91,9 +92,10 @@
|
||||||
success: function(buildData) {
|
success: function(buildData) {
|
||||||
$('.js-build-output').html(buildData.trace_html);
|
$('.js-build-output').html(buildData.trace_html);
|
||||||
if (removeRefreshStatuses.indexOf(buildData.status) >= 0) {
|
if (removeRefreshStatuses.indexOf(buildData.status) >= 0) {
|
||||||
return $('.js-build-refresh').remove();
|
this.initScrollMonitor();
|
||||||
|
return this.$buildRefreshAnimation.remove();
|
||||||
}
|
}
|
||||||
}
|
}.bind(this)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,22 +124,95 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.checkAutoscroll = function() {
|
Build.prototype.checkAutoscroll = function() {
|
||||||
if ("enabled" === $("#autoscroll-button").data("state")) {
|
if (this.$autoScrollStatus.data("state") === "enabled") {
|
||||||
return $("html,body").scrollTop($("#build-trace").height());
|
return $("html,body").scrollTop(this.$buildTrace.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle a situation where user started new build
|
||||||
|
// but never scrolled a page
|
||||||
|
if (!this.$scrollTopBtn.is(':visible') &&
|
||||||
|
!this.$scrollBottomBtn.is(':visible') &&
|
||||||
|
!gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
||||||
|
this.$scrollBottomBtn.show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.initScrollButtonAffix = function() {
|
Build.prototype.initScrollButtonAffix = function() {
|
||||||
var $body, $buildTrace;
|
// Hide everything initially
|
||||||
$body = $('body');
|
this.$scrollTopBtn.hide();
|
||||||
$buildTrace = $('#build-trace');
|
this.$scrollBottomBtn.hide();
|
||||||
return this.$buildScroll.affix({
|
this.$autoScrollContainer.hide();
|
||||||
offset: {
|
}
|
||||||
bottom: function() {
|
|
||||||
return $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top);
|
// Page scroll listener to detect if user has scrolling page
|
||||||
}
|
// and handle following cases
|
||||||
|
// 1) User is at Top of Build Log;
|
||||||
|
// - Hide Top Arrow button
|
||||||
|
// - Show Bottom Arrow button
|
||||||
|
// - Disable Autoscroll and hide indicator (when build is running)
|
||||||
|
// 2) User is at Bottom of Build Log;
|
||||||
|
// - Show Top Arrow button
|
||||||
|
// - Hide Bottom Arrow button
|
||||||
|
// - Enable Autoscroll and show indicator (when build is running)
|
||||||
|
// 3) User is somewhere in middle of Build Log;
|
||||||
|
// - Show Top Arrow button
|
||||||
|
// - Show Bottom Arrow button
|
||||||
|
// - Disable Autoscroll and hide indicator (when build is running)
|
||||||
|
Build.prototype.initScrollMonitor = function() {
|
||||||
|
if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
||||||
|
// User is somewhere in middle of Build Log
|
||||||
|
|
||||||
|
this.$scrollTopBtn.show();
|
||||||
|
|
||||||
|
if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed
|
||||||
|
this.$scrollBottomBtn.show();
|
||||||
|
} else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation.get(0))) {
|
||||||
|
this.$scrollBottomBtn.show();
|
||||||
|
} else {
|
||||||
|
this.$scrollBottomBtn.hide();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// Hide Autoscroll Status Indicator
|
||||||
|
if (this.$scrollBottomBtn.is(':visible')) {
|
||||||
|
this.$autoScrollContainer.hide();
|
||||||
|
this.$autoScrollStatusText.removeClass('animate');
|
||||||
|
} else {
|
||||||
|
this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
|
||||||
|
this.$autoScrollStatusText.addClass('animate');
|
||||||
|
}
|
||||||
|
} else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
||||||
|
// User is at Top of Build Log
|
||||||
|
|
||||||
|
this.$scrollTopBtn.hide();
|
||||||
|
this.$scrollBottomBtn.show();
|
||||||
|
|
||||||
|
this.$autoScrollContainer.hide();
|
||||||
|
this.$autoScrollStatusText.removeClass('animate');
|
||||||
|
} else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) ||
|
||||||
|
(this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) {
|
||||||
|
// User is at Bottom of Build Log
|
||||||
|
|
||||||
|
this.$scrollTopBtn.show();
|
||||||
|
this.$scrollBottomBtn.hide();
|
||||||
|
|
||||||
|
// Show and Reposition Autoscroll Status Indicator
|
||||||
|
this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
|
||||||
|
this.$autoScrollStatusText.addClass('animate');
|
||||||
|
} else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
||||||
|
// Build Log height is small
|
||||||
|
|
||||||
|
this.$scrollTopBtn.hide();
|
||||||
|
this.$scrollBottomBtn.hide();
|
||||||
|
|
||||||
|
// Hide Autoscroll Status Indicator
|
||||||
|
this.$autoScrollContainer.hide();
|
||||||
|
this.$autoScrollStatusText.removeClass('animate');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.buildStatus === "running" || this.buildStatus === "pending") {
|
||||||
|
// Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise.
|
||||||
|
this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)) ? 'enabled' : 'disabled');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.shouldHideSidebarForViewport = function() {
|
Build.prototype.shouldHideSidebarForViewport = function() {
|
||||||
|
|
|
@ -138,14 +138,8 @@
|
||||||
new MergedButtons();
|
new MergedButtons();
|
||||||
break;
|
break;
|
||||||
case 'projects:merge_requests:commits':
|
case 'projects:merge_requests:commits':
|
||||||
case 'projects:merge_requests:builds':
|
|
||||||
new MergedButtons();
|
new MergedButtons();
|
||||||
break;
|
break;
|
||||||
case 'projects:merge_requests:pipelines':
|
|
||||||
new gl.MiniPipelineGraph({
|
|
||||||
container: '.js-pipeline-table',
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "projects:merge_requests:diffs":
|
case "projects:merge_requests:diffs":
|
||||||
new gl.Diff();
|
new gl.Diff();
|
||||||
new ZenMode();
|
new ZenMode();
|
||||||
|
@ -168,9 +162,6 @@
|
||||||
container: '.js-pipeline-table',
|
container: '.js-pipeline-table',
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'projects:commit:builds':
|
|
||||||
new gl.Pipelines();
|
|
||||||
break;
|
|
||||||
case 'projects:commits:show':
|
case 'projects:commits:show':
|
||||||
case 'projects:activity':
|
case 'projects:activity':
|
||||||
shortcut_handler = new ShortcutsNavigation();
|
shortcut_handler = new ShortcutsNavigation();
|
||||||
|
|
|
@ -74,15 +74,16 @@
|
||||||
// The below is taken from At.js source
|
// The below is taken from At.js source
|
||||||
// Tweaked to commands to start without a space only if char before is a non-word character
|
// Tweaked to commands to start without a space only if char before is a non-word character
|
||||||
// https://github.com/ichord/At.js
|
// https://github.com/ichord/At.js
|
||||||
var _a, _y, regexp, match, atSymbols;
|
var _a, _y, regexp, match, atSymbolsWithBar, atSymbolsWithoutBar;
|
||||||
atSymbols = Object.keys(this.app.controllers).join('|');
|
atSymbolsWithBar = Object.keys(this.app.controllers).join('|');
|
||||||
|
atSymbolsWithoutBar = Object.keys(this.app.controllers).join('');
|
||||||
subtext = subtext.split(' ').pop();
|
subtext = subtext.split(' ').pop();
|
||||||
flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||||
|
|
||||||
_a = decodeURI("%C3%80");
|
_a = decodeURI("%C3%80");
|
||||||
_y = decodeURI("%C3%BF");
|
_y = decodeURI("%C3%BF");
|
||||||
|
|
||||||
regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?![" + atSymbols + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
|
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
|
||||||
|
|
||||||
match = regexp.exec(subtext);
|
match = regexp.exec(subtext);
|
||||||
|
|
||||||
|
@ -112,7 +113,6 @@
|
||||||
return value.path != null ? this.Emoji.template : this.Loading.template;
|
return value.path != null ? this.Emoji.template : this.Loading.template;
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
insertTpl: ':${name}:',
|
insertTpl: ':${name}:',
|
||||||
startWithSpace: false,
|
|
||||||
skipSpecialCharacterTest: true,
|
skipSpecialCharacterTest: true,
|
||||||
data: this.defaultLoadingData,
|
data: this.defaultLoadingData,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
|
@ -129,7 +129,6 @@
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
insertTpl: '${atwho-at}${username}',
|
insertTpl: '${atwho-at}${username}',
|
||||||
searchKey: 'search',
|
searchKey: 'search',
|
||||||
startWithSpace: false,
|
|
||||||
alwaysHighlightFirst: true,
|
alwaysHighlightFirst: true,
|
||||||
skipSpecialCharacterTest: true,
|
skipSpecialCharacterTest: true,
|
||||||
data: this.defaultLoadingData,
|
data: this.defaultLoadingData,
|
||||||
|
@ -172,7 +171,6 @@
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
data: this.defaultLoadingData,
|
data: this.defaultLoadingData,
|
||||||
insertTpl: '${atwho-at}${id}',
|
insertTpl: '${atwho-at}${id}',
|
||||||
startWithSpace: false,
|
|
||||||
callbacks: {
|
callbacks: {
|
||||||
sorter: this.DefaultOptions.sorter,
|
sorter: this.DefaultOptions.sorter,
|
||||||
filter: this.DefaultOptions.filter,
|
filter: this.DefaultOptions.filter,
|
||||||
|
@ -200,7 +198,6 @@
|
||||||
displayTpl: function(value) {
|
displayTpl: function(value) {
|
||||||
return value.title != null ? this.Milestones.template : this.Loading.template;
|
return value.title != null ? this.Milestones.template : this.Loading.template;
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
startWithSpace: false,
|
|
||||||
data: this.defaultLoadingData,
|
data: this.defaultLoadingData,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
matcher: this.DefaultOptions.matcher,
|
matcher: this.DefaultOptions.matcher,
|
||||||
|
@ -225,7 +222,6 @@
|
||||||
at: '!',
|
at: '!',
|
||||||
alias: 'mergerequests',
|
alias: 'mergerequests',
|
||||||
searchKey: 'search',
|
searchKey: 'search',
|
||||||
startWithSpace: false,
|
|
||||||
displayTpl: function(value) {
|
displayTpl: function(value) {
|
||||||
return value.title != null ? this.Issues.template : this.Loading.template;
|
return value.title != null ? this.Issues.template : this.Loading.template;
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
|
@ -259,7 +255,6 @@
|
||||||
return this.isLoading(value) ? this.Loading.template : this.Labels.template;
|
return this.isLoading(value) ? this.Loading.template : this.Labels.template;
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
insertTpl: '${atwho-at}${title}',
|
insertTpl: '${atwho-at}${title}',
|
||||||
startWithSpace: false,
|
|
||||||
callbacks: {
|
callbacks: {
|
||||||
matcher: this.DefaultOptions.matcher,
|
matcher: this.DefaultOptions.matcher,
|
||||||
sorter: this.DefaultOptions.sorter,
|
sorter: this.DefaultOptions.sorter,
|
||||||
|
@ -379,14 +374,7 @@
|
||||||
togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) {
|
togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) {
|
||||||
this.setting.tabSelectsMatch = !isPrevented;
|
this.setting.tabSelectsMatch = !isPrevented;
|
||||||
this.setting.spaceSelectsMatch = !isPrevented;
|
this.setting.spaceSelectsMatch = !isPrevented;
|
||||||
const eventListenerAction = `${isPrevented ? 'add' : 'remove'}EventListener`;
|
|
||||||
this.$inputor[0][eventListenerAction]('keydown', gl.GfmAutoComplete.preventSpaceTabEnter);
|
|
||||||
},
|
},
|
||||||
preventSpaceTabEnter(e) {
|
|
||||||
const key = e.which || e.keyCode;
|
|
||||||
const preventables = [9, 13, 32];
|
|
||||||
if (preventables.indexOf(key) > -1) e.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/* eslint-disable func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */
|
/* eslint-disable no-param-reassign, func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */
|
||||||
/* global Issuable */
|
/* global Issuable */
|
||||||
/* global Turbolinks */
|
/* global Turbolinks */
|
||||||
|
|
||||||
(function() {
|
((global) => {
|
||||||
var issuable_created;
|
var issuable_created;
|
||||||
|
|
||||||
issuable_created = false;
|
issuable_created = false;
|
||||||
|
|
||||||
this.Issuable = {
|
global.Issuable = {
|
||||||
init: function() {
|
init: function() {
|
||||||
Issuable.initTemplates();
|
Issuable.initTemplates();
|
||||||
Issuable.initSearch();
|
Issuable.initSearch();
|
||||||
|
@ -111,7 +111,11 @@
|
||||||
filterResults: (function(_this) {
|
filterResults: (function(_this) {
|
||||||
return function(form) {
|
return function(form) {
|
||||||
var formAction, formData, issuesUrl;
|
var formAction, formData, issuesUrl;
|
||||||
formData = form.serialize();
|
formData = form.serializeArray();
|
||||||
|
formData = formData.filter(function(data) {
|
||||||
|
return data.value !== '';
|
||||||
|
});
|
||||||
|
formData = $.param(formData);
|
||||||
formAction = form.attr('action');
|
formAction = form.attr('action');
|
||||||
issuesUrl = formAction;
|
issuesUrl = formAction;
|
||||||
issuesUrl += "" + (formAction.indexOf('?') < 0 ? '?' : '&');
|
issuesUrl += "" + (formAction.indexOf('?') < 0 ? '?' : '&');
|
||||||
|
@ -184,4 +188,4 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}).call(this);
|
})(window);
|
||||||
|
|
|
@ -93,6 +93,19 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if element scrolled into viewport from above or below
|
||||||
|
// Courtesy http://stackoverflow.com/a/7557433/414749
|
||||||
|
w.gl.utils.isInViewport = function(el) {
|
||||||
|
var rect = el.getBoundingClientRect();
|
||||||
|
|
||||||
|
return (
|
||||||
|
rect.top >= 0 &&
|
||||||
|
rect.left >= 0 &&
|
||||||
|
rect.bottom <= window.innerHeight &&
|
||||||
|
rect.right <= window.innerWidth
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
gl.utils.getPagePath = function() {
|
gl.utils.getPagePath = function() {
|
||||||
return $('body').data('page').split(':')[0];
|
return $('body').data('page').split(':')[0];
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,16 +59,13 @@
|
||||||
|
|
||||||
class MergeRequestTabs {
|
class MergeRequestTabs {
|
||||||
|
|
||||||
constructor({ action, setUrl, buildsLoaded, stubLocation } = {}) {
|
constructor({ action, setUrl, stubLocation } = {}) {
|
||||||
this.diffsLoaded = false;
|
this.diffsLoaded = false;
|
||||||
this.buildsLoaded = false;
|
|
||||||
this.pipelinesLoaded = false;
|
this.pipelinesLoaded = false;
|
||||||
this.commitsLoaded = false;
|
this.commitsLoaded = false;
|
||||||
this.fixedLayoutPref = null;
|
this.fixedLayoutPref = null;
|
||||||
|
|
||||||
this.setUrl = setUrl !== undefined ? setUrl : true;
|
this.setUrl = setUrl !== undefined ? setUrl : true;
|
||||||
this.buildsLoaded = buildsLoaded || false;
|
|
||||||
|
|
||||||
this.setCurrentAction = this.setCurrentAction.bind(this);
|
this.setCurrentAction = this.setCurrentAction.bind(this);
|
||||||
this.tabShown = this.tabShown.bind(this);
|
this.tabShown = this.tabShown.bind(this);
|
||||||
this.showTab = this.showTab.bind(this);
|
this.showTab = this.showTab.bind(this);
|
||||||
|
@ -119,10 +116,6 @@
|
||||||
$.scrollTo('.merge-request-details .merge-request-tabs', {
|
$.scrollTo('.merge-request-details .merge-request-tabs', {
|
||||||
offset: -navBarHeight,
|
offset: -navBarHeight,
|
||||||
});
|
});
|
||||||
} else if (action === 'builds') {
|
|
||||||
this.loadBuilds($target.attr('href'));
|
|
||||||
this.expandView();
|
|
||||||
this.resetViewContainer();
|
|
||||||
} else if (action === 'pipelines') {
|
} else if (action === 'pipelines') {
|
||||||
this.loadPipelines($target.attr('href'));
|
this.loadPipelines($target.attr('href'));
|
||||||
this.expandView();
|
this.expandView();
|
||||||
|
@ -180,8 +173,8 @@
|
||||||
setCurrentAction(action) {
|
setCurrentAction(action) {
|
||||||
this.currentAction = action === 'show' ? 'notes' : action;
|
this.currentAction = action === 'show' ? 'notes' : action;
|
||||||
|
|
||||||
// Remove a trailing '/commits' '/diffs' '/builds' '/pipelines' '/new' '/new/diffs'
|
// Remove a trailing '/commits' '/diffs' '/pipelines' '/new' '/new/diffs'
|
||||||
let newState = location.pathname.replace(/\/(commits|diffs|builds|pipelines|new|new\/diffs)(\.html)?\/?$/, '');
|
let newState = location.pathname.replace(/\/(commits|diffs|pipelines|new|new\/diffs)(\.html)?\/?$/, '');
|
||||||
|
|
||||||
// Append the new action if we're on a tab other than 'notes'
|
// Append the new action if we're on a tab other than 'notes'
|
||||||
if (this.currentAction !== 'notes') {
|
if (this.currentAction !== 'notes') {
|
||||||
|
@ -255,22 +248,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadBuilds(source) {
|
|
||||||
if (this.buildsLoaded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.ajaxGet({
|
|
||||||
url: `${source}.json`,
|
|
||||||
success: (data) => {
|
|
||||||
document.querySelector('div#builds').innerHTML = data.html;
|
|
||||||
gl.utils.localTimeAgo($('.js-timeago', 'div#builds'));
|
|
||||||
this.buildsLoaded = true;
|
|
||||||
new gl.Pipelines();
|
|
||||||
this.scrollToElement('#builds');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadPipelines(source) {
|
loadPipelines(source) {
|
||||||
if (this.pipelinesLoaded) {
|
if (this.pipelinesLoaded) {
|
||||||
return;
|
return;
|
||||||
|
@ -282,6 +259,10 @@
|
||||||
gl.utils.localTimeAgo($('.js-timeago', '#pipelines'));
|
gl.utils.localTimeAgo($('.js-timeago', '#pipelines'));
|
||||||
this.pipelinesLoaded = true;
|
this.pipelinesLoaded = true;
|
||||||
this.scrollToElement('#pipelines');
|
this.scrollToElement('#pipelines');
|
||||||
|
|
||||||
|
new gl.MiniPipelineGraph({
|
||||||
|
container: '.js-pipeline-table',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
|
|
||||||
MergeRequestWidget.prototype.addEventListeners = function() {
|
MergeRequestWidget.prototype.addEventListeners = function() {
|
||||||
var allowedPages;
|
var allowedPages;
|
||||||
allowedPages = ['show', 'commits', 'builds', 'pipelines', 'changes'];
|
allowedPages = ['show', 'commits', 'pipelines', 'changes'];
|
||||||
$(document).on('page:change.merge_request', (function(_this) {
|
$(document).on('page:change.merge_request', (function(_this) {
|
||||||
return function() {
|
return function() {
|
||||||
var page;
|
var page;
|
||||||
|
@ -173,7 +173,6 @@
|
||||||
message = message.replace('{{title}}', data.title);
|
message = message.replace('{{title}}', data.title);
|
||||||
notify(title, message, _this.opts.gitlab_icon, function() {
|
notify(title, message, _this.opts.gitlab_icon, function() {
|
||||||
this.close();
|
this.close();
|
||||||
return Turbolinks.visit(_this.opts.builds_path);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* global merge_request_widget */
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
$(() => {
|
||||||
|
/* TODO: This needs a better home, or should be refactored. It was previously contained
|
||||||
|
* in a script tag in app/views/projects/merge_requests/widget/open/_accept.html.haml,
|
||||||
|
* but Vue chokes on script tags and prevents their execution. So it was moved here
|
||||||
|
* temporarily.
|
||||||
|
* */
|
||||||
|
|
||||||
|
if ($('.accept-mr-form').length) {
|
||||||
|
$('.accept-mr-form').on('ajax:send', () => {
|
||||||
|
$('.accept-mr-form :input').disable();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.accept_merge_request').on('click', () => {
|
||||||
|
$('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.merge_when_build_succeeds').on('click', () => {
|
||||||
|
$('#merge_when_build_succeeds').val('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.js-merge-dropdown a').on('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).closest('form').submit();
|
||||||
|
});
|
||||||
|
} else if ($('.rebase-in-progress').length) {
|
||||||
|
merge_request_widget.rebaseInProgress();
|
||||||
|
} else if ($('.rebase-mr-form').length) {
|
||||||
|
$('.rebase-mr-form').on('ajax:send', () => {
|
||||||
|
$('.rebase-mr-form :input').disable();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.js-rebase-button').on('click', () => {
|
||||||
|
$('.js-rebase-button').html("<i class='fa fa-spinner fa-spin'></i> Rebase in progress");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
merge_request_widget.getMergeStatus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
|
@ -9,6 +9,7 @@
|
||||||
@import "framework/asciidoctor.scss";
|
@import "framework/asciidoctor.scss";
|
||||||
@import "framework/blocks.scss";
|
@import "framework/blocks.scss";
|
||||||
@import "framework/buttons.scss";
|
@import "framework/buttons.scss";
|
||||||
|
@import "framework/badges.scss";
|
||||||
@import "framework/calendar.scss";
|
@import "framework/calendar.scss";
|
||||||
@import "framework/callout.scss";
|
@import "framework/callout.scss";
|
||||||
@import "framework/common.scss";
|
@import "framework/common.scss";
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
.badge {
|
||||||
|
font-weight: normal;
|
||||||
|
background-color: $badge-bg;
|
||||||
|
color: $badge-color;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-dark {
|
||||||
|
background-color: $badge-bg-dark;
|
||||||
|
color: $badge-color-dark;
|
||||||
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
|
|
||||||
&.diff-collapsed {
|
&.diff-collapsed {
|
||||||
|
|
|
@ -76,13 +76,6 @@
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
|
||||||
font-weight: normal;
|
|
||||||
background-color: $nav-badge-bg;
|
|
||||||
color: $gl-gray-light;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.sub-nav {
|
&.sub-nav {
|
||||||
|
@ -434,4 +427,4 @@
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@
|
||||||
@import "bootstrap/labels";
|
@import "bootstrap/labels";
|
||||||
@import "bootstrap/badges";
|
@import "bootstrap/badges";
|
||||||
@import "bootstrap/alerts";
|
@import "bootstrap/alerts";
|
||||||
// @import "bootstrap/progress-bars";
|
@import "bootstrap/progress-bars";
|
||||||
@import "bootstrap/list-group";
|
@import "bootstrap/list-group";
|
||||||
@import "bootstrap/wells";
|
@import "bootstrap/wells";
|
||||||
@import "bootstrap/close";
|
@import "bootstrap/close";
|
||||||
|
|
|
@ -134,8 +134,8 @@ $md-area-border: #ddd;
|
||||||
/*
|
/*
|
||||||
* Code
|
* Code
|
||||||
*/
|
*/
|
||||||
$code_font_size: 13px;
|
$code_font_size: 12px;
|
||||||
$code_line_height: 1.5;
|
$code_line_height: 1.6;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Padding
|
* Padding
|
||||||
|
@ -279,6 +279,14 @@ $dropdown-toggle-active-border-color: darken($border-color, 14%);
|
||||||
$btn-active-gray: #ececec;
|
$btn-active-gray: #ececec;
|
||||||
$btn-active-gray-light: e4e7ed;
|
$btn-active-gray-light: e4e7ed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Badges
|
||||||
|
*/
|
||||||
|
$badge-bg: #f3f3f3;
|
||||||
|
$badge-bg-dark: #eee;
|
||||||
|
$badge-color: #929292;
|
||||||
|
$badge-color-dark: #8f8f8f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Award emoji
|
* Award emoji
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,34 @@
|
||||||
|
@keyframes fade-out-status {
|
||||||
|
0%, 50% { opacity: 1; }
|
||||||
|
100% { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blinking-dots {
|
||||||
|
0% {
|
||||||
|
background-color: rgba($white-light, 1);
|
||||||
|
box-shadow: 12px 0 0 0 rgba($white-light,0.2),
|
||||||
|
24px 0 0 0 rgba($white-light,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
25% {
|
||||||
|
background-color: rgba($white-light, 0.4);
|
||||||
|
box-shadow: 12px 0 0 0 rgba($white-light,2),
|
||||||
|
24px 0 0 0 rgba($white-light,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
background-color: rgba($white-light, 0.4);
|
||||||
|
box-shadow: 12px 0 0 0 rgba($white-light,0.2),
|
||||||
|
24px 0 0 0 rgba($white-light,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
background-color: rgba($white-light, 1);
|
||||||
|
box-shadow: 12px 0 0 0 rgba($white-light,0.2),
|
||||||
|
24px 0 0 0 rgba($white-light,0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.build-page {
|
.build-page {
|
||||||
pre.trace {
|
pre.trace {
|
||||||
background: $builds-trace-bg;
|
background: $builds-trace-bg;
|
||||||
|
@ -14,33 +45,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll-controls {
|
|
||||||
.scroll-step {
|
|
||||||
width: 31px;
|
|
||||||
margin: 0 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.affix-bottom {
|
|
||||||
position: absolute;
|
|
||||||
right: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.affix {
|
|
||||||
right: 25px;
|
|
||||||
bottom: 15px;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.sidebar-expanded {
|
|
||||||
right: #{$gutter_width + ($gl-padding * 2)};
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.environment-information {
|
.environment-information {
|
||||||
background-color: $gray-light;
|
background-color: $gray-light;
|
||||||
border: 1px solid $border-color;
|
border: 1px solid $border-color;
|
||||||
|
@ -55,6 +59,87 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scroll-controls {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.scroll-step {
|
||||||
|
width: 31px;
|
||||||
|
margin: 0 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-link,
|
||||||
|
.autoscroll-container {
|
||||||
|
right: 25px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-link {
|
||||||
|
position: fixed;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&.scroll-top .gitlab-icon-scroll-up-hover,
|
||||||
|
&.scroll-top:hover .gitlab-icon-scroll-up,
|
||||||
|
&.scroll-bottom .gitlab-icon-scroll-down-hover,
|
||||||
|
&.scroll-bottom:hover .gitlab-icon-scroll-down {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scroll-top:hover .gitlab-icon-scroll-up-hover,
|
||||||
|
&.scroll-bottom:hover .gitlab-icon-scroll-down-hover {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scroll-top {
|
||||||
|
top: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scroll-bottom {
|
||||||
|
bottom: -2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.autoscroll-container {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sidebar-expanded {
|
||||||
|
|
||||||
|
.scroll-link,
|
||||||
|
.autoscroll-container {
|
||||||
|
right: ($gutter_width + ($gl-padding * 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-message {
|
||||||
|
display: inline-block;
|
||||||
|
color: $white-light;
|
||||||
|
|
||||||
|
.status-icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
height: 33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
float: left;
|
||||||
|
opacity: 0;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 1.8;
|
||||||
|
transition: opacity 1s ease-out;
|
||||||
|
|
||||||
|
&.animate {
|
||||||
|
animation: fade-out-status 2s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .status-text {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.build-header {
|
.build-header {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -109,6 +194,15 @@
|
||||||
.bash {
|
.bash {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.build-loader-animation {
|
||||||
|
position: relative;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
margin: auto auto 12px 2px;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: blinking-dots 1s linear infinite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-sidebar.build-sidebar {
|
.right-sidebar.build-sidebar {
|
||||||
|
@ -248,6 +342,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.build-sidebar {
|
||||||
|
.container-fluid.container-limited {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.build-detail-row {
|
.build-detail-row {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
|
|
@ -121,13 +121,6 @@
|
||||||
|
|
||||||
.folder-name {
|
.folder-name {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.badge {
|
|
||||||
font-weight: normal;
|
|
||||||
background-color: $gray-darker;
|
|
||||||
color: $gl-gray-light;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,4 +135,4 @@
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -434,6 +434,7 @@
|
||||||
.issuable-meta {
|
.issuable-meta {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.js-issuable-selector-wrap {
|
.js-issuable-selector-wrap {
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
padding: 8px 9px 9px;
|
padding: 8px 9px 9px $gl-padding;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,14 @@
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
float: left;
|
float: left;
|
||||||
|
|
||||||
|
.btn-success.dropdown-toggle .fa {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success.dropdown-toggle:disabled {
|
||||||
|
background-color: $gl-success;
|
||||||
|
}
|
||||||
|
|
||||||
.accept_merge_request {
|
.accept_merge_request {
|
||||||
&.ci-pending,
|
&.ci-pending,
|
||||||
&.ci-running {
|
&.ci-running {
|
||||||
|
@ -96,7 +104,7 @@
|
||||||
.mr-widget-body {
|
.mr-widget-body {
|
||||||
h4 {
|
h4 {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 17px;
|
font-size: 16px;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
color: $gl-gray-dark;
|
color: $gl-gray-dark;
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.issuable-row {
|
.issuable-row {
|
||||||
.color-label {
|
|
||||||
border-radius: 2px;
|
|
||||||
padding: 3px !important;
|
|
||||||
margin-right: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span a {
|
span a {
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
|
@ -448,11 +448,6 @@ ul.notes {
|
||||||
border-radius: $border-radius-base;
|
border-radius: $border-radius-base;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diff-file .note .note-actions {
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Line note button on the side of diffs
|
* Line note button on the side of diffs
|
||||||
|
@ -586,3 +581,19 @@ ul.notes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge request notes in diffs
|
||||||
|
.diff-file {
|
||||||
|
|
||||||
|
// Diff is side by side
|
||||||
|
.notes_content.parallel .note-header .note-headline-light {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff is inline
|
||||||
|
.notes_content .note-header .note-headline-light {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -63,6 +63,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-list.pipelines .table-holder {
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
.pipeline-holder {
|
.pipeline-holder {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
@ -91,6 +95,10 @@
|
||||||
td {
|
td {
|
||||||
padding: 10px 8px;
|
padding: 10px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.commit-link {
|
||||||
|
padding: 9px 8px 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody {
|
tbody {
|
||||||
|
@ -203,7 +211,7 @@
|
||||||
width: 8px;
|
width: 8px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -7px;
|
right: -7px;
|
||||||
bottom: 9px;
|
top: 10px;
|
||||||
border-bottom: 2px solid $border-color;
|
border-bottom: 2px solid $border-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,15 +517,10 @@
|
||||||
|
|
||||||
> .ci-action-icon-container {
|
> .ci-action-icon-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 4px;
|
right: 5px;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ci-status-icon {
|
|
||||||
position: relative;
|
|
||||||
top: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-status-icon svg {
|
.ci-status-icon svg {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
@ -604,6 +607,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grouped-pipeline-dropdown {
|
||||||
|
.dropdown-build {
|
||||||
|
.build-content {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $stage-hover-bg;
|
||||||
|
color: $gl-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-action-icon-container {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-counter-badge {
|
.dropdown-counter-badge {
|
||||||
|
@ -614,9 +638,11 @@
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.grouped-pipeline-dropdown {
|
.grouped-pipeline-dropdown {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 191px;
|
width: 191px;
|
||||||
|
min-width: 191px;
|
||||||
left: auto;
|
left: auto;
|
||||||
right: -195px;
|
right: -195px;
|
||||||
top: -4px;
|
top: -4px;
|
||||||
|
@ -624,28 +650,55 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
.dropdown-build {
|
||||||
background-color: $stage-hover-bg;
|
.build-content {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $stage-hover-bg;
|
||||||
|
color: $gl-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-action-icon-container {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 3px;
|
||||||
|
right: 7px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
max-height: 245px;
|
max-height: 245px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin: 5px 0;
|
margin: 3px 0;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
padding-top: 2px;
|
margin: 4px 8px 4px 9px;
|
||||||
margin: 0 5px;
|
padding: 0;
|
||||||
padding-left: 0;
|
line-height: 1.1;
|
||||||
padding-bottom: 0;
|
position: relative;
|
||||||
margin-bottom: 0;
|
|
||||||
line-height: 1.2;
|
.ci-action-icon-container:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-status-icon {
|
||||||
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pipeline-graph .dropdown-build .ci-status-icon svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.ci-status-text {
|
.ci-status-text {
|
||||||
max-width: 110px;
|
max-width: 110px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -654,7 +707,7 @@
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-weight: 100;
|
font-weight: 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action Icons
|
// Action Icons
|
||||||
|
@ -690,11 +743,15 @@
|
||||||
.dropdown-build {
|
.dropdown-build {
|
||||||
color: $gl-text-color-light;
|
color: $gl-text-color-light;
|
||||||
|
|
||||||
|
.build-content {
|
||||||
|
padding: 4px 7px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.ci-action-icon-container {
|
.ci-action-icon-container {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
float: right;
|
float: right;
|
||||||
margin-top: 4px;
|
margin-top: 3px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -704,16 +761,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $stage-hover-bg;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: $gl-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-action-icon-container {
|
.ci-action-icon-container {
|
||||||
i {
|
i {
|
||||||
width: 25px;
|
width: 24px;
|
||||||
height: 25px;
|
height: 24px;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
top: 1px;
|
top: 1px;
|
||||||
|
@ -743,11 +794,76 @@
|
||||||
.mini-pipeline-graph {
|
.mini-pipeline-graph {
|
||||||
.builds-dropdown {
|
.builds-dropdown {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: $gl-text-color-light;
|
color: $gl-text-color-light;
|
||||||
border: none;
|
border: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:hover {
|
||||||
|
outline: none;
|
||||||
|
margin-right: -8px;
|
||||||
|
|
||||||
|
.ci-status-icon {
|
||||||
|
width: 32px;
|
||||||
|
padding: 0 8px 0 0;
|
||||||
|
transition: width 0.1s cubic-bezier(0.25, 0, 1, 1);
|
||||||
|
|
||||||
|
+ .dropdown-caret {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
.ci-status-icon-success {
|
||||||
|
background-color: rgba($gl-success, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-status-icon-failed {
|
||||||
|
background-color: rgba($gl-danger, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-status-icon-pending,
|
||||||
|
.ci-status-icon-success_with_warnings {
|
||||||
|
background-color: rgba($gl-warning, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-status-icon-running {
|
||||||
|
background-color: rgba($blue-normal, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-status-icon-canceled,
|
||||||
|
.ci-status-icon-disabled,
|
||||||
|
.ci-status-icon-not-found {
|
||||||
|
background-color: rgba($gl-gray, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ci-status-icon-created,
|
||||||
|
.ci-status-icon-skipped {
|
||||||
|
background-color: rgba($gray-darkest, .1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-pipeline-graph-icon-container {
|
||||||
|
.dropdown-caret {
|
||||||
|
font-size: 11px;
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
left: 20px;
|
||||||
|
margin-right: -6px;
|
||||||
|
z-index: 2;
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
transition: visibility 0.1s, opacity 0.1s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-build .build-content {
|
||||||
|
padding: 3px 7px 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.builds-dropdown-loading {
|
.builds-dropdown-loading {
|
||||||
|
@ -798,89 +914,26 @@
|
||||||
.mini-pipeline-graph-icon-container .ci-status-icon {
|
.mini-pipeline-graph-icon-container .ci-status-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-radius: 20px;
|
border-radius: 22px;
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
width: 20px;
|
width: 22px;
|
||||||
height: 20px;
|
height: 22px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
transition: all 0.2s cubic-bezier(0.25, 0, 1, 1);
|
transition: all 0.1s cubic-bezier(0.25, 0, 1, 1);
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
top: -1px;
|
top: -1px;
|
||||||
|
left: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.builds-dropdown {
|
.stage-cell .mini-pipeline-graph-icon-container .ci-status-icon svg {
|
||||||
&:focus {
|
width: 22px;
|
||||||
outline: none;
|
height: 22px;
|
||||||
margin-right: -8px;
|
|
||||||
|
|
||||||
.ci-status-icon {
|
|
||||||
width: 28px;
|
|
||||||
padding: 0 8px 0 0;
|
|
||||||
transition: width 0.2s cubic-bezier(0.25, 0, 1, 1);
|
|
||||||
|
|
||||||
+ .dropdown-caret {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
.ci-status-icon-success {
|
|
||||||
background-color: rgba($gl-success, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-status-icon-failed {
|
|
||||||
background-color: rgba($gl-danger, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-status-icon-pending,
|
|
||||||
.ci-status-icon-success_with_warnings {
|
|
||||||
background-color: rgba($gl-warning, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-status-icon-running {
|
|
||||||
background-color: rgba($blue-normal, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-status-icon-canceled,
|
|
||||||
.ci-status-icon-disabled,
|
|
||||||
.ci-status-icon-not-found {
|
|
||||||
background-color: rgba($gl-gray, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ci-status-icon-created,
|
|
||||||
.ci-status-icon-skipped {
|
|
||||||
background-color: rgba($gray-darkest, .1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mini-pipeline-graph-icon-container {
|
|
||||||
.ci-status-icon:hover,
|
|
||||||
.ci-status-icon:focus {
|
|
||||||
width: 28px;
|
|
||||||
padding: 0 8px 0 0;
|
|
||||||
|
|
||||||
+ .dropdown-caret {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-caret {
|
|
||||||
font-size: 11px;
|
|
||||||
position: relative;
|
|
||||||
top: 3px;
|
|
||||||
left: -11px;
|
|
||||||
margin-right: -6px;
|
|
||||||
display: none;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.terminal-icon {
|
.terminal-icon {
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -880,3 +880,23 @@ pre.light-well {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.services-installation-info .row {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-installation {
|
||||||
|
padding: 32px;
|
||||||
|
margin: 32px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: $white-light;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 32px 0;
|
||||||
|
border-color: $border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
.ci-status {
|
.ci-status {
|
||||||
padding: 2px 7px;
|
padding: 2px 7px 4px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
border: 1px solid $gray-darker;
|
border: 1px solid $gray-darker;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
|
@ -82,6 +82,8 @@ class GroupsController < Groups::ApplicationController
|
||||||
if Groups::UpdateService.new(@group, current_user, group_params).execute
|
if Groups::UpdateService.new(@group, current_user, group_params).execute
|
||||||
redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated."
|
redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated."
|
||||||
else
|
else
|
||||||
|
@group.reset_path!
|
||||||
|
|
||||||
render action: "edit"
|
render action: "edit"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,13 +8,11 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
|
|
||||||
# Authorize
|
# Authorize
|
||||||
before_action :require_non_empty_project
|
before_action :require_non_empty_project
|
||||||
before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds]
|
before_action :authorize_download_code!
|
||||||
before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
|
|
||||||
before_action :authorize_read_pipeline!, only: [:pipelines]
|
before_action :authorize_read_pipeline!, only: [:pipelines]
|
||||||
before_action :authorize_read_commit_status!, only: [:builds]
|
|
||||||
before_action :commit
|
before_action :commit
|
||||||
before_action :define_commit_vars, only: [:show, :diff_for_path, :builds, :pipelines]
|
before_action :define_commit_vars, only: [:show, :diff_for_path, :pipelines]
|
||||||
before_action :define_status_vars, only: [:show, :builds, :pipelines]
|
before_action :define_status_vars, only: [:show, :pipelines]
|
||||||
before_action :define_note_vars, only: [:show, :diff_for_path]
|
before_action :define_note_vars, only: [:show, :diff_for_path]
|
||||||
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
|
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
|
||||||
|
|
||||||
|
@ -35,25 +33,6 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
def pipelines
|
def pipelines
|
||||||
end
|
end
|
||||||
|
|
||||||
def builds
|
|
||||||
end
|
|
||||||
|
|
||||||
def cancel_builds
|
|
||||||
ci_builds.running_or_pending.each(&:cancel)
|
|
||||||
|
|
||||||
redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
|
|
||||||
end
|
|
||||||
|
|
||||||
def retry_builds
|
|
||||||
ci_builds.latest.failed.each do |build|
|
|
||||||
if build.retryable?
|
|
||||||
Ci::Build.retry(build, current_user)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
|
|
||||||
end
|
|
||||||
|
|
||||||
def branches
|
def branches
|
||||||
@branches = @project.repository.branch_names_contains(commit.id)
|
@branches = @project.repository.branch_names_contains(commit.id)
|
||||||
@tags = @project.repository.tag_names_contains(commit.id)
|
@tags = @project.repository.tag_names_contains(commit.id)
|
||||||
|
@ -98,10 +77,6 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
@noteable = @commit ||= @project.commit(params[:id])
|
@noteable = @commit ||= @project.commit(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def ci_builds
|
|
||||||
@ci_builds ||= Ci::Build.where(pipeline: pipelines)
|
|
||||||
end
|
|
||||||
|
|
||||||
def define_commit_vars
|
def define_commit_vars
|
||||||
return git_not_found! unless commit
|
return git_not_found! unless commit
|
||||||
|
|
||||||
|
@ -133,8 +108,6 @@ class Projects::CommitController < Projects::ApplicationController
|
||||||
|
|
||||||
def define_status_vars
|
def define_status_vars
|
||||||
@ci_pipelines = project.pipelines.where(sha: commit.sha)
|
@ci_pipelines = project.pipelines.where(sha: commit.sha)
|
||||||
@statuses = CommitStatus.where(pipeline: @ci_pipelines).relevant
|
|
||||||
@builds = Ci::Build.where(pipeline: @ci_pipelines).relevant
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_change_commit_vars(mr_source_branch)
|
def assign_change_commit_vars(mr_source_branch)
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
class Projects::MattermostsController < Projects::ApplicationController
|
||||||
|
include TriggersHelper
|
||||||
|
include ActionView::Helpers::AssetUrlHelper
|
||||||
|
|
||||||
|
layout 'project_settings'
|
||||||
|
|
||||||
|
before_action :authorize_admin_project!
|
||||||
|
before_action :service
|
||||||
|
before_action :teams, only: [:new]
|
||||||
|
|
||||||
|
def new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
result, message = @service.configure(current_user, configure_params)
|
||||||
|
|
||||||
|
if result
|
||||||
|
flash[:notice] = 'This service is now configured'
|
||||||
|
redirect_to edit_namespace_project_service_path(
|
||||||
|
@project.namespace, @project, service)
|
||||||
|
else
|
||||||
|
flash[:alert] = message || 'Failed to configure service'
|
||||||
|
redirect_to new_namespace_project_mattermost_path(
|
||||||
|
@project.namespace, @project)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def configure_params
|
||||||
|
params.require(:mattermost).permit(:trigger, :team_id).merge(
|
||||||
|
url: service_trigger_url(@service),
|
||||||
|
icon_url: asset_url('gitlab_logo.png'))
|
||||||
|
end
|
||||||
|
|
||||||
|
def teams
|
||||||
|
@teams ||= @service.list_teams(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def service
|
||||||
|
@service ||= @project.find_or_initialize_service('mattermost_slash_commands')
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,10 +9,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||||
|
|
||||||
before_action :module_enabled
|
before_action :module_enabled
|
||||||
before_action :merge_request, only: [
|
before_action :merge_request, only: [
|
||||||
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines, :merge, :merge_check,
|
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :pipelines, :merge, :merge_check,
|
||||||
:ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
|
:ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
|
||||||
]
|
]
|
||||||
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines]
|
before_action :validates_merge_request, only: [:show, :diffs, :commits, :pipelines]
|
||||||
before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines]
|
before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines]
|
||||||
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
|
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
|
||||||
before_action :define_commit_vars, only: [:diffs]
|
before_action :define_commit_vars, only: [:diffs]
|
||||||
|
@ -201,17 +201,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def builds
|
|
||||||
respond_to do |format|
|
|
||||||
format.html do
|
|
||||||
define_discussion_vars
|
|
||||||
|
|
||||||
render 'show'
|
|
||||||
end
|
|
||||||
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def pipelines
|
def pipelines
|
||||||
@pipelines = @merge_request.all_pipelines
|
@pipelines = @merge_request.all_pipelines
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module AuthHelper
|
module AuthHelper
|
||||||
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2).freeze
|
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq).freeze
|
||||||
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
|
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
|
||||||
|
|
||||||
def ldap_enabled?
|
def ldap_enabled?
|
||||||
|
|
|
@ -188,7 +188,7 @@ module BlobHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def gitlab_ci_ymls
|
def gitlab_ci_ymls
|
||||||
@gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names
|
@gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names(params[:context])
|
||||||
end
|
end
|
||||||
|
|
||||||
def dockerfile_names
|
def dockerfile_names
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module CiStatusHelper
|
module CiStatusHelper
|
||||||
def ci_status_path(pipeline)
|
def ci_status_path(pipeline)
|
||||||
project = pipeline.project
|
project = pipeline.project
|
||||||
builds_namespace_project_commit_path(project.namespace, project, pipeline.sha)
|
namespace_project_pipeline_path(project.namespace, project, pipeline)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Is used by Commit and Merge Request Widget
|
# Is used by Commit and Merge Request Widget
|
||||||
|
|
|
@ -96,8 +96,8 @@ module IssuablesHelper
|
||||||
|
|
||||||
if issuable.tasks?
|
if issuable.tasks?
|
||||||
output << " ".html_safe
|
output << " ".html_safe
|
||||||
output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs")
|
output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs hidden-sm")
|
||||||
output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-sm hidden-md hidden-lg")
|
output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-md hidden-lg")
|
||||||
end
|
end
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
module MattermostHelper
|
||||||
|
def mattermost_teams_options(teams)
|
||||||
|
teams_options = teams.map do |id, options|
|
||||||
|
[options['display_name'] || options['name'], id]
|
||||||
|
end
|
||||||
|
|
||||||
|
teams_options.compact.unshift(['Select team...', '0'])
|
||||||
|
end
|
||||||
|
end
|
|
@ -280,13 +280,15 @@ module ProjectsHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_special_file_path(project, file_name:, commit_message: nil)
|
def add_special_file_path(project, file_name:, commit_message: nil, target_branch: nil, context: nil)
|
||||||
namespace_project_new_blob_path(
|
namespace_project_new_blob_path(
|
||||||
project.namespace,
|
project.namespace,
|
||||||
project,
|
project,
|
||||||
project.default_branch || 'master',
|
project.default_branch || 'master',
|
||||||
file_name: file_name,
|
file_name: file_name,
|
||||||
commit_message: commit_message || "Add #{file_name.downcase}"
|
commit_message: commit_message || "Add #{file_name.downcase}",
|
||||||
|
target_branch: target_branch,
|
||||||
|
context: context
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ module TodosHelper
|
||||||
else
|
else
|
||||||
path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target]
|
path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target]
|
||||||
|
|
||||||
path.unshift(:builds) if todo.build_failed?
|
path.unshift(:pipelines) if todo.build_failed?
|
||||||
|
|
||||||
polymorphic_path(path, anchor: anchor)
|
polymorphic_path(path, anchor: anchor)
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,11 +93,8 @@ module Ci
|
||||||
.select("max(#{quoted_table_name}.id)")
|
.select("max(#{quoted_table_name}.id)")
|
||||||
.group(:ref, :sha)
|
.group(:ref, :sha)
|
||||||
|
|
||||||
if ref
|
relation = ref ? where(ref: ref) : self
|
||||||
where(id: max_id, ref: ref)
|
relation.where(id: max_id).order(id: :desc)
|
||||||
else
|
|
||||||
where(id: max_id)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.latest_status(ref = nil)
|
def self.latest_status(ref = nil)
|
||||||
|
|
|
@ -98,7 +98,7 @@ class Namespace < ActiveRecord::Base
|
||||||
|
|
||||||
def move_dir
|
def move_dir
|
||||||
if any_project_has_container_registry_tags?
|
if any_project_has_container_registry_tags?
|
||||||
raise Exception.new('Namespace cannot be moved, because at least one project has tags in container registry')
|
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Move the namespace directory in all storages paths used by member projects
|
# Move the namespace directory in all storages paths used by member projects
|
||||||
|
@ -111,7 +111,7 @@ class Namespace < ActiveRecord::Base
|
||||||
|
|
||||||
# if we cannot move namespace directory we should rollback
|
# if we cannot move namespace directory we should rollback
|
||||||
# db changes in order to prevent out of sync between db and fs
|
# db changes in order to prevent out of sync between db and fs
|
||||||
raise Exception.new('namespace directory cannot be moved')
|
raise Gitlab::UpdatePathError.new('namespace directory cannot be moved')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -418,7 +418,7 @@ class Project < ActiveRecord::Base
|
||||||
repository.commit(ref)
|
repository.commit(ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ref can't be HEAD, can only be branch/tag name or SHA
|
# ref can't be HEAD or SHA, can only be branch/tag name
|
||||||
def latest_successful_builds_for(ref = default_branch)
|
def latest_successful_builds_for(ref = default_branch)
|
||||||
latest_pipeline = pipelines.latest_successful_for(ref)
|
latest_pipeline = pipelines.latest_successful_for(ref)
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,13 @@ class ChatNotificationService < Service
|
||||||
|
|
||||||
return false unless message
|
return false unless message
|
||||||
|
|
||||||
opt = {}
|
channel_name = get_channel_field(object_kind).presence || channel
|
||||||
|
|
||||||
opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel
|
opts = {}
|
||||||
opt[:username] = username if username
|
opts[:channel] = channel_name if channel_name
|
||||||
notifier = Slack::Notifier.new(webhook, opt)
|
opts[:username] = username if username
|
||||||
|
|
||||||
|
notifier = Slack::Notifier.new(webhook, opts)
|
||||||
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
|
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -71,7 +73,7 @@ class ChatNotificationService < Service
|
||||||
fields.reject { |field| field[:name].end_with?('channel') }
|
fields.reject { |field| field[:name].end_with?('channel') }
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_channel
|
def default_channel_placeholder
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -103,7 +105,7 @@ class ChatNotificationService < Service
|
||||||
|
|
||||||
def build_event_channels
|
def build_event_channels
|
||||||
supported_events.reduce([]) do |channels, event|
|
supported_events.reduce([]) do |channels, event|
|
||||||
channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel }
|
channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel_placeholder }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ class MattermostService < ChatNotificationService
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_channel
|
def default_channel_placeholder
|
||||||
"#town-square"
|
"#town-square"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,4 +18,34 @@ class MattermostSlashCommandsService < ChatSlashCommandsService
|
||||||
def to_param
|
def to_param
|
||||||
'mattermost_slash_commands'
|
'mattermost_slash_commands'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def configure(user, params)
|
||||||
|
token = Mattermost::Command.new(user).
|
||||||
|
create(command(params))
|
||||||
|
|
||||||
|
update(active: true, token: token) if token
|
||||||
|
rescue Mattermost::Error => e
|
||||||
|
[false, e.message]
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_teams(user)
|
||||||
|
Mattermost::Team.new(user).all
|
||||||
|
rescue Mattermost::Error => e
|
||||||
|
[[], e.message]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def command(params)
|
||||||
|
pretty_project_name = project.name_with_namespace
|
||||||
|
|
||||||
|
params.merge(
|
||||||
|
auto_complete: true,
|
||||||
|
auto_complete_desc: "Perform common operations on: #{pretty_project_name}",
|
||||||
|
auto_complete_hint: '[help]',
|
||||||
|
description: "Perform common operations on: #{pretty_project_name}",
|
||||||
|
display_name: "GitLab / #{pretty_project_name}",
|
||||||
|
method: 'P',
|
||||||
|
username: 'GitLab')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,7 @@ class SlackService < ChatNotificationService
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_channel
|
def default_channel_placeholder
|
||||||
"#general"
|
"#general"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ class SlackSlashCommandsService < ChatSlashCommandsService
|
||||||
def trigger(params)
|
def trigger(params)
|
||||||
# Format messages to be Slack-compatible
|
# Format messages to be Slack-compatible
|
||||||
super.tap do |result|
|
super.tap do |result|
|
||||||
result[:text] = format(result[:text])
|
result[:text] = format(result[:text]) if result.is_a?(Hash)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -654,11 +654,19 @@ class Repository
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_commit_for_path(sha, path)
|
def last_commit_for_path(sha, path)
|
||||||
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
|
sha = last_commit_id_for_path(sha, path)
|
||||||
sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
|
|
||||||
commit(sha)
|
commit(sha)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def last_commit_id_for_path(sha, path)
|
||||||
|
key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}"
|
||||||
|
|
||||||
|
cache.fetch(key) do
|
||||||
|
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
|
||||||
|
Gitlab::Popen.popen(args, path_to_repo).first.strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def next_branch(name, opts = {})
|
def next_branch(name, opts = {})
|
||||||
branch_ids = self.branch_names.map do |n|
|
branch_ids = self.branch_names.map do |n|
|
||||||
next 1 if n == name
|
next 1 if n == name
|
||||||
|
|
|
@ -3,6 +3,9 @@ class GitPushService < BaseService
|
||||||
include Gitlab::CurrentSettings
|
include Gitlab::CurrentSettings
|
||||||
include Gitlab::Access
|
include Gitlab::Access
|
||||||
|
|
||||||
|
# The N most recent commits to process in a single push payload.
|
||||||
|
PROCESS_COMMIT_LIMIT = 100
|
||||||
|
|
||||||
# This method will be called after each git update
|
# This method will be called after each git update
|
||||||
# and only if the provided user and project are present in GitLab.
|
# and only if the provided user and project are present in GitLab.
|
||||||
#
|
#
|
||||||
|
@ -77,6 +80,16 @@ class GitPushService < BaseService
|
||||||
ProjectCacheWorker.perform_async(@project.id, types)
|
ProjectCacheWorker.perform_async(@project.id, types)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Schedules processing of commit messages.
|
||||||
|
def process_commit_messages
|
||||||
|
default = is_default_branch?
|
||||||
|
|
||||||
|
push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
|
||||||
|
ProcessCommitWorker.
|
||||||
|
perform_async(project.id, current_user.id, commit.to_hash, default)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def execute_related_hooks
|
def execute_related_hooks
|
||||||
|
@ -128,17 +141,6 @@ class GitPushService < BaseService
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched,
|
|
||||||
# close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables.
|
|
||||||
def process_commit_messages
|
|
||||||
default = is_default_branch?
|
|
||||||
|
|
||||||
@push_commits.each do |commit|
|
|
||||||
ProcessCommitWorker.
|
|
||||||
perform_async(project.id, current_user.id, commit.to_hash, default)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_push_data
|
def build_push_data
|
||||||
@push_data ||= Gitlab::DataBuilder::Push.build(
|
@push_data ||= Gitlab::DataBuilder::Push.build(
|
||||||
@project,
|
@project,
|
||||||
|
|
|
@ -14,7 +14,13 @@ module Groups
|
||||||
|
|
||||||
group.assign_attributes(params)
|
group.assign_attributes(params)
|
||||||
|
|
||||||
group.save
|
begin
|
||||||
|
group.save
|
||||||
|
rescue Gitlab::UpdatePathError => e
|
||||||
|
group.errors.add(:base, e.message)
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,8 @@ class ProjectPathValidator < ActiveModel::EachValidator
|
||||||
# without tree as reserved name routing can match 'group/project' as group name,
|
# without tree as reserved name routing can match 'group/project' as group name,
|
||||||
# 'tree' as project name and 'deploy_keys' as route.
|
# 'tree' as project name and 'deploy_keys' as route.
|
||||||
#
|
#
|
||||||
RESERVED = (NamespaceValidator::RESERVED +
|
RESERVED = (NamespaceValidator::RESERVED -
|
||||||
|
%w[dashboard help ci admin search notes services] +
|
||||||
%w[tree commits wikis new edit create update logs_tree
|
%w[tree commits wikis new edit create update logs_tree
|
||||||
preview blob blame raw files create_dir find_file]).freeze
|
preview blob blame raw files create_dir find_file]).freeze
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
= link_to admin_abuse_reports_path, title: "Abuse Reports" do
|
= link_to admin_abuse_reports_path, title: "Abuse Reports" do
|
||||||
%span
|
%span
|
||||||
Abuse Reports
|
Abuse Reports
|
||||||
%span.badge.count= number_with_delimiter(AbuseReport.count(:all))
|
%span.badge.badge-dark.count= number_with_delimiter(AbuseReport.count(:all))
|
||||||
|
|
||||||
- if askimet_enabled?
|
- if askimet_enabled?
|
||||||
= nav_link(controller: :spam_logs) do
|
= nav_link(controller: :spam_logs) do
|
||||||
|
|
|
@ -26,13 +26,13 @@
|
||||||
%span
|
%span
|
||||||
Issues
|
Issues
|
||||||
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
|
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
|
||||||
%span.badge.count= number_with_delimiter(issues.count)
|
%span.badge.badge-dark.count= number_with_delimiter(issues.count)
|
||||||
= nav_link(path: 'groups#merge_requests') do
|
= nav_link(path: 'groups#merge_requests') do
|
||||||
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
|
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
|
||||||
%span
|
%span
|
||||||
Merge Requests
|
Merge Requests
|
||||||
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
|
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
|
||||||
%span.badge.count= number_with_delimiter(merge_requests.count)
|
%span.badge.badge-dark.count= number_with_delimiter(merge_requests.count)
|
||||||
= nav_link(controller: [:group_members]) do
|
= nav_link(controller: [:group_members]) do
|
||||||
= link_to group_group_members_path(@group), title: 'Members' do
|
= link_to group_group_members_path(@group), title: 'Members' do
|
||||||
%span
|
%span
|
||||||
|
|
|
@ -61,14 +61,14 @@
|
||||||
%span
|
%span
|
||||||
Issues
|
Issues
|
||||||
- if @project.default_issues_tracker?
|
- if @project.default_issues_tracker?
|
||||||
%span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
%span.badge.badge-dark.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
||||||
|
|
||||||
- if project_nav_tab? :merge_requests
|
- if project_nav_tab? :merge_requests
|
||||||
= nav_link(controller: :merge_requests) do
|
= nav_link(controller: :merge_requests) do
|
||||||
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
|
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
|
||||||
%span
|
%span
|
||||||
Merge Requests
|
Merge Requests
|
||||||
%span.badge.count.merge_counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
%span.badge.badge-dark.count.merge_counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
||||||
|
|
||||||
- if project_nav_tab? :wiki
|
- if project_nav_tab? :wiki
|
||||||
= nav_link(controller: :wikis) do
|
= nav_link(controller: :wikis) do
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
- ref = local_assigns.fetch(:ref)
|
- ref = local_assigns.fetch(:ref)
|
||||||
- status = commit.status(ref)
|
- status = commit.status(ref)
|
||||||
- if status
|
- if status
|
||||||
= link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do
|
= link_to pipelines_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do
|
||||||
= ci_icon_for_status(status)
|
= ci_icon_for_status(status)
|
||||||
= ci_label_for_status(status)
|
= ci_label_for_status(status)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
= link_to pipeline_path(@build.pipeline) do
|
= link_to pipeline_path(@build.pipeline) do
|
||||||
%strong ##{@build.pipeline.id}
|
%strong ##{@build.pipeline.id}
|
||||||
for commit
|
for commit
|
||||||
= link_to ci_status_path(@build.pipeline) do
|
= link_to namespace_project_commit_path(@project.namespace, @project, @build.pipeline.sha) do
|
||||||
%strong= @build.pipeline.short_sha
|
%strong= @build.pipeline.short_sha
|
||||||
from
|
from
|
||||||
= link_to namespace_project_commits_path(@project.namespace, @project, @build.ref) do
|
= link_to namespace_project_commits_path(@project.namespace, @project, @build.ref) do
|
||||||
|
|
|
@ -56,17 +56,22 @@
|
||||||
- else
|
- else
|
||||||
#js-build-scroll.scroll-controls
|
#js-build-scroll.scroll-controls
|
||||||
.scroll-step
|
.scroll-step
|
||||||
= link_to '#build-trace', class: 'btn' do
|
%a{ href: '#up-build-trace', id: 'scroll-top', class: 'scroll-link scroll-top', title: 'Scroll to top' }
|
||||||
%i.fa.fa-angle-up
|
= custom_icon('scroll_up')
|
||||||
= link_to '#down-build-trace', class: 'btn' do
|
= custom_icon('scroll_up_hover_active')
|
||||||
%i.fa.fa-angle-down
|
%a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom' }
|
||||||
|
= custom_icon('scroll_down')
|
||||||
|
= custom_icon('scroll_down_hover_active')
|
||||||
- if @build.active?
|
- if @build.active?
|
||||||
.autoscroll-container
|
.autoscroll-container
|
||||||
%button.btn.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}}
|
%span.status-message#autoscroll-status{ data: { state: 'disabled' } }
|
||||||
Enable autoscroll
|
%span.status-text Autoscroll active
|
||||||
|
%i.status-icon
|
||||||
|
= custom_icon('scroll_down_hover_active')
|
||||||
|
#up-build-trace
|
||||||
%pre.build-trace#build-trace
|
%pre.build-trace#build-trace
|
||||||
%code.bash.js-build-output
|
%code.bash.js-build-output
|
||||||
= icon("refresh spin", class: "js-build-refresh")
|
.build-loader-animation.js-build-refresh
|
||||||
|
|
||||||
#down-build-trace
|
#down-build-trace
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
- @ci_pipelines.each do |pipeline|
|
|
||||||
= render "pipeline", pipeline: pipeline, pipeline_details: true
|
|
|
@ -8,7 +8,3 @@
|
||||||
= link_to pipelines_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
|
= link_to pipelines_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
|
||||||
Pipelines
|
Pipelines
|
||||||
%span.badge= @ci_pipelines.count
|
%span.badge= @ci_pipelines.count
|
||||||
= nav_link(path: 'commit#builds') do
|
|
||||||
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
|
|
||||||
Builds
|
|
||||||
%span.badge= @statuses.count
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
- @no_container = true
|
|
||||||
- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits"
|
|
||||||
= render "projects/commits/head"
|
|
||||||
|
|
||||||
%div{ class: container_class }
|
|
||||||
= render "commit_box"
|
|
||||||
|
|
||||||
= render "ci_menu"
|
|
||||||
= render "builds"
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
%p
|
||||||
|
You aren’t a member of any team on the Mattermost instance at
|
||||||
|
%strong= Gitlab.config.mattermost.host
|
||||||
|
%p
|
||||||
|
To install this service,
|
||||||
|
= link_to "#{Gitlab.config.mattermost.host}/select_team", target: '__blank' do
|
||||||
|
join a team
|
||||||
|
= icon('external-link')
|
||||||
|
and try again.
|
||||||
|
%hr
|
||||||
|
.clearfix
|
||||||
|
= link_to 'Go back', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg pull-right'
|
|
@ -0,0 +1,44 @@
|
||||||
|
%p
|
||||||
|
This service will be installed on the Mattermost instance at
|
||||||
|
%strong= link_to Gitlab.config.mattermost.host, Gitlab.config.mattermost.host
|
||||||
|
%hr
|
||||||
|
= form_for(:mattermost, method: :post, url: namespace_project_mattermost_path(@project.namespace, @project)) do |f|
|
||||||
|
%h4 Team
|
||||||
|
%p
|
||||||
|
= @teams.one? ? 'The team' : 'Select the team'
|
||||||
|
where the slash commands will be used in
|
||||||
|
- selected_id = @teams.keys.first if @teams.one?
|
||||||
|
= f.select(:team_id, mattermost_teams_options(@teams), {}, { class: 'form-control', selected: "#{selected_id}", disabled: @teams.one? })
|
||||||
|
.help-block
|
||||||
|
- if @teams.one?
|
||||||
|
This is the only team where you are an administrator.
|
||||||
|
- else
|
||||||
|
The list shows teams where you are administrator
|
||||||
|
To create a team, ask your Mattermost system administrator.
|
||||||
|
To create a team,
|
||||||
|
= link_to "#{Gitlab.config.mattermost.host}/create_team" do
|
||||||
|
use Mattermost's interface
|
||||||
|
= icon('external-link')
|
||||||
|
%hr
|
||||||
|
%h4 Command trigger word
|
||||||
|
%p Choose the word that will trigger commands
|
||||||
|
= f.text_field(:trigger, value: @project.path, class: 'form-control')
|
||||||
|
.help-block
|
||||||
|
%p
|
||||||
|
Trigger word must be unique, and can't begin with a slash or contain any spaces.
|
||||||
|
Use the word that works best for your team.
|
||||||
|
%p
|
||||||
|
Suggestions:
|
||||||
|
%code= 'gitlab'
|
||||||
|
%code= @project.path # Path contains no spaces, but dashes
|
||||||
|
%code= @project.path_with_namespace
|
||||||
|
%p
|
||||||
|
Reserved:
|
||||||
|
= link_to 'https://docs.mattermost.com/help/messaging/executing-commands.html#built-in-commands', target: '__blank' do
|
||||||
|
see list of built-in slash commands
|
||||||
|
= icon('external-link')
|
||||||
|
%hr
|
||||||
|
.clearfix
|
||||||
|
.pull-right
|
||||||
|
= link_to 'Cancel', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg'
|
||||||
|
= f.submit 'Install', class: 'btn btn-save btn-lg'
|
|
@ -0,0 +1,8 @@
|
||||||
|
.service-installation
|
||||||
|
.inline.pull-right
|
||||||
|
= custom_icon('mattermost_logo', size: 48)
|
||||||
|
%h3 Install Mattermost Command
|
||||||
|
- if @teams.empty?
|
||||||
|
= render 'no_teams'
|
||||||
|
- else
|
||||||
|
= render 'team_selection'
|
|
@ -34,11 +34,6 @@
|
||||||
= link_to url_for(params), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tab'} do
|
= link_to url_for(params), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tab'} do
|
||||||
Pipelines
|
Pipelines
|
||||||
%span.badge= @pipelines.size
|
%span.badge= @pipelines.size
|
||||||
- if @pipeline.present?
|
|
||||||
%li.builds-tab
|
|
||||||
= link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do
|
|
||||||
Builds
|
|
||||||
%span.badge= @statuses_count
|
|
||||||
%li.diffs-tab
|
%li.diffs-tab
|
||||||
= link_to url_for(params.merge(action: 'new_diffs')), data: {target: 'div#diffs', action: 'new/diffs', toggle: 'tab'} do
|
= link_to url_for(params.merge(action: 'new_diffs')), data: {target: 'div#diffs', action: 'new/diffs', toggle: 'tab'} do
|
||||||
Changes
|
Changes
|
||||||
|
@ -49,9 +44,6 @@
|
||||||
= render "projects/merge_requests/show/commits"
|
= render "projects/merge_requests/show/commits"
|
||||||
#diffs.diffs.tab-pane
|
#diffs.diffs.tab-pane
|
||||||
- # This tab is always loaded via AJAX
|
- # This tab is always loaded via AJAX
|
||||||
- if @pipeline.present?
|
|
||||||
#builds.builds.tab-pane
|
|
||||||
= render "projects/merge_requests/show/builds"
|
|
||||||
- if @pipelines.any?
|
- if @pipelines.any?
|
||||||
#pipelines.pipelines.tab-pane
|
#pipelines.pipelines.tab-pane
|
||||||
= render "projects/merge_requests/show/pipelines"
|
= render "projects/merge_requests/show/pipelines"
|
||||||
|
@ -66,6 +58,5 @@
|
||||||
});
|
});
|
||||||
:javascript
|
:javascript
|
||||||
var merge_request = new MergeRequest({
|
var merge_request = new MergeRequest({
|
||||||
action: "#{(@show_changes_tab ? 'new/diffs' : 'new')}",
|
action: "#{(@show_changes_tab ? 'new/diffs' : 'new')}"
|
||||||
buildsLoaded: "#{@pipeline.present? ? 'true' : 'false'}"
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -65,11 +65,6 @@
|
||||||
= link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
|
= link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
|
||||||
Pipelines
|
Pipelines
|
||||||
%span.badge= @pipelines.size
|
%span.badge= @pipelines.size
|
||||||
- if @pipeline.present?
|
|
||||||
%li.builds-tab
|
|
||||||
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#builds', action: 'builds', toggle: 'tab' } do
|
|
||||||
Builds
|
|
||||||
%span.badge= @statuses_count
|
|
||||||
%li.diffs-tab
|
%li.diffs-tab
|
||||||
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do
|
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do
|
||||||
Changes
|
Changes
|
||||||
|
@ -98,8 +93,6 @@
|
||||||
|
|
||||||
#commits.commits.tab-pane
|
#commits.commits.tab-pane
|
||||||
- # This tab is always loaded via AJAX
|
- # This tab is always loaded via AJAX
|
||||||
#builds.builds.tab-pane
|
|
||||||
- # This tab is always loaded via AJAX
|
|
||||||
#pipelines.pipelines.tab-pane
|
#pipelines.pipelines.tab-pane
|
||||||
- # This tab is always loaded via AJAX
|
- # This tab is always loaded via AJAX
|
||||||
#diffs.diffs.tab-pane
|
#diffs.diffs.tab-pane
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
= render "projects/commit/pipeline", pipeline: @pipeline, link_to_commit: true
|
|
|
@ -17,7 +17,7 @@
|
||||||
- # TODO, remove in later versions when services like Jenkins will set CI status via Commit status API
|
- # TODO, remove in later versions when services like Jenkins will set CI status via Commit status API
|
||||||
.mr-widget-heading
|
.mr-widget-heading
|
||||||
- %w[success skipped canceled failed running pending].each do |status|
|
- %w[success skipped canceled failed running pending].each do |status|
|
||||||
.ci_widget{class: "ci-#{status}", style: "display:none"}
|
.ci_widget{class: "ci-#{status} ci-status-icon-#{status}", style: "display:none"}
|
||||||
= ci_icon_for_status(status)
|
= ci_icon_for_status(status)
|
||||||
%span
|
%span
|
||||||
CI build
|
CI build
|
||||||
|
|
|
@ -24,12 +24,10 @@
|
||||||
preparing: "{{status}} build",
|
preparing: "{{status}} build",
|
||||||
normal: "Build {{status}}"
|
normal: "Build {{status}}"
|
||||||
},
|
},
|
||||||
builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
|
|
||||||
pipelines_path: "#{pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
|
pipelines_path: "#{pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof merge_request_widget !== 'undefined') {
|
if (typeof merge_request_widget !== 'undefined') {
|
||||||
clearInterval(merge_request_widget.fetchBuildStatusInterval);
|
|
||||||
merge_request_widget.cancelPolling();
|
merge_request_widget.cancelPolling();
|
||||||
merge_request_widget.clearEventListeners();
|
merge_request_widget.clearEventListeners();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
- content_for :page_specific_javascripts do
|
||||||
|
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
|
||||||
|
|
||||||
- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil
|
- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil
|
||||||
|
|
||||||
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
|
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
|
||||||
|
@ -47,21 +50,3 @@
|
||||||
rows: 14, hint: true
|
rows: 14, hint: true
|
||||||
|
|
||||||
= hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off"
|
= hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off"
|
||||||
|
|
||||||
:javascript
|
|
||||||
$('.accept-mr-form').on('ajax:send', function() {
|
|
||||||
$(".accept-mr-form :input").disable();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.accept_merge_request').on('click', function() {
|
|
||||||
$('.js-merge-button').html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.merge_when_build_succeeds').on('click', function() {
|
|
||||||
$("#merge_when_build_succeeds").val("1");
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.js-merge-dropdown a').on('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
$(this).closest("form").submit();
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
|
- content_for :page_specific_javascripts do
|
||||||
|
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
|
||||||
|
|
||||||
%strong
|
%strong
|
||||||
= icon("spinner spin")
|
= icon("spinner spin")
|
||||||
Checking ability to merge automatically…
|
Checking ability to merge automatically…
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function() {
|
|
||||||
merge_request_widget.getMergeStatus();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
.timeline-content
|
.timeline-content
|
||||||
.note-header
|
.note-header
|
||||||
= link_to_member(note.project, note.author, avatar: false)
|
= link_to_member(note.project, note.author, avatar: false)
|
||||||
.inline.note-headline-light
|
.note-headline-light
|
||||||
= note.author.to_reference
|
= note.author.to_reference
|
||||||
- unless note.system
|
- unless note.system
|
||||||
commented
|
commented
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
%ul
|
%ul
|
||||||
- @stage.statuses.each do |status|
|
- @stage.statuses.latest.each do |status|
|
||||||
%li.dropdown-build
|
%li.dropdown-build
|
||||||
= render 'ci/status/graph_badge', subject: status
|
= render 'ci/status/graph_badge', subject: status
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
.col-lg-9
|
.col-lg-9
|
||||||
= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
|
= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
|
||||||
= render 'shared/service_settings', form: form, subject: @service
|
= render 'shared/service_settings', form: form, subject: @service
|
||||||
|
|
||||||
.footer-block.row-content-block
|
.footer-block.row-content-block
|
||||||
= form.submit 'Save changes', class: 'btn btn-save'
|
= form.submit 'Save changes', class: 'btn btn-save'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}"
|
||||||
|
|
||||||
|
To setup this service:
|
||||||
|
%ul.list-unstyled
|
||||||
|
%li
|
||||||
|
1.
|
||||||
|
= link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands'
|
||||||
|
on your Mattermost installation
|
||||||
|
%li
|
||||||
|
2.
|
||||||
|
= link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command'
|
||||||
|
in Mattermost with these options:
|
||||||
|
|
||||||
|
%hr
|
||||||
|
|
||||||
|
.help-form
|
||||||
|
.form-group
|
||||||
|
= label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#display_name')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#description')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.text-block
|
||||||
|
%p Fill in the word that works best for your team.
|
||||||
|
%p
|
||||||
|
Suggestions:
|
||||||
|
%code= 'gitlab'
|
||||||
|
%code= @project.path # Path contains no spaces, but dashes
|
||||||
|
%code= @project.path_with_namespace
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#request_url')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.text-block POST
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#response_username')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#response_icon')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.text-block Yes
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#autocomplete_hint')
|
||||||
|
|
||||||
|
.form-group
|
||||||
|
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
|
||||||
|
.col-sm-10.col-xs-12.input-group
|
||||||
|
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
||||||
|
.input-group-btn
|
||||||
|
= clipboard_button(clipboard_target: '#autocomplete_description')
|
||||||
|
|
||||||
|
%hr
|
||||||
|
|
||||||
|
%ul.list-unstyled
|
||||||
|
%li
|
||||||
|
3. After adding the slash command, paste the
|
||||||
|
|
||||||
|
%strong token
|
||||||
|
into the field below
|
|
@ -1,4 +1,4 @@
|
||||||
- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}"
|
- enabled = Gitlab.config.mattermost.enabled
|
||||||
|
|
||||||
.well
|
.well
|
||||||
This service allows GitLab users to perform common operations on this
|
This service allows GitLab users to perform common operations on this
|
||||||
|
@ -7,93 +7,9 @@
|
||||||
See list of available commands in Mattermost after setting up this service,
|
See list of available commands in Mattermost after setting up this service,
|
||||||
by entering
|
by entering
|
||||||
%code /<command_trigger_word> help
|
%code /<command_trigger_word> help
|
||||||
%br
|
|
||||||
%br
|
|
||||||
To setup this service:
|
|
||||||
%ul.list-unstyled
|
|
||||||
%li
|
|
||||||
1.
|
|
||||||
= link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands'
|
|
||||||
on your Mattermost installation
|
|
||||||
%li
|
|
||||||
2.
|
|
||||||
= link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command'
|
|
||||||
in Mattermost with these options:
|
|
||||||
|
|
||||||
%hr
|
- unless enabled
|
||||||
|
= render 'projects/services/mattermost_slash_commands/detailed_help', subject: @service
|
||||||
|
|
||||||
.help-form
|
- if enabled
|
||||||
.form-group
|
= render 'projects/services/mattermost_slash_commands/installation_info', subject: @service
|
||||||
= label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#display_name')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#description')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.text-block
|
|
||||||
%p Fill in the word that works best for your team.
|
|
||||||
%p
|
|
||||||
Suggestions:
|
|
||||||
%code= 'gitlab'
|
|
||||||
%code= @project.path # Path contains no spaces, but dashes
|
|
||||||
%code= @project.path_with_namespace
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#request_url')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.text-block POST
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#response_username')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#response_icon')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.text-block Yes
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#autocomplete_hint')
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
|
|
||||||
.col-sm-10.col-xs-12.input-group
|
|
||||||
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
|
||||||
.input-group-btn
|
|
||||||
= clipboard_button(clipboard_target: '#autocomplete_description')
|
|
||||||
|
|
||||||
%hr
|
|
||||||
|
|
||||||
%ul.list-unstyled
|
|
||||||
%li
|
|
||||||
3. After adding the slash command, paste the
|
|
||||||
%strong token
|
|
||||||
into the field below
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
.services-installation-info
|
||||||
|
- unless @service.activated?
|
||||||
|
.row
|
||||||
|
.col-sm-9.col-sm-offset-3
|
||||||
|
= link_to new_namespace_project_mattermost_path(@project.namespace, @project), class: 'btn btn-lg' do
|
||||||
|
= custom_icon('mattermost_logo', size: 15)
|
||||||
|
= 'Add to Mattermost'
|
|
@ -68,6 +68,10 @@
|
||||||
- if koding_enabled? && @repository.koding_yml.blank?
|
- if koding_enabled? && @repository.koding_yml.blank?
|
||||||
%li.missing
|
%li.missing
|
||||||
= link_to 'Set up Koding', add_koding_stack_path(@project)
|
= link_to 'Set up Koding', add_koding_stack_path(@project)
|
||||||
|
- if @repository.gitlab_ci_yml.blank? && @project.deployment_service.present?
|
||||||
|
%li.missing
|
||||||
|
= link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml', commit_message: 'Set up autodeploy', target_branch: 'autodeploy', context: 'autodeploy') do
|
||||||
|
Set up autodeploy
|
||||||
|
|
||||||
- if @repository.commit
|
- if @repository.commit
|
||||||
.project-last-commit{ class: container_class }
|
.project-last-commit{ class: container_class }
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
- group_status = CommitStatus.where(id: subject).status
|
- group_status = CommitStatus.where(id: subject).status
|
||||||
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown'} }
|
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown', title: "#{name} - #{group_status}" } }
|
||||||
%span{class: "ci-status-icon ci-status-icon-#{group_status}"}
|
%span{class: "ci-status-icon ci-status-icon-#{group_status}"}
|
||||||
= ci_icon_for_status(group_status)
|
= ci_icon_for_status(group_status)
|
||||||
%span.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{name} - #{group_status}" }
|
%span.ci-status-text
|
||||||
= name
|
= name
|
||||||
%span.dropdown-counter-badge= subject.size
|
%span.dropdown-counter-badge= subject.size
|
||||||
.dropdown-menu.grouped-pipeline-dropdown
|
.dropdown-menu.grouped-pipeline-dropdown
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
.text-content
|
.text-content
|
||||||
- if has_button && current_user
|
- if has_button && current_user
|
||||||
%h4
|
%h4
|
||||||
The Issue Tracker is a good place to add things that need to be improved or solved in a project!
|
The Issue Tracker is the place to add things that need to be improved or solved in a project
|
||||||
%p
|
%p
|
||||||
An issue can be a bug, a todo or a feature request that needs to be discussed in a project.
|
Issues can be bugs, tasks or ideas to be discussed.
|
||||||
Besides, issues are searchable and filterable.
|
Also, issues are searchable and filterable.
|
||||||
- if project_select_button
|
- if project_select_button
|
||||||
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue'
|
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue'
|
||||||
- else
|
- else
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="<%= size %>" height="<%= size %>" version="1" viewBox="0 0 501 501"><path d="M236 .7C137.7 7.5 54 68.2 18.2 158.5c-32 81-19.6 172.8 33 242.5 39.8 53 97.2 87 164.3 97 16.5 2.7 48 3.2 63.5 1.2 48.7-6.3 92.2-24.6 129-54.2 13-10.5 33-31.2 42.2-43.7 26.4-35.5 42.8-75.8 49-120.3 1.6-12.3 1.6-48.7 0-61-4-28.3-12-54.8-24.2-79.5-12.8-26-26.5-45.3-46.8-65.8C417.8 64 400.2 49 398.4 49c-.6 0-.4 10.5.3 26l1.3 26 7 8.7c19 23.7 32.8 53.5 38.2 83 2.5 14 3 43 1 55.8-4.5 27.8-15.2 54-31 76.5-8.6 12.2-28 31.6-40.2 40.2-24 17-50 27.6-80 33-10 1.8-49 1.8-59 0-43-7.7-78.8-26-107.2-54.8-29.3-29.7-46.5-64-52.4-104.4-2-14-1.5-42 1-55C90 121.4 132 72 192 49.7c8-3 18.4-5.8 29.5-8.2 1.7-.4 34.4-38 35.3-40.6.3-1-10.2-1-20.8-.4z"/><path d="M322.2 24.6c-1.3.8-8.4 9.3-16 18.7-7.4 9.5-22.4 28-33.2 41.2-51 62.2-66 81.6-70.6 91-6 12-8.4 21-9 33-1.2 19.8 5 36 19 50C222 268 230 273 243 277.2c9 3 10.4 3.2 24 3.2 13.8 0 15 0 22.6-3 23.2-9 39-28.4 45-55.7 2-8.2 2-28.7.4-79.7l-2-72c-1-36.8-1.4-41.8-3-44-2-3-4.8-3.6-7.8-1.4z"/></svg>
|
After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="33" class="gitlab-icon-scroll-down" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M1.385 5.534v12.47a4.145 4.145 0 0 0 4.144 4.15h4.942a4.151 4.151 0 0 0 4.144-4.15V5.535a4.145 4.145 0 0 0-4.144-4.15H5.53a4.151 4.151 0 0 0-4.144 4.15zM8.88 30.27v-4.351a.688.688 0 0 0-.69-.688.687.687 0 0 0-.69.688v4.334l-1.345-1.346a.69.69 0 0 0-.976.976l2.526 2.526a.685.685 0 0 0 .494.2.685.685 0 0 0 .493-.2l2.526-2.526a.69.69 0 1 0-.976-.976L8.88 30.27zM0 5.534A5.536 5.536 0 0 1 5.529 0h4.942A5.53 5.53 0 0 1 16 5.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 18.005V5.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0V6.544z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 719 B |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="33" class="gitlab-icon-scroll-down-hover" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M8.88 30.27v-4.351a.688.688 0 0 0-.69-.688.687.687 0 0 0-.69.688v4.334l-1.345-1.346a.69.69 0 0 0-.976.976l2.526 2.526a.685.685 0 0 0 .494.2.685.685 0 0 0 .493-.2l2.526-2.526a.69.69 0 1 0-.976-.976L8.88 30.27zM0 5.534A5.536 5.536 0 0 1 5.529 0h4.942A5.53 5.53 0 0 1 16 5.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 18.005V5.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0V6.544z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 573 B |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="33" class="gitlab-icon-scroll-up" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M1.385 14.534v12.47a4.145 4.145 0 0 0 4.144 4.15h4.942a4.151 4.151 0 0 0 4.144-4.15v-12.47a4.145 4.145 0 0 0-4.144-4.15H5.53a4.151 4.151 0 0 0-4.144 4.15zM8.88 2.609V6.96a.688.688 0 0 1-.69.688.687.687 0 0 1-.69-.688V2.627L6.155 3.972a.69.69 0 0 1-.976-.976L7.705.47a.685.685 0 0 1 .494-.2.685.685 0 0 1 .493.2l2.526 2.526a.69.69 0 1 1-.976.976L8.88 2.609zM0 14.534A5.536 5.536 0 0 1 5.529 9h4.942A5.53 5.53 0 0 1 16 14.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 27.005V14.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0v-2.143z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 717 B |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="33" class="gitlab-icon-scroll-up-hover" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M8.88 2.646l1.362 1.362a.69.69 0 0 0 .976-.976L8.692.507A.685.685 0 0 0 8.2.306a.685.685 0 0 0-.494.2L5.179 3.033a.69.69 0 1 0 .976.976L7.5 2.663v4.179c0 .38.306.688.69.688.381 0 .69-.306.69-.688V2.646zM0 14.534A5.536 5.536 0 0 1 5.529 9h4.942A5.53 5.53 0 0 1 16 14.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 27.005V14.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0v-2.143z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 569 B |
|
@ -3,7 +3,7 @@
|
||||||
- show_menu_above = show_menu_above || false
|
- show_menu_above = show_menu_above || false
|
||||||
- selected_text = selected.try(:title) || params[:milestone_title]
|
- selected_text = selected.try(:title) || params[:milestone_title]
|
||||||
- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by milestone")
|
- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by milestone")
|
||||||
- if selected.present?
|
- if selected.present? || params[:milestone_title].present?
|
||||||
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
|
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
|
||||||
= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone",
|
= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone",
|
||||||
placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, field_name: name, selected: selected.try(:title), project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
|
placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, field_name: name, selected: selected.try(:title), project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix wrong tab selected when loggin fails and multiple login tabs exists
|
|
||||||
merge_request: 7314
|
|
||||||
author: Jacopo Beschi @jacopo-beschi
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Made comment autocomplete more performant and removed some loading bugs
|
|
||||||
merge_request: 6856
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Update wiki page design
|
|
||||||
merge_request: 7429
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: group authors in contribution graph with case insensitive email handle comparison
|
|
||||||
merge_request: 8021
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Adds Direct link from pipeline list to builds
|
|
||||||
merge_request: 8097
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Prevent overflow with vertical scroll when we have space to show content
|
|
||||||
merge_request: 8061
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Add scopes for personal access tokens and OAuth tokens
|
|
||||||
merge_request: 5951
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: New Gitea importer
|
|
||||||
merge_request: 8116
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: 'Make API::Helpers find a project with only one query'
|
|
||||||
merge_request: 7714
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Resolve "Manual actions on pipeline graph"
|
|
||||||
merge_request: 7931
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: New `gitlab:workhorse:install` rake task
|
|
||||||
merge_request: 6574
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Prevent DOM ID collisions resulting from user-generated content anchors
|
|
||||||
merge_request: 7631
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Introduce $CI_BUILD_REF_SLUG
|
|
||||||
merge_request: 8072
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Add a slug to environments
|
|
||||||
merge_request: 7983
|
|
||||||
author:
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue