1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Various fixes, particularly on the revision update workflow.

This commit is contained in:
epriestley 2011-02-04 17:53:14 -08:00
parent 8b7755b834
commit 905870d793
26 changed files with 308 additions and 75 deletions

View file

@ -15,6 +15,9 @@ $package_spec = array(
'aphront-typeahead-control-css',
'phabricator-directory-css',
'phabricator-remarkup-css',
'syntax-highlighting-css',
),
'differential.pkg.css' => array(
'differential-core-view-css',
@ -22,6 +25,16 @@ $package_spec = array(
'differential-revision-detail-css',
'differential-revision-history-css',
'differential-table-of-contents-css',
'differential-revision-comment-css',
'differential-revision-add-comment-css',
'differential-revision-comment-list-css',
),
'differential.pkg.js' => array(
'javelin-behavior-differential-feedback-preview',
'javelin-behavior-differential-edit-inline-comments',
'javelin-behavior-differential-populate',
'javelin-behavior-differential-show-more',
'javelin-behavior-differential-diff-radios',
),
);

View file

@ -109,7 +109,7 @@ celerity_register_resource_map(array(
),
'differential-changeset-view-css' =>
array(
'uri' => '/res/4e0295a9/rsrc/css/application/differential/changeset-view.css',
'uri' => '/res/8b893b8e/rsrc/css/application/differential/changeset-view.css',
'type' => 'css',
'requires' =>
array(
@ -163,7 +163,7 @@ celerity_register_resource_map(array(
),
'differential-table-of-contents-css' =>
array(
'uri' => '/res/a4a7b2b5/rsrc/css/application/differential/table-of-contents.css',
'uri' => '/res/e68f6f05/rsrc/css/application/differential/table-of-contents.css',
'type' => 'css',
'requires' =>
array(
@ -190,7 +190,7 @@ celerity_register_resource_map(array(
),
'phabricator-core-css' =>
array(
'uri' => '/res/39ce37c2/rsrc/css/core/core.css',
'uri' => '/res/41c62455/rsrc/css/core/core.css',
'type' => 'css',
'requires' =>
array(
@ -255,7 +255,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-differential-diff-radios' =>
array(
'uri' => '/res/ea6b0062/rsrc/js/application/differential/behavior-diff-radios.js',
'uri' => '/res/fdeb3823/rsrc/js/application/differential/behavior-diff-radios.js',
'type' => 'js',
'requires' =>
array(
@ -275,7 +275,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-differential-populate' =>
array(
'uri' => '/res/f7efbf62/rsrc/js/application/differential/behavior-populate.js',
'uri' => '/res/a13dcd7e/rsrc/js/application/differential/behavior-populate.js',
'type' => 'js',
'requires' =>
array(
@ -349,7 +349,7 @@ celerity_register_resource_map(array(
),
'javelin-workflow-dev' =>
array(
'uri' => '/res/7e690e16/rsrc/js/javelin/workflow.dev.js',
'uri' => '/res/c6b17f93/rsrc/js/javelin/workflow.dev.js',
'type' => 'js',
'requires' =>
array(
@ -368,7 +368,7 @@ celerity_register_resource_map(array(
), array (
'packages' =>
array (
'1a33af6b' =>
'85861df3' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
@ -384,11 +384,13 @@ celerity_register_resource_map(array(
8 => 'aphront-tokenizer-control-css',
9 => 'aphront-typeahead-control-css',
10 => 'phabricator-directory-css',
11 => 'phabricator-remarkup-css',
12 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/1a33af6b/core.pkg.css',
'uri' => '/res/pkg/85861df3/core.pkg.css',
'type' => 'css',
),
'9d9c881c' =>
'86498b42' =>
array (
'name' => 'differential.pkg.css',
'symbols' =>
@ -398,28 +400,55 @@ celerity_register_resource_map(array(
2 => 'differential-revision-detail-css',
3 => 'differential-revision-history-css',
4 => 'differential-table-of-contents-css',
5 => 'differential-revision-comment-css',
6 => 'differential-revision-add-comment-css',
7 => 'differential-revision-comment-list-css',
),
'uri' => '/res/pkg/9d9c881c/differential.pkg.css',
'uri' => '/res/pkg/86498b42/differential.pkg.css',
'type' => 'css',
),
'30d594cf' =>
array (
'name' => 'differential.pkg.js',
'symbols' =>
array (
0 => 'javelin-behavior-differential-feedback-preview',
1 => 'javelin-behavior-differential-edit-inline-comments',
2 => 'javelin-behavior-differential-populate',
3 => 'javelin-behavior-differential-show-more',
4 => 'javelin-behavior-differential-diff-radios',
),
'uri' => '/res/pkg/30d594cf/differential.pkg.js',
'type' => 'js',
),
),
'reverse' =>
array (
'phabricator-core-css' => '1a33af6b',
'phabricator-core-buttons-css' => '1a33af6b',
'phabricator-standard-page-view' => '1a33af6b',
'aphront-dialog-view-css' => '1a33af6b',
'aphront-form-view-css' => '1a33af6b',
'aphront-panel-view-css' => '1a33af6b',
'aphront-side-nav-view-css' => '1a33af6b',
'aphront-table-view-css' => '1a33af6b',
'aphront-tokenizer-control-css' => '1a33af6b',
'aphront-typeahead-control-css' => '1a33af6b',
'phabricator-directory-css' => '1a33af6b',
'differential-core-view-css' => '9d9c881c',
'differential-changeset-view-css' => '9d9c881c',
'differential-revision-detail-css' => '9d9c881c',
'differential-revision-history-css' => '9d9c881c',
'differential-table-of-contents-css' => '9d9c881c',
'phabricator-core-css' => '85861df3',
'phabricator-core-buttons-css' => '85861df3',
'phabricator-standard-page-view' => '85861df3',
'aphront-dialog-view-css' => '85861df3',
'aphront-form-view-css' => '85861df3',
'aphront-panel-view-css' => '85861df3',
'aphront-side-nav-view-css' => '85861df3',
'aphront-table-view-css' => '85861df3',
'aphront-tokenizer-control-css' => '85861df3',
'aphront-typeahead-control-css' => '85861df3',
'phabricator-directory-css' => '85861df3',
'phabricator-remarkup-css' => '85861df3',
'syntax-highlighting-css' => '85861df3',
'differential-core-view-css' => '86498b42',
'differential-changeset-view-css' => '86498b42',
'differential-revision-detail-css' => '86498b42',
'differential-revision-history-css' => '86498b42',
'differential-table-of-contents-css' => '86498b42',
'differential-revision-comment-css' => '86498b42',
'differential-revision-add-comment-css' => '86498b42',
'differential-revision-comment-list-css' => '86498b42',
'javelin-behavior-differential-feedback-preview' => '30d594cf',
'javelin-behavior-differential-edit-inline-comments' => '30d594cf',
'javelin-behavior-differential-populate' => '30d594cf',
'javelin-behavior-differential-show-more' => '30d594cf',
'javelin-behavior-differential-diff-radios' => '30d594cf',
),
));

View file

@ -23,6 +23,7 @@ phutil_register_library_map(array(
'AphrontFileResponse' => 'aphront/response/file',
'AphrontFormCheckboxControl' => 'view/form/control/checkbox',
'AphrontFormControl' => 'view/form/control/base',
'AphrontFormDividerControl' => 'view/form/control/divider',
'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormMarkupControl' => 'view/form/control/markup',
'AphrontFormPasswordControl' => 'view/form/control/password',
@ -231,6 +232,7 @@ phutil_register_library_map(array(
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormMarkupControl' => 'AphrontFormControl',
'AphrontFormPasswordControl' => 'AphrontFormControl',

View file

@ -168,6 +168,7 @@ class AphrontDefaultApplicationConfiguration
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax()) {
$view = new PhabricatorStandardPageView();
$view->setRequest($request);
$view->appendChild(
'<div style="padding: 2em 0;">'.
$response->buildResponseString().

View file

@ -185,6 +185,7 @@ class DifferentialInlineCommentEditController extends DifferentialController {
return phutil_render_tag(
'textarea',
array(
'class' => 'differential-inline-comment-edit-textarea',
'name' => 'text',
),
$text);

View file

@ -133,6 +133,21 @@ class DifferentialRevisionEditController extends DifferentialController {
->setErrors($errors);
}
if ($diff && $revision->getID()) {
$form
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Comments')
->setName('comments')
->setCaption("Explain what's new in this diff.")
->setValue($request->getStr('comments')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'))
->appendChild(
id(new AphrontFormDividerControl()));
}
$form
->appendChild(
id(new AphrontFormTextAreaControl())
@ -190,7 +205,11 @@ class DifferentialRevisionEditController extends DifferentialController {
$panel = new AphrontPanelView();
if ($revision->getID()) {
$panel->setHeader('Edit Differential Revision');
if ($diff) {
$panel->setHeader('Update Differential Revision');
} else {
$panel->setHeader('Edit Differential Revision');
}
} else {
$panel->setHeader('Create New Differential Revision');
}

View file

@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'applications/differential/storage/diff');
phutil_require_module('phabricator', 'applications/differential/storage/revision');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/divider');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');

View file

@ -167,19 +167,24 @@ class DifferentialRevisionViewController extends DifferentialController {
$handles,
$revision->getCCPHIDs()));
$path = $diff->getSourcePath();
if ($path) {
$branch = $diff->getBranch() ? ' (' . $diff->getBranch() . ')' : '';
$host = $diff->getSourceMachine();
if ($host) {
$host .= ':';
}
$properties['Path'] = phutil_escape_html("{$host}{$path} {$branch}");
$host = $diff->getSourceMachine();
if ($host) {
$properties['Host'] = phutil_escape_html($host);
}
$path = $diff->getSourcePath();
if ($path) {
$branch = $diff->getBranch() ? ' ('.$diff->getBranch().')' : '';
$properties['Path'] = phutil_escape_html("{$path} {$branch}");
}
$properties['Lint'] = 'TODO';
$properties['Unit'] = 'TODO';
$lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff);
$lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff);
$properties['Lint'] = $lstar.' '.$lmsg;
$ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff);
$umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff);
$properties['Unit'] = $ustar.' '.$umsg;
return $properties;
}

View file

@ -331,10 +331,9 @@ class DifferentialRevisionEditor {
$feedback = null;
if ($diff) {
$changesets = $diff->loadChangesets();
// TODO: move to DifferentialFeedbackEditor
// TODO: This should probably be in DifferentialFeedbackEditor?
if (!$is_new) {
// TODO
// $feedback = $this->createFeedback();
$comment = $this->createComment();
}
if ($feedback) {
$mail[] = id(new DifferentialNewDiffMail(
@ -350,8 +349,7 @@ class DifferentialRevisionEditor {
// Save the changes we made above.
// TODO
// $diff->setDescription(substr($this->getComments(), 0, 80));
$diff->setDescription(substr($this->getComments(), 0, 80));
$diff->save();
// An updated diff should require review, as long as it's not committed
@ -574,20 +572,18 @@ class DifferentialRevisionEditor {
$conn_w->saveTransaction();
}
/*
protected function createFeedback() {
$revision = $this->getRevision();
$feedback = id(new DifferentialFeedback())
->setUserID($this->getActorPHID())
->setRevision($revision)
private function createComment() {
$revision_id = $this->revision->getID();
$comment = id(new DifferentialComment())
->setAuthorPHID($this->getActorPHID())
->setRevisionID($revision_id)
->setContent($this->getComments())
->setAction('update');
$comment->save();
$feedback->save();
return $feedback;
return $comment;
}
*/
}

View file

@ -9,6 +9,7 @@
phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus');
phutil_require_module('phabricator', 'applications/differential/mail/ccwelcome');
phutil_require_module('phabricator', 'applications/differential/mail/newdiff');
phutil_require_module('phabricator', 'applications/differential/storage/comment');
phutil_require_module('phabricator', 'applications/differential/storage/revision');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');

View file

@ -1029,7 +1029,7 @@ EOSYNTHETIC;
if (isset($this->old[$ii])) {
$o_num = $this->old[$ii]['line'];
$o_text = $this->oldRender[$ii];
$o_text = isset($this->oldRender[$ii]) ? $this->oldRender[$ii] : null;
$o_attr = null;
if ($this->old[$ii]['type']) {
if (empty($this->new[$ii])) {
@ -1046,7 +1046,7 @@ EOSYNTHETIC;
if (isset($this->new[$ii])) {
$n_num = $this->new[$ii]['line'];
$n_text = $this->newRender[$ii];
$n_text = isset($this->newRender[$ii]) ? $this->newRender[$ii] : null;
$n_attr = null;
if ($this->new[$ii]['type']) {
if (empty($this->old[$ii])) {

View file

@ -139,7 +139,7 @@ class DifferentialChangeset extends DifferentialDAO {
}
return implode("\n", $file);
}
public function getAnchorName() {
return substr(md5($this->getFilename()), 0, 8);
}

View file

@ -39,6 +39,8 @@ class DifferentialDiff extends DifferentialDAO {
protected $arcanistProject;
protected $creationMethod;
protected $description;
private $unsavedChangesets = array();
private $changesets;

View file

@ -21,7 +21,7 @@ class DifferentialChangesetListView extends AphrontView {
private $changesets = array();
private $editable;
private $revision;
private $vsMap;
private $vsMap = array();
public function setChangesets($changesets) {
$this->changesets = $changesets;

View file

@ -48,8 +48,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
'id' => null,
'desc' => 'Base',
'age' => null,
'lint' => null,
'unit' => null,
'obj' => null,
),
);
@ -58,10 +57,9 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$data[] = array(
'name' => 'Diff '.(++$seq),
'id' => $diff->getID(),
'desc' => 'TODO',//$diff->getDescription(),
'desc' => $diff->getDescription(),
'age' => $diff->getDateCreated(),
'lint' => $diff->getLintStatus(),
'unit' => $diff->getUnitStatus(),
'obj' => $diff,
);
}
@ -76,9 +74,6 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$name = phutil_escape_html($row['name']);
$id = phutil_escape_html($row['id']);
$lint = '*';
$unit = '*';
$old_class = null;
$new_class = null;
@ -122,8 +117,12 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$old = null;
}
$desc = 'TODO';
$age = '-';
$desc = phutil_escape_html($row['desc']);
if ($row['age']) {
$age = phabricator_format_timestamp($row['age']);
} else {
$age = null;
}
if (++$idx % 2) {
$class = ' class="alt"';
@ -131,6 +130,14 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$class = null;
}
if ($row['obj']) {
$lint = self::renderDiffLintStar($row['obj']);
$unit = self::renderDiffUnitStar($row['obj']);
} else {
$lint = null;
$unit = null;
}
$rows[] =
'<tr'.$class.'>'.
'<td class="revhistory-name">'.$name.'</td>'.
@ -161,7 +168,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
'<th>Diff</th>'.
'<th>ID</th>'.
'<th>Description</th>'.
'<th>Age</th>'.
'<th>Created</th>'.
'<th>Lint</th>'.
'<th>Unit</th>'.
'</tr>'.
@ -176,4 +183,79 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
'</form>'.
'</div>';
}
const STAR_NONE = 'none';
const STAR_OKAY = 'okay';
const STAR_WARN = 'warn';
const STAR_FAIL = 'fail';
const STAR_SKIP = 'skip';
public static function renderDiffLintStar(DifferentialDiff $diff) {
static $map = array(
DifferentialLintStatus::LINT_NONE => self::STAR_NONE,
DifferentialLintStatus::LINT_OKAY => self::STAR_OKAY,
DifferentialLintStatus::LINT_WARN => self::STAR_WARN,
DifferentialLintStatus::LINT_FAIL => self::STAR_FAIL,
DifferentialLintStatus::LINT_SKIP => self::STAR_SKIP,
);
$star = idx($map, $diff->getLintStatus(), self::STAR_FAIL);
return self::renderDiffStar($star);
}
public static function renderDiffUnitStar(DifferentialDiff $diff) {
static $map = array(
DifferentialUnitStatus::UNIT_NONE => self::STAR_NONE,
DifferentialUnitStatus::UNIT_OKAY => self::STAR_OKAY,
DifferentialUnitStatus::UNIT_WARN => self::STAR_WARN,
DifferentialUnitStatus::UNIT_FAIL => self::STAR_FAIL,
DifferentialUnitStatus::UNIT_SKIP => self::STAR_SKIP,
);
$star = idx($map, $diff->getUnitStatus(), self::STAR_FAIL);
return self::renderDiffStar($star);
}
public static function getDiffLintMessage(DifferentialDiff $diff) {
switch ($diff->getLintStatus()) {
case DifferentialLintStatus::LINT_NONE:
return 'No Linters Available';
case DifferentialLintStatus::LINT_OKAY:
return 'Lint OK';
case DifferentialLintStatus::LINT_WARN:
return 'Lint Warnings';
case DifferentialLintStatus::LINT_FAIL:
return 'Lint Errors';
case DifferentialLintStatus::LINT_SKIP:
return 'Lint Skipped';
}
return '???';
}
public static function getDiffUnitMessage(DifferentialDiff $diff) {
switch ($diff->getUnitStatus()) {
case DifferentialUnitStatus::UNIT_NONE:
return 'No Unit Test Coverage';
case DifferentialUnitStatus::UNIT_OKAY:
return 'Unit Tests OK';
case DifferentialUnitStatus::UNIT_WARN:
return 'Unit Test Warnings';
case DifferentialUnitStatus::UNIT_FAIL:
return 'Unit Test Errors';
case DifferentialUnitStatus::UNIT_SKIP:
return 'Unit Tests Skipped';
}
return '???';
}
private static function renderDiffStar($star) {
$class = 'diff-star-'.$star;
return
'<span class="'.$class.'">'.
"\xE2\x98\x85".
'</span>';
}
}

View file

@ -6,12 +6,16 @@
phutil_require_module('phabricator', 'applications/differential/constants/lintstatus');
phutil_require_module('phabricator', 'applications/differential/constants/unitstatus');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialRevisionUpdateHistoryView.php');

View file

@ -39,6 +39,7 @@ class PhabricatorDirectoryCategoryDeleteController
}
$dialog = new AphrontDialogView();
$dialog->setUser($request->getUser());
$dialog->setTitle('Really delete this category?');
$dialog->appendChild("Are you sure you want to delete this category?");
$dialog->addSubmitButton('Delete');

View file

@ -39,6 +39,7 @@ class PhabricatorDirectoryItemDeleteController
}
$dialog = new AphrontDialogView();
$dialog->setUser($request->getUser());
$dialog->setTitle('Really delete this item?');
$dialog->appendChild("Are you sure you want to delete this item?");
$dialog->addSubmitButton('Delete');

View file

@ -47,7 +47,8 @@ class PhabricatorXHProfProfileTopLevelView extends AphrontView {
$aggregated = array();
foreach ($flat as $call => $counters) {
$agg_call = reset(explode('@', $call, 2));
$parts = explode('@', $call, 2);
$agg_call = reset($parts);
if (empty($aggregated[$agg_call])) {
$aggregated[$agg_call] = $counters;
} else {

View file

@ -64,10 +64,13 @@ class AphrontDialogView extends AphrontView {
$buttons = array();
if ($this->submitButton) {
$buttons[] =
'<button name="__submit__">'.
phutil_escape_html($this->submitButton).
'</button>';
$buttons[] = phutil_render_tag(
'button',
array(
'name' => '__submit__',
'sigil' => '__default__',
),
phutil_escape_html($this->submitButton));
}
if ($this->cancelURI) {

View file

@ -0,0 +1,29 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class AphrontFormDividerControl extends AphrontFormControl {
protected function getCustomControlClass() {
return 'aphront-form-control-divider';
}
protected function renderInput() {
return '<hr />';
}
}

View file

@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'view/form/control/base');
phutil_require_source('AphrontFormDividerControl.php');

View file

@ -27,10 +27,10 @@ function phabricator_format_relative_time($duration) {
function phabricator_format_timestamp($epoch) {
$difference = (time() - $epoch);
if ($difference < 60 * 60) {
if ($difference < 60 * 60 * 24) {
return phabricator_format_relative_time($difference).' ago';
} else if (date('Y') == date('Y', $epoch)) {
return date('M jS, g:i A', $epoch);
return date('M j, g:i A', $epoch);
} else {
return date('F jS, Y', $epoch);
}

View file

@ -164,3 +164,9 @@
margin-left: 8px;
font-style: normal;
}
.differential-inline-comment-edit-textarea {
width: 100%;
height: 12em;
}

View file

@ -23,3 +23,25 @@
.differential-toc-file {
color: #444444;
}
.diff-star-none {
color: #666666;
}
.diff-star-okay {
color: #ff9700;
}
/* TODO: 'warn' and 'fail' are both red, but we can't make 'warn' yellow since
'okay' is a "gold star". */
.diff-star-warn {
color: #aa0000;
}
.diff-star-fail {
color: #aa0000;
}
.diff-star-skip {
color: #ff00aa;
}

View file

@ -161,7 +161,9 @@ JX.install('Workflow', {
var s = JX.$V.getScroll();
JX.$V((v.x - d.x) / 2, s.y + 100).setPos(this._root);
try {
JX.DOM.focus(JX.DOM.find(this._root, 'button', '__default__'));
try {
JX.DOM.focus(JX.DOM.find(this._root, 'button', '__default__'));
} catch (_ignored) {}
var inputs = JX.DOM.scry(this._root, 'input')
.concat(JX.DOM.scry(this._root, 'textarea'));
var miny = Number.POSITIVE_INFINITY;