Commit a538b0da authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge remote-tracking branch 'upstream/master' into 27762-add-default-artifacts-expiration

* upstream/master: (234 commits)
  Improve performance of User Agent Detail
  Fix some grammar in the API docs
  Remove shared example for pagination
  API: Use POST to (un)block a user
  API: Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar`
  Use grape validation for dates
  Change wording for LDAP doc that was moved to a new location
  API: Remove `DELETE projects/:id/deploy_keys/:key_id/disable`
  Download snippets with LF line-endings by default
  utilize pre-minified Vue in production since no CJS distribution is available
  Prevent project team from being truncated too early during project destruction
  loading icon sometimes toggled alongside MR pipeline contents
  fix failed spec because haml_lint
  fix incorrect sidekiq concurrency count in admin background page
  exclude rpc_pipefs from system disc info
  Fix wrong line ending [ci-skip]
  fix overlooked window binding in spec files
  remove imports loader
  replace implicit this == window with explicit binding
  Todo done clicking is kind of unusable.
  ...
parents eede4ab1 9fe863f4
### Background:
(Include problem, use cases, benefits, and/or goals)
**What questions are you trying to answer?**
**Are you looking to verify an existing hypothesis or uncover new issues you should be exploring?**
**What is the backstory of this project and how does it impact the approach?**
**What do you already know about the areas you are exploring?**
**What does success look like at the end of the project?**
### Links / references:
/label ~"UX research"
......@@ -2,6 +2,22 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 8.16.6 (2017-02-17)
- API: Fix file downloading. !0 (8267)
- Reduce hits to LDAP on Git HTTP auth by reordering auth mechanisms. !8752
- Fix filtered search user autocomplete for gitlab instances that are hosted on a subdirectory. !8891
- Fix wrong call to ProjectCacheWorker.perform. !8910
- Remove unnecessary queries for .atom and .json in Dashboard::ProjectsController#index. !8956
- Fix broken anchor links when special characters are used. !8961 (Andrey Krivko)
- Do not display deploy keys in user's own ssh keys list. !9024
- Show merge errors in merge request widget. !9229
- Don't delete assigned MRs/issues when user is deleted.
- backport of EE fix !954.
- Refresh authorizations when transferring projects.
- Don't use backup Active Record connections for Sidekiq.
- Check public snippets for spam.
## 8.16.5 (2017-02-14)
- Patch Asciidocs rendering to block XSS.
......@@ -181,6 +197,10 @@ entry.
- Add margin to markdown math blocks.
- Add hover state to MR comment reply button.
## 8.15.7 (2017-02-15)
- No changes.
## 8.15.6 (2017-02-14)
- Patch Asciidocs rendering to block XSS.
......@@ -451,6 +471,10 @@ entry.
- Whitelist next project names: help, ci, admin, search. !8227
- Adds back CSS for progress-bars. !8237
## 8.14.10 (2017-02-15)
- No changes.
## 8.14.9 (2017-02-14)
- Patch Asciidocs rendering to block XSS.
......
......@@ -93,18 +93,20 @@ Please see the [UX Guide for GitLab].
### Retrospective
After each release (usually on the 22nd of each month), we have a retrospective
call where we discuss what went well, what went wrong, and what we can improve
for the next release. The [retrospective notes] are public and you are invited
to comment them.
If you're interested, you can even join the [retrospective call][retro-kickoff-call].
After each release, we have a retrospective call where we discuss what went well,
what went wrong, and what we can improve for the next release. The
[retrospective notes] are public and you are invited to comment on them.
If you're interested, you can even join the
[retrospective call][retro-kickoff-call], on the first working day after the
22nd at 6pm CET / 9am PST.
### Kickoff
Before working on the next release (usually on the 8th of each month), we have a
Before working on the next release, we have a
kickoff call to explain what we expect to ship in the next release. The
[kickoff notes] are public and you are invited to comment them.
If you're interested, you can even join the [kickoff call][retro-kickoff-call].
[kickoff notes] are public and you are invited to comment on them.
If you're interested, you can even join the [kickoff call][retro-kickoff-call],
on the first working day after the 7th at 6pm CET / 9am PST..
[retrospective notes]: https://docs.google.com/document/d/1nEkM_7Dj4bT21GJy0Ut3By76FZqCfLBmFQNVThmW2TY/edit?usp=sharing
[kickoff notes]: https://docs.google.com/document/d/1ElPkZ90A8ey_iOkTvUs_ByMlwKK6NAB2VOK5835wYK0/edit?usp=sharing
......
......@@ -61,4 +61,4 @@
return Admin;
})();
}).call(this);
}).call(window);
......@@ -147,4 +147,4 @@
};
window.Api = Api;
}).call(this);
}).call(window);
......@@ -101,11 +101,6 @@ require('es6-promise').polyfill();
}
});
$('.nav-sidebar').niceScroll({
cursoropacitymax: '0.4',
cursorcolor: '#FFF',
cursorborder: '1px solid #FFF'
});
$('.js-select-on-focus').on('focusin', function () {
return $(this).select().one('mouseup', function (e) {
return e.preventDefault();
......@@ -245,9 +240,7 @@ require('es6-promise').polyfill();
});
gl.awardsHandler = new AwardsHandler();
new Aside();
// bind sidebar events
new gl.Sidebar();
gl.utils.initTimeagoTimeout();
});
}).call(this);
}).call(window);
......@@ -22,4 +22,4 @@
return Aside;
})();
}).call(this);
}).call(window);
......@@ -59,4 +59,4 @@
return Autosave;
})();
}).call(this);
}).call(window);
......@@ -377,4 +377,4 @@ var emojiAliases = require('emoji-aliases');
return AwardsHandler;
})();
}).call(this);
}).call(window);
......@@ -25,4 +25,4 @@ var autosize = require('vendor/autosize');
autosize.update($fields);
return $fields.css('resize', 'vertical');
});
}).call(this);
}).call(window);
......@@ -23,4 +23,4 @@
return e.preventDefault();
});
});
}).call(this);
}).call(window);
......@@ -74,4 +74,4 @@ require('../extensions/jquery');
return $this.tooltip('hide');
});
});
}).call(this);
}).call(window);
......@@ -59,4 +59,4 @@ require('../extensions/jquery');
return hideOrShowHelpBlock($form);
});
});
}).call(this);
}).call(window);
......@@ -63,4 +63,4 @@
return BlobFileDropzone;
})();
}).call(this);
}).call(window);
......@@ -20,4 +20,4 @@ require('./template_selector');
return BlobGitignoreSelector;
})(gl.TemplateSelector);
}).call(this);
}).call(window);
......@@ -23,4 +23,4 @@
return BlobGitignoreSelectors;
})();
}).call(this);
}).call(window);
......@@ -25,4 +25,4 @@ require('./template_selector');
return BlobLicenseSelector;
})(gl.TemplateSelector);
}).call(this);
}).call(window);
......@@ -12,4 +12,4 @@ require('./edit_blob');
var blob = new EditBlob(url, $('.js-edit-blob-form').data('blob-language'));
new NewCommitForm($('.js-edit-blob-form'));
});
}).call(this);
}).call(window);
......@@ -85,4 +85,4 @@
return EditBlob;
})();
}).call(this);
}).call(window);
......@@ -95,7 +95,7 @@ $(() => {
},
computed: {
disabled() {
return Store.shouldAddBlankState();
return !this.store.lists.filter(list => list.type !== 'blank' && list.type !== 'done').length;
},
},
template: `
......
......@@ -69,4 +69,4 @@
})(this));
window.Breakpoints = Breakpoints;
}).call(this);
}).call(window);
......@@ -31,4 +31,4 @@
}
});
});
}).call(this);
}).call(window);
......@@ -275,4 +275,4 @@
return Build;
})();
}).call(this);
}).call(window);
......@@ -23,4 +23,4 @@
return BuildArtifacts;
})();
}).call(this);
}).call(window);
......@@ -11,4 +11,4 @@
return Commit;
})();
}).call(this);
}).call(window);
......@@ -11,4 +11,4 @@
return CommitFile;
})();
}).call(this);
}).call(window);
......@@ -173,4 +173,4 @@
return ImageFile;
})();
}).call(this);
}).call(window);
......@@ -4,6 +4,7 @@
*
* Used to store the Pipelines rendered in the commit view in the pipelines table.
*/
require('../../vue_realtime_listener');
class PipelinesStore {
constructor() {
......@@ -24,7 +25,7 @@ class PipelinesStore {
* update the time to show how long as passed.
*
*/
startTimeAgoLoops() {
static startTimeAgoLoops() {
const startTimeLoops = () => {
this.timeLoopInterval = setInterval(() => {
this.$children[0].$children.reduce((acc, component) => {
......@@ -44,7 +45,4 @@ class PipelinesStore {
}
}
window.gl = window.gl || {};
gl.commits = gl.commits || {};
gl.commits.pipelines = gl.commits.pipelines || {};
gl.commits.pipelines.PipelinesStore = PipelinesStore;
module.exports = PipelinesStore;
......@@ -6,9 +6,8 @@ window.Vue.use(require('vue-resource'));
require('../../lib/utils/common_utils');
require('../../vue_shared/vue_resource_interceptor');
require('../../vue_shared/components/pipelines_table');
require('../../vue_realtime_listener/index');
require('./pipelines_service');
require('./pipelines_store');
const PipelineStore = require('./pipelines_store');
/**
*
......@@ -41,7 +40,7 @@ require('./pipelines_store');
data() {
const pipelinesTableData = document.querySelector('#commit-pipeline-table-view').dataset;
const svgsData = document.querySelector('.pipeline-svgs').dataset;
const store = new gl.commits.pipelines.PipelinesStore();
const store = new PipelineStore();
// Transform svgs DOMStringMap to a plain Object.
const svgsObject = gl.utils.DOMStringMapToObject(svgsData);
......@@ -71,7 +70,6 @@ require('./pipelines_store');
.then(response => response.json())
.then((json) => {
this.store.storePipelines(json);
this.store.startTimeAgoLoops.call(this, Vue);
this.isLoading = false;
})
.catch(() => {
......@@ -80,6 +78,12 @@ require('./pipelines_store');
});
},
beforeUpdate() {
if (this.state.pipelines.length && this.$children) {
PipelineStore.startTimeAgoLoops.call(this, Vue);
}
},
template: `
<div class="pipelines">
<div class="realtime-loading" v-if="isLoading">
......
......@@ -65,4 +65,4 @@
return CommitsList;
})();
}).call(this);
}).call(window);
......@@ -88,4 +88,4 @@
return Compare;
})();
}).call(this);
}).call(window);
......@@ -66,4 +66,4 @@
return CompareAutocomplete;
})();
}).call(this);
}).call(window);
......@@ -28,4 +28,4 @@
return ConfirmDangerModal;
})();
}).call(this);
}).call(window);
......@@ -46,4 +46,4 @@ window.Clipboard = require('vendor/clipboard');
clipboard.on('success', genericSuccess);
return clipboard.on('error', genericError);
});
}).call(this);
}).call(window);
......@@ -97,7 +97,7 @@ $(() => {
}
this.isLoadingStage = true;
cycleAnalyticsStore.setStageEvents([]);
cycleAnalyticsStore.setStageEvents([], stage);
cycleAnalyticsStore.setActiveStage(stage);
cycleAnalyticsService
......@@ -107,7 +107,7 @@ $(() => {
})
.done((response) => {
this.isEmptyStage = !response.events.length;
cycleAnalyticsStore.setStageEvents(response.events);
cycleAnalyticsStore.setStageEvents(response.events, stage);
})
.error(() => {
this.isEmptyStage = true;
......
/* eslint-disable no-param-reassign */
require('../lib/utils/text_utility');
const DEFAULT_EVENT_OBJECTS = require('./default_event_objects');
((global) => {
global.cycleAnalytics = global.cycleAnalytics || {};
......@@ -34,11 +38,12 @@
});
newData.stages.forEach((item) => {
const stageName = item.title.toLowerCase();
const stageSlug = gl.text.dasherize(item.title.toLowerCase());
item.active = false;
item.isUserAllowed = data.permissions[stageName];
item.emptyStageText = EMPTY_STAGE_TEXTS[stageName];
item.component = `stage-${stageName}-component`;
item.isUserAllowed = data.permissions[stageSlug];
item.emptyStageText = EMPTY_STAGE_TEXTS[stageSlug];
item.component = `stage-${stageSlug}-component`;
item.slug = stageSlug;
});
newData.analytics = data;
return newData;
......@@ -58,31 +63,33 @@
this.deactivateAllStages();
stage.active = true;
},
setStageEvents(events) {
this.state.events = this.decorateEvents(events);
setStageEvents(events, stage) {
this.state.events = this.decorateEvents(events, stage);
},
decorateEvents(events) {
decorateEvents(events, stage) {
const newEvents = [];
events.forEach((item) => {
if (!item) return;
item.totalTime = item.total_time;
item.author.webUrl = item.author.web_url;
item.author.avatarUrl = item.author.avatar_url;
const eventItem = Object.assign({}, DEFAULT_EVENT_OBJECTS[stage.slug], item);
eventItem.totalTime = eventItem.total_time;
eventItem.author.webUrl = eventItem.author.web_url;
eventItem.author.avatarUrl = eventItem.author.avatar_url;
if (item.created_at) item.createdAt = item.created_at;
if (item.short_sha) item.shortSha = item.short_sha;
if (item.commit_url) item.commitUrl = item.commit_url;
if (eventItem.created_at) eventItem.createdAt = eventItem.created_at;
if (eventItem.short_sha) eventItem.shortSha = eventItem.short_sha;
if (eventItem.commit_url) eventItem.commitUrl = eventItem.commit_url;
delete item.author.web_url;
delete item.author.avatar_url;
delete item.total_time;
delete item.created_at;
delete item.short_sha;
delete item.commit_url;
delete eventItem.author.web_url;
delete eventItem.author.avatar_url;
delete eventItem.total_time;
delete eventItem.created_at;
delete eventItem.short_sha;
delete eventItem.commit_url;
newEvents.push(item);
newEvents.push(eventItem);
});
return newEvents;
......
module.exports = {
issue: {
created_at: '',
url: '',
iid: '',
title: '',
total_time: {},
author: {
avatar_url: '',
id: '',
name: '',
web_url: '',
},
},
plan: {
title: '',
commit_url: '',
short_sha: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
code: {
title: '',
iid: '',
created_at: '',
url: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
test: {
name: '',
id: '',
date: '',
url: '',
short_sha: '',
commit_url: '',
total_time: {},
branch: {
name: '',
url: '',
},
},
review: {
title: '',
iid: '',
created_at: '',
url: '',
state: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
staging: {
id: '',
short_sha: '',
date: '',
url: '',
commit_url: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
branch: {
name: '',
url: '',
},
},
production: {
title: '',
created_at: '',
url: '',
iid: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
};
......@@ -118,6 +118,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
new gl.IssuableTemplateSelectors();
break;
case 'projects:merge_requests:new':
case 'projects:merge_requests:new_diffs':
case 'projects:merge_requests:edit':
new gl.Diff();
shortcut_handler = new ShortcutsNavigation();
......@@ -382,4 +383,4 @@ const ShortcutsBlob = require('./shortcuts_blob');
return Dispatcher;
})();
}).call(this);
}).call(window);
......@@ -216,4 +216,4 @@ require('./preview_markdown');
return DropzoneInput;
})();
}).call(this);
}).call(window);
/* global Vue */
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.ActionsComponent = Vue.component('actions-component', {
props: {
actions: {
type: Array,
required: false,
default: () => [],
},
playIconSvg: {
type: String,
required: false,
},
const Vue = require('vue');
module.exports = Vue.component('actions-component', {
props: {
actions: {
type: Array,
required: false,
default: () => [],
},
template: `
<div class="inline">
<div class="dropdown">
<a class="dropdown-new btn btn-default" data-toggle="dropdown">
<span class="js-dropdown-play-icon-container" v-html="playIconSvg"></span>
<i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-menu-align-right">
<li v-for="action in actions">
<a :href="action.play_path"
data-method="post"
rel="nofollow"
class="js-manual-action-link">
<span class="js-action-play-icon-container" v-html="playIconSvg"></span>
<span>
{{action.name}}
</span>
</a>
</li>
</ul>
</div>
playIconSvg: {
type: String,
required: false,
},
},
template: `
<div class="inline">
<div class="dropdown">
<a class="dropdown-new btn btn-default" data-toggle="dropdown">
<span class="js-dropdown-play-icon-container" v-html="playIconSvg"></span>
<i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-menu-align-right">
<li v-for="action in actions">
<a :href="action.play_path"
data-method="post"
rel="nofollow"
class="js-manual-action-link">
<span class="js-action-play-icon-container" v-html="playIconSvg"></span>
<span>
{{action.name}}
</span>
</a>
</li>
</ul>
</div>
`,
});
})();
</div>
`,
});
/* global Vue */
/**
* Renders the external url link in environments table.
*/
const Vue = require('vue');
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.ExternalUrlComponent = Vue.component('external-url-component', {
props: {
externalUrl: {
type: String,
default: '',
},
module.exports = Vue.component('external-url-component', {
props: {
externalUrl: {
type: String,
default: '',
},
},
template: `
<a class="btn external_url" :href="externalUrl" target="_blank">
<i class="fa fa-external-link"></i>
</a>
`,
});
})();
template: `
<a class="btn external_url" :href="externalUrl" target="_blank">
<i class="fa fa-external-link"></i>
</a>
`,
});
/* global Vue */
/**
* Renders Rollback or Re deploy button in environments table depending
* of the provided property `isLastDeployment`
*/
const Vue = require('vue');
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.RollbackComponent = Vue.component('rollback-component', {
props: {
retryUrl: {
type: String,
default: '',
},
module.exports = Vue.component('rollback-component', {
props: {
retryUrl: {
type: String,
default: '',
},
isLastDeployment: {
type: Boolean,
default: true,
},
isLastDeployment: {
type: Boolean,
default: true,
},
},
template: `
<a class="btn" :href="retryUrl" data-method="post" rel="nofollow">
<span v-if="isLastDeployment">
Re-deploy
</span>
<span v-else>
Rollback
</span>
</a>
`,
});
})();
template: `
<a class="btn" :href="retryUrl" data-method="post" rel="nofollow">
<span v-if="isLastDeployment">
Re-deploy
</span>
<span v-else>
Rollback
</span>
</a>
`,
});
/* global Vue */
/**
* Renders the stop "button" that allows stop an environment.
* Used in environments table.
*/
const Vue = require('vue');
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.StopComponent = Vue.component('stop-component', {
props: {
stopUrl: {
type: String,
default: '',
},
module.exports = Vue.component('stop-component', {
props: {
stopUrl: {
type: String,
default: '',
},
},
template: `
<a class="btn stop-env-link"
:href="stopUrl"
data-confirm="Are you sure you want to stop this environment?"
data-method="post"
rel="nofollow">
<i class="fa fa-stop stop-env-icon"></i>
</a>
`,
});
})();
template: `
<a class="btn stop-env-link"
:href="stopUrl"
data-confirm="Are you sure you want to stop this environment?"
data-method="post"
rel="nofollow">
<i class="fa fa-stop stop-env-icon" aria-hidden="true"></i>
</a>
`,
});
/* global Vue */
/**
* Renders a terminal button to open a web terminal.
* Used in environments table.
*/
const Vue = require('vue');
window.Vue = require('vue');
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.TerminalButtonComponent = Vue.component('terminal-button-component', {
props: {
terminalPath: {
type: String,
default: '',
},
terminalIconSvg: {
type: String,
default: '',
},
module.exports = Vue.component('terminal-button-component', {
props: {
terminalPath: {
type: String,
default: '',
},
terminalIconSvg: {
type: String,
default: '',
},
},
template: `
<a class="btn terminal-button"
:href="terminalPath">
<span class="js-terminal-icon-container" v-html="terminalIconSvg"></span>
</a>
`,
});
})();
template: `
<a class="btn terminal-button"
:href="terminalPath">
<span class="js-terminal-icon-container" v-html="terminalIconSvg"></span>
</a>
`,
});
/**
* Render environments table.
*/
const Vue = require('vue');
const EnvironmentItem = require('./environment_item');
module.exports = Vue.component('environment-table-component', {
components: {
'environment-item': EnvironmentItem,
},
props: {
environments: {
type: Array,
required: true,
default: () => ([]),
},
canReadEnvironment: {
type: Boolean,
required: false,
default: false,
},
canCreateDeployment: {
type: Boolean,
required: false,
default: false,
},
commitIconSvg: {
type: String,
required: false,
},
playIconSvg: {
type: String,
required: false,
},
terminalIconSvg: {
type: String,
required: false,
},
},
template: `
<table class="table ci-table environments">
<thead>
<tr>
<th class="environments-name">Environment</th>
<th class="environments-deploy">Last deployment</th>
<th class="environments-build">Job</th>
<th class="environments-commit">Commit</th>
<th class="environments-date">Updated</th>
<th class="hidden-xs environments-actions"></th>
</tr>
</thead>
<tbody>
<template v-for="model in environments"
v-bind:model="model">
<tr is="environment-item"
:model="model"
:can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
:play-icon-svg="playIconSvg"
:terminal-icon-svg="terminalIconSvg"
:commit-icon-svg="commitIconSvg"></tr>
</template>
</tbody>
</table>
`,
});
window.Vue = require('vue');
require('./stores/environments_store');
require('./components/environment');
require('../vue_shared/vue_resource_interceptor');
const EnvironmentsComponent = require('./components/environment');
$(() => {
window.gl = window.gl || {};
......@@ -9,14 +6,8 @@ $(() => {
if (gl.EnvironmentsListApp) {
gl.EnvironmentsListApp.$destroy(true);
}
const Store = gl.environmentsList.EnvironmentsStore;
gl.EnvironmentsListApp = new gl.environmentsList.EnvironmentsComponent({
gl.EnvironmentsListApp = new EnvironmentsComponent({
el: document.querySelector('#environments-list-view'),
propsData: {
store: Store.create(),
},
});
});
const EnvironmentsFolderComponent = require('./environments_folder_view');
$(() => {
window.gl = window.gl || {};
if (gl.EnvironmentsListFolderApp) {
gl.EnvironmentsListFolderApp.$destroy(true);
}
gl.EnvironmentsListFolderApp = new EnvironmentsFolderComponent({
el: document.querySelector('#environments-folder-list-view'),
});
});
/* eslint-disable no-param-reassign, no-new */
/* global Flash */
const Vue = window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
const EnvironmentsService = require('../services/environments_service');
const EnvironmentTable = require('../components/environments_table');
const EnvironmentsStore = require('../stores/environments_store');
require('../../vue_shared/components/table_pagination');
require('../../lib/utils/common_utils');
require('../../vue_shared/vue_resource_interceptor');
module.exports = Vue.component('environment-folder-view', {
components: {
'environment-table': EnvironmentTable,
'table-pagination': gl.VueGlPagination,
},
data() {
const environmentsData = document.querySelector('#environments-folder-list-view').dataset;
const store = new EnvironmentsStore();
const pathname = window.location.pathname;
const endpoint = `${pathname}.json`;
const folderName = pathname.substr(pathname.lastIndexOf('/') + 1);
return {
store,
folderName,
endpoint,
state: store.state,
visibility: 'available',
isLoading: false,
cssContainerClass: environmentsData.cssClass,
canCreateDeployment: environmentsData.canCreateDeployment,
canReadEnvironment: environmentsData.canReadEnvironment,
// svgs
commitIconSvg: environmentsData.commitIconSvg,
playIconSvg: environmentsData.playIconSvg,
terminalIconSvg: environmentsData.terminalIconSvg,
// Pagination Properties,
paginationInformation: {},
pageNumber: 1,
};
},
computed: {
scope() {
return gl.utils.getParameterByName('scope');
},
canReadEnvironmentParsed() {
return gl.utils.convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
return gl.utils.convertPermissionToBoolean(this.canCreateDeployment);
},
/**
* URL to link in the stopped tab.
*
* @return {String}
*/
stoppedPath() {
return `${window.location.pathname}?scope=stopped`;
},
/**
* URL to link in the available tab.
*
* @return {String}
*/
availablePath() {
return window.location.pathname;
},
},
/**
* Fetches all the environments and stores them.
* Toggles loading property.
*/
created() {
const scope = gl.utils.getParameterByName('scope') || this.visibility;
const pageNumber = gl.utils.getParameterByName('page') || this.pageNumber;
const endpoint = `${this.endpoint}?scope=${scope}&page=${pageNumber}`;
const service = new EnvironmentsService(endpoint);
this.isLoading = true;
return service.all()
.then(resp => ({
headers: resp.headers,
body: resp.json(),
}))
.then((response) => {
this.store.storeAvailableCount(response.body.available_count);
this.store.storeStoppedCount(response.body.stopped_count);
this.store.storeEnvironments(response.body.environments);
this.store.setPagination(response.headers);
})
.then(() => {
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
new Flash('An error occurred while fetching the environments.', 'alert');
});
},
methods: {
/**
* Will change the page number and update the URL.
*
* @param {Number} pageNumber desired page to go to.
*/
changePage(pageNumber) {
const param = gl.utils.setParamInURL('page', pageNumber);
gl.utils.visitUrl(param);
return param;
},
},
template: `
<div :class="cssContainerClass">
<div class="top-area" v-if="!isLoading">
<h4 class="js-folder-name environments-folder-name">
Environments / <b>{{folderName}}</b>
</h4>
<ul class="nav-links">
<li v-bind:class="{ 'active': scope === null || scope === 'available' }">
<a :href="availablePath" class="js-available-environments-folder-tab">
Available
<span class="badge js-available-environments-count">
{{state.availableCounter}}
</span>
</a>
</li>
<li v-bind:class="{ 'active' : scope === 'stopped' }">
<a :href="stoppedPath" class="js-stopped-environments-folder-tab">
Stopped
<span class="badge js-stopped-environments-count">
{{state.stoppedCounter}}
</span>
</a>
</li>
</ul>
</div>
<div class="environments-container">
<div class="environments-list-loading text-center" v-if="isLoading">
<i class="fa fa-spinner fa-spin"></i>
</div>
<div class="table-holder"
v-if="!isLoading && state.environments.length > 0">
<environment-table
:environments="state.environments"
:can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed"
:play-icon-svg="playIconSvg"
:terminal-icon-svg="terminalIconSvg"
:commit-icon-svg="commitIconSvg">
</environment-table>
<table-pagination v-if="state.paginationInformation && state.paginationInformation.totalPages > 1"
:change="changePage"
:pageInfo="state.paginationInformation">
</table-pagination>
</div>
</div>
</div>
`,
});
/* globals Vue */
/* eslint-disable no-unused-vars, no-param-reassign */
const Vue = require('vue');
class EnvironmentsService {
constructor(root) {
Vue.http.options.root = root;
this.environments = Vue.resource(root);
Vue.http.interceptors.push((request, next) => {
// needed in order to not break the tests.
if ($.rails) {
request.headers['X-CSRF-Token'] = $.rails.csrfToken();
}
next();
});
constructor(endpoint) {
this.environments = Vue.resource(endpoint);
}
all() {
......@@ -22,4 +10,4 @@ class EnvironmentsService {
}
}
window.EnvironmentsService = EnvironmentsService;
module.exports = EnvironmentsService;
/* eslint-disable no-param-reassign */
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.EnvironmentsStore = {
state: {},
create() {
this.state.environments = [];
this.state.stoppedCounter = 0;
this.state.availableCounter = 0;
this.state.visibility = 'available';
this.state.filteredEnvironments = [];
return this;
},
/**
* In order to display a tree view we need to modify the received
* data in to a tree structure based on `environment_type`
* sorted alphabetically.
* In each children a `vue-` property will be added. This property will be
* used to know if an item is a children mostly for css purposes. This is
* needed because the children row is a fragment instance and therfore does
* not accept non-prop attributes.
*
*
* @example
* it will transform this:
* [
* { name: "environment", environment_type: "review" },
* { name: "environment_1", environment_type: null }
* { name: "environment_2, environment_type: "review" }
* ]
* into this:
* [
* { name: "review", children:
* [
* { name: "environment", environment_type: "review", vue-isChildren: true},
* { name: "environment_2", environment_type: "review", vue-isChildren: true}
* ]
* },
* {name: "environment_1", environment_type: null}
* ]
*
*
* @param {Array} environments List of environments.
* @returns {Array} Tree structured array with the received environments.
*/
storeEnvironments(environments = []) {
this.state.stoppedCounter = this.countByState(environments, 'stopped');
this.state.availableCounter = this.countByState(environments, 'available');
const environmentsTree = environments.reduce((acc, environment) => {
if (environment.environment_type !== null) {
const occurs = acc.filter(element => element.children &&
element.name === environment.environment_type);
environment['vue-isChildren'] = true;
if (occurs.length) {
acc[acc.indexOf(occurs[0])].children.push(environment);
acc[acc.indexOf(occurs[0])].children.slice().sort(this.sortByName);
} else {
acc.push({
name: environment.environment_type,
children: [environment],
isOpen: false,
'vue-isChildren': environment['vue-isChildren'],
});
}
} else {
acc.push(environment);
}
return acc;
}, []).slice().sort(this.sortByName);
this.state.environments = environmentsTree;
this.filterEnvironmentsByVisibility(this.state.environments);
return environmentsTree;
},
storeVisibility(visibility) {
this.state.visibility = visibility;
},
/**
* Given the visibility prop provided by the url query parameter and which
* changes according to the active tab we need to filter which environments
* should be visible.
*
* The environments array is a recursive tree structure and we need to filter
* both root level environments and children environments.
*
* In order to acomplish that, both `filterState` and `filterEnvironmentsByVisibility`
* functions work together.
* The first one works as the filter that verifies if the given environment matches
* the given state.
* The second guarantees both root level and children elements are filtered as well.
*
* Given array of environments will return only
* the environments that match the state stored.
*
* @param {Array} array
* @return {Array}
*/
filterEnvironmentsByVisibility(arr) {
const filteredEnvironments = arr.map((item) => {
if (item.children) {
const filteredChildren = this.filterEnvironmentsByVisibility(
item.children,
).filter(Boolean);
if (filteredChildren.length) {
item.children = filteredChildren;
return item;
}
}
return this.filterState(this.state.visibility, item);
}).filter(Boolean);
this.state.filteredEnvironments = filteredEnvironments;
return filteredEnvironments;
},
/**
* Given the state and the environment,
* returns only if the environment state matches the one provided.
*
* @param {String} state
* @param {Object} environment
* @return {Object}
*/
filterState(state, environment) {
return environment.state === state && environment;
},
/**
* Toggles folder open property given the environment type.
*
* @param {String} envType
* @return {Array}
*/
toggleFolder(envType) {
const environments = this.state.environments;
const environmentsCopy = environments.map((env) => {
if (env['vue-isChildren'] && env.name === envType) {
env.isOpen = !env.isOpen;
}
return env;
});
this.state.environments = environmentsCopy;
return environmentsCopy;
},
/**
* Given an array of environments, returns the number of environments
* that have the given state.
*
* @param {Array} environments
* @param {String} state
* @returns {Number}
*/
countByState(environments, state) {
return environments.filter(env => env.state === state).length;
},
/**
* Sorts the two objects provided by their name.
*
* @param {Object} a
* @param {Object} b
* @returns {Number}
*/
sortByName(a, b) {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
return nameA < nameB ? -1 : nameA > nameB ? 1 : 0; // eslint-disable-line
},
};
})();
require('~/lib/utils/common_utils');
/**
* Environments Store.
*
* Stores received environments, count of stopped environments and count of
* available environments.
*/
class EnvironmentsStore {
constructor() {
this.state = {};
this.state.environments = [];
this.state.stoppedCounter = 0;
this.state.availableCounter = 0;
this.state.paginationInformation = {};
return this;
}
/**
*
* Stores the received environments.
*
* In the main environments endpoint, each environment has the following schema
* { name: String, size: Number, latest: Object }
* In the endpoint to retrieve environments from each folder, the environment does
* not have the `latest` key and the data is all in the root level.
* To avoid doing this check in the view, we store both cases the same by extracting
* what is inside the `latest` key.
*
* If the `size` is bigger than 1, it means it should be rendered as a folder.
* In those cases we add `isFolder` key in order to render it properly.
*
* @param {Array} environments
* @returns {Array}
*/
storeEnvironments(environments = []) {
const filteredEnvironments = environments.map((env) => {
let filtered = {};
if (env.size > 1) {
filtered = Object.assign({}, env, { isFolder: true, folderName: env.name });
}
if (env.latest) {
filtered = Object.assign(filtered, env, env.latest);
delete filtered.latest;
} else {
filtered = Object.assign(filtered, env);
}
return filtered;
});
this.state.environments = filteredEnvironments;
return filteredEnvironments;
}
setPagination(pagination = {}) {
const normalizedHeaders = gl.utils.normalizeHeaders(pagination);
const paginationInformation = gl.utils.parseIntPagination(normalizedHeaders);
this.state.paginationInformation = paginationInformation;
return paginationInformation;
}
/**
* Stores the number of available environments.
*
* @param {Number} count = 0
* @return {Number}
*/
storeAvailableCount(count = 0) {
this.state.availableCounter = count;
return count;
}
/**
* Stores the number of closed environments.
*
* @param {Number} count = 0
* @return {Number}
*/
storeStoppedCount(count = 0) {
this.state.stoppedCounter = count;
return count;
}
}
module.exports = EnvironmentsStore;
......@@ -13,4 +13,4 @@
return $(this).removeAttr('disabled').removeClass('disabled');
}
});
}).call(this);
}).call(window);
......@@ -144,4 +144,4 @@
}
});
};
}).call(this);
}).call(window);
......@@ -39,4 +39,4 @@
return Flash;
})();
}).call(this);
}).call(window);
......@@ -83,12 +83,12 @@
_a = decodeURI("%C3%80");
_y = decodeURI("%C3%BF");
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])(([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]|[^\\x00-\\x7a])*)$", 'gi');
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?!" + atSymbolsWithBar + ")((?:[A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]|[^\\x00-\\x7a])*)$", 'gi');
match = regexp.exec(subtext);
if (match) {
return (match[1] || match[1] === "") ? match[1] : match[2];
return match[1];
} else {
return null;
}
......@@ -103,6 +103,9 @@
this.input.each((i, input) => {
const $input = $(input);
$input.off('focus.setupAtWho').on('focus.setupAtWho', this.setupAtWho.bind(this, $input));
// This triggers at.js again
// Needed for slash commands with suffixes (ex: /label ~)
$input.on('inserted-commands.atwho', $input.trigger.bind($input, 'keyup'));
});
},
setupAtWho: function($input) {
......@@ -377,4 +380,4 @@
(dataToInspect === loadingState || dataToInspect.name === loadingState);
}
};
}).call(this);
}).call(window);
......@@ -846,4 +846,4 @@
}
});
};
}).call(this);
}).call(window);
......@@ -15,4 +15,4 @@
return StatGraph;
})();
}).call(this);
}).call(window);
......@@ -113,4 +113,4 @@ window.d3 = require('d3');
return ContributorsStatGraph;
})();
}).call(this);
}).call(window);
......@@ -273,4 +273,4 @@ window.d3 = require('d3');
return ContributorsAuthorGraph;
})(ContributorsGraph);
}).call(this);
}).call(window);
......@@ -135,4 +135,4 @@
}
}
};
}).call(this);
}).call(window);
......@@ -17,4 +17,4 @@
return GroupAvatar;
})();
}).call(this);
}).call(window);
......@@ -68,4 +68,4 @@
return GroupsSelect;
})();
}).call(this);
}).call(window);
......@@ -78,4 +78,4 @@
new window.ImporterStatus(jobsImportPath, importPath);
}
});
}).call(this);
}).call(window);
......@@ -76,4 +76,4 @@
return IssuableContext;
})();
}).call(this);
}).call(window);
......@@ -156,4 +156,4 @@
return IssuableForm;
})();
}).call(this);
}).call(window);
......@@ -3,7 +3,7 @@
require('./flash');
require('vendor/jquery.waitforimages');
require('vendor/task_list');
require('./task_list');
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
......@@ -11,10 +11,16 @@ require('vendor/task_list');
this.Issue = (function() {
function Issue() {
this.submitNoteForm = bind(this.submitNoteForm, this);
// Prevent duplicate event bindings
this.disableTaskList();
if ($('a.btn-close').length) {
this.initTaskList();
this.taskList = new gl.TaskList({
dataType: 'issue',
fieldName: 'description',
selector: '.detail-page-description',
onSuccess: (result) => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
}
});
this.initIssueBtnEventListeners();
}
this.initMergeRequests();
......@@ -22,11 +28,6 @@ require('vendor/task_list');
this.initCanCreateBranch();
}
Issue.prototype.initTaskList = function() {
$('.detail-page-description .js-task-list-container').taskList('enable');
return $(document).on('tasklist:changed', '.detail-page-description .js-task-list-container', this.updateTaskList);
};
Issue.prototype.initIssueBtnEventListeners = function() {
var _this, issueFailMessage;
_this = this;
......@@ -54,16 +55,19 @@ require('vendor/task_list');
success: function(data, textStatus, jqXHR) {
if ('id' in data) {
$(document).trigger('issuable:change');
const currentTotal = Number($('.issue_counter').text());
if (isClose) {
$('a.btn-close').addClass('hidden');
$('a.btn-reopen').removeClass('hidden');
$('div.status-box-closed').removeClass('hidden');
$('div.status-box-open').addClass('hidden');
$('.issue_counter').text(currentTotal - 1);
} else {
$('a.btn-reopen').addClass('hidden');
$('a.btn-close').removeClass('hidden');
$('div.status-box-closed').addClass('hidden');
$('div.status-box-open').removeClass('hidden');
$('.issue_counter').text(currentTotal + 1);
}
} else {
new Flash(issueFailMessage, 'alert');
......@@ -82,30 +86,6 @@ require('vendor/task_list');
}
};
Issue.prototype.disableTaskList = function() {
$('.detail-page-description .js-task-list-container').taskList('disable');
return $(document).off('tasklist:changed', '.detail-page-description .js-task-list-container');
};
Issue.prototype.updateTaskList = function() {
var patchData;
patchData = {};
patchData['issue'] = {
'description': $('.js-task-list-field', this).val()
};
return $.ajax({
type: 'PATCH',
url: $('form.js-issuable-update').attr('action'),
data: patchData,
success: function(issue) {
document.querySelector('#task_status').innerText = issue.task_status;
document.querySelector('#task_status_short').innerText = issue.task_status_short;
}
});
// TODO (rspeicher): Make the issue description inline-editable like a note so
// that we can re-use its form here
};
Issue.prototype.initMergeRequests = function() {
var $container;
$container = $('#merge-requests');
......@@ -152,4 +132,4 @@ require('vendor/task_list');
return Issue;
})();
}).call(this);
}).call(window);
......@@ -31,4 +31,4 @@
return IssueStatusSelect;
})();
}).call(this);
}).call(window);
......@@ -43,4 +43,4 @@
return Labels;
})();
}).call(this);
}).call(window);
......@@ -504,4 +504,4 @@
return LabelsSelect;
})();
}).call(this);
}).call(window);
......@@ -44,4 +44,4 @@
}
});
});
}).call(this);
}).call(window);
......@@ -4,4 +4,4 @@
(function() {
}).call(this);
}).call(window);
......@@ -6,4 +6,4 @@
(function() {
}).call(this);
}).call(window);
......@@ -46,4 +46,4 @@
return dfd.promise();
};
})(window);
}).call(this);
}).call(window);
......@@ -231,6 +231,21 @@
return upperCaseHeaders;
};
/**
* Parses pagination object string values into numbers.
*
* @param {Object} paginationInformation
* @returns {Object}
*/
w.gl.utils.parseIntPagination = paginationInformation => ({
perPage: parseInt(paginationInformation['X-PER-PAGE'], 10),
page: parseInt(paginationInformation['X-PAGE'], 10),
total: parseInt(paginationInformation['X-TOTAL'], 10),
totalPages: parseInt(paginationInformation['X-TOTAL-PAGES'], 10),
nextPage: parseInt(paginationInformation['X-NEXT-PAGE'], 10),
previousPage: parseInt(paginationInformation['X-PREV-PAGE'], 10),
});
/**
* Transforms a DOMStringMap into a plain object.
*
......@@ -241,5 +256,45 @@
acc[element] = DOMStringMapObject[element];
return acc;
}, {});
/**
* Updates the search parameter of a URL given the parameter and values provided.
*
* If no search params are present we'll add it.
* If param for page is already present, we'll update it
* If there are params but not for the given one, we'll add it at the end.
* Returns the new search parameters.
*
* @param {String} param
* @param {Number|String|Undefined|Null} value
* @return {String}
*/
w.gl.utils.setParamInURL = (param, value) => {
let search;
const locationSearch = window.location.search;
if (locationSearch.length === 0) {
search = `?${param}=${value}`;
}
if (locationSearch.indexOf(param) !== -1) {
const regex = new RegExp(param + '=\\d');
search = locationSearch.replace(regex, `${param}=${value}`);
}
if (locationSearch.length && locationSearch.indexOf(param) === -1) {
search = `${locationSearch}&${param}=${value}`;
}
return search;
};
/**
* Converts permission provided as strings to booleans.
*
* @param {String} string
* @returns {Boolean}
*/
w.gl.utils.convertPermissionToBoolean = permission => permission === 'true';
})(window);
}).call(this);
}).call(window);
......@@ -123,4 +123,4 @@ window.dateFormat = require('vendor/date.format');
return Math.floor((date2 - date1) / millisecondsPerDay);
};
})(window);
}).call(this);
}).call(window);
......@@ -44,4 +44,4 @@
w.notify = notifyMe;
return w.notifyPermissions = notifyPermissions;
})(window);
}).call(this);
}).call(window);
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len */
require('vendor/latinise');
(function() {
(function(w) {
var base;
......@@ -164,8 +166,14 @@
gl.text.pluralize = function(str, count) {
return str + (count > 1 || count === 0 ? 's' : '');
};
return gl.text.truncate = function(string, maxLength) {
gl.text.truncate = function(string, maxLength) {
return string.substr(0, (maxLength - 3)) + '...';
};
gl.text.dasherize = function(str) {
return str.replace(/[_\s]+/g, '-');
};
gl.text.slugify = function(str) {
return str.trim().toLowerCase().latinise();
};
})(window);
}).call(this);
}).call(window);
......@@ -12,4 +12,4 @@
return (obj != null) && (obj.constructor === Object);
};
})(window);
}).call(this);
}).call(window);
......@@ -83,4 +83,4 @@
document.location.href = url;
};
})(window);
}).call(this);
}).call(window);
......@@ -179,4 +179,4 @@ require('vendor/jquery.scrollTo');
return LineHighlighter;
})();
}).call(this);
}).call(window);
......@@ -4,4 +4,4 @@
window.addEventListener('beforeunload', function() {
$('.tanuki-logo').addClass('animate');
});
}).call(this);
}).call(window);
......@@ -49,4 +49,4 @@
inputs.each(toggleClearInput);
};
}).call(this);
}).call(window);
......@@ -2,7 +2,7 @@
/* global MergeRequestTabs */
require('vendor/jquery.waitforimages');
require('vendor/task_list');
require('./task_list');
require('./merge_request_tabs');
(function() {
......@@ -24,12 +24,18 @@ require('./merge_request_tabs');
};
})(this));
this.initTabs();
// Prevent duplicate event bindings
this.disableTaskList();
this.initMRBtnListeners();
this.initCommitMessageListeners();
if ($("a.btn-close").length) {
this.initTaskList();
this.taskList = new gl.TaskList({
dataType: 'merge_request',
fieldName: 'description',
selector: '.detail-page-description',
onSuccess: (result) => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
}
});
}
}
......@@ -50,11 +56,6 @@ require('./merge_request_tabs');
return this.$('.all-commits').removeClass('hide');
};
MergeRequest.prototype.initTaskList = function() {
$('.detail-page-description .js-task-list-container').taskList('enable');
return $(document).on('tasklist:changed', '.detail-page-description .js-task-list-container', this.updateTaskList);
};
MergeRequest.prototype.initMRBtnListeners = function() {
var _this;
_this = this;
......@@ -85,30 +86,6 @@ require('./merge_request_tabs');
}
};
MergeRequest.prototype.disableTaskList = function() {
$('.detail-page-description .js-task-list-container').taskList('disable');
return $(document).off('tasklist:changed', '.detail-page-description .js-task-list-container');
};
MergeRequest.prototype.updateTaskList = function() {
var patchData;
patchData = {};
patchData['merge_request'] = {
'description': $('.js-task-list-field', this).val()
};
return $.ajax({
type: 'PATCH',
url: $('form.js-issuable-update').attr('action'),
data: patchData,
success: function(mergeRequest) {
document.querySelector('#task_status').innerText = mergeRequest.task_status;
document.querySelector('#task_status_short').innerText = mergeRequest.task_status_short;
}
});
// TODO (rspeicher): Make the merge request description inline-editable like a
// note so that we can re-use its form here
};
MergeRequest.prototype.initCommitMessageListeners = function() {
$(document).on('click', 'a.js-with-description-link', function(e) {
var textarea = $('textarea.js-commit-message');
......@@ -131,4 +108,4 @@ require('./merge_request_tabs');
return MergeRequest;
})();
}).call(this);
}).call(window);
......@@ -252,7 +252,6 @@ require('./smart_interval');
$('.ci_widget.ci-error').show();
this.setMergeButtonClass('btn-danger');
}
this.initMiniPipelineGraph();
};
MergeRequestWidget.prototype.showCICoverage = function(coverage) {
......
......@@ -42,4 +42,4 @@
return MergedButtons;
})();
}).call(this);
}).call(window);
......@@ -172,4 +172,4 @@
return Milestone;
})();
}).call(this);
}).call(window);
......@@ -199,4 +199,4 @@
return MilestoneSelect;
})();
}).call(this);
}).call(window);
......@@ -28,7 +28,7 @@
* All dropdown events are fired at the .dropdown-menu's parent element.
*/
bindEvents() {
$(document).on('shown.bs.dropdown', this.container, this.getBuildsList);
$(document).off('shown.bs.dropdown', this.container).on('shown.bs.dropdown', this.container, this.getBuildsList);
}
/**
......
......@@ -83,4 +83,4 @@
return NamespaceSelects;
})();
}).call(this);
}).call(window);
......@@ -421,4 +421,4 @@
y: h
});
};
}).call(this);
}).call(window);
......@@ -17,4 +17,4 @@
return Network;
})();
}).call(this);
}).call(window);
......@@ -19,4 +19,4 @@ requireAll(require.context('.', false, /^\.\/(?!network_bundle).*\.(js|es6)$/));
});
return new ShortcutsNetwork(network_graph.branch_graph);
});
}).call(this);
}).call(window);
......@@ -100,4 +100,4 @@
return NewBranchForm;
})();
}).call(this);
}).call(window);
......@@ -30,4 +30,4 @@
return NewCommitForm;
})();
}).call(this);
}).call(window);
......@@ -11,7 +11,7 @@ require('./dropzone_input');
require('./gfm_auto_complete');
require('vendor/jquery.caret'); // required by jquery.atwho
require('vendor/jquery.atwho');
require('vendor/task_list');
require('./task_list');
(function() {
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
......@@ -51,7 +51,11 @@ require('vendor/task_list');
this.addBinding();
this.setPollingInterval();
this.setupMainTargetNoteForm();
this.initTaskList();
this.taskList = new gl.TaskList({
dataType: 'note',
fieldName: 'note',
selector: '.notes'
});
this.collapseLongCommitList();
// We are in the Merge Requests page so we need another edit form for Changes tab
......@@ -125,8 +129,6 @@ require('vendor/task_list');
$(document).off("keydown", ".js-note-text");
$(document).off('click', '.js-comment-resolve-button');
$(document).off("click", '.system-note-commit-list-toggler');
$('.note .js-task-list-container').taskList('disable');
return $(document).off('tasklist:changed', '.note .js-task-list-container');
};
Notes.prototype.keydownNoteText = function(e) {
......@@ -286,7 +288,7 @@ require('vendor/task_list');
// Update datetime format on the recent note
gl.utils.localTimeAgo($notesList.find("#note_" + note.id + " .js-timeago"), false);
this.collapseLongCommitList();
this.initTaskList();
this.taskList.init();
this.refresh();
return this.updateNotesCount(1);
}
......@@ -863,15 +865,6 @@ require('vendor/task_list');
}
};
Notes.prototype.initTaskList = function() {
this.enableTaskList();
return $(document).on('tasklist:changed', '.note .js-task-list-container', this.updateTaskList.bind(this));
};
Notes.prototype.enableTaskList = function() {
return $('.note .js-task-list-container').taskList('enable');
};
Notes.prototype.putEditFormInPlace = function($el) {
var $editForm = $(this.getEditFormSelector($el));
var $note = $el.closest('.note');
......@@ -896,17 +889,6 @@ require('vendor/task_list');
$editForm.find('.referenced-users').hide();
};
Notes.prototype.updateTaskList = function(e) {
var $target = $(e.target);
var $list = $target.closest('.js-task-list-container');
var $editForm = $(this.getEditFormSelector($target));
var $note = $list.closest('.note');
this.putEditFormInPlace($list);
$editForm.find('#note_note').val($note.find('.original-task-list').val());
$('form', $list).submit();
};
Notes.prototype.updateNotesCount = function(updateCount) {
return this.notesCountBadge.text(parseInt(this.notesCountBadge.text(), 10) + updateCount);
};
......@@ -955,4 +937,4 @@ require('vendor/task_list');
return Notes;
})();
}).call(this);
}).call(window);
......@@ -28,4 +28,4 @@
return NotificationsDropdown;
})();
}).call(this);
}).call(window);
......@@ -54,4 +54,4 @@
return NotificationsForm;
})();
}).call(this);
}).call(window);
......@@ -126,4 +126,4 @@
return Project;
})();
}).call(this);
}).call(window);
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.
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.
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.
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.
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