Commit 812686f0 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'master' into 'ee-update-trace-handling-code'

# Conflicts:
#   app/models/ci/build.rb
parents ff8e923f f7a3fc49
......@@ -281,8 +281,6 @@ docs:check:apilint:
image: "phusion/baseimage"
stage: test
<<: *dedicated-runner
variables:
GIT_DEPTH: "3"
cache: {}
dependencies: []
before_script: []
......@@ -293,8 +291,6 @@ docs:check:links:
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
stage: test
<<: *dedicated-runner
variables:
GIT_DEPTH: "3"
cache: {}
dependencies: []
before_script: []
......
Please view this file on the master branch, on stable branches it's out of date.
## 9.0.4 (2017-04-05)
- No changes.
## 9.0.3 (2017-04-05)
- Allow to edit pipelines quota for user.
......@@ -60,6 +64,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- [Elasticsearch] More efficient search.
- Get Geo secondaries nodes statuses over AJAX.
## 8.17.5 (2017-04-05)
- No changes.
## 8.17.4 (2017-03-19)
- Elastic security fix: Respect feature visibility level.
......@@ -98,6 +106,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Reduce queries needed to check if node is a primary or secondary Geo node.
- Allow squashing merge requests into a single commit.
## 8.16.9 (2017-04-05)
- No changes.
## 8.16.8 (2017-03-19)
- No changes.
......
......@@ -2,6 +2,14 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 9.0.4 (2017-04-05)
- Don’t show source project name when user does not have access.
- Remove the class attribute from the whitelist for HTML generated from Markdown.
- Fix path disclosure in project import/export.
- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
## 9.0.3 (2017-04-05)
- Fix name colision when importing GitHub pull requests from forked repositories. !9719
......@@ -320,6 +328,14 @@ entry.
- Change development tanuki favicon colors to match logo color order.
- API issues - support filtering by iids.
## 8.17.5 (2017-04-05)
- Don’t show source project name when user does not have access.
- Remove the class attribute from the whitelist for HTML generated from Markdown.
- Fix path disclosure in project import/export.
- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
## 8.17.4 (2017-03-19)
- Only show public emails in atom feeds.
......@@ -534,6 +550,14 @@ entry.
- Remove deprecated GitlabCiService.
- Requeue pending deletion projects.
## 8.16.9 (2017-04-05)
- Don’t show source project name when user does not have access.
- Remove the class attribute from the whitelist for HTML generated from Markdown.
- Fix path disclosure in project import/export.
- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
## 8.16.8 (2017-03-19)
- Only show public emails in atom feeds.
......
......@@ -13,30 +13,32 @@ _This notice should stay as the first item in the CONTRIBUTING.MD file._
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Contributor license agreement](#contributor-license-agreement)
- [Contribute to GitLab](#contribute-to-gitlab)
- [Security vulnerability disclosure](#security-vulnerability-disclosure)
- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
- [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute)
- [Implement design & UI elements](#implement-design-ui-elements)
- [Workflow labels](#workflow-labels)
- [Implement design & UI elements](#implement-design--ui-elements)
- [Release retrospective and kickoff](#release-retrospective-and-kickoff)
- [Retrospective](#retrospective)
- [Kickoff](#kickoff)
- [Retrospective](#retrospective)
- [Kickoff](#kickoff)
- [Issue tracker](#issue-tracker)
- [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines)
- [Issue weight](#issue-weight)
- [Regression issues](#regression-issues)
- [Technical debt](#technical-debt)
- [Stewardship](#stewardship)
- [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines)
- [Issue weight](#issue-weight)
- [Regression issues](#regression-issues)
- [Technical debt](#technical-debt)
- [Stewardship](#stewardship)
- [Merge requests](#merge-requests)
- [Merge request guidelines](#merge-request-guidelines)
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
- [Merge request guidelines](#merge-request-guidelines)
- [Getting your merge request reviewed, approved, and merged](#getting-your-merge-request-reviewed-approved-and-merged)
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
- [Changes for Stable Releases](#changes-for-stable-releases)
- [Definition of done](#definition-of-done)
- [Style guides](#style-guides)
- [Code of conduct](#code-of-conduct)
- [Contribution Flow](#contribution-flow)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
......@@ -529,6 +531,24 @@ reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
## Contribution Flow
When contributing to GitLab, your merge request is subject to review by merge request maintainers of a particular specialty.
When you submit code to GitLab, we really want it to get merged, but there will be times when it will not be merged.
When maintainers are reading through a merge request they may request guidance from other maintainers. If merge request maintainers conclude that the code should not be merged, our reasons will be fully disclosed. If it has been decided that the code quality is not up to GitLab’s standards, the merge request maintainer will refer the author to our docs and code style guides, and provide some guidance.
Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach.
When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
When your code contains more than 500 changes, any major breaking changes, or an external library, `@mention` a maintainer in the merge request. If you are not sure who to mention, the reviewer will add one early in the merge request process.
[core team]: https://about.gitlab.com/core-team/
[team]: https://about.gitlab.com/team/
[getting-help]: https://about.gitlab.com/getting-help/
......
......@@ -476,10 +476,10 @@ AwardsHandler.prototype.setupSearch = function setupSearch() {
this.registerEventListener('on', $('input.emoji-search'), 'input', (e) => {
const term = $(e.target).val().trim();
// Clean previous search results
$('ul.emoji-menu-search, h5.emoji-search').remove();
$('ul.emoji-menu-search, h5.emoji-search-title').remove();
if (term.length > 0) {
// Generate a search result block
const h5 = $('<h5 class="emoji-search" />').text('Search results');
const h5 = $('<h5 class="emoji-search-title"/>').text('Search results');
const foundEmojis = this.searchEmojis(term).show();
const ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis);
$('.emoji-menu-content ul, .emoji-menu-content h5').hide();
......
function BlobForkSuggestion(openButton, cancelButton, suggestionSection) {
if (openButton) {
openButton.addEventListener('click', () => {
suggestionSection.classList.remove('hidden');
});
}
if (cancelButton) {
cancelButton.addEventListener('click', () => {
suggestionSection.classList.add('hidden');
});
}
}
export default BlobForkSuggestion;
/* eslint-disable no-new */
import Vue from 'vue';
import PDFLab from 'vendor/pdflab';
import workerSrc from 'vendor/pdf.worker';
Vue.use(PDFLab, {
workerSrc,
});
export default () => {
const el = document.getElementById('js-pdf-viewer');
new Vue({
el,
data() {
return {
error: false,
loadError: false,
loading: true,
pdf: el.dataset.endpoint,
};
},
methods: {
onLoad() {
this.loading = false;
},
onError(error) {
this.loading = false;
this.loadError = true;
this.error = error;
},
},
template: `
<div class="container-fluid md prepend-top-default append-bottom-default">
<div
class="text-center loading"
v-if="loading && !error">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true"
aria-label="PDF loading">
</i>
</div>
<pdf-lab
v-if="!loadError"
:pdf="pdf"
@pdflabload="onLoad"
@pdflaberror="onError" />
<p
class="text-center"
v-if="error">
<span v-if="loadError">
An error occured whilst loading the file. Please try again later.
</span>
<span v-else>
An error occured whilst decoding the file.
</span>
</p>
</div>
`,
});
};
import renderPDF from './pdf';
document.addEventListener('DOMContentLoaded', renderPDF);
import JSZip from 'jszip';
import JSZipUtils from 'jszip-utils';
export default class SketchLoader {
constructor(container) {
this.container = container;
this.loadingIcon = this.container.querySelector('.js-loading-icon');
this.load();
}
load() {
return this.getZipFile()
.then(data => JSZip.loadAsync(data))
.then(asyncResult => asyncResult.files['previews/preview.png'].async('uint8array'))
.then((content) => {
const url = window.URL || window.webkitURL;
const blob = new Blob([new Uint8Array(content)], {
type: 'image/png',
});
const previewUrl = url.createObjectURL(blob);
this.render(previewUrl);
})
.catch(this.error.bind(this));
}
getZipFile() {
return new JSZip.external.Promise((resolve, reject) => {
JSZipUtils.getBinaryContent(this.container.dataset.endpoint, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
render(previewUrl) {
const previewLink = document.createElement('a');
const previewImage = document.createElement('img');
previewLink.href = previewUrl;
previewLink.target = '_blank';
previewImage.src = previewUrl;
previewImage.className = 'img-responsive';
previewLink.appendChild(previewImage);
this.container.appendChild(previewLink);
this.removeLoadingIcon();
}
error() {
const errorMsg = document.createElement('p');
errorMsg.className = 'prepend-top-default append-bottom-default text-center';
errorMsg.textContent = `
Cannot show preview. For previews on sketch files, they must have the file format
introduced by Sketch version 43 and above.
`;
this.container.appendChild(errorMsg);
this.removeLoadingIcon();
}
removeLoadingIcon() {
if (this.loadingIcon) {
this.loadingIcon.remove();
}
}
}
/* eslint-disable no-new */
import SketchLoader from './sketch';
document.addEventListener('DOMContentLoaded', () => {
const el = document.getElementById('js-sketch-viewer');
new SketchLoader(el);
});
/* eslint-disable comma-dangle, space-before-function-paren, one-var */
/* global Sortable */
import Vue from 'vue';
import boardList from './board_list';
import boardBlankState from './board_blank_state';
require('./board_delete');
......@@ -16,7 +16,7 @@ require('./board_list');
gl.issueBoards.Board = Vue.extend({
template: '#js-board-template',
components: {
'board-list': gl.issueBoards.BoardList,
boardList,
'board-delete': gl.issueBoards.BoardDelete,
boardBlankState,
},
......
/* eslint-disable comma-dangle, space-before-function-paren, max-len */
/* global Sortable */
import Vue from 'vue';
import boardNewIssue from './board_new_issue';
import boardCard from './board_card';
import eventHub from '../eventhub';
(() => {
const Store = gl.issueBoards.BoardsStore;
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
const Store = gl.issueBoards.BoardsStore;
gl.issueBoards.BoardList = Vue.extend({
template: '#js-board-list-template',
components: {
boardCard,
boardNewIssue,
export default {
name: 'BoardList',
props: {
disabled: {
type: Boolean,
required: true,
},
props: {
disabled: Boolean,
list: Object,
issues: Array,
loading: Boolean,
issueLinkBase: String,
rootPath: String,
list: {
type: Object,
required: true,
},
data () {
return {
scrollOffset: 250,
filters: Store.state.filters,
showCount: false,
showIssueForm: false
};
issues: {
type: Array,
required: true,
},
watch: {
filters: {
handler () {
this.list.loadingMore = false;
this.$refs.list.scrollTop = 0;
},
deep: true
},
issues () {
this.$nextTick(() => {
if (this.scrollHeight() <= this.listHeight() && this.list.issuesSize > this.list.issues.length) {
this.list.page += 1;
this.list.getIssues(false);
}
loading: {
type: Boolean,
required: true,
},
issueLinkBase: {
type: String,
required: true,
},
rootPath: {
type: String,
required: true,
},
},
data() {
return {
scrollOffset: 250,
filters: Store.state.filters,
showCount: false,
showIssueForm: false,
};
},
components: {
boardCard,
boardNewIssue,
},
methods: {
listHeight() {
return this.$refs.list.getBoundingClientRect().height;
},
scrollHeight() {
return this.$refs.list.scrollHeight;
},
scrollTop() {
return this.$refs.list.scrollTop + this.listHeight();
},
loadNextPage() {
const getIssues = this.list.nextPage();
if (this.scrollHeight() > Math.ceil(this.listHeight())) {
this.showCount = true;
} else {
this.showCount = false;
}
if (getIssues) {
this.list.loadingMore = true;
getIssues.then(() => {
this.list.loadingMore = false;
});
}
},
methods: {
listHeight () {
return this.$refs.list.getBoundingClientRect().height;
},
scrollHeight () {
return this.$refs.list.scrollHeight;
},
scrollTop () {
return this.$refs.list.scrollTop + this.listHeight();
toggleForm() {
this.showIssueForm = !this.showIssueForm;
},
onScroll() {
if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) {
this.loadNextPage();
}
},
},
watch: {
filters: {
handler() {
this.list.loadingMore = false;
this.$refs.list.scrollTop = 0;
},
loadNextPage () {
const getIssues = this.list.nextPage();
deep: true,
},
issues() {
this.$nextTick(() => {
if (this.scrollHeight() <= this.listHeight() &&
this.list.issuesSize > this.list.issues.length) {
this.list.page += 1;
this.list.getIssues(false);
}
if (getIssues) {
this.list.loadingMore = true;
getIssues.then(() => {
this.list.loadingMore = false;
});
if (this.scrollHeight() > Math.ceil(this.listHeight())) {
this.showCount = true;
} else {
this.showCount = false;
}
},
toggleForm() {
this.showIssueForm = !this.showIssueForm;
},
},
created() {
gl.IssueBoardsApp.$on(`hide-issue-form-${this.list.id}`, this.toggleForm);
});
},
mounted () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({
scroll: document.querySelectorAll('.boards-list')[0],
group: 'issues',
disabled: this.disabled,
filter: '.board-list-count, .is-disabled',
dataIdAttr: 'data-issue-id',
onStart: (e) => {
const card = this.$refs.issue[e.oldIndex];
},
created() {
eventHub.$on(`hide-issue-form-${this.list.id}`, this.toggleForm);
},
mounted() {
const options = gl.issueBoards.getBoardSortableDefaultOptions({
scroll: document.querySelectorAll('.boards-list')[0],
group: 'issues',
disabled: this.disabled,
filter: '.board-list-count, .is-disabled',
dataIdAttr: 'data-issue-id',
onStart: (e) => {
const card = this.$refs.issue[e.oldIndex];
card.showDetail = false;
Store.moving.list = card.list;
Store.moving.issue = Store.moving.list.findIssue(+e.item.dataset.issueId);
card.showDetail = false;
Store.moving.list = card.list;
Store.moving.issue = Store.moving.list.findIssue(+e.item.dataset.issueId);
gl.issueBoards.onStart();
},
onAdd: (e) => {
gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue, e.newIndex);
gl.issueBoards.onStart();
},
onAdd: (e) => {
gl.issueBoards.BoardsStore
.moveIssueToList(Store.moving.list, this.list, Store.moving.issue, e.newIndex);
this.$nextTick(() => {
e.item.remove();
});
},
onUpdate: (e) => {
const sortedArray = this.sortable.toArray().filter(id => id !== '-1');
gl.issueBoards.BoardsStore.moveIssueInList(this.list, Store.moving.issue, e.oldIndex, e.newIndex, sortedArray);
},
onMove(e) {
return !e.related.classList.contains('board-list-count');
}
});
this.$nextTick(() => {
e.item.remove();
});
},
onUpdate: (e) => {
const sortedArray = this.sortable.toArray().filter(id => id !== '-1');
gl.issueBoards.BoardsStore
.moveIssueInList(this.list, Store.moving.issue, e.oldIndex, e.newIndex, sortedArray);
},
onMove(e) {
return !e.related.classList.contains('board-list-count');
},
});
this.sortable = Sortable.create(this.$refs.list, options);
this.sortable = Sortable.create(this.$refs.list, options);
// Scroll event on list to load more
this.$refs.list.onscroll = () => {
if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) {
this.loadNextPage();
}
};
},
beforeDestroy() {
gl.IssueBoardsApp.$off(`hide-issue-form-${this.list.id}`, this.toggleForm);
},
});
})();
// Scroll event on list to load more
this.$refs.list.addEventListener('scroll', this.onScroll);
},
beforeDestroy() {
eventHub.$off(`hide-issue-form-${this.list.id}`, this.toggleForm);
this.$refs.list.removeEventListener('scroll', this.onScroll);
},
template: `
<div class="board-list-component">
<div
class="board-list-loading text-center"
aria-label="Loading issues"
v-if="loading">
<i
class="fa fa-spinner fa-spin"
aria-hidden="true">
</i>
</div>
<board-new-issue
:list="list"
v-if="list.type !== 'closed' && showIssueForm"/>
<ul
class="board-list"
v-show="!loading"
ref="list"
:data-board="list.id"
:class="{ 'is-smaller': showIssueForm }">
<board-card
v-for="(issue, index) in issues"
ref="issue"
:index="index"
:list="list"
:issue="issue"
:issue-link-base="issueLinkBase"
:root-path="rootPath"
:disabled="disabled"
:key="issue.id" />
<li
class="board-list-count text-center"
v-if="showCount"
data-id="-1">
<i
class="fa fa-spinner fa-spin"
aria-label="Loading more issues"
aria-hidden="true"
v-show="list.loadingMore">
</i>
<span v-if="list.issues.length === list.issuesSize">
Showing all issues
</span>
<span v-else>
Showing {{ list.issues.length }} of {{ list.issuesSize }} issues
</span>
</li>
</ul>
</div>
`,
};
/* global ListIssue */
import eventHub from '../eventhub';
const Store = gl.issueBoards.BoardsStore;
export default {
......@@ -53,7 +55,7 @@ export default {
},
cancel() {
this.title = '';
gl.IssueBoardsApp.$emit(`hide-issue-form-${this.list.id}`);
eventHub.$emit(`hide-issue-form-${this.list.id}`);
},
},
mounted() {
......
This diff is collapsed.
import Cookies from 'js-cookie';
import BurndownChart from './burndown_chart';
$(() => {
// handle hint dismissal
const hint = $('.burndown-hint');
hint.on('click', '.dismiss-icon', () => {
hint.hide();
Cookies.set('hide_burndown_message', 'true');
});
// generate burndown chart (if data available)
const container = '.burndown-chart';
const $chartElm = $(container);
if ($chartElm.length) {
const startDate = $chartElm.data('startDate');
const dueDate = $chartElm.data('dueDate');
const chartData = $chartElm.data('chartData');
const openIssuesCount = chartData.map(d => [d[0], d[1]]);
const openIssuesWeight = chartData.map(d => [d[0], d[2]]);
const chart = new BurndownChart({ container, startDate, dueDate });
let currentView = 'count';
chart.setData(openIssuesCount, { label: 'Open issues', animate: true });
$('.js-burndown-data-selector').on('click', 'button', function switchData() {
const $this = $(this);
const show = $this.data('show');
if (currentView !== show) {
currentView = show;
$this.addClass('active').siblings().removeClass('active');
switch (show) {
case 'count':
chart.setData(openIssuesCount, { label: 'Open issues', animate: true });
break;
case 'weight':
chart.setData(openIssuesWeight, { label: 'Open issue weight', animate: true });
break;
default:
break;
}
}
});
window.addEventListener('resize', () => chart.animateResize(1));
$(document).on('click', '.js-sidebar-toggle', () => chart.animateResize(2));
}
});
......@@ -45,6 +45,7 @@ import GroupsList from './groups_list';
import ProjectsList from './projects_list';
import MiniPipelineGraph from './mini_pipeline_graph_dropdown';
import BlobLinePermalinkUpdater from './blob/blob_line_permalink_updater';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import UserCallout from './user_callout';
import GeoNodes from './geo_nodes';
......@@ -90,6 +91,12 @@ const ShortcutsBlob = require('./shortcuts_blob');
skipResetBindings: true,
fileBlobPermalinkUrl,
});
new BlobForkSuggestion(
document.querySelector('.js-edit-blob-link-fork-toggler'),
document.querySelector('.js-cancel-fork-suggestion'),
document.querySelector('.js-file-fork-suggestion-section'),
);
}
switch (page) {
......
......@@ -163,7 +163,8 @@ export default {
<template v-for="instance in deployBoardData.instances">
<instance-component
:status="instance.status"
:tooltipText="instance.tooltip"/>
:tooltip-text="instance.tooltip"
:stable="instance.stable" />
</template>
</div>
</section>
......
......@@ -7,6 +7,9 @@
* see more information about this in
* https://gitlab.com/gitlab-org/gitlab-ee/uploads/5fff049fd88336d9ee0c6ef77b1ba7e3/monitoring__deployboard--key.png
*
* An instance can represent a normal deploy or a canary deploy. In the latter we need to provide
* this information in the tooltip and the colors.
* Mockup is https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1551#note_26595150
*/
export default {
......@@ -28,11 +31,23 @@ export default {
required: false,
default: '',
},
stable: {
type: Boolean,
required: false,
default: true,
},
},
computed: {
cssClass() {
return `deploy-board-instance-${this.status}`;
let cssClassName = `deploy-board-instance-${this.status}`;
if (!this.stable) {
cssClassName = `${cssClassName} deploy-board-instance-canary`;
}
return cssClassName;
},
},
......
......@@ -45,14 +45,14 @@ window.GroupsSelect = (function() {
page,
per_page: GroupsSelect.PER_PAGE,
all_available,
skip_groups,
};
},
results: function (data, page) {
if (data.length) return { results: [] };
const results = data.length ? data : data.results || [];
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
const results = groups.filter(group => skip_groups.indexOf(group.id) === -1);
return {
results,
......
/* eslint-disable import/prefer-default-export */
/**
* Function that allows a number with an X amount of decimals
* to be formatted in the following fashion:
* * For 1 digit to the left of the decimal point and X digits to the right of it
* * * Show 3 digits to the right
* * For 2 digits to the left of the decimal point and X digits to the right of it
* * * Show 2 digits to the right
*/
export function formatRelevantDigits(number) {
let digitsLeft = '';
let relevantDigits = 0;
let formattedNumber = '';
if (!isNaN(Number(number))) {
digitsLeft = number.split('.')[0];
switch (digitsLeft.length) {
case 1:
relevantDigits = 3;
break;
case 2:
relevantDigits = 2;
break;
case 3:
relevantDigits = 1;
break;
default:
relevantDigits = 4;
break;
}
formattedNumber = Number(number).toFixed(relevantDigits);
}
return formattedNumber;
}
......@@ -292,6 +292,10 @@
}
@media(min-width: $screen-xs-max) {
&.merge-requests .text-content {
margin-top: 40px;
}
&.labels .text-content {
margin-top: 70px;
}
......
......@@ -275,3 +275,16 @@ span.idiff {
}
}
}
.file-fork-suggestion {
display: flex;
align-items: center;
justify-content: flex-end;
background-color: $gray-light;
border-bottom: 1px solid $border-color;
padding: 5px $gl-padding;
}
.file-fork-suggestion-note {
margin-right: 1.5em;
}
......@@ -46,7 +46,7 @@
}
.issue-boards-page {
.page-with-sidebar {
.content-wrapper {
padding-bottom: 0;
}
......@@ -101,8 +101,8 @@
@media (min-width: $screen-sm-min) {
height: 475px; // Needed for PhantomJS
height: calc(100vh - 220px);
min-height: 409px;
height: calc(100vh - 222px);
min-height: 475px;
transition: width .2s;
&.is-compact {
......
......@@ -240,6 +240,9 @@
border-width: 1px;
border-style: solid;
margin: 1px;
display: flex;
justify-content: center;
align-items: center;
&-finished {
background-color: $green-100;
......@@ -270,6 +273,17 @@
background-color: $white-light;
border-color: $border-color;
}
&.deploy-board-instance-canary {
&::after {
width: 7px;
height: 7px;
border: 1px solid $white-light;
background-color: $orange-300;
border-radius: 50%;
content: "";
}
}
}
.deploy-board-icon i {
......@@ -295,6 +309,16 @@
text {
fill: $stat-graph-axis-fill;
}
.label-axis-text,
.text-metric-usage {
fill: $black;
font-weight: 500;
}
.legend-axis-text {
fill: $black;
}
}
.x-axis path,
......
......@@ -200,3 +200,157 @@
cursor: -webkit-grab;
cursor: grab;
}
// EE-only
.burndown-hint.container-fluid {
border: 1px solid $border-color;
border-radius: $border-radius-default;
position: relative;
margin: $gl-padding 0;
overflow: hidden;
padding-top: 15px;
padding-bottom: 15px;
.dismiss-icon {
position: absolute;
right: $gl-padding;
cursor: pointer;
color: $cycle-analytics-dismiss-icon-color;
z-index: 1;
}
.svg-container {
text-align: center;
svg {
max-width: 200px;
max-height: 200px;
}
}
.inner-content {
@media (max-width: $screen-xs-max) {
padding: 0 28px;
text-align: center;
}
h4 {
color: $gl-text-color;
font-size: 17px;
}
p {
color: $cycle-analytics-box-text-color;
margin-bottom: $gl-padding;
}
}
}
.burndown-header {
margin: 24px 0 12px;
h3 {
font-size: 16px;
margin: 0;
}
.btn-group {
margin-left: 20px;
margin-bottom: 2px;
}
.btn {
font-size: 12px;
@include btn-outline($white-light, $blue-500, $blue-500, $blue-500, $white-light, $blue-600, $blue-600, $blue-700);
&.active {
background-color: $blue-500;
border-color: $blue-600;
color: $white-light;
}
}
}
.burndown-chart {
width: 100%;
height: 380px;
margin: 5px 0;
@media (max-width: $screen-sm-max) {
height: 320px;
}
@media (max-width: $screen-xs-max) {
height: 200px;
}
.axis {
font-size: 12px;
line,
path {
fill: none;
stroke: $stat-graph-axis-fill;
shape-rendering: crispEdges;
}
}
.axis-label {
text {
fill: $gl-text-color-secondary;
}
line {
stroke: $border-color;
}
}
.legend {
shape-rendering: crispEdges;
text {
font-size: 13px;
fill: $gl-text-color-disabled;
}
rect {
stroke: $border-color;
fill: none;
}
}
.line {
stroke-width: 2px;
fill: none;
&.actual {
stroke: $gl-success;
}
&.ideal {
stroke: $stat-graph-axis-fill;
stroke-dasharray: 6px 6px;
}
}
.focus {
circle {
fill: $white-light;
stroke: $gl-success;
stroke-width: 2px;
}
}
.chart-tooltip {
text {
font-size: 12px;
fill: $white-light;
}
rect {
fill: $black;
}
}
}
......@@ -459,20 +459,13 @@ a.deploy-project-label {
flex-wrap: wrap;
.btn {
margin: 0 10px 10px 0;
padding: 8px;
margin-left: 10px;
}
> div {
margin-bottom: 10px;
padding-left: 0;
&:last-child {
margin-bottom: 0;
.btn {
margin-right: 0;
}
}
}
}
}
......
......@@ -10,6 +10,7 @@ class Groups::ApplicationController < ApplicationController
unless @group
id = params[:group_id] || params[:id]
@group = Group.find_by_full_path(id)
@group_merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id).execute
unless @group && can?(current_user, :read_group, @group)
@group = nil
......
class Import::BaseController < ApplicationController
private
def find_or_create_namespace(name, owner)
return current_user.namespace if name == owner
def find_or_create_namespace(names, owner)
return current_user.namespace if names == owner
return current_user.namespace unless current_user.can_create_group?
begin
name = params[:target_namespace].presence || name
namespace = Group.create!(name: name, path: name, owner: current_user)
namespace.add_owner(current_user)
namespace
rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid
Namespace.find_by_full_path(name)
names = params[:target_namespace].presence || names
full_path_namespace = Namespace.find_by_full_path(names)
return full_path_namespace if full_path_namespace
names.split('/').inject(nil) do |parent, name|
begin
namespace = Group.create!(name: name,
path: name,
owner: current_user,
parent: parent)
namespace.add_owner(current_user)
namespace
rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid
Namespace.where(parent: parent).find_by_path_or_name(name)
end
end
end
end
......@@ -7,9 +7,11 @@ class Projects::BlobController < Projects::ApplicationController
# Raised when given an invalid file path
InvalidPathError = Class.new(StandardError)
prepend_before_action :authenticate_user!, only: [:edit]
before_action :require_non_empty_project, except: [:new, :create]
before_action :authorize_download_code!
before_action :authorize_edit_tree!, only: [:new, :create, :edit, :update, :destroy]
before_action :authorize_edit_tree!, only: [:new, :create, :update, :destroy]
before_action :assign_blob_vars
before_action :commit, except: [:new, :create]
before_action :blob, except: [:new, :create]
......@@ -37,7 +39,11 @@ class Projects::BlobController < Projects::ApplicationController
end
def edit
blob.load_all_data!(@repository)
if can_collaborate_with_project?
blob.load_all_data!(@repository)
else
redirect_to action: 'show'
end
end
def update
......
class Projects::EnvironmentsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_environment!
before_action :authorize_read_deploy_board!, only: :status
before_action :authorize_create_environment!, only: [:new, :create]
before_action :authorize_create_deployment!, only: [:stop]
before_action :authorize_update_environment!, only: [:edit, :update]
......
......@@ -77,11 +77,6 @@ class Projects::IssuesController < Projects::ApplicationController
@merge_request_to_resolve_discussions_of = service.merge_request_to_resolve_discussions_of
@discussion_to_resolve = service.discussions_to_resolve.first if params[:discussion_to_resolve]
# Set Issue description based on project template
if @project.issues_template.present?
@issue.description = @project.issues_template
end
respond_with(@issue)
end
......
......@@ -42,6 +42,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end
def show
@burndown = Burndown.new(@milestone)
end
def create
......
......@@ -9,7 +9,7 @@
# state: 'open' or 'closed' or 'all'
# group_id: integer
# project_id: integer
# milestone_id: integer
# milestone_title: string
# assignee_id: integer
# search: string
# label_name: string
......
......@@ -9,7 +9,7 @@
# state: 'open' or 'closed' or 'all'
# group_id: integer
# project_id: integer
# milestone_id: integer
# milestone_title: string
# assignee_id: integer
# search: string
# label_name: string
......
......@@ -8,31 +8,36 @@ module BlobHelper
%w(credits changelog news copying copyright license authors)
end
def edit_blob_link(project = @project, ref = @ref, path = @path, options = {})
return unless current_user
def edit_path(project = @project, ref = @ref, path = @path, options = {})
namespace_project_edit_blob_path(project.namespace, project,
tree_join(ref, path),
options[:link_opts])
end
def fork_path(project = @project, ref = @ref, path = @path, options = {})
continue_params = {
to: edit_path,
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now
}
namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params)
end
def edit_blob_link(project = @project, ref = @ref, path = @path, options = {})
blob = options.delete(:blob)
blob ||= project.repository.blob_at(ref, path) rescue nil
return unless blob
edit_path = namespace_project_edit_blob_path(project.namespace, project,
tree_join(ref, path),
options[:link_opts])
common_classes = "btn js-edit-blob #{options[:extra_class]}"
if !on_top_of_branch?(project, ref)
button_tag "Edit", class: "btn disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
elsif can_edit_blob?(blob, project, ref)
link_to "Edit", edit_path, class: 'btn btn-sm'
elsif can?(current_user, :fork_project, project)
continue_params = {
to: edit_path,
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now
}
fork_path = namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params)
link_to "Edit", fork_path, class: 'btn', method: :post
button_tag 'Edit', class: "#{common_classes} disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
# This condition applies to anonymous or users who can edit directly
elsif !current_user || (current_user && can_edit_blob?(blob, project, ref))
link_to 'Edit', edit_path(project, ref, path, options), class: "#{common_classes} btn-sm"
elsif current_user && can?(current_user, :fork_project, project)
button_tag 'Edit', class: "#{common_classes} js-edit-blob-link-fork-toggler"
end
end
......
......@@ -301,6 +301,12 @@ class ApplicationSetting < ActiveRecord::Base
read_attribute(:elasticsearch_url).split(',').map(&:strip)
end
def elasticsearch_url=(values)
cleaned = values.split(',').map {|url| url.strip.gsub(%r{/*\z}, '') }
write_attribute(:elasticsearch_url, cleaned.join(','))
end
def elasticsearch_config
{
url: elasticsearch_url,
......
......@@ -46,10 +46,18 @@ class Blob < SimpleDelegator
text? && language && language.name == 'SVG'
end
def pdf?
name && File.extname(name) == '.pdf'
end
def ipython_notebook?
text? && language&.name == 'Jupyter Notebook'
end
def sketch?
binary? && extname.downcase.delete('.') == 'sketch'
end
def size_within_svg_limits?
size <= MAXIMUM_SVG_SIZE
end
......@@ -67,8 +75,12 @@ class Blob < SimpleDelegator
end
elsif image? || svg?
'image'
elsif pdf?
'pdf'
elsif ipython_notebook?
'notebook'
elsif sketch?
'sketch'
elsif text?
'text'
else
......
class Burndown
attr_accessor :start_date, :due_date, :end_date, :issues_count, :issues_weight
def initialize(milestone)
@milestone = milestone
@start_date = @milestone.start_date
@due_date = @milestone.due_date
@end_date = @milestone.due_date
@end_date = Date.today if @end_date.present? && @end_date > Date.today
@issues_count, @issues_weight = milestone.issues.reorder(nil).pluck('COUNT(*), COALESCE(SUM(weight), 0)').first
end
# Returns the chart data in the following format:
# [date, issue count, issue weight] eg: [["2017-03-01", 33, 127], ["2017-03-02", 35, 73], ["2017-03-03", 28, 50]...]
def as_json(opts = nil)
return [] unless valid?
open_issues_count = issues_count
open_issues_weight = issues_weight
start_date.upto(end_date).each_with_object([]) do |date, chart_data|
closed, reopened = closed_and_reopened_issues_by(date)
closed_issues_count = closed.count
closed_issues_weight = sum_issues_weight(closed)
open_issues_count -= closed_issues_count
open_issues_weight -= closed_issues_weight
chart_data << [date.strftime("%Y-%m-%d"), open_issues_count, open_issues_weight]
reopened_count = reopened.count
reopened_weight = sum_issues_weight(reopened)
open_issues_count += reopened_count
open_issues_weight += reopened_weight
end
end
def valid?
start_date && due_date
end
private
def sum_issues_weight(issues)
issues.map(&:weight).compact.sum
end
def closed_and_reopened_issues_by(date)
current_date = date.to_date
closed = issues_with_closed_at.select { |issue| issue.closed_at.to_date == current_date }
reopened = closed.select { |issue| issue.state == 'reopened' }
[closed, reopened]
end
def issues_with_closed_at
@issues_with_closed_at ||=
@milestone.issues.select('closed_at, weight, state').
where('closed_at IS NOT NULL').
order('closed_at ASC')
end
end
......@@ -427,6 +427,8 @@ module Ci
end
def dependencies
return [] if empty_dependencies?
depended_jobs = depends_on_builds
return depended_jobs unless options[:dependencies].present?
......@@ -528,4 +530,4 @@ module Ci
ProjectCacheWorker.perform_async(project_id, [], [:build_artifacts_size])
end
end
end
end
\ No newline at end of file
......@@ -67,10 +67,6 @@ class Issue < ActiveRecord::Base
before_transition any => :closed do |issue|
issue.closed_at = Time.zone.now
end
before_transition closed: any do |issue|
issue.closed_at = nil
end
end
def hook_attrs
......
......@@ -177,6 +177,16 @@ class MergeRequestDiff < ActiveRecord::Base
st_commits.count
end
def utf8_st_diffs
return [] if st_diffs.blank?
st_diffs.map do |diff|
diff.each do |k, v|
diff[k] = encode_utf8(v) if v.respond_to?(:encoding)
end
end
end
private
# Old GitLab implementations may have generated diffs as ["--broken-diff"].
......@@ -270,14 +280,6 @@ class MergeRequestDiff < ActiveRecord::Base
project.merge_base_commit(head_commit_sha, start_commit_sha).try(:sha)
end
def utf8_st_diffs
st_diffs.map do |diff|
diff.each do |k, v|
diff[k] = encode_utf8(v) if v.respond_to?(:encoding)
end
end
end
#
# #save or #update_attributes providing changes on serialized attributes do a lot of
# serialization and deserialization calls resulting in bad performance.
......
......@@ -116,6 +116,8 @@ class Project < ActiveRecord::Base
has_one :prometheus_service, dependent: :destroy, inverse_of: :project
has_one :index_status, dependent: :destroy
has_one :mock_ci_service, dependent: :destroy
has_one :mock_deployment_service, dependent: :destroy
has_one :mock_monitoring_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link
......
class MockDeploymentService < DeploymentService
def title
'Mock deployment'
end
def description
'Mock deployment service'
end
def self.to_param
'mock_deployment'
end
# No terminals support
def terminals(environment)
[]
end
def rollout_status(environment)
OpenStruct.new(
instances: rollout_status_instances,
completion: 80,
valid?: true,
complete?: true
)
end
private
def rollout_status_instances
JSON.parse(Rails.root.join('spec', 'fixtures', 'rollout_status_instances.json'))
end
end
class MockMonitoringService < MonitoringService
def title
'Mock monitoring'
end
def description
'Mock monitoring service'
end
def self.to_param
'mock_monitoring'
end
def metrics(environment)
JSON.parse(Rails.root.join('spec', 'fixtures', 'metrics.json'))
end
end
......@@ -240,7 +240,9 @@ class Service < ActiveRecord::Base
slack
teamcity
]
service_names << 'mock_ci' if Rails.env.development?
if Rails.env.development?
service_names += %w[mock_ci mock_deployment mock_monitoring]
end
service_names.sort_by(&:downcase)
end
......
......@@ -73,6 +73,10 @@ class ProjectPolicy < BasePolicy
can! :read_environment
can! :read_deployment
can! :read_merge_request
if License.current&.add_on?('GitLab_DeployBoard')
can! :read_deploy_board
end
end
# Permissions given when an user is team member of a project
......
......@@ -39,11 +39,12 @@ class EnvironmentEntity < Grape::Entity
end
expose :rollout_status_path, if: ->(environment, _) { environment.deployment_service_ready? } do |environment|
status_namespace_project_environment_path(
environment.project.namespace,
environment.project,
environment,
format: :json)
can?(request.user, :read_deploy_board, environment.project) &&
status_namespace_project_environment_path(
environment.project.namespace,
environment.project,
environment,
format: :json)
end
expose :created_at, :updated_at
......
......@@ -7,6 +7,10 @@ module Issues
@issue = project.issues.new(issue_params)
end
def issue_params_from_template
{ description: project.issues_template }
end
def issue_params_with_info_from_discussions
return {} unless merge_request_to_resolve_discussions_of
......@@ -49,8 +53,13 @@ module Issues
[discussion_info, quote].join("\n\n")
end
# Issue params can be built from 3 types of passed params,
# They take precedence over eachother like this
# passed params > discussion params > template params
def issue_params
@issue_params ||= issue_params_with_info_from_discussions.merge(whitelisted_issue_params)
@issue_params ||= issue_params_from_template.
merge(issue_params_with_info_from_discussions).
merge(whitelisted_issue_params)
end
def whitelisted_issue_params
......
......@@ -62,6 +62,7 @@ module Users
:email,
:external,
:force_random_password,
:password_automatically_set,
:hide_no_password,
:hide_no_ssh_key,
:key_id,
......@@ -85,6 +86,7 @@ module Users
[
:email,
:email_confirmation,
:password_automatically_set,
:name,
:password,
:username
......
- page_title "Merge Requests"
.top-area
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
- if @group_merge_requests.empty?
= render 'shared/empty_states/merge_requests', project_select_button: true
- else
.top-area
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
= render 'shared/issuable/filter', type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests
.row-content-block.second-block
Only merge requests from
%strong= @group.name
group are listed here.
- if current_user
To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
.row-content-block.second-block
Only merge requests from
%strong= @group.name
group are listed here.
- if current_user
To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
= render 'shared/merge_requests'
.prepend-top-default
= render 'shared/merge_requests'
......@@ -26,4 +26,11 @@
#blob-content-holder.blob-content-holder
%article.file-holder
= render "projects/blob/header", blob: blob
- if current_user
.js-file-fork-suggestion-section.file-fork-suggestion.hidden
%span.file-fork-suggestion-note
You don't have permission to edit this file. Try forking this project to edit the file.
= link_to 'Fork', fork_path, method: :post, class: 'btn btn-grouped btn-inverted btn-new'
%button.js-cancel-fork-suggestion.btn.btn-grouped{ type: 'button' }
Cancel
= render blob.to_partial_path(@project), blob: blob
......@@ -32,10 +32,11 @@
= link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
tree_join(@commit.sha, @path)), class: 'btn btn-sm js-data-file-blob-permalink-url'
- if current_user
.btn-group{ role: "group" }<
.btn-group{ role: "group" }<
- if current_user
= lock_file_link(html_options: {class: 'btn btn-sm path-lock'})
= edit_blob_link if blob_text_viewable?(blob)
= edit_blob_link if blob_text_viewable?(blob)
- if current_user
= replace_blob_link
= delete_blob_link
......
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('pdf_viewer')
.file-content#js-pdf-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sketch_viewer')
.file-content#js-sketch-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
.js-loading-icon.text-center.prepend-top-default.append-bottom-default.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' }
= icon('spinner spin 2x', 'aria-hidden' => 'true');
......@@ -9,7 +9,6 @@
= page_specific_javascript_bundle_tag('boards')
%script#js-board-template{ type: "text/x-template" }= render "projects/boards/components/board"
%script#js-board-list-template{ type: "text/x-template" }= render "projects/boards/components/board_list"
%script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal
= render "projects/issues/head"
......
.board-list-component
.board-list-loading.text-center{ "v-if" => "loading" }
= icon("spinner spin")
- if can? current_user, :create_issue, @project
%board-new-issue{ ":list" => "list",
"v-if" => 'list.type !== "closed" && showIssueForm' }
%ul.board-list{ "ref" => "list",
"v-show" => "!loading",
":data-board" => "list.id",
":class" => '{ "is-smaller": showIssueForm }' }
%board-card{ "v-for" => "(issue, index) in issues",
"ref" => "issue",
":index" => "index",
":list" => "list",
":issue" => "issue",
":issue-link-base" => "issueLinkBase",
":root-path" => "rootPath",
":disabled" => "disabled",
":key" => "issue.id" }
%li.board-list-count.text-center{ "v-if" => "showCount",
"data-issue-id" => "-1" }
= icon("spinner spin", "v-show" => "list.loadingMore" )
%span{ "v-if" => "list.issues.length === list.issuesSize" }
Showing all issues
%span{ "v-else" => true }
Showing {{ list.issues.length }} of {{ list.issuesSize }} issues
- if environment.external_url && can?(current_user, :read_environment, environment)
= link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url' do
= icon('external-link')
View deployment
......@@ -4,3 +4,4 @@
= link_to environment_metrics_path(environment), title: 'See metrics', class: 'btn metrics-button' do
= icon('area-chart')
Monitoring
......@@ -11,7 +11,7 @@
.col-sm-6
%h3.page-title
Environment:
= @environment.name
= link_to @environment.name, environment_path(@environment)
.col-sm-6
.nav-controls
......
......@@ -4,9 +4,9 @@
%div{ class: container_class }
.top-area.adjust
.col-md-9
.col-md-7
%h3.page-title= @environment.name
.col-md-3
.col-md-5
.nav-controls
= render 'projects/environments/metrics_button', environment: @environment
= render 'projects/environments/terminal_button', environment: @environment
......
%ul.content-list.mr-list.issuable-list
= render @merge_requests
- if @merge_requests.blank?
%li
.nothing-here-block No merge requests to show
- if @merge_requests.exists?
= render @merge_requests
- else
= render 'shared/empty_states/merge_requests'
- if @merge_requests.present?
= paginate @merge_requests, theme: "gitlab"
......@@ -7,16 +7,19 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('filtered_search')
%div{ class: container_class }
.top-area
= render 'shared/issuable/nav', type: :merge_requests
.nav-controls
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
- if merge_project
= link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do
New Merge Request
- if @project.merge_requests.exists?
%div{ class: container_class }
.top-area
= render 'shared/issuable/nav', type: :merge_requests
.nav-controls
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
- if merge_project
= link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New merge request" do
New merge request
= render 'shared/issuable/search_bar', type: :merge_requests
= render 'shared/issuable/search_bar', type: :merge_requests
.merge-requests-holder
= render 'merge_requests'
.merge-requests-holder
= render 'merge_requests'
- else
= render 'shared/empty_states/merge_requests', button_path: new_namespace_project_merge_request_path(@project.namespace, @project)
......@@ -46,6 +46,8 @@
= preserve do
= markdown_field(@milestone, :description)
= render 'shared/milestones/burndown', milestone: @milestone, project: @project, burndown: @burndown
- if can?(current_user, :read_issue, @project) && @milestone.total_items_count(current_user).zero?
.alert.alert-success.prepend-top-default
%span Assign some issues to this milestone.
......
......@@ -78,7 +78,7 @@
- if git_import_enabled?
%button.btn.js-toggle-button.import_git{ type: "button" }
= icon('git', text: 'Repo by URL')
.import_gitlab_project
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
- if gitlab_project_import_enabled?
= link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
= icon('gitlab', text: 'GitLab export')
......@@ -109,6 +109,9 @@
%p Please wait a moment, this page will automatically refresh when ready.
:javascript
var importBtnTooltip = "Please enter a valid project name.";
var $importBtnWrapper = $('.import_gitlab_project');
$('.how_to_import_link').bind('click', function (e) {
e.preventDefault();
var import_modal = $(this).next(".modal").show();
......@@ -123,15 +126,8 @@
$(".btn_import_gitlab_project").attr("href", _href + '?namespace_id=' + $("#project_namespace_id").val() + '&path=' + $("#project_path").val());
});
$('.btn_import_gitlab_project').attr('disabled',true)
$('.import_gitlab_project').attr('title', 'Project path and name required.');
$('.import_gitlab_project').click(function( event ) {
if($('.btn_import_gitlab_project').attr('disabled')) {
event.preventDefault();
new Flash("Please enter path and name for the project to be imported to.");
}
});
$('.btn_import_gitlab_project').attr('disabled', $('#project_path').val().trim().length === 0);
$importBtnWrapper.attr('title', importBtnTooltip);
$('#new_project').submit(function(){
var $path = $('#project_path');
......@@ -139,13 +135,13 @@
});
$('#project_path').keyup(function(){
if($(this).val().length !=0) {
if($(this).val().trim().length !== 0) {
$('.btn_import_gitlab_project').attr('disabled', false);
$('.import_gitlab_project').attr('title','');
$(".flash-container").html("")
$importBtnWrapper.attr('title','');
$importBtnWrapper.removeClass('has-tooltip');
} else {
$('.btn_import_gitlab_project').attr('disabled',true);
$('.import_gitlab_project').attr('title', 'Project path and name required.');
$importBtnWrapper.addClass('has-tooltip');
}
});
......
- commit_message = @page.persisted? ? "Update #{@page.title}" : "Create #{@page.title}"
= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form common-note-form prepend-top-default js-quick-submit' } do |f|
= form_errors(@page)
......@@ -28,7 +30,7 @@
.form-group
= f.label :commit_message, class: 'control-label'
.col-sm-10= f.text_field :message, class: 'form-control', rows: 18
.col-sm-10= f.text_field :message, class: 'form-control', rows: 18, value: commit_message
.form-actions
- if @page && @page.persisted?
......
......@@ -6,4 +6,4 @@
= paginate @merge_requests, theme: "gitlab"
- else
.nothing-here-block No merge requests to show
= render 'shared/empty_states/merge_requests'
- button_path = local_assigns.fetch(:button_path, false)
- project_select_button = local_assigns.fetch(:project_select_button, false)
- has_button = button_path || project_select_button
.row.empty-state.merge-requests
.col-xs-12{ class: "#{'col-sm-6 pull-right' if has_button}" }
.svg-content
= render 'shared/empty_states/icons/merge_requests.svg'
.col-xs-12{ class: "#{'col-sm-6' if has_button}" }
.text-content
- if has_button
%h4
Merge requests are a place to propose changes you've made to a project and discuss those changes with others.
%p
Interested parties can even contribute by pushing commits if they want to.
- if project_select_button
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request'
- else
= link_to 'New merge request', button_path, class: 'btn btn-new', title: 'New merge request', id: 'new_merge_request_link'
- else
%h4.text-center
There are no merge requests to show.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="755 221 385 225" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><rect id="a" width="278" height="179" rx="10"/><mask id="d" width="278" height="179" x="0" y="0" fill="#fff"><use xlink:href="#a"/></mask><path id="b" d="M13.6 49H57c5.5 0 10-4.5 10-10V10c0-5.5-4.5-10-10-10H10C4.5 0 0 4.5 0 10v42c0 5.5 3.2 7 7.2 3l6.4-6z"/><mask id="e" width="67" height="57.2" x="0" y="0" fill="#fff"><use xlink:href="#b"/></mask><path id="c" d="M13.6 49H57c5.5 0 10-4.5 10-10V10c0-5.5-4.5-10-10-10H10C4.5 0 0 4.5 0 10v42c0 5.5 3.2 7 7.2 3l6.4-6z"/><mask id="f" width="67" height="57.2" x="0" y="0" fill="#fff"><use xlink:href="#c"/></mask></defs><g fill="none" fill-rule="evenodd"><g fill="#F9F9F9" transform="translate(752 227)"><rect width="120" height="22" x="30" rx="11"/><rect width="132" height="22" y="44" rx="11"/><rect width="190" height="22" x="208" y="66" rx="11"/><rect width="158" height="22" x="129" y="197" rx="11"/><rect width="158" height="22" x="66" y="154" rx="11"/><rect width="350" height="22" x="31" y="110" rx="11"/><path d="M153 22H21h21.5c6 0 11 5 11 11s-5 11-11 11H21h132-36.5c-6 0-11-5-11-11s5-11 11-11H153zm252 66H288h36.5c6 0 11 5 11 11s-5 11-11 11H288h117-36.5c-6 0-11-5-11-11s5-11 11-11H405zm-244 44H44h36.5c6 0 11 5 11 11s-5 11-11 11H44h117-36.5c-6 0-11-5-11-11s5-11 11-11H161zm75 44H119h21.5c6 0 11 5 11 11s-5 11-11 11H119h117-51.5c-6 0-11-5-11-11s5-11 11-11H236z"/></g><g transform="translate(812 240)"><use fill="#FFF" stroke="#EEE" stroke-width="8" mask="url(#d)" xlink:href="#a"/><path fill="#EEE" d="M4 29h271v4H4z"/><g transform="translate(34 60)"><rect width="6" height="2" y="1" fill="#B5A7DD" rx="1"/><rect width="15" height="4" x="15" fill="#EEE" rx="2"/><rect width="15" height="4" x="72" fill="#EEE" rx="2"/><rect width="15" height="4" x="39" y="22" fill="#EEE" rx="2"/><rect width="15" height="4" x="53" y="11" fill="#FC6D26" rx="2"/><rect width="20" height="4" x="48" fill="#FC6D26" opacity=".5" rx="2"/><rect width="20" height="4" x="15" y="22" fill="#EEE" rx="2"/><rect width="20" height="4" x="29" y="11" fill="#EEE" rx="2"/><rect width="10" height="4" x="34" fill="#FC6D26" rx="2"/><rect width="10" height="4" x="15" y="11" fill="#EEE" rx="2"/><rect width="6" height="2" y="12" fill="#B5A7DD" rx="1"/><rect width="6" height="2" y="23" fill="#B5A7DD" rx="1"/></g><g transform="translate(34 93)"><rect width="6" height="2" y="1" fill="#B5A7DD" rx="1"/><rect width="15" height="4" x="15" fill="#FC6D26" rx="2"/><rect width="15" height="4" x="72" fill="#EEE" rx="2"/><rect width="15" height="4" x="39" y="22" fill="#FC6D26" opacity=".5" rx="2"/><rect width="15" height="4" x="53" y="11" fill="#EEE" rx="2"/><rect width="20" height="4" x="48" fill="#FC6D26" rx="2"/><rect width="20" height="4" x="15" y="22" fill="#FC6D26" rx="2"/><rect width="20" height="4" x="29" y="11" fill="#EEE" rx="2"/><rect width="10" height="4" x="34" fill="#FC6D26" opacity=".5" rx="2"/><rect width="10" height="4" x="15" y="11" fill="#EEE" rx="2"/><rect width="6" height="2" y="12" fill="#B5A7DD" rx="1"/><rect width="6" height="2" y="23" fill="#B5A7DD" rx="1"/></g><g transform="translate(34 126)"><rect width="6" height="2" y="1" fill="#B5A7DD" rx="1"/><rect width="15" height="4" x="15" fill="#EEE" rx="2"/><rect width="15" height="4" x="72" fill="#EEE" rx="2"/><rect width="15" height="4" x="39" y="22" fill="#EEE" rx="2"/><rect width="15" height="4" x="53" y="11" fill="#EEE" rx="2"/><rect width="20" height="4" x="48" fill="#FC6D26" rx="2"/><rect width="20" height="4" x="15" y="22" fill="#EEE" rx="2"/><rect width="20" height="4" x="29" y="11" fill="#EEE" rx="2"/><rect width="10" height="4" x="34" fill="#FC6D26" opacity=".5" rx="2"/><rect width="10" height="4" x="15" y="11" fill="#EEE" rx="2"/><rect width="6" height="2" y="12" fill="#B5A7DD" rx="1"/><rect width="6" height="2" y="23" fill="#B5A7DD" rx="1"/></g><g transform="translate(157 59)"><rect width="6" height="2" y="1" fill="#FDE5D8" rx="1"/><rect width="15" height="4" x="15" fill="#EEE" rx="2"/><rect width="15" height="4" x="72" fill="#EEE" rx="2"/><rect width="15" height="4" x="39" y="22" fill="#6B4FBB" opacity=".5" rx="2"/><rect width="15" height="4" x="53" y="11" fill="#6B4FBB" rx="2"/><rect width="20" height="4" x="48" fill="#6B4FBB" opacity=".5" rx="2"/><rect width="20" height="4" x="15" y="22" fill="#6B4FBB" rx="2"/><rect width="20" height="4" x="29" y="11" fill="#EEE" rx="2"/><rect width="10" height="4" x="34" fill="#6B4FBB" rx="2"/><rect width="10" height="4" x="15" y="11" fill="#EEE" rx="2"/><rect width="6" height="2" y="12" fill="#FDE5D8" rx="1"/><rect width="6" height="2" y="23" fill="#FDE5D8" rx="1"/><rect width="6" height="2" y="34" fill="#FDE5D8" rx="1"/><rect width="15" height="4" x="15" y="33" fill="#EEE" rx="2"/><rect width="15" height="4" x="58" y="22" fill="#EEE" rx="2"/><rect width="15" height="4" x="39" y="55" fill="#6B4FBB" opacity=".5" rx="2"/><rect width="15" height="4" x="29" y="44" fill="#6B4FBB" rx="2"/><rect width="20" height="4" x="48" y="33" fill="#6B4FBB" rx="2"/><rect width="20" height="4" x="15" y="55" fill="#EEE" rx="2"/><rect width="10" height="4" x="34" y="33" fill="#EEE" rx="2"/><rect width="10" height="4" x="15" y="44" fill="#EEE" rx="2"/><rect width="10" height="4" x="48" y="44" fill="#EEE" rx="2"/><rect width="10" height="4" x="62" y="44" fill="#EEE" rx="2"/><rect width="10" height="4" x="77" y="22" fill="#EEE" rx="2"/><rect width="6" height="2" y="45" fill="#FDE5D8" rx="1"/><rect width="6" height="2" y="56" fill="#FDE5D8" rx="1"/><rect width="6" height="2" y="67" fill="#FDE5D8" rx="1"/><rect width="15" height="4" x="15" y="66" fill="#6B4FBB" rx="2"/><rect width="15" height="4" x="39" y="88" fill="#EEE" rx="2"/><rect width="15" height="4" x="53" y="77" fill="#6B4FBB" opacity=".5" rx="2"/><rect width="20" height="4" x="15" y="88" fill="#EEE" rx="2"/><rect width="20" height="4" x="29" y="77" fill="#6B4FBB" rx="2"/><rect width="10" height="4" x="34" y="66" fill="#EEE" rx="2"/><rect width="10" height="4" x="72" y="77" fill="#EEE" rx="2"/><rect width="10" height="4" x="15" y="77" fill="#EEE" rx="2"/><rect width="6" height="2" y="78" fill="#FDE5D8" rx="1"/><rect width="6" height="2" y="89" fill="#FDE5D8" rx="1"/></g></g><g transform="translate(1057 221)"><use fill="#FFF" stroke="#FDE5D8" stroke-width="8" mask="url(#e)" xlink:href="#b"/><rect width="29" height="3" x="14" y="14" fill="#FDB692" rx="1.5"/><rect width="39" height="3" x="14" y="23" fill="#FDB692" rx="1.5"/><rect width="29" height="3" x="14" y="32" fill="#FDB692" rx="1.5"/></g><g transform="translate(1046 285)"><circle cx="16" cy="15" r="15" fill="#FFF7F4" stroke="#FC6D26" stroke-width="3"/><path stroke="#FC6D26" stroke-width="2" d="M0 14h1c5 0 9.2-2.7 11.4-6.7M14 1V0"/><path stroke="#FC6D26" stroke-width="2" d="M7.8 3c3 4.3 7.8 7 13.2 7 3.3 0 6.3-1 9-2.7"/><circle cx="10.5" cy="17.5" r="1.5" fill="#FC6D26"/><circle cx="21.5" cy="17.5" r="1.5" fill="#FC6D26"/></g><g transform="translate(825 370)"><circle cx="15" cy="16" r="15" fill="#F4F1FA" stroke="#6B4FBB" stroke-width="3"/><path fill="#6B4FBB" d="M25 7h2.7C25 2.8 20.4 0 15 0 9.6 0 5 2.8 2.3 7H5l2.5-3L10 7l2.5-3L15 7l2.5-3L20 7l2.5-3L25 7z"/><circle cx="9.5" cy="17.5" r="1.5" fill="#6B4FBB"/><circle cx="20.5" cy="17.5" r="1.5" fill="#6B4FBB"/></g><g transform="matrix(-1 0 0 1 840 306)"><use fill="#FFF" stroke="#E2DCF2" stroke-width="8" mask="url(#f)" xlink:href="#c"/><rect width="29" height="3" x="24" y="14" fill="#6B4FBB" opacity=".5" rx="1.5"/><rect width="19" height="3" x="34" y="23" fill="#6B4FBB" opacity=".5" rx="1.5"/><rect width="19" height="3" x="34" y="32" fill="#6B4FBB" opacity=".5" rx="1.5"/></g></g></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>path-1</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="_activity" fill="#7E7D7D">
<g id="Page-1">
<g id="path-1">
<path d="M5,0 C4.448,0 4,0.448 4,1 L4,3 L1,3 C0.448,3 0,3.448 0,4 L0,9 C0,9.552 0.448,10 1,10 L5,10 L5,8 L11,8 L11,10 L15,10 C15.552,10 16,9.552 16,9 L16,4 C16,3.448 15.552,3 15,3 L12,3 L12,1 C12,0.448 11.552,0 11,0 L5,0 L5,0 L5,0 L5,0 Z M6,2.5 C6,2.224 6.224,2 6.5,2 L9.5,2 C9.776,2 10,2.224 10,2.5 C10,2.776 9.776,3 9.5,3 L6.5,3 C6.224,3 6,2.776 6,2.5 L6,2.5 L6,2.5 L6,2.5 Z M6,11 L10.001,11 L10.001,9 L6,9 L6,11 L6,11 L6,11 L6,11 Z M11,11 L11,12 L5,12 L5,11 L1,11 C0.448,11 0,11.448 0,12 L0,15 C0,15.552 0.448,16 1,16 L15,16 C15.552,16 16,15.552 16,15 L16,12 C16,11.448 15.552,11 15,11 L11,11 L11,11 L11,11 L11,11 Z"></path>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>Pasted Image 240</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M3,8 C3,5.951 4.236,4.194 6,3.422 L6,0 L1,0 C0.448,0 0,0.448 0,1 L0,15 C0,15.552 0.448,16 1,16 L6,16 L6,12.578 C4.236,11.806 3,10.049 3,8 M7,12.899 L7,16 L9,16 L9,12.899 C8.677,12.965 8.343,13 8,13 C7.657,13 7.323,12.965 7,12.899 M15,0 L10,0 L10,3.422 C11.764,4.194 13,5.951 13,8 C13,10.049 11.764,11.806 10,12.578 L10,16 L15,16 C15.552,16 16,15.552 16,15 L16,1 C16,0.448 15.552,0 15,0 M10,8 C10,9.105 9.105,10 8,10 C6.895,10 6,9.105 6,8 C6,6.895 6.895,6 8,6 C9.105,6 10,6.895 10,8 M4,8 C4,10.209 5.791,12 8,12 C10.209,12 12,10.209 12,8 C12,5.791 10.209,4 8,4 C5.791,4 4,5.791 4,8 M9,3.101 L9,0 L7,0 L7,3.101 C7.323,3.035 7.657,3 8,3 C8.343,3 8.677,3.035 9,3.101" id="Pasted-Image-240" fill="#7E7D7D"></path>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group">
<path d="M8,0 C3.581,0 0,3.581 0,8 C0,12.419 3.581,16 8,16 C12.419,16 16,12.419 16,8 C16,3.581 12.419,0 8,0 M8,2 C11.308,2 14,4.692 14,8 C14,11.308 11.308,14 8,14 C4.692,14 2,11.308 2,8 C2,4.692 4.692,2 8,2" id="Fill-1" fill="#7E7C7C"></path>
<polygon id="Stroke-6" fill="#7E7C7C" points="2.0197351 9.86809696 6.4567351 6.52409696 5.79233671 6.46815759 9.53233671 10.4271576 9.87070552 10.78534 10.2338016 10.4522494 15.0258016 6.05624938 14.3497984 5.31935062 9.55779844 9.71535062 10.2592633 9.74044241 6.51926329 5.78144241 6.21208651 5.45627854 5.8548649 5.72550304 1.4178649 9.06950304"></polygon>
<path d="M7.0313,6.3928 C7.0313,6.9448 6.5833,7.3928 6.0313,7.3928 C5.4793,7.3928 5.0313,6.9448 5.0313,6.3928 C5.0313,5.8408 5.4793,5.3928 6.0313,5.3928 C6.5833,5.3928 7.0313,5.8408 7.0313,6.3928" id="Fill-8" fill="#FEFEFE"></path>
<path d="M6.5313,6.3928 C6.5313,6.66865763 6.30715763,6.8928 6.0313,6.8928 C5.75544237,6.8928 5.5313,6.66865763 5.5313,6.3928 C5.5313,6.11694237 5.75544237,5.8928 6.0313,5.8928 C6.30715763,5.8928 6.5313,6.11694237 6.5313,6.3928 L6.5313,6.3928 Z M7.5313,6.3928 C7.5313,5.56465763 6.85944237,4.8928 6.0313,4.8928 C5.20315763,4.8928 4.5313,5.56465763 4.5313,6.3928 C4.5313,7.22094237 5.20315763,7.8928 6.0313,7.8928 C6.85944237,7.8928 7.5313,7.22094237 7.5313,6.3928 L7.5313,6.3928 Z" id="Stroke-10" fill="#7E7C7C"></path>
<path d="M10.8854,9.8715 C10.8854,10.4235 10.4374,10.8715 9.8854,10.8715 C9.3334,10.8715 8.8854,10.4235 8.8854,9.8715 C8.8854,9.3195 9.3334,8.8715 9.8854,8.8715 C10.4374,8.8715 10.8854,9.3195 10.8854,9.8715" id="Fill-12" fill="#FEFEFE"></path>
<path d="M10.3854,9.8715 C10.3854,10.1473576 10.1612576,10.3715 9.8854,10.3715 C9.60954237,10.3715 9.3854,10.1473576 9.3854,9.8715 C9.3854,9.59564237 9.60954237,9.3715 9.8854,9.3715 C10.1612576,9.3715 10.3854,9.59564237 10.3854,9.8715 L10.3854,9.8715 Z M11.3854,9.8715 C11.3854,9.04335763 10.7135424,8.3715 9.8854,8.3715 C9.05725763,8.3715 8.3854,9.04335763 8.3854,9.8715 C8.3854,10.6996424 9.05725763,11.3715 9.8854,11.3715 C10.7135424,11.3715 11.3854,10.6996424 11.3854,9.8715 L11.3854,9.8715 Z" id="Stroke-14" fill="#7E7C7C"></path>
</g>
</g>
</svg>
\ No newline at end of file
<svg width="14px" height="10px" viewBox="322 21 14 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M330.078605,22.8166945 L335.259532,29.6235062 C335.615145,30.0907182 335.412062,30.4694683 334.822641,30.4694683 L331.657805,30.4694683 L324.04678,30.4694683 C323.449879,30.4694683 323.260751,30.0822112 323.609889,29.6235062 L328.790816,22.8166945 C329.146429,22.3494825 329.729467,22.3579895 330.078605,22.8166945 Z" id="delta" stroke="#5C5C5C" stroke-width="1" fill="none"></path>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>Pasted Image 237</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Pasted-Image-237">
<path d="M15.1111,16 C15.6021,16 16.0001,15.602 16.0001,15.111 L16.0001,4.444 C15.5341,3.983 12.0671,0.378 11.5551,0 L0.8891,0 C0.3981,0 0.0001,0.398 0.0001,0.889 L0.0001,15.111 C0.0001,15.602 0.3981,16 0.8891,16 L15.1111,16 M14.0001,14.111 L1.8891,14.111 L1.8891,2 L10.8131,2 C11.4451,2.42 13.5811,4.555 14.0001,5.187 L14.0001,14.111" id="Fill-1" fill="#7E7D7D"></path>
<path d="M0.889,0 C0.398,0 0,0.398 0,0.889 L0,15.111 C0,15.602 0.398,16 0.889,16 L15.111,16 C15.602,16 16,15.602 16,15.111 L16,4.445 C15.534,3.983 12.068,0.377 11.555,0 L0.889,0 L0.889,0 Z M1.889,2 L10.813,2 C11.446,2.42 13.581,4.554 14,5.187 L14,14.111 L1.889,14.111 L1.889,2 L1.889,2 Z" id="Clip-4"></path>
<polygon id="Fill-6" fill="#7E7D7D" points="9 7 11 7 11 2 9 2"></polygon>
<polygon id="Clip-9" points="9 7 11 7 11 2.001 9 2.001"></polygon>
<polygon id="Fill-11" fill="#7E7D7D" points="10 7 15.444 7 15.444 5 10 5"></polygon>
<polygon id="Clip-14" points="10 7 15.444 7 15.444 5 10 5"></polygon>
</g>
</g>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 158"><g fill="none" fill-rule="evenodd" transform="translate(-48-26)"><path fill="#fff" d="m25 28h240v158h-240z"/><g transform="translate(56 37)"><g transform="translate(0 21)"><path fill="#eee" d="m13.591 92.21l3.03-3.979c.669-.879.499-2.134-.38-2.803-.879-.669-2.134-.499-2.803.38l-3.03 3.979c-.669.879-.499 2.134.38 2.803.879.669 2.134.499 2.803-.38m10.902-14.323l3.03-3.979c.669-.879.499-2.134-.38-2.803-.879-.669-2.134-.499-2.803.38l-3.03 3.979c-.669.879-.499 2.134.38 2.803.879.669 2.134.499 2.803-.38m10.902-14.323l3.03-3.979c.669-.879.499-2.134-.38-2.803-.879-.669-2.134-.499-2.803.38l-3.03 3.979c-.669.879-.499 2.134.38 2.803.879.669 2.134.499 2.803-.38m10.902-14.323l3.03-3.979c.669-.879.499-2.134-.38-2.803-.879-.669-2.134-.499-2.803.38l-3.03 3.979c-.669.879-.499 2.134.38 2.803.879.669 2.134.499 2.803-.38m10.902-14.323l3.03-3.979c.669-.879.499-2.134-.38-2.803-.879-.669-2.134-.499-2.803.38l-3.03 3.979c-.669.879-.499 2.134.38 2.803.879.669 2.134.499 2.803-.38m7.167-4.942l2.644 4.244c.584.938 1.818 1.224 2.755.64.938-.584 1.224-1.818.64-2.755l-2.644-4.244c-.584-.938-1.818-1.224-2.755-.64-.938.584-1.224 1.818-.64 2.755m9.517 15.278l2.644 4.244c.584.938 1.818 1.224 2.755.64.938-.584 1.224-1.818.64-2.755l-2.644-4.244c-.584-.938-1.818-1.224-2.755-.64-.938.584-1.224 1.818-.64 2.755m9.517 15.278l2.644 4.244c.584.938 1.818 1.224 2.755.64.938-.584 1.224-1.818.64-2.755l-2.644-4.244c-.584-.938-1.818-1.224-2.755-.64-.938.584-1.224 1.818-.64 2.755m9.517 15.278l2.644 4.244c.584.938 1.818 1.224 2.755.64.938-.584 1.224-1.818.64-2.755l-2.644-4.244c-.584-.938-1.818-1.224-2.755-.64-.938.584-1.224 1.818-.64 2.755m13.423 5.929l3.213-3.831c.71-.846.599-2.108-.247-2.818-.846-.71-2.108-.599-2.818.247l-3.213 3.831c-.71.846-.599 2.108.247 2.818.846.71 2.108.599 2.818-.247m11.567-13.791l3.213-3.831c.71-.846.599-2.108-.247-2.818-.846-.71-2.108-.599-2.818.247l-3.213 3.831c-.71.846-.599 2.108.247 2.818.846.71 2.108.599 2.818-.247m8.253-11.614l2.794 4.146c.617.916 1.86 1.158 2.776.541.916-.617 1.158-1.86.541-2.776l-2.794-4.146c-.617-.916-1.86-1.158-2.776-.541-.916.617-1.158 1.86-.541 2.776m10.06 14.927l2.794 4.146c.617.916 1.86 1.158 2.776.541.916-.617 1.158-1.86.541-2.776l-2.794-4.146c-.617-.916-1.86-1.158-2.776-.541-.916.617-1.158 1.86-.541 2.776m10.06 14.927l2.794 4.146c.617.916 1.86 1.158 2.776.541.916-.617 1.158-1.86.541-2.776l-2.794-4.146c-.617-.916-1.86-1.158-2.776-.541-.916.617-1.158 1.86-.541 2.776m10.06 14.927c.618.917 1.861 1.159 2.777.541.916-.617 1.158-1.86.541-2.776-.618-.917-1.861-1.159-2.777-.541-.916.617-1.158 1.86-.541 2.776"/><g transform="translate(61)"><rect width="3" height="24" fill="#fde5d8" rx="1.5"/><path fill="#fc6d26" d="m3 13v-11l11.533 3.105c1.387.373 1.478 1.207.192 1.868l-11.724 6.03"/></g><path fill="#b5a7dd" d="m166.93 83.6l-13.994-7.365c-.287-.151-.607-.23-.931-.23h-20.485c-.491-.271-.816-.45-4.08-2.251l-24.469-13.5c-.694-.383-1.548-.32-2.178.16l-19.433 14.806-20.783-26.451c-.65-.827-1.83-1.01-2.699-.417l-20.604 14.05-20.904-21.708c-.614 1.222-1.633 2.206-2.881 2.775l22.08 22.924c.677.703 1.761.815 2.567.265l20.456-13.947 20.845 26.53c.675.859 1.915 1.018 2.785.355l19.963-15.21c-.005-.003.678.374 3.39 1.87l24.469 13.5c.296.163.628.249.966.249h20.506l13.556 7.135c.201-1.391.879-2.628 1.864-3.539"/><path fill="#6b4fbb" d="m171 96c4.418 0 8-3.582 8-8 0-4.418-3.582-8-8-8-4.418 0-8 3.582-8 8 0 4.418 3.582 8 8 8m0-4c-2.209 0-4-1.791-4-4 0-2.209 1.791-4 4-4 2.209 0 4 1.791 4 4 0 2.209-1.791 4-4 4m-160-46c4.418 0 8-3.582 8-8 0-4.418-3.582-8-8-8-4.418 0-8 3.582-8 8 0 4.418 3.582 8 8 8m0-4c-2.209 0-4-1.791-4-4 0-2.209 1.791-4 4-4 2.209 0 4 1.791 4 4 0 2.209-1.791 4-4 4"/></g><path fill="#fde5d8" d="m168.78 39.803l-2.908.646c-.542.12-.882-.228-.763-.763l.646-2.908-.646-2.908c-.12-.542.228-.882.763-.763l2.908.646 2.908-.646c.542-.12.882.228.763.763l-.646 2.908.646 2.908c.12.542-.228.882-.763.763l-2.908-.646" transform="matrix(.70711.70711-.70711.70711 75.44-108.57)"/><path fill="#d4cde8" d="m101.36 53.839l-2.21.491c-.537.119-.874-.226-.756-.756l.491-2.21-.491-2.21c-.119-.537.226-.874.756-.756l2.21.491 2.21-.491c.537-.119.874.226.756.756l-.491 2.21.491 2.21c.119.537-.226.874-.756.756l-2.21-.491" transform="matrix(.70711.70711-.70711.70711 66.01-56.631)"/><g fill="#fde5d8"><path d="m125.36 8.839l-2.21.491c-.537.119-.874-.226-.756-.756l.491-2.21-.491-2.21c-.119-.537.226-.874.756-.756l2.21.491 2.21-.491c.537-.119.874.226.756.756l-.491 2.21.491 2.21c.119.537-.226.874-.756.756l-2.21-.491" transform="matrix(.70711.70711-.70711.70711 41.22-86.78)"/><path d="m18.778 23.803l-2.908.646c-.542.12-.882-.228-.763-.763l.646-2.908-.646-2.908c-.12-.542.228-.882.763-.763l2.908.646 2.908-.646c.542-.12.882.228.763.763l-.646 2.908.646 2.908c.12.542-.228.882-.763.763l-2.908-.646" transform="matrix(.70711.70711-.70711.70711 20.19-7.192)"/></g></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><path d="M9,7.5l5.83-5.91a.48.48,0,0,0,0-.69L14.11.15a.46.46,0,0,0-.68,0l-5.93,6L1.57.15a.46.46,0,0,0-.68,0L.15.9a.48.48,0,0,0,0,.69L6,7.5.15,13.41a.48.48,0,0,0,0,.69l.74.75a.46.46,0,0,0,.68,0l5.93-6,5.93,6a.46.46,0,0,0,.68,0l.74-.75a.48.48,0,0,0,0-.69Z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><path d="M9,7.5l5.83-5.91a.48.48,0,0,0,0-.69L14.11.15a.46.46,0,0,0-.68,0l-5.93,6L1.57.15a.46.46,0,0,0-.68,0L.15.9a.48.48,0,0,0,0,.69L6,7.5.15,13.41a.48.48,0,0,0,0,.69l.74.75a.46.46,0,0,0,.68,0l5.93-6,5.93,6a.46.46,0,0,0,.68,0l.74-.75a.48.48,0,0,0,0-.69Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g fill-rule="evenodd"><path d="m8.411 1.012c-.136-.008-.273-.012-.411-.012-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-.138-.004-.275-.012-.411-.464.201-.964.334-1.488.386 0 .008 0 .016 0 .025 0 3.038-2.462 5.5-5.5 5.5-3.038 0-5.5-2.462-5.5-5.5 0-3.038 2.462-5.5 5.5-5.5.008 0 .016 0 .025 0 .052-.524.185-1.024.386-1.488"/><path d="m12 2h-1.01c-.54 0-.991.448-.991 1 0 .556.444 1 .991 1h1.01v1.01c0 .54.448.991 1 .991.556 0 1-.444 1-.991v-1.01h1.01c.54 0 .991-.448.991-1 0-.556-.444-1-.991-1h-1.01v-1.01c0-.54-.448-.991-1-.991-.556 0-1 .444-1 .991v1.01m-5 4.01c0-.557.444-1.01 1-1.01.552 0 1 .443 1 1.01v1.981c0 .557-.444 1.01-1 1.01-.552 0-1-.443-1-1.01v-1.981m1 5.991c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g fill-rule="evenodd"><path d="m8.411 1.012c-.136-.008-.273-.012-.411-.012-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-.138-.004-.275-.012-.411-.464.201-.964.334-1.488.386 0 .008 0 .016 0 .025 0 3.038-2.462 5.5-5.5 5.5-3.038 0-5.5-2.462-5.5-5.5 0-3.038 2.462-5.5 5.5-5.5.008 0 .016 0 .025 0 .052-.524.185-1.024.386-1.488"/><path d="m12 2h-1.01c-.54 0-.991.448-.991 1 0 .556.444 1 .991 1h1.01v1.01c0 .54.448.991 1 .991.556 0 1-.444 1-.991v-1.01h1.01c.54 0 .991-.448.991-1 0-.556-.444-1-.991-1h-1.01v-1.01c0-.54-.448-.991-1-.991-.556 0-1 .444-1 .991v1.01m-5 4.01c0-.557.444-1.01 1-1.01.552 0 1 .443 1 1.01v1.981c0 .557-.444 1.01-1 1.01-.552 0-1-.443-1-1.01v-1.981m1 5.991c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 11" class="icon-play">
<path fill-rule="evenodd" d="m9.283 6.47l-7.564 4.254c-.949.534-1.719.266-1.719-.576v-9.292c0-.852.756-1.117 1.719-.576l7.564 4.254c.949.534.963 1.392 0 1.934"/>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 11" class="icon-play"><path fill-rule="evenodd" d="m9.283 6.47l-7.564 4.254c-.949.534-1.719.266-1.719-.576v-9.292c0-.852.756-1.117 1.719-.576l7.564 4.254c.949.534.963 1.392 0 1.934"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 14" enable-background="new 0 0 12 14"><path d="m11.5 2.4l-1.3-1.1-1 1.1 1.4 1.1.9-1.1"/><path d="m6.8 2v-.5h.5v-1.5h-2.6v1.5h.5v.5c-2.9.4-5.2 2.9-5.2 6 0 3.3 2.7 6 6 6s6-2.7 6-6c0-3-2.3-5.6-5.2-6m-.8 10.5c-2.5 0-4.5-2-4.5-4.5s2-4.5 4.5-4.5 4.5 2 4.5 4.5-2 4.5-4.5 4.5"/><path d="m6.2 8.9h-.5c-.1 0-.2-.1-.2-.2v-3.5c0-.1.1-.2.2-.2h.5c.1 0 .2.1.2.2v3.5c0 .1-.1.2-.2.2"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 14" enable-background="new 0 0 12 14"><path d="m11.5 2.4l-1.3-1.1-1 1.1 1.4 1.1.9-1.1"/><path d="m6.8 2v-.5h.5v-1.5h-2.6v1.5h.5v.5c-2.9.4-5.2 2.9-5.2 6 0 3.3 2.7 6 6 6s6-2.7 6-6c0-3-2.3-5.6-5.2-6m-.8 10.5c-2.5 0-4.5-2-4.5-4.5s2-4.5 4.5-4.5 4.5 2 4.5 4.5-2 4.5-4.5 4.5"/><path d="m6.2 8.9h-.5c-.1 0-.2-.1-.2-.2v-3.5c0-.1.1-.2.2-.2h.5c.1 0 .2.1.2.2v3.5c0 .1-.1.2-.2.2"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><g fill="#8F8F8F" fill-rule="evenodd"><path d="M29.513 10.134A15.922 15.922 0 0 0 23 7.28V6h2.993C26.55 6 27 5.552 27 5V2a1 1 0 0 0-1.007-1H14.007C13.45 1 13 1.448 13 2v3a1 1 0 0 0 1.007 1H17v1.28C9.597 8.686 4 15.19 4 23c0 8.837 7.163 16 16 16s16-7.163 16-16c0-3.461-1.099-6.665-2.967-9.283l1.327-1.58a2.498 2.498 0 0 0-.303-3.53 2.499 2.499 0 0 0-3.528.315l-1.016 1.212zM20 34c6.075 0 11-4.925 11-11s-4.925-11-11-11S9 16.925 9 23s4.925 11 11 11z"/><path d="M19 21h-4.002c-.552 0-.998.452-.998 1.01v1.98c0 .567.447 1.01.998 1.01h7.004c.274 0 .521-.111.701-.291a.979.979 0 0 0 .297-.704v-8.01c0-.54-.452-.995-1.01-.995h-1.98a.997.997 0 0 0-1.01.995V21z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><g fill="#8F8F8F" fill-rule="evenodd"><path d="M29.513 10.134A15.922 15.922 0 0 0 23 7.28V6h2.993C26.55 6 27 5.552 27 5V2a1 1 0 0 0-1.007-1H14.007C13.45 1 13 1.448 13 2v3a1 1 0 0 0 1.007 1H17v1.28C9.597 8.686 4 15.19 4 23c0 8.837 7.163 16 16 16s16-7.163 16-16c0-3.461-1.099-6.665-2.967-9.283l1.327-1.58a2.498 2.498 0 0 0-.303-3.53 2.499 2.499 0 0 0-3.528.315l-1.016 1.212zM20 34c6.075 0 11-4.925 11-11s-4.925-11-11-11S9 16.925 9 23s4.925 11 11 11z"/><path d="M19 21h-4.002c-.552 0-.998.452-.998 1.01v1.98c0 .567.447 1.01.998 1.01h7.004c.274 0 .521-.111.701-.291a.979.979 0 0 0 .297-.704v-8.01c0-.54-.452-.995-1.01-.995h-1.98a.997.997 0 0 0-1.01.995V21z"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 168 107" xmlns:xlink="http://www.w3.org/1999/xlink"><g fill="#eee" fill-rule="evenodd"><path d="m4.01 2h1.102c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-1.102c-2.218 0-4.01 1.788-4.01 4 0 .552.448 1 1 1 .552 0 1-.448 1-1 0-1.108.892-2 2.01-2m12.702 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m8.088 0c.822 0 1.554.503 1.86 1.254.208.512.791.758 1.303.55.512-.208.758-.791.55-1.303-.609-1.497-2.069-2.5-3.712-2.5h-2.188c-.552 0-1 .448-1 1 0 .552.448 1 1 1h2.188m2.01 12.518c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7m0 11.6c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7m0 11.6c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7m0 6.282c0 1.108-.892 2-2.01 2h-.72c-.552 0-1 .448-1 1 0 .552.448 1 1 1h.72c2.218 0 4.01-1.788 4.01-4v-.382c0-.552-.448-1-1-1-.552 0-1 .448-1 1v.382m-14.325 2c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-8.47 0c-.755 0-1.438-.424-1.782-1.085-.255-.49-.859-.681-1.349-.426-.49.255-.681.859-.426 1.349.684 1.316 2.046 2.162 3.556 2.162h2.57c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-2.57m-2.01-12.136c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7m0-11.6c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7m0-11.6c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7m0-6.664c0-.552-.448-1-1-1-.552 0-1 .448-1 1v.764c0 .552.448 1 1 1 .552 0 1-.448 1-1v-.764" id="0"/><circle cx="21" cy="24" r="10"/><rect width="33" height="3" x="37" y="18" rx="1.5" id="1"/><rect width="53" height="3" x="37" y="27" rx="1.5" id="2"/><path d="m131 29c0 .552.447.999.996.999h22.01c.545 0 .996-.451.996-.999v-9c0-.552-.447-.999-.996-.999h-22.01c-.545 0-.996.451-.996.999v9m.996-12h22.01c1.655 0 2.996 1.344 2.996 2.999v9c0 1.657-1.35 2.999-2.996 2.999h-22.01c-1.655 0-2.996-1.344-2.996-2.999v-9c0-1.657 1.35-2.999 2.996-2.999" id="3"/><g transform="translate(0 59)"><use xlink:href="#0"/><circle cx="21" cy="24" r="10"/><use xlink:href="#1"/><use xlink:href="#2"/><use xlink:href="#3"/></g></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 168 107" xmlns:xlink="http://www.w3.org/1999/xlink"><g fill="#eee" fill-rule="evenodd"><path d="m4.01 2h1.102c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-1.102c-2.218 0-4.01 1.788-4.01 4 0 .552.448 1 1 1 .552 0 1-.448 1-1 0-1.108.892-2 2.01-2m12.702 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m11.6 0c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7m8.088 0c.822 0 1.554.503 1.86 1.254.208.512.791.758 1.303.55.512-.208.758-.791.55-1.303-.609-1.497-2.069-2.5-3.712-2.5h-2.188c-.552 0-1 .448-1 1 0 .552.448 1 1 1h2.188m2.01 12.518c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7m0 11.6c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7m0 11.6c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7m0 6.282c0 1.108-.892 2-2.01 2h-.72c-.552 0-1 .448-1 1 0 .552.448 1 1 1h.72c2.218 0 4.01-1.788 4.01-4v-.382c0-.552-.448-1-1-1-.552 0-1 .448-1 1v.382m-14.325 2c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-11.6 0c-.552 0-1 .448-1 1 0 .552.448 1 1 1h5.7c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-5.7m-8.47 0c-.755 0-1.438-.424-1.782-1.085-.255-.49-.859-.681-1.349-.426-.49.255-.681.859-.426 1.349.684 1.316 2.046 2.162 3.556 2.162h2.57c.552 0 1-.448 1-1 0-.552-.448-1-1-1h-2.57m-2.01-12.136c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7m0-11.6c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7m0-11.6c0-.552-.448-1-1-1-.552 0-1 .448-1 1v5.7c0 .552.448 1 1 1 .552 0 1-.448 1-1v-5.7m0-6.664c0-.552-.448-1-1-1-.552 0-1 .448-1 1v.764c0 .552.448 1 1 1 .552 0 1-.448 1-1v-.764" id="0"/><circle cx="21" cy="24" r="10"/><rect width="33" height="3" x="37" y="18" rx="1.5" id="1"/><rect width="53" height="3" x="37" y="27" rx="1.5" id="2"/><path d="m131 29c0 .552.447.999.996.999h22.01c.545 0 .996-.451.996-.999v-9c0-.552-.447-.999-.996-.999h-22.01c-.545 0-.996.451-.996.999v9m.996-12h22.01c1.655 0 2.996 1.344 2.996 2.999v9c0 1.657-1.35 2.999-2.996 2.999h-22.01c-1.655 0-2.996-1.344-2.996-2.999v-9c0-1.657 1.35-2.999 2.996-2.999" id="3"/><g transform="translate(0 59)"><use xlink:href="#0"/><circle cx="21" cy="24" r="10"/><use xlink:href="#1"/><use xlink:href="#2"/><use xlink:href="#3"/></g></g></svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="22px" height="16px" viewBox="0 0 22 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" fill="#7E7C7C">
<path d="M6.4357,11.8588 C7.1487,11.2798 7.8797,10.7808 8.5357,10.3708 C8.5837,10.3008 8.6187,10.2338 8.6187,10.1768 L8.6187,8.8088 C8.9197,8.5218 9.0927,8.1248 9.0927,7.7028 L9.0927,5.3748 C9.0927,3.9478 7.9187,2.7858 6.4757,2.7858 L5.9687,2.7858 C4.5247,2.7858 3.3507,3.9478 3.3507,5.3748 L3.3507,7.7028 C3.3507,8.1248 3.5247,8.5218 3.8247,8.8088 L3.8247,10.5838 C3.2537,10.8738 1.8797,11.6198 0.5967,12.6618 C0.2177,12.9698 -0.0003,13.4258 -0.0003,13.9138 L-0.0003,15.5088 C-0.0003,15.5438 0.0857,15.7668 0.3467,15.7778 C1.3257,15.8198 3.8417,15.8328 5.9617,15.9038 C5.8337,15.8148 5.7447,15.6748 5.7447,15.5088 L5.7447,13.5498 C5.7447,12.9848 5.9967,12.2158 6.4357,11.8588" id="Fill-1"></path>
<path d="M21.3092,12.1 C19.6932,10.787 17.9592,9.86 17.3042,9.53 L17.3042,7.235 C17.6722,6.9 17.8862,6.428 17.8862,5.925 L17.8862,3.066 C17.8862,1.376 16.4952,0 14.7852,0 L14.1632,0 C12.4532,0 11.0622,1.376 11.0622,3.066 L11.0622,5.925 C11.0622,6.428 11.2752,6.9 11.6442,7.235 L11.6442,9.53 C10.9892,9.86 9.2542,10.787 7.6392,12.1 C7.2002,12.457 6.9482,12.985 6.9482,13.55 L6.9482,15.509 C6.9482,15.78 7.1702,16 7.4442,16 L14.1172,16 L14.1172,11.704 C12.6812,11.595 11.5652,10.853 11.5652,9.945 C11.5652,9.804 11.5982,9.669 11.6482,9.538 C11.9502,10.326 13.0982,10.913 14.4762,10.913 C15.8532,10.913 17.0012,10.326 17.3032,9.538 C17.3532,9.669 17.3862,9.804 17.3862,9.945 C17.3862,10.793 16.4152,11.5 15.1172,11.679 L15.1172,16 L21.5032,16 C21.7772,16 22.0002,15.78 22.0002,15.509 L22.0002,13.55 C22.0002,12.985 21.7482,12.457 21.3092,12.1" id="Fill-4"></path>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="17px" viewBox="0 0 16 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" fill="#7E7C7C">
<path d="M15.1111,1 L0.8891,1 C0.3981,1 0.0001,1.446 0.0001,1.996 L0.0001,15.945 C0.0001,16.495 0.3981,16.941 0.8891,16.941 L15.1111,16.941 C15.6021,16.941 16.0001,16.495 16.0001,15.945 L16.0001,1.996 C16.0001,1.446 15.6021,1 15.1111,1 L15.1111,1 L15.1111,1 Z M14.0001,6.0002 L14.0001,14.949 L2.0001,14.949 L2.0001,6.0002 L14.0001,6.0002 Z M14.0001,4.0002 L14.0001,2.993 L2.0001,2.993 L2.0001,4.0002 L14.0001,4.0002 Z" id="Combined-Shape"></path>
<polygon id="Fill-11" points="3 2.0002 5 2.0002 5 0.0002 3 0.0002"></polygon>
<polygon id="Fill-16" points="11 2.0002 13 2.0002 13 0.0002 11 0.0002"></polygon>
<path d="M5.37709616,11.5511984 L6.92309616,12.7821984 C7.35112915,13.123019 7.97359761,13.0565604 8.32002627,12.6330535 L10.7740263,9.63305349 C11.1237073,9.20557058 11.0606364,8.57555475 10.6331535,8.22587373 C10.2056706,7.87619272 9.57565475,7.93926361 9.22597373,8.36674651 L6.77197373,11.3667465 L8.16890384,11.2176016 L6.62290384,9.98660159 C6.19085236,9.6425813 5.56172188,9.71394467 5.21770159,10.1459962 C4.8736813,10.5780476 4.94504467,11.2071781 5.37709616,11.5511984 L5.37709616,11.5511984 Z" id="Stroke-21"></path>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" fill="#7E7C7C">
<path d="M15.1111,0 L0.8891,0 C0.3981,0 0.0001,0.446 0.0001,0.996 L0.0001,14.945 C0.0001,15.495 0.3981,15.941 0.8891,15.941 L15.1111,15.941 C15.6021,15.941 16.0001,15.495 16.0001,14.945 L16.0001,0.996 C16.0001,0.446 15.6021,0 15.1111,0 L15.1111,0 L15.1111,0 Z M2.0001,13.949 L14.0001,13.949 L14.0001,1.993 L2.0001,1.993 L2.0001,13.949 Z M2,5.0002 L14,5.0002 L14,3.0002 L2,3.0002 L2,5.0002 Z" id="Combined-Shape"></path>
<path d="M8.547,12.0002 L12,12.0002 L12,10.0002 L8.547,10.0002 L8.547,12.0002 Z M5.2029,12 L3.9999,10.867 L5.2029,9.501 L3.9999,8.181 L5.2029,7 L7.4529,9.499 L5.2029,12 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>Pasted Image 246</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M12.5,14 C11.672,14 11,13.328 11,12.5 C11,11.672 11.672,11 12.5,11 C13.328,11 14,11.672 14,12.5 C14,13.328 13.328,14 12.5,14 M12.5,9 L3.5,9 C1.567,9 0,10.567 0,12.5 C0,14.433 1.567,16 3.5,16 L12.5,16 C14.433,16 16,14.433 16,12.5 C16,10.567 14.433,9 12.5,9 M3.5,2 C4.328,2 5,2.672 5,3.5 C5,4.328 4.328,5 3.5,5 C2.672,5 2,4.328 2,3.5 C2,2.672 2.672,2 3.5,2 M3.5,7 L12.5,7 C14.433,7 16,5.433 16,3.5 C16,1.567 14.433,0 12.5,0 L3.5,0 C1.567,0 0,1.567 0,3.5 C0,5.433 1.567,7 3.5,7" id="Pasted-Image-246" fill="#303030"></path>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>Pasted Image 241</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M2.004,12.9999459 L3.939,12.9999459 L3.939,4.99994585 L2.004,4.99994585 L2.004,12.9999459 Z M7.017,9.99994585 L13.018,9.99994585 L13.018,8.99994585 L7.017,8.99994585 L7.017,9.99994585 Z M7.017,7.99994585 L13.018,7.99994585 L13.018,6.99994585 L7.017,6.99994585 L7.017,7.99994585 Z M7.017,5.99994585 L13.018,5.99994585 L13.018,4.99994585 L7.017,4.99994585 L7.017,5.99994585 Z M14.754,-5.41499267e-05 L4.938,-5.41499267e-05 C4.386,-5.41499267e-05 3.938,0.44794585 3.938,0.99994585 L3.938,2.99994585 L1,2.99994585 C0.448,2.99994585 0,3.44794585 0,3.99994585 L0,12.9999459 C0.037,13.4999459 -0.25,16.0509459 3.938,15.9999459 L12.408,15.9999459 C12.408,15.9999459 15.754,15.9169459 15.754,13.9999459 L15.754,0.99994585 C15.754,0.44794585 15.306,-5.41499267e-05 14.754,-5.41499267e-05 L14.754,-5.41499267e-05 Z" id="Pasted-Image-241" fill="#7E7D7D"></path>
</g>
</svg>
\ No newline at end of file
- milestone = local_assigns[:milestone]
- project = local_assigns[:project]
- burndown = local_assigns[:burndown]
- can_generate_chart = burndown&.valid?
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('burndown_chart')
- if can_generate_chart
.burndown-header
%h3
Burndown chart
.btn-group.js-burndown-data-selector
%button.btn.btn-xs.active{ data: { show: 'count' } }
Issues
%button.btn.btn-xs{ data: { show: 'weight' } }
Issue weight
.burndown-chart{ data: { start_date: burndown.start_date.strftime("%Y-%m-%d"), due_date: burndown.due_date.strftime("%Y-%m-%d"), chart_data: burndown.to_json } }
- elsif can?(current_user, :admin_milestone, @project) && cookies['hide_burndown_message'].nil?
.burndown-hint.content-block.container-fluid
= icon("times", class: "dismiss-icon")
.row
.col-sm-4.col-xs-12.svg-container
= custom_icon('icon_burndown_chart_splash')
.col-sm-8.col-xs-12.inner-content
%h4
Burndown chart
%p
View your milestone's progress as a burndown chart. Add both a start and a due date to
this milestone and the chart will appear here, always up-to-date.
= link_to "Add start and due date", edit_namespace_project_milestone_path(project.namespace, project, milestone), class: 'btn'
---
title: Fix Elasticsearch not working when URL ends with a forward slash
merge_request: 1566
author:
---
title: Added mock data for Deployboard
merge_request:
author:
---
title: Add burndown chart to milestones
merge_request:
author:
---
title: Add a Rake task to make the current node the primary Geo node
merge_request:
author:
---
title: Return 404 instead of a 500 error on API status endpoint if Geo tracking DB is not enabled
merge_request:
author:
---
title: Visualise Canary Deployments
merge_request:
author:
---
title: Added merge requests empty state
merge_request: 7342
author:
---
title: Set GIT_TERMINAL_PROMPT env variable in initializer
merge_request: 10372
author:
---
title: Linking to blob edit page handles anonymous users and users without enough permissions
to edit directly
merge_request:
author:
---
title: Fix project title validation, prevent clicking on disabled button
merge_request: 9931
author:
---
title: Added mock deployment and monitoring service with environments fixtures
merge_request:
author:
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment