Add screenshot support for tasks (copy/paste images directly)
This commit is contained in:
parent
2a150dd3be
commit
3b403a1a4b
|
|
@ -80,6 +80,7 @@ Documentation
|
|||
#### Working with tasks
|
||||
|
||||
- [Creating tasks](docs/creating-tasks.markdown)
|
||||
- [Adding screenshots](docs/screenshots.markdown)
|
||||
- [Task links](docs/task-links.markdown)
|
||||
- [Transitions](docs/transitions.markdown)
|
||||
- [Time tracking](docs/time-tracking.markdown)
|
||||
|
|
|
|||
|
|
@ -335,4 +335,19 @@ class Board extends Base
|
|||
|
||||
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $values['project_id'])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Screenshot popover
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function screenshot()
|
||||
{
|
||||
$task = $this->getTask();
|
||||
|
||||
$this->response->html($this->template->render('file/screenshot', array(
|
||||
'task' => $task,
|
||||
'redirect' => 'board',
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,32 @@ namespace Controller;
|
|||
*/
|
||||
class File extends Base
|
||||
{
|
||||
/**
|
||||
* Screenshot
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function screenshot()
|
||||
{
|
||||
$task = $this->getTask();
|
||||
|
||||
if ($this->request->isPost() && $this->file->uploadScreenshot($task['project_id'], $task['id'], $this->request->getValue('screenshot'))) {
|
||||
|
||||
$this->session->flash(t('Screenshot uploaded successfully.'));
|
||||
|
||||
if ($this->request->getStringParam('redirect') === 'board') {
|
||||
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
$this->response->html($this->taskLayout('file/screenshot', array(
|
||||
'task' => $task,
|
||||
'redirect' => 'task',
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* File upload form
|
||||
*
|
||||
|
|
@ -34,13 +60,11 @@ class File extends Base
|
|||
{
|
||||
$task = $this->getTask();
|
||||
|
||||
if ($this->file->upload($task['project_id'], $task['id'], 'files') === true) {
|
||||
$this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'].'#attachments');
|
||||
}
|
||||
else {
|
||||
if (! $this->file->upload($task['project_id'], $task['id'], 'files')) {
|
||||
$this->session->flashError(t('Unable to upload the file.'));
|
||||
$this->response->redirect('?controller=file&action=create&task_id='.$task['id'].'&project_id='.$task['project_id']);
|
||||
}
|
||||
|
||||
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -59,7 +83,7 @@ class File extends Base
|
|||
$this->response->binary(file_get_contents($filename));
|
||||
}
|
||||
|
||||
$this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']);
|
||||
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -140,7 +164,7 @@ class File extends Base
|
|||
$this->session->flashError(t('Unable to remove this file.'));
|
||||
}
|
||||
|
||||
$this->response->redirect('?controller=task&action=show&task_id='.$task['id'].'&project_id='.$task['project_id']);
|
||||
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -849,10 +849,16 @@ return array(
|
|||
'Test your device' => 'Testez votre appareil',
|
||||
'Assign a color when the task is moved to a specific column' => 'Assigner une couleur lorsque la tâche est déplacée dans une colonne spécifique',
|
||||
'%s via Kanboard' => '%s via Kanboard',
|
||||
'uploaded by: %s' => 'Télécharger par : %s',
|
||||
'uploaded on: %s' => 'Télécharger le : %s',
|
||||
'uploaded by: %s' => 'Téléchargé par %s',
|
||||
'uploaded on: %s' => 'Téléchargé le %s',
|
||||
'size: %s' => 'Taille : %s',
|
||||
'Burndown chart for "%s"' => 'Graphique d\'avancement pour « %s »',
|
||||
'Burndown chart' => 'Graphique d\'avancement',
|
||||
'This chart show the task complexity over the time (Work Remaining).' => 'Ce graphique représente la complexité des tâches en fonction du temps (travail restant).',
|
||||
'Screenshot taken %s' => 'Capture d\'écran prise le %s',
|
||||
'Add a screenshot' => 'Ajouter une capture d\'écran',
|
||||
'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => 'Copier/coller des images est uniquement supporté par Mozilla Firefox et Google Chrome.',
|
||||
'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Prenez une capture d\'écran et appuyez sur CTRL+V ou ⌘+V pour coller ici.',
|
||||
'Screenshot uploaded successfully.' => 'Capture d\'écran téléchargée avec succès.',
|
||||
'SEK - Swedish Krona' => 'SEK - Couronne suédoise',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -802,7 +802,6 @@ return array(
|
|||
'The budget line have been created successfully.' => 'Budgetlinjen har skapats.',
|
||||
'Unable to create the budget line.' => 'Kunde inte skapa budgetlinjen.',
|
||||
'Unable to remove this budget line.' => 'Kunde inte ta bort budgetlinjen.',
|
||||
'SEK - Swedish Krona' => 'SEK - Svensk Krona',
|
||||
'USD - US Dollar' => 'USD - Amerikanska Dollar',
|
||||
'Remaining' => 'Återstående',
|
||||
'Destination column' => 'Målkolumn',
|
||||
|
|
@ -854,4 +853,10 @@ return array(
|
|||
'Burndown chart for "%s"' => 'Burndown diagram för "%s"',
|
||||
'Burndown chart' => 'Burndown diagram',
|
||||
'This chart show the task complexity over the time (Work Remaining).' => 'Diagrammet visar uppgiftens svårighet över tid (återstående arbete).',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
'SEK - Swedish Krona' => 'SEK - Svensk Krona',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -853,4 +853,10 @@ return array(
|
|||
// 'Burndown chart for "%s"' => '',
|
||||
// 'Burndown chart' => '',
|
||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||
// 'Screenshot taken %s' => '',
|
||||
// 'Add a screenshot' => '',
|
||||
// 'Copy and paste images are only supported with Mozilla Firefox and Google Chrome.' => '',
|
||||
// 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '',
|
||||
// 'Screenshot uploaded successfully.' => '',
|
||||
// 'SEK - Swedish Krona' => '',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class Config extends Base
|
|||
'INR' => t('INR - Indian Rupee'),
|
||||
'JPY' => t('JPY - Japanese Yen'),
|
||||
'RSD' => t('RSD - Serbian dinar'),
|
||||
'SEK' => t('SEK - Swedish Krona'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -248,9 +248,9 @@ class File extends Base
|
|||
* Handle file upload
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $task_id Task id
|
||||
* @param string $form_name File form name
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $task_id Task id
|
||||
* @param string $form_name File form name
|
||||
* @return bool
|
||||
*/
|
||||
public function upload($project_id, $task_id, $form_name)
|
||||
|
|
@ -287,6 +287,38 @@ class File extends Base
|
|||
return count(array_unique($result)) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle screenshot upload
|
||||
*
|
||||
* @access public
|
||||
* @param integer $project_id Project id
|
||||
* @param integer $task_id Task id
|
||||
* @param string $blob Base64 encoded image
|
||||
* @return bool
|
||||
*/
|
||||
public function uploadScreenshot($project_id, $task_id, $blob)
|
||||
{
|
||||
$data = base64_decode($blob);
|
||||
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$original_filename = e('Screenshot taken %s', dt('%B %e, %Y at %k:%M %p', time()));
|
||||
$destination_filename = $this->generatePath($project_id, $task_id, $original_filename);
|
||||
|
||||
@mkdir(FILES_DIR.dirname($destination_filename), 0755, true);
|
||||
@file_put_contents(FILES_DIR.$destination_filename, $data);
|
||||
|
||||
return $this->create(
|
||||
$task_id,
|
||||
$original_filename,
|
||||
$destination_filename,
|
||||
true,
|
||||
strlen($data)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a jpeg thumbnail from an image (output directly the image)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<li><i class="fa fa-comment-o"></i> <?= $this->a(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
|
||||
<li><i class="fa fa-code-fork"></i> <?= $this->a(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
|
||||
<li><i class="fa fa-pencil-square-o"></i> <?= $this->a(t('Edit this task'), 'task', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
|
||||
<li><i class="fa fa-camera"></i> <?= $this->a(t('Add a screenshot'), 'board', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
|
||||
<li><i class="fa fa-close"></i> <?= $this->a(t('Close this task'), 'task', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'task-board-popover') ?></li>
|
||||
</ul>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<div class="page-header">
|
||||
<h2><?= t('Add a screenshot') ?></h2>
|
||||
</div>
|
||||
|
||||
<div id="screenshot-zone">
|
||||
<p id="screenshot-inner"><?= t('Take a screenshot and press CTRL+V or ⌘+V to paste here.') ?></p>
|
||||
</div>
|
||||
|
||||
<form action="<?= $this->u('file', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => $redirect)) ?>" method="post">
|
||||
<input type="hidden" name="screenshot"/>
|
||||
<?= $this->formCsrf() ?>
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||
<?= t('or') ?>
|
||||
<?= $this->a(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'close-popover') ?>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="alert alert-info"><?= t('Copy and paste images are only supported with Mozilla Firefox and Google Chrome.') ?></p>
|
||||
|
|
@ -36,6 +36,9 @@
|
|||
<li>
|
||||
<?= $this->a(t('Attach a document'), 'file', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||
</li>
|
||||
<li>
|
||||
<?= $this->a(t('Add a screenshot'), 'file', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||
</li>
|
||||
<li>
|
||||
<?= $this->a(t('Duplicate'), 'task', 'duplicate', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -769,7 +769,7 @@ nav .active a {
|
|||
|
||||
/* board table */
|
||||
#board-container {
|
||||
padding-bottom: 180px; /* Space to avoid dropdown menu truncated */
|
||||
padding-bottom: 200px; /* Space to avoid dropdown menu truncated */
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
|
|
@ -1083,17 +1083,21 @@ span.task-board-date-overdue {
|
|||
.task-link-closed {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.task-show-images {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.task-show-images li img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.task-show-images li .img_container {
|
||||
width: 250px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.task-show-images li {
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
|
|
@ -1102,20 +1106,44 @@ span.task-board-date-overdue {
|
|||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.task-show-images li p{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.task-show-images li:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.task-show-image-actions {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.task-show-file-table {
|
||||
width: auto;
|
||||
}
|
||||
/* comments */
|
||||
|
||||
/* screenshots */
|
||||
#screenshot-zone {
|
||||
position: relative;
|
||||
border: 2px dashed #ccc;
|
||||
width: 90%;
|
||||
height: 250px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#screenshot-inner {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 48%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#screenshot-zone.screenshot-pasted {
|
||||
border: 2px solid #333;
|
||||
}/* comments */
|
||||
.comment {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
/* board table */
|
||||
#board-container {
|
||||
padding-bottom: 180px; /* Space to avoid dropdown menu truncated */
|
||||
padding-bottom: 200px; /* Space to avoid dropdown menu truncated */
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -243,17 +243,21 @@ span.task-board-date-overdue {
|
|||
.task-link-closed {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.task-show-images {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.task-show-images li img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.task-show-images li .img_container {
|
||||
width: 250px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.task-show-images li {
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
|
|
@ -262,16 +266,41 @@ span.task-board-date-overdue {
|
|||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.task-show-images li p{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.task-show-images li:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.task-show-image-actions {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.task-show-file-table {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* screenshots */
|
||||
#screenshot-zone {
|
||||
position: relative;
|
||||
border: 2px dashed #ccc;
|
||||
width: 90%;
|
||||
height: 250px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#screenshot-inner {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 48%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#screenshot-zone.screenshot-pasted {
|
||||
border: 2px solid #333;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -263,6 +263,11 @@ var Kanboard = (function() {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Screenshot
|
||||
if (Kanboard.Exists("screenshot-zone")) {
|
||||
Kanboard.Screenshot.Init();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
Kanboard.Screenshot = (function() {
|
||||
|
||||
var pasteCatcher = null;
|
||||
|
||||
// Setup event listener and workarounds
|
||||
function init()
|
||||
{
|
||||
if (! window.Clipboard) {
|
||||
|
||||
// Create a contenteditable element
|
||||
pasteCatcher = document.createElement("div");
|
||||
pasteCatcher.setAttribute("contenteditable", "");
|
||||
pasteCatcher.style.opacity = 0;
|
||||
document.body.appendChild(pasteCatcher);
|
||||
|
||||
// Make sure it is always in focus
|
||||
pasteCatcher.focus();
|
||||
document.addEventListener("click", function() { pasteCatcher.focus(); });
|
||||
}
|
||||
|
||||
window.addEventListener("paste", pasteHandler);
|
||||
}
|
||||
|
||||
// Paste event callback
|
||||
function pasteHandler(e)
|
||||
{
|
||||
// Firefox doesn't have the property e.clipboardData.items (only Chrome)
|
||||
if (e.clipboardData && e.clipboardData.items) {
|
||||
|
||||
var items = e.clipboardData.items;
|
||||
|
||||
if (items) {
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
|
||||
// Find an image in pasted elements
|
||||
if (items[i].type.indexOf("image") !== -1) {
|
||||
|
||||
var blob = items[i].getAsFile();
|
||||
|
||||
// Get the image as base64 data
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(event) {
|
||||
createImage(event.target.result);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Handle Firefox
|
||||
setTimeout(checkInput, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the input in the paste catcher element
|
||||
function checkInput()
|
||||
{
|
||||
var child = pasteCatcher.childNodes[0];
|
||||
pasteCatcher.innerHTML = "";
|
||||
|
||||
if (child) {
|
||||
// If the user pastes an image, the src attribute
|
||||
// will represent the image as a base64 encoded string.
|
||||
if (child.tagName === "IMG") {
|
||||
createImage(child.src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new image from a given source
|
||||
function createImage(blob)
|
||||
{
|
||||
var pastedImage = new Image();
|
||||
pastedImage.src = blob;
|
||||
|
||||
// Send the image content to the form variable
|
||||
pastedImage.onload = function() {
|
||||
var sourceSplit = blob.split("base64,");
|
||||
var sourceString = sourceSplit[1];
|
||||
$("input[name=screenshot]").val(sourceString);
|
||||
};
|
||||
|
||||
document.getElementById("screenshot-inner").style.display = "none";
|
||||
document.getElementById("screenshot-zone").className = "screenshot-pasted";
|
||||
document.getElementById("screenshot-zone").appendChild(pastedImage);
|
||||
}
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
|
||||
if (Kanboard.Exists("screenshot-zone")) {
|
||||
init();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
Init: init
|
||||
};
|
||||
})();
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
Adding screenshots
|
||||
==================
|
||||
|
||||
You can copy and paste images directly in Kanboard to save time.
|
||||
These images are uploaded as attachments to the task.
|
||||
|
||||
This is especially useful for taking screenshots to describe an issue by example.
|
||||
|
||||
You can add screenshots directly from the board by clicking on the dropdown menu or in the task view page.
|
||||
|
||||

|
||||
|
||||
To add a new image, take your screenshot and paste with CTRL+V or Command+V:
|
||||
|
||||

|
||||
|
||||
On Mac OS X, you can use those shortcuts to take screenshots:
|
||||
|
||||
- Command-Control-Shift-3: Take a screenshot of the screen, and save it to the clipboard
|
||||
- Command-Control-Shift-4, then select an area: Take a screenshot of an area and save it to the clipboard
|
||||
- Command-Control-Shift-4, then space, then click a window: Take a screenshot of a window and save it to the clipboard
|
||||
|
||||
There are also several third-party applications that can be used to take screenshots with annotations and shapes.
|
||||
|
||||
Note: this feature **works only with Mozilla Firefox and Google Chrome**.
|
||||
If you use another browser, you have to upload an attachment manually.
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
app_css="base links title table form button alert tooltip header board task comment subtask markdown listing activity dashboard pagination popover confirm sidebar responsive dropdown"
|
||||
vendor_css="jquery-ui.min chosen.min fullcalendar.min font-awesome.min"
|
||||
|
||||
app_js="base board calendar analytic swimlane dashboard budget"
|
||||
app_js="base board calendar analytic swimlane dashboard budget screenshot"
|
||||
vendor_js="jquery-1.11.1.min jquery-ui.min jquery.ui.touch-punch.min chosen.jquery.min dropit.min moment.min fullcalendar.min mousetrap.min mousetrap-global-bind.min app.min"
|
||||
lang_js="da de es fi fr hu it ja pl pt-br ru sv th zh-cn tr"
|
||||
lang_js="da de es fi fr hu it ja nl pl pt-br ru sv th tr zh-cn"
|
||||
|
||||
function merge_css {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue