Merge branch 'master' into sh-headless-chrome-support
|
@ -7,4 +7,5 @@
|
|||
/vendor/
|
||||
karma.config.js
|
||||
webpack.config.js
|
||||
svg.config.js
|
||||
/app/assets/javascripts/locale/**/*.js
|
||||
|
|
|
@ -176,11 +176,20 @@ build-package:
|
|||
image: ruby:2.4-alpine
|
||||
before_script:
|
||||
- gem install gitlab --no-doc
|
||||
# We need to download the script rather than clone the repo since the
|
||||
# review-docs-cleanup job will not be able to run when the branch gets
|
||||
# deleted (when merging the MR).
|
||||
- apk add --update openssl
|
||||
- wget https://gitlab.com/gitlab-org/gitlab-ce/raw/master/scripts/trigger-build-docs
|
||||
- chmod 755 trigger-build-docs
|
||||
services: []
|
||||
cache: {}
|
||||
dependencies: []
|
||||
artifacts: {}
|
||||
variables:
|
||||
SETUP_DB: "false"
|
||||
USE_BUNDLE_INSTALL: "false"
|
||||
cache: {}
|
||||
GIT_STRATEGY: none
|
||||
when: manual
|
||||
only:
|
||||
- branches
|
||||
|
@ -197,7 +206,7 @@ review-docs-deploy:
|
|||
url: http://preview-$CI_COMMIT_REF_SLUG.$DOCS_REVIEW_APPS_DOMAIN/$DOCS_GITLAB_REPO_SUFFIX
|
||||
on_stop: review-docs-cleanup
|
||||
script:
|
||||
- scripts/trigger-build-docs deploy
|
||||
- ./trigger-build-docs deploy
|
||||
|
||||
# Cleanup remote environment of gitlab-docs
|
||||
review-docs-cleanup:
|
||||
|
@ -207,7 +216,7 @@ review-docs-cleanup:
|
|||
name: review-docs/$CI_COMMIT_REF_NAME
|
||||
action: stop
|
||||
script:
|
||||
- scripts/trigger-build-docs cleanup
|
||||
- ./trigger-build-docs cleanup
|
||||
|
||||
# Retrieve knapsack and rspec_flaky reports
|
||||
retrieve-tests-metadata:
|
||||
|
|
184
CHANGELOG.md
|
@ -2,6 +2,190 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 10.0.1 (2017-09-23)
|
||||
|
||||
- [FIXED] Fix duplicate key errors in PostDeployMigrateUserExternalMailData migration.
|
||||
|
||||
## 10.0.0 (2017-09-22)
|
||||
|
||||
- [SECURITY] Upgrade brace-expansion NPM package due to security issue. !13665 (Markus Koller)
|
||||
- [REMOVED] Remove CI API v1.
|
||||
- [FIXED] Ensure correct visibility level options shown on all Project, Group, and Snippets forms. !13442
|
||||
- [FIXED] Fix the /projects/:id/repository/files/:file_path/raw endpoint to handle dots in the file_path. !13512 (mahcsig)
|
||||
- [FIXED] Merge request reference in merge commit changed to full reference. !13518 (haseebeqx)
|
||||
- [FIXED] Removes Sortable default scope. !13558
|
||||
- [FIXED] Wiki table of contents are now properly nested to reflect header level. !13650 (Akihiro Nakashima)
|
||||
- [FIXED] Improve bare project import: Allow subgroups, take default visibility level into account. !13670
|
||||
- [FIXED] Fix group and project search for anonymous users. !13745
|
||||
- [FIXED] Fix searching for files by path. !13798
|
||||
- [FIXED] Fix division by zero error in blame age mapping. !13803 (Jeff Stubler)
|
||||
- [FIXED] Fix incorrect date/time formatting on prometheus graphs. !13865
|
||||
- [FIXED] Changes the password change workflow for admins. !13901
|
||||
- [FIXED] API: Respect default group visibility when creating a group. !13903 (Robert Schilling)
|
||||
- [FIXED] Unescape HTML characters in Wiki title. !13942 (Jacopo Beschi @jacopo-beschi)
|
||||
- [FIXED] Make blob viewer for rich contents wider for mobile. !14011 (Takuya Noguchi)
|
||||
- [FIXED] Fix typo in the API Deploy Keys documentation page. !14014 (Vitaliy @blackst0ne Klachkov)
|
||||
- [FIXED] Hide admin link from default search results for non-admins. !14015
|
||||
- [FIXED] Fix problems sanitizing URLs with empty passwords. !14083
|
||||
- [FIXED] Fix stray OR in New Project page. !14096 (Robin Bobbitt)
|
||||
- [FIXED] Fix a wrong `X-Gitlab-Event` header when testing webhooks. !14108
|
||||
- [FIXED] Fix the diff file header from being html escaped for renamed files. !14121
|
||||
- [FIXED] Image attachments are properly displayed in notification emails again. !14161
|
||||
- [FIXED] Fixes the 500 errors caused by a race condition in GPG's tmp directory handling. !14194 (Alexis Reigel)
|
||||
- [FIXED] Fix MR ready to merge buttons/controls at mobile breakpoint. !14242
|
||||
- [FIXED] Fix Pipeline Triggers to show triggered label and predefined variables (e.g. CI_PIPELINE_TRIGGERED). !14244
|
||||
- [FIXED] Allow using newlines in pipeline email service recipients. !14250
|
||||
- [FIXED] Fix errors when moving issue with reference to a group milestone. !14294
|
||||
- [FIXED] Fix the "resolve discussion in a new issue" button. !14357
|
||||
- [FIXED] File uploaders do not perform hard check, only soft check.
|
||||
- [FIXED] Add to_project_id parameter to Move Issue via API example.
|
||||
- [FIXED] Update x/x discussions resolved checkmark icon to be green when all discussions resolved.
|
||||
- [FIXED] Fixed add diff note button not showing after deleting a comment.
|
||||
- [FIXED] Fix broken svg in jobs dropdown for success status.
|
||||
- [FIXED] Fix buttons with different height in merge request widget.
|
||||
- [FIXED] Removes disabled state from dashboard project button.
|
||||
- [FIXED] Better align fallback image emojis.
|
||||
- [FIXED] Remove focus styles from dropdown empty links.
|
||||
- [FIXED] Fix inconsistent spacing for edit buttons on issues and merge request page.
|
||||
- [FIXED] Fix edit merge request and issues button inconsistent letter casing.
|
||||
- [FIXED] Improve Import/Export memory usage.
|
||||
- [FIXED] Fix Import/Export issue to do with fork merge requests.
|
||||
- [FIXED] Fix invite by email address duplication.
|
||||
- [FIXED] Adds tooltip to the branch name and improves performance.
|
||||
- [FIXED] Disable GitLab Project Import Button if source disabled.
|
||||
- [FIXED] Migrate issues authored by deleted user to the Ghost user.
|
||||
- [FIXED] Fix new navigation wrapping and causing height to grow.
|
||||
- [FIXED] Normalize styles for empty state combo button.
|
||||
- [FIXED] Fix external link to Composer website.
|
||||
- [FIXED] Prevents jobs dropdown from closing in pipeline graph.
|
||||
- [FIXED] Include the `is_admin` field in the `GET /users/:id` API when current user is an admin.
|
||||
- [FIXED] Fix breadcrumbs container in issue boards.
|
||||
- [FIXED] Fix project feature being deleted when updating project with invalid visibility level.
|
||||
- [FIXED] Truncate milestone title if sidebar is collapsed.
|
||||
- [FIXED] Prevents rendering empty badges when request fails.
|
||||
- [FIXED] Fixes margins on the top buttons of the pipeline table.
|
||||
- [FIXED] Bump jira-ruby gem to 1.4.1 to fix issues with HTTP proxies.
|
||||
- [FIXED] Eliminate N+1 queries in loading discussions.json endpoint.
|
||||
- [FIXED] Eliminate N+1 queries referencing issues.
|
||||
- [FIXED] Remove unnecessary loading of discussions in `IssuesController#show`.
|
||||
- [FIXED] Fix errors thrown in merge request widget with external CI service/integration.
|
||||
- [FIXED] Do not show the Auto DevOps banner when the project has a .gitlab-ci.yml on master.
|
||||
- [FIXED] Reword job to pipeline to reflect what the graphs are really about.
|
||||
- [FIXED] Sort templates in the dropdown.
|
||||
- [FIXED] Fix Auto DevOps banner to be shown on empty projects.
|
||||
- [FIXED] Resolve Image onion skin + swipe does not work anymore.
|
||||
- [FIXED] Fix mini graph pipeline breakin in merge request view.
|
||||
- [FIXED] Fixed merge request changes bar jumping.
|
||||
- [FIXED] Improve migrations using triggers.
|
||||
- [FIXED] Fix ConvDev Index nav item and Monitoring submenu regression.
|
||||
- [DEPRECATED] Deprecate custom SSH client configuration for the git user. !13930
|
||||
- [CHANGED] allow all users to delete their account. !13636 (Jacopo Beschi @jacopo-beschi)
|
||||
- [CHANGED] Use full path of project's avatar in webhooks. !13649 (Vitaliy @blackst0ne Klachkov)
|
||||
- [CHANGED] Add filtered search to group merge requests dashboard. !13688 (Hiroyuki Sato)
|
||||
- [CHANGED] Fire hooks asynchronously when creating a new job to improve performance. !13734
|
||||
- [CHANGED] Improve performance for AutocompleteController#users.json. !13754 (Hiroyuki Sato)
|
||||
- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
|
||||
- [CHANGED] Support a multi-word fuzzy seach issues/merge requests on search bar. !13780 (Hiroyuki Sato)
|
||||
- [CHANGED] Default LDAP config "verify_certificates" to true for security. !13915
|
||||
- [CHANGED] "Share with group lock" now applies to subgroups, but owner can override setting on subgroups. !13944
|
||||
- [CHANGED] Make Gitaly PostUploadPack mandatory. !13953
|
||||
- [CHANGED] Remove project select dropdown from breadcrumb. !14010
|
||||
- [CHANGED] Redesign project feature permissions settings. !14062
|
||||
- [CHANGED] Document version Group Milestones API introduced.
|
||||
- [CHANGED] Finish migration to the new events setup.
|
||||
- [CHANGED] restyling of OAuth authorization confirmation. (Jacopo Beschi @jacopo-beschi)
|
||||
- [CHANGED] Added support for specific labels and colors.
|
||||
- [CHANGED] Move "Move issue" controls to right-sidebar.
|
||||
- [CHANGED] Remove pages settings when not available.
|
||||
- [CHANGED] Allow all AutoDevOps banners to be turned off.
|
||||
- [CHANGED] Update Rails project template to use Postgresql by default.
|
||||
- [CHANGED] Added support the multiple time series for prometheus monitoring.
|
||||
- [ADDED] API: Respect the "If-Unmodified-Since" header when delting a resource. !9621 (Robert Schilling)
|
||||
- [ADDED] Protected runners. !13194
|
||||
- [ADDED] Add support for copying permalink to notes via more actions dropdown. !13299
|
||||
- [ADDED] Add API support for wiki pages. !13372 (Vitaliy @blackst0ne Klachkov)
|
||||
- [ADDED] Add a `Last 7 days` option for Cycle Analytics view. !13443 (Mehdi Lahmam (@mehlah))
|
||||
- [ADDED] inherits milestone and labels when a merge request is created from issue. !13461 (haseebeqx)
|
||||
- [ADDED] Add 'from commit' information to cherry-picked commits. !13475 (Saverio Miroddi)
|
||||
- [ADDED] Add an option to list only archived projects. !13492 (Mehdi Lahmam (@mehlah))
|
||||
- [ADDED] Extend API: Pipeline Schedule Variable. !13653
|
||||
- [ADDED] Add settings for minimum SSH key strength and allowed key type. !13712 (Cory Hinshaw)
|
||||
- [ADDED] Add div id to the readme in the project overview. !13735 (Riccardo Padovani @rpadovani)
|
||||
- [ADDED] Add CI/CD job predefined variables with user name and login. !13824
|
||||
- [ADDED] API: Add GPG key management. !13828 (Robert Schilling)
|
||||
- [ADDED] Add CI/CD active kubernetes job policy. !13849
|
||||
- [ADDED] Add dropdown to Projects nav item. !13866
|
||||
- [ADDED] Allow users and administrator to configure Auto-DevOps. !13923
|
||||
- [ADDED] Implement `failure_reason` on `ci_builds`. !13937
|
||||
- [ADDED] Add branch existence check to the APIv4 branches via HEAD request. !13979 (Vitaliy @blackst0ne Klachkov)
|
||||
- [ADDED] Add quick submission on user settings page. !14007 (Vitaliy @blackst0ne Klachkov)
|
||||
- [ADDED] Add my_reaction_emoji param to /issues and /merge_requests API. !14016 (Hiroyuki Sato)
|
||||
- [ADDED] Make it possible to download a single job artifact file using the API. !14027
|
||||
- [ADDED] Add repository toggle for automatically resolving outdated diff discussions. !14053 (AshleyDumaine)
|
||||
- [ADDED] Scripts to detect orphaned repositories. !14204
|
||||
- [ADDED] Created callout for auto devops.
|
||||
- [ADDED] Add option in preferences to change navigation theme color.
|
||||
- [ADDED] Add JSON logger in `log/api_json.log` for Grape API endpoints.
|
||||
- [ADDED] Add CI_PIPELINE_SOURCE variable on CI Jobs.
|
||||
- [ADDED] Changed message and title on the 404 page. (Branka Martinovic)
|
||||
- [ADDED] Handle if Auto DevOps domain is not set in project settings.
|
||||
- [ADDED] Add collapsable sections for Pipeline Settings.
|
||||
- [OTHER] Add badge for dependency status. !13588 (Markus Koller)
|
||||
- [OTHER] Migration to remove pending delete projects with non-existing namespace. !13598
|
||||
- [OTHER] Bump rouge to v2.2.0. !13633
|
||||
- [OTHER] Fix repository equality check and avoid fetching ref if the commit is already available. This affects merge request creation performance. !13685
|
||||
- [OTHER] Replace 'source/search_code.feature' spinach test with an rspec analog. !13697 (blackst0ne)
|
||||
- [OTHER] Remove unwanted refs after importing a project. !13766
|
||||
- [OTHER] Never wait for sidekiq jobs when creating projects. !13775
|
||||
- [OTHER] Gitaly feature toggles are on by default in development. !13802
|
||||
- [OTHER] Remove `is_` prefix from predicate method names. !13810 (Maxim Rydkin)
|
||||
- [OTHER] Update 'Using Docker images' documentation. !13848
|
||||
- [OTHER] Update gpg documentation with gpg2. !13851 (M M Arif)
|
||||
- [OTHER] Replace 'project/star.feature' spinach test with an rspec analog. !13855 (Vitaliy @blackst0ne Klachkov)
|
||||
- [OTHER] Replace 'project/user_lookup.feature' spinach test with an rspec analog. !13863 (Vitaliy @blackst0ne Klachkov)
|
||||
- [OTHER] Bump rouge to v2.2.1. !13887
|
||||
- [OTHER] Add documentation for PlantUML in reStructuredText. !13900 (Markus Koller)
|
||||
- [OTHER] Decrease ABC threshold to 55.25. !13904 (Maxim Rydkin)
|
||||
- [OTHER] Decrease Cyclomatic Complexity threshold to 14. !13972 (Maxim Rydkin)
|
||||
- [OTHER] Update documentation for confidential issue. !14117
|
||||
- [OTHER] Remove redundant WHERE from event queries.
|
||||
- [OTHER] Memoize the latest builds of a pipeline on a project's homepage.
|
||||
- [OTHER] Re-use issue/MR counts for the pagination system.
|
||||
- [OTHER] Memoize pipelines for project download buttons.
|
||||
- [OTHER] Reorganize indexes for the "deployments" table.
|
||||
- [OTHER] Improves markdown rendering performance for commit lists.
|
||||
- [OTHER] Only update the sidebar count caches when needed.
|
||||
- [OTHER] Improves performance of vue code by using vue files and moving svg out of data function in pipeline schedule callout.
|
||||
- [OTHER] Rework how recent push events are retrieved.
|
||||
- [OTHER] Restyle dropdown menus to make them look consistent.
|
||||
- [OTHER] Upgrade grape to 1.0.
|
||||
- [OTHER] Add usage data for Auto DevOps.
|
||||
- [OTHER] Cache the number of open issues and merge requests.
|
||||
- [OTHER] Constrain environment deployments to project IDs.
|
||||
- [OTHER] Eager load namespace owners for project dashboards.
|
||||
- [OTHER] Add description template examples to documentation.
|
||||
- [OTHER] Disallow NULL values for environments.project_id.
|
||||
- Add my reaction filter to search bar. !12962 (Hiroyuki Sato)
|
||||
- Generalize profile updates from providers. !12968 (Alexandros Keramidas)
|
||||
- Validate PO-files in static analysis. !13000
|
||||
- First-time contributor badge. !13143 (Micaël Bergeron <micaelbergeron@gmail.com>)
|
||||
- Add option to disable project export on instance. !13211 (Robin Bobbitt)
|
||||
- Hashed Storage support for Repositories (EXPERIMENTAL). !13246
|
||||
- Added tests for commits API unauthenticated user and public/private project. !13287 (Jacopo Beschi @jacopo-beschi)
|
||||
- Fix CI_PROJECT_PATH_SLUG slugify. !13350 (Ivan Chernov)
|
||||
- Add checks for branch existence before changing HEAD. !13359 (Vitaliy @blackst0ne Klachkov)
|
||||
- Fix the alignment of line numbers to lines of code in code viewer. !13403 (Trevor Flynn)
|
||||
- Allow users to move issues to other projects using a / command. !13436 (Manolis Mavrofidis)
|
||||
- Bumps omniauth-ldap gem version to 2.0.4. !13465
|
||||
- Implement the Gitaly RefService::RefExists endpoint. !13528 (Andrew Newdigate)
|
||||
- Changed all font-weight values to 400 and 600 and introduced 2 variables to manage them.
|
||||
- Simplify checking if objects exist code in new issaubles workers.
|
||||
- Present enqueued merge jobs as Merging as well.
|
||||
- Don't escape html entities in InlineDiffMarkdownMarker.
|
||||
- Move ConvDev Index location to after Cohorts.
|
||||
- Added type to CHANGELOG entries. (Jacopo Beschi @jacopo-beschi)
|
||||
- [BUGIFX] Improves subgroup creation permissions. !13418
|
||||
|
||||
## 9.5.5 (2017-09-18)
|
||||
|
||||
- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.38.0
|
||||
0.40.0
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.9.0
|
||||
5.9.2
|
||||
|
|
4
Gemfile
|
@ -26,7 +26,7 @@ gem 'doorkeeper', '~> 4.2.0'
|
|||
gem 'doorkeeper-openid_connect', '~> 1.1.0'
|
||||
gem 'omniauth', '~> 1.4.2'
|
||||
gem 'omniauth-auth0', '~> 1.4.1'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.9'
|
||||
gem 'omniauth-cas3', '~> 1.1.4'
|
||||
gem 'omniauth-facebook', '~> 4.0.0'
|
||||
gem 'omniauth-github', '~> 1.1.1'
|
||||
|
@ -128,7 +128,7 @@ gem 'asciidoctor-plantuml', '0.0.7'
|
|||
gem 'rouge', '~> 2.0'
|
||||
gem 'truncato', '~> 0.7.9'
|
||||
gem 'bootstrap_form', '~> 2.7.0'
|
||||
gem 'nokogiri', '~> 1.8.0'
|
||||
gem 'nokogiri', '~> 1.8.1'
|
||||
|
||||
# Diffs
|
||||
gem 'diffy', '~> 3.1.0'
|
||||
|
|
18
Gemfile.lock
|
@ -195,7 +195,7 @@ GEM
|
|||
factory_girl_rails (4.7.0)
|
||||
factory_girl (~> 4.7.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.12.1)
|
||||
faraday (0.12.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday_middleware (0.11.0.1)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
|
@ -483,7 +483,7 @@ GEM
|
|||
mime-types (2.99.3)
|
||||
mimemagic (0.3.0)
|
||||
mini_mime (0.1.4)
|
||||
mini_portile2 (2.2.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.7.0)
|
||||
mmap2 (2.2.7)
|
||||
mousetrap-rails (1.4.6)
|
||||
|
@ -497,8 +497,8 @@ GEM
|
|||
net-ldap (0.16.0)
|
||||
net-ssh (4.1.0)
|
||||
netrc (0.11.0)
|
||||
nokogiri (1.8.0)
|
||||
mini_portile2 (~> 2.2.0)
|
||||
nokogiri (1.8.1)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
numerizer (0.1.1)
|
||||
oauth (0.5.1)
|
||||
oauth2 (1.4.0)
|
||||
|
@ -517,10 +517,10 @@ GEM
|
|||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-authentiq (0.3.1)
|
||||
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
||||
omniauth-azure-oauth2 (0.0.6)
|
||||
omniauth-azure-oauth2 (0.0.9)
|
||||
jwt (~> 1.0)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-oauth2 (~> 1.4)
|
||||
omniauth-cas3 (1.1.4)
|
||||
addressable (~> 2.3)
|
||||
nokogiri (~> 1.7, >= 1.7.1)
|
||||
|
@ -546,7 +546,7 @@ GEM
|
|||
omniauth-oauth (1.1.0)
|
||||
oauth
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (1.3.1)
|
||||
omniauth-oauth2 (1.4.0)
|
||||
oauth2 (~> 1.0)
|
||||
omniauth (~> 1.2)
|
||||
omniauth-oauth2-generic (0.2.2)
|
||||
|
@ -1064,14 +1064,14 @@ DEPENDENCIES
|
|||
mysql2 (~> 0.4.5)
|
||||
net-ldap
|
||||
net-ssh (~> 4.1.0)
|
||||
nokogiri (~> 1.8.0)
|
||||
nokogiri (~> 1.8.1)
|
||||
oauth2 (~> 1.4)
|
||||
octokit (~> 4.6.2)
|
||||
oj (~> 2.17.4)
|
||||
omniauth (~> 1.4.2)
|
||||
omniauth-auth0 (~> 1.4.1)
|
||||
omniauth-authentiq (~> 0.3.1)
|
||||
omniauth-azure-oauth2 (~> 0.0.6)
|
||||
omniauth-azure-oauth2 (~> 0.0.9)
|
||||
omniauth-cas3 (~> 1.1.4)
|
||||
omniauth-facebook (~> 4.0.0)
|
||||
omniauth-github (~> 1.1.1)
|
||||
|
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1 @@
|
|||
{"iconCount":134,"icons":["abuse","account","admin","angle-double-left","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-right","assignee","bold","book","branch","calendar","cancel","chevron-down","chevron-left","chevron-right","chevron-up","clock","code","comment-dots","comment-next","comment","comments","commit","credit-card","disk","doc_code","doc_image","doc_text","download","duplicate","earth","eye-slash","eye","file-additions","file-deletion","file-modified","filter","folder","fork","geo-nodes","git-merge","group","history","home","hook","issue-block","issue-child","issue-close","issue-duplicate","issue-new","issue-open-m","issue-open","issue-parent","issues","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","merge-request-close-m","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil","pipeline","play","plus-square-o","plus-square","plus","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","star-o","star","stop","talic","task-done","template","thump-down","thump-up","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
|
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 150"><g fill="none" fill-rule="evenodd"><g fill="#e5e5e5" transform="translate(0 102)"><rect width="74" height="4" x="34" y="21" opacity=".5" rx="2"/><path d="M152 23c0-1.105.887-2 1.998-2h4c1.104 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4A1.994 1.994 0 0 1 152 23m14 0c0-1.105.887-2 1.998-2h4c1.104 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4A1.994 1.994 0 0 1 166 23m14 0c0-1.105.887-2 1.998-2h4c1.104 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4A1.994 1.994 0 0 1 180 23m14 0c0-1.105.887-2 1.998-2h4c1.104 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4A1.994 1.994 0 0 1 194 23m14 0c0-1.105.887-2 1.998-2h4c1.104 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4A1.994 1.994 0 0 1 208 23"/></g><g fill="#31af64"><path fill-rule="nonzero" d="M19 144c-10.493 0-19-8.507-19-19s8.507-19 19-19 19 8.507 19 19-8.507 19-19 19m0-4c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15-8.284 0-15 6.716-15 15 0 8.284 6.716 15 15 15"/><path d="M17.07 127.02l-2.829-2.829a1.995 1.995 0 0 0-2.828 0 1.995 1.995 0 0 0 0 2.828l4.243 4.243a1.995 1.995 0 0 0 2.822.006l7.79-7.79a1.997 1.997 0 0 0-.006-2.823 1.992 1.992 0 0 0-2.823-.006l-6.37 6.37"/></g><g fill="#e52c5a"><path fill-rule="nonzero" d="M126 149.5c-12.979 0-23.5-10.521-23.5-23.5s10.521-23.5 23.5-23.5 23.5 10.521 23.5 23.5-10.521 23.5-23.5 23.5m0-5c10.217 0 18.5-8.283 18.5-18.5s-8.283-18.5-18.5-18.5-18.5 8.283-18.5 18.5 8.283 18.5 18.5 18.5"/><path d="M130.24 126l2.833-2.833a3 3 0 0 0-4.243-4.243l-2.833 2.833-2.833-2.833a3 3 0 0 0-4.243 4.243l2.833 2.833-2.833 2.833a3 3 0 0 0 4.243 4.243l2.833-2.833 2.833 2.833a3 3 0 0 0 4.243-4.243L130.24 126"/></g><path fill="#e5e5e5" fill-rule="nonzero" d="M236 139c-7.732 0-14-6.268-14-14s6.268-14 14-14 14 6.268 14 14-6.268 14-14 14m0-4c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10"/><g transform="translate(73 4)"><path stroke="#e5e5e5" stroke-width="4" d="M64.82 76H98c4.419 0 8-3.579 8-7.99V7.99C106 3.577 102.417 0 98 0H8.009c-4.419 0-8 3.579-8 7.99v60.02c0 4.413 3.583 7.99 8 7.99h31.935l9.263 9.855a4.357 4.357 0 0 0 6.354 0L64.824 76"/><rect width="18" height="6" x="11" y="19" fill="#fc8a51" rx="3"/><rect width="18" height="6" x="35" y="35" fill="#e52c5a" rx="3"/><rect width="18" height="6" x="29" y="51" fill="#e5e5e5" rx="3"/><rect width="12" height="6" x="35" y="19" fill="#fde5d8" rx="3"/><rect width="12" height="6" x="53" y="51" fill="#e52c5a" rx="3"/><rect width="12" height="6" x="11" y="51" fill="#b5a7dd" rx="3"/><rect width="18" height="6" x="77" y="19" fill="#fc8a51" rx="3"/><rect width="18" height="6" x="11" y="35" fill="#fde5d8" rx="3"/><rect width="6" height="6" x="53" y="19" fill="#e52c5a" rx="3"/><g fill="#fde5d8"><rect width="6" height="6" x="65" y="19" rx="3"/><rect width="6" height="6" x="71" y="35" rx="3"/></g><rect width="6" height="6" x="59" y="35" fill="#e52c5a" rx="3"/></g><path fill="#6b4fbb" fill-rule="nonzero" d="M151.869 77.403c-13.26 9.264-31.649 7.977-43.484-3.858-13.279-13.279-13.279-34.806 0-48.084 13.278-13.278 34.805-13.278 48.083 0 11.836 11.836 13.118 30.23 3.858 43.485.133.111.262.229.387.354l15.556 15.555a6.004 6.004 0 0 1 0 8.486 5.997 5.997 0 0 1-8.486 0l-15.555-15.556a6.051 6.051 0 0 1-.355-.387m-1.06-9.512c10.154-10.154 10.154-26.617 0-36.77-10.153-10.154-26.616-10.154-36.77 0-10.153 10.153-10.153 26.616 0 36.77 10.154 10.153 26.617 10.153 36.77 0"/></g></svg>
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 6.5 KiB |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="68" viewBox="181 0 116 68"><g fill="none" fill-rule="evenodd" transform="translate(182)"><rect width="78" height="34" x="37" y="34" fill="#FAFAFA" rx="3"/><rect width="78" height="34" x="31" y="28" fill="#FFF" stroke="#EEE" stroke-width="4" stroke-linecap="round" rx="3"/><path fill="#FFF" stroke="#FC6D26" stroke-width="3" d="M34 35.8c-.6 0-1.4 0-1.8.4L29 38.8c-1 .7-1.7.4-2-.7l-.6-4c0-.5-.5-1.2-1-1.5L22 30.2c-1-.6-1-1.5 0-2l3.7-2c.5-.2 1-.8 1.2-1.3l1-4.2c.3-1 1-1.3 2-.5l3 3c.3.3 1 .6 1.6.6l4.2-.3c1 0 1.5.7 1 1.7L38 29c-.3.6-.3 1.4 0 2l1.3 3.8c.4 1 0 1.8-1.2 1.6l-4-.6z" stroke-linecap="round"/><path fill="#FDE5D8" d="M51.6 14.3c-.2-.2-.8-.4-1-.3l-2.8.5c-.7 0-1-.4-.8-1l1-2.8V9.5L46.6 7c-.3-.7 0-1.2.8-1h2.7c.3 0 .8-.2 1-.5l2-2c.6-.5 1-.4 1.3.3l.7 2.8c0 .3.4.8.7 1l2.3 1.2c.7.3.7 1 0 1.3l-2.2 1.7-.6 1-.4 3c-.2.6-.7.8-1.3.4l-2-1.7zM5.4 43.2c-.2-.2-.5-.2-.7-.2l-1.8.3c-.6 0-1-.2-.7-.7l.7-1.8V40l-1-1.7c0-.4 0-.7.6-.7h1.8c.3 0 .6 0 .8-.2L6.5 36c.3-.3.7-.2.8.2l.5 2 .5.5 1.6.8c.3.2.3.7 0 1l-1.6 1c-.2 0-.4.4-.4.7l-.4 2c0 .3-.4.5-.8.2l-1.4-1.2zM10.4 9.2C10.2 9 10 9 9.7 9L8 9.3c-.6 0-1-.2-.7-.7L8 6.8V6L7 4.3c0-.4 0-.7.6-.7h1.8c.3 0 .6 0 .8-.2L11.5 2c.3-.3.7-.2.8.2l.5 2 .5.5 1.6.8c.3.2.3.7 0 1l-1.6 1c-.2 0-.4.4-.4.7l-.4 2c0 .3-.4.5-.8.2l-1.4-1.2z"/><rect width="52" height="4" x="43" y="38" fill="#EEE" rx="2"/><rect width="36" height="4" x="43" y="48" fill="#EEE" rx="2"/></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="68" viewBox="181 0 116 68"><g fill="none" fill-rule="evenodd" transform="translate(182)"><rect width="78" height="34" x="37" y="34" fill="#FAFAFA" rx="3"/><rect width="78" height="34" x="31" y="28" fill="#FFF" stroke="#EEE" stroke-width="4" stroke-linecap="round" rx="3"/><path fill="#FFF" stroke="#FC6D26" stroke-width="3" d="M34 35.8c-.6 0-1.4 0-1.8.4L29 38.8c-1 .7-1.7.4-2-.7l-.6-4c0-.5-.5-1.2-1-1.5L22 30.2c-1-.6-1-1.5 0-2l3.7-2c.5-.2 1-.8 1.2-1.3l1-4.2c.3-1 1-1.3 2-.5l3 3c.3.3 1 .6 1.6.6l4.2-.3c1 0 1.5.7 1 1.7L38 29c-.3.6-.3 1.4 0 2l1.3 3.8c.4 1 0 1.8-1.2 1.6l-4-.6z" stroke-linecap="round"/><path fill="#FDE5D8" d="M51.6 14.3c-.2-.2-.8-.4-1-.3l-2.8.5c-.7 0-1-.4-.8-1l1-2.8V9.5L46.6 7c-.3-.7 0-1.2.8-1h2.7c.3 0 .8-.2 1-.5l2-2c.6-.5 1-.4 1.3.3l.7 2.8c0 .3.4.8.7 1l2.3 1.2c.7.3.7 1 0 1.3l-2.2 1.7-.6 1-.4 3c-.2.6-.7.8-1.3.4l-2-1.7zM5.4 43.2c-.2-.2-.5-.2-.7-.2l-1.8.3c-.6 0-1-.2-.7-.7l.7-1.8V40l-1-1.7c0-.4 0-.7.6-.7h1.8c.3 0 .6 0 .8-.2L6.5 36c.3-.3.7-.2.8.2l.5 2 .5.5 1.6.8c.3.2.3.7 0 1l-1.6 1c-.2 0-.4.4-.4.7l-.4 2c0 .3-.4.5-.8.2l-1.4-1.2zm5-34C10.2 9 10 9 9.7 9L8 9.3c-.6 0-1-.2-.7-.7L8 6.8V6L7 4.3c0-.4 0-.7.6-.7h1.8c.3 0 .6 0 .8-.2L11.5 2c.3-.3.7-.2.8.2l.5 2 .5.5 1.6.8c.3.2.3.7 0 1l-1.6 1c-.2 0-.4.4-.4.7l-.4 2c0 .3-.4.5-.8.2l-1.4-1.2z"/><rect width="52" height="4" x="43" y="38" fill="#EEE" rx="2"/><rect width="36" height="4" x="43" y="48" fill="#EEE" rx="2"/></g></svg>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 293 216"><g fill="none" fill-rule="evenodd"><g transform="rotate(-5 211.388 -693.89)"><rect width="163.6" height="200" x=".2" fill="#FFF" stroke="#EEE" stroke-width="3" stroke-linecap="round" stroke-dasharray="6 9" rx="6"/><g transform="translate(24 38)"><path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/><path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/><rect width="76" height="3" x="40" y="11" fill="#6B4FBB" opacity=".5" rx="1.5"/><rect width="43" height="3" x="40" y="21" fill="#6B4FBB" opacity=".5" rx="1.5"/></g><g transform="translate(24 83)"><path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/><path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/><rect width="76" height="3" x="40" y="11" fill="#B5A7DD" rx="1.5"/><rect width="43" height="3" x="40" y="21" fill="#B5A7DD" rx="1.5"/></g><g transform="translate(24 130)"><path fill="#FC6D26" d="M18.2 14l-4-3.8c-.4-.6-1.4-.6-2 0-.6.6-.6 1.5 0 2l5 5c.3.4.6.5 1 .5s.8 0 1-.4L28 8.8c.6-.6.6-1.5 0-2-.6-.7-1.6-.7-2 0L18 14z"/><path stroke="#6B4FBB" stroke-width="3" d="M27 23.3V27c0 2.3-1.7 4-4 4H4c-2.3 0-4-1.7-4-4V8c0-2.3 1.7-4 4-4h3.8" stroke-linecap="round"/><rect width="76" height="3" x="40" y="11" fill="#B5A7DD" rx="1.5"/><rect width="43" height="3" x="40" y="21" fill="#B5A7DD" rx="1.5"/></g></g><path fill="#FFCE29" d="M30 11l-1.8 4-2-4-4-1.8 4-2 2-4 2 4 4 2M286 60l-2.7 6.3-3-6-6-3 6-3 3-6 2.8 6.2 6.6 2.8M263 97l-2 4-2-4-4-2 4-2 2-4 2 4 4 2M12 85l-2.7 6.3-3-6-6-3 6-3 3-6 2.8 6.2 6.6 2.8"/></g></svg>
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 5.7 KiB |
|
@ -24,6 +24,9 @@ const categoryLabelMap = {
|
|||
flags: 'Flags',
|
||||
};
|
||||
|
||||
const IS_VISIBLE = 'is-visible';
|
||||
const IS_RENDERED = 'is-rendered';
|
||||
|
||||
class AwardsHandler {
|
||||
constructor(emoji) {
|
||||
this.emoji = emoji;
|
||||
|
@ -51,7 +54,7 @@ class AwardsHandler {
|
|||
if (!$target.closest('.emoji-menu').length) {
|
||||
if ($('.emoji-menu').is(':visible')) {
|
||||
$('.js-add-award.is-active').removeClass('is-active');
|
||||
$('.emoji-menu').removeClass('is-visible');
|
||||
this.hideMenuElement($('.emoji-menu'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -88,12 +91,12 @@ class AwardsHandler {
|
|||
if ($menu.length) {
|
||||
if ($menu.is('.is-visible')) {
|
||||
$addBtn.removeClass('is-active');
|
||||
$menu.removeClass('is-visible');
|
||||
this.hideMenuElement($menu);
|
||||
$('.js-emoji-menu-search').blur();
|
||||
} else {
|
||||
$addBtn.addClass('is-active');
|
||||
this.positionMenu($menu, $addBtn);
|
||||
$menu.addClass('is-visible');
|
||||
this.showMenuElement($menu);
|
||||
$('.js-emoji-menu-search').focus();
|
||||
}
|
||||
} else {
|
||||
|
@ -103,7 +106,7 @@ class AwardsHandler {
|
|||
$addBtn.removeClass('is-loading');
|
||||
this.positionMenu($createdMenu, $addBtn);
|
||||
return setTimeout(() => {
|
||||
$createdMenu.addClass('is-visible');
|
||||
this.showMenuElement($createdMenu);
|
||||
$('.js-emoji-menu-search').focus();
|
||||
}, 200);
|
||||
});
|
||||
|
@ -241,7 +244,8 @@ class AwardsHandler {
|
|||
if (isInIssuePage() && !isMainAwardsBlock) {
|
||||
const id = votesBlock.attr('id').replace('note_', '');
|
||||
|
||||
$('.emoji-menu').removeClass('is-visible');
|
||||
this.hideMenuElement($('.emoji-menu'));
|
||||
|
||||
$('.js-add-award.is-active').removeClass('is-active');
|
||||
const toggleAwardEvent = new CustomEvent('toggleAward', {
|
||||
detail: {
|
||||
|
@ -261,7 +265,8 @@ class AwardsHandler {
|
|||
return typeof callback === 'function' ? callback() : undefined;
|
||||
});
|
||||
|
||||
$('.emoji-menu').removeClass('is-visible');
|
||||
this.hideMenuElement($('.emoji-menu'));
|
||||
|
||||
return $('.js-add-award.is-active').removeClass('is-active');
|
||||
}
|
||||
|
||||
|
@ -529,6 +534,33 @@ class AwardsHandler {
|
|||
return $matchingElements.closest('li').clone();
|
||||
}
|
||||
|
||||
/* showMenuElement and hideMenuElement are performance optimizations. We use
|
||||
* opacity to show/hide the emoji menu, because we can animate it. But opacity
|
||||
* leaves hidden elements in the render tree, which is unacceptable given the number
|
||||
* of emoji elements in the emoji menu (5k+). To get the best of both worlds, we separately
|
||||
* apply IS_RENDERED to add/remove the menu from the render tree and IS_VISIBLE to animate
|
||||
* the menu being opened and closed. */
|
||||
|
||||
showMenuElement($emojiMenu) {
|
||||
$emojiMenu.addClass(IS_RENDERED);
|
||||
|
||||
// enqueues animation as a microtask, so it begins ASAP once IS_RENDERED added
|
||||
return Promise.resolve()
|
||||
.then(() => $emojiMenu.addClass(IS_VISIBLE));
|
||||
}
|
||||
|
||||
hideMenuElement($emojiMenu) {
|
||||
$emojiMenu.on(transitionEndEventString, (e) => {
|
||||
if (e.currentTarget === e.target) {
|
||||
$emojiMenu
|
||||
.removeClass(IS_RENDERED)
|
||||
.off(transitionEndEventString);
|
||||
}
|
||||
});
|
||||
|
||||
$emojiMenu.removeClass(IS_VISIBLE);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.eventListeners.forEach((entry) => {
|
||||
entry.element.off.call(entry.element, ...entry.args);
|
||||
|
|
|
@ -8,11 +8,11 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
|
|||
return ModalStore.store;
|
||||
},
|
||||
props: {
|
||||
image: {
|
||||
newIssuePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
newIssuePath: {
|
||||
emptyStateSvg: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
@ -42,7 +42,7 @@ gl.issueBoards.ModalEmptyState = Vue.extend({
|
|||
<section class="empty-state">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-sm-push-6">
|
||||
<aside class="svg-content" v-html="image"></aside>
|
||||
<aside class="svg-content"><img :src="emptyStateSvg"/></aside>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-sm-pull-6">
|
||||
<div class="text-content">
|
||||
|
|
|
@ -12,11 +12,11 @@ const ModalStore = gl.issueBoards.ModalStore;
|
|||
|
||||
gl.issueBoards.IssuesModal = Vue.extend({
|
||||
props: {
|
||||
blankStateImage: {
|
||||
newIssuePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
newIssuePath: {
|
||||
emptyStateSvg: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
@ -150,14 +150,14 @@ gl.issueBoards.IssuesModal = Vue.extend({
|
|||
:label-path="labelPath">
|
||||
</modal-header>
|
||||
<modal-list
|
||||
:image="blankStateImage"
|
||||
:issue-link-base="issueLinkBase"
|
||||
:root-path="rootPath"
|
||||
:empty-state-svg="emptyStateSvg"
|
||||
v-if="!loading && showList && !filterLoading"></modal-list>
|
||||
<empty-state
|
||||
v-if="showEmptyState"
|
||||
:image="blankStateImage"
|
||||
:new-issue-path="newIssuePath"></empty-state>
|
||||
:new-issue-path="newIssuePath"
|
||||
:empty-state-svg="emptyStateSvg"></empty-state>
|
||||
<section
|
||||
class="add-issues-list text-center"
|
||||
v-if="loading || filterLoading">
|
||||
|
|
|
@ -15,7 +15,7 @@ gl.issueBoards.ModalList = Vue.extend({
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
image: {
|
||||
emptyStateSvg: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
@ -119,8 +119,8 @@ gl.issueBoards.ModalList = Vue.extend({
|
|||
class="empty-state add-issues-empty-state-filter text-center"
|
||||
v-if="issuesCount > 0 && issues.length === 0">
|
||||
<div
|
||||
class="svg-content"
|
||||
v-html="image">
|
||||
class="svg-content">
|
||||
<img :src="emptyStateSvg"/>
|
||||
</div>
|
||||
<div class="text-content">
|
||||
<h4>
|
||||
|
|
|
@ -35,6 +35,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
propsData: {
|
||||
endpoint: pipelineTableViewEl.dataset.endpoint,
|
||||
helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
|
||||
emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
|
||||
errorStateSvgPath: pipelineTableViewEl.dataset.errorStateSvgPath,
|
||||
autoDevopsHelpPath: pipelineTableViewEl.dataset.helpAutoDevopsPath,
|
||||
},
|
||||
}).$mount();
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
emptyStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
errorStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
mixins: [
|
||||
pipelinesMixin,
|
||||
|
@ -87,10 +95,12 @@
|
|||
<empty-state
|
||||
v-if="shouldRenderEmptyState"
|
||||
:help-page-path="helpPagePath"
|
||||
:empty-state-svg-path="emptyStateSvgPath"
|
||||
/>
|
||||
|
||||
<error-state
|
||||
v-if="shouldRenderErrorState"
|
||||
:error-state-svg-path="errorStateSvgPath"
|
||||
/>
|
||||
|
||||
<div
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
export default {
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<span v-if="count === 50" class="events-info pull-right">
|
||||
<i class="fa fa-warning has-tooltip"
|
||||
aria-hidden="true"
|
||||
:title="n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)"
|
||||
data-placement="top"></i>
|
||||
{{ n__('Showing %d event', 'Showing %d events', 50) }}
|
||||
</span>
|
||||
`,
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
<script>
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span v-if="count === 50" class="events-info pull-right">
|
||||
<i
|
||||
class="fa fa-warning"
|
||||
v-tooltip
|
||||
aria-hidden="true"
|
||||
:title="n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)"
|
||||
data-placement="top"></i>
|
||||
{{ n__('Showing %d event', 'Showing %d events', 50) }}
|
||||
</span>
|
||||
</template>
|
|
@ -1,51 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageCodeComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,53 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(issue, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||
<h5 class="item-title issue-title">
|
||||
<a class="issue-title" :href="issue.url">
|
||||
{{ issue.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="issue.author.webUrl" class="issue-author-link">
|
||||
{{ issue.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="issue.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageIssueComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="issue in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||
<h5 class="item-title issue-title">
|
||||
<a class="issue-title" :href="issue.url">
|
||||
{{ issue.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="issue.author.webUrl" class="issue-author-link">
|
||||
{{ issue.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="issue.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -1,53 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconCommit from '../svg/icon_commit.svg';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StagePlanComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
data() {
|
||||
return { iconCommit };
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="commit in items" class="stage-event-item">
|
||||
<div class="item-details item-conmmit-component">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="commit.author.avatarUrl"/>
|
||||
<h5 class="item-title commit-title">
|
||||
<a :href="commit.commitUrl">
|
||||
{{ commit.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<span>
|
||||
{{ s__('FirstPushedBy|First') }}
|
||||
<span class="commit-icon">${iconCommit}</span>
|
||||
<a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{ commit.shortSha }}</a>
|
||||
{{ s__('FirstPushedBy|pushed by') }}
|
||||
<a :href="commit.author.webUrl" class="commit-author-link">
|
||||
{{ commit.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="commit.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,56 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconCommit from '../svg/icon_commit.svg';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
computed: {
|
||||
iconCommit() {
|
||||
return iconCommit;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(commit, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item">
|
||||
<div class="item-details item-conmmit-component">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="commit.author.avatarUrl"/>
|
||||
<h5 class="item-title commit-title">
|
||||
<a :href="commit.commitUrl">
|
||||
{{ commit.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<span>
|
||||
{{ s__('FirstPushedBy|First') }}
|
||||
<span class="commit-icon" v-html="iconCommit"></span>
|
||||
<a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{ commit.shortSha }}</a>
|
||||
{{ s__('FirstPushedBy|pushed by') }}
|
||||
<a :href="commit.author.webUrl" class="commit-author-link">
|
||||
{{ commit.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="commit.totalTime" />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageProductionComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="issue in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||
<h5 class="item-title issue-title">
|
||||
<a class="issue-title" :href="issue.url">
|
||||
{{ issue.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="issue.author.webUrl" class="issue-author-link">
|
||||
{{ issue.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="issue.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -1,62 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageReviewComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
<template v-if="mergeRequest.state === 'closed'">
|
||||
<span class="merge-request-state">
|
||||
<i class="fa fa-ban"></i>
|
||||
{{ mergeRequest.state.toUpperCase() }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="merge-request-branch" v-if="mergeRequest.branch">
|
||||
<i class= "fa fa-code-fork"></i>
|
||||
<a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,62 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(mergeRequest, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||
<h5 class="item-title merge-merquest-title">
|
||||
<a :href="mergeRequest.url">
|
||||
{{ mergeRequest.title }}
|
||||
</a>
|
||||
</h5>
|
||||
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a>
|
||||
·
|
||||
<span>
|
||||
{{ s__('OpenedNDaysAgo|Opened') }}
|
||||
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
|
||||
</span>
|
||||
<span>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{ mergeRequest.author.name }}</a>
|
||||
</span>
|
||||
<template v-if="mergeRequest.state === 'closed'">
|
||||
<span class="merge-request-state">
|
||||
<i class="fa fa-ban"></i>
|
||||
{{ mergeRequest.state.toUpperCase() }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="merge-request-branch" v-if="mergeRequest.branch">
|
||||
<i class= "fa fa-code-fork"></i>
|
||||
<a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="mergeRequest.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
|
@ -1,53 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageStagingComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
data() {
|
||||
return { iconBranch };
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="build in items" class="stage-event-item item-build-component">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="build.author.avatarUrl"/>
|
||||
<h5 class="item-title">
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch">${iconBranch}</span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="build-date">{{ build.date }}</a>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="build.author.webUrl" class="issue-author-link">
|
||||
{{ build.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,55 @@
|
|||
<script>
|
||||
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
components: {
|
||||
userAvatarImage,
|
||||
},
|
||||
computed: {
|
||||
iconBranch() {
|
||||
return iconBranch;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(build, i) in items"
|
||||
class="stage-event-item item-build-component"
|
||||
:key="i">
|
||||
<div class="item-details">
|
||||
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||
<user-avatar-image :img-src="build.author.avatarUrl"/>
|
||||
<h5 class="item-title">
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch" v-html="iconBranch"></span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="build-date">{{ build.date }}</a>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<a :href="build.author.webUrl" class="issue-author-link">
|
||||
{{ build.author.name }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
|
@ -1,49 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import iconBuildStatus from '../svg/icon_build_status.svg';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageTestComponent = Vue.extend({
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
data() {
|
||||
return { iconBuildStatus, iconBranch };
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li v-for="build in items" class="stage-event-item item-build-component">
|
||||
<div class="item-details">
|
||||
<h5 class="item-title">
|
||||
<span class="icon-build-status">${iconBuildStatus}</span>
|
||||
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
|
||||
·
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch">${iconBranch}</span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="issue-date">
|
||||
{{ build.date }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"></total-time>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,54 @@
|
|||
<script>
|
||||
import iconBuildStatus from '../svg/icon_build_status.svg';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
items: Array,
|
||||
stage: Object,
|
||||
},
|
||||
computed: {
|
||||
iconBuildStatus() {
|
||||
return iconBuildStatus;
|
||||
},
|
||||
iconBranch() {
|
||||
return iconBranch;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div class="events-description">
|
||||
{{ stage.description }}
|
||||
<limit-warning :count="items.length" />
|
||||
</div>
|
||||
<ul class="stage-event-list">
|
||||
<li
|
||||
v-for="(build, i) in items"
|
||||
:key="i"
|
||||
class="stage-event-item item-build-component">
|
||||
<div class="item-details">
|
||||
<h5 class="item-title">
|
||||
<span class="icon-build-status" v-html="iconBuildStatus"></span>
|
||||
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
|
||||
·
|
||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||
<i class="fa fa-code-fork"></i>
|
||||
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||
<span class="icon-branch" v-html="iconBranch"></span>
|
||||
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||
</h5>
|
||||
<span>
|
||||
<a :href="build.url" class="issue-date">
|
||||
{{ build.date }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-time">
|
||||
<total-time :time="build.totalTime"/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
|
@ -1,25 +0,0 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.TotalTimeComponent = Vue.extend({
|
||||
props: {
|
||||
time: Object,
|
||||
},
|
||||
template: `
|
||||
<span class="total-time">
|
||||
<template v-if="Object.keys(time).length">
|
||||
<template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template>
|
||||
<template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template>
|
||||
<template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template>
|
||||
<template v-if="time.seconds && Object.keys(time).length === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template>
|
||||
</template>
|
||||
<template v-else>
|
||||
--
|
||||
</template>
|
||||
</span>
|
||||
`,
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
time: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasData() {
|
||||
return Object.keys(this.time).length;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<span class="total-time">
|
||||
<template v-if="hasData">
|
||||
<template v-if="time.days">{{ time.days }} <span>{{ n__('day', 'days', time.days) }}</span></template>
|
||||
<template v-if="time.hours">{{ time.hours }} <span>{{ n__('Time|hr', 'Time|hrs', time.hours) }}</span></template>
|
||||
<template v-if="time.mins && !time.days">{{ time.mins }} <span>{{ n__('Time|min', 'Time|mins', time.mins) }}</span></template>
|
||||
<template v-if="time.seconds && hasDa === 1 || time.seconds === 0">{{ time.seconds }} <span>{{ s__('Time|s') }}</span></template>
|
||||
</template>
|
||||
<template v-else>
|
||||
--
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
|
@ -3,60 +3,63 @@
|
|||
import Vue from 'vue';
|
||||
import Cookies from 'js-cookie';
|
||||
import Translate from '../vue_shared/translate';
|
||||
import LimitWarningComponent from './components/limit_warning_component';
|
||||
import './components/stage_code_component';
|
||||
import './components/stage_issue_component';
|
||||
import './components/stage_plan_component';
|
||||
import './components/stage_production_component';
|
||||
import './components/stage_review_component';
|
||||
import './components/stage_staging_component';
|
||||
import './components/stage_test_component';
|
||||
import './components/total_time_component';
|
||||
import './cycle_analytics_service';
|
||||
import './cycle_analytics_store';
|
||||
import limitWarningComponent from './components/limit_warning_component.vue';
|
||||
import stageCodeComponent from './components/stage_code_component.vue';
|
||||
import stagePlanComponent from './components/stage_plan_component.vue';
|
||||
import stageComponent from './components/stage_component.vue';
|
||||
import stageReviewComponent from './components/stage_review_component.vue';
|
||||
import stageStagingComponent from './components/stage_staging_component.vue';
|
||||
import stageTestComponent from './components/stage_test_component.vue';
|
||||
import totalTime from './components/total_time_component.vue';
|
||||
import CycleAnalyticsService from './cycle_analytics_service';
|
||||
import CycleAnalyticsStore from './cycle_analytics_store';
|
||||
|
||||
Vue.use(Translate);
|
||||
|
||||
$(() => {
|
||||
const OVERVIEW_DIALOG_COOKIE = 'cycle_analytics_help_dismissed';
|
||||
const cycleAnalyticsEl = document.querySelector('#cycle-analytics');
|
||||
const cycleAnalyticsStore = gl.cycleAnalytics.CycleAnalyticsStore;
|
||||
const cycleAnalyticsService = new gl.cycleAnalytics.CycleAnalyticsService({
|
||||
requestPath: cycleAnalyticsEl.dataset.requestPath,
|
||||
});
|
||||
|
||||
gl.cycleAnalyticsApp = new Vue({
|
||||
el: '#cycle-analytics',
|
||||
name: 'CycleAnalytics',
|
||||
data: {
|
||||
state: cycleAnalyticsStore.state,
|
||||
isLoading: false,
|
||||
isLoadingStage: false,
|
||||
isEmptyStage: false,
|
||||
hasError: false,
|
||||
startDate: 30,
|
||||
isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE),
|
||||
data() {
|
||||
const cycleAnalyticsEl = document.querySelector('#cycle-analytics');
|
||||
const cycleAnalyticsService = new CycleAnalyticsService({
|
||||
requestPath: cycleAnalyticsEl.dataset.requestPath,
|
||||
});
|
||||
|
||||
return {
|
||||
store: CycleAnalyticsStore,
|
||||
state: CycleAnalyticsStore.state,
|
||||
isLoading: false,
|
||||
isLoadingStage: false,
|
||||
isEmptyStage: false,
|
||||
hasError: false,
|
||||
startDate: 30,
|
||||
isOverviewDialogDismissed: Cookies.get(OVERVIEW_DIALOG_COOKIE),
|
||||
service: cycleAnalyticsService,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentStage() {
|
||||
return cycleAnalyticsStore.currentActiveStage();
|
||||
return this.store.currentActiveStage();
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'stage-issue-component': gl.cycleAnalytics.StageIssueComponent,
|
||||
'stage-plan-component': gl.cycleAnalytics.StagePlanComponent,
|
||||
'stage-code-component': gl.cycleAnalytics.StageCodeComponent,
|
||||
'stage-test-component': gl.cycleAnalytics.StageTestComponent,
|
||||
'stage-review-component': gl.cycleAnalytics.StageReviewComponent,
|
||||
'stage-staging-component': gl.cycleAnalytics.StageStagingComponent,
|
||||
'stage-production-component': gl.cycleAnalytics.StageProductionComponent,
|
||||
'stage-issue-component': stageComponent,
|
||||
'stage-plan-component': stagePlanComponent,
|
||||
'stage-code-component': stageCodeComponent,
|
||||
'stage-test-component': stageTestComponent,
|
||||
'stage-review-component': stageReviewComponent,
|
||||
'stage-staging-component': stageStagingComponent,
|
||||
'stage-production-component': stageComponent,
|
||||
},
|
||||
created() {
|
||||
this.fetchCycleAnalyticsData();
|
||||
},
|
||||
methods: {
|
||||
handleError() {
|
||||
cycleAnalyticsStore.setErrorState(true);
|
||||
this.store.setErrorState(true);
|
||||
return new Flash('There was an error while fetching cycle analytics data.');
|
||||
},
|
||||
initDropdown() {
|
||||
|
@ -77,17 +80,17 @@ $(() => {
|
|||
|
||||
this.isLoading = true;
|
||||
|
||||
cycleAnalyticsService
|
||||
this.service
|
||||
.fetchCycleAnalyticsData(fetchOptions)
|
||||
.done((response) => {
|
||||
cycleAnalyticsStore.setCycleAnalyticsData(response);
|
||||
.then(resp => resp.json())
|
||||
.then((response) => {
|
||||
this.store.setCycleAnalyticsData(response);
|
||||
this.selectDefaultStage();
|
||||
this.initDropdown();
|
||||
this.isLoading = false;
|
||||
})
|
||||
.error(() => {
|
||||
.catch(() => {
|
||||
this.handleError();
|
||||
})
|
||||
.always(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
|
@ -100,27 +103,27 @@ $(() => {
|
|||
if (this.currentStage === stage) return;
|
||||
|
||||
if (!stage.isUserAllowed) {
|
||||
cycleAnalyticsStore.setActiveStage(stage);
|
||||
this.store.setActiveStage(stage);
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoadingStage = true;
|
||||
cycleAnalyticsStore.setStageEvents([], stage);
|
||||
cycleAnalyticsStore.setActiveStage(stage);
|
||||
this.store.setStageEvents([], stage);
|
||||
this.store.setActiveStage(stage);
|
||||
|
||||
cycleAnalyticsService
|
||||
this.service
|
||||
.fetchStageData({
|
||||
stage,
|
||||
startDate: this.startDate,
|
||||
})
|
||||
.done((response) => {
|
||||
.then(resp => resp.json())
|
||||
.then((response) => {
|
||||
this.isEmptyStage = !response.events.length;
|
||||
cycleAnalyticsStore.setStageEvents(response.events, stage);
|
||||
this.store.setStageEvents(response.events, stage);
|
||||
this.isLoadingStage = false;
|
||||
})
|
||||
.error(() => {
|
||||
.catch(() => {
|
||||
this.isEmptyStage = true;
|
||||
})
|
||||
.always(() => {
|
||||
this.isLoadingStage = false;
|
||||
});
|
||||
},
|
||||
|
@ -132,6 +135,6 @@ $(() => {
|
|||
});
|
||||
|
||||
// Register global components
|
||||
Vue.component('limit-warning', LimitWarningComponent);
|
||||
Vue.component('total-time', gl.cycleAnalytics.TotalTimeComponent);
|
||||
Vue.component('limit-warning', limitWarningComponent);
|
||||
Vue.component('total-time', totalTime);
|
||||
});
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import Vue from 'vue';
|
||||
import VueResource from 'vue-resource';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
Vue.use(VueResource);
|
||||
|
||||
class CycleAnalyticsService {
|
||||
export default class CycleAnalyticsService {
|
||||
constructor(options) {
|
||||
this.requestPath = options.requestPath;
|
||||
this.cycleAnalytics = Vue.resource(this.requestPath);
|
||||
}
|
||||
|
||||
fetchCycleAnalyticsData(options) {
|
||||
options = options || { startDate: 30 };
|
||||
|
||||
return $.ajax({
|
||||
url: this.requestPath,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: {
|
||||
cycle_analytics: {
|
||||
start_date: options.startDate,
|
||||
},
|
||||
},
|
||||
});
|
||||
fetchCycleAnalyticsData(options = { startDate: 30 }) {
|
||||
return this.cycleAnalytics.get({ cycle_analytics: { start_date: options.startDate } });
|
||||
}
|
||||
|
||||
fetchStageData(options) {
|
||||
|
@ -30,12 +19,12 @@ class CycleAnalyticsService {
|
|||
startDate,
|
||||
} = options;
|
||||
|
||||
return $.get(`${this.requestPath}/events/${stage.name}.json`, {
|
||||
cycle_analytics: {
|
||||
start_date: startDate,
|
||||
return Vue.http.get(`${this.requestPath}/events/${stage.name}.json`, {
|
||||
params: {
|
||||
cycle_analytics: {
|
||||
start_date: startDate,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
global.cycleAnalytics.CycleAnalyticsService = CycleAnalyticsService;
|
||||
|
|
|
@ -4,9 +4,6 @@ import { __ } from '../locale';
|
|||
import '../lib/utils/text_utility';
|
||||
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
const EMPTY_STAGE_TEXTS = {
|
||||
issue: __('The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.'),
|
||||
plan: __('The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.'),
|
||||
|
@ -17,7 +14,7 @@ const EMPTY_STAGE_TEXTS = {
|
|||
production: __('The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.'),
|
||||
};
|
||||
|
||||
global.cycleAnalytics.CycleAnalyticsStore = {
|
||||
export default {
|
||||
state: {
|
||||
summary: '',
|
||||
stats: '',
|
||||
|
|
|
@ -34,7 +34,7 @@ export const canShowActiveSubItems = (el) => {
|
|||
export const canShowSubItems = () => bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md' || bp.getBreakpointSize() === 'lg';
|
||||
|
||||
export const getHideSubItemsInterval = () => {
|
||||
if (!currentOpenMenu) return 0;
|
||||
if (!currentOpenMenu || !mousePos.length) return 0;
|
||||
|
||||
const currentMousePos = mousePos[mousePos.length - 1];
|
||||
const prevMousePos = mousePos[0];
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// We will render the icons list here
|
||||
if ($('#user-content-gitlab-icons').length > 0) {
|
||||
const $iconsHeader = $('#user-content-gitlab-icons');
|
||||
const $iconsList = $('<div id="iconsList">ICONS</div>');
|
||||
$($iconsList).insertAfter($iconsHeader.parent());
|
||||
}
|
|
@ -408,6 +408,10 @@ export const setCiStatusFavicon = (pageUrl) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const spriteIcon = icon => `<svg><use xlink:href="${gon.sprite_icons}#${icon}" /></svg>`;
|
||||
|
||||
export const imagePath = imgUrl => `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/${imgUrl}`;
|
||||
|
||||
window.gl = window.gl || {};
|
||||
window.gl.utils = {
|
||||
...(window.gl.utils || {}),
|
||||
|
@ -434,4 +438,6 @@ window.gl.utils = {
|
|||
getSelectedFragment,
|
||||
insertText,
|
||||
nodeMatchesSelector,
|
||||
spriteIcon,
|
||||
imagePath,
|
||||
};
|
||||
|
|
|
@ -1,14 +1,34 @@
|
|||
export const isSticky = (el, scrollY, stickyTop) => {
|
||||
export const createPlaceholder = () => {
|
||||
const placeholder = document.createElement('div');
|
||||
placeholder.classList.add('sticky-placeholder');
|
||||
|
||||
return placeholder;
|
||||
};
|
||||
|
||||
export const isSticky = (el, scrollY, stickyTop, insertPlaceholder) => {
|
||||
const top = Math.floor(el.offsetTop - scrollY);
|
||||
|
||||
if (top <= stickyTop) {
|
||||
if (top <= stickyTop && !el.classList.contains('is-stuck')) {
|
||||
const placeholder = insertPlaceholder ? createPlaceholder() : null;
|
||||
const heightBefore = el.offsetHeight;
|
||||
|
||||
el.classList.add('is-stuck');
|
||||
} else {
|
||||
|
||||
if (insertPlaceholder) {
|
||||
el.parentNode.insertBefore(placeholder, el.nextElementSibling);
|
||||
|
||||
placeholder.style.height = `${heightBefore - el.offsetHeight}px`;
|
||||
}
|
||||
} else if (top > stickyTop && el.classList.contains('is-stuck')) {
|
||||
el.classList.remove('is-stuck');
|
||||
|
||||
if (insertPlaceholder && el.nextElementSibling && el.nextElementSibling.classList.contains('sticky-placeholder')) {
|
||||
el.nextElementSibling.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default (el) => {
|
||||
export default (el, insertPlaceholder = true) => {
|
||||
if (!el) return;
|
||||
|
||||
const computedStyle = window.getComputedStyle(el);
|
||||
|
@ -17,7 +37,7 @@ export default (el) => {
|
|||
|
||||
const stickyTop = parseInt(computedStyle.top, 10);
|
||||
|
||||
document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop), {
|
||||
document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop, insertPlaceholder), {
|
||||
passive: true,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@ import _ from 'underscore';
|
|||
import Cookies from 'js-cookie';
|
||||
import Dropzone from 'dropzone';
|
||||
import Sortable from 'vendor/Sortable';
|
||||
import svg4everybody from 'svg4everybody';
|
||||
|
||||
// libraries with import side-effects
|
||||
import 'mousetrap';
|
||||
|
@ -151,6 +152,8 @@ if (process.env.NODE_ENV !== 'production') require('./test_utils/');
|
|||
|
||||
Dropzone.autoDiscover = false;
|
||||
|
||||
svg4everybody();
|
||||
|
||||
document.addEventListener('beforeunload', function () {
|
||||
// Unbind scroll events
|
||||
$(document).off('scroll');
|
||||
|
|
|
@ -248,6 +248,8 @@ import {
|
|||
propsData: {
|
||||
endpoint: pipelineTableViewEl.dataset.endpoint,
|
||||
helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
|
||||
emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
|
||||
errorStateSvgPath: pipelineTableViewEl.dataset.errorStateSvgPath,
|
||||
autoDevopsHelpPath: pipelineTableViewEl.dataset.helpAutoDevopsPath,
|
||||
},
|
||||
}).$mount();
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
settingsPath: metricsData.settingsPath,
|
||||
metricsEndpoint: metricsData.additionalMetrics,
|
||||
deploymentEndpoint: metricsData.deploymentEndpoint,
|
||||
emptyGettingStartedSvgPath: metricsData.emptyGettingStartedSvgPath,
|
||||
emptyLoadingSvgPath: metricsData.emptyLoadingSvgPath,
|
||||
emptyUnableToConnectSvgPath: metricsData.emptyUnableToConnectSvgPath,
|
||||
showEmptyState: true,
|
||||
updateAspectRatio: false,
|
||||
updatedAspectRatios: 0,
|
||||
|
@ -109,5 +112,8 @@
|
|||
:selected-state="state"
|
||||
:documentation-path="documentationPath"
|
||||
:settings-path="settingsPath"
|
||||
:empty-getting-started-svg-path="emptyGettingStartedSvgPath"
|
||||
:empty-loading-svg-path="emptyLoadingSvgPath"
|
||||
:empty-unable-to-connect-svg-path="emptyUnableToConnectSvgPath"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
<script>
|
||||
import gettingStartedSvg from 'empty_states/monitoring/_getting_started.svg';
|
||||
import loadingSvg from 'empty_states/monitoring/_loading.svg';
|
||||
import unableToConnectSvg from 'empty_states/monitoring/_unable_to_connect.svg';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
documentationPath: {
|
||||
|
@ -18,24 +14,36 @@
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
emptyGettingStartedSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
emptyLoadingSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
emptyUnableToConnectSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
states: {
|
||||
gettingStarted: {
|
||||
svg: gettingStartedSvg,
|
||||
svgUrl: this.emptyGettingStartedSvgPath,
|
||||
title: 'Get started with performance monitoring',
|
||||
description: 'Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments.',
|
||||
buttonText: 'Configure Prometheus',
|
||||
},
|
||||
loading: {
|
||||
svg: loadingSvg,
|
||||
svgUrl: this.emptyLoadingSvgPath,
|
||||
title: 'Waiting for performance data',
|
||||
description: 'Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available.',
|
||||
buttonText: 'View documentation',
|
||||
},
|
||||
unableToConnect: {
|
||||
svg: unableToConnectSvg,
|
||||
svgUrl: this.emptyUnableToConnectSvgPath,
|
||||
title: 'Unable to connect to Prometheus server',
|
||||
description: 'Ensure connectivity is available from the GitLab server to the ',
|
||||
buttonText: 'View documentation',
|
||||
|
@ -66,7 +74,9 @@
|
|||
<template>
|
||||
<div class="prometheus-state">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-4 state-svg" v-html="currentState.svg"></div>
|
||||
<div class="col-md-4 col-md-offset-4 state-svg svg-content">
|
||||
<img :src="currentState.svgUrl"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
|
|
|
@ -97,6 +97,8 @@
|
|||
methods: {
|
||||
...mapActions([
|
||||
'saveNote',
|
||||
'stopPolling',
|
||||
'restartPolling',
|
||||
'removePlaceholderNotes',
|
||||
]),
|
||||
setIsSubmitButtonDisabled(note, isSubmitting) {
|
||||
|
@ -126,10 +128,13 @@
|
|||
this.isSubmitting = true;
|
||||
this.note = ''; // Empty textarea while being requested. Repopulate in catch
|
||||
this.resizeTextarea();
|
||||
this.stopPolling();
|
||||
|
||||
this.saveNote(noteData)
|
||||
.then((res) => {
|
||||
this.isSubmitting = false;
|
||||
this.restartPolling();
|
||||
|
||||
if (res.errors) {
|
||||
if (res.errors.commands_only) {
|
||||
this.discard();
|
||||
|
@ -177,6 +182,7 @@
|
|||
if (shouldClear) {
|
||||
this.note = '';
|
||||
this.resizeTextarea();
|
||||
this.$refs.markdownField.previewMarkdown = false;
|
||||
}
|
||||
|
||||
// reset autostave
|
||||
|
@ -255,7 +261,8 @@
|
|||
:markdown-docs-path="markdownDocsPath"
|
||||
:quick-actions-docs-path="quickActionsDocsPath"
|
||||
:add-spacing-classes="false"
|
||||
:is-confidential-issue="isConfidentialIssue">
|
||||
:is-confidential-issue="isConfidentialIssue"
|
||||
ref="markdownField">
|
||||
<textarea
|
||||
id="note-body"
|
||||
name="note[note]"
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import iconArrowCircle from 'icons/_icon_arrow_circle_o_right.svg';
|
||||
import iconCheck from 'icons/_icon_check_square_o.svg';
|
||||
import iconClock from 'icons/_icon_clock_o.svg';
|
||||
import iconCodeFork from 'icons/_icon_code_fork.svg';
|
||||
import iconComment from 'icons/_icon_comment_o.svg';
|
||||
import iconCommit from 'icons/_icon_commit.svg';
|
||||
import iconEdit from 'icons/_icon_edit.svg';
|
||||
import iconEye from 'icons/_icon_eye.svg';
|
||||
import iconEyeSlash from 'icons/_icon_eye_slash.svg';
|
||||
import iconMerge from 'icons/_icon_merge.svg';
|
||||
import iconMerged from 'icons/_icon_merged.svg';
|
||||
import iconRandom from 'icons/_icon_random.svg';
|
||||
import iconClosed from 'icons/_icon_status_closed.svg';
|
||||
import iconStatusOpen from 'icons/_icon_status_open.svg';
|
||||
import iconStopwatch from 'icons/_icon_stopwatch.svg';
|
||||
import iconTags from 'icons/_icon_tags.svg';
|
||||
import iconUser from 'icons/_icon_user.svg';
|
||||
|
||||
export default {
|
||||
icon_arrow_circle_o_right: iconArrowCircle,
|
||||
icon_check_square_o: iconCheck,
|
||||
icon_clock_o: iconClock,
|
||||
icon_code_fork: iconCodeFork,
|
||||
icon_comment_o: iconComment,
|
||||
icon_commit: iconCommit,
|
||||
icon_edit: iconEdit,
|
||||
icon_eye: iconEye,
|
||||
icon_eye_slash: iconEyeSlash,
|
||||
icon_merge: iconMerge,
|
||||
icon_merged: iconMerged,
|
||||
icon_random: iconRandom,
|
||||
icon_status_closed: iconClosed,
|
||||
icon_status_open: iconStatusOpen,
|
||||
icon_stopwatch: iconStopwatch,
|
||||
icon_tags: iconTags,
|
||||
icon_user: iconUser,
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import iconsMap from './issue_note_icons';
|
||||
import issueNoteHeader from './issue_note_header.vue';
|
||||
|
||||
export default {
|
||||
|
@ -24,9 +23,9 @@
|
|||
isTargetNote() {
|
||||
return this.targetNoteHash === this.noteAnchorId;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.svg = iconsMap[this.note.system_note_icon_name];
|
||||
iconHtml() {
|
||||
return gl.utils.spriteIcon(this.note.system_note_icon_name);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -39,7 +38,7 @@
|
|||
<div class="timeline-entry-inner">
|
||||
<div
|
||||
class="timeline-icon"
|
||||
v-html="svg">
|
||||
v-html="iconHtml">
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="note-header">
|
||||
|
|
|
@ -187,6 +187,14 @@ export const poll = ({ commit, state, getters }) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const stopPolling = () => {
|
||||
eTagPoll.stop();
|
||||
};
|
||||
|
||||
export const restartPolling = () => {
|
||||
eTagPoll.restart();
|
||||
};
|
||||
|
||||
export const fetchData = ({ commit, state, getters }) => {
|
||||
const requestData = { endpoint: state.notesData.notesPath, lastFetchedAt: state.lastFetchedAt };
|
||||
|
||||
|
|
|
@ -5,15 +5,19 @@ import * as constants from '../constants';
|
|||
export default {
|
||||
[types.ADD_NEW_NOTE](state, note) {
|
||||
const { discussion_id, type } = note;
|
||||
const noteData = {
|
||||
expanded: true,
|
||||
id: discussion_id,
|
||||
individual_note: !(type === constants.DISCUSSION_NOTE),
|
||||
notes: [note],
|
||||
reply_id: discussion_id,
|
||||
};
|
||||
const [exists] = state.notes.filter(n => n.id === note.discussion_id);
|
||||
|
||||
state.notes.push(noteData);
|
||||
if (!exists) {
|
||||
const noteData = {
|
||||
expanded: true,
|
||||
id: discussion_id,
|
||||
individual_note: !(type === constants.DISCUSSION_NOTE),
|
||||
notes: [note],
|
||||
reply_id: discussion_id,
|
||||
};
|
||||
|
||||
state.notes.push(noteData);
|
||||
}
|
||||
},
|
||||
|
||||
[types.ADD_NEW_REPLY_TO_DISCUSSION](state, note) {
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
<script>
|
||||
import pipelinesEmptyStateSVG from 'empty_states/icons/_pipelines_empty.svg';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
helpPagePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
emptyStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data: () => ({ pipelinesEmptyStateSVG }),
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row empty-state js-empty-state">
|
||||
<div class="col-xs-12">
|
||||
<div class="svg-content" v-html="pipelinesEmptyStateSVG" />
|
||||
<div class="svg-content">
|
||||
<img :src="emptyStateSvgPath"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 text-center">
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
<script>
|
||||
import pipelinesErrorStateSVG from 'empty_states/icons/_pipelines_failed.svg';
|
||||
|
||||
export default {
|
||||
data: () => ({ pipelinesErrorStateSVG }),
|
||||
props: {
|
||||
errorStateSvgPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="row empty-state js-pipelines-error-state">
|
||||
<div class="col-xs-12">
|
||||
<div class="svg-content" v-html="pipelinesErrorStateSVG" />
|
||||
<div class="svg-content">
|
||||
<img :src="errorStateSvgPath"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 text-center">
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
return {
|
||||
endpoint: pipelinesData.endpoint,
|
||||
helpPagePath: pipelinesData.helpPagePath,
|
||||
emptyStateSvgPath: pipelinesData.emptyStateSvgPath,
|
||||
errorStateSvgPath: pipelinesData.errorStateSvgPath,
|
||||
autoDevopsPath: pipelinesData.helpAutoDevopsPath,
|
||||
newPipelinePath: pipelinesData.newPipelinePath,
|
||||
canCreatePipeline: pipelinesData.canCreatePipeline,
|
||||
|
@ -182,9 +184,13 @@
|
|||
<empty-state
|
||||
v-if="shouldRenderEmptyState"
|
||||
:help-page-path="helpPagePath"
|
||||
:empty-state-svg-path="emptyStateSvgPath"
|
||||
/>
|
||||
|
||||
<error-state v-if="shouldRenderErrorState" />
|
||||
<error-state
|
||||
v-if="shouldRenderErrorState"
|
||||
:error-state-svg-path="errorStateSvgPath"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="blank-state blank-state-no-icon"
|
||||
|
|
|
@ -69,8 +69,7 @@
|
|||
@click="onClickAction(action.path)"
|
||||
:class="{ disabled: isActionDisabled(action) }"
|
||||
:disabled="isActionDisabled(action)">
|
||||
<span v-html="playIconSvg"></span>
|
||||
<span>{{action.name}}</span>
|
||||
{{action.name}}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -39,11 +39,7 @@
|
|||
rel="nofollow"
|
||||
download
|
||||
:href="artifact.path">
|
||||
<i
|
||||
class="fa fa-download"
|
||||
aria-hidden="true">
|
||||
</i>
|
||||
<span>Download {{artifact.name}} artifacts</span>
|
||||
Download {{artifact.name}} artifacts
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -178,8 +178,8 @@ const RepoHelper = {
|
|||
|
||||
setFile(data, file) {
|
||||
const newFile = data;
|
||||
newFile.url = file.url || Service.url; // Grab the URL from service, happens on page refresh.
|
||||
|
||||
newFile.url = file.url;
|
||||
if (newFile.render_error === 'too_large' || newFile.render_error === 'collapsed') {
|
||||
newFile.tooLarge = true;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<script>
|
||||
import { s__ } from '../../locale';
|
||||
|
||||
const PAGINATION_UI_BUTTON_LIMIT = 4;
|
||||
const UI_LIMIT = 6;
|
||||
const SPREAD = '...';
|
||||
const PREV = 'Prev';
|
||||
const NEXT = 'Next';
|
||||
const FIRST = '« First';
|
||||
const LAST = 'Last »';
|
||||
const PREV = s__('Pagination|Prev');
|
||||
const NEXT = s__('Pagination|Next');
|
||||
const FIRST = s__('Pagination|« First');
|
||||
const LAST = s__('Pagination|Last »');
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
|
@ -31,10 +31,12 @@
|
|||
@import "framework/mobile";
|
||||
@import "framework/modal";
|
||||
@import "framework/nav";
|
||||
@import "framework/new-nav";
|
||||
@import "framework/pagination";
|
||||
@import "framework/panels";
|
||||
@import "framework/selects";
|
||||
@import "framework/sidebar";
|
||||
@import "framework/new-sidebar";
|
||||
@import "framework/tables";
|
||||
@import "framework/notes";
|
||||
@import "framework/timeline";
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
}
|
||||
|
||||
.emoji-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
margin-top: 3px;
|
||||
|
@ -27,6 +28,10 @@
|
|||
transition: .3s cubic-bezier(.67, .06, .19, 1.44);
|
||||
transition-property: transform, opacity;
|
||||
|
||||
&.is-rendered {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.is-aligned-right {
|
||||
transform-origin: 100% -45px;
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@
|
|||
position: relative;
|
||||
border: 1px solid $blue-300;
|
||||
border-radius: $border-radius-default;
|
||||
background-color: $blue-25;
|
||||
background-color: $blue-50;
|
||||
justify-content: center;
|
||||
|
||||
.dismiss-button {
|
||||
|
@ -319,16 +319,6 @@
|
|||
padding: $gl-padding;
|
||||
}
|
||||
|
||||
.svg-content {
|
||||
text-align: center;
|
||||
|
||||
svg {
|
||||
max-width: 425px;
|
||||
width: 100%;
|
||||
padding: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-icon {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
@ -779,6 +779,14 @@
|
|||
white-space: normal;
|
||||
width: 100%;
|
||||
|
||||
&.dropdown-menu-user-link {
|
||||
white-space: nowrap;
|
||||
|
||||
.dropdown-menu-user-username {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the text color is not overriden
|
||||
&.text-danger {
|
||||
color: $brand-danger;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Header
|
||||
|
||||
header.navbar-gitlab-new {
|
||||
background: linear-gradient(to right, $color-900, $color-800);
|
||||
background-color: $color-900;
|
||||
|
||||
.navbar-collapse {
|
||||
color: $color-200;
|
||||
|
@ -201,7 +201,7 @@ body {
|
|||
@include gitlab-theme($theme-gray-900, $theme-gray-700, $theme-gray-800, $theme-gray-700, $theme-gray-700, $theme-gray-100, $theme-gray-700);
|
||||
|
||||
header.navbar-gitlab-new {
|
||||
background: $theme-gray-100;
|
||||
background-color: $theme-gray-100;
|
||||
box-shadow: 0 2px 0 0 $border-color;
|
||||
|
||||
.logo-text svg {
|
||||
|
@ -242,10 +242,10 @@ body {
|
|||
|
||||
&:hover {
|
||||
background-color: $white-light;
|
||||
box-shadow: inset 0 0 0 1px $blue-100;
|
||||
box-shadow: inset 0 0 0 1px $blue-200;
|
||||
|
||||
.location-badge {
|
||||
box-shadow: inset 0 0 0 1px $blue-100;
|
||||
box-shadow: inset 0 0 0 1px $blue-200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,6 +254,10 @@ body {
|
|||
.search-icon {
|
||||
color: $theme-gray-200;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
|
|
|
@ -9,3 +9,27 @@
|
|||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.svg-content {
|
||||
text-align: center;
|
||||
padding: $gl-padding;
|
||||
|
||||
svg,
|
||||
img {
|
||||
max-width: 425px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin svg-size($size) {
|
||||
width: $size;
|
||||
height: $size;
|
||||
}
|
||||
|
||||
svg {
|
||||
&.s16 { @include svg-size(16px); }
|
||||
&.s24 { @include svg-size(24px); }
|
||||
&.s32 { @include svg-size(32px); }
|
||||
&.s48 { @include svg-size(48px); }
|
||||
&.s72 { @include svg-size(72px); }
|
||||
}
|
||||
|
|
|
@ -142,5 +142,41 @@
|
|||
}
|
||||
|
||||
@mixin green-status-color {
|
||||
@include status-color($green-50, $green-500, $green-700);
|
||||
@include status-color($green-100, $green-500, $green-700);
|
||||
}
|
||||
|
||||
@mixin fade($gradient-direction, $gradient-color) {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
width: 43px;
|
||||
height: 30px;
|
||||
transition-duration: .3s;
|
||||
-webkit-transform: translateZ(0);
|
||||
background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4));
|
||||
|
||||
&.scrolling {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition-duration: .3s;
|
||||
}
|
||||
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin scrolling-links() {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
display: flex;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +1,4 @@
|
|||
@mixin fade($gradient-direction, $gradient-color) {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
width: 43px;
|
||||
height: 30px;
|
||||
transition-duration: .3s;
|
||||
-webkit-transform: translateZ(0);
|
||||
background: linear-gradient(to $gradient-direction, $gradient-color 45%, rgba($gradient-color, 0.4));
|
||||
|
||||
&.scrolling {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition-duration: .3s;
|
||||
}
|
||||
|
||||
.fa {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin scrolling-links() {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
display: flex;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
|
|
|
@ -295,75 +295,6 @@ header.navbar-gitlab-new {
|
|||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin: 4px 8px 0;
|
||||
|
||||
form {
|
||||
height: 32px;
|
||||
border: 0;
|
||||
border-radius: $border-radius-default;
|
||||
transition: border-color ease-in-out 0.15s, background-color ease-in-out 0.15s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.search-active form {
|
||||
box-shadow: none;
|
||||
|
||||
.search-input {
|
||||
color: $gl-text-color;
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: $gl-text-color-tertiary;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
color: $gl-text-color-tertiary;
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
color: $white-light;
|
||||
background: none;
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
transition: color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
font-size: 12px;
|
||||
margin: -4px 4px -4px -4px;
|
||||
line-height: 25px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 2px 0 0 2px;
|
||||
height: 32px;
|
||||
transition: border-color ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
&.search-active {
|
||||
.location-badge {
|
||||
background-color: $nav-badge-bg;
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
.clear-icon {
|
||||
color: $white-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
|
@ -386,11 +317,6 @@ header.navbar-gitlab-new {
|
|||
align-self: center;
|
||||
color: $gl-text-color-secondary;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
padding-left: 17px;
|
||||
border-left: 1px solid $gl-text-color-quaternary;
|
||||
}
|
||||
|
||||
.avatar-tile {
|
||||
margin-right: 4px;
|
||||
border: 1px solid $border-color;
|
|
@ -461,6 +461,13 @@ $new-sidebar-collapsed-width: 50px;
|
|||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
+ .breadcrumbs-links {
|
||||
padding-left: 17px;
|
||||
border-left: 1px solid $gl-text-color-quaternary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
|
@ -137,7 +137,7 @@ $well-border: #eee;
|
|||
//##
|
||||
|
||||
$code-color: $red-600;
|
||||
$code-bg: lighten($red-50, 2%);
|
||||
$code-bg: lighten($red-100, 2%);
|
||||
|
||||
$kbd-color: $white-light;
|
||||
$kbd-bg: #333;
|
||||
|
|
|
@ -6,6 +6,7 @@ $gutter_width: 290px;
|
|||
$gutter_inner_width: 250px;
|
||||
$sidebar-transition-duration: .15s;
|
||||
$sidebar-breakpoint: 1024px;
|
||||
$default-transition-duration: .15s;
|
||||
|
||||
/*
|
||||
* Color schema
|
||||
|
@ -27,46 +28,45 @@ $gray-dark: darken($gray-light, $darken-dark-factor);
|
|||
$gray-darker: #eee;
|
||||
$gray-darkest: #c4c4c4;
|
||||
|
||||
$green-25: #f6fcf8;
|
||||
$green-50: #e4f5eb;
|
||||
$green-100: #bae6cc;
|
||||
$green-200: #8dd5aa;
|
||||
$green-300: #5fc488;
|
||||
$green-400: #3cb76f;
|
||||
$green-50: #f1fdf6;
|
||||
$green-100: #dcf5e7;
|
||||
$green-200: #b3e6c8;
|
||||
$green-300: #75d09b;
|
||||
$green-400: #37b96d;
|
||||
$green-500: #1aaa55;
|
||||
$green-600: #168f48;
|
||||
$green-700: #12753a;
|
||||
$green-800: #0e5a2d;
|
||||
$green-900: #0a4020;
|
||||
$green-950: #072b15;
|
||||
|
||||
$blue-25: #f6fafd;
|
||||
$blue-50: #e4eff9;
|
||||
$blue-100: #bcd7f1;
|
||||
$blue-200: #8fbce8;
|
||||
$blue-300: #62a1df;
|
||||
$blue-400: #418cd8;
|
||||
$blue-50: #f6fafe;
|
||||
$blue-100: #e4f0fb;
|
||||
$blue-200: #b8d6f4;
|
||||
$blue-300: #73afea;
|
||||
$blue-400: #2e87e0;
|
||||
$blue-500: #1f78d1;
|
||||
$blue-600: #1b69b6;
|
||||
$blue-700: #17599c;
|
||||
$blue-800: #134a81;
|
||||
$blue-900: #0f3b66;
|
||||
$blue-950: #0a2744;
|
||||
|
||||
$orange-25: #fffcf8;
|
||||
$orange-50: #fff2e1;
|
||||
$orange-100: #fedfb3;
|
||||
$orange-200: #feca81;
|
||||
$orange-300: #fdb44f;
|
||||
$orange-400: #fca429;
|
||||
$orange-50: #fffaf4;
|
||||
$orange-100: #fff1de;
|
||||
$orange-200: #fed69f;
|
||||
$orange-300: #fdbc60;
|
||||
$orange-400: #fca121;
|
||||
$orange-500: #fc9403;
|
||||
$orange-600: #de7e00;
|
||||
$orange-700: #c26700;
|
||||
$orange-800: #a35100;
|
||||
$orange-900: #853b00;
|
||||
$orange-800: #a35200;
|
||||
$orange-900: #853c00;
|
||||
$orange-950: #592800;
|
||||
|
||||
$red-25: #fef7f6;
|
||||
$red-50: #fbe7e4;
|
||||
$red-100: #f4c4bc;
|
||||
$red-200: #ed9d90;
|
||||
$red-50: #fef6f5;
|
||||
$red-100: #fbe5e1;
|
||||
$red-200: #f2b4a9;
|
||||
$red-300: #e67664;
|
||||
$red-400: #e05842;
|
||||
$red-500: #db3b21;
|
||||
|
@ -74,6 +74,7 @@ $red-600: #c0341d;
|
|||
$red-700: #a62d19;
|
||||
$red-800: #8b2615;
|
||||
$red-900: #711e11;
|
||||
$red-950: #4b140b;
|
||||
|
||||
// GitLab themes
|
||||
|
||||
|
@ -184,8 +185,8 @@ $list-text-disabled-color: $gl-text-color-tertiary;
|
|||
$list-border-light: #eee;
|
||||
$list-border: rgba(0, 0, 0, 0.05);
|
||||
$list-text-height: 42px;
|
||||
$list-warning-row-bg: $orange-50;
|
||||
$list-warning-row-border: $orange-100;
|
||||
$list-warning-row-bg: $orange-100;
|
||||
$list-warning-row-border: $orange-200;
|
||||
$list-warning-row-color: $orange-700;
|
||||
|
||||
/*
|
||||
|
@ -214,8 +215,8 @@ $gl-sidebar-padding: 22px;
|
|||
/*
|
||||
* Misc
|
||||
*/
|
||||
$row-hover: $blue-25;
|
||||
$row-hover-border: $blue-100;
|
||||
$row-hover: $blue-50;
|
||||
$row-hover-border: $blue-200;
|
||||
$progress-color: #c0392b;
|
||||
$header-height: 50px;
|
||||
$new-navbar-height: 40px;
|
||||
|
@ -265,8 +266,8 @@ $time-color: #999;
|
|||
$project-member-show-color: #aaa;
|
||||
$gl-promo-color: #aaa;
|
||||
$error-bg: $red-400;
|
||||
$warning-message-bg: $orange-50;
|
||||
$warning-message-border: $orange-100;
|
||||
$warning-message-bg: $orange-100;
|
||||
$warning-message-border: $orange-200;
|
||||
$warning-message-color: $orange-700;
|
||||
$control-group-descr-color: #666;
|
||||
$table-permission-x-bg: #d9edf7;
|
||||
|
@ -451,17 +452,17 @@ $builds-trace-bg: #111;
|
|||
/*
|
||||
* Callout
|
||||
*/
|
||||
$callout-danger-bg: $red-50;
|
||||
$callout-danger-border: $red-100;
|
||||
$callout-danger-bg: $red-100;
|
||||
$callout-danger-border: $red-200;
|
||||
$callout-danger-color: $red-700;
|
||||
$callout-warning-bg: $orange-50;
|
||||
$callout-warning-border: $orange-100;
|
||||
$callout-warning-bg: $orange-100;
|
||||
$callout-warning-border: $orange-200;
|
||||
$callout-warning-color: $orange-700;
|
||||
$callout-info-bg: $blue-50;
|
||||
$callout-info-border: $blue-100;
|
||||
$callout-info-bg: $blue-100;
|
||||
$callout-info-border: $blue-200;
|
||||
$callout-info-color: $blue-700;
|
||||
$callout-success-bg: $green-50;
|
||||
$callout-success-border: $green-100;
|
||||
$callout-success-bg: $green-100;
|
||||
$callout-success-border: $green-200;
|
||||
$callout-success-color: $green-700;
|
||||
|
||||
/*
|
||||
|
|
|
@ -83,7 +83,7 @@ $space-between-cards: 8px;
|
|||
border-top-color: $color-low-score;
|
||||
|
||||
.card-score-big {
|
||||
background-color: $red-25;
|
||||
background-color: $red-50;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ $space-between-cards: 8px;
|
|||
border-top-color: $color-average-score;
|
||||
|
||||
.card-score-big {
|
||||
background-color: $orange-25;
|
||||
background-color: $orange-50;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ $space-between-cards: 8px;
|
|||
border-top-color: $color-high-score;
|
||||
|
||||
.card-score-big {
|
||||
background-color: $green-25;
|
||||
background-color: $green-50;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -451,7 +451,7 @@
|
|||
}
|
||||
|
||||
.files {
|
||||
margin-top: -1px;
|
||||
margin-top: 1px;
|
||||
|
||||
.diff-file:last-child {
|
||||
margin-bottom: 0;
|
||||
|
@ -586,11 +586,6 @@
|
|||
top: 76px;
|
||||
}
|
||||
|
||||
+ .files,
|
||||
+ .alert {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
&:not(.is-stuck) .diff-stats-additions-deletions-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
@ -605,11 +600,6 @@
|
|||
.inline-parallel-buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
+ .files,
|
||||
+ .alert {
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
.is-confidential {
|
||||
color: $orange-600;
|
||||
background-color: $orange-50;
|
||||
background-color: $orange-100;
|
||||
border-radius: $border-radius-default;
|
||||
padding: 5px;
|
||||
margin: 0 3px 0 -4px;
|
||||
|
|
|
@ -255,7 +255,7 @@ $colors: (
|
|||
|
||||
&.saved {
|
||||
.editor {
|
||||
border-top: solid 2px $green-200;
|
||||
border-top: solid 2px $green-300;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
|
||||
.confidential-issue-warning {
|
||||
color: $orange-600;
|
||||
background-color: $orange-50;
|
||||
background-color: $orange-100;
|
||||
border-radius: $border-radius-default $border-radius-default 0 0;
|
||||
border: 1px solid $border-gray-normal;
|
||||
border-bottom: none;
|
||||
|
|
|
@ -644,20 +644,20 @@ button.mini-pipeline-graph-dropdown-toggle {
|
|||
|
||||
// Dropdown button animation in mini pipeline graph
|
||||
&.ci-status-icon-success {
|
||||
@include mini-pipeline-graph-color($green-50, $green-500, $green-600);
|
||||
@include mini-pipeline-graph-color($green-100, $green-500, $green-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-failed {
|
||||
@include mini-pipeline-graph-color($red-50, $red-500, $red-600);
|
||||
@include mini-pipeline-graph-color($red-100, $red-500, $red-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-pending,
|
||||
&.ci-status-icon-success_with_warnings {
|
||||
@include mini-pipeline-graph-color($orange-50, $orange-500, $orange-600);
|
||||
@include mini-pipeline-graph-color($orange-100, $orange-500, $orange-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-running {
|
||||
@include mini-pipeline-graph-color($blue-50, $blue-400, $blue-600);
|
||||
@include mini-pipeline-graph-color($blue-100, $blue-400, $blue-600);
|
||||
}
|
||||
|
||||
&.ci-status-icon-canceled,
|
||||
|
|
|
@ -291,7 +291,7 @@ table.u2f-registrations {
|
|||
.bordered-box {
|
||||
border: 1px solid $blue-300;
|
||||
border-radius: $border-radius-default;
|
||||
background-color: $blue-25;
|
||||
background-color: $blue-50;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -379,7 +379,7 @@ table.u2f-registrations {
|
|||
|
||||
.nav-wip {
|
||||
border: 1px solid $blue-500;
|
||||
background: $blue-25;
|
||||
background: $blue-50;
|
||||
padding: $gl-padding;
|
||||
margin-bottom: $gl-padding;
|
||||
|
||||
|
|
|
@ -28,9 +28,7 @@ input[type="checkbox"]:hover {
|
|||
}
|
||||
|
||||
.search {
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
margin-top: ($header-height - 35) / 2;
|
||||
margin: 4px 8px 0;
|
||||
|
||||
form {
|
||||
@extend .form-control;
|
||||
|
@ -38,15 +36,23 @@ input[type="checkbox"]:hover {
|
|||
padding: 4px;
|
||||
width: $search-input-width;
|
||||
line-height: 24px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
border-radius: $border-radius-default;
|
||||
transition: border-color ease-in-out $default-transition-duration, background-color ease-in-out $default-transition-duration;
|
||||
|
||||
&:hover {
|
||||
border-color: lighten($dropdown-input-focus-border, 20%);
|
||||
box-shadow: 0 0 4px lighten($search-input-focus-shadow-color, 20%);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.location-text {
|
||||
font-style: normal;
|
||||
.location-badge {
|
||||
font-size: 12px;
|
||||
margin: -4px 4px -4px -4px;
|
||||
line-height: 25px;
|
||||
padding: 4px 8px;
|
||||
border-radius: $border-radius-default 0 0 $border-radius-default;
|
||||
transition: border-color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
|
@ -56,41 +62,26 @@ input[type="checkbox"]:hover {
|
|||
margin-left: 5px;
|
||||
line-height: 25px;
|
||||
width: 98%;
|
||||
color: $white-light;
|
||||
background: none;
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
line-height: 25px;
|
||||
padding: 0 5px;
|
||||
border-radius: $border-radius-default;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
color: $note-disabled-comment-color;
|
||||
display: inline-block;
|
||||
background-color: $gray-normal;
|
||||
vertical-align: top;
|
||||
cursor: default;
|
||||
.search-input::placeholder {
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.search-input-container {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
// Fallback if flexbox is not supported
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
width: 100%;
|
||||
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 0;
|
||||
color: $location-icon-color;
|
||||
|
||||
&::before {
|
||||
font-family: FontAwesome;
|
||||
|
@ -101,7 +92,7 @@ input[type="checkbox"]:hover {
|
|||
|
||||
.search-icon {
|
||||
@extend .fa-search;
|
||||
transition: color 0.15s;
|
||||
transition: color $default-transition-duration;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
|
@ -148,19 +139,30 @@ input[type="checkbox"]:hover {
|
|||
form {
|
||||
@extend .form-control:focus;
|
||||
border-color: $dropdown-input-focus-border;
|
||||
box-shadow: 0 0 4px $search-input-focus-shadow-color;
|
||||
box-shadow: none;
|
||||
|
||||
.search-input-wrap {
|
||||
.search-icon,
|
||||
.clear-icon {
|
||||
color: $gl-text-color-tertiary;
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
color: $gl-text-color;
|
||||
transition: color ease-in-out $default-transition-duration;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: $gl-text-color-tertiary;
|
||||
}
|
||||
}
|
||||
|
||||
.location-badge {
|
||||
transition: all 0.15s;
|
||||
background-color: $location-badge-active-bg;
|
||||
color: $white-light;
|
||||
}
|
||||
|
||||
.search-input-wrap {
|
||||
i {
|
||||
color: $layout-link-gray;
|
||||
}
|
||||
transition: all $default-transition-duration;
|
||||
background-color: $nav-badge-bg;
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
|
||||
&.ci-failed {
|
||||
@include status-color($red-50, $red-500, $red-600);
|
||||
@include status-color($red-100, $red-500, $red-600);
|
||||
}
|
||||
|
||||
&.ci-success {
|
||||
|
@ -39,12 +39,12 @@
|
|||
&.ci-pending,
|
||||
&.ci-failed_with_warnings,
|
||||
&.ci-success_with_warnings {
|
||||
@include status-color($orange-50, $orange-500, $orange-700);
|
||||
@include status-color($orange-100, $orange-500, $orange-700);
|
||||
}
|
||||
|
||||
&.ci-info,
|
||||
&.ci-running {
|
||||
@include status-color($blue-50, $blue-500, $blue-600);
|
||||
@include status-color($blue-100, $blue-500, $blue-600);
|
||||
}
|
||||
|
||||
&.ci-created,
|
||||
|
|
|
@ -15,3 +15,9 @@
|
|||
-ms-animation: none !important;
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
// Disable sticky changes bar for tests
|
||||
.diff-files-changed {
|
||||
position: relative !important;
|
||||
top: 0 !important;
|
||||
}
|
||||
|
|
|
@ -117,19 +117,32 @@ module IssuableCollections
|
|||
key = 'issuable_sort'
|
||||
|
||||
cookies[key] = params[:sort] if params[:sort].present?
|
||||
|
||||
# id_desc and id_asc are old values for these two.
|
||||
cookies[key] = sort_value_recently_created if cookies[key] == 'id_desc'
|
||||
cookies[key] = sort_value_oldest_created if cookies[key] == 'id_asc'
|
||||
|
||||
cookies[key] = update_cookie_value(cookies[key])
|
||||
params[:sort] = cookies[key]
|
||||
end
|
||||
|
||||
def default_sort_order
|
||||
case params[:state]
|
||||
when 'opened', 'all' then sort_value_recently_created
|
||||
when 'opened', 'all' then sort_value_created_date
|
||||
when 'merged', 'closed' then sort_value_recently_updated
|
||||
else sort_value_recently_created
|
||||
else sort_value_created_date
|
||||
end
|
||||
end
|
||||
|
||||
# Update old values to the actual ones.
|
||||
def update_cookie_value(value)
|
||||
case value
|
||||
when 'id_asc' then sort_value_oldest_created
|
||||
when 'id_desc' then sort_value_recently_created
|
||||
when 'created_asc' then sort_value_created_date
|
||||
when 'created_desc' then sort_value_created_date
|
||||
when 'due_date_asc' then sort_value_due_date
|
||||
when 'due_date_desc' then sort_value_due_date
|
||||
when 'milestone_due_asc' then sort_value_milestone
|
||||
when 'milestone_due_desc' then sort_value_milestone
|
||||
when 'downvotes_asc' then sort_value_popularity
|
||||
when 'downvotes_desc' then sort_value_popularity
|
||||
else value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,7 +35,10 @@ class Projects::TreeController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
format.json do
|
||||
render json: TreeSerializer.new(project: @project, repository: @repository, ref: @ref).represent(@tree)
|
||||
# n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/38261
|
||||
Gitlab::GitalyClient.allow_n_plus_1_calls do
|
||||
render json: TreeSerializer.new(project: @project, repository: @repository, ref: @ref).represent(@tree)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,10 +30,4 @@ module AppearancesHelper
|
|||
render 'shared/logo.svg'
|
||||
end
|
||||
end
|
||||
|
||||
def custom_icon(icon_name, size: 16)
|
||||
# We can't simply do the below, because there are some .erb SVGs.
|
||||
# File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe
|
||||
render "shared/icons/#{icon_name}.svg", size: size
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,22 +13,29 @@ module AvatarsHelper
|
|||
user_name = options[:user].try(:name) || options[:user_name]
|
||||
avatar_url = options[:url] || avatar_icon(options[:user] || options[:user_email], avatar_size)
|
||||
has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip]
|
||||
data_attributes = {}
|
||||
data_attributes = options[:data] || {}
|
||||
css_class = %W[avatar s#{avatar_size}].push(*options[:css_class])
|
||||
|
||||
if has_tooltip
|
||||
css_class.push('has-tooltip')
|
||||
data_attributes = { container: 'body' }
|
||||
data_attributes[:container] = 'body'
|
||||
end
|
||||
|
||||
image_tag(
|
||||
avatar_url,
|
||||
if options[:lazy]
|
||||
css_class << 'lazy'
|
||||
data_attributes[:src] = avatar_url
|
||||
avatar_url = LazyImageTagHelper.placeholder_image
|
||||
end
|
||||
|
||||
image_options = {
|
||||
alt: "#{user_name}'s avatar",
|
||||
src: avatar_url,
|
||||
data: data_attributes,
|
||||
class: css_class,
|
||||
alt: "#{user_name}'s avatar",
|
||||
title: user_name,
|
||||
data: data_attributes,
|
||||
lazy: true
|
||||
)
|
||||
title: user_name
|
||||
}
|
||||
|
||||
tag(:img, image_options)
|
||||
end
|
||||
|
||||
def user_avatar(options = {})
|
||||
|
|
|
@ -176,13 +176,15 @@ module CommitsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def view_file_button(commit_sha, diff_new_path, project)
|
||||
def view_file_button(commit_sha, diff_new_path, project, replaced: false)
|
||||
title = replaced ? _('View replaced file @ ') : _('View file @ ')
|
||||
|
||||
link_to(
|
||||
project_blob_path(project,
|
||||
tree_join(commit_sha, diff_new_path)),
|
||||
class: 'btn view-file js-view-file'
|
||||
) do
|
||||
raw('View file @ ') + content_tag(:span, Commit.truncate_sha(commit_sha),
|
||||
raw(title) + content_tag(:span, Commit.truncate_sha(commit_sha),
|
||||
class: 'commit-sha')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -125,7 +125,7 @@ module GroupsHelper
|
|||
end
|
||||
|
||||
def default_help
|
||||
s_("GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner.")
|
||||
s_("GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually.")
|
||||
end
|
||||
|
||||
def ancestor_locked_but_you_can_override(group)
|
||||
|
|
|
@ -17,6 +17,18 @@ module IconsHelper
|
|||
options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options)
|
||||
end
|
||||
|
||||
def custom_icon(icon_name, size: 16)
|
||||
# We can't simply do the below, because there are some .erb SVGs.
|
||||
# File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe
|
||||
render "shared/icons/#{icon_name}.svg", size: size
|
||||
end
|
||||
|
||||
def sprite_icon(icon_name, size: nil, css_class: nil)
|
||||
css_classes = size ? "s#{size}" : nil
|
||||
css_classes << " #{css_class}" unless css_class.blank?
|
||||
content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{image_path('icons.svg')}##{icon_name}" } ), class: css_classes)
|
||||
end
|
||||
|
||||
def audit_icon(names, options = {})
|
||||
case names
|
||||
when "standard"
|
||||
|
|
|
@ -239,8 +239,8 @@ module ProjectsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def has_projects_or_name?(projects, params)
|
||||
!!(params[:name] || any_projects?(projects))
|
||||
def show_projects?(projects, params)
|
||||
!!(params[:personal] || params[:name] || any_projects?(projects))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,34 +1,38 @@
|
|||
module SortingHelper
|
||||
def sort_options_hash
|
||||
{
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_name_desc => sort_title_name_desc,
|
||||
sort_value_recently_updated => sort_title_recently_updated,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated,
|
||||
sort_value_created_date => sort_title_created_date,
|
||||
sort_value_downvotes => sort_title_downvotes,
|
||||
sort_value_due_date => sort_title_due_date,
|
||||
sort_value_due_date_later => sort_title_due_date_later,
|
||||
sort_value_due_date_soon => sort_title_due_date_soon,
|
||||
sort_value_label_priority => sort_title_label_priority,
|
||||
sort_value_largest_group => sort_title_largest_group,
|
||||
sort_value_largest_repo => sort_title_largest_repo,
|
||||
sort_value_milestone => sort_title_milestone,
|
||||
sort_value_milestone_later => sort_title_milestone_later,
|
||||
sort_value_milestone_soon => sort_title_milestone_soon,
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_name_desc => sort_title_name_desc,
|
||||
sort_value_oldest_created => sort_title_oldest_created,
|
||||
sort_value_oldest_signin => sort_title_oldest_signin,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated,
|
||||
sort_value_recently_created => sort_title_recently_created,
|
||||
sort_value_oldest_created => sort_title_oldest_created,
|
||||
sort_value_milestone_soon => sort_title_milestone_soon,
|
||||
sort_value_milestone_later => sort_title_milestone_later,
|
||||
sort_value_due_date_soon => sort_title_due_date_soon,
|
||||
sort_value_due_date_later => sort_title_due_date_later,
|
||||
sort_value_largest_repo => sort_title_largest_repo,
|
||||
sort_value_largest_group => sort_title_largest_group,
|
||||
sort_value_recently_signin => sort_title_recently_signin,
|
||||
sort_value_oldest_signin => sort_title_oldest_signin,
|
||||
sort_value_downvotes => sort_title_downvotes,
|
||||
sort_value_upvotes => sort_title_upvotes,
|
||||
sort_value_priority => sort_title_priority,
|
||||
sort_value_label_priority => sort_title_label_priority
|
||||
sort_value_recently_signin => sort_title_recently_signin,
|
||||
sort_value_recently_updated => sort_title_recently_updated,
|
||||
sort_value_popularity => sort_title_popularity,
|
||||
sort_value_priority => sort_title_priority,
|
||||
sort_value_upvotes => sort_title_upvotes
|
||||
}
|
||||
end
|
||||
|
||||
def projects_sort_options_hash
|
||||
options = {
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_latest_activity => sort_title_latest_activity,
|
||||
sort_value_oldest_activity => sort_title_oldest_activity,
|
||||
sort_value_recently_created => sort_title_recently_created,
|
||||
sort_value_oldest_created => sort_title_oldest_created
|
||||
sort_value_latest_activity => sort_title_latest_activity,
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_oldest_activity => sort_title_oldest_activity,
|
||||
sort_value_oldest_created => sort_title_oldest_created,
|
||||
sort_value_recently_created => sort_title_recently_created
|
||||
}
|
||||
|
||||
if current_controller?('admin/projects')
|
||||
|
@ -40,160 +44,174 @@ module SortingHelper
|
|||
|
||||
def member_sort_options_hash
|
||||
{
|
||||
sort_value_access_level_asc => sort_title_access_level_asc,
|
||||
sort_value_access_level_asc => sort_title_access_level_asc,
|
||||
sort_value_access_level_desc => sort_title_access_level_desc,
|
||||
sort_value_last_joined => sort_title_last_joined,
|
||||
sort_value_oldest_joined => sort_title_oldest_joined,
|
||||
sort_value_name => sort_title_name_asc,
|
||||
sort_value_name_desc => sort_title_name_desc,
|
||||
sort_value_recently_signin => sort_title_recently_signin,
|
||||
sort_value_oldest_signin => sort_title_oldest_signin
|
||||
sort_value_last_joined => sort_title_last_joined,
|
||||
sort_value_name => sort_title_name_asc,
|
||||
sort_value_name_desc => sort_title_name_desc,
|
||||
sort_value_oldest_joined => sort_title_oldest_joined,
|
||||
sort_value_oldest_signin => sort_title_oldest_signin,
|
||||
sort_value_recently_signin => sort_title_recently_signin
|
||||
}
|
||||
end
|
||||
|
||||
def milestone_sort_options_hash
|
||||
{
|
||||
sort_value_name => sort_title_name_asc,
|
||||
sort_value_name_desc => sort_title_name_desc,
|
||||
sort_value_due_date_soon => sort_title_due_date_soon,
|
||||
sort_value_due_date_later => sort_title_due_date_later,
|
||||
sort_value_start_date_soon => sort_title_start_date_soon,
|
||||
sort_value_start_date_later => sort_title_start_date_later
|
||||
sort_value_name => sort_title_name_asc,
|
||||
sort_value_name_desc => sort_title_name_desc,
|
||||
sort_value_due_date_later => sort_title_due_date_later,
|
||||
sort_value_due_date_soon => sort_title_due_date_soon,
|
||||
sort_value_start_date_later => sort_title_start_date_later,
|
||||
sort_value_start_date_soon => sort_title_start_date_soon
|
||||
}
|
||||
end
|
||||
|
||||
def branches_sort_options_hash
|
||||
{
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_recently_updated => sort_title_recently_updated,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated,
|
||||
sort_value_recently_updated => sort_title_recently_updated
|
||||
}
|
||||
end
|
||||
|
||||
def tags_sort_options_hash
|
||||
{
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_recently_updated => sort_title_recently_updated,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated
|
||||
sort_value_name => sort_title_name,
|
||||
sort_value_oldest_updated => sort_title_oldest_updated,
|
||||
sort_value_recently_updated => sort_title_recently_updated
|
||||
}
|
||||
end
|
||||
|
||||
def sort_title_priority
|
||||
'Priority'
|
||||
end
|
||||
|
||||
def sort_title_label_priority
|
||||
'Label priority'
|
||||
end
|
||||
|
||||
def sort_title_oldest_updated
|
||||
'Oldest updated'
|
||||
end
|
||||
|
||||
def sort_title_recently_updated
|
||||
'Last updated'
|
||||
end
|
||||
|
||||
def sort_title_oldest_activity
|
||||
'Oldest updated'
|
||||
end
|
||||
|
||||
def sort_title_latest_activity
|
||||
'Last updated'
|
||||
end
|
||||
|
||||
def sort_title_oldest_created
|
||||
'Oldest created'
|
||||
end
|
||||
|
||||
def sort_title_recently_created
|
||||
'Last created'
|
||||
end
|
||||
|
||||
def sort_title_milestone_soon
|
||||
'Milestone due soon'
|
||||
end
|
||||
|
||||
def sort_title_milestone_later
|
||||
'Milestone due later'
|
||||
end
|
||||
|
||||
def sort_title_due_date_soon
|
||||
'Due soon'
|
||||
end
|
||||
|
||||
def sort_title_due_date_later
|
||||
'Due later'
|
||||
end
|
||||
|
||||
def sort_title_start_date_soon
|
||||
'Start soon'
|
||||
end
|
||||
|
||||
def sort_title_start_date_later
|
||||
'Start later'
|
||||
end
|
||||
|
||||
def sort_title_name
|
||||
'Name'
|
||||
end
|
||||
|
||||
def sort_title_largest_repo
|
||||
'Largest repository'
|
||||
end
|
||||
|
||||
def sort_title_largest_group
|
||||
'Largest group'
|
||||
end
|
||||
|
||||
def sort_title_recently_signin
|
||||
'Recent sign in'
|
||||
end
|
||||
|
||||
def sort_title_oldest_signin
|
||||
'Oldest sign in'
|
||||
end
|
||||
|
||||
def sort_title_downvotes
|
||||
'Least popular'
|
||||
end
|
||||
|
||||
def sort_title_upvotes
|
||||
'Most popular'
|
||||
end
|
||||
|
||||
def sort_title_last_joined
|
||||
'Last joined'
|
||||
end
|
||||
|
||||
def sort_title_oldest_joined
|
||||
'Oldest joined'
|
||||
def sortable_item(item, path, sorted_by)
|
||||
link_to item, path, class: sorted_by == item ? 'is-active' : ''
|
||||
end
|
||||
|
||||
# Titles.
|
||||
def sort_title_access_level_asc
|
||||
'Access level, ascending'
|
||||
s_('SortOptions|Access level, ascending')
|
||||
end
|
||||
|
||||
def sort_title_access_level_desc
|
||||
'Access level, descending'
|
||||
s_('SortOptions|Access level, descending')
|
||||
end
|
||||
|
||||
def sort_title_created_date
|
||||
s_('SortOptions|Created date')
|
||||
end
|
||||
|
||||
def sort_title_downvotes
|
||||
s_('SortOptions|Least popular')
|
||||
end
|
||||
|
||||
def sort_title_due_date
|
||||
s_('SortOptions|Due date')
|
||||
end
|
||||
|
||||
def sort_title_due_date_later
|
||||
s_('SortOptions|Due later')
|
||||
end
|
||||
|
||||
def sort_title_due_date_soon
|
||||
s_('SortOptions|Due soon')
|
||||
end
|
||||
|
||||
def sort_title_label_priority
|
||||
s_('SortOptions|Label priority')
|
||||
end
|
||||
|
||||
def sort_title_largest_group
|
||||
s_('SortOptions|Largest group')
|
||||
end
|
||||
|
||||
def sort_title_largest_repo
|
||||
s_('SortOptions|Largest repository')
|
||||
end
|
||||
|
||||
def sort_title_last_joined
|
||||
s_('SortOptions|Last joined')
|
||||
end
|
||||
|
||||
def sort_title_latest_activity
|
||||
s_('SortOptions|Last updated')
|
||||
end
|
||||
|
||||
def sort_title_milestone
|
||||
s_('SortOptions|Milestone')
|
||||
end
|
||||
|
||||
def sort_title_milestone_later
|
||||
s_('SortOptions|Milestone due later')
|
||||
end
|
||||
|
||||
def sort_title_milestone_soon
|
||||
s_('SortOptions|Milestone due soon')
|
||||
end
|
||||
|
||||
def sort_title_name
|
||||
s_('SortOptions|Name')
|
||||
end
|
||||
|
||||
def sort_title_name_asc
|
||||
'Name, ascending'
|
||||
s_('SortOptions|Name, ascending')
|
||||
end
|
||||
|
||||
def sort_title_name_desc
|
||||
'Name, descending'
|
||||
s_('SortOptions|Name, descending')
|
||||
end
|
||||
|
||||
def sort_value_last_joined
|
||||
'last_joined'
|
||||
def sort_title_oldest_activity
|
||||
s_('SortOptions|Oldest updated')
|
||||
end
|
||||
|
||||
def sort_value_oldest_joined
|
||||
'oldest_joined'
|
||||
def sort_title_oldest_created
|
||||
s_('SortOptions|Oldest created')
|
||||
end
|
||||
|
||||
def sort_title_oldest_joined
|
||||
s_('SortOptions|Oldest joined')
|
||||
end
|
||||
|
||||
def sort_title_oldest_signin
|
||||
s_('SortOptions|Oldest sign in')
|
||||
end
|
||||
|
||||
def sort_title_oldest_updated
|
||||
s_('SortOptions|Oldest updated')
|
||||
end
|
||||
|
||||
def sort_title_popularity
|
||||
s_('SortOptions|Popularity')
|
||||
end
|
||||
|
||||
def sort_title_priority
|
||||
s_('SortOptions|Priority')
|
||||
end
|
||||
|
||||
def sort_title_recently_created
|
||||
s_('SortOptions|Last created')
|
||||
end
|
||||
|
||||
def sort_title_recently_signin
|
||||
s_('SortOptions|Recent sign in')
|
||||
end
|
||||
|
||||
def sort_title_recently_updated
|
||||
s_('SortOptions|Last updated')
|
||||
end
|
||||
|
||||
def sort_title_start_date_later
|
||||
s_('SortOptions|Start later')
|
||||
end
|
||||
|
||||
def sort_title_start_date_soon
|
||||
s_('SortOptions|Start soon')
|
||||
end
|
||||
|
||||
def sort_title_upvotes
|
||||
s_('SortOptions|Most popular')
|
||||
end
|
||||
|
||||
# Values.
|
||||
def sort_value_access_level_asc
|
||||
'access_level_asc'
|
||||
end
|
||||
|
@ -202,90 +220,114 @@ module SortingHelper
|
|||
'access_level_desc'
|
||||
end
|
||||
|
||||
def sort_value_name_desc
|
||||
'name_desc'
|
||||
end
|
||||
|
||||
def sort_value_priority
|
||||
'priority'
|
||||
end
|
||||
|
||||
def sort_value_label_priority
|
||||
'label_priority'
|
||||
end
|
||||
|
||||
def sort_value_oldest_updated
|
||||
'updated_asc'
|
||||
end
|
||||
|
||||
def sort_value_recently_updated
|
||||
'updated_desc'
|
||||
end
|
||||
|
||||
def sort_value_oldest_activity
|
||||
'latest_activity_asc'
|
||||
end
|
||||
|
||||
def sort_value_latest_activity
|
||||
'latest_activity_desc'
|
||||
end
|
||||
|
||||
def sort_value_oldest_created
|
||||
'created_asc'
|
||||
end
|
||||
|
||||
def sort_value_recently_created
|
||||
'created_desc'
|
||||
end
|
||||
|
||||
def sort_value_milestone_soon
|
||||
'milestone_due_asc'
|
||||
end
|
||||
|
||||
def sort_value_milestone_later
|
||||
'milestone_due_desc'
|
||||
end
|
||||
|
||||
def sort_value_due_date_soon
|
||||
'due_date_asc'
|
||||
end
|
||||
|
||||
def sort_value_due_date_later
|
||||
'due_date_desc'
|
||||
end
|
||||
|
||||
def sort_value_start_date_soon
|
||||
'start_date_asc'
|
||||
end
|
||||
|
||||
def sort_value_start_date_later
|
||||
'start_date_desc'
|
||||
end
|
||||
|
||||
def sort_value_name
|
||||
'name_asc'
|
||||
end
|
||||
|
||||
def sort_value_largest_repo
|
||||
'storage_size_desc'
|
||||
end
|
||||
|
||||
def sort_value_largest_group
|
||||
'storage_size_desc'
|
||||
end
|
||||
|
||||
def sort_value_recently_signin
|
||||
'recent_sign_in'
|
||||
end
|
||||
|
||||
def sort_value_oldest_signin
|
||||
'oldest_sign_in'
|
||||
def sort_value_created_date
|
||||
'created_date'
|
||||
end
|
||||
|
||||
def sort_value_downvotes
|
||||
'downvotes_desc'
|
||||
end
|
||||
|
||||
def sort_value_due_date
|
||||
'due_date'
|
||||
end
|
||||
|
||||
def sort_value_due_date_later
|
||||
'due_date_desc'
|
||||
end
|
||||
|
||||
def sort_value_due_date_soon
|
||||
'due_date_asc'
|
||||
end
|
||||
|
||||
def sort_value_label_priority
|
||||
'label_priority'
|
||||
end
|
||||
|
||||
def sort_value_largest_group
|
||||
'storage_size_desc'
|
||||
end
|
||||
|
||||
def sort_value_largest_repo
|
||||
'storage_size_desc'
|
||||
end
|
||||
|
||||
def sort_value_last_joined
|
||||
'last_joined'
|
||||
end
|
||||
|
||||
def sort_value_latest_activity
|
||||
'latest_activity_desc'
|
||||
end
|
||||
|
||||
def sort_value_milestone
|
||||
'milestone'
|
||||
end
|
||||
|
||||
def sort_value_milestone_later
|
||||
'milestone_due_desc'
|
||||
end
|
||||
|
||||
def sort_value_milestone_soon
|
||||
'milestone_due_asc'
|
||||
end
|
||||
|
||||
def sort_value_name
|
||||
'name_asc'
|
||||
end
|
||||
|
||||
def sort_value_name_desc
|
||||
'name_desc'
|
||||
end
|
||||
|
||||
def sort_value_oldest_activity
|
||||
'latest_activity_asc'
|
||||
end
|
||||
|
||||
def sort_value_oldest_created
|
||||
'created_asc'
|
||||
end
|
||||
|
||||
def sort_value_oldest_signin
|
||||
'oldest_sign_in'
|
||||
end
|
||||
|
||||
def sort_value_oldest_joined
|
||||
'oldest_joined'
|
||||
end
|
||||
|
||||
def sort_value_oldest_updated
|
||||
'updated_asc'
|
||||
end
|
||||
|
||||
def sort_value_popularity
|
||||
'popularity'
|
||||
end
|
||||
|
||||
def sort_value_priority
|
||||
'priority'
|
||||
end
|
||||
|
||||
def sort_value_recently_created
|
||||
'created_desc'
|
||||
end
|
||||
|
||||
def sort_value_recently_signin
|
||||
'recent_sign_in'
|
||||
end
|
||||
|
||||
def sort_value_recently_updated
|
||||
'updated_desc'
|
||||
end
|
||||
|
||||
def sort_value_start_date_later
|
||||
'start_date_desc'
|
||||
end
|
||||
|
||||
def sort_value_start_date_soon
|
||||
'start_date_asc'
|
||||
end
|
||||
|
||||
def sort_value_upvotes
|
||||
'upvotes_desc'
|
||||
end
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
module SystemNoteHelper
|
||||
ICON_NAMES_BY_ACTION = {
|
||||
'commit' => 'icon_commit',
|
||||
'description' => 'icon_edit',
|
||||
'merge' => 'icon_merge',
|
||||
'merged' => 'icon_merged',
|
||||
'opened' => 'icon_status_open',
|
||||
'closed' => 'icon_status_closed',
|
||||
'time_tracking' => 'icon_stopwatch',
|
||||
'assignee' => 'icon_user',
|
||||
'title' => 'icon_edit',
|
||||
'task' => 'icon_check_square_o',
|
||||
'label' => 'icon_tags',
|
||||
'cross_reference' => 'icon_random',
|
||||
'branch' => 'icon_code_fork',
|
||||
'confidential' => 'icon_eye_slash',
|
||||
'visible' => 'icon_eye',
|
||||
'milestone' => 'icon_clock_o',
|
||||
'discussion' => 'icon_comment_o',
|
||||
'moved' => 'icon_arrow_circle_o_right',
|
||||
'outdated' => 'icon_edit',
|
||||
'duplicate' => 'icon_clone'
|
||||
'commit' => 'commit',
|
||||
'description' => 'pencil',
|
||||
'merge' => 'git-merge',
|
||||
'merged' => 'git-merge',
|
||||
'opened' => 'issue-open',
|
||||
'closed' => 'issue-close',
|
||||
'time_tracking' => 'timer',
|
||||
'assignee' => 'user',
|
||||
'title' => 'pencil',
|
||||
'task' => 'task-done',
|
||||
'label' => 'label',
|
||||
'cross_reference' => 'comment-dots',
|
||||
'branch' => 'fork',
|
||||
'confidential' => 'eye-slash',
|
||||
'visible' => 'eye',
|
||||
'milestone' => 'clock',
|
||||
'discussion' => 'comment',
|
||||
'moved' => 'arrow-right',
|
||||
'outdated' => 'pencil',
|
||||
'duplicate' => 'issue-duplicate'
|
||||
}.freeze
|
||||
|
||||
def system_note_icon_name(note)
|
||||
|
@ -28,7 +28,7 @@ module SystemNoteHelper
|
|||
|
||||
def icon_for_system_note(note)
|
||||
icon_name = system_note_icon_name(note)
|
||||
custom_icon(icon_name) if icon_name
|
||||
sprite_icon(icon_name) if icon_name
|
||||
end
|
||||
|
||||
extend self
|
||||
|
|