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

AphrontPagerView and UIExamples.

This commit is contained in:
epriestley 2011-03-31 17:06:33 -07:00
parent d3766cad98
commit f76c3bbc22
15 changed files with 590 additions and 18 deletions

View file

@ -61,6 +61,15 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/css/aphront/headsup-action-list-view.css',
),
'aphront-pager-view-css' =>
array(
'uri' => '/res/73ec8cd5/rsrc/css/aphront/pager-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/pager-view.css',
),
'aphront-panel-view-css' =>
array(
'uri' => '/res/63672373/rsrc/css/aphront/panel-view.css',
@ -90,7 +99,7 @@ celerity_register_resource_map(array(
),
'aphront-table-view-css' =>
array(
'uri' => '/res/7bf17fb8/rsrc/css/aphront/table-view.css',
'uri' => '/res/03724b05/rsrc/css/aphront/table-view.css',
'type' => 'css',
'requires' =>
array(
@ -288,6 +297,15 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/css/application/people/profile.css',
),
'phabricator-ui-example-css' =>
array(
'uri' => '/res/b2593f53/rsrc/css/application/uiexample/example.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/uiexample/example.css',
),
'phabricator-core-buttons-css' =>
array(
'uri' => '/res/53b4f712/rsrc/css/core/buttons.css',
@ -455,7 +473,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-diffusion-pull-lastmodified' =>
array(
'uri' => '/res/1c95a58e/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
'uri' => '/res/6a5e7374/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
'type' => 'js',
'requires' =>
array(
@ -571,7 +589,7 @@ celerity_register_resource_map(array(
), array (
'packages' =>
array (
'aa9bbfd1' =>
'930fd839' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
@ -591,7 +609,7 @@ celerity_register_resource_map(array(
12 => 'phabricator-remarkup-css',
13 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/aa9bbfd1/core.pkg.css',
'uri' => '/res/pkg/930fd839/core.pkg.css',
'type' => 'css',
),
'76f3c1f8' =>
@ -638,20 +656,20 @@ celerity_register_resource_map(array(
),
'reverse' =>
array (
'phabricator-core-css' => 'aa9bbfd1',
'phabricator-core-buttons-css' => 'aa9bbfd1',
'phabricator-standard-page-view' => 'aa9bbfd1',
'aphront-dialog-view-css' => 'aa9bbfd1',
'aphront-form-view-css' => 'aa9bbfd1',
'aphront-panel-view-css' => 'aa9bbfd1',
'aphront-side-nav-view-css' => 'aa9bbfd1',
'aphront-table-view-css' => 'aa9bbfd1',
'aphront-crumbs-view-css' => 'aa9bbfd1',
'aphront-tokenizer-control-css' => 'aa9bbfd1',
'aphront-typeahead-control-css' => 'aa9bbfd1',
'phabricator-directory-css' => 'aa9bbfd1',
'phabricator-remarkup-css' => 'aa9bbfd1',
'syntax-highlighting-css' => 'aa9bbfd1',
'phabricator-core-css' => '930fd839',
'phabricator-core-buttons-css' => '930fd839',
'phabricator-standard-page-view' => '930fd839',
'aphront-dialog-view-css' => '930fd839',
'aphront-form-view-css' => '930fd839',
'aphront-panel-view-css' => '930fd839',
'aphront-side-nav-view-css' => '930fd839',
'aphront-table-view-css' => '930fd839',
'aphront-crumbs-view-css' => '930fd839',
'aphront-tokenizer-control-css' => '930fd839',
'aphront-typeahead-control-css' => '930fd839',
'phabricator-directory-css' => '930fd839',
'phabricator-remarkup-css' => '930fd839',
'syntax-highlighting-css' => '930fd839',
'differential-core-view-css' => '76f3c1f8',
'differential-changeset-view-css' => '76f3c1f8',
'differential-revision-detail-css' => '76f3c1f8',

View file

@ -41,6 +41,7 @@ phutil_register_library_map(array(
'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql',
'AphrontNullView' => 'view/null',
'AphrontPageView' => 'view/page/base',
'AphrontPagerView' => 'view/control/pager',
'AphrontPanelView' => 'view/layout/panel',
'AphrontQueryConnectionException' => 'storage/exception/connection',
'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost',
@ -385,6 +386,10 @@ phutil_register_library_map(array(
'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/iterator',
'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common',
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base',
'PhabricatorUIExample' => 'applications/uiexample/examples/base',
'PhabricatorUIExampleController' => 'applications/uiexample/controller/base',
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/render',
'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager',
'PhabricatorUser' => 'applications/people/storage/user',
'PhabricatorUserDAO' => 'applications/people/storage/base',
'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo',
@ -453,6 +458,7 @@ phutil_register_library_map(array(
'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontNullView' => 'AphrontView',
'AphrontPageView' => 'AphrontView',
'AphrontPagerView' => 'AphrontView',
'AphrontPanelView' => 'AphrontView',
'AphrontQueryConnectionException' => 'AphrontQueryException',
'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
@ -714,6 +720,9 @@ phutil_register_library_map(array(
'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO',
'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
'PhabricatorUIExampleController' => 'PhabricatorController',
'PhabricatorUIExampleRenderController' => 'PhabricatorUIExampleController',
'PhabricatorUIPagerExample' => 'PhabricatorUIExample',
'PhabricatorUser' => 'PhabricatorUserDAO',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO',

View file

@ -245,6 +245,12 @@ class AphrontDefaultApplicationConfiguration
'/preferences/' => array(
'$' => 'PhabricatorEditPreferencesController'
),
'/uiexample/' => array(
'$' => 'PhabricatorUIExampleRenderController',
'view/(?P<class>[^/]+)/$' => 'PhabricatorUIExampleRenderController',
),
);
}

View file

@ -0,0 +1,34 @@
<?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.
*/
abstract class PhabricatorUIExampleController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName('UI Examples');
$page->setBaseURI('/uiexample/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("\xE2\x8F\x9A");
$page->appendChild($view);
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/webpage');
phutil_require_module('phabricator', 'applications/base/controller/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUIExampleController.php');

View file

@ -0,0 +1,91 @@
<?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 PhabricatorUIExampleRenderController
extends PhabricatorUIExampleController {
private $class;
public function willProcessRequest(array $data) {
$this->class = idx($data, 'class');
}
public function processRequest() {
$classes = id(new PhutilSymbolLoader())
->setAncestorClass('PhabricatorUIExample')
->selectAndLoadSymbols();
$classes = ipull($classes, 'name', 'name');
$selected = null;
foreach ($classes as $class => $ignored) {
$classes[$class] = newv($class, array());
if ($this->class == $class) {
$selected = $class;
}
}
if (!$selected) {
reset($classes);
$selected = key($classes);
}
$nav = new AphrontSideNavView();
foreach ($classes as $class => $obj) {
$name = $obj->getName();
$nav->addNavItem(
phutil_render_tag(
'a',
array(
'href' => '/uiexample/view/'.$name.'/',
'class' => ($selected == $class)
? 'aphront-side-nav-selected'
: null,
),
phutil_escape_html($obj->getName())));
}
require_celerity_resource('phabricator-ui-example-css');
$example = $classes[$selected];
$example->setRequest($this->getRequest());
$nav->appendChild(
'<div class="phabricator-ui-example-header">'.
'<h1 class="phabricator-ui-example-name">'.
phutil_escape_html($example->getName()).
' ('.get_class($example).')'.
'</h1>'.
'<p class="phabricator-ui-example-description">'
.$example->getDescription().
'</p>'.
'</div>');
$nav->appendChild($example->renderExample());
return $this->buildStandardPageResponse(
$nav,
array(
'title' => 'UI Example',
));
}
}

View file

@ -0,0 +1,18 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/uiexample/controller/base');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'view/layout/sidenav');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'symbols');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUIExampleRenderController.php');

View file

@ -0,0 +1,36 @@
<?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.
*/
abstract class PhabricatorUIExample {
private $request;
public function setRequest($request) {
$this->request = $request;
return $this;
}
public function getRequest() {
return $this->request;
}
abstract public function getName();
abstract public function getDescription();
abstract public function renderExample();
}

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('PhabricatorUIExample.php');

View file

@ -0,0 +1,94 @@
<?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 PhabricatorUIPagerExample extends PhabricatorUIExample {
public function getName() {
return 'Pager';
}
public function getDescription() {
return 'Use <tt>AphrontPagerView</tt> to create a control which allows '.
'users to paginate through large amounts of content.';
}
public function renderExample() {
$request = $this->getRequest();
$offset = (int)$request->getInt('offset');
$page_size = 20;
$item_count = 173;
$rows = array();
for ($ii = $offset; $ii < min($item_count, $offset + $page_size); $ii++) {
$rows[] = array(
'Item #'.($ii + 1),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Item',
));
$panel = new AphrontPanelView();
$panel->appendChild($table);
$panel->appendChild(
'<p class="phabricator-ui-example-note">'.
'Use <tt>AphrontPagerView</tt> to render a pager element.'.
'</p>');
$pager = new AphrontPagerView();
$pager->setPageSize($page_size);
$pager->setOffset($offset);
$pager->setCount($item_count);
$pager->setURI($request->getRequestURI(), 'offset');
$panel->appendChild($pager);
$panel->appendChild(
'<p class="phabricator-ui-example-note">'.
'You can show more or fewer pages of surrounding context.'.
'</p>');
$many_pages_pager = new AphrontPagerView();
$many_pages_pager->setPageSize($page_size);
$many_pages_pager->setOffset($offset);
$many_pages_pager->setCount($item_count);
$many_pages_pager->setURI($request->getRequestURI(), 'offset');
$many_pages_pager->setSurroundingPages(7);
$panel->appendChild($many_pages_pager);
$panel->appendChild(
'<p class="phabricator-ui-example-note">'.
'When it is prohibitively expensive or complex to attain a complete '.
'count of the items, you can select one extra item and set '.
'<tt>hasMorePages(true)</tt> if it exists, creating an inexact pager.'.
'</p>');
$inexact_pager = new AphrontPagerView();
$inexact_pager->setPageSize($page_size);
$inexact_pager->setOffset($offset);
$inexact_pager->setHasMorePages($offset < ($item_count - $page_size));
$inexact_pager->setURI($request->getRequestURI(), 'offset');
$panel->appendChild($inexact_pager);
return $panel;
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/uiexample/examples/base');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_source('PhabricatorUIPagerExample.php');

View file

@ -0,0 +1,171 @@
<?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.
*/
final class AphrontPagerView extends AphrontView {
private $offset;
private $pageSize;
private $count;
private $hasMorePages;
private $uri;
private $pagingParameter;
private $surroundingPages = 2;
final public function setPageSize($page_size) {
$this->pageSize = max(1, $page_size);
return $this;
}
final public function setOffset($offset) {
$this->offset = max(0, $offset);
return $this;
}
final public function getOffset() {
return $this->offset;
}
final public function getPageSize() {
return $this->pageSize;
}
final public function setCount($count) {
$this->count = $count;
return $this;
}
final public function setHasMorePages($has_more) {
$this->hasMorePages = $has_more;
return $this;
}
final public function setURI(PhutilURI $uri, $paging_parameter) {
$this->uri = $uri;
$this->pagingParameter = $paging_parameter;
return $this;
}
final public function setSurroundingPages($pages) {
$this->surroundingPages = max(0, $pages);
return $this;
}
private function computeCount() {
if ($this->count !== null) {
return $this->count;
}
return $this->getOffset()
+ $this->getPageSize()
+ ($this->hasMorePages ? 1 : 0);
}
private function isExactCountKnown() {
return $this->count !== null;
}
public function render() {
require_celerity_resource('aphront-pager-view-css');
$page = (int)floor($this->getOffset() / $this->getPageSize());
$last = ((int)ceil($this->computeCount() / $this->getPageSize())) - 1;
$near = $this->surroundingPages;
$min = $page - $near;
$max = $page + $near;
// Limit the window size to no larger than the number of available pages.
if ($max - $min > $last) {
$max = $min + $last;
if ($max == $min) {
return '<div class="aphront-pager-view"></div>';
}
}
// Slide the window so it is entirely over displayable pages.
if ($min < 0) {
$max += 0 - $min;
$min += 0 - $min;
}
if ($max > $last) {
$min -= $max - $last;
$max -= $max - $last;
}
// Build up a list of <index, label, css-class> tuples which describe the
// links we'll display, then render them all at once.
$links = array();
if ($min > 0) {
$links[] = array(0, 'First', null);
}
if ($page > 0) {
$links[] = array($page - 1, 'Prev', null);
}
for ($ii = $min; $ii <= $max; $ii++) {
$links[] = array($ii, $ii + 1, ($ii == $page) ? 'current' : null);
}
if ($page < $last && $last > 0) {
$links[] = array($page + 1, 'Next', null);
}
if ($max < ($last - 1)) {
$links[] = array($last, 'Last', null);
}
$base_uri = $this->uri;
$parameter = $this->pagingParameter;
$page_size = $this->getPageSize();
// Convert tuples into rendered nodes.
$rendered_links = array();
foreach ($links as $link) {
list($index, $label, $class) = $link;
// Use a 1-based sequence for display so that the number in the URI is
// the same as the page number you're on.
if ($index == 0) {
// No need for the first page to say page=1.
$display_index = null;
} else {
$display_index = $index * $page_size;
}
$link = $base_uri->alter($parameter, $display_index);
$rendered_links[] = phutil_render_tag(
'a',
array(
'href' => $link,
'class' => $class,
),
$label);
}
return
'<div class="aphront-pager-view">'.
implode('', $rendered_links).
'</div>';
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phutil', 'markup');
phutil_require_source('AphrontPagerView.php');

View file

@ -0,0 +1,18 @@
/**
* @provides aphront-pager-view-css
*/
.aphront-pager-view {
clear: both;
text-align: right;
padding: 8px 4px 16px;
font-weight: bold;
}
.aphront-pager-view a {
padding: 2px 3px;
}
.aphront-pager-view a.current {
border-bottom: 2px solid;
}

View file

@ -0,0 +1,22 @@
/**
* @provides phabricator-ui-example-css
*/
.phabricator-ui-example-note {
padding: .5em;
margin: 2em 1em 0.5em;
background: #ffffdd;
border: 1px solid #f5e178;
}
.phabricator-ui-example-note tt {
font-weight: bold;
}
.phabricator-ui-example-header {
margin: 1em 2em 2em;
}
.phabricator-ui-example-description {
margin: 1em 0;
}