summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock11
-rw-r--r--app/assets/images/new_nav.pngbin0 -> 23771 bytes
-rw-r--r--app/assets/images/old_nav.pngbin0 -> 25617 bytes
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/javascripts/experimental_flags.js11
-rw-r--r--app/assets/javascripts/locale/eo/app.js1
-rw-r--r--app/assets/javascripts/main.js3
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue3
-rw-r--r--app/assets/stylesheets/framework/header.scss17
-rw-r--r--app/assets/stylesheets/framework/variables.scss4
-rw-r--r--app/assets/stylesheets/new_nav.scss267
-rw-r--r--app/helpers/application_helper.rb8
-rw-r--r--app/models/project_services/prometheus_service.rb2
-rw-r--r--app/views/admin/runners/index.html.haml35
-rw-r--r--app/views/layouts/_head.html.haml3
-rw-r--r--app/views/layouts/application.html.haml5
-rw-r--r--app/views/layouts/header/_default.html.haml3
-rw-r--r--app/views/layouts/header/_new.html.haml93
-rw-r--r--app/views/layouts/header/_new_dropdown.haml8
-rw-r--r--app/views/layouts/nav/_new_dashboard.html.haml33
-rw-r--r--app/views/layouts/nav/_new_explore.html.haml19
-rw-r--r--app/views/profiles/preferences/show.html.haml19
-rw-r--r--app/views/projects/deployments/_deployment.html.haml11
-rw-r--r--app/views/projects/environments/show.html.haml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml4
-rw-r--r--changelogs/unreleased/33846-no-runner-for-admin.yml4
-rw-r--r--changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml4
-rw-r--r--changelogs/unreleased/sh-fix-premailer-gem-for-filesystem.yml5
-rw-r--r--config/application.rb1
-rw-r--r--features/dashboard/merge_requests.feature21
-rw-r--r--features/steps/dashboard/merge_requests.rb121
-rw-r--r--lib/gitlab/exclusive_lease.rb19
-rw-r--r--lib/gitlab/i18n.rb3
-rw-r--r--locale/eo/gitlab.po1143
-rw-r--r--locale/eo/gitlab.po.time_stamp0
-rw-r--r--spec/features/admin/admin_runners_spec.rb61
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb97
-rw-r--r--spec/features/dashboard/milestone_filter_spec.rb22
-rw-r--r--spec/javascripts/pipelines/stage_spec.js43
-rw-r--r--spec/lib/gitlab/exclusive_lease_spec.rb13
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb7
-rw-r--r--spec/support/filter_item_select_helper.rb19
45 files changed, 1924 insertions, 233 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8b6c87ae518..89e505709a3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -49,6 +49,8 @@ _This notice should stay as the first item in the CONTRIBUTING.MD file._
Thank you for your interest in contributing to GitLab. This guide details how
to contribute to GitLab in a way that is efficient for everyone.
+Looking for something to work on? Look for the label [Accepting Merge Requests](#i-want-to-contribute).
+
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index ab0fa336dd0..c20c645d7e4 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-5.0.5
+5.0.6
diff --git a/Gemfile b/Gemfile
index 6c53bfe6efe..3cc40eb26a4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -256,7 +256,7 @@ gem 'base32', '~> 0.3.0'
# Sentry integration
gem 'sentry-raven', '~> 2.4.0'
-gem 'premailer-rails', '~> 1.9.0'
+gem 'premailer-rails', '~> 1.9.7'
# I18n
gem 'ruby_parser', '~> 3.8', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 7c9dd051211..817a1fd6aa3 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -137,7 +137,7 @@ GEM
crack (0.4.3)
safe_yaml (~> 1.0.0)
creole (0.5.0)
- css_parser (1.4.1)
+ css_parser (1.5.0)
addressable
d3_rails (3.5.11)
railties (>= 3.1.0)
@@ -589,10 +589,11 @@ GEM
websocket-driver (>= 0.2.0)
posix-spawn (0.3.11)
powerpack (0.1.1)
- premailer (1.8.6)
- css_parser (>= 1.3.6)
+ premailer (1.10.4)
+ addressable
+ css_parser (>= 1.4.10)
htmlentities (>= 4.0.0)
- premailer-rails (1.9.2)
+ premailer-rails (1.9.7)
actionmailer (>= 3, < 6)
premailer (~> 1.7, >= 1.7.9)
prometheus-client-mmap (0.7.0.beta5)
@@ -1045,7 +1046,7 @@ DEPENDENCIES
peek-sidekiq (~> 1.0.3)
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
- premailer-rails (~> 1.9.0)
+ premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.7.0.beta5)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
diff --git a/app/assets/images/new_nav.png b/app/assets/images/new_nav.png
new file mode 100644
index 00000000000..8879d26d341
--- /dev/null
+++ b/app/assets/images/new_nav.png
Binary files differ
diff --git a/app/assets/images/old_nav.png b/app/assets/images/old_nav.png
new file mode 100644
index 00000000000..23fae7aa19e
--- /dev/null
+++ b/app/assets/images/old_nav.png
Binary files differ
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 88b4b567fa9..31a86090242 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -55,6 +55,7 @@ import RefSelectDropdown from './ref_select_dropdown';
import GfmAutoComplete from './gfm_auto_complete';
import ShortcutsBlob from './shortcuts_blob';
import initSettingsPanels from './settings_panels';
+import initExperimentalFlags from './experimental_flags';
(function() {
var Dispatcher;
@@ -120,6 +121,9 @@ import initSettingsPanels from './settings_panels';
}
switch (page) {
+ case 'profiles:preferences:show':
+ initExperimentalFlags();
+ break;
case 'sessions:new':
new UsernameValidator();
new ActiveTabMemoizer();
diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js
new file mode 100644
index 00000000000..dbd3843cef7
--- /dev/null
+++ b/app/assets/javascripts/experimental_flags.js
@@ -0,0 +1,11 @@
+import Cookies from 'js-cookie';
+
+export default () => {
+ $('.js-experiment-feature-toggle').on('change', (e) => {
+ const el = e.target;
+
+ Cookies.set(el.name, el.value, {
+ expires: 365 * 10,
+ });
+ });
+};
diff --git a/app/assets/javascripts/locale/eo/app.js b/app/assets/javascripts/locale/eo/app.js
new file mode 100644
index 00000000000..55f000e9b88
--- /dev/null
+++ b/app/assets/javascripts/locale/eo/app.js
@@ -0,0 +1 @@
+var locales = locales || {}; locales['eo'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 21:59-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-20 06:24-0400","Last-Translator":"Lyubomir Vasilev <lyubomirv@abv.bg>","Language-Team":"Esperanto (https://translate.zanata.org/project/view/GitLab)","Language":"eo","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"eo","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} enmetis %{commit_timeago}"],"About auto deploy":["Pri la aŭtomata disponigado"],"Active":["Aktiva"],"Activity":["Aktiveco"],"Add Changelog":["Aldoni liston de ŝanĝoj"],"Add Contribution guide":["Aldoni gvidliniojn por kontribuado"],"Add License":["Aldoni rajtigilon"],"Add an SSH key to your profile to pull or push via SSH.":["Aldonu SSH-ŝlosilon al via profilo por ebligi al vi eltiri kaj alpuŝi per SSH."],"Add new directory":["Aldoni novan dosierujon"],"Archived project! Repository is read-only":["Arkivita projekto! La deponejo permesas nur legadon"],"Are you sure you want to delete this pipeline schedule?":["Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"],"Attach a file by drag &amp; drop or %{upload_link}":["Alkroĉu dosieron per ŝovmetado aŭ %{upload_link}"],"Branch":["Branĉo","Branĉoj"],"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":["La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aŭtomatan disponigadon, bonvolu elekti Yaml-ŝablonon por GitLab CI kaj enmeti viajn ŝanĝojn. %{link_to_autodeploy_doc}"],"Branches":["Branĉoj"],"Browse files":["Elekti dosierojn"],"ByAuthor|by":["de"],"CI configuration":["Agordoj de seninterrompa integrado"],"Cancel":["Nuligi"],"ChangeTypeActionLabel|Pick into branch":["Elekti en branĉon"],"ChangeTypeActionLabel|Revert in branch":["Malfari en branĉo"],"ChangeTypeAction|Cherry-pick":["Precize elekti"],"ChangeTypeAction|Revert":["Malfari"],"Changelog":["Listo de ŝanĝoj"],"Charts":["Diagramoj"],"Cherry-pick this commit":["Precize elekti ĉi tiun kunmetadon"],"Cherry-pick this merge request":["Precize elekti ĉi tiun peton pri kunfando"],"CiStatusLabel|canceled":["nuligita"],"CiStatusLabel|created":["kreita"],"CiStatusLabel|failed":["malsukcesa"],"CiStatusLabel|manual action":["mana ago"],"CiStatusLabel|passed":["sukcesa"],"CiStatusLabel|passed with warnings":["sukcesa, kun avertoj"],"CiStatusLabel|pending":["okazonta"],"CiStatusLabel|skipped":["transsaltita"],"CiStatusLabel|waiting for manual action":["atendanta manan agon"],"CiStatusText|blocked":["blokita"],"CiStatusText|canceled":["nuligita"],"CiStatusText|created":["kreita"],"CiStatusText|failed":["malsukcesa"],"CiStatusText|manual":["mana"],"CiStatusText|passed":["sukcesa"],"CiStatusText|pending":["okazonta"],"CiStatusText|skipped":["transsaltita"],"CiStatus|running":["plenumiĝanta"],"Commit":["Enmetado","Enmetadoj"],"Commit message":["Mesaĝo pri la enmetado"],"CommitBoxTitle|Commit":["Enmeti"],"CommitMessage|Add %{file_name}":["Aldoni „%{file_name}“"],"Commits":["Enmetadoj"],"Commits|History":["Historio"],"Committed by":["Enmetita de"],"Compare":["Kompari"],"Contribution guide":["Gvidlinioj por kontribuado"],"Contributors":["Kontribuantoj"],"Copy URL to clipboard":["Kopii la adreson en la kopibufron"],"Copy commit SHA to clipboard":["Kopii la identigilon de la enmetado"],"Create New Directory":["Krei novan dosierujon"],"Create directory":["Krei dosierujon"],"Create empty bare repository":["Krei malplenan deponejon"],"Create merge request":["Krei peton pri kunfando"],"Create new...":["Krei novan…"],"CreateNewFork|Fork":["Disbranĉigi"],"CreateTag|Tag":["Etikedo"],"Cron Timezone":["Horzono por Cron"],"Cron syntax":["La sintakso de Cron"],"Custom notification events":["Propraj sciigaj eventoj"],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":["La propraj sciigaj niveloj estas la samaj kiel la niveloj de partoprenado. Uzante la proprajn sciigajn nivelojn, vi ricevos ankaŭ sciigojn por elektitaj de vi eventoj. Por lerni pli, bonvolu vidi %{notification_link}."],"Cycle Analytics":["Cikla analizo"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["La cikla analizo esploras kiom da tempo necesas por disvolvi ideon ĝis ĝi fariĝos realaĵo."],"CycleAnalyticsStage|Code":["Programado"],"CycleAnalyticsStage|Issue":["Problemo"],"CycleAnalyticsStage|Plan":["Plano"],"CycleAnalyticsStage|Production":["Eldonado"],"CycleAnalyticsStage|Review":["Kontrolo"],"CycleAnalyticsStage|Staging":["Preparo por eldono"],"CycleAnalyticsStage|Test":["Testado"],"Define a custom pattern with cron syntax":["Difini propran ŝablonon, uzante la sintakson de Cron"],"Delete":["Forigi"],"Deploy":["Disponigado","Disponigadoj"],"Description":["Priskribo"],"Directory name":["Nomo de dosierujo"],"Don't show again":["Ne montru denove"],"Download":["Elŝuti"],"Download tar":["Elŝuti en formato „tar“"],"Download tar.bz2":["Elŝuti en formato „tar.bz2“"],"Download tar.gz":["Elŝuti en formato „tar.gz“"],"Download zip":["Elŝuti en formato „zip“"],"DownloadArtifacts|Download":["Elŝuti"],"DownloadCommit|Email Patches":["Sendi flikaĵojn per retpoŝto"],"DownloadCommit|Plain Diff":["Normala dosiero kun diferencoj"],"DownloadSource|Download":["Elŝuti"],"Edit":["Redakti"],"Edit Pipeline Schedule %{id}":["Redakti ĉenstablan planon %{id}"],"Every day (at 4:00am)":["Ĉiutage (je 4:00)"],"Every month (on the 1st at 4:00am)":["Ĉiumonate (en la 1a de la monato, je 4:00)"],"Every week (Sundays at 4:00am)":["Ĉiusemajne (en dimanĉo, je 4:00)"],"Failed to change the owner":["Ne eblas ŝanĝi la posedanton"],"Failed to remove the pipeline schedule":["Ne eblas forigi la ĉenstablan planon"],"Files":["Dosieroj"],"Find by path":["Trovi per dosierindiko"],"Find file":["Trovi dosieron"],"FirstPushedBy|First":["Unue"],"FirstPushedBy|pushed by":["alpuŝita de"],"Fork":["Disbranĉigo","Disbranĉigoj"],"ForkedFromProjectPath|Forked from":["Disbranĉigita el"],"From issue creation until deploy to production":["De la kreado de la problemo ĝis la disponigado en la publika versio"],"From merge request merge until deploy to production":["De la kunfandado de la peto pri kunfando ĝis la disponigado en la publika versio"],"Go to your fork":["Al via disbranĉigo"],"GoToYourFork|Fork":["Disbranĉigo"],"Home":["Hejmo"],"Housekeeping successfully started":["La refreŝigo komenciĝis sukcese"],"Import repository":["Enporti deponejon"],"Interval Pattern":["Intervala ŝablono"],"Introducing Cycle Analytics":["Ni prezentas al vi la ciklan analizon"],"LFSStatus|Disabled":["Malŝaltita"],"LFSStatus|Enabled":["Ŝaltita"],"Last %d day":["La lasta %d tago","La lastaj %d tagoj"],"Last Pipeline":["Lasta ĉenstablo"],"Last Update":["Lasta ĝisdatigo"],"Last commit":["Lasta enmetado"],"Learn more in the":["Lernu pli en la"],"Learn more in the|pipeline schedules documentation":["dokumentado pri ĉenstablaj planoj"],"Leave group":["Forlasi la grupon"],"Leave project":["Forlasi la projekton"],"Limited to showing %d event at most":["Limigita al montrado de ne pli ol %d evento","Limigita al montrado de ne pli ol %d eventoj"],"Median":["Mediano"],"MissingSSHKeyWarningLink|add an SSH key":["aldonos SSH-ŝlosilon"],"New Issue":["Nova problemo","Novaj problemoj"],"New Pipeline Schedule":["Nova ĉenstabla plano"],"New branch":["Nova branĉo"],"New directory":["Nova dosierujo"],"New file":["Nova dosiero"],"New issue":["Nova problemo"],"New merge request":["Nova peto pri kunfando"],"New schedule":["Nova plano"],"New snippet":["Nova kodaĵo"],"New tag":["Nova etikedo"],"No repository":["Ne estas deponejo"],"No schedules":["Ne estas planoj"],"Not available":["Ne disponebla"],"Not enough data":["Ne estas sufiĉe da datenoj"],"Notification events":["Sciigaj eventoj"],"NotificationEvent|Close issue":["Fermi problemon"],"NotificationEvent|Close merge request":["Fermi peton pri kunfando"],"NotificationEvent|Failed pipeline":["Malsukcesa ĉenstablo"],"NotificationEvent|Merge merge request":["Apliki peton pri kunfando"],"NotificationEvent|New issue":["Nova problemo"],"NotificationEvent|New merge request":["Nova peto pri kunfando"],"NotificationEvent|New note":["Nova noto"],"NotificationEvent|Reassign issue":["Reatribui problemon"],"NotificationEvent|Reassign merge request":["Reatribui peton pri kunfando"],"NotificationEvent|Reopen issue":["Remalfermi problemon"],"NotificationEvent|Successful pipeline":["Sukcesa ĉenstablo"],"NotificationLevel|Custom":["Propraj"],"NotificationLevel|Disabled":["Malŝaltitaj"],"NotificationLevel|Global":["Ĝeneralaj"],"NotificationLevel|On mention":["Ĉe mencio"],"NotificationLevel|Participate":["Partoprenado"],"NotificationLevel|Watch":["Rigardado"],"OfSearchInADropdown|Filter":["Filtrilo"],"OpenedNDaysAgo|Opened":["Malfermita"],"Options":["Opcioj"],"Owner":["Posedanto"],"Pipeline":["Ĉenstablo"],"Pipeline Health":["Stato"],"Pipeline Schedule":["Ĉenstabla plano"],"Pipeline Schedules":["Ĉenstablaj planoj"],"PipelineSchedules|Activated":["Ŝaltita"],"PipelineSchedules|Active":["Ŝaltitaj"],"PipelineSchedules|All":["Ĉiuj"],"PipelineSchedules|Inactive":["Malŝaltitaj"],"PipelineSchedules|Next Run":["Sekvanta plenumo"],"PipelineSchedules|None":["Nenio"],"PipelineSchedules|Provide a short description for this pipeline":["Entajpu mallongan priskribon pri ĉi tiu ĉenstablo"],"PipelineSchedules|Take ownership":["Akiri posedon"],"PipelineSchedules|Target":["Celo"],"PipelineSheduleIntervalPattern|Custom":["Propra"],"Pipeline|with stage":["kun etapo"],"Pipeline|with stages":["kun etapoj"],"Project '%{project_name}' queued for deletion.":["La projekto „%{project_name}“ estis alvicigita por forigado."],"Project '%{project_name}' was successfully created.":["La projekto „%{project_name}“ estis sukcese kreita."],"Project '%{project_name}' was successfully updated.":["La projekto „%{project_name}“ estis sukcese ĝisdatigita."],"Project '%{project_name}' will be deleted.":["La projekto „%{project_name}“ estos forigita."],"Project access must be granted explicitly to each user.":["Ĉiu uzanto devas akiri propran atingon al la projekto."],"Project export could not be deleted.":["Ne eblas forigi la projektan elporton."],"Project export has been deleted.":["La projekta elporto estis forigita."],"Project export link has expired. Please generate a new export from your project settings.":["La ligilo por la projekta elporto eksvalidiĝis. Bonvolu krei novan elporton en la agordoj de la projekto."],"Project export started. A download link will be sent by email.":["La elporto de la projekto komenciĝis. Vi ricevos ligilon per retpoŝto por elŝuti la datenoj."],"Project home":["Hejmo de la projekto"],"ProjectFeature|Disabled":["Malŝaltita"],"ProjectFeature|Everyone with access":["Ĉiu, kiu havas atingon"],"ProjectFeature|Only team members":["Nur skipanoj"],"ProjectFileTree|Name":["Nomo"],"ProjectLastActivity|Never":["Neniam"],"ProjectLifecycle|Stage":["Etapo"],"ProjectNetworkGraph|Graph":["Grafeo"],"Read more":["Legu pli"],"Readme":["LeguMin"],"RefSwitcher|Branches":["Branĉoj"],"RefSwitcher|Tags":["Etikedoj"],"Related Commits":["Rilataj enmetadoj"],"Related Deployed Jobs":["Rilataj disponigitaj taskoj"],"Related Issues":["Rilataj problemoj"],"Related Jobs":["Rilataj taskoj"],"Related Merge Requests":["Rilataj petoj pri kunfando"],"Related Merged Requests":["Rilataj aplikitaj petoj pri kunfando"],"Remind later":["Rememorigu denove"],"Remove project":["Forigi la projekton"],"Request Access":["Peti atingeblon"],"Revert this commit":["Malfari ĉi tiun enmetadon"],"Revert this merge request":["Malfari ĉi tiun peton pri kunfando"],"Save pipeline schedule":["Konservi ĉenstablan planon"],"Schedule a new pipeline":["Plani novan ĉenstablon"],"Scheduling Pipelines":["Planado de la ĉenstabloj"],"Search branches and tags":["Serĉu branĉon aŭ etikedon"],"Select Archive Format":["Elektu formaton de arkivo"],"Select a timezone":["Elektu horzonon"],"Select target branch":["Elektu celan branĉon"],"Set a password on your account to pull or push via %{protocol}":["Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuŝi per %{protocol}"],"Set up CI":["Agordi SI"],"Set up Koding":["Agordi „Koding“"],"Set up auto deploy":["Agordi aŭtomatan disponigadon"],"SetPasswordToCloneLink|set a password":["kreos pasvorton"],"Showing %d event":["Estas montrata %d evento","Estas montrataj %d eventoj"],"Source code":["Kodo"],"StarProject|Star":["Steligi"],"Start a %{new_merge_request} with these changes":["Kreu %{new_merge_request} kun ĉi tiuj ŝanĝoj"],"Switch branch/tag":["Iri al branĉo/etikedo"],"Tag":["Etikedo","Etikedoj"],"Tags":["Etikedoj"],"Target Branch":["Cela branĉo"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["La etapo de programado montras la tempon de la unua enmetado ĝis la kreado de la peto pri kunfando. La datenoj aldoniĝos aŭtomate ĉi tie post kiam vi kreas la unuan peton pri kunfando."],"The collection of events added to the data gathered for that stage.":["La aro da eventoj, kiuj estas aldonitaj al la datenoj kolektitaj por la etapo."],"The fork relationship has been removed.":["La rilato de disbranĉigo estis forigita."],"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.":["La etapo de la problemo montras kiom la tempo pasas de la kreado de problemo ĝis la atribuado de la problemo al cela etapo de la projekto, aŭ al listo sur la problemtabulo. Komencu krei problemojn por vidi la datenojn por ĉi tiu etapo."],"The phase of the development lifecycle.":["La etapo de la disvolva ciklo."],"The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":["La ĉenstabla plano plenumas ĉenstablojn en la estonteco, ripete, por difinitaj branĉoj aŭ etikedoj. Tiuj planitaj ĉenstabloj heredos la limigitan atingon al la projekto de la rilata uzanto."],"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.":["La etapo de la plano montras la tempon de la antaŭa ŝtupo ĝis la alpuŝado de via unua enmetado. Ĉi tiu tempo aldoniĝos aŭtomate post kiam vi alpuŝas la unuan enmetadon."],"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.":["La etapo de eldonado montras la tutan tempon de la kreado de problemo ĝis la disponigado en la publika versio. La datenoj aldoniĝos aŭtomate post kiam vi kompletigos plenan ciklon de ideo ĝis realaĵo."],"The project can be accessed by any logged in user.":["Ĉiu ensalutita uzanto havas atingon al la projekto"],"The project can be accessed without any authentication.":["Ĉiu povas havi atingon al la projekto, sen ensaluti"],"The repository for this project does not exist.":["La deponejo por ĉi tiu projekto ne ekzistas."],"The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.":["La etapo de la kontrolo montras la tempon de la kreado de la peto pri kunfando ĝis ĝia aplikado. La datenoj aldoniĝos aŭtomate post kiam vi aplikos la unuan peton pri kunfando."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["La etapo de preparo por eldono montras la tempon inter la aplikado de la peto pri kunfando kaj la disponigado de la kodo en la publika versio. La datenoj aldoniĝos aŭtomate post kiam vi faros la unuan disponigadon en la publika versio."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["La etapo de testado montras kiom da tempo necesas al „GitLab CI“ por plenumi ĉiujn ĉenstablojn por la rilata peto pri kunfando. La datenoj aldoniĝos aŭtomate post kiam via unua ĉenstablo finiĝos."],"The time taken by each data entry gathered by that stage.":["La tempo, kiu estas necesa por ĉiu dateno kolektita de la etapo."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["La valoro, kiu troviĝas en la mezo de aro da rigardataj valoroj. Ekzemple: inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas (5+7)/2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":["Ĉi tiu signifas, ke vi ne povos alpuŝi kodon, antaŭ ol vi kreos malplenan deponejon aŭ enportos jam ekzistantan."],"Time before an issue gets scheduled":["Tempo antaŭ problemo estas planita por ellabori"],"Time before an issue starts implementation":["Tempo antaŭ la komenco de laboro super problemo"],"Time between merge request creation and merge/close":["Tempo inter la kreado de poeto pri kunfando kaj ĝia aplikado/fermado"],"Time until first merge request":["Tempo ĝis la unua peto pri kunfando"],"Timeago|%s days ago":["antaŭ %s tagoj"],"Timeago|%s days remaining":["restas %s tagoj"],"Timeago|%s hours remaining":["restas %s horoj"],"Timeago|%s minutes ago":["antaŭ %s minutoj"],"Timeago|%s minutes remaining":["restas %s minutoj"],"Timeago|%s months ago":["antaŭ %s monatoj"],"Timeago|%s months remaining":["restas %s monatoj"],"Timeago|%s seconds remaining":["restas %s sekundoj"],"Timeago|%s weeks ago":["antaŭ %s semajnoj"],"Timeago|%s weeks remaining":["restas %s semajnoj"],"Timeago|%s years ago":["antaŭ %s jaroj"],"Timeago|%s years remaining":["restas %s jaroj"],"Timeago|1 day remaining":["restas 1 tago"],"Timeago|1 hour remaining":["restas 1 horo"],"Timeago|1 minute remaining":["restas 1 minuto"],"Timeago|1 month remaining":["restas 1 monato"],"Timeago|1 week remaining":["restas 1 semajno"],"Timeago|1 year remaining":["restas 1 jaro"],"Timeago|Past due":["Malfruiĝis"],"Timeago|a day ago":["antaŭ unu tago"],"Timeago|a month ago":["antaŭ unu monato"],"Timeago|a week ago":["antaŭ unu semajno"],"Timeago|a while":["antaŭ iom da tempo"],"Timeago|a year ago":["antaŭ unu jaro"],"Timeago|about %s hours ago":["antaŭ ĉirkaŭ %s horoj"],"Timeago|about a minute ago":["antaŭ ĉirkaŭ unu minuto"],"Timeago|about an hour ago":["antaŭ ĉirkaŭ unu horo"],"Timeago|in %s days":["post %s tagoj"],"Timeago|in %s hours":["post %s horoj"],"Timeago|in %s minutes":["post %s minutoj"],"Timeago|in %s months":["post %s monatoj"],"Timeago|in %s seconds":["post %s sekundoj"],"Timeago|in %s weeks":["post %s semajnoj"],"Timeago|in %s years":["post %s jaroj"],"Timeago|in 1 day":["post 1 tago"],"Timeago|in 1 hour":["post 1 horo"],"Timeago|in 1 minute":["post 1 minuto"],"Timeago|in 1 month":["post 1 monato"],"Timeago|in 1 week":["post 1 semajno"],"Timeago|in 1 year":["post 1 jaro"],"Timeago|less than a minute ago":["antaŭ malpli ol minuto"],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Totala tempo"],"Total test time for all commits/merges":["Totala tempo por la testado de ĉiuj enmetadoj/kunfandoj"],"Unstar":["Malsteligi"],"Upload New File":["Alŝuti novan dosieron"],"Upload file":["Alŝuti dosieron"],"Use your global notification setting":["Uzi vian ĝeneralan agordon pri la sciigoj"],"VisibilityLevel|Internal":["Interna"],"VisibilityLevel|Private":["Privata"],"VisibilityLevel|Public":["Publika"],"Want to see the data? Please ask an administrator for access.":["Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."],"We don't have enough data to show this stage.":["Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."],"Withdraw Access Request":["Nuligi la peton pri atingeblo"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Vi forigos „%{project_name_with_namespace}“.\\nOni NE POVAS malfari la forigon de projekto!\\nĈu vi estas ABSOLUTE certa?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Vi forigos la rilaton de la disbranĉigo al la originala projekto, „%{forked_from_project}“. Ĉu vi estas ABSOLUTE certa?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Vi transigos „%{project_name_with_namespace}“ al alia posedanto. Ĉu vi estas ABSOLUTE certa?"],"You can only add files when you are on a branch":["Oni povas aldoni dosierojn nur kiam oni estas en branĉo"],"You have reached your project limit":["Vi ne povas krei pliajn projektojn"],"You must sign in to star a project":["Oni devas ensaluti por steligi projekton"],"You need permission.":["VI bezonas permeson."],"You will not get any notifications via email":["VI ne ricevos sciigojn per retpoŝto"],"You will only receive notifications for the events you choose":["Vi ricevos sciigojn nur por la eventoj elektitaj de vi"],"You will only receive notifications for threads you have participated in":["Vi ricevos sciigojn nur por la fadenoj, en kiuj vi partoprenis"],"You will receive notifications for any activity":["Vi ricevos sciigojn por ĉiu ago"],"You will receive notifications only for comments in which you were @mentioned":["Vi ricevos sciigojn nur por komentoj, en kiuj vi estas @menciita"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["Vi ne povos eltiri aŭ alpuŝi kodon per %{protocol} antaŭ ol vi %{set_password_link} por via konto"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["Vi ne povos eltiri aŭ alpuŝi kodon per SSH antaŭ ol vi %{add_ssh_key_link} al via profilo"],"Your name":["Via nomo"],"day":["tago","tagoj"],"new merge request":["novan peton pri kunfando"],"notification emails":["sciigoj per retpoŝto"],"parent":["patro","patroj"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index ed7629948ca..d27b4ec78c6 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -299,9 +299,10 @@ $(function () {
// Commit show suppressed diff
});
$('.navbar-toggle').on('click', function () {
- $('.header-content .title').toggle();
+ $('.header-content .title, .header-content .navbar-sub-nav').toggle();
$('.header-content .header-logo').toggle();
$('.header-content .navbar-collapse').toggle();
+ $('.js-navbar-toggle-left, .js-navbar-toggle-right, .title-container').toggle();
return $('.navbar-toggle').toggleClass('active');
});
// Show/hide comments on diff
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index e98f35bb58c..87b2725a045 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -40,7 +40,6 @@ export default {
return {
isLoading: false,
dropdownContent: '',
- endpoint: this.stage.dropdown_path,
};
},
@@ -73,7 +72,7 @@ export default {
},
fetchJobs() {
- this.$http.get(this.endpoint)
+ this.$http.get(this.stage.dropdown_path)
.then((response) => {
this.dropdownContent = response.json().html;
this.isLoading = false;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 94986badaf9..5bd6c095109 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -34,6 +34,8 @@ header {
top: 0;
left: 0;
right: 0;
+ color: $gl-text-color-secondary;
+ border-radius: 0;
@media (max-width: $screen-xs-min) {
padding: 0 16px;
@@ -59,7 +61,7 @@ header {
padding: 0;
.nav > li > a {
- color: $gl-text-color-secondary;
+ color: currentColor;
font-size: 18px;
padding: 0;
margin: (($header-height - 28) / 2) 3px;
@@ -84,7 +86,7 @@ header {
&:hover,
&:focus,
&:active {
- background-color: $gray-light;
+ background-color: transparent;
color: $gl-text-color;
svg {
@@ -96,13 +98,19 @@ header {
font-size: 14px;
}
+ .fa-chevron-down {
+ position: relative;
+ top: -3px;
+ font-size: 10px;
+ }
+
svg {
position: relative;
top: 2px;
height: 17px;
// hack to get SVG to line up with FA icons
width: 23px;
- fill: $gl-text-color-secondary;
+ fill: currentColor;
}
}
@@ -225,7 +233,7 @@ header {
}
a {
- color: $gl-text-color;
+ color: currentColor;
&:hover {
text-decoration: underline;
@@ -346,6 +354,7 @@ header {
width: auto;
min-width: 140px;
margin-top: -5px;
+ color: $gl-text-color;
left: auto;
.current-user {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 476427c1593..630f557602c 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -74,6 +74,10 @@ $red-700: #a62d19;
$red-800: #8b2615;
$red-900: #711e11;
+$purple-700: #4a2192;
+$purple-800: #2c0a5c;
+$purple-900: #380d75;
+
$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/new_nav.scss
new file mode 100644
index 00000000000..441bfc479f6
--- /dev/null
+++ b/app/assets/stylesheets/new_nav.scss
@@ -0,0 +1,267 @@
+@import "framework/variables";
+@import 'framework/tw_bootstrap_variables';
+@import "bootstrap/variables";
+
+header.navbar-gitlab-new {
+ color: $white-light;
+ background-color: $purple-900;
+ border-bottom: 0;
+
+ .header-content {
+ padding-left: 0;
+
+ .title-container {
+ padding-top: 0;
+ overflow: visible;
+ }
+
+ .title {
+ display: block;
+ height: 100%;
+ padding-right: 0;
+ color: currentColor;
+
+ > a {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ padding-top: 3px;
+ padding-right: $gl-padding;
+ padding-left: $gl-padding;
+ margin-left: -$gl-padding;
+ border-bottom: 3px solid transparent;
+
+ @media (min-width: $screen-sm-min) {
+ padding-right: $gl-padding;
+ padding-left: $gl-padding;
+ }
+
+ svg {
+ margin-top: -3px;
+
+ @media (min-width: $screen-sm-min) {
+ margin-right: 10px;
+ }
+ }
+
+ &:hover,
+ &:focus {
+ color: currentColor;
+ text-decoration: none;
+ border-bottom-color: $white-light;
+ }
+ }
+ }
+
+ .dropdown.open {
+ > a {
+ border-bottom-color: $white-light;
+ }
+ }
+
+ .dropdown-menu {
+ margin-top: 4px;
+ min-width: 130px;
+
+ @media (max-width: $screen-xs-max) {
+ left: auto;
+ right: 0;
+ }
+ }
+ }
+
+ .navbar-collapse {
+ padding-left: 0;
+ color: $white-light;
+ box-shadow: 0;
+
+ @media (max-width: $screen-xs-max) {
+ margin-left: -$gl-padding;
+ margin-right: -10px;
+ }
+
+ .dropdown-bold-header {
+ color: initial;
+ }
+
+ .nav {
+ > li:not(.hidden-xs) a {
+ @media (max-width: $screen-xs-max) {
+ margin-left: 0;
+ min-width: 100%;
+ }
+ }
+ }
+ }
+
+ .container-fluid {
+ .navbar-toggle {
+ min-width: 45px;
+ padding: 6px $gl-padding;
+ margin-right: -7px;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+ border-left: 1px solid lighten($purple-700, 10%);
+
+ &:hover,
+ &:focus,
+ &.active {
+ color: currentColor;
+ background-color: transparent;
+ }
+ }
+
+ .navbar-nav {
+ @media (max-width: $screen-xs-max) {
+ display: flex;
+ padding-right: 10px;
+ }
+
+ li {
+ .badge {
+ box-shadow: none;
+ }
+ }
+ }
+
+ .nav > li {
+ &.header-user {
+ @media (max-width: $screen-xs-max) {
+ padding-left: 10px;
+ }
+ }
+
+ > a {
+ background: none;
+ opacity: .9;
+ will-change: opacity;
+
+ &.header-user-dropdown-toggle {
+ .header-user-avatar {
+ border-color: $white-light;
+ }
+ }
+
+ &:hover,
+ &:focus {
+ color: $white-light;
+ opacity: 1;
+
+ > svg {
+ fill: $white-light;
+ }
+
+ &.header-user-dropdown-toggle {
+ .header-user-avatar {
+ border-color: $white-light;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+.navbar-sub-nav {
+ display: flex;
+ margin-bottom: 0;
+ color: $white-light;
+
+ > li {
+ &.active > a,
+ a:hover,
+ a:focus {
+ border-bottom-color: $white-light;
+ text-decoration: none;
+ outline: 0;
+ opacity: 1;
+ }
+
+ > a {
+ display: block;
+ padding: 16px 10px 13px;
+ font-size: 13px;
+ color: currentColor;
+ border-bottom: 3px solid transparent;
+ opacity: .9;
+ will-change: opacity;
+
+ @media (min-width: $screen-sm-min) {
+ padding: 15px $gl-padding 12px;
+ font-size: 14px;
+ }
+ }
+ }
+
+ .dropdown-chevron {
+ position: relative;
+ top: -1px;
+ font-size: 10px;
+ }
+}
+
+.header-user .dropdown-menu-nav,
+.header-new .dropdown-menu-nav {
+ margin-top: 4px;
+}
+
+.search {
+ form {
+ border-color: $purple-800;
+
+ &:hover {
+ border-color: rgba($white-light, .6);
+ box-shadow: none;
+ }
+ }
+
+ &.search-active form {
+ border-color: $white-light;
+ }
+
+ form,
+ .search-input {
+ background-color: $purple-700;
+ }
+
+ .search-input {
+ color: $white-light;
+ }
+
+ .search-input::placeholder {
+ color: rgba($white-light, .6);
+ }
+
+ .location-badge {
+ font-size: 12px;
+ color: rgba($white-light, .6);
+ background-color: $purple-800;
+ transition: color 0.15s;
+ will-change: color;
+ }
+
+ .search-input-wrap {
+ .search-icon,
+ .clear-icon {
+ color: rgba($white-light, .6);
+ }
+ }
+
+ &.search-active {
+ .location-badge {
+ color: $white-light;
+ background-color: $purple-800;
+ }
+
+ .search-input-wrap {
+ .search-icon {
+ color: rgba($white-light, .6);
+ }
+
+ .clear-icon {
+ color: $white-light;
+ }
+ }
+ }
+}
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a3b243fccb7..dc7ff78f3df 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -300,4 +300,12 @@ module ApplicationHelper
"https://www.twitter.com/#{name}"
end
end
+
+ def can_toggle_new_nav?
+ Rails.env.development?
+ end
+
+ def show_new_nav?
+ cookies["new_nav"] == "true"
+ end
end
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index c9df678f97e..217f753f05f 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -60,7 +60,7 @@ class PrometheusService < MonitoringService
def deployment_metrics(deployment)
metrics = with_reactive_cache(Gitlab::Prometheus::Queries::DeploymentQuery.name, deployment.id, &method(:rename_data_to_metrics))
- metrics&.merge(deployment_time: created_at.to_i) || {}
+ metrics&.merge(deployment_time: deployment.created_at.to_i) || {}
end
def additional_environment_metrics(environment)
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index e242e851b4d..2da8f615470 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -58,20 +58,23 @@
%br
- .table-holder
- %table.table
- %thead
- %tr
- %th Type
- %th Runner token
- %th Description
- %th Version
- %th Projects
- %th Jobs
- %th Tags
- %th Last contact
- %th
+ - if @runners.any?
+ .table-holder
+ %table.table
+ %thead
+ %tr
+ %th Type
+ %th Runner token
+ %th Description
+ %th Version
+ %th Projects
+ %th Jobs
+ %th Tags
+ %th Last contact
+ %th
- - @runners.each do |runner|
- = render "admin/runners/runner", runner: runner
- = paginate @runners, theme: "gitlab"
+ - @runners.each do |runner|
+ = render "admin/runners/runner", runner: runner
+ = paginate @runners, theme: "gitlab"
+ - else
+ .nothing-here-block No runners found
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index eea33b5966f..f7a1d7e8844 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -30,6 +30,9 @@
= stylesheet_link_tag "test", media: "all" if Rails.env.test?
= stylesheet_link_tag 'peek' if peek_enabled?
+ - if show_new_nav?
+ = stylesheet_link_tag "new_nav", media: "all"
+
= Gon::Base.render_data
= webpack_bundle_tag "runtime"
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 2b07273a0a8..d879df8fc82 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -4,7 +4,10 @@
%body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } }
= render "layouts/init_auto_complete" if @gfm_form
= render 'peek/bar'
- = render "layouts/header/default", title: header_title
+ - if show_new_nav?
+ = render "layouts/header/new"
+ - else
+ = render "layouts/header/default", title: header_title
= render 'layouts/page', sidebar: sidebar, nav: nav
= yield :scripts_body
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 249253f4906..f056c0af968 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -74,6 +74,9 @@
= link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
%li
= link_to "Settings", profile_path
+ - if can_toggle_new_nav?
+ %li
+ = link_to "Turn on new nav", profile_preferences_path(anchor: "new-navigation")
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
diff --git a/app/views/layouts/header/_new.html.haml b/app/views/layouts/header/_new.html.haml
new file mode 100644
index 00000000000..c0833c64911
--- /dev/null
+++ b/app/views/layouts/header/_new.html.haml
@@ -0,0 +1,93 @@
+%header.navbar.navbar-gitlab.navbar-gitlab-new{ class: nav_header_class }
+ %a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
+ .container-fluid
+ .header-content
+ .title-container
+ %h1.title
+ = link_to root_path, title: 'Dashboard' do
+ = brand_header_logo
+ %span.hidden-xs
+ GitLab
+
+ - if current_user
+ = render "layouts/nav/new_dashboard"
+ - else
+ = render "layouts/nav/new_explore"
+
+ .navbar-collapse.collapse
+ %ul.nav.navbar-nav
+ %li.hidden-sm.hidden-xs
+ = render 'layouts/search' unless current_controller?(:search)
+ %li.visible-sm-inline-block.visible-xs-inline-block
+ = link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('search')
+ - if current_user
+ - if session[:impersonator_id]
+ %li.impersonation
+ = link_to admin_impersonation_path, method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
+ = icon('user-secret fw')
+ - if current_user.admin?
+ %li
+ = link_to admin_root_path, title: 'Admin area', aria: { label: "Admin area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('wrench fw')
+ = render 'layouts/header/new_dropdown'
+ - if Gitlab::Sherlock.enabled?
+ %li
+ = link_to sherlock_transactions_path, title: 'Sherlock Transactions',
+ data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('tachometer fw')
+ %li
+ = link_to assigned_issues_dashboard_path, title: 'Issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('hashtag fw')
+ - issues_count = assigned_issuables_count(:issues)
+ %span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
+ = number_with_delimiter(issues_count)
+ %li
+ = link_to assigned_mrs_dashboard_path, title: 'Merge requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = custom_icon('mr_bold')
+ - merge_requests_count = assigned_issuables_count(:merge_requests)
+ %span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) }
+ = number_with_delimiter(merge_requests_count)
+ %li
+ = link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('check-circle fw')
+ %span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
+ = todos_count_format(todos_pending_count)
+ %li.header-user.dropdown
+ = link_to current_user, class: "header-user-dropdown-toggle", data: { toggle: "dropdown" } do
+ = image_tag avatar_icon(current_user, 26), width: 26, height: 26, class: "header-user-avatar"
+ = icon('chevron-down')
+ .dropdown-menu-nav.dropdown-menu-align-right
+ %ul
+ %li.current-user
+ .user-name.bold
+ = current_user.name
+ @#{current_user.username}
+ %li.divider
+ %li
+ = link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
+ %li
+ = link_to "Settings", profile_path
+ %li
+ = link_to "Turn off new nav", profile_preferences_path(anchor: "new-navigation")
+ %li.divider
+ %li
+ = link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
+ - else
+ %li
+ %div
+ = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
+
+ %button.navbar-toggle.hidden-sm.hidden-md.hidden-lg{ type: 'button' }
+ %span.sr-only Toggle navigation
+ = icon('ellipsis-v', class: 'js-navbar-toggle-right')
+ = icon('times', class: 'js-navbar-toggle-left', style: 'display: none;')
+
+ = yield :header_content
+
+= render 'shared/outdated_browser'
+
+- if @project && !@project.empty_repo?
+ - if ref = @ref || @project.repository.root_ref
+ :javascript
+ var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, ref)}";
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index 969c423b032..9ff1164f2ee 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -1,7 +1,11 @@
%li.header-new.dropdown
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", title: "New...", ref: 'tooltip', aria: { label: "New..." }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body' } do
- = icon('plus fw')
- = icon('caret-down')
+ - if show_new_nav?
+ = icon('plus')
+ = icon('chevron-down')
+ - else
+ = icon('plus fw')
+ = icon('caret-down')
.dropdown-menu-nav.dropdown-menu-align-right
%ul
- if @group&.persisted?
diff --git a/app/views/layouts/nav/_new_dashboard.html.haml b/app/views/layouts/nav/_new_dashboard.html.haml
new file mode 100644
index 00000000000..7109baa4dad
--- /dev/null
+++ b/app/views/layouts/nav/_new_dashboard.html.haml
@@ -0,0 +1,33 @@
+%ul.list-unstyled.navbar-sub-nav
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "home"}) do
+ = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
+ Projects
+
+ = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
+ = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
+ Groups
+
+ = nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm" }) do
+ = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
+ Activity
+
+ %li.dropdown
+ %a{ href: "#", data: { toggle: "dropdown" } }
+ More
+ = icon("chevron-down", class: "dropdown-chevron")
+ .dropdown-menu
+ %ul
+ = nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm" }) do
+ = link_to activity_dashboard_path, title: 'Activity' do
+ Activity
+
+ = nav_link(controller: 'dashboard/milestones') do
+ = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
+ Milestones
+
+ = nav_link(controller: 'dashboard/snippets') do
+ = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
+ Snippets
+ %li.divider
+ %li
+ = link_to "Help", help_path, title: 'About GitLab CE'
diff --git a/app/views/layouts/nav/_new_explore.html.haml b/app/views/layouts/nav/_new_explore.html.haml
new file mode 100644
index 00000000000..40385f251e3
--- /dev/null
+++ b/app/views/layouts/nav/_new_explore.html.haml
@@ -0,0 +1,19 @@
+%ul.list-unstyled.navbar-sub-nav
+ = nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
+ = link_to explore_root_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
+ Projects
+ = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
+ = link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do
+ Groups
+ %li.dropdown
+ %a{ href: "#", data: { toggle: "dropdown" } }
+ More
+ = icon("chevron-down", class: "dropdown-chevron")
+ .dropdown-menu
+ %ul
+ = nav_link(controller: :snippets) do
+ = link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do
+ Snippets
+ %li.divider
+ %li
+ = link_to "Help", help_path, title: 'About GitLab CE'
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 0ff19b3eab1..0b5995415e9 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -15,6 +15,25 @@
.preview= image_tag "#{scheme.css_class}-scheme-preview.png"
= f.radio_button :color_scheme_id, scheme.id
= scheme.name
+ - if can_toggle_new_nav?
+ .col-sm-12
+ %hr
+ .col-lg-3.profile-settings-sidebar#new-navigation
+ %h4.prepend-top-0
+ New Navigation
+ %p
+ This setting allows you to turn on or off the new upcoming navigation concept.
+ = succeed '.' do
+ = link_to 'Learn more', '', target: '_blank'
+ .col-lg-9.syntax-theme
+ = label_tag do
+ .preview= image_tag "old_nav.png"
+ %input.js-experiment-feature-toggle{ type: "radio", value: "false", name: "new_nav", checked: !show_new_nav? }
+ Old
+ = label_tag do
+ .preview= image_tag "new_nav.png"
+ %input.js-experiment-feature-toggle{ type: "radio", value: "true", name: "new_nav", checked: show_new_nav? }
+ New
.col-sm-12
%hr
.col-lg-3.profile-settings-sidebar
diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml
index 26f3c297260..520696b01c6 100644
--- a/app/views/projects/deployments/_deployment.html.haml
+++ b/app/views/projects/deployments/_deployment.html.haml
@@ -11,11 +11,14 @@
.table-mobile-header{ role: 'rowheader' } Job
- if deployment.deployable
.table-mobile-content
- = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable], class: 'build-link' do
- #{deployment.deployable.name} (##{deployment.deployable.id})
+ .flex-truncate-parent
+ .flex-truncate-child
+ = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable], class: 'build-link' do
+ #{deployment.deployable.name} (##{deployment.deployable.id})
- if deployment.user
- by
- = user_avatar(user: deployment.user, size: 20)
+ %div
+ by
+ = user_avatar(user: deployment.user, size: 20)
.table-section.section-15{ role: 'gridcell' }
.table-mobile-header{ role: 'rowheader' } Created
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 23aa4c29e69..31e2bb11ce8 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -31,8 +31,8 @@
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'columnheader' } ID
- .table-section.section-40{ role: 'columnheader' } Commit
- .table-section.section-15{ role: 'columnheader' } Job
+ .table-section.section-30{ role: 'columnheader' } Commit
+ .table-section.section-25{ role: 'columnheader' } Job
.table-section.section-15{ role: 'columnheader' } Created
= render @deployments
diff --git a/changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml
new file mode 100644
index 00000000000..07c201de96e
--- /dev/null
+++ b/changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml
@@ -0,0 +1,4 @@
+---
+title: Replace 'dashboard/merge_requests' spinach with rspec
+merge_request: 12440
+author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/33846-no-runner-for-admin.yml b/changelogs/unreleased/33846-no-runner-for-admin.yml
new file mode 100644
index 00000000000..a2d46802c61
--- /dev/null
+++ b/changelogs/unreleased/33846-no-runner-for-admin.yml
@@ -0,0 +1,4 @@
+---
+title: Add explicit message when no runners on admin
+merge_request: 12266
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml b/changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml
new file mode 100644
index 00000000000..af743f3e506
--- /dev/null
+++ b/changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml
@@ -0,0 +1,4 @@
+---
+title: Add Esperanto translations for Cycle Analytics, Project, and Repository pages
+merge_request: 12442
+author: Huang Tao
diff --git a/changelogs/unreleased/sh-fix-premailer-gem-for-filesystem.yml b/changelogs/unreleased/sh-fix-premailer-gem-for-filesystem.yml
new file mode 100644
index 00000000000..9e3c3e19bea
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-premailer-gem-for-filesystem.yml
@@ -0,0 +1,5 @@
+---
+title: Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval
+ of assets
+merge_request:
+author:
diff --git a/config/application.rb b/config/application.rb
index 8bbecf3ed0f..12242c3b0f5 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -109,6 +109,7 @@ module Gitlab
config.assets.precompile << "lib/ace.js"
config.assets.precompile << "vendor/assets/fonts/*"
config.assets.precompile << "test.css"
+ config.assets.precompile << "new_nav.css"
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
diff --git a/features/dashboard/merge_requests.feature b/features/dashboard/merge_requests.feature
deleted file mode 100644
index 4a2c997d707..00000000000
--- a/features/dashboard/merge_requests.feature
+++ /dev/null
@@ -1,21 +0,0 @@
-@dashboard
-Feature: Dashboard Merge Requests
- Background:
- Given I sign in as a user
- And I have authored merge requests
- And I have assigned merge requests
- And I have other merge requests
- And I visit dashboard merge requests page
-
- Scenario: I should see assigned merge_requests
- Then I should see merge requests assigned to me
-
- @javascript
- Scenario: I should see authored merge_requests
- When I click "Authored by me" link
- Then I should see merge requests authored by me
-
- @javascript
- Scenario: I should see all merge_requests
- When I click "All" link
- Then I should see all merge requests
diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb
deleted file mode 100644
index 909ffec3646..00000000000
--- a/features/steps/dashboard/merge_requests.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps
- include SharedAuthentication
- include SharedPaths
- include Select2Helper
-
- step 'I should see merge requests assigned to me' do
- should_see(assigned_merge_request)
- should_see(assigned_merge_request_from_fork)
- should_not_see(authored_merge_request)
- should_not_see(authored_merge_request_from_fork)
- should_not_see(other_merge_request)
- end
-
- step 'I should see merge requests authored by me' do
- should_see(authored_merge_request)
- should_see(authored_merge_request_from_fork)
- should_not_see(assigned_merge_request)
- should_not_see(assigned_merge_request_from_fork)
- should_not_see(other_merge_request)
- end
-
- step 'I should see all merge requests' do
- should_see(authored_merge_request)
- should_see(assigned_merge_request)
- should_see(other_merge_request)
- end
-
- step 'I have authored merge requests' do
- authored_merge_request
- authored_merge_request_from_fork
- end
-
- step 'I have assigned merge requests' do
- assigned_merge_request
- assigned_merge_request_from_fork
- end
-
- step 'I have other merge requests' do
- other_merge_request
- end
-
- step 'I click "Authored by me" link' do
- find("#assignee_id").set("")
- find(".js-author-search", match: :first).click
- find(".dropdown-menu-author li a", match: :first, text: current_user.to_reference).click
- end
-
- step 'I click "All" link' do
- find(".js-author-search").click
- expect(page).to have_selector(".dropdown-menu-author li a")
- find(".dropdown-menu-author li a", match: :first).click
- expect(page).not_to have_selector(".dropdown-menu-author li a")
-
- find(".js-assignee-search").click
- expect(page).to have_selector(".dropdown-menu-assignee li a")
- find(".dropdown-menu-assignee li a", match: :first).click
- expect(page).not_to have_selector(".dropdown-menu-assignee li a")
- end
-
- def should_see(merge_request)
- expect(page).to have_content(merge_request.title[0..10])
- end
-
- def should_not_see(merge_request)
- expect(page).not_to have_content(merge_request.title[0..10])
- end
-
- def assigned_merge_request
- @assigned_merge_request ||= create :merge_request,
- assignee: current_user,
- target_project: project,
- source_project: project
- end
-
- def authored_merge_request
- @authored_merge_request ||= create :merge_request,
- source_branch: 'markdown',
- author: current_user,
- target_project: project,
- source_project: project
- end
-
- def other_merge_request
- @other_merge_request ||= create :merge_request,
- source_branch: 'fix',
- target_project: project,
- source_project: project
- end
-
- def authored_merge_request_from_fork
- @authored_merge_request_from_fork ||= create :merge_request,
- source_branch: 'feature_conflict',
- author: current_user,
- target_project: public_project,
- source_project: forked_project
- end
-
- def assigned_merge_request_from_fork
- @assigned_merge_request_from_fork ||= create :merge_request,
- source_branch: 'markdown',
- assignee: current_user,
- target_project: public_project,
- source_project: forked_project
- end
-
- def project
- @project ||= begin
- project = create(:project, :repository)
- project.team << [current_user, :master]
- project
- end
- end
-
- def public_project
- @public_project ||= create(:project, :public, :repository)
- end
-
- def forked_project
- @forked_project ||= Projects::ForkService.new(public_project, current_user).execute
- end
-end
diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb
index 62ddd45785d..a0f46594eb1 100644
--- a/lib/gitlab/exclusive_lease.rb
+++ b/lib/gitlab/exclusive_lease.rb
@@ -10,13 +10,21 @@ module Gitlab
# ExclusiveLease.
#
class ExclusiveLease
- LUA_CANCEL_SCRIPT = <<-EOS.freeze
+ LUA_CANCEL_SCRIPT = <<~EOS.freeze
local key, uuid = KEYS[1], ARGV[1]
if redis.call("get", key) == uuid then
redis.call("del", key)
end
EOS
+ LUA_RENEW_SCRIPT = <<~EOS.freeze
+ local key, uuid, ttl = KEYS[1], ARGV[1], ARGV[2]
+ if redis.call("get", key) == uuid then
+ redis.call("expire", key, ttl)
+ return uuid
+ end
+ EOS
+
def self.cancel(key, uuid)
Gitlab::Redis.with do |redis|
redis.eval(LUA_CANCEL_SCRIPT, keys: [redis_key(key)], argv: [uuid])
@@ -42,6 +50,15 @@ module Gitlab
end
end
+ # Try to renew an existing lease. Return lease UUID on success,
+ # false if the lease is taken by a different UUID or inexistent.
+ def renew
+ Gitlab::Redis.with do |redis|
+ result = redis.eval(LUA_RENEW_SCRIPT, keys: [@redis_key], argv: [@uuid, @timeout])
+ result == @uuid
+ end
+ end
+
# Returns true if the key for this lease is set.
def exists?
Gitlab::Redis.with do |redis|
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index a5ad2f952d3..db7cdf4b5c7 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -11,7 +11,8 @@ module Gitlab
'zh_CN' => '简体中文',
'zh_HK' => '繁體中文(香港)',
'zh_TW' => '繁體中文(臺灣)',
- 'bg' => 'български'
+ 'bg' => 'български',
+ 'eo' => 'Esperanto'
}.freeze
def available_locales
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
new file mode 100644
index 00000000000..3ef9e19067d
--- /dev/null
+++ b/locale/eo/gitlab.po
@@ -0,0 +1,1143 @@
+# Huang Tao <htve@outlook.com>, 2017. #zanata
+# Lyubomir Vasilev <lyubomirv@abv.bg>, 2017. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab 1.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-06-15 21:59-0500\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"PO-Revision-Date: 2017-06-20 06:24-0400\n"
+"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
+"Language-Team: Esperanto (https://translate.zanata.org/project/view/GitLab)\n"
+"Language: eo\n"
+"X-Generator: Zanata 3.9.6\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+msgid "%{commit_author_link} committed %{commit_timeago}"
+msgstr "%{commit_author_link} enmetis %{commit_timeago}"
+
+msgid "About auto deploy"
+msgstr "Pri la aŭtomata disponigado"
+
+msgid "Active"
+msgstr "Aktiva"
+
+msgid "Activity"
+msgstr "Aktiveco"
+
+msgid "Add Changelog"
+msgstr "Aldoni liston de ŝanĝoj"
+
+msgid "Add Contribution guide"
+msgstr "Aldoni gvidliniojn por kontribuado"
+
+msgid "Add License"
+msgstr "Aldoni rajtigilon"
+
+msgid "Add an SSH key to your profile to pull or push via SSH."
+msgstr ""
+"Aldonu SSH-ŝlosilon al via profilo por ebligi al vi eltiri kaj alpuŝi per "
+"SSH."
+
+msgid "Add new directory"
+msgstr "Aldoni novan dosierujon"
+
+msgid "Archived project! Repository is read-only"
+msgstr "Arkivita projekto! La deponejo permesas nur legadon"
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr "Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr "Alkroĉu dosieron per ŝovmetado aŭ %{upload_link}"
+
+msgid "Branch"
+msgid_plural "Branches"
+msgstr[0] "Branĉo"
+msgstr[1] "Branĉoj"
+
+msgid ""
+"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
+"choose a GitLab CI Yaml template and commit your changes. "
+"%{link_to_autodeploy_doc}"
+msgstr ""
+"La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aŭtomatan "
+"disponigadon, bonvolu elekti Yaml-ŝablonon por GitLab CI kaj enmeti viajn "
+"ŝanĝojn. %{link_to_autodeploy_doc}"
+
+msgid "Branches"
+msgstr "Branĉoj"
+
+msgid "Browse files"
+msgstr "Elekti dosierojn"
+
+msgid "ByAuthor|by"
+msgstr "de"
+
+msgid "CI configuration"
+msgstr "Agordoj de seninterrompa integrado"
+
+msgid "Cancel"
+msgstr "Nuligi"
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr "Elekti en branĉon"
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr "Malfari en branĉo"
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr "Precize elekti"
+
+msgid "ChangeTypeAction|Revert"
+msgstr "Malfari"
+
+msgid "Changelog"
+msgstr "Listo de ŝanĝoj"
+
+msgid "Charts"
+msgstr "Diagramoj"
+
+msgid "Cherry-pick this commit"
+msgstr "Precize elekti ĉi tiun kunmetadon"
+
+msgid "Cherry-pick this merge request"
+msgstr "Precize elekti ĉi tiun peton pri kunfando"
+
+msgid "CiStatusLabel|canceled"
+msgstr "nuligita"
+
+msgid "CiStatusLabel|created"
+msgstr "kreita"
+
+msgid "CiStatusLabel|failed"
+msgstr "malsukcesa"
+
+msgid "CiStatusLabel|manual action"
+msgstr "mana ago"
+
+msgid "CiStatusLabel|passed"
+msgstr "sukcesa"
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr "sukcesa, kun avertoj"
+
+msgid "CiStatusLabel|pending"
+msgstr "okazonta"
+
+msgid "CiStatusLabel|skipped"
+msgstr "transsaltita"
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr "atendanta manan agon"
+
+msgid "CiStatusText|blocked"
+msgstr "blokita"
+
+msgid "CiStatusText|canceled"
+msgstr "nuligita"
+
+msgid "CiStatusText|created"
+msgstr "kreita"
+
+msgid "CiStatusText|failed"
+msgstr "malsukcesa"
+
+msgid "CiStatusText|manual"
+msgstr "mana"
+
+msgid "CiStatusText|passed"
+msgstr "sukcesa"
+
+msgid "CiStatusText|pending"
+msgstr "okazonta"
+
+msgid "CiStatusText|skipped"
+msgstr "transsaltita"
+
+msgid "CiStatus|running"
+msgstr "plenumiĝanta"
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] "Enmetado"
+msgstr[1] "Enmetadoj"
+
+msgid "Commit message"
+msgstr "Mesaĝo pri la enmetado"
+
+msgid "CommitBoxTitle|Commit"
+msgstr "Enmeti"
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr "Aldoni „%{file_name}“"
+
+msgid "Commits"
+msgstr "Enmetadoj"
+
+msgid "Commits|History"
+msgstr "Historio"
+
+msgid "Committed by"
+msgstr "Enmetita de"
+
+msgid "Compare"
+msgstr "Kompari"
+
+msgid "Contribution guide"
+msgstr "Gvidlinioj por kontribuado"
+
+msgid "Contributors"
+msgstr "Kontribuantoj"
+
+msgid "Copy URL to clipboard"
+msgstr "Kopii la adreson en la kopibufron"
+
+msgid "Copy commit SHA to clipboard"
+msgstr "Kopii la identigilon de la enmetado"
+
+msgid "Create New Directory"
+msgstr "Krei novan dosierujon"
+
+msgid "Create directory"
+msgstr "Krei dosierujon"
+
+msgid "Create empty bare repository"
+msgstr "Krei malplenan deponejon"
+
+msgid "Create merge request"
+msgstr "Krei peton pri kunfando"
+
+msgid "Create new..."
+msgstr "Krei novan…"
+
+msgid "CreateNewFork|Fork"
+msgstr "Disbranĉigi"
+
+msgid "CreateTag|Tag"
+msgstr "Etikedo"
+
+msgid "Cron Timezone"
+msgstr "Horzono por Cron"
+
+msgid "Cron syntax"
+msgstr "La sintakso de Cron"
+
+msgid "Custom notification events"
+msgstr "Propraj sciigaj eventoj"
+
+msgid ""
+"Custom notification levels are the same as participating levels. With custom "
+"notification levels you will also receive notifications for select events. "
+"To find out more, check out %{notification_link}."
+msgstr ""
+"La propraj sciigaj niveloj estas la samaj kiel la niveloj de partoprenado. "
+"Uzante la proprajn sciigajn nivelojn, vi ricevos ankaŭ sciigojn por "
+"elektitaj de vi eventoj. Por lerni pli, bonvolu vidi %{notification_link}."
+
+msgid "Cycle Analytics"
+msgstr "Cikla analizo"
+
+msgid ""
+"Cycle Analytics gives an overview of how much time it takes to go from idea "
+"to production in your project."
+msgstr ""
+"La cikla analizo esploras kiom da tempo necesas por disvolvi ideon ĝis ĝi "
+"fariĝos realaĵo."
+
+msgid "CycleAnalyticsStage|Code"
+msgstr "Programado"
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr "Problemo"
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr "Plano"
+
+msgid "CycleAnalyticsStage|Production"
+msgstr "Eldonado"
+
+msgid "CycleAnalyticsStage|Review"
+msgstr "Kontrolo"
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr "Preparo por eldono"
+
+msgid "CycleAnalyticsStage|Test"
+msgstr "Testado"
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Difini propran ŝablonon, uzante la sintakson de Cron"
+
+msgid "Delete"
+msgstr "Forigi"
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] "Disponigado"
+msgstr[1] "Disponigadoj"
+
+msgid "Description"
+msgstr "Priskribo"
+
+msgid "Directory name"
+msgstr "Nomo de dosierujo"
+
+msgid "Don't show again"
+msgstr "Ne montru denove"
+
+msgid "Download"
+msgstr "Elŝuti"
+
+msgid "Download tar"
+msgstr "Elŝuti en formato „tar“"
+
+msgid "Download tar.bz2"
+msgstr "Elŝuti en formato „tar.bz2“"
+
+msgid "Download tar.gz"
+msgstr "Elŝuti en formato „tar.gz“"
+
+msgid "Download zip"
+msgstr "Elŝuti en formato „zip“"
+
+msgid "DownloadArtifacts|Download"
+msgstr "Elŝuti"
+
+msgid "DownloadCommit|Email Patches"
+msgstr "Sendi flikaĵojn per retpoŝto"
+
+msgid "DownloadCommit|Plain Diff"
+msgstr "Normala dosiero kun diferencoj"
+
+msgid "DownloadSource|Download"
+msgstr "Elŝuti"
+
+msgid "Edit"
+msgstr "Redakti"
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr "Redakti ĉenstablan planon %{id}"
+
+msgid "Every day (at 4:00am)"
+msgstr "Ĉiutage (je 4:00)"
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr "Ĉiumonate (en la 1a de la monato, je 4:00)"
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr "Ĉiusemajne (en dimanĉo, je 4:00)"
+
+msgid "Failed to change the owner"
+msgstr "Ne eblas ŝanĝi la posedanton"
+
+msgid "Failed to remove the pipeline schedule"
+msgstr "Ne eblas forigi la ĉenstablan planon"
+
+msgid "Files"
+msgstr "Dosieroj"
+
+msgid "Find by path"
+msgstr "Trovi per dosierindiko"
+
+msgid "Find file"
+msgstr "Trovi dosieron"
+
+msgid "FirstPushedBy|First"
+msgstr "Unue"
+
+msgid "FirstPushedBy|pushed by"
+msgstr "alpuŝita de"
+
+msgid "Fork"
+msgid_plural "Forks"
+msgstr[0] "Disbranĉigo"
+msgstr[1] "Disbranĉigoj"
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr "Disbranĉigita el"
+
+msgid "From issue creation until deploy to production"
+msgstr "De la kreado de la problemo ĝis la disponigado en la publika versio"
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+"De la kunfandado de la peto pri kunfando ĝis la disponigado en la publika "
+"versio"
+
+msgid "Go to your fork"
+msgstr "Al via disbranĉigo"
+
+msgid "GoToYourFork|Fork"
+msgstr "Disbranĉigo"
+
+msgid "Home"
+msgstr "Hejmo"
+
+msgid "Housekeeping successfully started"
+msgstr "La refreŝigo komenciĝis sukcese"
+
+msgid "Import repository"
+msgstr "Enporti deponejon"
+
+msgid "Interval Pattern"
+msgstr "Intervala ŝablono"
+
+msgid "Introducing Cycle Analytics"
+msgstr "Ni prezentas al vi la ciklan analizon"
+
+msgid "LFSStatus|Disabled"
+msgstr "Malŝaltita"
+
+msgid "LFSStatus|Enabled"
+msgstr "Ŝaltita"
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] "La lasta %d tago"
+msgstr[1] "La lastaj %d tagoj"
+
+msgid "Last Pipeline"
+msgstr "Lasta ĉenstablo"
+
+msgid "Last Update"
+msgstr "Lasta ĝisdatigo"
+
+msgid "Last commit"
+msgstr "Lasta enmetado"
+
+msgid "Learn more in the"
+msgstr "Lernu pli en la"
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr "dokumentado pri ĉenstablaj planoj"
+
+msgid "Leave group"
+msgstr "Forlasi la grupon"
+
+msgid "Leave project"
+msgstr "Forlasi la projekton"
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] "Limigita al montrado de ne pli ol %d evento"
+msgstr[1] "Limigita al montrado de ne pli ol %d eventoj"
+
+msgid "Median"
+msgstr "Mediano"
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr "aldonos SSH-ŝlosilon"
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] "Nova problemo"
+msgstr[1] "Novaj problemoj"
+
+msgid "New Pipeline Schedule"
+msgstr "Nova ĉenstabla plano"
+
+msgid "New branch"
+msgstr "Nova branĉo"
+
+msgid "New directory"
+msgstr "Nova dosierujo"
+
+msgid "New file"
+msgstr "Nova dosiero"
+
+msgid "New issue"
+msgstr "Nova problemo"
+
+msgid "New merge request"
+msgstr "Nova peto pri kunfando"
+
+msgid "New schedule"
+msgstr "Nova plano"
+
+msgid "New snippet"
+msgstr "Nova kodaĵo"
+
+msgid "New tag"
+msgstr "Nova etikedo"
+
+msgid "No repository"
+msgstr "Ne estas deponejo"
+
+msgid "No schedules"
+msgstr "Ne estas planoj"
+
+msgid "Not available"
+msgstr "Ne disponebla"
+
+msgid "Not enough data"
+msgstr "Ne estas sufiĉe da datenoj"
+
+msgid "Notification events"
+msgstr "Sciigaj eventoj"
+
+msgid "NotificationEvent|Close issue"
+msgstr "Fermi problemon"
+
+msgid "NotificationEvent|Close merge request"
+msgstr "Fermi peton pri kunfando"
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr "Malsukcesa ĉenstablo"
+
+msgid "NotificationEvent|Merge merge request"
+msgstr "Apliki peton pri kunfando"
+
+msgid "NotificationEvent|New issue"
+msgstr "Nova problemo"
+
+msgid "NotificationEvent|New merge request"
+msgstr "Nova peto pri kunfando"
+
+msgid "NotificationEvent|New note"
+msgstr "Nova noto"
+
+msgid "NotificationEvent|Reassign issue"
+msgstr "Reatribui problemon"
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr "Reatribui peton pri kunfando"
+
+msgid "NotificationEvent|Reopen issue"
+msgstr "Remalfermi problemon"
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr "Sukcesa ĉenstablo"
+
+msgid "NotificationLevel|Custom"
+msgstr "Propraj"
+
+msgid "NotificationLevel|Disabled"
+msgstr "Malŝaltitaj"
+
+msgid "NotificationLevel|Global"
+msgstr "Ĝeneralaj"
+
+msgid "NotificationLevel|On mention"
+msgstr "Ĉe mencio"
+
+msgid "NotificationLevel|Participate"
+msgstr "Partoprenado"
+
+msgid "NotificationLevel|Watch"
+msgstr "Rigardado"
+
+msgid "OfSearchInADropdown|Filter"
+msgstr "Filtrilo"
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr "Malfermita"
+
+msgid "Options"
+msgstr "Opcioj"
+
+msgid "Owner"
+msgstr "Posedanto"
+
+msgid "Pipeline"
+msgstr "Ĉenstablo"
+
+msgid "Pipeline Health"
+msgstr "Stato"
+
+msgid "Pipeline Schedule"
+msgstr "Ĉenstabla plano"
+
+msgid "Pipeline Schedules"
+msgstr "Ĉenstablaj planoj"
+
+msgid "PipelineSchedules|Activated"
+msgstr "Ŝaltita"
+
+msgid "PipelineSchedules|Active"
+msgstr "Ŝaltitaj"
+
+msgid "PipelineSchedules|All"
+msgstr "Ĉiuj"
+
+msgid "PipelineSchedules|Inactive"
+msgstr "Malŝaltitaj"
+
+msgid "PipelineSchedules|Next Run"
+msgstr "Sekvanta plenumo"
+
+msgid "PipelineSchedules|None"
+msgstr "Nenio"
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr "Entajpu mallongan priskribon pri ĉi tiu ĉenstablo"
+
+msgid "PipelineSchedules|Take ownership"
+msgstr "Akiri posedon"
+
+msgid "PipelineSchedules|Target"
+msgstr "Celo"
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr "Propra"
+
+msgid "Pipeline|with stage"
+msgstr "kun etapo"
+
+msgid "Pipeline|with stages"
+msgstr "kun etapoj"
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr "La projekto „%{project_name}“ estis alvicigita por forigado."
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr "La projekto „%{project_name}“ estis sukcese kreita."
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr "La projekto „%{project_name}“ estis sukcese ĝisdatigita."
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr "La projekto „%{project_name}“ estos forigita."
+
+msgid "Project access must be granted explicitly to each user."
+msgstr "Ĉiu uzanto devas akiri propran atingon al la projekto."
+
+msgid "Project export could not be deleted."
+msgstr "Ne eblas forigi la projektan elporton."
+
+msgid "Project export has been deleted."
+msgstr "La projekta elporto estis forigita."
+
+msgid ""
+"Project export link has expired. Please generate a new export from your "
+"project settings."
+msgstr ""
+"La ligilo por la projekta elporto eksvalidiĝis. Bonvolu krei novan elporton "
+"en la agordoj de la projekto."
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+"La elporto de la projekto komenciĝis. Vi ricevos ligilon per retpoŝto por "
+"elŝuti la datenoj."
+
+msgid "Project home"
+msgstr "Hejmo de la projekto"
+
+msgid "ProjectFeature|Disabled"
+msgstr "Malŝaltita"
+
+msgid "ProjectFeature|Everyone with access"
+msgstr "Ĉiu, kiu havas atingon"
+
+msgid "ProjectFeature|Only team members"
+msgstr "Nur skipanoj"
+
+msgid "ProjectFileTree|Name"
+msgstr "Nomo"
+
+msgid "ProjectLastActivity|Never"
+msgstr "Neniam"
+
+msgid "ProjectLifecycle|Stage"
+msgstr "Etapo"
+
+msgid "ProjectNetworkGraph|Graph"
+msgstr "Grafeo"
+
+msgid "Read more"
+msgstr "Legu pli"
+
+msgid "Readme"
+msgstr "LeguMin"
+
+msgid "RefSwitcher|Branches"
+msgstr "Branĉoj"
+
+msgid "RefSwitcher|Tags"
+msgstr "Etikedoj"
+
+msgid "Related Commits"
+msgstr "Rilataj enmetadoj"
+
+msgid "Related Deployed Jobs"
+msgstr "Rilataj disponigitaj taskoj"
+
+msgid "Related Issues"
+msgstr "Rilataj problemoj"
+
+msgid "Related Jobs"
+msgstr "Rilataj taskoj"
+
+msgid "Related Merge Requests"
+msgstr "Rilataj petoj pri kunfando"
+
+msgid "Related Merged Requests"
+msgstr "Rilataj aplikitaj petoj pri kunfando"
+
+msgid "Remind later"
+msgstr "Rememorigu denove"
+
+msgid "Remove project"
+msgstr "Forigi la projekton"
+
+msgid "Request Access"
+msgstr "Peti atingeblon"
+
+msgid "Revert this commit"
+msgstr "Malfari ĉi tiun enmetadon"
+
+msgid "Revert this merge request"
+msgstr "Malfari ĉi tiun peton pri kunfando"
+
+msgid "Save pipeline schedule"
+msgstr "Konservi ĉenstablan planon"
+
+msgid "Schedule a new pipeline"
+msgstr "Plani novan ĉenstablon"
+
+msgid "Scheduling Pipelines"
+msgstr "Planado de la ĉenstabloj"
+
+msgid "Search branches and tags"
+msgstr "Serĉu branĉon aŭ etikedon"
+
+msgid "Select Archive Format"
+msgstr "Elektu formaton de arkivo"
+
+msgid "Select a timezone"
+msgstr "Elektu horzonon"
+
+msgid "Select target branch"
+msgstr "Elektu celan branĉon"
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr ""
+"Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuŝi per "
+"%{protocol}"
+
+msgid "Set up CI"
+msgstr "Agordi SI"
+
+msgid "Set up Koding"
+msgstr "Agordi „Koding“"
+
+msgid "Set up auto deploy"
+msgstr "Agordi aŭtomatan disponigadon"
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr "kreos pasvorton"
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] "Estas montrata %d evento"
+msgstr[1] "Estas montrataj %d eventoj"
+
+msgid "Source code"
+msgstr "Kodo"
+
+msgid "StarProject|Star"
+msgstr "Steligi"
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr "Kreu %{new_merge_request} kun ĉi tiuj ŝanĝoj"
+
+msgid "Switch branch/tag"
+msgstr "Iri al branĉo/etikedo"
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] "Etikedo"
+msgstr[1] "Etikedoj"
+
+msgid "Tags"
+msgstr "Etikedoj"
+
+msgid "Target Branch"
+msgstr "Cela branĉo"
+
+msgid ""
+"The coding stage shows the time from the first commit to creating the merge "
+"request. The data will automatically be added here once you create your "
+"first merge request."
+msgstr ""
+"La etapo de programado montras la tempon de la unua enmetado ĝis la kreado "
+"de la peto pri kunfando. La datenoj aldoniĝos aŭtomate ĉi tie post kiam vi "
+"kreas la unuan peton pri kunfando."
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+"La aro da eventoj, kiuj estas aldonitaj al la datenoj kolektitaj por la "
+"etapo."
+
+msgid "The fork relationship has been removed."
+msgstr "La rilato de disbranĉigo estis forigita."
+
+msgid ""
+"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."
+msgstr ""
+"La etapo de la problemo montras kiom la tempo pasas de la kreado de problemo "
+"ĝis la atribuado de la problemo al cela etapo de la projekto, aŭ al listo "
+"sur la problemtabulo. Komencu krei problemojn por vidi la datenojn por ĉi "
+"tiu etapo."
+
+msgid "The phase of the development lifecycle."
+msgstr "La etapo de la disvolva ciklo."
+
+msgid ""
+"The pipelines schedule runs pipelines in the future, repeatedly, for "
+"specific branches or tags. Those scheduled pipelines will inherit limited "
+"project access based on their associated user."
+msgstr ""
+"La ĉenstabla plano plenumas ĉenstablojn en la estonteco, ripete, por "
+"difinitaj branĉoj aŭ etikedoj. Tiuj planitaj ĉenstabloj heredos la limigitan "
+"atingon al la projekto de la rilata uzanto."
+
+msgid ""
+"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."
+msgstr ""
+"La etapo de la plano montras la tempon de la antaŭa ŝtupo ĝis la alpuŝado de "
+"via unua enmetado. Ĉi tiu tempo aldoniĝos aŭtomate post kiam vi alpuŝas la "
+"unuan enmetadon."
+
+msgid ""
+"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."
+msgstr ""
+"La etapo de eldonado montras la tutan tempon de la kreado de problemo ĝis la "
+"disponigado en la publika versio. La datenoj aldoniĝos aŭtomate post kiam vi "
+"kompletigos plenan ciklon de ideo ĝis realaĵo."
+
+msgid "The project can be accessed by any logged in user."
+msgstr "Ĉiu ensalutita uzanto havas atingon al la projekto"
+
+msgid "The project can be accessed without any authentication."
+msgstr "Ĉiu povas havi atingon al la projekto, sen ensaluti"
+
+msgid "The repository for this project does not exist."
+msgstr "La deponejo por ĉi tiu projekto ne ekzistas."
+
+msgid ""
+"The review stage shows the time from creating the merge request to merging "
+"it. The data will automatically be added after you merge your first merge "
+"request."
+msgstr ""
+"La etapo de la kontrolo montras la tempon de la kreado de la peto pri "
+"kunfando ĝis ĝia aplikado. La datenoj aldoniĝos aŭtomate post kiam vi "
+"aplikos la unuan peton pri kunfando."
+
+msgid ""
+"The staging stage shows the time between merging the MR and deploying code "
+"to the production environment. The data will be automatically added once you "
+"deploy to production for the first time."
+msgstr ""
+"La etapo de preparo por eldono montras la tempon inter la aplikado de la "
+"peto pri kunfando kaj la disponigado de la kodo en la publika versio. La "
+"datenoj aldoniĝos aŭtomate post kiam vi faros la unuan disponigadon en la "
+"publika versio."
+
+msgid ""
+"The testing stage shows the time GitLab CI takes to run every pipeline for "
+"the related merge request. The data will automatically be added after your "
+"first pipeline finishes running."
+msgstr ""
+"La etapo de testado montras kiom da tempo necesas al „GitLab CI“ por plenumi "
+"ĉiujn ĉenstablojn por la rilata peto pri kunfando. La datenoj aldoniĝos "
+"aŭtomate post kiam via unua ĉenstablo finiĝos."
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr "La tempo, kiu estas necesa por ĉiu dateno kolektita de la etapo."
+
+msgid ""
+"The value lying at the midpoint of a series of observed values. E.g., "
+"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
+" 6."
+msgstr ""
+"La valoro, kiu troviĝas en la mezo de aro da rigardataj valoroj. Ekzemple: "
+"inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas "
+"(5+7)/2 = 6."
+
+msgid ""
+"This means you can not push code until you create an empty repository or "
+"import existing one."
+msgstr ""
+"Ĉi tiu signifas, ke vi ne povos alpuŝi kodon, antaŭ ol vi kreos malplenan "
+"deponejon aŭ enportos jam ekzistantan."
+
+msgid "Time before an issue gets scheduled"
+msgstr "Tempo antaŭ problemo estas planita por ellabori"
+
+msgid "Time before an issue starts implementation"
+msgstr "Tempo antaŭ la komenco de laboro super problemo"
+
+msgid "Time between merge request creation and merge/close"
+msgstr "Tempo inter la kreado de poeto pri kunfando kaj ĝia aplikado/fermado"
+
+msgid "Time until first merge request"
+msgstr "Tempo ĝis la unua peto pri kunfando"
+
+msgid "Timeago|%s days ago"
+msgstr "antaŭ %s tagoj"
+
+msgid "Timeago|%s days remaining"
+msgstr "restas %s tagoj"
+
+msgid "Timeago|%s hours remaining"
+msgstr "restas %s horoj"
+
+msgid "Timeago|%s minutes ago"
+msgstr "antaŭ %s minutoj"
+
+msgid "Timeago|%s minutes remaining"
+msgstr "restas %s minutoj"
+
+msgid "Timeago|%s months ago"
+msgstr "antaŭ %s monatoj"
+
+msgid "Timeago|%s months remaining"
+msgstr "restas %s monatoj"
+
+msgid "Timeago|%s seconds remaining"
+msgstr "restas %s sekundoj"
+
+msgid "Timeago|%s weeks ago"
+msgstr "antaŭ %s semajnoj"
+
+msgid "Timeago|%s weeks remaining"
+msgstr "restas %s semajnoj"
+
+msgid "Timeago|%s years ago"
+msgstr "antaŭ %s jaroj"
+
+msgid "Timeago|%s years remaining"
+msgstr "restas %s jaroj"
+
+msgid "Timeago|1 day remaining"
+msgstr "restas 1 tago"
+
+msgid "Timeago|1 hour remaining"
+msgstr "restas 1 horo"
+
+msgid "Timeago|1 minute remaining"
+msgstr "restas 1 minuto"
+
+msgid "Timeago|1 month remaining"
+msgstr "restas 1 monato"
+
+msgid "Timeago|1 week remaining"
+msgstr "restas 1 semajno"
+
+msgid "Timeago|1 year remaining"
+msgstr "restas 1 jaro"
+
+msgid "Timeago|Past due"
+msgstr "Malfruiĝis"
+
+msgid "Timeago|a day ago"
+msgstr "antaŭ unu tago"
+
+msgid "Timeago|a month ago"
+msgstr "antaŭ unu monato"
+
+msgid "Timeago|a week ago"
+msgstr "antaŭ unu semajno"
+
+msgid "Timeago|a while"
+msgstr "antaŭ iom da tempo"
+
+msgid "Timeago|a year ago"
+msgstr "antaŭ unu jaro"
+
+msgid "Timeago|about %s hours ago"
+msgstr "antaŭ ĉirkaŭ %s horoj"
+
+msgid "Timeago|about a minute ago"
+msgstr "antaŭ ĉirkaŭ unu minuto"
+
+msgid "Timeago|about an hour ago"
+msgstr "antaŭ ĉirkaŭ unu horo"
+
+msgid "Timeago|in %s days"
+msgstr "post %s tagoj"
+
+msgid "Timeago|in %s hours"
+msgstr "post %s horoj"
+
+msgid "Timeago|in %s minutes"
+msgstr "post %s minutoj"
+
+msgid "Timeago|in %s months"
+msgstr "post %s monatoj"
+
+msgid "Timeago|in %s seconds"
+msgstr "post %s sekundoj"
+
+msgid "Timeago|in %s weeks"
+msgstr "post %s semajnoj"
+
+msgid "Timeago|in %s years"
+msgstr "post %s jaroj"
+
+msgid "Timeago|in 1 day"
+msgstr "post 1 tago"
+
+msgid "Timeago|in 1 hour"
+msgstr "post 1 horo"
+
+msgid "Timeago|in 1 minute"
+msgstr "post 1 minuto"
+
+msgid "Timeago|in 1 month"
+msgstr "post 1 monato"
+
+msgid "Timeago|in 1 week"
+msgstr "post 1 semajno"
+
+msgid "Timeago|in 1 year"
+msgstr "post 1 jaro"
+
+msgid "Timeago|less than a minute ago"
+msgstr "antaŭ malpli ol minuto"
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] "h"
+msgstr[1] "h"
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] "min"
+msgstr[1] "min"
+
+msgid "Time|s"
+msgstr "s"
+
+msgid "Total Time"
+msgstr "Totala tempo"
+
+msgid "Total test time for all commits/merges"
+msgstr "Totala tempo por la testado de ĉiuj enmetadoj/kunfandoj"
+
+msgid "Unstar"
+msgstr "Malsteligi"
+
+msgid "Upload New File"
+msgstr "Alŝuti novan dosieron"
+
+msgid "Upload file"
+msgstr "Alŝuti dosieron"
+
+msgid "Use your global notification setting"
+msgstr "Uzi vian ĝeneralan agordon pri la sciigoj"
+
+msgid "VisibilityLevel|Internal"
+msgstr "Interna"
+
+msgid "VisibilityLevel|Private"
+msgstr "Privata"
+
+msgid "VisibilityLevel|Public"
+msgstr "Publika"
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+"Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
+
+msgid "We don't have enough data to show this stage."
+msgstr "Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."
+
+msgid "Withdraw Access Request"
+msgstr "Nuligi la peton pri atingeblo"
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
+msgstr ""
+"Vi forigos „%{project_name_with_namespace}“.\n"
+"Oni NE POVAS malfari la forigon de projekto!\n"
+"Ĉu vi estas ABSOLUTE certa?"
+
+msgid ""
+"You are going to remove the fork relationship to source project "
+"%{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+"Vi forigos la rilaton de la disbranĉigo al la originala projekto, "
+"„%{forked_from_project}“. Ĉu vi estas ABSOLUTE certa?"
+
+msgid ""
+"You are going to transfer %{project_name_with_namespace} to another owner. "
+"Are you ABSOLUTELY sure?"
+msgstr ""
+"Vi transigos „%{project_name_with_namespace}“ al alia posedanto. Ĉu vi estas "
+"ABSOLUTE certa?"
+
+msgid "You can only add files when you are on a branch"
+msgstr "Oni povas aldoni dosierojn nur kiam oni estas en branĉo"
+
+msgid "You have reached your project limit"
+msgstr "Vi ne povas krei pliajn projektojn"
+
+msgid "You must sign in to star a project"
+msgstr "Oni devas ensaluti por steligi projekton"
+
+msgid "You need permission."
+msgstr "VI bezonas permeson."
+
+msgid "You will not get any notifications via email"
+msgstr "VI ne ricevos sciigojn per retpoŝto"
+
+msgid "You will only receive notifications for the events you choose"
+msgstr "Vi ricevos sciigojn nur por la eventoj elektitaj de vi"
+
+msgid ""
+"You will only receive notifications for threads you have participated in"
+msgstr "Vi ricevos sciigojn nur por la fadenoj, en kiuj vi partoprenis"
+
+msgid "You will receive notifications for any activity"
+msgstr "Vi ricevos sciigojn por ĉiu ago"
+
+msgid ""
+"You will receive notifications only for comments in which you were "
+"@mentioned"
+msgstr "Vi ricevos sciigojn nur por komentoj, en kiuj vi estas @menciita"
+
+msgid ""
+"You won't be able to pull or push project code via %{protocol} until you "
+"%{set_password_link} on your account"
+msgstr ""
+"Vi ne povos eltiri aŭ alpuŝi kodon per %{protocol} antaŭ ol vi "
+"%{set_password_link} por via konto"
+
+msgid ""
+"You won't be able to pull or push project code via SSH until you "
+"%{add_ssh_key_link} to your profile"
+msgstr ""
+"Vi ne povos eltiri aŭ alpuŝi kodon per SSH antaŭ ol vi %{add_ssh_key_link} "
+"al via profilo"
+
+msgid "Your name"
+msgstr "Via nomo"
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] "tago"
+msgstr[1] "tagoj"
+
+msgid "new merge request"
+msgstr "novan peton pri kunfando"
+
+msgid "notification emails"
+msgstr "sciigoj per retpoŝto"
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] "patro"
+msgstr[1] "patroj"
+
diff --git a/locale/eo/gitlab.po.time_stamp b/locale/eo/gitlab.po.time_stamp
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/locale/eo/gitlab.po.time_stamp
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 5b3323fed13..6ad2d456b93 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -9,31 +9,54 @@ describe "Admin Runners" do
end
describe "Runners page" do
- before do
- runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now)
- pipeline = FactoryGirl.create(:ci_pipeline)
- FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id)
- visit admin_runners_path
- end
+ let(:pipeline) { create(:ci_pipeline) }
+
+ context "when there are runners" do
+ before do
+ runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now)
+ FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id)
+ visit admin_runners_path
+ end
+
+ it 'has all necessary texts' do
+ expect(page).to have_text "To register a new Runner"
+ expect(page).to have_text "Runners with last contact more than a minute ago: 1"
+ end
+
+ describe 'search' do
+ before do
+ FactoryGirl.create :ci_runner, description: 'runner-foo'
+ FactoryGirl.create :ci_runner, description: 'runner-bar'
+ end
+
+ it 'shows correct runner when description matches' do
+ search_form = find('#runners-search')
+ search_form.fill_in 'search', with: 'runner-foo'
+ search_form.click_button 'Search'
+
+ expect(page).to have_content("runner-foo")
+ expect(page).not_to have_content("runner-bar")
+ end
+
+ it 'shows no runner when description does not match' do
+ search_form = find('#runners-search')
+ search_form.fill_in 'search', with: 'runner-baz'
+ search_form.click_button 'Search'
- it 'has all necessary texts' do
- expect(page).to have_text "To register a new Runner"
- expect(page).to have_text "Runners with last contact more than a minute ago: 1"
+ expect(page).to have_text 'No runners found'
+ end
+ end
end
- describe 'search' do
+ context "when there are no runners" do
before do
- FactoryGirl.create :ci_runner, description: 'runner-foo'
- FactoryGirl.create :ci_runner, description: 'runner-bar'
-
- search_form = find('#runners-search')
- search_form.fill_in 'search', with: 'runner-foo'
- search_form.click_button 'Search'
+ visit admin_runners_path
end
- it 'shows correct runner' do
- expect(page).to have_content("runner-foo")
- expect(page).not_to have_content("runner-bar")
+ it 'has all necessary texts including no runner message' do
+ expect(page).to have_text "To register a new Runner"
+ expect(page).to have_text "Runners with last contact more than a minute ago: 0"
+ expect(page).to have_text 'No runners found'
end
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index 69d5500848e..bb1fb5b3feb 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -1,18 +1,24 @@
require 'spec_helper'
-describe 'Dashboard Merge Requests' do
+feature 'Dashboard Merge Requests' do
+ include FilterItemSelectHelper
+
let(:current_user) { create :user }
let(:project) { create(:empty_project) }
- let(:project_with_merge_requests_disabled) { create(:empty_project, :merge_requests_disabled) }
- before do
- [project, project_with_merge_requests_disabled].each { |project| project.team << [current_user, :master] }
+ let(:public_project) { create(:empty_project, :public, :repository) }
+ let(:forked_project) { Projects::ForkService.new(public_project, current_user).execute }
- gitlab_sign_in(current_user)
+ before do
+ project.add_master(current_user)
+ sign_in(current_user)
end
- describe 'new merge request dropdown' do
+ context 'new merge request dropdown' do
+ let(:project_with_disabled_merge_requests) { create(:empty_project, :merge_requests_disabled) }
+
before do
+ project_with_disabled_merge_requests.add_master(current_user)
visit merge_requests_dashboard_path
end
@@ -21,26 +27,87 @@ describe 'Dashboard Merge Requests' do
page.within('.select2-results') do
expect(page).to have_content(project.name_with_namespace)
- expect(page).not_to have_content(project_with_merge_requests_disabled.name_with_namespace)
+ expect(page).not_to have_content(project_with_disabled_merge_requests.name_with_namespace)
end
end
end
- it 'should show an empty state' do
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ context 'no merge requests exist' do
+ it 'shows an empty state' do
+ visit merge_requests_dashboard_path(assignee_id: current_user.id)
- expect(page).to have_selector('.empty-state')
+ expect(page).to have_selector('.empty-state')
+ end
end
- context 'if there are merge requests' do
- before do
- create(:merge_request, assignee: current_user, source_project: project)
+ context 'merge requests exist' do
+ let!(:assigned_merge_request) do
+ create(:merge_request, assignee: current_user, target_project: project, source_project: project)
+ end
+
+ let!(:assigned_merge_request_from_fork) do
+ create(:merge_request,
+ source_branch: 'markdown', assignee: current_user,
+ target_project: public_project, source_project: forked_project
+ )
+ end
+ let!(:authored_merge_request) do
+ create(:merge_request,
+ source_branch: 'markdown', author: current_user,
+ target_project: project, source_project: project
+ )
+ end
+
+ let!(:authored_merge_request_from_fork) do
+ create(:merge_request,
+ source_branch: 'feature_conflict',
+ author: current_user,
+ target_project: public_project, source_project: forked_project
+ )
+ end
+
+ let!(:other_merge_request) do
+ create(:merge_request,
+ source_branch: 'fix',
+ target_project: project, source_project: project
+ )
+ end
+
+ before do
visit merge_requests_dashboard_path(assignee_id: current_user.id)
end
- it 'should not show an empty state' do
- expect(page).not_to have_selector('.empty-state')
+ it 'shows assigned merge requests' do
+ expect(page).to have_content(assigned_merge_request.title)
+ expect(page).to have_content(assigned_merge_request_from_fork.title)
+
+ expect(page).not_to have_content(authored_merge_request.title)
+ expect(page).not_to have_content(authored_merge_request_from_fork.title)
+ expect(page).not_to have_content(other_merge_request.title)
+ end
+
+ it 'shows authored merge requests', js: true do
+ filter_item_select('Any Assignee', '.js-assignee-search')
+ filter_item_select(current_user.to_reference, '.js-author-search')
+
+ expect(page).to have_content(authored_merge_request.title)
+ expect(page).to have_content(authored_merge_request_from_fork.title)
+
+ expect(page).not_to have_content(assigned_merge_request.title)
+ expect(page).not_to have_content(assigned_merge_request_from_fork.title)
+ expect(page).not_to have_content(other_merge_request.title)
+ end
+
+ it 'shows all merge requests', js: true do
+ filter_item_select('Any Assignee', '.js-assignee-search')
+ filter_item_select('Any Author', '.js-author-search')
+
+ expect(page).to have_content(authored_merge_request.title)
+ expect(page).to have_content(authored_merge_request_from_fork.title)
+ expect(page).to have_content(assigned_merge_request.title)
+ expect(page).to have_content(assigned_merge_request_from_fork.title)
+ expect(page).to have_content(other_merge_request.title)
end
end
end
diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb
index 295262980a6..b0e4036f27c 100644
--- a/spec/features/dashboard/milestone_filter_spec.rb
+++ b/spec/features/dashboard/milestone_filter_spec.rb
@@ -1,10 +1,12 @@
require 'spec_helper'
-describe 'Dashboard > milestone filter', :feature, :js do
+feature 'Dashboard > milestone filter', :feature, :js do
+ include FilterItemSelectHelper
+
let(:user) { create(:user) }
let(:project) { create(:project, name: 'test', namespace: user.namespace) }
- let(:milestone) { create(:milestone, title: "v1.0", project: project) }
- let(:milestone2) { create(:milestone, title: "v2.0", project: project) }
+ let(:milestone) { create(:milestone, title: 'v1.0', project: project) }
+ let(:milestone2) { create(:milestone, title: 'v2.0', project: project) }
let!(:issue) { create :issue, author: user, project: project, milestone: milestone }
let!(:issue2) { create :issue, author: user, project: project, milestone: milestone2 }
@@ -22,17 +24,11 @@ describe 'Dashboard > milestone filter', :feature, :js do
end
context 'filtering by milestone' do
- milestone_select = '.js-milestone-select'
+ milestone_select_selector = '.js-milestone-select'
before do
- find(milestone_select).click
- wait_for_requests
-
- page.within('.dropdown-content') do
- click_link 'v1.0'
- end
-
- find(milestone_select).click
+ filter_item_select('v1.0', milestone_select_selector)
+ find(milestone_select_selector).click
wait_for_requests
end
@@ -49,7 +45,7 @@ describe 'Dashboard > milestone filter', :feature, :js do
expect(find('.milestone-filter')).not_to have_selector('.dropdown.open')
- find(milestone_select).click
+ find(milestone_select_selector).click
expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1)
expect(find('.dropdown-content a.is-active')).to have_content('v1.0')
diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js
index a4f32a1faed..1b96b2e3d51 100644
--- a/spec/javascripts/pipelines/stage_spec.js
+++ b/spec/javascripts/pipelines/stage_spec.js
@@ -83,4 +83,47 @@ describe('Pipelines stage component', () => {
}, 0);
});
});
+
+ describe('update endpoint correctly', () => {
+ const updatedInterceptor = (request, next) => {
+ if (request.url === 'bar') {
+ next(request.respondWith(JSON.stringify({ html: 'this is the updated content' }), {
+ status: 200,
+ }));
+ }
+ next();
+ };
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(updatedInterceptor);
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(
+ Vue.http.interceptors, updatedInterceptor,
+ );
+ });
+
+ it('should update the stage to request the new endpoint provided', (done) => {
+ component.stage = {
+ status: {
+ group: 'running',
+ icon: 'running',
+ title: 'running',
+ },
+ dropdown_path: 'bar',
+ };
+
+ Vue.nextTick(() => {
+ component.$el.querySelector('button').click();
+
+ setTimeout(() => {
+ expect(
+ component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(),
+ ).toEqual('this is the updated content');
+ done();
+ });
+ });
+ });
+ });
});
diff --git a/spec/lib/gitlab/exclusive_lease_spec.rb b/spec/lib/gitlab/exclusive_lease_spec.rb
index a366d68a146..81bbd70ffb8 100644
--- a/spec/lib/gitlab/exclusive_lease_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_spec.rb
@@ -19,6 +19,19 @@ describe Gitlab::ExclusiveLease, type: :redis do
end
end
+ describe '#renew' do
+ it 'returns true when we have the existing lease' do
+ lease = described_class.new(unique_key, timeout: 3600)
+ expect(lease.try_obtain).to be_present
+ expect(lease.renew).to be_truthy
+ end
+
+ it 'returns false when we dont have a lease' do
+ lease = described_class.new(unique_key, timeout: 3600)
+ expect(lease.renew).to be_falsey
+ end
+ end
+
describe '#exists?' do
it 'returns true for an existing lease' do
lease = described_class.new(unique_key, timeout: 3600)
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index c914b32f7a4..37f23b1243c 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -71,7 +71,7 @@ describe PrometheusService, models: true, caching: true do
end
describe '#deployment_metrics' do
- let(:deployment) { build_stubbed(:deployment)}
+ let(:deployment) { build_stubbed(:deployment) }
let(:deployment_query) { Gitlab::Prometheus::Queries::DeploymentQuery }
around do |example|
@@ -80,13 +80,16 @@ describe PrometheusService, models: true, caching: true do
context 'with valid data' do
subject { service.deployment_metrics(deployment) }
+ let(:fake_deployment_time) { 10 }
before do
stub_reactive_cache(service, prometheus_data, deployment_query, deployment.id)
end
it 'returns reactive data' do
- is_expected.to eq(prometheus_metrics_data.merge(deployment_time: deployment.created_at.to_i))
+ expect(deployment).to receive(:created_at).and_return(fake_deployment_time)
+
+ expect(subject).to eq(prometheus_metrics_data.merge(deployment_time: fake_deployment_time))
end
end
end
diff --git a/spec/support/filter_item_select_helper.rb b/spec/support/filter_item_select_helper.rb
new file mode 100644
index 00000000000..519e84d359e
--- /dev/null
+++ b/spec/support/filter_item_select_helper.rb
@@ -0,0 +1,19 @@
+# Helper allows you to select value from filter-items
+#
+# Params
+# value - value for select
+# selector - css selector of item
+#
+# Usage:
+#
+# filter_item_select('Any Author', '.js-author-search')
+#
+module FilterItemSelectHelper
+ def filter_item_select(value, selector)
+ find(selector).click
+ wait_for_requests
+ page.within('.dropdown-content') do
+ click_link value
+ end
+ end
+end