Added Markdown editor and Javascript code refactoring

This commit is contained in:
Frederic Guillot
2016-03-20 15:45:02 -04:00
parent 787e91ca41
commit f77d6c590b
64 changed files with 1154 additions and 3644 deletions

View File

@@ -1,11 +1,16 @@
Version 1.0.27 (unreleased) Version 1.0.27 (unreleased)
-------------- --------------
Improvements: New features:
* Improve comments design * Added Markdown editor
* Added letter avatar provider * Added letter avatar provider
* Added pluggable Avatar providers * Added pluggable Avatar providers
Improvements:
* Refactoring of Javascript code
* Improve comments design
* Improve task summary sections * Improve task summary sections
* Put back the action sidebar in task view * Put back the action sidebar in task view
* Added support for multiple placeholders for LDAP_USER_FILTER * Added support for multiple placeholders for LDAP_USER_FILTER

View File

@@ -2,10 +2,10 @@ BUILD_DIR = /tmp
CSS_APP = $(addprefix assets/css/src/, $(addsuffix .css, base links title table form button alert tooltip header board task comment subtask tasklink markdown listing activity dashboard pagination popover confirm sidebar responsive dropdown upload filters gantt project files views accordion avatar)) CSS_APP = $(addprefix assets/css/src/, $(addsuffix .css, base links title table form button alert tooltip header board task comment subtask tasklink markdown listing activity dashboard pagination popover confirm sidebar responsive dropdown upload filters gantt project files views accordion avatar))
CSS_PRINT = $(addprefix assets/css/src/, $(addsuffix .css, print links table board task comment subtask tasklink markdown)) CSS_PRINT = $(addprefix assets/css/src/, $(addsuffix .css, print links table board task comment subtask tasklink markdown))
CSS_VENDOR = $(addprefix assets/css/vendor/, $(addsuffix .css, jquery-ui.min jquery-ui-timepicker-addon.min chosen.min fullcalendar.min font-awesome.min c3.min)) CSS_VENDOR = $(addprefix assets/css/vendor/, $(addsuffix .css, jquery-ui.min jquery-ui-timepicker-addon.min chosen.min fullcalendar.min font-awesome.min c3.min simplemde.min))
JS_APP = $(addprefix assets/js/src/, $(addsuffix .js, Popover Dropdown Tooltip Markdown Search App Screenshot FileUpload Calendar Board Column Swimlane Gantt Task Project Subtask TaskRepartitionChart UserRepartitionChart CumulativeFlowDiagram BurndownChart AvgTimeColumnChart TaskTimeColumnChart LeadCycleTimeChart CompareHoursColumnChart Accordion Router)) JS_APP = $(addprefix assets/js/src/, $(addsuffix .js, Namespace App Dropdown Popover Notification Accordion Session Calendar AvgTimeColumnChart BurndownChart CompareHoursColumnChart CumulativeFlowDiagram LeadCycleTimeChart UserRepartitionChart TaskTimeColumnChart TaskRepartitionChart Gantt Column Markdown ProjectPermission ProjectCreation Screenshot FileUpload Search Task Subtask Swimlane BoardColumnView BoardColumnScrolling BoardHorizontalScrolling BoardCollapsedMode BoardDragAndDrop BoardTask BoardPolling Tooltip Bootstrap))
JS_VENDOR = $(addprefix assets/js/vendor/, $(addsuffix .js, jquery-1.11.3.min jquery-ui.min jquery-ui-timepicker-addon.min jquery.ui.touch-punch.min chosen.jquery.min moment.min fullcalendar.min mousetrap.min mousetrap-global-bind.min jquery.textcomplete)) JS_VENDOR = $(addprefix assets/js/vendor/, $(addsuffix .js, jquery-1.11.3.min jquery-ui.min jquery-ui-timepicker-addon.min jquery.ui.touch-punch.min chosen.jquery.min moment.min fullcalendar.min mousetrap.min mousetrap-global-bind.min simplemde.min))
JS_LANG = $(addprefix assets/js/vendor/lang/, $(addsuffix .js, cs da de es el fi fr hu id it ja nl nb pl pt pt-br ru sv sr th tr zh-cn)) JS_LANG = $(addprefix assets/js/vendor/lang/, $(addsuffix .js, cs da de es el fi fr hu id it ja nl nb pl pt pt-br ru sv sr th tr zh-cn))
all: css js all: css js
@@ -35,10 +35,9 @@ vendor.js:
@ cat ${JS_LANG} >> vendor.js @ cat ${JS_LANG} >> vendor.js
app.js: app.js:
@ rm -f tmp.js
@ rm -f assets/js/app.js @ rm -f assets/js/app.js
@ echo "(function() { 'use strict';" > tmp.js
@ cat ${JS_APP} >> tmp.js @ cat ${JS_APP} >> tmp.js
@ echo "})();" >> tmp.js
@ yuicompressor --charset utf-8 --type js -o tmp.js tmp.js @ yuicompressor --charset utf-8 --type js -o tmp.js tmp.js
@ cat vendor.js tmp.js >> assets/js/app.js @ cat vendor.js tmp.js >> assets/js/app.js
@ rm -f tmp.js @ rm -f tmp.js

View File

@@ -13,24 +13,7 @@
<?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<?= $this->form->textarea('description', $values, $errors, array(), 'markdown-editor') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -14,24 +14,7 @@
<?= $this->form->number('task_limit', $values, $errors) ?> <?= $this->form->number('task_limit', $values, $errors) ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<?= $this->form->textarea('description', $values, $errors, array(), 'markdown-editor') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -16,25 +16,7 @@
<?= $this->form->number('task_limit', $values, $errors) ?> <?= $this->form->number('task_limit', $values, $errors) ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<?= $this->form->textarea('description', $values, $errors, array(), 'markdown-editor') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -6,16 +6,7 @@
<?= $this->form->hidden('task_id', $values) ?> <?= $this->form->hidden('task_id', $values) ?>
<?= $this->form->hidden('user_id', $values) ?> <?= $this->form->hidden('user_id', $values) ?>
<div class="form-tabs"> <div class="markdown-editor-small">
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
<div class="write-area">
<?= $this->form->textarea( <?= $this->form->textarea(
'comment', 'comment',
$values, $values,
@@ -26,15 +17,9 @@
'placeholder="'.t('Leave a comment').'"', 'placeholder="'.t('Leave a comment').'"',
'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"', 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"',
), ),
'comment-textarea' 'markdown-editor'
) ?> ) ?>
</div> </div>
<div class="preview-area">
<div class="markdown"></div>
</div>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -9,24 +9,15 @@
<?= $this->form->hidden('task_id', $values) ?> <?= $this->form->hidden('task_id', $values) ?>
<?= $this->form->hidden('user_id', $values) ?> <?= $this->form->hidden('user_id', $values) ?>
<div class="form-tabs"> <div class="markdown-editor-small">
<ul class="form-tabs-nav"> <?= $this->form->textarea(
<li class="form-tab form-tab-selected"> 'comment',
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a> $values,
</li> $errors,
<li class="form-tab"> array('autofocus', 'required', 'placeholder="'.t('Leave a comment').'"'),
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a> 'markdown-editor'
</li> ) ?>
</ul>
<div class="write-area">
<?= $this->form->textarea('comment', $values, $errors, array('autofocus', 'required', 'placeholder="'.t('Leave a comment').'"'), 'comment-textarea') ?>
</div> </div>
<div class="preview-area">
<div class="markdown"></div>
</div>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -3,32 +3,20 @@
<?= $this->form->hidden('task_id', $values) ?> <?= $this->form->hidden('task_id', $values) ?>
<?= $this->form->hidden('user_id', $values) ?> <?= $this->form->hidden('user_id', $values) ?>
<div class="form-tabs"> <div class="markdown-editor-small">
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
<div class="write-area">
<?= $this->form->textarea( <?= $this->form->textarea(
'comment', 'comment',
$values, $values,
$errors, $errors,
array( array(
'data-markdown-editor-disable-toolbar="true"',
'required', 'required',
'placeholder="'.t('Leave a comment').'"', 'placeholder="'.t('Leave a comment').'"',
'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"', 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"',
), ),
'comment-textarea' 'markdown-editor'
) ?> ) ?>
</div> </div>
<div class="preview-area">
<div class="markdown"></div>
</div>
</div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -12,22 +12,7 @@
<?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"'), 'form-input-large') ?> <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"'), 'form-input-large') ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<div class="form-tabs"> <?= $this->form->textarea('description', $values, $errors, array('placeholder="'.t('Leave a description').'"', 'tabindex="2"'), 'markdown-editor') ?>
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors, array('placeholder="'.t('Leave a description').'"', 'tabindex="2"')) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<?= $this->render('task/color_picker', array('colors_list' => $colors_list, 'values' => $values)) ?> <?= $this->render('task/color_picker', array('colors_list' => $colors_list, 'values' => $values)) ?>
</div> </div>

View File

@@ -11,25 +11,7 @@
<?= $this->form->csrf() ?> <?= $this->form->csrf() ?>
<?= $this->form->hidden('id', $values) ?> <?= $this->form->hidden('id', $values) ?>
<?= $this->form->hidden('name', $values) ?> <?= $this->form->hidden('name', $values) ?>
<?= $this->form->textarea('description', $values, $errors, array(), 'markdown-editor') ?>
<?= $this->form->label(t('Description'), 'description') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -10,24 +10,7 @@
<?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<?= $this->form->textarea('description', $values, $errors, array(), 'markdown-editor') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -13,25 +13,7 @@
<?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<?= $this->form->textarea('description', $values, $errors, array(), 'markdown-editor') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea('description', $values, $errors) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

View File

@@ -11,9 +11,6 @@
<?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"'), 'form-input-large') ?> <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="200"', 'tabindex="1"'), 'form-input-large') ?>
<?= $this->form->label(t('Description'), 'description') ?> <?= $this->form->label(t('Description'), 'description') ?>
<div class="form-tabs">
<div class="write-area">
<?= $this->form->textarea( <?= $this->form->textarea(
'description', 'description',
$values, $values,
@@ -22,21 +19,9 @@
'placeholder="'.t('Leave a description').'"', 'placeholder="'.t('Leave a description').'"',
'tabindex="2"', 'tabindex="2"',
'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $values['project_id'])).'"' 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $values['project_id'])).'"'
) ),
'markdown-editor'
) ?> ) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
</div>
<?= $this->render('task/color_picker', array('colors_list' => $colors_list, 'values' => $values)) ?> <?= $this->render('task/color_picker', array('colors_list' => $colors_list, 'values' => $values)) ?>

View File

@@ -7,16 +7,6 @@
<?= $this->form->csrf() ?> <?= $this->form->csrf() ?>
<?= $this->form->hidden('id', $values) ?> <?= $this->form->hidden('id', $values) ?>
<div class="form-tabs">
<ul class="form-tabs-nav">
<li class="form-tab form-tab-selected">
<i class="fa fa-pencil-square-o fa-fw"></i><a id="markdown-write" href="#"><?= t('Write') ?></a>
</li>
<li class="form-tab">
<a id="markdown-preview" href="#"><i class="fa fa-eye fa-fw"></i><?= t('Preview') ?></a>
</li>
</ul>
<div class="write-area">
<?= $this->form->textarea( <?= $this->form->textarea(
'description', 'description',
$values, $values,
@@ -26,15 +16,8 @@
'placeholder="'.t('Leave a description').'"', 'placeholder="'.t('Leave a description').'"',
'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"' 'data-mention-search-url="'.$this->url->href('UserHelper', 'mention', array('project_id' => $task['project_id'])).'"'
), ),
'task-show-description-textarea' 'markdown-editor'
) ?> ) ?>
</div>
<div class="preview-area">
<div class="markdown"></div>
</div>
</div>
<div class="form-help"><?= $this->url->doc(t('Write your text in Markdown'), 'syntax-guide') ?></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -68,15 +68,3 @@
.comment-content { .comment-content {
margin-left: 55px; margin-left: 55px;
} }
/* comment textarea */
.comment-textarea {
height: 200px;
width: 80%;
max-width: 800px;
}
#comments .comment-textarea {
height: 80px;
width: 500px;
}

View File

@@ -149,7 +149,8 @@ input.form-input-large {
.form-column { .form-column {
float: left; float: left;
margin-right: 3%; margin-right: 3%;
max-width: 47%; max-width: 50%;
min-width: 40%;
} }
.form-column ul { .form-column ul {
@@ -184,55 +185,6 @@ input.form-input-large {
margin-bottom: 0; margin-bottom: 0;
} }
/* preview tabs */
label + .form-tabs {
margin-top: 10px;
}
.form-tabs {
width: 100%;
max-width: 800px;
}
ul.form-tabs-nav {
margin-bottom: 8px;
margin-top: 0;
}
.form-tabs-nav li {
margin-left: 0;
display: inline;
}
.form-tab {
margin-right: 20px;
}
.form-tab a {
color: #ccc;
font-weight: bold;
text-decoration: none;
}
.form-tab a:focus,
.form-tab a:hover {
color: #000;
}
.form-tab-selected a {
color: #333;
}
.preview-area {
border: 1px dashed #000;
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
margin-bottom: 5px;
display: none;
overflow: auto;
}
.reset-password { .reset-password {
margin-top: 20px; margin-top: 20px;
} }

View File

@@ -1,7 +1,23 @@
/* markdown editor */
div.CodeMirror,
div.CodeMirror-scroll {
max-height: 250px;
min-height: 200px;
}
.markdown-editor-small div.CodeMirror,
.markdown-editor-small div.CodeMirror-scroll {
min-height: 100px;
max-height: 180px;
}
.form-column div.CodeMirror {
margin-bottom: 10px;
}
/* markdown content */ /* markdown content */
.markdown { .markdown {
line-height: 1.4em; line-height: 1.4em;
font-size: 1.0em;
} }
.markdown h1 { .markdown h1 {

View File

@@ -13,11 +13,10 @@
#popover-content { #popover-content {
position: absolute; position: absolute;
width: 70%; width: 70%;
margin: 0 0 0 -35%; left: 15%;
left: 50%;
top: 1%; top: 1%;
padding: 15px; padding: 15px;
background: #fff; background: #fff;
overflow: auto; overflow: auto;
max-height: 85%; max-height: 90%;
} }

View File

@@ -10,6 +10,15 @@
text-decoration: underline; text-decoration: underline;
} }
td.task-table a {
color: #000;
text-decoration: none;
}
td.task-table a:hover {
text-decoration: underline;
}
/* task inside the board */ /* task inside the board */
.task-board { .task-board {
position: relative; position: relative;

7
assets/css/vendor/simplemde.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,11 @@
function Accordion(app) { Kanboard.Accordion = function(app) {
this.app = app; this.app = app;
} };
Accordion.prototype.listen = function() { Kanboard.Accordion.prototype.listen = function() {
$(document).on("click", ".accordion-toggle", function(e) { $(document).on("click", ".accordion-toggle", function(e) {
e.preventDefault();
var section = $(this).parents(".accordion-section"); var section = $(this).parents(".accordion-section");
e.preventDefault();
if (section.hasClass("accordion-collapsed")) { if (section.hasClass("accordion-collapsed")) {
section.find(".accordion-content").show(); section.find(".accordion-content").show();

View File

@@ -1,75 +1,43 @@
function App() { Kanboard.App = function() {
this.board = new Board(this); this.controllers = {};
this.markdown = new Markdown(); };
this.search = new Search(this);
this.swimlane = new Swimlane(this);
this.dropdown = new Dropdown();
this.tooltip = new Tooltip(this);
this.popover = new Popover(this);
this.task = new Task(this);
this.project = new Project();
this.subtask = new Subtask(this);
this.column = new Column(this);
this.file = new FileUpload(this);
this.accordion = new Accordion(this);
this.keyboardShortcuts();
this.task.keyboardShortcuts();
this.chosen();
this.poll();
// Alert box fadeout Kanboard.App.prototype.get = function(controller) {
$(".alert-fade-out").delay(5000).fadeOut(800, function() { return this.controllers[controller];
$(this).remove(); };
});
Kanboard.App.prototype.execute = function() {
for (var className in Kanboard) {
if (className !== "App") {
var controller = new Kanboard[className](this);
this.controllers[className] = controller;
if (typeof controller.execute === "function") {
controller.execute();
}
if (typeof controller.listen === "function") {
controller.listen();
}
if (typeof controller.focus === "function") {
controller.focus();
}
if (typeof controller.keyboardShortcuts === "function") {
controller.keyboardShortcuts();
}
}
} }
App.prototype.listen = function() {
this.project.listen();
this.popover.listen();
this.markdown.listen();
this.tooltip.listen();
this.dropdown.listen();
this.search.listen();
this.task.listen();
this.swimlane.listen();
this.subtask.listen();
this.column.listen();
this.file.listen();
this.accordion.listen();
this.search.focus();
this.autoComplete();
this.datePicker();
this.focus(); this.focus();
this.chosen();
this.keyboardShortcuts();
this.datePicker();
this.autoComplete();
}; };
App.prototype.refresh = function() { Kanboard.App.prototype.keyboardShortcuts = function() {
$(document).off();
this.listen();
};
App.prototype.focus = function() {
// Autofocus fields (html5 autofocus works only with page onload)
$("[autofocus]").each(function(index, element) {
$(this).focus();
})
// Auto-select input fields
$(document).on('focus', '.auto-select', function() {
$(this).select();
});
// Workaround for chrome
$(document).on('mouseup', '.auto-select', function(e) {
e.preventDefault();
});
};
App.prototype.poll = function() {
window.setInterval(this.checkSession, 60000);
};
App.prototype.keyboardShortcuts = function() {
var self = this; var self = this;
// Submit form // Submit form
@@ -85,31 +53,50 @@ App.prototype.keyboardShortcuts = function() {
// Close popover and dropdown // Close popover and dropdown
Mousetrap.bindGlobal("esc", function() { Mousetrap.bindGlobal("esc", function() {
self.popover.close(); self.get("Popover").close();
self.dropdown.close(); self.get("Dropdown").close();
}); });
// Show keyboard shortcut // Show keyboard shortcut
Mousetrap.bind("?", function() { Mousetrap.bind("?", function() {
self.popover.open($("body").data("keyboard-shortcut-url")); self.get("Popover").open($("body").data("keyboard-shortcut-url"));
}); });
}; };
App.prototype.checkSession = function() { Kanboard.App.prototype.focus = function() {
if (! $(".form-login").length) { // Auto-select input fields
$.ajax({ $(document).on('focus', '.auto-select', function() {
cache: false, $(this).select();
url: $("body").data("status-url"), });
statusCode: {
401: function() { // Workaround for chrome
window.location = $("body").data("login-url"); $(document).on('mouseup', '.auto-select', function(e) {
} e.preventDefault();
}
}); });
}
}; };
App.prototype.datePicker = function() { Kanboard.App.prototype.chosen = function() {
$(".chosen-select").each(function() {
var searchThreshold = $(this).data("search-threshold");
if (searchThreshold === undefined) {
searchThreshold = 10;
}
$(this).chosen({
width: "180px",
no_results_text: $(this).data("notfound"),
disable_search_threshold: searchThreshold
});
});
$(".select-auto-redirect").change(function() {
var regex = new RegExp($(this).data('redirect-regex'), 'g');
window.location = $(this).data('redirect-url').replace(regex, $(this).val());
});
};
Kanboard.App.prototype.datePicker = function() {
// Datepicker translation // Datepicker translation
$.datepicker.setDefaults($.datepicker.regional[$("body").data("js-lang")]); $.datepicker.setDefaults($.datepicker.regional[$("body").data("js-lang")]);
@@ -131,7 +118,7 @@ App.prototype.datePicker = function() {
}); });
}; };
App.prototype.autoComplete = function() { Kanboard.App.prototype.autoComplete = function() {
$(".autocomplete").each(function() { $(".autocomplete").each(function() {
var input = $(this); var input = $(this);
var field = input.data("dst-field"); var field = input.data("dst-field");
@@ -157,36 +144,33 @@ App.prototype.autoComplete = function() {
}); });
}; };
App.prototype.chosen = function() { Kanboard.App.prototype.hasId = function(id) {
$(".chosen-select").each(function() { return !!document.getElementById(id);
var searchThreshold = $(this).data("search-threshold");
if (searchThreshold === undefined) {
searchThreshold = 10;
}
$(this).chosen({
width: "180px",
no_results_text: $(this).data("notfound"),
disable_search_threshold: searchThreshold
});
});
$(".select-auto-redirect").change(function() {
var regex = new RegExp($(this).data('redirect-regex'), 'g');
window.location = $(this).data('redirect-url').replace(regex, $(this).val());
});
}; };
App.prototype.showLoadingIcon = function() { Kanboard.App.prototype.showLoadingIcon = function() {
$("body").append('<span id="app-loading-icon">&nbsp;<i class="fa fa-spinner fa-spin"></i></span>'); $("body").append('<span id="app-loading-icon">&nbsp;<i class="fa fa-spinner fa-spin"></i></span>');
}; };
App.prototype.hideLoadingIcon = function() { Kanboard.App.prototype.hideLoadingIcon = function() {
$("#app-loading-icon").remove(); $("#app-loading-icon").remove();
}; };
App.prototype.isVisible = function() { Kanboard.App.prototype.formatDuration = function(d) {
if (d >= 86400) {
return Math.round(d/86400) + "d";
}
else if (d >= 3600) {
return Math.round(d/3600) + "h";
}
else if (d >= 60) {
return Math.round(d/60) + "m";
}
return d + "s";
};
Kanboard.App.prototype.isVisible = function() {
var property = ""; var property = "";
if (typeof document.hidden !== "undefined") { if (typeof document.hidden !== "undefined") {
@@ -205,17 +189,3 @@ App.prototype.isVisible = function() {
return true; return true;
}; };
App.prototype.formatDuration = function(d) {
if (d >= 86400) {
return Math.round(d/86400) + "d";
}
else if (d >= 3600) {
return Math.round(d/3600) + "h";
}
else if (d >= 60) {
return Math.round(d/60) + "m";
}
return d + "s";
};

View File

@@ -1,10 +1,17 @@
function AvgTimeColumnChart(app) { Kanboard.AvgTimeColumnChart = function(app) {
this.app = app; this.app = app;
} };
AvgTimeColumnChart.prototype.execute = function() { Kanboard.AvgTimeColumnChart.prototype.execute = function() {
var metrics = $("#chart").data("metrics"); if (this.app.hasId("analytic-avg-time-column")) {
var plots = [$("#chart").data("label")]; this.show();
}
};
Kanboard.AvgTimeColumnChart.prototype.show = function() {
var chart = $("#chart");
var metrics = chart.data("metrics");
var plots = [chart.data("label")];
var categories = []; var categories = [];
for (var column_id in metrics) { for (var column_id in metrics) {

View File

@@ -1,336 +0,0 @@
function Board(app) {
this.app = app;
this.checkInterval = null;
this.savingInProgress = false;
}
Board.prototype.execute = function() {
this.app.swimlane.refresh();
this.restoreColumnViewMode();
this.compactView();
this.poll();
this.keyboardShortcuts();
this.listen();
this.dragAndDrop();
$(window).on("load", this.columnScrolling);
$(window).resize(this.columnScrolling);
};
Board.prototype.poll = function() {
var interval = parseInt($("#board").attr("data-check-interval"));
if (interval > 0) {
this.checkInterval = window.setInterval(this.check.bind(this), interval * 1000);
}
};
Board.prototype.reloadFilters = function(search) {
this.app.showLoadingIcon();
$.ajax({
cache: false,
url: $("#board").data("reload-url"),
contentType: "application/json",
type: "POST",
processData: false,
data: JSON.stringify({
search: search
}),
success: this.refresh.bind(this),
error: this.app.hideLoadingIcon.bind(this)
});
};
Board.prototype.check = function() {
if (this.app.isVisible() && ! this.savingInProgress) {
var self = this;
this.app.showLoadingIcon();
$.ajax({
cache: false,
url: $("#board").data("check-url"),
statusCode: {
200: function(data) { self.refresh(data); },
304: function () { self.app.hideLoadingIcon(); }
}
});
}
};
Board.prototype.save = function(taskId, columnId, position, swimlaneId) {
var self = this;
this.app.showLoadingIcon();
this.savingInProgress = true;
$.ajax({
cache: false,
url: $("#board").data("save-url"),
contentType: "application/json",
type: "POST",
processData: false,
data: JSON.stringify({
"task_id": taskId,
"column_id": columnId,
"swimlane_id": swimlaneId,
"position": position
}),
success: function(data) {
self.refresh(data);
this.savingInProgress = false;
},
error: function() {
self.app.hideLoadingIcon();
this.savingInProgress = false;
}
});
};
Board.prototype.refresh = function(data) {
$("#board-container").replaceWith(data);
this.app.refresh();
this.app.swimlane.refresh();
this.app.hideLoadingIcon();
this.listen();
this.dragAndDrop();
this.compactView();
this.restoreColumnViewMode();
this.columnScrolling();
};
Board.prototype.dragAndDrop = function() {
var self = this;
var params = {
forcePlaceholderSize: true,
tolerance: "pointer",
connectWith: ".board-task-list",
placeholder: "draggable-placeholder",
items: ".draggable-item",
stop: function(event, ui) {
var task = ui.item;
var taskId = task.attr('data-task-id');
var taskPosition = task.attr('data-position');
var taskColumnId = task.attr('data-column-id');
var taskSwimlaneId = task.attr('data-swimlane-id');
var newColumnId = task.parent().attr("data-column-id");
var newSwimlaneId = task.parent().attr('data-swimlane-id');
var newPosition = task.index() + 1;
task.removeClass("draggable-item-selected");
if (newColumnId != taskColumnId || newSwimlaneId != taskSwimlaneId || newPosition != taskPosition) {
self.changeTaskState(taskId);
self.save(taskId, newColumnId, newPosition, newSwimlaneId);
}
},
start: function(event, ui) {
ui.item.addClass("draggable-item-selected");
ui.placeholder.height(ui.item.height());
}
};
if ($.support.touch) {
$(".task-board-sort-handle").css("display", "inline");
params["handle"] = ".task-board-sort-handle";
}
$(".board-task-list").sortable(params);
};
Board.prototype.changeTaskState = function(taskId) {
var task = $("div[data-task-id=" + taskId + "]");
task.addClass('task-board-saving-state');
task.find('.task-board-saving-icon').show();
};
Board.prototype.listen = function() {
var self = this;
$(document).on("click", ".task-board-change-assignee", function(e) {
e.preventDefault();
self.app.popover.open($(this).data('url'));
});
$(document).on("click", ".task-board", function(e) {
if (e.target.tagName != "A" && e.target.tagName != "IMG") {
window.location = $(this).data("task-url");
}
});
$(document).on('click', ".filter-toggle-scrolling", function(e) {
e.preventDefault();
self.toggleCompactView();
});
$(document).on('click', ".filter-toggle-height", function(e) {
e.preventDefault();
self.toggleColumnScrolling();
});
$(document).on("click", ".board-toggle-column-view", function() {
self.toggleColumnViewMode($(this).data("column-id"));
});
};
Board.prototype.toggleColumnScrolling = function() {
var scrolling = localStorage.getItem("column_scroll");
if (scrolling == undefined) {
scrolling = 1;
}
localStorage.setItem("column_scroll", scrolling == 0 ? 1 : 0);
this.columnScrolling();
};
Board.prototype.columnScrolling = function() {
if (localStorage.getItem("column_scroll") == 0) {
var height = 80;
$(".filter-max-height").show();
$(".filter-min-height").hide();
$(".board-rotation-wrapper").css("min-height", '');
$(".board-task-list").each(function() {
var columnHeight = $(this).height();
if (columnHeight > height) {
height = columnHeight;
}
});
$(".board-task-list").css("min-height", height);
$(".board-task-list").css("height", '');
}
else {
$(".filter-max-height").hide();
$(".filter-min-height").show();
if ($(".board-swimlane").length > 1) {
$(".board-task-list").each(function() {
if ($(this).height() > 500) {
$(this).css("height", 500);
}
else {
$(this).css("min-height", 320); // Height of the dropdown menu
$(".board-rotation-wrapper").css("min-height", 320);
}
});
}
else {
var height = $(window).height() - 170;
$(".board-task-list").css("height", height);
$(".board-rotation-wrapper").css("min-height", height);
}
}
};
Board.prototype.toggleCompactView = function() {
var scrolling = localStorage.getItem("horizontal_scroll") || 1;
localStorage.setItem("horizontal_scroll", scrolling == 0 ? 1 : 0);
this.compactView();
};
Board.prototype.compactView = function() {
if (localStorage.getItem("horizontal_scroll") == 0) {
$(".filter-wide").show();
$(".filter-compact").hide();
$("#board-container").addClass("board-container-compact");
$("#board th:not(.board-column-header-collapsed)").addClass("board-column-compact");
}
else {
$(".filter-wide").hide();
$(".filter-compact").show();
$("#board-container").removeClass("board-container-compact");
$("#board th").removeClass("board-column-compact");
}
};
Board.prototype.toggleCollapsedMode = function() {
var self = this;
this.app.showLoadingIcon();
$.ajax({
cache: false,
url: $('.filter-display-mode:not([style="display: none;"]) a').attr('href'),
success: function(data) {
$('.filter-display-mode').toggle();
self.refresh(data);
}
});
};
Board.prototype.restoreColumnViewMode = function() {
var self = this;
$(".board-column-header").each(function() {
var columnId = $(this).data('column-id');
if (localStorage.getItem("hidden_column_" + columnId)) {
self.hideColumn(columnId);
}
});
};
Board.prototype.toggleColumnViewMode = function(columnId) {
if (localStorage.getItem("hidden_column_" + columnId)) {
this.showColumn(columnId);
}
else {
this.hideColumn(columnId);
}
};
Board.prototype.hideColumn = function(columnId) {
$(".board-column-" + columnId + " .board-column-expanded").hide();
$(".board-column-" + columnId + " .board-column-collapsed").show();
$(".board-column-header-" + columnId + " .board-column-expanded").hide();
$(".board-column-header-" + columnId + " .board-column-collapsed").show();
$(".board-column-header-" + columnId).each(function() {
$(this).removeClass("board-column-compact");
$(this).addClass("board-column-header-collapsed");
});
$(".board-column-" + columnId ).each(function() {
$(this).addClass("board-column-task-collapsed");
});
$(".board-column-" + columnId + " .board-rotation").each(function() {
$(this).css("width", $(".board-column-" + columnId + "").height());
});
localStorage.setItem("hidden_column_" + columnId, 1);
};
Board.prototype.showColumn = function(columnId) {
$(".board-column-" + columnId + " .board-column-expanded").show();
$(".board-column-" + columnId + " .board-column-collapsed").hide();
$(".board-column-header-" + columnId + " .board-column-expanded").show();
$(".board-column-header-" + columnId + " .board-column-collapsed").hide();
$(".board-column-header-" + columnId).removeClass("board-column-header-collapsed");
$(".board-column-" + columnId).removeClass("board-column-task-collapsed");
if (localStorage.getItem("horizontal_scroll") == 0) {
$(".board-column-header-" + columnId).addClass("board-column-compact");
}
localStorage.removeItem("hidden_column_" + columnId);
};
Board.prototype.keyboardShortcuts = function() {
var self = this;
Mousetrap.bind("c", function() { self.toggleCompactView(); });
Mousetrap.bind("s", function() { self.toggleCollapsedMode(); });
Mousetrap.bind("n", function() {
self.app.popover.open($("#board").data("task-creation-url"));
});
};

View File

@@ -0,0 +1,25 @@
Kanboard.BoardCollapsedMode = function(app) {
this.app = app;
};
Kanboard.BoardCollapsedMode.prototype.keyboardShortcuts = function() {
var self = this;
Mousetrap.bind("s", function() {
self.toggle();
});
};
Kanboard.BoardCollapsedMode.prototype.toggle = function() {
var self = this;
this.app.showLoadingIcon();
$.ajax({
cache: false,
url: $('.filter-display-mode:not([style="display: none;"]) a').attr('href'),
success: function(data) {
$('.filter-display-mode').toggle();
self.app.get("BoardDragAndDrop").refresh(data);
}
});
};

View File

@@ -0,0 +1,85 @@
Kanboard.BoardColumnScrolling = function(app) {
this.app = app;
};
Kanboard.BoardColumnScrolling.prototype.execute = function() {
if (this.app.hasId("board")) {
this.render();
$(window).on("load", this.render);
$(window).resize(this.render);
}
};
Kanboard.BoardColumnScrolling.prototype.listen = function() {
var self = this;
$(document).on('click', ".filter-toggle-height", function(e) {
e.preventDefault();
self.toggle();
});
};
Kanboard.BoardColumnScrolling.prototype.onBoardRendered = function() {
this.render();
};
Kanboard.BoardColumnScrolling.prototype.toggle = function() {
var scrolling = localStorage.getItem("column_scroll");
if (scrolling == undefined) {
scrolling = 1;
}
localStorage.setItem("column_scroll", scrolling == 0 ? 1 : 0);
this.render();
};
Kanboard.BoardColumnScrolling.prototype.render = function() {
var taskList = $(".board-task-list");
var rotationWrapper = $(".board-rotation-wrapper");
var filterMax = $(".filter-max-height");
var filterMin = $(".filter-min-height");
if (localStorage.getItem("column_scroll") == 0) {
var height = 80;
filterMax.show();
filterMin.hide();
rotationWrapper.css("min-height", '');
taskList.each(function() {
var columnHeight = $(this).height();
if (columnHeight > height) {
height = columnHeight;
}
});
taskList.css("min-height", height);
taskList.css("height", '');
}
else {
filterMax.hide();
filterMin.show();
if ($(".board-swimlane").length > 1) {
taskList.each(function() {
if ($(this).height() > 500) {
$(this).css("height", 500);
}
else {
$(this).css("min-height", 320); // Height of the dropdown menu
rotationWrapper.css("min-height", 320);
}
});
}
else {
var height = $(window).height() - 170;
taskList.css("height", height);
rotationWrapper.css("min-height", height);
}
}
};

View File

@@ -0,0 +1,79 @@
Kanboard.BoardColumnView = function(app) {
this.app = app;
};
Kanboard.BoardColumnView.prototype.execute = function() {
if (this.app.hasId("board")) {
this.render();
}
};
Kanboard.BoardColumnView.prototype.listen = function() {
var self = this;
$(document).on("click", ".board-toggle-column-view", function() {
self.toggle($(this).data("column-id"));
});
};
Kanboard.BoardColumnView.prototype.onBoardRendered = function() {
this.render();
};
Kanboard.BoardColumnView.prototype.render = function() {
var self = this;
$(".board-column-header").each(function() {
var columnId = $(this).data('column-id');
if (localStorage.getItem("hidden_column_" + columnId)) {
self.hideColumn(columnId);
}
});
};
Kanboard.BoardColumnView.prototype.toggle = function(columnId) {
if (localStorage.getItem("hidden_column_" + columnId)) {
this.showColumn(columnId);
}
else {
this.hideColumn(columnId);
}
};
Kanboard.BoardColumnView.prototype.hideColumn = function(columnId) {
$(".board-column-" + columnId + " .board-column-expanded").hide();
$(".board-column-" + columnId + " .board-column-collapsed").show();
$(".board-column-header-" + columnId + " .board-column-expanded").hide();
$(".board-column-header-" + columnId + " .board-column-collapsed").show();
$(".board-column-header-" + columnId).each(function() {
$(this).removeClass("board-column-compact");
$(this).addClass("board-column-header-collapsed");
});
$(".board-column-" + columnId).each(function() {
$(this).addClass("board-column-task-collapsed");
});
$(".board-column-" + columnId + " .board-rotation").each(function() {
$(this).css("width", $(".board-column-" + columnId + "").height());
});
localStorage.setItem("hidden_column_" + columnId, 1);
};
Kanboard.BoardColumnView.prototype.showColumn = function(columnId) {
$(".board-column-" + columnId + " .board-column-expanded").show();
$(".board-column-" + columnId + " .board-column-collapsed").hide();
$(".board-column-header-" + columnId + " .board-column-expanded").show();
$(".board-column-header-" + columnId + " .board-column-collapsed").hide();
$(".board-column-header-" + columnId).removeClass("board-column-header-collapsed");
$(".board-column-" + columnId).removeClass("board-column-task-collapsed");
if (localStorage.getItem("horizontal_scroll") == 0) {
$(".board-column-header-" + columnId).addClass("board-column-compact");
}
localStorage.removeItem("hidden_column_" + columnId);
};

View File

@@ -0,0 +1,103 @@
Kanboard.BoardDragAndDrop = function(app) {
this.app = app;
this.savingInProgress = false;
};
Kanboard.BoardDragAndDrop.prototype.execute = function() {
if (this.app.hasId("board")) {
this.dragAndDrop();
this.executeListeners();
}
};
Kanboard.BoardDragAndDrop.prototype.dragAndDrop = function() {
var self = this;
var params = {
forcePlaceholderSize: true,
tolerance: "pointer",
connectWith: ".board-task-list",
placeholder: "draggable-placeholder",
items: ".draggable-item",
stop: function(event, ui) {
var task = ui.item;
var taskId = task.attr('data-task-id');
var taskPosition = task.attr('data-position');
var taskColumnId = task.attr('data-column-id');
var taskSwimlaneId = task.attr('data-swimlane-id');
var newColumnId = task.parent().attr("data-column-id");
var newSwimlaneId = task.parent().attr('data-swimlane-id');
var newPosition = task.index() + 1;
task.removeClass("draggable-item-selected");
if (newColumnId != taskColumnId || newSwimlaneId != taskSwimlaneId || newPosition != taskPosition) {
self.changeTaskState(taskId);
self.save(taskId, newColumnId, newPosition, newSwimlaneId);
}
},
start: function(event, ui) {
ui.item.addClass("draggable-item-selected");
ui.placeholder.height(ui.item.height());
}
};
if ($.support.touch) {
$(".task-board-sort-handle").css("display", "inline");
params["handle"] = ".task-board-sort-handle";
}
$(".board-task-list").sortable(params);
};
Kanboard.BoardDragAndDrop.prototype.changeTaskState = function(taskId) {
var task = $("div[data-task-id=" + taskId + "]");
task.addClass('task-board-saving-state');
task.find('.task-board-saving-icon').show();
};
Kanboard.BoardDragAndDrop.prototype.save = function(taskId, columnId, position, swimlaneId) {
var self = this;
self.app.showLoadingIcon();
self.savingInProgress = true;
$.ajax({
cache: false,
url: $("#board").data("save-url"),
contentType: "application/json",
type: "POST",
processData: false,
data: JSON.stringify({
"task_id": taskId,
"column_id": columnId,
"swimlane_id": swimlaneId,
"position": position
}),
success: function(data) {
self.refresh(data);
self.savingInProgress = false;
},
error: function() {
self.app.hideLoadingIcon();
self.savingInProgress = false;
}
});
};
Kanboard.BoardDragAndDrop.prototype.refresh = function(data) {
$("#board-container").replaceWith(data);
this.app.hideLoadingIcon();
this.dragAndDrop();
this.executeListeners();
};
Kanboard.BoardDragAndDrop.prototype.executeListeners = function() {
for (var className in this.app.controllers) {
var controller = this.app.get(className);
if (typeof controller.onBoardRendered === "function") {
controller.onBoardRendered();
}
}
};

View File

@@ -0,0 +1,53 @@
Kanboard.BoardHorizontalScrolling = function(app) {
this.app = app;
};
Kanboard.BoardHorizontalScrolling.prototype.execute = function() {
if (this.app.hasId("board")) {
this.render();
}
};
Kanboard.BoardHorizontalScrolling.prototype.listen = function() {
var self = this;
$(document).on('click', ".filter-toggle-scrolling", function(e) {
e.preventDefault();
self.toggle();
});
};
Kanboard.BoardHorizontalScrolling.prototype.keyboardShortcuts = function() {
var self = this;
Mousetrap.bind("c", function() {
self.toggle();
});
};
Kanboard.BoardHorizontalScrolling.prototype.onBoardRendered = function() {
this.render();
};
Kanboard.BoardHorizontalScrolling.prototype.toggle = function() {
var scrolling = localStorage.getItem("horizontal_scroll") || 1;
localStorage.setItem("horizontal_scroll", scrolling == 0 ? 1 : 0);
this.render();
};
Kanboard.BoardHorizontalScrolling.prototype.render = function() {
if (localStorage.getItem("horizontal_scroll") == 0) {
$(".filter-wide").show();
$(".filter-compact").hide();
$("#board-container").addClass("board-container-compact");
$("#board th:not(.board-column-header-collapsed)").addClass("board-column-compact");
}
else {
$(".filter-wide").hide();
$(".filter-compact").show();
$("#board-container").removeClass("board-container-compact");
$("#board th").removeClass("board-column-compact");
}
};

View File

@@ -0,0 +1,33 @@
Kanboard.BoardPolling = function(app) {
this.app = app;
};
Kanboard.BoardPolling.prototype.execute = function() {
if (this.app.hasId("board")) {
var interval = parseInt($("#board").attr("data-check-interval"));
if (interval > 0) {
window.setInterval(this.check.bind(this), interval * 1000);
}
}
};
Kanboard.BoardPolling.prototype.check = function() {
if (this.app.isVisible() && !this.app.get("BoardDragAndDrop").savingInProgress) {
var self = this;
this.app.showLoadingIcon();
$.ajax({
cache: false,
url: $("#board").data("check-url"),
statusCode: {
200: function(data) {
self.app.get("BoardDragAndDrop").refresh(data);
},
304: function () {
self.app.hideLoadingIcon();
}
}
});
}
};

View File

@@ -0,0 +1,27 @@
Kanboard.BoardTask = function(app) {
this.app = app;
};
Kanboard.BoardTask.prototype.listen = function() {
var self = this;
$(document).on("click", ".task-board-change-assignee", function(e) {
e.preventDefault();
e.stopPropagation();
self.app.get("Popover").open($(this).data('url'));
});
$(document).on("click", ".task-board", function(e) {
if (e.target.tagName != "A" && e.target.tagName != "IMG") {
window.location = $(this).data("task-url");
}
});
};
Kanboard.BoardTask.prototype.keyboardShortcuts = function() {
var self = this;
Mousetrap.bind("n", function() {
self.app.get("Popover").open($("#board").data("task-creation-url"));
});
};

View File

@@ -1,12 +1,20 @@
function BurndownChart() { Kanboard.BurndownChart = function(app) {
} this.app = app;
};
BurndownChart.prototype.execute = function() { Kanboard.BurndownChart.prototype.execute = function() {
var metrics = $("#chart").data("metrics"); if (this.app.hasId("analytic-burndown")) {
var columns = [[$("#chart").data("label-total")]]; this.show();
}
};
Kanboard.BurndownChart.prototype.show = function() {
var chart = $("#chart");
var metrics = chart.data("metrics");
var columns = [[chart.data("label-total")]];
var categories = []; var categories = [];
var inputFormat = d3.time.format("%Y-%m-%d"); var inputFormat = d3.time.format("%Y-%m-%d");
var outputFormat = d3.time.format($("#chart").data("date-format")); var outputFormat = d3.time.format(chart.data("date-format"));
for (var i = 0; i < metrics.length; i++) { for (var i = 0; i < metrics.length; i++) {

View File

@@ -1,10 +1,16 @@
function Calendar() { Kanboard.Calendar = function(app) {
this.app = app;
};
} Kanboard.Calendar.prototype.execute = function() {
Calendar.prototype.execute = function() {
var calendar = $('#calendar'); var calendar = $('#calendar');
if (calendar.length == 1) {
this.show(calendar);
}
};
Kanboard.Calendar.prototype.show = function(calendar) {
calendar.fullCalendar({ calendar.fullCalendar({
lang: $("body").data("js-lang"), lang: $("body").data("js-lang"),
editable: true, editable: true,

View File

@@ -1,12 +1,12 @@
function Column(app) { Kanboard.Column = function(app) {
this.app = app; this.app = app;
} };
Column.prototype.listen = function() { Kanboard.Column.prototype.listen = function() {
this.dragAndDrop(); this.dragAndDrop();
}; };
Column.prototype.dragAndDrop = function() { Kanboard.Column.prototype.dragAndDrop = function() {
var self = this; var self = this;
$(".draggable-row-handle").mouseenter(function() { $(".draggable-row-handle").mouseenter(function() {
@@ -36,7 +36,7 @@ Column.prototype.dragAndDrop = function() {
}).disableSelection(); }).disableSelection();
}; };
Column.prototype.savePosition = function(columnId, position) { Kanboard.Column.prototype.savePosition = function(columnId, position) {
var url = $(".columns-table").data("save-position-url"); var url = $(".columns-table").data("save-position-url");
var self = this; var self = this;

View File

@@ -1,13 +1,20 @@
function CompareHoursColumnChart(app) { Kanboard.CompareHoursColumnChart = function(app) {
this.app = app; this.app = app;
} };
CompareHoursColumnChart.prototype.execute = function() { Kanboard.CompareHoursColumnChart.prototype.execute = function() {
var metrics = $("#chart").data("metrics"); if (this.app.hasId("analytic-compare-hours")) {
var labelOpen = $("#chart").data("label-open"); this.show();
var labelClosed = $("#chart").data("label-closed"); }
var spent = [$("#chart").data("label-spent")]; };
var estimated = [$("#chart").data("label-estimated")];
Kanboard.CompareHoursColumnChart.prototype.show = function() {
var chart = $("#chart");
var metrics = chart.data("metrics");
var labelOpen = chart.data("label-open");
var labelClosed = chart.data("label-closed");
var spent = [chart.data("label-spent")];
var estimated = [chart.data("label-estimated")];
var categories = []; var categories = [];
for (var status in metrics) { for (var status in metrics) {

View File

@@ -1,14 +1,21 @@
function CumulativeFlowDiagram() { Kanboard.CumulativeFlowDiagram = function(app) {
this.app = app;
};
Kanboard.CumulativeFlowDiagram.prototype.execute = function() {
if (this.app.hasId("analytic-cfd")) {
this.show();
} }
};
CumulativeFlowDiagram.prototype.execute = function() { Kanboard.CumulativeFlowDiagram.prototype.show = function() {
var chart = $("#chart");
var metrics = $("#chart").data("metrics"); var metrics = chart.data("metrics");
var columns = []; var columns = [];
var groups = []; var groups = [];
var categories = []; var categories = [];
var inputFormat = d3.time.format("%Y-%m-%d"); var inputFormat = d3.time.format("%Y-%m-%d");
var outputFormat = d3.time.format($("#chart").data("date-format")); var outputFormat = d3.time.format(chart.data("date-format"));
for (var i = 0; i < metrics.length; i++) { for (var i = 0; i < metrics.length; i++) {

View File

@@ -1,7 +1,8 @@
function Dropdown() { Kanboard.Dropdown = function(app) {
} this.app = app;
};
Dropdown.prototype.listen = function() { Kanboard.Dropdown.prototype.listen = function() {
var self = this; var self = this;
$(document).on('click', function() { $(document).on('click', function() {
@@ -46,23 +47,12 @@ Dropdown.prototype.listen = function() {
$(this).find('a:visible')[0].click(); // Calling native click() not the jQuery one $(this).find('a:visible')[0].click(); // Calling native click() not the jQuery one
} }
}); });
// User mention autocomplete
$('textarea[data-mention-search-url]').textcomplete([{
match: /(^|\s)@(\w*)$/,
search: function (term, callback) {
var url = $('textarea[data-mention-search-url]').data('mention-search-url');
$.getJSON(url, { q: term })
.done(function (resp) { callback(resp); })
.fail(function () { callback([]); });
},
replace: function (value) {
return '$1@' + value + ' ';
},
cache: true
}], {className: "textarea-dropdown"});
}; };
Dropdown.prototype.close = function() { Kanboard.Dropdown.prototype.close = function() {
$("#dropdown").remove(); $("#dropdown").remove();
}; };
Kanboard.Dropdown.prototype.onPopoverOpened = function() {
this.close();
};

View File

@@ -1,10 +1,10 @@
function FileUpload(app) { Kanboard.FileUpload = function(app) {
this.app = app; this.app = app;
this.files = []; this.files = [];
this.currentFile = 0; this.currentFile = 0;
} };
FileUpload.prototype.listen = function() { Kanboard.FileUpload.prototype.onPopoverOpened = function() {
var dropzone = document.getElementById("file-dropzone"); var dropzone = document.getElementById("file-dropzone");
var self = this; var self = this;
@@ -12,7 +12,7 @@ FileUpload.prototype.listen = function() {
dropzone.ondragover = dropzone.ondragenter = function(e) { dropzone.ondragover = dropzone.ondragenter = function(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
} };
dropzone.ondrop = function(e) { dropzone.ondrop = function(e) {
e.stopPropagation(); e.stopPropagation();
@@ -20,7 +20,7 @@ FileUpload.prototype.listen = function() {
self.files = e.dataTransfer.files; self.files = e.dataTransfer.files;
self.show(); self.show();
$("#file-error-max-size").hide(); $("#file-error-max-size").hide();
} };
$(document).on("click", "#file-browser", function(e) { $(document).on("click", "#file-browser", function(e) {
e.preventDefault(); e.preventDefault();
@@ -41,7 +41,7 @@ FileUpload.prototype.listen = function() {
} }
}; };
FileUpload.prototype.show = function() { Kanboard.FileUpload.prototype.show = function() {
$("#file-list").remove(); $("#file-list").remove();
if (this.files.length > 0) { if (this.files.length > 0) {
@@ -69,7 +69,7 @@ FileUpload.prototype.show = function() {
} }
}; };
FileUpload.prototype.checkFiles = function() { Kanboard.FileUpload.prototype.checkFiles = function() {
var max = parseInt($("#file-dropzone").data("max-size")); var max = parseInt($("#file-dropzone").data("max-size"));
for (var i = 0; i < this.files.length; i++) { for (var i = 0; i < this.files.length; i++) {
@@ -84,13 +84,13 @@ FileUpload.prototype.checkFiles = function() {
this.uploadFiles(); this.uploadFiles();
}; };
FileUpload.prototype.uploadFiles = function() { Kanboard.FileUpload.prototype.uploadFiles = function() {
if (this.files.length > 0) { if (this.files.length > 0) {
this.uploadFile(this.files[this.currentFile]); this.uploadFile(this.files[this.currentFile]);
} }
}; };
FileUpload.prototype.uploadFile = function(file) { Kanboard.FileUpload.prototype.uploadFile = function(file) {
var dropzone = document.getElementById("file-dropzone"); var dropzone = document.getElementById("file-dropzone");
var url = dropzone.dataset.url; var url = dropzone.dataset.url;
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
@@ -104,21 +104,22 @@ FileUpload.prototype.uploadFile = function(file) {
xhr.send(fd); xhr.send(fd);
}; };
FileUpload.prototype.updateProgress = function(e) { Kanboard.FileUpload.prototype.updateProgress = function(e) {
if (e.lengthComputable) { if (e.lengthComputable) {
$("#file-progress-" + this.currentFile).val(e.loaded / e.total); $("#file-progress-" + this.currentFile).val(e.loaded / e.total);
$("#file-percentage-" + this.currentFile).text('(' + Math.floor((e.loaded / e.total) * 100) + '%)'); $("#file-percentage-" + this.currentFile).text('(' + Math.floor((e.loaded / e.total) * 100) + '%)');
} }
}; };
FileUpload.prototype.transferComplete = function() { Kanboard.FileUpload.prototype.transferComplete = function() {
this.currentFile++; this.currentFile++;
if (this.currentFile < this.files.length) { if (this.currentFile < this.files.length) {
this.uploadFile(this.files[this.currentFile]); this.uploadFile(this.files[this.currentFile]);
} else { } else {
$("#file-upload-button").prop("disabled", true); var uploadButton = $("#file-upload-button");
$("#file-upload-button").parent().hide(); uploadButton.prop("disabled", true);
uploadButton.parent().hide();
$("#file-done").show(); $("#file-done").show();
} }
}; };

View File

@@ -1,5 +1,5 @@
// Based on jQuery.ganttView v.0.8.8 Copyright (c) 2010 JC Grubbs - jc.grubbs@devmynd.com - MIT License // Based on jQuery.ganttView v.0.8.8 Copyright (c) 2010 JC Grubbs - jc.grubbs@devmynd.com - MIT License
function Gantt(app) { Kanboard.Gantt = function(app) {
this.app = app; this.app = app;
this.data = []; this.data = [];
@@ -13,10 +13,16 @@ function Gantt(app) {
slideWidth: 1000, slideWidth: 1000,
vHeaderWidth: 200 vHeaderWidth: 200
}; };
};
Kanboard.Gantt.prototype.execute = function() {
if (this.app.hasId("gantt-chart")) {
this.show();
} }
};
// Save record after a resize or move // Save record after a resize or move
Gantt.prototype.saveRecord = function(record) { Kanboard.Gantt.prototype.saveRecord = function(record) {
this.app.showLoadingIcon(); this.app.showLoadingIcon();
$.ajax({ $.ajax({
@@ -31,7 +37,7 @@ Gantt.prototype.saveRecord = function(record) {
}; };
// Build the Gantt chart // Build the Gantt chart
Gantt.prototype.execute = function() { Kanboard.Gantt.prototype.show = function() {
this.data = this.prepareData($(this.options.container).data('records')); this.data = this.prepareData($(this.options.container).data('records'));
var minDays = Math.floor((this.options.slideWidth / this.options.cellWidth) + 5); var minDays = Math.floor((this.options.slideWidth / this.options.cellWidth) + 5);
@@ -60,7 +66,7 @@ Gantt.prototype.execute = function() {
}; };
// Render record list on the left // Render record list on the left
Gantt.prototype.renderVerticalHeader = function() { Kanboard.Gantt.prototype.renderVerticalHeader = function() {
var headerDiv = jQuery("<div>", { "class": "ganttview-vtheader" }); var headerDiv = jQuery("<div>", { "class": "ganttview-vtheader" });
var itemDiv = jQuery("<div>", { "class": "ganttview-vtheader-item" }); var itemDiv = jQuery("<div>", { "class": "ganttview-vtheader-item" });
var seriesDiv = jQuery("<div>", { "class": "ganttview-vtheader-series" }); var seriesDiv = jQuery("<div>", { "class": "ganttview-vtheader-series" });
@@ -92,7 +98,7 @@ Gantt.prototype.renderVerticalHeader = function() {
}; };
// Render right part of the chart (top header + grid + bars) // Render right part of the chart (top header + grid + bars)
Gantt.prototype.renderSlider = function(startDate, endDate) { Kanboard.Gantt.prototype.renderSlider = function(startDate, endDate) {
var slideDiv = jQuery("<div>", {"class": "ganttview-slide-container"}); var slideDiv = jQuery("<div>", {"class": "ganttview-slide-container"});
var dates = this.getDates(startDate, endDate); var dates = this.getDates(startDate, endDate);
@@ -105,7 +111,7 @@ Gantt.prototype.renderSlider = function(startDate, endDate) {
}; };
// Render top header (days) // Render top header (days)
Gantt.prototype.renderHorizontalHeader = function(dates) { Kanboard.Gantt.prototype.renderHorizontalHeader = function(dates) {
var headerDiv = jQuery("<div>", { "class": "ganttview-hzheader" }); var headerDiv = jQuery("<div>", { "class": "ganttview-hzheader" });
var monthsDiv = jQuery("<div>", { "class": "ganttview-hzheader-months" }); var monthsDiv = jQuery("<div>", { "class": "ganttview-hzheader-months" });
var daysDiv = jQuery("<div>", { "class": "ganttview-hzheader-days" }); var daysDiv = jQuery("<div>", { "class": "ganttview-hzheader-days" });
@@ -135,7 +141,7 @@ Gantt.prototype.renderHorizontalHeader = function(dates) {
}; };
// Render grid // Render grid
Gantt.prototype.renderGrid = function(dates) { Kanboard.Gantt.prototype.renderGrid = function(dates) {
var gridDiv = jQuery("<div>", { "class": "ganttview-grid" }); var gridDiv = jQuery("<div>", { "class": "ganttview-grid" });
var rowDiv = jQuery("<div>", { "class": "ganttview-grid-row" }); var rowDiv = jQuery("<div>", { "class": "ganttview-grid-row" });
@@ -162,7 +168,7 @@ Gantt.prototype.renderGrid = function(dates) {
}; };
// Render bar containers // Render bar containers
Gantt.prototype.addBlockContainers = function() { Kanboard.Gantt.prototype.addBlockContainers = function() {
var blocksDiv = jQuery("<div>", { "class": "ganttview-blocks" }); var blocksDiv = jQuery("<div>", { "class": "ganttview-blocks" });
for (var i = 0; i < this.data.length; i++) { for (var i = 0; i < this.data.length; i++) {
@@ -173,7 +179,7 @@ Gantt.prototype.addBlockContainers = function() {
}; };
// Render bars // Render bars
Gantt.prototype.addBlocks = function(slider, start) { Kanboard.Gantt.prototype.addBlocks = function(slider, start) {
var rows = jQuery("div.ganttview-blocks div.ganttview-block-container", slider); var rows = jQuery("div.ganttview-blocks div.ganttview-block-container", slider);
var rowIdx = 0; var rowIdx = 0;
@@ -219,7 +225,7 @@ Gantt.prototype.addBlocks = function(slider, start) {
}; };
// Get tooltip for vertical header // Get tooltip for vertical header
Gantt.prototype.getVerticalHeaderTooltip = function(record) { Kanboard.Gantt.prototype.getVerticalHeaderTooltip = function(record) {
var tooltip = ""; var tooltip = "";
if (record.type == "task") { if (record.type == "task") {
@@ -246,7 +252,7 @@ Gantt.prototype.getVerticalHeaderTooltip = function(record) {
}; };
// Get tooltip for bars // Get tooltip for bars
Gantt.prototype.getBarTooltip = function(record) { Kanboard.Gantt.prototype.getBarTooltip = function(record) {
var tooltip = ""; var tooltip = "";
if (record.not_defined) { if (record.not_defined) {
@@ -266,7 +272,7 @@ Gantt.prototype.getBarTooltip = function(record) {
}; };
// Set bar color // Set bar color
Gantt.prototype.setBarColor = function(block, record) { Kanboard.Gantt.prototype.setBarColor = function(block, record) {
if (record.not_defined) { if (record.not_defined) {
block.addClass("ganttview-block-not-defined"); block.addClass("ganttview-block-not-defined");
} }
@@ -277,7 +283,7 @@ Gantt.prototype.setBarColor = function(block, record) {
}; };
// Setup jquery-ui resizable // Setup jquery-ui resizable
Gantt.prototype.listenForBlockResize = function(startDate) { Kanboard.Gantt.prototype.listenForBlockResize = function(startDate) {
var self = this; var self = this;
jQuery("div.ganttview-block", this.options.container).resizable({ jQuery("div.ganttview-block", this.options.container).resizable({
@@ -293,7 +299,7 @@ Gantt.prototype.listenForBlockResize = function(startDate) {
}; };
// Setup jquery-ui drag and drop // Setup jquery-ui drag and drop
Gantt.prototype.listenForBlockMove = function(startDate) { Kanboard.Gantt.prototype.listenForBlockMove = function(startDate) {
var self = this; var self = this;
jQuery("div.ganttview-block", this.options.container).draggable({ jQuery("div.ganttview-block", this.options.container).draggable({
@@ -309,7 +315,7 @@ Gantt.prototype.listenForBlockMove = function(startDate) {
}; };
// Update the record data and the position on the chart // Update the record data and the position on the chart
Gantt.prototype.updateDataAndPosition = function(block, startDate) { Kanboard.Gantt.prototype.updateDataAndPosition = function(block, startDate) {
var container = jQuery("div.ganttview-slide-container", this.options.container); var container = jQuery("div.ganttview-slide-container", this.options.container);
var scroll = container.scrollLeft(); var scroll = container.scrollLeft();
var offset = block.offset().left - container.offset().left - 1 + scroll; var offset = block.offset().left - container.offset().left - 1 + scroll;
@@ -349,7 +355,7 @@ Gantt.prototype.updateDataAndPosition = function(block, startDate) {
// Creates a 3 dimensional array [year][month][day] of every day // Creates a 3 dimensional array [year][month][day] of every day
// between the given start and end dates // between the given start and end dates
Gantt.prototype.getDates = function(start, end) { Kanboard.Gantt.prototype.getDates = function(start, end) {
var dates = []; var dates = [];
dates[start.getFullYear()] = []; dates[start.getFullYear()] = [];
dates[start.getFullYear()][start.getMonth()] = [start]; dates[start.getFullYear()][start.getMonth()] = [start];
@@ -374,7 +380,7 @@ Gantt.prototype.getDates = function(start, end) {
}; };
// Convert data to Date object // Convert data to Date object
Gantt.prototype.prepareData = function(data) { Kanboard.Gantt.prototype.prepareData = function(data) {
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
var start = new Date(data[i].start[0], data[i].start[1] - 1, data[i].start[2], 0, 0, 0, 0); var start = new Date(data[i].start[0], data[i].start[1] - 1, data[i].start[2], 0, 0, 0, 0);
data[i].start = start; data[i].start = start;
@@ -387,7 +393,7 @@ Gantt.prototype.prepareData = function(data) {
}; };
// Get the start and end date from the data provided // Get the start and end date from the data provided
Gantt.prototype.getDateRange = function(minDays) { Kanboard.Gantt.prototype.getDateRange = function(minDays) {
var minStart = new Date(); var minStart = new Date();
var maxEnd = new Date(); var maxEnd = new Date();
@@ -425,7 +431,7 @@ Gantt.prototype.getDateRange = function(minDays) {
}; };
// Returns the number of day between 2 dates // Returns the number of day between 2 dates
Gantt.prototype.daysBetween = function(start, end) { Kanboard.Gantt.prototype.daysBetween = function(start, end) {
if (! start || ! end) { if (! start || ! end) {
return 0; return 0;
} }
@@ -441,17 +447,17 @@ Gantt.prototype.daysBetween = function(start, end) {
}; };
// Return true if it's the weekend // Return true if it's the weekend
Gantt.prototype.isWeekend = function(date) { Kanboard.Gantt.prototype.isWeekend = function(date) {
return date.getDay() % 6 == 0; return date.getDay() % 6 == 0;
}; };
// Clone Date object // Clone Date object
Gantt.prototype.cloneDate = function(date) { Kanboard.Gantt.prototype.cloneDate = function(date) {
return new Date(date.getTime()); return new Date(date.getTime());
}; };
// Add days to a Date object // Add days to a Date object
Gantt.prototype.addDays = function(date, value) { Kanboard.Gantt.prototype.addDays = function(date, value) {
date.setDate(date.getDate() + value * 1); date.setDate(date.getDate() + value * 1);
return date; return date;
}; };
@@ -463,7 +469,7 @@ Gantt.prototype.addDays = function(date, value) {
* 0 = values are equal * 0 = values are equal
* 1 = date1 is greaterthan date2. * 1 = date1 is greaterthan date2.
*/ */
Gantt.prototype.compareDate = function(date1, date2) { Kanboard.Gantt.prototype.compareDate = function(date1, date2) {
if (isNaN(date1) || isNaN(date2)) { if (isNaN(date1) || isNaN(date2)) {
throw new Error(date1 + " - " + date2); throw new Error(date1 + " - " + date2);
} else if (date1 instanceof Date && date2 instanceof Date) { } else if (date1 instanceof Date && date2 instanceof Date) {

View File

@@ -1,20 +1,27 @@
function LeadCycleTimeChart(app) { Kanboard.LeadCycleTimeChart = function(app) {
this.app = app; this.app = app;
} };
LeadCycleTimeChart.prototype.execute = function() { Kanboard.LeadCycleTimeChart.prototype.execute = function() {
var metrics = $("#chart").data("metrics"); if (this.app.hasId("analytic-lead-cycle-time")) {
var cycle = [$("#chart").data("label-cycle")]; this.show();
var lead = [$("#chart").data("label-lead")]; }
};
Kanboard.LeadCycleTimeChart.prototype.show = function() {
var chart = $("#chart");
var metrics = chart.data("metrics");
var cycle = [chart.data("label-cycle")];
var lead = [chart.data("label-lead")];
var categories = []; var categories = [];
var types = {}; var types = {};
types[$("#chart").data("label-cycle")] = 'area'; types[chart.data("label-cycle")] = 'area';
types[$("#chart").data("label-lead")] = 'area-spline'; types[chart.data("label-lead")] = 'area-spline';
var colors = {}; var colors = {};
colors[$("#chart").data("label-lead")] = '#afb42b'; colors[chart.data("label-lead")] = '#afb42b';
colors[$("#chart").data("label-cycle")] = '#4e342e'; colors[chart.data("label-cycle")] = '#4e342e';
for (var i = 0; i < metrics.length; i++) { for (var i = 0; i < metrics.length; i++) {
cycle.push(parseInt(metrics[i].avg_cycle_time)); cycle.push(parseInt(metrics[i].avg_cycle_time));

View File

@@ -1,48 +1,59 @@
function Markdown() { Kanboard.Markdown = function(app) {
this.app = app;
this.editor = null;
};
Kanboard.Markdown.prototype.onPopoverOpened = function() {
this.listen();
};
Kanboard.Markdown.prototype.onPopoverClosed = function() {
this.listen();
};
Kanboard.Markdown.prototype.listen = function() {
var editors = $(".markdown-editor");
if (this.editor) {
this.destroy();
} }
Markdown.prototype.showPreview = function(e) { if (editors.length > 0) {
e.preventDefault(); this.show(editors[0]);
}
};
var write = $(".write-area"); Kanboard.Markdown.prototype.destroy = function() {
var preview = $(".preview-area"); var cm = this.editor.codemirror;
var textarea = $("textarea"); var wrapper = cm.getWrapperElement();
$("#markdown-write").parent().removeClass("form-tab-selected"); for (var item in ["toolbar", "statusbar", "sideBySide"]) {
$("#markdown-preview").parent().addClass("form-tab-selected"); if (this.editor.gui[item]) {
wrapper.parentNode.removeChild(this.editor.gui[item]);
}
}
var request = $.ajax({ cm.toTextArea();
url: $("body").data("markdown-preview-url"), this.editor = null;
contentType: "application/json", };
type: "POST",
processData: false,
dataType: "html",
data: JSON.stringify({
"text": textarea.val()
})
});
request.done(function(data) { Kanboard.Markdown.prototype.show = function(textarea) {
preview.find(".markdown").html(data) var toolbar = ["bold", "italic", "strikethrough", "heading", "|", "unordered-list", "ordered-list", "link", "|", "code", "table"];
preview.css("height", textarea.css("height"));
preview.css("width", textarea.css("width"));
write.hide(); this.editor = new SimpleMDE({
preview.show(); element: textarea,
status: false,
toolbarTips: false,
autoDownloadFontAwesome: false,
spellChecker: false,
autosave: {
enabled: false
},
forceSync: true,
blockStyles: {
italic: "_"
},
toolbar: textarea.hasAttribute("data-markdown-editor-disable-toolbar") ? false : toolbar,
placeholder: textarea.getAttribute("placeholder")
}); });
}; };
Markdown.prototype.showWriter = function(e) {
e.preventDefault();
$("#markdown-write").parent().addClass("form-tab-selected");
$("#markdown-preview").parent().removeClass("form-tab-selected");
$(".write-area").show();
$(".preview-area").hide();
};
Markdown.prototype.listen = function() {
$(document).on("click", "#markdown-preview", this.showPreview.bind(this));
$(document).on("click", "#markdown-write", this.showWriter.bind(this));
};

View File

@@ -0,0 +1,3 @@
'use strict';
var Kanboard = {};

View File

@@ -0,0 +1,9 @@
Kanboard.Notification = function(app) {
this.app = app;
};
Kanboard.Notification.prototype.execute = function() {
$(".alert-fade-out").delay(4000).fadeOut(800, function() {
$(this).remove();
});
};

View File

@@ -1,35 +1,28 @@
function Popover(app) { Kanboard.Popover = function(app) {
this.app = app; this.app = app;
this.router = new Router();
this.router.addRoute('screenshot-zone', Screenshot);
}
Popover.prototype.isOpen = function() {
return $('#popover-container').size() > 0;
}; };
Popover.prototype.open = function(link) { Kanboard.Popover.prototype.listen = function() {
var self = this; var self = this;
self.app.dropdown.close();
$.get(link, function(content) { $(document).on("click", ".popover", function(e) {
$("body").prepend('<div id="popover-container"><div id="popover-content">' + content + '</div></div>'); self.onClick(e);
self.afterOpen(); });
$(document).on("click", ".close-popover", function(e) {
self.close(e);
});
$(document).on("click", "#popover-container", function(e) {
self.close(e);
});
$(document).on("click", "#popover-content", function(e) {
e.stopPropagation();
}); });
}; };
Popover.prototype.close = function(e) { Kanboard.Popover.prototype.onClick = function(e) {
if (this.isOpen()) {
if (e) {
e.preventDefault();
}
$('#popover-container').remove();
}
};
Popover.prototype.onClick = function(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@@ -45,20 +38,69 @@ Popover.prototype.onClick = function(e) {
} }
}; };
Popover.prototype.listen = function() { Kanboard.Popover.prototype.isOpen = function() {
$(document).on("click", ".popover", this.onClick.bind(this)); return $('#popover-container').size() > 0;
$(document).on("click", ".close-popover", this.close.bind(this));
$(document).on("click", "#popover-container", this.close.bind(this));
$(document).on("click", "#popover-content", function(e) { e.stopPropagation(); });
}; };
Popover.prototype.afterOpen = function() { Kanboard.Popover.prototype.open = function(link) {
var self = this;
$.get(link, function(content) {
$("body").prepend('<div id="popover-container"><div id="popover-content">' + content + '</div></div>');
self.executeOnOpenedListeners();
});
};
Kanboard.Popover.prototype.close = function(e) {
if (this.isOpen()) {
if (e) {
e.preventDefault();
}
$("#popover-container").remove();
this.executeOnClosedListeners();
}
};
Kanboard.Popover.prototype.ajaxReload = function(data, request, self) {
var redirect = request.getResponseHeader("X-Ajax-Redirect");
if (redirect) {
window.location = redirect === 'self' ? window.location.href.split("#")[0] : redirect;
}
else {
$("#popover-content").html(data);
$("#popover-content input[autofocus]").focus();
self.executeOnOpenedListeners();
}
};
Kanboard.Popover.prototype.executeOnOpenedListeners = function() {
for (var className in this.app.controllers) {
var controller = this.app.get(className);
if (typeof controller.onPopoverOpened === "function") {
controller.onPopoverOpened();
}
}
this.afterOpen();
};
Kanboard.Popover.prototype.executeOnClosedListeners = function() {
for (var className in this.app.controllers) {
var controller = this.app.get(className);
if (typeof controller.onPopoverClosed === "function") {
controller.onPopoverClosed();
}
}
};
Kanboard.Popover.prototype.afterOpen = function() {
var self = this; var self = this;
var popoverForm = $("#popover-content .popover-form"); var popoverForm = $("#popover-content .popover-form");
self.app.refresh();
self.router.dispatch(this.app);
// Submit forms with Ajax request // Submit forms with Ajax request
if (popoverForm) { if (popoverForm) {
popoverForm.on("submit", function(e) { popoverForm.on("submit", function(e) {
@@ -69,7 +111,7 @@ Popover.prototype.afterOpen = function() {
url: popoverForm.attr("action"), url: popoverForm.attr("action"),
data: popoverForm.serialize(), data: popoverForm.serialize(),
success: function(data, textStatus, request) { success: function(data, textStatus, request) {
self.afterSubmit(data, request, self); self.ajaxReload(data, request, self);
}, },
beforeSend: function() { beforeSend: function() {
var button = $('.popover-form button[type="submit"]'); var button = $('.popover-form button[type="submit"]');
@@ -88,21 +130,16 @@ Popover.prototype.afterOpen = function() {
type: "GET", type: "GET",
url: $(this).attr("href"), url: $(this).attr("href"),
success: function(data, textStatus, request) { success: function(data, textStatus, request) {
self.afterSubmit(data, request, self); self.ajaxReload(data, request, self);
} }
}); });
}); });
};
Popover.prototype.afterSubmit = function(data, request, self) { // Autofocus fields (html5 autofocus works only with page onload)
var redirect = request.getResponseHeader("X-Ajax-Redirect"); $("[autofocus]").each(function() {
$(this).focus();
});
if (redirect) { this.app.datePicker();
window.location = redirect === 'self' ? window.location.href.split("#")[0] : redirect; this.app.autoComplete();
}
else {
$("#popover-content").html(data);
$("#popover-content input[autofocus]").focus();
self.afterOpen();
}
}; };

View File

@@ -1,28 +0,0 @@
function Project() {
}
Project.prototype.listen = function() {
$('.project-change-role').on('change', function() {
$.ajax({
cache: false,
url: $(this).data('url'),
contentType: "application/json",
type: "POST",
processData: false,
data: JSON.stringify({
"id": $(this).data('id'),
"role": $(this).val()
})
});
});
$('#project-creation-form #form-src_project_id').on('change', function() {
var srcProjectId = $(this).val();
if (srcProjectId == 0) {
$(".project-creation-options").hide();
} else {
$(".project-creation-options").show();
}
});
};

View File

@@ -0,0 +1,15 @@
Kanboard.ProjectCreation = function(app) {
this.app = app;
};
Kanboard.ProjectCreation.prototype.onPopoverOpened = function() {
$('#project-creation-form #form-src_project_id').on('change', function() {
var srcProjectId = $(this).val();
if (srcProjectId == 0) {
$(".project-creation-options").hide();
} else {
$(".project-creation-options").show();
}
});
};

View File

@@ -0,0 +1,19 @@
Kanboard.ProjectPermission = function(app) {
this.app = app;
};
Kanboard.ProjectPermission.prototype.listen = function() {
$('.project-change-role').on('change', function () {
$.ajax({
cache: false,
url: $(this).data('url'),
contentType: "application/json",
type: "POST",
processData: false,
data: JSON.stringify({
"id": $(this).data('id'),
"role": $(this).val()
})
});
});
};

View File

@@ -1,37 +0,0 @@
function Router() {
this.routes = {};
}
Router.prototype.addRoute = function(id, controller) {
this.routes[id] = controller;
};
Router.prototype.dispatch = function(app) {
for (var id in this.routes) {
if (document.getElementById(id)) {
var controller = Object.create(this.routes[id].prototype);
this.routes[id].apply(controller, [app]);
controller.execute();
break;
}
}
};
jQuery(document).ready(function() {
var app = new App();
var router = new Router();
router.addRoute('board', Board);
router.addRoute('calendar', Calendar);
router.addRoute('screenshot-zone', Screenshot);
router.addRoute('analytic-task-repartition', TaskRepartitionChart);
router.addRoute('analytic-user-repartition', UserRepartitionChart);
router.addRoute('analytic-cfd', CumulativeFlowDiagram);
router.addRoute('analytic-burndown', BurndownChart);
router.addRoute('analytic-avg-time-column', AvgTimeColumnChart);
router.addRoute('analytic-task-time-column', TaskTimeColumnChart);
router.addRoute('analytic-lead-cycle-time', LeadCycleTimeChart);
router.addRoute('analytic-compare-hours', CompareHoursColumnChart);
router.addRoute('gantt-chart', Gantt);
router.dispatch(app);
app.listen();
});

View File

@@ -1,13 +1,16 @@
function Screenshot() { Kanboard.Screenshot = function(app) {
this.app = app;
this.pasteCatcher = null; this.pasteCatcher = null;
} };
Screenshot.prototype.execute = function() { Kanboard.Screenshot.prototype.onPopoverOpened = function() {
if (this.app.hasId("screenshot-zone")) {
this.initialize(); this.initialize();
}
}; };
// Setup event listener and workarounds // Setup event listener and workarounds
Screenshot.prototype.initialize = function() { Kanboard.Screenshot.prototype.initialize = function() {
this.destroy(); this.destroy();
if (! window.Clipboard) { if (! window.Clipboard) {
@@ -40,7 +43,7 @@ Screenshot.prototype.initialize = function() {
}; };
// Destroy contentEditable element // Destroy contentEditable element
Screenshot.prototype.destroy = function() { Kanboard.Screenshot.prototype.destroy = function() {
if (this.pasteCatcher != null) { if (this.pasteCatcher != null) {
document.body.removeChild(this.pasteCatcher); document.body.removeChild(this.pasteCatcher);
} }
@@ -53,14 +56,14 @@ Screenshot.prototype.destroy = function() {
}; };
// Set focus on contentEditable element // Set focus on contentEditable element
Screenshot.prototype.setFocus = function() { Kanboard.Screenshot.prototype.setFocus = function() {
if (this.pasteCatcher !== null) { if (this.pasteCatcher !== null) {
this.pasteCatcher.focus(); this.pasteCatcher.focus();
} }
}; };
// Paste event callback // Paste event callback
Screenshot.prototype.pasteHandler = function(e) { Kanboard.Screenshot.prototype.pasteHandler = function(e) {
// Firefox doesn't have the property e.clipboardData.items (only Chrome) // Firefox doesn't have the property e.clipboardData.items (only Chrome)
if (e.clipboardData && e.clipboardData.items) { if (e.clipboardData && e.clipboardData.items) {
@@ -95,7 +98,7 @@ Screenshot.prototype.pasteHandler = function(e) {
}; };
// Parse the input in the paste catcher element // Parse the input in the paste catcher element
Screenshot.prototype.checkInput = function() { Kanboard.Screenshot.prototype.checkInput = function() {
var child = this.pasteCatcher.childNodes[0]; var child = this.pasteCatcher.childNodes[0];
if (child) { if (child) {
@@ -110,7 +113,7 @@ Screenshot.prototype.checkInput = function() {
}; };
// Creates a new image from a given source // Creates a new image from a given source
Screenshot.prototype.createImage = function(blob) { Kanboard.Screenshot.prototype.createImage = function(blob) {
var pastedImage = new Image(); var pastedImage = new Image();
pastedImage.src = blob; pastedImage.src = blob;

View File

@@ -1,18 +1,21 @@
function Search(app) { Kanboard.Search = function(app) {
this.app = app; this.app = app;
this.keyboardShortcuts(); };
}
Kanboard.Search.prototype.focus = function() {
Search.prototype.focus = function() {
// Place cursor at the end when focusing on the search box // Place cursor at the end when focusing on the search box
$(document).on("focus", "#form-search", function() { $(document).on("focus", "#form-search", function() {
if ($("#form-search")[0].setSelectionRange) { var input = $("#form-search");
$('#form-search')[0].setSelectionRange($('#form-search').val().length, $('#form-search').val().length);
if (input[0].setSelectionRange) {
var len = input.val().length * 2;
input[0].setSelectionRange(len, len);
} }
}); });
}; };
Search.prototype.listen = function() { Kanboard.Search.prototype.listen = function() {
var self = this; var self = this;
// Filter helper for search // Filter helper for search
@@ -21,68 +24,51 @@ Search.prototype.listen = function() {
var filter = $(this).data("filter"); var filter = $(this).data("filter");
var appendFilter = $(this).data("append-filter"); var appendFilter = $(this).data("append-filter");
var input = $("#form-search");
if (appendFilter) { if (appendFilter) {
filter = $("#form-search").val() + " " + appendFilter; filter = input.val() + " " + appendFilter;
} }
$("#form-search").val(filter); input.val(filter);
if ($('#board').length) {
self.app.board.reloadFilters(filter);
}
else {
$("form.search").submit(); $("form.search").submit();
}
}); });
}; };
Search.prototype.keyboardShortcuts = function() { Kanboard.Search.prototype.goToView = function(label) {
var link = $(label);
if (link.length) {
window.location = link.attr('href');
}
};
Kanboard.Search.prototype.keyboardShortcuts = function() {
var self = this; var self = this;
// Switch view mode for projects: go to the overview page // Switch view mode for projects: go to the overview page
Mousetrap.bind("v o", function(e) { Mousetrap.bind("v o", function() {
var link = $(".view-overview"); self.goToView(".view-overview");
if (link.length) {
window.location = link.attr('href');
}
}); });
// Switch view mode for projects: go to the board // Switch view mode for projects: go to the board
Mousetrap.bind("v b", function(e) { Mousetrap.bind("v b", function() {
var link = $(".view-board"); self.goToView(".view-board");
if (link.length) {
window.location = link.attr('href');
}
}); });
// Switch view mode for projects: go to the calendar // Switch view mode for projects: go to the calendar
Mousetrap.bind("v c", function(e) { Mousetrap.bind("v c", function() {
var link = $(".view-calendar"); self.goToView(".view-calendar");
if (link.length) {
window.location = link.attr('href');
}
}); });
// Switch view mode for projects: go to the listing // Switch view mode for projects: go to the listing
Mousetrap.bind("v l", function(e) { Mousetrap.bind("v l", function() {
var link = $(".view-listing"); self.goToView(".view-listing");
if (link.length) {
window.location = link.attr('href');
}
}); });
// Switch view mode for projects: go to the gantt chart // Switch view mode for projects: go to the gantt chart
Mousetrap.bind("v g", function(e) { Mousetrap.bind("v g", function() {
var link = $(".view-gantt"); self.goToView(".view-gantt");
if (link.length) {
window.location = link.attr('href');
}
}); });
// Focus to the search field // Focus to the search field
@@ -99,14 +85,9 @@ Search.prototype.keyboardShortcuts = function() {
Mousetrap.bind("r", function(e) { Mousetrap.bind("r", function(e) {
e.preventDefault(); e.preventDefault();
var reset = $(".filter-reset").data("filter"); var reset = $(".filter-reset").data("filter");
var input = $("#form-search");
$("#form-search").val(reset); input.val(reset);
if ($('#board').length) {
self.app.board.reloadFilters(reset);
}
else {
$("form.search").submit(); $("form.search").submit();
}
}); });
}; };

21
assets/js/src/Session.js Normal file
View File

@@ -0,0 +1,21 @@
Kanboard.Session = function(app) {
this.app = app;
};
Kanboard.Session.prototype.execute = function() {
window.setInterval(this.checkSession, 60000);
};
Kanboard.Session.prototype.checkSession = function() {
if (! $(".form-login").length) {
$.ajax({
cache: false,
url: $("body").data("status-url"),
statusCode: {
401: function() {
window.location = $("body").data("login-url");
}
}
});
}
};

View File

@@ -1,15 +1,14 @@
function Subtask(app) { Kanboard.Subtask = function(app) {
this.app = app; this.app = app;
} };
Subtask.prototype.listen = function() { Kanboard.Subtask.prototype.listen = function() {
var self = this; var self = this;
this.dragAndDrop(); this.dragAndDrop();
$(document).on("click", ".subtask-toggle-status", function(e) { $(document).on("click", ".subtask-toggle-status", function(e) {
e.preventDefault();
var el = $(this); var el = $(this);
e.preventDefault();
$.ajax({ $.ajax({
cache: false, cache: false,
@@ -27,8 +26,8 @@ Subtask.prototype.listen = function() {
}); });
$(document).on("click", ".subtask-toggle-timer", function(e) { $(document).on("click", ".subtask-toggle-timer", function(e) {
e.preventDefault();
var el = $(this); var el = $(this);
e.preventDefault();
$.ajax({ $.ajax({
cache: false, cache: false,
@@ -41,7 +40,7 @@ Subtask.prototype.listen = function() {
}); });
}; };
Subtask.prototype.dragAndDrop = function() { Kanboard.Subtask.prototype.dragAndDrop = function() {
var self = this; var self = this;
$(".draggable-row-handle").mouseenter(function() { $(".draggable-row-handle").mouseenter(function() {
@@ -71,7 +70,7 @@ Subtask.prototype.dragAndDrop = function() {
}).disableSelection(); }).disableSelection();
}; };
Subtask.prototype.savePosition = function(subtaskId, position) { Kanboard.Subtask.prototype.savePosition = function(subtaskId, position) {
var url = $(".subtasks-table").data("save-position-url"); var url = $(".subtasks-table").data("save-position-url");
var self = this; var self = this;

View File

@@ -1,60 +1,15 @@
function Swimlane(app) { Kanboard.Swimlane = function(app) {
this.app = app; this.app = app;
}
Swimlane.prototype.getStorageKey = function() {
return "hidden_swimlanes_" + $("#board").data("project-id");
}; };
Swimlane.prototype.expand = function(swimlaneId) { Kanboard.Swimlane.prototype.execute = function() {
var swimlaneIds = this.getAllCollapsed(); if ($(".swimlanes-table").length) {
var index = swimlaneIds.indexOf(swimlaneId); this.dragAndDrop();
if (index > -1) {
swimlaneIds.splice(index, 1);
}
localStorage.setItem(this.getStorageKey(), JSON.stringify(swimlaneIds));
$('.board-swimlane-columns-' + swimlaneId).css('display', 'table-row');
$('.board-swimlane-tasks-' + swimlaneId).css('display', 'table-row');
$('.hide-icon-swimlane-' + swimlaneId).css('display', 'inline');
$('.show-icon-swimlane-' + swimlaneId).css('display', 'none');
};
Swimlane.prototype.collapse = function(swimlaneId) {
var swimlaneIds = this.getAllCollapsed();
if (swimlaneIds.indexOf(swimlaneId) < 0) {
swimlaneIds.push(swimlaneId);
localStorage.setItem(this.getStorageKey(), JSON.stringify(swimlaneIds));
}
$('.board-swimlane-columns-' + swimlaneId + ':not(:first-child)').css('display', 'none');
$('.board-swimlane-tasks-' + swimlaneId).css('display', 'none');
$('.hide-icon-swimlane-' + swimlaneId).css('display', 'none');
$('.show-icon-swimlane-' + swimlaneId).css('display', 'inline');
};
Swimlane.prototype.isCollapsed = function(swimlaneId) {
return this.getAllCollapsed().indexOf(swimlaneId) > -1;
};
Swimlane.prototype.getAllCollapsed = function() {
return JSON.parse(localStorage.getItem(this.getStorageKey())) || [];
};
Swimlane.prototype.refresh = function() {
var swimlaneIds = this.getAllCollapsed();
for (var i = 0; i < swimlaneIds.length; i++) {
this.collapse(swimlaneIds[i]);
} }
}; };
Swimlane.prototype.listen = function() { Kanboard.Swimlane.prototype.listen = function() {
var self = this; var self = this;
self.dragAndDrop();
$(document).on('click', ".board-swimlane-toggle", function(e) { $(document).on('click', ".board-swimlane-toggle", function(e) {
e.preventDefault(); e.preventDefault();
@@ -70,7 +25,57 @@ Swimlane.prototype.listen = function() {
}); });
}; };
Swimlane.prototype.dragAndDrop = function() { Kanboard.Swimlane.prototype.onBoardRendered = function() {
var swimlaneIds = this.getAllCollapsed();
for (var i = 0; i < swimlaneIds.length; i++) {
this.collapse(swimlaneIds[i]);
}
};
Kanboard.Swimlane.prototype.getStorageKey = function() {
return "hidden_swimlanes_" + $("#board").data("project-id");
};
Kanboard.Swimlane.prototype.expand = function(swimlaneId) {
var swimlaneIds = this.getAllCollapsed();
var index = swimlaneIds.indexOf(swimlaneId);
if (index > -1) {
swimlaneIds.splice(index, 1);
}
localStorage.setItem(this.getStorageKey(), JSON.stringify(swimlaneIds));
$('.board-swimlane-columns-' + swimlaneId).css('display', 'table-row');
$('.board-swimlane-tasks-' + swimlaneId).css('display', 'table-row');
$('.hide-icon-swimlane-' + swimlaneId).css('display', 'inline');
$('.show-icon-swimlane-' + swimlaneId).css('display', 'none');
};
Kanboard.Swimlane.prototype.collapse = function(swimlaneId) {
var swimlaneIds = this.getAllCollapsed();
if (swimlaneIds.indexOf(swimlaneId) < 0) {
swimlaneIds.push(swimlaneId);
localStorage.setItem(this.getStorageKey(), JSON.stringify(swimlaneIds));
}
$('.board-swimlane-columns-' + swimlaneId + ':not(:first-child)').css('display', 'none');
$('.board-swimlane-tasks-' + swimlaneId).css('display', 'none');
$('.hide-icon-swimlane-' + swimlaneId).css('display', 'none');
$('.show-icon-swimlane-' + swimlaneId).css('display', 'inline');
};
Kanboard.Swimlane.prototype.isCollapsed = function(swimlaneId) {
return this.getAllCollapsed().indexOf(swimlaneId) > -1;
};
Kanboard.Swimlane.prototype.getAllCollapsed = function() {
return JSON.parse(localStorage.getItem(this.getStorageKey())) || [];
};
Kanboard.Swimlane.prototype.dragAndDrop = function() {
var self = this; var self = this;
$(".draggable-row-handle").mouseenter(function() { $(".draggable-row-handle").mouseenter(function() {
@@ -100,7 +105,7 @@ Swimlane.prototype.dragAndDrop = function() {
}).disableSelection(); }).disableSelection();
}; };
Swimlane.prototype.savePosition = function(swimlaneId, position) { Kanboard.Swimlane.prototype.savePosition = function(swimlaneId, position) {
var url = $(".swimlanes-table").data("save-position-url"); var url = $(".swimlanes-table").data("save-position-url");
var self = this; var self = this;

View File

@@ -1,31 +1,31 @@
function Task(app) { Kanboard.Task = function(app) {
this.app = app; this.app = app;
} };
Task.prototype.keyboardShortcuts = function() { Kanboard.Task.prototype.keyboardShortcuts = function() {
var taskView = $("#task-view"); var taskView = $("#task-view");
var self = this; var self = this;
if (taskView.length) { if (this.app.hasId("task-view")) {
Mousetrap.bind("e", function() { Mousetrap.bind("e", function() {
self.app.popover.open(taskView.data("edit-url")); self.app.get("Popover").open(taskView.data("edit-url"));
}); });
Mousetrap.bind("c", function() { Mousetrap.bind("c", function() {
self.app.popover.open(taskView.data("comment-url")); self.app.get("Popover").open(taskView.data("comment-url"));
}); });
Mousetrap.bind("s", function() { Mousetrap.bind("s", function() {
self.app.popover.open(taskView.data("subtask-url")); self.app.get("Popover").open(taskView.data("subtask-url"));
}); });
Mousetrap.bind("l", function() { Mousetrap.bind("l", function() {
self.app.popover.open(taskView.data("internal-link-url")); self.app.get("Popover").open(taskView.data("internal-link-url"));
}); });
} }
}; };
Task.prototype.listen = function() { Kanboard.Task.prototype.onPopoverOpened = function() {
var self = this; var self = this;
var reloadingProjectId = 0; var reloadingProjectId = 0;
@@ -38,11 +38,11 @@ Task.prototype.listen = function() {
// Assign to me // Assign to me
$(document).on("click", ".assign-me", function(e) { $(document).on("click", ".assign-me", function(e) {
e.preventDefault();
var currentId = $(this).data("current-id"); var currentId = $(this).data("current-id");
var dropdownId = "#" + $(this).data("target-id"); var dropdownId = "#" + $(this).data("target-id");
e.preventDefault();
if ($(dropdownId + ' option[value=' + currentId + ']').length) { if ($(dropdownId + ' option[value=' + currentId + ']').length) {
$(dropdownId).val(currentId); $(dropdownId).val(currentId);
} }
@@ -65,8 +65,7 @@ Task.prototype.listen = function() {
success: function(data, textStatus, request) { success: function(data, textStatus, request) {
reloadingProjectId = 0; reloadingProjectId = 0;
$(".loading-icon").hide(); $(".loading-icon").hide();
self.app.get("Popover").ajaxReload(data, request, self.app.get("Popover"));
self.app.popover.afterSubmit(data, request, self.app.popover);
} }
}); });
} }

View File

@@ -1,7 +1,14 @@
function TaskRepartitionChart() { Kanboard.TaskRepartitionChart = function(app) {
} this.app = app;
};
TaskRepartitionChart.prototype.execute = function() { Kanboard.TaskRepartitionChart.prototype.execute = function() {
if (this.app.hasId("analytic-task-repartition")) {
this.show();
}
};
Kanboard.TaskRepartitionChart.prototype.show = function() {
var metrics = $("#chart").data("metrics"); var metrics = $("#chart").data("metrics");
var columns = []; var columns = [];

View File

@@ -1,10 +1,17 @@
function TaskTimeColumnChart(app) { Kanboard.TaskTimeColumnChart = function(app) {
this.app = app; this.app = app;
} };
TaskTimeColumnChart.prototype.execute = function() { Kanboard.TaskTimeColumnChart.prototype.execute = function() {
var metrics = $("#chart").data("metrics"); if (this.app.hasId("analytic-task-time-column")) {
var plots = [$("#chart").data("label")]; this.show();
}
};
Kanboard.TaskTimeColumnChart.prototype.show = function() {
var chart = $("#chart");
var metrics = chart.data("metrics");
var plots = [chart.data("label")];
var categories = []; var categories = [];
for (var i = 0; i < metrics.length; i++) { for (var i = 0; i < metrics.length; i++) {

View File

@@ -1,10 +1,8 @@
function Tooltip(app) { Kanboard.Tooltip = function(app) {
this.app = app; this.app = app;
} };
Tooltip.prototype.listen = function() {
var self = this;
Kanboard.Tooltip.prototype.execute = function() {
$(".tooltip").tooltip({ $(".tooltip").tooltip({
track: false, track: false,
show: false, show: false,

View File

@@ -1,7 +1,14 @@
function UserRepartitionChart() { Kanboard.UserRepartitionChart = function(app) {
} this.app = app;
};
UserRepartitionChart.prototype.execute = function() { Kanboard.UserRepartitionChart.prototype.execute = function() {
if (this.app.hasId("analytic-user-repartition")) {
this.show();
}
};
Kanboard.UserRepartitionChart.prototype.show = function() {
var metrics = $("#chart").data("metrics"); var metrics = $("#chart").data("metrics");
var columns = []; var columns = [];

4
assets/js/src/bootstrap.js vendored Normal file
View File

@@ -0,0 +1,4 @@
jQuery(document).ready(function() {
var app = new Kanboard.App();
app.execute();
});

File diff suppressed because it is too large Load Diff

14
assets/js/vendor/simplemde.min.js vendored Normal file

File diff suppressed because one or more lines are too long