diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f97feca9f7b..87c3944dcce 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,7 +75,7 @@ stages: .use-mysql: &use-mysql services: - - mysql:latest + - mysql:5.7 - redis:alpine .rails5-variables: &rails5-variables diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d443238b9e1..16b0b5c95e2 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -143,7 +143,7 @@ Lint/MissingCopEnableDirective: Lint/NestedPercentLiteral: Exclude: - 'lib/gitlab/git/repository.rb' - - 'spec/support/email_format_shared_examples.rb' + - 'spec/support/shared_examples/email_format_shared_examples.rb' # Offense count: 1 Lint/ReturnInVoidContext: @@ -195,8 +195,8 @@ Naming/HeredocDelimiterCase: - 'spec/lib/gitlab/diff/parser_spec.rb' - 'spec/lib/json_web_token/rsa_token_spec.rb' - 'spec/models/commit_spec.rb' - - 'spec/support/repo_helpers.rb' - - 'spec/support/seed_repo.rb' + - 'spec/support/helpers/repo_helpers.rb' + - 'spec/support/helpers/seed_repo.rb' # Offense count: 112 # Configuration parameters: Blacklist. @@ -496,7 +496,7 @@ Style/EmptyLiteral: - 'spec/lib/gitlab/request_context_spec.rb' - 'spec/lib/gitlab/workhorse_spec.rb' - 'spec/requests/api/jobs_spec.rb' - - 'spec/support/chat_slash_commands_shared_examples.rb' + - 'spec/support/shared_examples/chat_slash_commands_shared_examples.rb' # Offense count: 102 # Cop supports --auto-correct. diff --git a/CHANGELOG.md b/CHANGELOG.md index d56c86523f5..8278119cf10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,241 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 10.7.1 (2018-04-23) + +### Fixed (11 changes) + +- [API] Fix URLs in the `Link` header for `GET /projects/:id/repository/contributors` when no value is passed for `order_by` or `sort`. !18393 +- Fix a case with secret variables being empty sometimes. !18400 +- Fix `Trace::HttpIO` can not render multi-byte chars. !18417 +- Fix specifying a non-default ref when requesting an archive using the legacy URL. !18468 +- Respect visibility options and description when importing project from template. !18473 +- Removes 'No Job log' message from build trace. !18523 +- Align action icons in pipeline graph. +- Fix direct_upload when records with null file_store are used. +- Removed alert box in IDE when redirecting to new merge request. +- Fixed IDE not loading for sub groups. +- Fixed IDE not showing loading state when tree is loading. + +### Performance (4 changes) + +- Validate project path prior to hitting the database. !18322 +- Add index to file_store on ci_job_artifacts. !18444 +- Fix N+1 queries when loading participants for a commit note. +- Support Markdown rendering using multiple projects. + +### Added (1 change) + +- Add an API endpoint to download git repository snapshots. !18173 + + +## 10.7.0 (2018-04-22) + +### Security (6 changes, 2 of them are from the community) + +- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337 +- Update ruby-saml to 1.7.2 and omniauth-saml to 1.10.0. !17734 (Takuya Noguchi) +- Update rack-protection to 2.0.1. !17835 (Takuya Noguchi) +- Adds confidential notes channel for Slack/Mattermost. +- Fix XSS on diff view stored on filenames. +- Fix GitLab Auth0 integration signing in the wrong user. + +### Fixed (65 changes, 20 of them are from the community) + +- File uploads in remote storage now support project renaming. !4597 +- Fixed bug in dropdown selector when selecting the same selection again. !14631 (bitsapien) +- Fixed group deletion linked to Mattermost. !16209 (Julien Millau) +- Create commit API and Web IDE obey LFS filters. !16718 +- Set breadcrumb for admin/runners/show. !17431 (Takuya Noguchi) +- Enable restore rake task to handle nested storage directories. !17516 (Balasankar C) +- Fix hover style of dropdown items in the right sidebar. !17519 +- Improve empty state for canceled job. !17646 +- Fix generated URL when listing repoitories for import. !17692 +- Use singular in the diff stats if only one line has been changed. !17697 (Jan Beckmann) +- Long instance urls do not overflow anymore during project creation. !17717 +- Fix importing multiple assignees from GitLab export. !17718 +- Correct copy text for the promote milestone and label modals. !17726 +- Fix search results stripping last endline when parsing the results. !17777 (Jasper Maes) +- Add read-only banner to all pages. !17798 +- Fix viewing diffs on old merge requests. !17805 +- Fix forking to subgroup via API when namespace is given by name. !17815 (Jan Beckmann) +- Fix UI breakdown for Create merge request button. !17821 (Takuya Noguchi) +- Unify format for nested non-task lists. !17823 (Takuya Noguchi) +- UX re-design branch items with flexbox. !17832 (Takuya Noguchi) +- Use porcelain commit lookup method on CI::CreatePipelineService. !17911 +- Update dashboard milestones breadcrumb link. !17933 (George Tsiolis) +- Deleting a MR you are assigned to should decrements counter. !17951 (m b) +- Update no repository placeholder. !17964 (George Tsiolis) +- Drop JSON response in Project Milestone along with avoiding error. !17977 (Takuya Noguchi) +- Fix personal access token clipboard button style. !17978 (Fabian Schneider) +- Avoid validation errors when running the Pages domain verification service. !17992 +- Project creation will now raise an error if a service template is invalid. !18013 +- Add better LDAP connection handling. !18039 +- Fix autolinking URLs containing ampersands. !18045 +- Fix exceptions raised when migrating pipeline stages in the background. !18076 +- Always display Labels section in issuable sidebar, even when the project has no labels. !18081 (Branka Martinovic) +- Fixed gitlab:uploads:migrate task ignoring some uploads. !18082 +- Fixed gitlab:uploads:migrate task failing for Groups' avatar. !18088 +- Increase dropdown width in pipeline graph & center action icon. !18089 +- Fix `JobsController#raw` endpoint can not read traces in database. !18101 +- Fix `gitlab-rake gitlab:two_factor:disable_for_all_users`. !18154 +- Adjust 404's for LegacyDiffNote discussion rendering. !18201 +- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert) +- Prioritize weight over title when sorting charts. !18233 +- Verify that deploy token has valid access when pulling container registry image. !18260 +- Stop redirecting the page in pipeline main actions. +- Fixed IDE button opening the wrong URL in tree list. +- Ensure hooks run when a deploy key without a user pushes. +- Fix 404 in group boards when moving issue between lists. +- Display state indicator for issuable references in non-project scope (e.g. when referencing issuables from group scope). +- Add missing port to artifact links. +- Fix data race between ObjectStorage background_upload and Pages publishing. +- Fixes unresolved discussions rendering the error state instead of the diff. +- Don't show Jump to Discussion button on Issues. +- Fix bug rendering group icons when forking. +- Automatically cleanup stale worktrees and lock files upon a push. +- Use the GitLab version as part of the appearances cache key. +- Fix Firefox stealing formatting characters on issue notes. +- Include matching branches and tags in protected branches / tags count. (Jan Beckmann) +- Fix 500 error when a merge request from a fork has conflicts and has not yet been updated. +- Test if remote repository exists when importing wikis. +- Hide emoji popup after multiple spaces. (Jan Beckmann) +- Fix relative uri when "#" is in branch name. (Jan) +- Escape Markdown characters properly when using autocomplete. +- Ignore project internal references in group context. +- Fix finding wiki file when Gitaly is enabled. +- Fix listing commit branch/tags that contain special characters. +- Ensure internal users (ghost, support bot) get assigned a namespace. +- Fix links to subdirectories of a directory with a plus character in its path. + +### Deprecated (1 change) + +- Remove support for legacy tar.gz pages artifacts. !18090 + +### Changed (22 changes, 2 of them are from the community) + +- Add yellow favicon when `CANARY=true` to differientate canary environment. !12477 +- Use human readable value build_timeout in Project. !17386 +- Improved visual styles and consistency for commit hash and possible actions across commit lists. !17406 +- Don't create permanent redirect routes. !17521 +- Add empty repo check before running AutoDevOps pipeline. !17605 +- Update wording to specify create/manage project vs group labels in labels dropdown. !17640 +- Add tooltips to icons in lists of issues and merge requests. !17700 +- Change avatar error message to include allowed file formats. !17747 (Fabian Schneider) +- Polish design for verifying domains. !17767 +- Move email footer info to a single line. !17916 +- Add average and maximum summary statistics to the prometheus dashboard. !17921 +- Add additional cluster usage metrics to usage ping. !17922 +- Move 'Registry' after 'CI/CD' in project navigation sidebar. !18018 (Elias Werberich) +- Redesign application settings to match project settings. !18019 +- Allow HTTP(s) when git request is made by GitLab CI. !18021 +- Added hover background color to IDE file list rows. +- Make project avatar in IDE consistent with the rest of GitLab. +- Show issues of subgroups in group-level issue board. +- Repository checksum calculation is handled by Gitaly when feature is enabled. +- Allow viewing timings for AJAX requests in the performance bar. +- Fixes remove source branch checkbox being visible when user cannot remove the branch. +- Make /-/ delimiter optional for search endpoints. + +### Performance (24 changes, 11 of them are from the community) + +- Move AssigneeTitle vue component. !17397 (George Tsiolis) +- Move TimeTrackingCollapsedState vue component. !17399 (George Tsiolis) +- Move MemoryGraph and MemoryUsage vue components. !17533 (George Tsiolis) +- Move UnresolvedDiscussions vue component. !17538 (George Tsiolis) +- Move NothingToMerge vue component. !17544 (George Tsiolis) +- Move ShaMismatch vue component. !17546 (George Tsiolis) +- Stop caching highlighted diffs in Redis unnecessarily. !17746 +- Add i18n and update specs for ShaMismatch vue component. !17870 (George Tsiolis) +- Update spec import path for vue mount component helper. !17880 (George Tsiolis) +- Move TimeTrackingComparisonPane vue component. !17931 (George Tsiolis) +- Improves the performance of projects list page. !17934 +- Remove N+1 query for Noteable association. !17956 +- Improve performance of loading issues with lots of references to merge requests. !17986 +- Reuse root_ref_hash for performance on Branches. !17998 (Takuya Noguchi) +- Update asciidoctor-plantuml to 0.0.8. !18022 (Takuya Noguchi) +- Cache personal projects count. !18197 +- Reduce complexity of issuable finder query. !18219 +- Reduce number of queries when viewing a merge request. +- Free open file descriptors and libgit2 buffers in UpdatePagesService. +- Memoize Git::Repository#has_visible_content?. +- Require at least one filter when listing issues or merge requests on dashboard page. +- lazy load diffs on merge request discussions. +- Bulk deleting refs is handled by Gitaly by default. +- ListCommitsByOid is executed by Gitaly by default. + +### Added (38 changes, 7 of them are from the community) + +- Add HTTPS-only pages. !16273 (rfwatson) +- adds closed by informations in issue api. !17042 (haseebeqx) +- Projects and groups badges settings UI. !17114 +- Add per-runner configured job timeout. !17221 +- Add alternate archive route for simplified packaging. !17225 +- Add support for pipeline variables expressions in only/except. !17316 +- Add object storage support for LFS objects, CI artifacts, and uploads. !17358 +- Added confirmation modal for changing username. !17405 +- Implement foreground verification of CI artifacts. !17578 +- Extend API for exporting a project with direct upload URL. !17686 +- Move ci/lint under project's namespace. !17729 +- Add Total CPU/Memory consumption metrics for Kubernetes. !17731 +- Adds the option to the project export API to override the project description and display GitLab export description once imported. !17744 +- Port direct upload of LFS artifacts from EE. !17752 +- Adds support for OmniAuth JWT provider. !17774 +- Display error message on job's tooltip if this one fails. !17782 +- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich) +- Extend API for importing a project export with overwrite support. !17883 +- Create Deploy Tokens to allow permanent access to repository and registry. !17894 +- Detect commit message trailers and link users properly to their accounts on Gitlab. !17919 (cousine) +- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi) +- API: Add parameter merge_method to projects. !18031 (Jan Beckmann) +- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036 +- Allow overriding params on project import through API. !18086 +- Support LFS objects when importing/exporting GitLab project archives. !18115 +- Store sha256 checksum of artifact metadata. !18149 +- Limit the number of failed logins when using LDAP for authentication. !43525 +- Allow assigning and filtering issuables by ancestor group labels. +- Include subgroup issues when searching for group issues using the API. +- Allow to store uploads by default on Object Storage. +- Add slash command for moving issues. (Adam Pahlevi) +- Render MR commit SHA instead "diffs" when viable. +- Send @mention notifications even if a user has explicitly unsubscribed from item. +- Add support for Sidekiq JSON logging. +- Add Gitaly call details to performance bar. +- Add support for patch link extension for commit links on GitLab Flavored Markdown. +- Allow feature gates to be removed through the API. +- Allow merge requests related to a commit to be found via API. + +### Other (27 changes, 11 of them are from the community) + +- Send notification emails when push to a merge request. !7610 (YarNayar) +- Rename modal.vue to deprecated_modal.vue. !17438 +- Atomic generation of internal ids for issues. !17580 +- Use object ID to prevent duplicate keys Vue warning on Issue Boards page during development. !17682 +- Update foreman from 0.78.0 to 0.84.0. !17690 (Takuya Noguchi) +- Add realtime pipeline status for adding/viewing files. !17705 +- Update documentation to reflect current minimum required versions of node and yarn. !17706 +- Update knapsack to 1.16.0. !17735 (Takuya Noguchi) +- Update CI services documnetation. !17749 +- Added i18n support for the prometheus memory widget. !17753 +- Use specific names for filtered CI variable controller parameters. !17796 +- Apply NestingDepth (level 5) (framework/dropdowns.scss). !17820 (Takuya Noguchi) +- Clean up selectors in framework/header.scss. !17822 (Takuya Noguchi) +- Bump `state_machines-activerecord` to 0.5.1. !17924 (blackst0ne) +- Increase the memory limits used in the unicorn killer. !17948 +- Replace the spinach test with an rspec analog. !17950 (blackst0ne) +- Remove unused index from events table. !18014 +- Make all workhorse gitaly calls opt-out, take 2. !18043 +- Update brakeman 3.6.1 to 4.2.1. !18122 (Takuya Noguchi) +- Replace the `project/issues/labels.feature` spinach test with an rspec analog. !18126 (blackst0ne) +- Bump html-pipeline to 2.7.1. !18132 (@blackst0ne) +- Remove test_ci rake task. !18139 (Takuya Noguchi) +- Add documentation for Pipelines failure reasons. !18352 +- Improve JIRA event descriptions. +- Add query counts to profiler output. +- Move Sidekiq exporter logs to log/sidekiq_exporter.log. +- Upgrade Gitaly to upgrade its charlock_holmes. + + ## 10.6.4 (2018-04-09) ### Fixed (8 changes, 1 of them is from the community) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02599907af7..29009010f0e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,9 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._ - [Type labels (~"feature proposal", ~bug, ~customer, etc.)](#type-labels-feature-proposal-bug-customer-etc) - [Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)](#subject-labels-wiki-container-registry-ldap-api-etc) - [Team labels (~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.)](#team-labels-cicd-discussion-edge-platform-etc) - - [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#priority-labels-deliverable-stretch-next-patch-release) + - [Milestone labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#milestone-labels-deliverable-stretch-next-patch-release) + - [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-priority-labels-p1-p2-p3-etc) + - [Severity labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-severity-labels-s1-s2-s3-etc) - [Label for community contributors (~"Accepting Merge Requests")](#label-for-community-contributors-accepting-merge-requests) - [Implement design & UI elements](#implement-design-ui-elements) - [Issue tracker](#issue-tracker) @@ -127,6 +129,8 @@ Most issues will have labels for at least one of the following: - Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc. - Team: ~"CI/CD", ~Discussion, ~Edge, ~Platform, etc. - Milestone: ~Deliverable, ~Stretch, ~"Next Patch Release" +- Priority: ~P1, ~P2, ~P3, ~P4 +- Severity: ~S1, ~S2, ~S3, ~S4 All labels, their meaning and priority are defined on the [labels page][labels-page]. @@ -210,7 +214,7 @@ This label documents the planned timeline & urgency which is used to measure aga | Label | Meaning | Estimate time to fix | Guidance | |-------|-----------------|------------------------------------------------------------------|----------| -| ~P1 | Urgent Priority | The current release | | +| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com | | | ~P2 | High Priority | The next release | | | ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) | | | ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) | The issue is prominent but does not impact user workflow and a workaround is documented | diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 5f8cbfdb7d7..483b7719418 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.95.0 +0.96.1 diff --git a/Gemfile.lock b/Gemfile.lock index 745732f3537..1ba99df5e44 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -178,7 +178,7 @@ GEM docile (1.1.5) domain_name (0.5.20170404) unf (>= 0.0.5, < 1.0.0) - doorkeeper (4.3.1) + doorkeeper (4.3.2) railties (>= 4.2) doorkeeper-openid_connect (1.3.0) doorkeeper (~> 4.3) diff --git a/VERSION b/VERSION index 7a86eda5728..60919325d67 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -10.7.0-pre +10.8.0-pre diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index e210d69895e..7144f4190e7 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -113,6 +113,8 @@ class List { issue.id = data.id; issue.iid = data.iid; issue.project = data.project; + issue.path = data.real_path; + issue.referencePath = data.reference_path; if (this.issuesSize > 1) { const moveBeforeId = this.issues[1].id; diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js index fb1fc9cd32e..a88b6971f90 100644 --- a/app/assets/javascripts/create_merge_request_dropdown.js +++ b/app/assets/javascripts/create_merge_request_dropdown.js @@ -84,20 +84,21 @@ export default class CreateMergeRequestDropdown { if (data.can_create_branch) { this.available(); this.enable(); + this.updateBranchName(data.suggested_branch_name); if (!this.droplabInitialized) { this.droplabInitialized = true; this.initDroplab(); this.bindEvents(); } - } else if (data.has_related_branch) { + } else { this.hide(); } }) .catch(() => { this.unavailable(); this.disable(); - Flash('Failed to check if a new branch can be created.'); + Flash(__('Failed to check related branches.')); }); } @@ -409,13 +410,16 @@ export default class CreateMergeRequestDropdown { this.unavailableButton.classList.remove('hide'); } + updateBranchName(suggestedBranchName) { + this.branchInput.value = suggestedBranchName; + this.updateCreatePaths('branch', suggestedBranchName); + } + updateInputState(target, ref, result) { // target - 'branch' or 'ref' - which the input field we are searching a ref for. // ref - string - what a user typed. // result - string - what has been found on backend. - const pathReplacement = `$1${ref}`; - // If a found branch equals exact the same text a user typed, // that means a new branch cannot be created as it already exists. if (ref === result) { @@ -426,18 +430,12 @@ export default class CreateMergeRequestDropdown { this.refIsValid = true; this.refInput.dataset.value = ref; this.showAvailableMessage('ref'); - this.createBranchPath = this.createBranchPath.replace(this.regexps.ref.createBranchPath, - pathReplacement); - this.createMrPath = this.createMrPath.replace(this.regexps.ref.createMrPath, - pathReplacement); + this.updateCreatePaths(target, ref); } } else if (target === 'branch') { this.branchIsValid = true; this.showAvailableMessage('branch'); - this.createBranchPath = this.createBranchPath.replace(this.regexps.branch.createBranchPath, - pathReplacement); - this.createMrPath = this.createMrPath.replace(this.regexps.branch.createMrPath, - pathReplacement); + this.updateCreatePaths(target, ref); } else { this.refIsValid = false; this.refInput.dataset.value = ref; @@ -457,4 +455,15 @@ export default class CreateMergeRequestDropdown { this.disableCreateAction(); } } + + // target - 'branch' or 'ref' + // ref - string - the new value to use as branch or ref + updateCreatePaths(target, ref) { + const pathReplacement = `$1${ref}`; + + this.createBranchPath = this.createBranchPath.replace(this.regexps[target].createBranchPath, + pathReplacement); + this.createMrPath = this.createMrPath.replace(this.regexps[target].createMrPath, + pathReplacement); + } } diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 2121907dff0..96f2b3eac98 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1427,7 +1427,7 @@ export default class Notes { const { discussion_html } = data; const lines = $(discussion_html).find('.line_holder'); lines.addClass('fade-in'); - $container.find('tbody').prepend(lines); + $container.find('.diff-content > table > tbody').prepend(lines); const fileHolder = $container.find('.file-holder'); $container.find('.line-holder-placeholder').remove(); syntaxHighlight(fileHolder); diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js index 8ce938c958b..cbc2d80ee18 100644 --- a/app/assets/javascripts/pages/users/activity_calendar.js +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -19,7 +19,7 @@ function getSystemDate(systemUtcOffsetSeconds) { const date = new Date(); const localUtcOffsetMinutes = 0 - date.getTimezoneOffset(); const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60; - date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes); + date.setMinutes(date.getMinutes() - localUtcOffsetMinutes + systemUtcOffsetMinutes); return date; } @@ -35,18 +35,36 @@ function formatTooltipText({ date, count }) { return `${contribText}
${dateDayName} ${dateText}`; } -const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]); +const initColorKey = () => + d3 + .scaleLinear() + .range(['#acd5f2', '#254e77']) + .domain([0, 3]); export default class ActivityCalendar { - constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0) { + constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0, firstDayOfWeek = 0) { this.calendarActivitiesPath = calendarActivitiesPath; this.clickDay = this.clickDay.bind(this); this.currentSelectedDate = ''; this.daySpace = 1; this.daySize = 15; - this.daySizeWithSpace = this.daySize + (this.daySpace * 2); - this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + this.daySizeWithSpace = this.daySize + this.daySpace * 2; + this.monthNames = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ]; this.months = []; + this.firstDayOfWeek = firstDayOfWeek; // Loop through the timestamps to create a group of objects // The group of objects will be grouped based on the day of the week they are @@ -70,7 +88,7 @@ export default class ActivityCalendar { // Create a new group array if this is the first day of the week // or if is first object - if ((day === 0 && i !== 0) || i === 0) { + if ((day === this.firstDayOfWeek && i !== 0) || i === 0) { this.timestampsTmp.push([]); group += 1; } @@ -109,21 +127,30 @@ export default class ActivityCalendar { } renderSvg(container, group) { - const width = ((group + 1) * this.daySizeWithSpace) + this.getExtraWidthPadding(group); - return d3.select(container) + const width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group); + return d3 + .select(container) .append('svg') - .attr('width', width) - .attr('height', 167) - .attr('class', 'contrib-calendar'); + .attr('width', width) + .attr('height', 167) + .attr('class', 'contrib-calendar'); + } + + dayYPos(day) { + return this.daySizeWithSpace * ((day + 7 - this.firstDayOfWeek) % 7); } renderDays() { - this.svg.selectAll('g').data(this.timestampsTmp).enter().append('g') + this.svg + .selectAll('g') + .data(this.timestampsTmp) + .enter() + .append('g') .attr('transform', (group, i) => { _.each(group, (stamp, a) => { if (a === 0 && stamp.day === 0) { const month = stamp.date.getMonth(); - const x = (this.daySizeWithSpace * i) + 1 + this.daySizeWithSpace; + const x = this.daySizeWithSpace * i + 1 + this.daySizeWithSpace; const lastMonth = _.last(this.months); if ( lastMonth == null || @@ -133,86 +160,113 @@ export default class ActivityCalendar { } } }); - return `translate(${(this.daySizeWithSpace * i) + 1 + this.daySizeWithSpace}, 18)`; + return `translate(${this.daySizeWithSpace * i + 1 + this.daySizeWithSpace}, 18)`; }) .selectAll('rect') - .data(stamp => stamp) - .enter() - .append('rect') - .attr('x', '0') - .attr('y', stamp => this.daySizeWithSpace * stamp.day) - .attr('width', this.daySize) - .attr('height', this.daySize) - .attr('fill', stamp => ( - stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed' - )) - .attr('title', stamp => formatTooltipText(stamp)) - .attr('class', 'user-contrib-cell js-tooltip') - .attr('data-container', 'body') - .on('click', this.clickDay); + .data(stamp => stamp) + .enter() + .append('rect') + .attr('x', '0') + .attr('y', stamp => this.dayYPos(stamp.day)) + .attr('width', this.daySize) + .attr('height', this.daySize) + .attr( + 'fill', + stamp => (stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed'), + ) + .attr('title', stamp => formatTooltipText(stamp)) + .attr('class', 'user-contrib-cell js-tooltip') + .attr('data-container', 'body') + .on('click', this.clickDay); } renderDayTitles() { const days = [ { text: 'M', - y: 29 + (this.daySizeWithSpace * 1), - }, { + y: 29 + this.dayYPos(1), + }, + { text: 'W', - y: 29 + (this.daySizeWithSpace * 3), - }, { + y: 29 + this.dayYPos(2), + }, + { text: 'F', - y: 29 + (this.daySizeWithSpace * 5), + y: 29 + this.dayYPos(3), }, ]; - this.svg.append('g') + this.svg + .append('g') .selectAll('text') - .data(days) - .enter() - .append('text') - .attr('text-anchor', 'middle') - .attr('x', 8) - .attr('y', day => day.y) - .text(day => day.text) - .attr('class', 'user-contrib-text'); + .data(days) + .enter() + .append('text') + .attr('text-anchor', 'middle') + .attr('x', 8) + .attr('y', day => day.y) + .text(day => day.text) + .attr('class', 'user-contrib-text'); } renderMonths() { - this.svg.append('g') + this.svg + .append('g') .attr('direction', 'ltr') .selectAll('text') - .data(this.months) - .enter() - .append('text') - .attr('x', date => date.x) - .attr('y', 10) - .attr('class', 'user-contrib-text') - .text(date => this.monthNames[date.month]); + .data(this.months) + .enter() + .append('text') + .attr('x', date => date.x) + .attr('y', 10) + .attr('class', 'user-contrib-text') + .text(date => this.monthNames[date.month]); } renderKey() { - const keyValues = ['no contributions', '1-9 contributions', '10-19 contributions', '20-29 contributions', '30+ contributions']; - const keyColors = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)]; + const keyValues = [ + 'no contributions', + '1-9 contributions', + '10-19 contributions', + '20-29 contributions', + '30+ contributions', + ]; + const keyColors = [ + '#ededed', + this.colorKey(0), + this.colorKey(1), + this.colorKey(2), + this.colorKey(3), + ]; - this.svg.append('g') - .attr('transform', `translate(18, ${(this.daySizeWithSpace * 8) + 16})`) + this.svg + .append('g') + .attr('transform', `translate(18, ${this.daySizeWithSpace * 8 + 16})`) .selectAll('rect') - .data(keyColors) - .enter() - .append('rect') - .attr('width', this.daySize) - .attr('height', this.daySize) - .attr('x', (color, i) => this.daySizeWithSpace * i) - .attr('y', 0) - .attr('fill', color => color) - .attr('class', 'js-tooltip') - .attr('title', (color, i) => keyValues[i]) - .attr('data-container', 'body'); + .data(keyColors) + .enter() + .append('rect') + .attr('width', this.daySize) + .attr('height', this.daySize) + .attr('x', (color, i) => this.daySizeWithSpace * i) + .attr('y', 0) + .attr('fill', color => color) + .attr('class', 'js-tooltip') + .attr('title', (color, i) => keyValues[i]) + .attr('data-container', 'body'); } initColor() { - const colorRange = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)]; - return d3.scaleThreshold().domain([0, 10, 20, 30]).range(colorRange); + const colorRange = [ + '#ededed', + this.colorKey(0), + this.colorKey(1), + this.colorKey(2), + this.colorKey(3), + ]; + return d3 + .scaleThreshold() + .domain([0, 10, 20, 30]) + .range(colorRange); } clickDay(stamp) { @@ -227,14 +281,15 @@ export default class ActivityCalendar { $('.user-calendar-activities').html(LOADING_HTML); - axios.get(this.calendarActivitiesPath, { - params: { - date, - }, - responseType: 'text', - }) - .then(({ data }) => $('.user-calendar-activities').html(data)) - .catch(() => flash(__('An error occurred while retrieving calendar activity'))); + axios + .get(this.calendarActivitiesPath, { + params: { + date, + }, + responseType: 'text', + }) + .then(({ data }) => $('.user-calendar-activities').html(data)) + .catch(() => flash(__('An error occurred while retrieving calendar activity'))); } else { this.currentSelectedDate = ''; $('.user-calendar-activities').html(''); diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue index e99d949801f..29ee73a2a6f 100644 --- a/app/assets/javascripts/pipelines/components/graph/action_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue @@ -32,26 +32,38 @@ export default { required: true, }, - buttonDisabled: { + requestFinishedFor: { type: String, required: false, - default: null, + default: '', }, }, + data() { + return { + isDisabled: false, + linkRequested: '', + }; + }, + computed: { cssClass() { const actionIconDash = dasherize(this.actionIcon); return `${actionIconDash} js-icon-${actionIconDash}`; }, - isDisabled() { - return this.buttonDisabled === this.link; + }, + watch: { + requestFinishedFor() { + if (this.requestFinishedFor === this.linkRequested) { + this.isDisabled = false; + } }, }, - methods: { onClickAction() { $(this.$el).tooltip('hide'); eventHub.$emit('graphAction', this.link); + this.linkRequested = this.link; + this.isDisabled = true; }, }, }; @@ -62,7 +74,8 @@ export default { @click="onClickAction" v-tooltip :title="tooltipText" - class="btn btn-blank btn-transparent ci-action-icon-container ci-action-icon-wrapper" + class="js-ci-action btn btn-blank +btn-transparent ci-action-icon-container ci-action-icon-wrapper" :class="cssClass" data-container="body" :disabled="isDisabled" diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue deleted file mode 100644 index 7c4fd65e36f..00000000000 --- a/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue +++ /dev/null @@ -1,53 +0,0 @@ - - diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue index be213c2ee78..43121dd38f3 100644 --- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue @@ -1,77 +1,83 @@