diff --git a/src/IDF/Form/IssueUpdate.php b/src/IDF/Form/IssueUpdate.php index b453b9a..9835bc3 100644 --- a/src/IDF/Form/IssueUpdate.php +++ b/src/IDF/Form/IssueUpdate.php @@ -69,11 +69,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate // case of someone allowing the upload path to be accessible // to everybody. for ($i=1;$i<4;$i++) { - $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; + $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; $this->fields['attachment'.$i] = new Pluf_Form_Field_File( array('required' => false, 'label' => __('Attach a file'), - 'move_function_params' => + 'move_function_params' => array('upload_path' => $upload_path, 'upload_path_create' => true, 'file_name' => $filename, @@ -102,6 +102,22 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate 'size' => 15, ), )); + + $relation_types = $extra['project']->getRelationsFromConfig(); + $this->fields['relation_type'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('This issue'), + 'initial' => $relation_types[0], + 'widget_attrs' => array('size' => 15), + )); + + $this->fields['relation_issue'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => null, + 'initial' => '', + 'widget_attrs' => array('size' => 10), + )); + $tags = $this->issue->get_tags_list(); for ($i=1;$i<7;$i++) { $initial = ''; diff --git a/src/IDF/Views/Issue.php b/src/IDF/Views/Issue.php index 7224347..21800ff 100644 --- a/src/IDF/Views/Issue.php +++ b/src/IDF/Views/Issue.php @@ -345,6 +345,7 @@ class IDF_Views_Issue 'form' => $form, 'page_title' => $title, 'preview' => $preview, + 'issue' => new IDF_Issue(), ), self::autoCompleteArrays($prj) ); @@ -651,22 +652,60 @@ class IDF_Views_Issue public function autoCompleteIssueList($request, $match) { $prj = $request->project; + $issue_id = !empty($match[2]) ? intval($match[2]) : 0; + $query = trim($request->REQUEST['q']); + $limit = !empty($request->REQUEST['limit']) ? intval($request->REQUEST['limit']) : 0; + $limit = max(10, $limit); + + $issues = array(); + + // empty search, return the most recently updated issues + if (empty($query)) { + $sql = new Pluf_SQL('project=%s', array($prj->id)); + $tmp = Pluf::factory('IDF_Issue')->getList(array( + 'filter' => $sql->gen(), + 'order' => 'modif_dtime DESC' + )); + $issues += $tmp->getArrayCopy(); + } + else { + // ID-based search + if (is_numeric($query)) { + $sql = new Pluf_SQL('project=%s AND id LIKE %s', array($prj->id, $query.'%')); + $tmp = Pluf::factory('IDF_Issue')->getList(array( + 'filter' => $sql->gen(), + 'order' => 'id ASC' + )); + $issues += $tmp->getArrayCopy(); + } + + // text-based search + $res = new Pluf_Search_ResultSet( + IDF_Search::mySearch($query, $prj, 'IDF_Issue') + ); + foreach ($res as $issue) + $issues[] = $issue; + } // Autocomplete from jQuery UI works with JSON, this old one still // expects a parsable string; since we'd need to bump jQuery beyond // 1.2.6 for this to use as well, we're trying to cope with the old format. // see http://www.learningjquery.com/2010/06/autocomplete-migration-guide - - $arr = array( - 'Fo|o' => 110, - 'Bar' => 111, - 'Baz' => 112, - ); - $out = ''; - foreach ($arr as $key => $val) + $ids = array(); + foreach ($issues as $issue) { - $out .= str_replace('|', '|', $key).'|'.$val."\n"; + if ($issue->id == $issue_id) + continue; + + if (in_array($issue->id, $ids)) + continue; + + if (--$limit < 0) + break; + + $out .= str_replace('|', '|', $issue->summary) .'|'.$issue->id."\n"; + $ids[] = $issue->id; } return new Pluf_HTTP_Response($out); diff --git a/src/IDF/conf/urls.php b/src/IDF/conf/urls.php index b218e95..642ace7 100644 --- a/src/IDF/conf/urls.php +++ b/src/IDF/conf/urls.php @@ -173,7 +173,7 @@ $ctl[] = array('regex' => '#^/watchlist/(\w+)$#', 'model' => 'IDF_Views_Issue', 'method' => 'forgeWatchList'); -$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/autocomplete/$#', +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/autocomplete/(\d*)$#', 'base' => $base, 'model' => 'IDF_Views_Issue', 'method' => 'autoCompleteIssueList'); diff --git a/src/IDF/templates/idf/issues/js-autocomplete.html b/src/IDF/templates/idf/issues/js-autocomplete.html index 24b27f8..8506783 100644 --- a/src/IDF/templates/idf/issues/js-autocomplete.html +++ b/src/IDF/templates/idf/issues/js-autocomplete.html @@ -64,11 +64,12 @@ return row.to; } }); - $("#id_relation_issue").autocomplete("{/literal}{url 'IDF_Views_Issue::autoCompleteIssueList', array($project.shortname)}{literal}", { + $("#id_relation_issue").autocomplete("{/literal}{url 'IDF_Views_Issue::autoCompleteIssueList', array($project.shortname, $issue.id)}{literal}", { minChars: 0, width: 310, matchContains: true, max: 10, + multiple: true, delay: 500, highlightItem: false, formatItem: function(row, i, max, term) { diff --git a/src/IDF/templates/idf/issues/view.html b/src/IDF/templates/idf/issues/view.html index 050460d..e27be87 100644 --- a/src/IDF/templates/idf/issues/view.html +++ b/src/IDF/templates/idf/issues/view.html @@ -120,6 +120,15 @@ +{$form.f.relation_type.labelTag}: + +{if $form.f.relation_type.errors}{$form.f.relation_type.fieldErrors}{/if} +{if $form.f.relation_issue.errors}{$form.f.relation_issue.fieldErrors}{/if} +{$form.f.relation_type|unsafe} +{$form.f.relation_issue|unsafe} + + + {$form.f.label1.labelTag}: {if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe}