@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update UI for PhortuneAccount

Summary: Primarily, this splits individual sections of the single account page into a more managable and robust sidenav for subscriptions, billing, and managers. The functionality on the subpages is light, but I expect to build on then in coming diffs. This also starts building out a more effective "status" area on the lead page.

Test Plan:
- Load up default account
- Make some edits
- Click on each of the new navigation items
- Verify links to "see all" work
- Test overdue and no payment states for status

{F4337317}

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D17589

+574 -194
+11 -1
src/__phutil_library_map__.php
··· 4319 4319 'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php', 4320 4320 'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php', 4321 4321 'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php', 4322 + 'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php', 4323 + 'PhortuneAccountBillingController' => 'applications/phortune/controller/account/PhortuneAccountBillingController.php', 4322 4324 'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php', 4323 4325 'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php', 4324 4326 'PhortuneAccountEditEngine' => 'applications/phortune/editor/PhortuneAccountEditEngine.php', 4325 4327 'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php', 4326 4328 'PhortuneAccountHasMemberEdgeType' => 'applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php', 4327 4329 'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php', 4330 + 'PhortuneAccountManagerController' => 'applications/phortune/controller/account/PhortuneAccountManagerController.php', 4328 4331 'PhortuneAccountNameTransaction' => 'applications/phortune/xaction/PhortuneAccountNameTransaction.php', 4329 4332 'PhortuneAccountPHIDType' => 'applications/phortune/phid/PhortuneAccountPHIDType.php', 4333 + 'PhortuneAccountProfileController' => 'applications/phortune/controller/account/PhortuneAccountProfileController.php', 4330 4334 'PhortuneAccountQuery' => 'applications/phortune/query/PhortuneAccountQuery.php', 4335 + 'PhortuneAccountSubscriptionController' => 'applications/phortune/controller/account/PhortuneAccountSubscriptionController.php', 4331 4336 'PhortuneAccountTransaction' => 'applications/phortune/storage/PhortuneAccountTransaction.php', 4332 4337 'PhortuneAccountTransactionQuery' => 'applications/phortune/query/PhortuneAccountTransactionQuery.php', 4333 4338 'PhortuneAccountTransactionType' => 'applications/phortune/xaction/PhortuneAccountTransactionType.php', ··· 9774 9779 'PhabricatorApplicationTransactionInterface', 9775 9780 'PhabricatorPolicyInterface', 9776 9781 ), 9782 + 'PhortuneAccountAddManagerController' => 'PhortuneController', 9783 + 'PhortuneAccountBillingController' => 'PhortuneAccountProfileController', 9777 9784 'PhortuneAccountChargeListController' => 'PhortuneController', 9778 9785 'PhortuneAccountEditController' => 'PhortuneController', 9779 9786 'PhortuneAccountEditEngine' => 'PhabricatorEditEngine', 9780 9787 'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor', 9781 9788 'PhortuneAccountHasMemberEdgeType' => 'PhabricatorEdgeType', 9782 9789 'PhortuneAccountListController' => 'PhortuneController', 9790 + 'PhortuneAccountManagerController' => 'PhortuneAccountProfileController', 9783 9791 'PhortuneAccountNameTransaction' => 'PhortuneAccountTransactionType', 9784 9792 'PhortuneAccountPHIDType' => 'PhabricatorPHIDType', 9793 + 'PhortuneAccountProfileController' => 'PhortuneController', 9785 9794 'PhortuneAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 9795 + 'PhortuneAccountSubscriptionController' => 'PhortuneAccountProfileController', 9786 9796 'PhortuneAccountTransaction' => 'PhabricatorModularTransaction', 9787 9797 'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 9788 9798 'PhortuneAccountTransactionType' => 'PhabricatorModularTransactionType', 9789 - 'PhortuneAccountViewController' => 'PhortuneController', 9799 + 'PhortuneAccountViewController' => 'PhortuneAccountProfileController', 9790 9800 'PhortuneAdHocCart' => 'PhortuneCartImplementation', 9791 9801 'PhortuneAdHocProduct' => 'PhortuneProductImplementation', 9792 9802 'PhortuneCart' => array(
+10
src/applications/phortune/application/PhabricatorPhortuneApplication.php
··· 69 69 '' => 'PhortuneAccountListController', 70 70 $this->getEditRoutePattern('edit/') 71 71 => 'PhortuneAccountEditController', 72 + 'edit/(?:(?P<id>\d+)/)?' => 'PhortuneAccountEditController', 73 + 'add/manager/(?:(?P<id>\d+)/)?' 74 + => 'PhortuneAccountAddManagerController', 75 + 'billing/(?:(?P<id>\d+)/)?' => 'PhortuneAccountBillingController', 76 + 'subscription/(?:(?P<id>\d+)/)?' 77 + => 'PhortuneAccountSubscriptionController', 78 + 'manager/' => array( 79 + '(?:(?P<id>\d+)/)?' => 'PhortuneAccountManagerController', 80 + 'add/(?:(?P<id>\d+)/)?' => 'PhortuneAccountAddManagerController', 81 + ), 72 82 ), 73 83 'product/' => array( 74 84 '' => 'PhortuneProductListController',
+75
src/applications/phortune/controller/account/PhortuneAccountAddManagerController.php
··· 1 + <?php 2 + 3 + final class PhortuneAccountAddManagerController extends PhortuneController { 4 + 5 + public function handleRequest(AphrontRequest $request) { 6 + $viewer = $request->getViewer(); 7 + $id = $request->getURIData('id'); 8 + 9 + $account = id(new PhortuneAccountQuery()) 10 + ->setViewer($viewer) 11 + ->withIDs(array($id)) 12 + ->requireCapabilities( 13 + array( 14 + PhabricatorPolicyCapability::CAN_VIEW, 15 + PhabricatorPolicyCapability::CAN_EDIT, 16 + )) 17 + ->executeOne(); 18 + if (!$account) { 19 + return new Aphront404Response(); 20 + } 21 + 22 + $v_managers = array(); 23 + $e_managers = null; 24 + $account_uri = $this->getApplicationURI("/account/manager/{$id}/"); 25 + 26 + if ($request->isFormPost()) { 27 + $xactions = array(); 28 + $v_managers = $request->getArr('managerPHIDs'); 29 + $type_edge = PhabricatorTransactions::TYPE_EDGE; 30 + 31 + $xactions[] = id(new PhortuneAccountTransaction()) 32 + ->setTransactionType($type_edge) 33 + ->setMetadataValue( 34 + 'edge:type', 35 + PhortuneAccountHasMemberEdgeType::EDGECONST) 36 + ->setNewValue( 37 + array( 38 + '+' => array_fuse($v_managers), 39 + )); 40 + 41 + $editor = id(new PhortuneAccountEditor()) 42 + ->setActor($viewer) 43 + ->setContentSourceFromRequest($request) 44 + ->setContinueOnNoEffect(true); 45 + 46 + try { 47 + $editor->applyTransactions($account, $xactions); 48 + 49 + return id(new AphrontRedirectResponse())->setURI($account_uri); 50 + } catch (PhabricatorApplicationTransactionValidationException $ex) { 51 + $validation_exception = $ex; 52 + $e_managers = $ex->getShortMessage($type_edge); 53 + } 54 + } 55 + 56 + $form = id(new AphrontFormView()) 57 + ->setUser($viewer) 58 + ->appendControl( 59 + id(new AphrontFormTokenizerControl()) 60 + ->setDatasource(new PhabricatorPeopleDatasource()) 61 + ->setLabel(pht('Managers')) 62 + ->setName('managerPHIDs') 63 + ->setValue($v_managers) 64 + ->setError($e_managers)); 65 + 66 + return $this->newDialog() 67 + ->setTitle(pht('Add New Manager')) 68 + ->appendForm($form) 69 + ->setWidth(AphrontDialogView::WIDTH_FORM) 70 + ->addCancelButton($account_uri) 71 + ->addSubmitButton(pht('Add Manager')); 72 + 73 + } 74 + 75 + }
+178
src/applications/phortune/controller/account/PhortuneAccountBillingController.php
··· 1 + <?php 2 + 3 + final class PhortuneAccountBillingController 4 + extends PhortuneAccountProfileController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + 9 + // TODO: Currently, you must be able to edit an account to view the detail 10 + // page, because the account must be broadly visible so merchants can 11 + // process orders but merchants should not be able to see all the details 12 + // of an account. Ideally this page should be visible to merchants, too, 13 + // just with less information. 14 + $can_edit = true; 15 + 16 + $account = id(new PhortuneAccountQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($request->getURIData('id'))) 19 + ->requireCapabilities( 20 + array( 21 + PhabricatorPolicyCapability::CAN_VIEW, 22 + PhabricatorPolicyCapability::CAN_EDIT, 23 + )) 24 + ->executeOne(); 25 + if (!$account) { 26 + return new Aphront404Response(); 27 + } 28 + 29 + $this->setAccount($account); 30 + $title = $account->getName(); 31 + 32 + $crumbs = $this->buildApplicationCrumbs(); 33 + $crumbs->addTextCrumb(pht('Billing')); 34 + 35 + $header = $this->buildHeaderView(); 36 + $methods = $this->buildPaymentMethodsSection($account); 37 + $charge_history = $this->buildChargeHistorySection($account); 38 + 39 + $view = id(new PHUITwoColumnView()) 40 + ->setHeader($header) 41 + ->setFooter(array( 42 + $methods, 43 + $charge_history, 44 + )); 45 + 46 + $navigation = $this->buildSideNavView('billing'); 47 + 48 + return $this->newPage() 49 + ->setTitle($title) 50 + ->setCrumbs($crumbs) 51 + ->setNavigation($navigation) 52 + ->appendChild($view); 53 + 54 + } 55 + 56 + private function buildPaymentMethodsSection(PhortuneAccount $account) { 57 + $viewer = $this->getViewer(); 58 + 59 + $can_edit = PhabricatorPolicyFilter::hasCapability( 60 + $viewer, 61 + $account, 62 + PhabricatorPolicyCapability::CAN_EDIT); 63 + 64 + $id = $account->getID(); 65 + 66 + // TODO: Allow adding a card here directly 67 + $add = id(new PHUIButtonView()) 68 + ->setTag('a') 69 + ->setText(pht('New Payment Method')) 70 + ->setIcon('fa-plus') 71 + ->setHref($this->getApplicationURI("{$id}/card/new/")); 72 + 73 + $header = id(new PHUIHeaderView()) 74 + ->setHeader(pht('Payment Methods')); 75 + 76 + $list = id(new PHUIObjectItemListView()) 77 + ->setUser($viewer) 78 + ->setFlush(true) 79 + ->setNoDataString( 80 + pht('No payment methods associated with this account.')); 81 + 82 + $methods = id(new PhortunePaymentMethodQuery()) 83 + ->setViewer($viewer) 84 + ->withAccountPHIDs(array($account->getPHID())) 85 + ->withStatuses( 86 + array( 87 + PhortunePaymentMethod::STATUS_ACTIVE, 88 + )) 89 + ->execute(); 90 + 91 + foreach ($methods as $method) { 92 + $id = $method->getID(); 93 + 94 + $item = new PHUIObjectItemView(); 95 + $item->setHeader($method->getFullDisplayName()); 96 + 97 + switch ($method->getStatus()) { 98 + case PhortunePaymentMethod::STATUS_ACTIVE: 99 + $item->setStatusIcon('fa-check green'); 100 + 101 + $disable_uri = $this->getApplicationURI('card/'.$id.'/disable/'); 102 + $item->addAction( 103 + id(new PHUIListItemView()) 104 + ->setIcon('fa-times') 105 + ->setHref($disable_uri) 106 + ->setDisabled(!$can_edit) 107 + ->setWorkflow(true)); 108 + break; 109 + case PhortunePaymentMethod::STATUS_DISABLED: 110 + $item->setStatusIcon('fa-ban lightbluetext'); 111 + $item->setDisabled(true); 112 + break; 113 + } 114 + 115 + $provider = $method->buildPaymentProvider(); 116 + $item->addAttribute($provider->getPaymentMethodProviderDescription()); 117 + 118 + $edit_uri = $this->getApplicationURI('card/'.$id.'/edit/'); 119 + 120 + $item->addAction( 121 + id(new PHUIListItemView()) 122 + ->setIcon('fa-pencil') 123 + ->setHref($edit_uri) 124 + ->setDisabled(!$can_edit) 125 + ->setWorkflow(!$can_edit)); 126 + 127 + $list->addItem($item); 128 + } 129 + 130 + return id(new PHUIObjectBoxView()) 131 + ->setHeader($header) 132 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 133 + ->setObjectList($list); 134 + } 135 + 136 + private function buildChargeHistorySection(PhortuneAccount $account) { 137 + $viewer = $this->getViewer(); 138 + 139 + $charges = id(new PhortuneChargeQuery()) 140 + ->setViewer($viewer) 141 + ->withAccountPHIDs(array($account->getPHID())) 142 + ->needCarts(true) 143 + ->setLimit(10) 144 + ->execute(); 145 + 146 + $phids = array(); 147 + foreach ($charges as $charge) { 148 + $phids[] = $charge->getProviderPHID(); 149 + $phids[] = $charge->getCartPHID(); 150 + $phids[] = $charge->getMerchantPHID(); 151 + $phids[] = $charge->getPaymentMethodPHID(); 152 + } 153 + 154 + $handles = $this->loadViewerHandles($phids); 155 + 156 + $charges_uri = $this->getApplicationURI($account->getID().'/charge/'); 157 + 158 + $table = id(new PhortuneChargeTableView()) 159 + ->setUser($viewer) 160 + ->setCharges($charges) 161 + ->setHandles($handles); 162 + 163 + $header = id(new PHUIHeaderView()) 164 + ->setHeader(pht('Charge History')) 165 + ->addActionLink( 166 + id(new PHUIButtonView()) 167 + ->setTag('a') 168 + ->setIcon('fa-list') 169 + ->setHref($charges_uri) 170 + ->setText(pht('View All Charges'))); 171 + 172 + return id(new PHUIObjectBoxView()) 173 + ->setHeader($header) 174 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 175 + ->setTable($table); 176 + } 177 + 178 + }
+101
src/applications/phortune/controller/account/PhortuneAccountManagerController.php
··· 1 + <?php 2 + 3 + final class PhortuneAccountManagerController 4 + extends PhortuneAccountProfileController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + 9 + // TODO: Currently, you must be able to edit an account to view the detail 10 + // page, because the account must be broadly visible so merchants can 11 + // process orders but merchants should not be able to see all the details 12 + // of an account. Ideally this page should be visible to merchants, too, 13 + // just with less information. 14 + $can_edit = true; 15 + 16 + $account = id(new PhortuneAccountQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($request->getURIData('id'))) 19 + ->requireCapabilities( 20 + array( 21 + PhabricatorPolicyCapability::CAN_VIEW, 22 + PhabricatorPolicyCapability::CAN_EDIT, 23 + )) 24 + ->executeOne(); 25 + if (!$account) { 26 + return new Aphront404Response(); 27 + } 28 + 29 + $this->setAccount($account); 30 + $title = $account->getName(); 31 + 32 + $crumbs = $this->buildApplicationCrumbs(); 33 + $crumbs->addTextCrumb(pht('Managers')); 34 + 35 + $header = $this->buildHeaderView(); 36 + $members = $this->buildMembersSection($account); 37 + 38 + $view = id(new PHUITwoColumnView()) 39 + ->setHeader($header) 40 + ->setFooter(array( 41 + $members, 42 + )); 43 + 44 + $navigation = $this->buildSideNavView('managers'); 45 + 46 + return $this->newPage() 47 + ->setTitle($title) 48 + ->setCrumbs($crumbs) 49 + ->setNavigation($navigation) 50 + ->appendChild($view); 51 + 52 + } 53 + 54 + private function buildMembersSection(PhortuneAccount $account) { 55 + $viewer = $this->getViewer(); 56 + 57 + $can_edit = PhabricatorPolicyFilter::hasCapability( 58 + $viewer, 59 + $account, 60 + PhabricatorPolicyCapability::CAN_EDIT); 61 + 62 + $id = $account->getID(); 63 + 64 + $add = id(new PHUIButtonView()) 65 + ->setTag('a') 66 + ->setText(pht('New Manager')) 67 + ->setIcon('fa-plus') 68 + ->setWorkflow(true) 69 + ->setHref("/phortune/account/manager/add/{$id}/"); 70 + 71 + $header = id(new PHUIHeaderView()) 72 + ->setHeader(pht('Account Managers')) 73 + ->addActionLink($add); 74 + 75 + $list = id(new PHUIObjectItemListView()) 76 + ->setUser($viewer); 77 + 78 + $member_phids = $account->getMemberPHIDs(); 79 + $handles = $viewer->loadHandles($member_phids); 80 + 81 + foreach ($member_phids as $member_phid) { 82 + $image_uri = $handles[$member_phid]->getImageURI(); 83 + $image_href = $handles[$member_phid]->getURI(); 84 + $person = $handles[$member_phid]; 85 + 86 + $member = id(new PHUIObjectItemView()) 87 + ->setImageURI($image_uri) 88 + ->setHref($image_href) 89 + ->setHeader($person->getFullName()) 90 + ->addAttribute(pht('Account Manager')); 91 + 92 + $list->addItem($member); 93 + } 94 + 95 + return id(new PHUIObjectBoxView()) 96 + ->setHeader($header) 97 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 98 + ->setObjectList($list); 99 + } 100 + 101 + }
+84
src/applications/phortune/controller/account/PhortuneAccountProfileController.php
··· 1 + <?php 2 + 3 + abstract class PhortuneAccountProfileController 4 + extends PhortuneController { 5 + 6 + private $account; 7 + 8 + public function setAccount(PhortuneAccount $account) { 9 + $this->account = $account; 10 + return $this; 11 + } 12 + 13 + public function getAccount() { 14 + return $this->account; 15 + } 16 + 17 + public function buildApplicationMenu() { 18 + return $this->buildSideNavView()->getMenu(); 19 + } 20 + 21 + protected function buildHeaderView() { 22 + $viewer = $this->getViewer(); 23 + $account = $this->getAccount(); 24 + $title = $account->getName(); 25 + 26 + $header = id(new PHUIHeaderView()) 27 + ->setUser($viewer) 28 + ->setHeader($title) 29 + ->setHeaderIcon('fa-user-circle'); 30 + 31 + return $header; 32 + } 33 + 34 + protected function buildApplicationCrumbs() { 35 + $account = $this->getAccount(); 36 + $id = $account->getID(); 37 + $account_uri = $this->getApplicationURI("/{$id}/"); 38 + 39 + $crumbs = parent::buildApplicationCrumbs(); 40 + $crumbs->addTextCrumb($account->getName(), $account_uri); 41 + $crumbs->setBorder(true); 42 + return $crumbs; 43 + } 44 + 45 + protected function buildSideNavView($filter = null) { 46 + $viewer = $this->getViewer(); 47 + $account = $this->getAccount(); 48 + $id = $account->getID(); 49 + 50 + $nav = id(new AphrontSideNavFilterView()) 51 + ->setBaseURI(new PhutilURI($this->getApplicationURI())); 52 + 53 + $nav->addLabel(pht('Account')); 54 + 55 + $nav->addFilter( 56 + 'overview', 57 + pht('Overview'), 58 + $this->getApplicationURI("/{$id}/"), 59 + 'fa-user-circle'); 60 + 61 + $nav->addFilter( 62 + 'subscriptions', 63 + pht('Subscriptions'), 64 + $this->getApplicationURI("/account/subscription/{$id}/"), 65 + 'fa-retweet'); 66 + 67 + $nav->addFilter( 68 + 'billing', 69 + pht('Billing / History'), 70 + $this->getApplicationURI("/account/billing/{$id}/"), 71 + 'fa-credit-card'); 72 + 73 + $nav->addFilter( 74 + 'managers', 75 + pht('Managers'), 76 + $this->getApplicationURI("/account/manager/{$id}/"), 77 + 'fa-group'); 78 + 79 + $nav->selectFilter($filter); 80 + 81 + return $nav; 82 + } 83 + 84 + }
+79
src/applications/phortune/controller/account/PhortuneAccountSubscriptionController.php
··· 1 + <?php 2 + 3 + final class PhortuneAccountSubscriptionController 4 + extends PhortuneAccountProfileController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + 9 + // TODO: Currently, you must be able to edit an account to view the detail 10 + // page, because the account must be broadly visible so merchants can 11 + // process orders but merchants should not be able to see all the details 12 + // of an account. Ideally this page should be visible to merchants, too, 13 + // just with less information. 14 + $can_edit = true; 15 + 16 + $account = id(new PhortuneAccountQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($request->getURIData('id'))) 19 + ->requireCapabilities( 20 + array( 21 + PhabricatorPolicyCapability::CAN_VIEW, 22 + PhabricatorPolicyCapability::CAN_EDIT, 23 + )) 24 + ->executeOne(); 25 + if (!$account) { 26 + return new Aphront404Response(); 27 + } 28 + 29 + $this->setAccount($account); 30 + $title = $account->getName(); 31 + 32 + $crumbs = $this->buildApplicationCrumbs(); 33 + $crumbs->addTextCrumb(pht('Subscriptions')); 34 + 35 + $header = $this->buildHeaderView(); 36 + $subscriptions = $this->buildSubscriptionsSection($account); 37 + 38 + $view = id(new PHUITwoColumnView()) 39 + ->setHeader($header) 40 + ->setFooter(array( 41 + $subscriptions, 42 + )); 43 + 44 + $navigation = $this->buildSideNavView('subscriptions'); 45 + 46 + return $this->newPage() 47 + ->setTitle($title) 48 + ->setCrumbs($crumbs) 49 + ->setNavigation($navigation) 50 + ->appendChild($view); 51 + 52 + } 53 + 54 + private function buildSubscriptionsSection(PhortuneAccount $account) { 55 + $viewer = $this->getViewer(); 56 + 57 + $subscriptions = id(new PhortuneSubscriptionQuery()) 58 + ->setViewer($viewer) 59 + ->withAccountPHIDs(array($account->getPHID())) 60 + ->setLimit(25) 61 + ->execute(); 62 + 63 + $handles = $this->loadViewerHandles(mpull($subscriptions, 'getPHID')); 64 + 65 + $table = id(new PhortuneSubscriptionTableView()) 66 + ->setUser($viewer) 67 + ->setHandles($handles) 68 + ->setSubscriptions($subscriptions); 69 + 70 + $header = id(new PHUIHeaderView()) 71 + ->setHeader(pht('Subscriptions')); 72 + 73 + return id(new PHUIObjectBoxView()) 74 + ->setHeader($header) 75 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 76 + ->setTable($table); 77 + } 78 + 79 + }
+35 -193
src/applications/phortune/controller/account/PhortuneAccountViewController.php
··· 1 1 <?php 2 2 3 - final class PhortuneAccountViewController extends PhortuneController { 3 + final class PhortuneAccountViewController 4 + extends PhortuneAccountProfileController { 4 5 5 6 public function handleRequest(AphrontRequest $request) { 6 7 $viewer = $this->getViewer(); 8 + $id = $request->getURIData('accountID'); 7 9 8 10 // TODO: Currently, you must be able to edit an account to view the detail 9 11 // page, because the account must be broadly visible so merchants can ··· 14 16 15 17 $account = id(new PhortuneAccountQuery()) 16 18 ->setViewer($viewer) 17 - ->withIDs(array($request->getURIData('accountID'))) 19 + ->withIDs(array($id)) 18 20 ->requireCapabilities( 19 21 array( 20 22 PhabricatorPolicyCapability::CAN_VIEW, ··· 25 27 return new Aphront404Response(); 26 28 } 27 29 30 + $this->setAccount($account); 28 31 $title = $account->getName(); 29 32 30 33 $invoices = id(new PhortuneCartQuery()) ··· 35 38 ->execute(); 36 39 37 40 $crumbs = $this->buildApplicationCrumbs(); 38 - $this->addAccountCrumb($crumbs, $account, $link = false); 39 41 $crumbs->setBorder(true); 40 42 41 - $header = id(new PHUIHeaderView()) 42 - ->setHeader($title) 43 - ->setHeaderIcon('fa-credit-card'); 43 + $header = $this->buildHeaderView(); 44 44 45 - $curtain = $this->buildCurtainView($account, $invoices); 45 + $curtain = $this->buildCurtainView($account); 46 + $status = $this->buildStatusView($account, $invoices); 46 47 $invoices = $this->buildInvoicesSection($account, $invoices); 47 48 $purchase_history = $this->buildPurchaseHistorySection($account); 48 - $charge_history = $this->buildChargeHistorySection($account); 49 - $subscriptions = $this->buildSubscriptionsSection($account); 50 - $payment_methods = $this->buildPaymentMethodsSection($account); 51 49 52 50 $timeline = $this->buildTransactionTimeline( 53 51 $account, ··· 58 56 ->setHeader($header) 59 57 ->setCurtain($curtain) 60 58 ->setMainColumn(array( 59 + $status, 61 60 $invoices, 62 61 $purchase_history, 63 - $charge_history, 64 - $subscriptions, 65 - $payment_methods, 66 62 $timeline, 67 63 )); 68 64 65 + $navigation = $this->buildSideNavView('overview'); 66 + 69 67 return $this->newPage() 70 68 ->setTitle($title) 71 69 ->setCrumbs($crumbs) 70 + ->setNavigation($navigation) 72 71 ->appendChild($view); 73 72 74 73 } 75 74 76 - private function buildCurtainView(PhortuneAccount $account, $invoices) { 75 + private function buildStatusView(PhortuneAccount $account, $invoices) { 76 + $status_items = $this->getStatusItemsForAccount($account, $invoices); 77 + $view = array(); 78 + foreach ($status_items as $item) { 79 + $view[] = id(new PHUIInfoView()) 80 + ->setSeverity(idx($item, 'severity')) 81 + ->appendChild(idx($item, 'note')); 82 + } 83 + return $view; 84 + } 85 + 86 + private function buildCurtainView(PhortuneAccount $account) { 77 87 $viewer = $this->getViewer(); 78 88 79 89 $can_edit = PhabricatorPolicyFilter::hasCapability( ··· 92 102 ->setDisabled(!$can_edit) 93 103 ->setWorkflow(!$can_edit)); 94 104 95 - $status_items = $this->getStatusItemsForAccount($account, $invoices); 96 - $status_view = new PHUIStatusListView(); 97 - foreach ($status_items as $item) { 98 - $status_view->addItem( 99 - id(new PHUIStatusItemView()) 100 - ->setIcon( 101 - idx($item, 'icon'), 102 - idx($item, 'color'), 103 - idx($item, 'label')) 104 - ->setTarget(idx($item, 'target')) 105 - ->setNote(idx($item, 'note'))); 106 - } 107 - 108 105 $member_phids = $account->getMemberPHIDs(); 109 106 $handles = $viewer->loadHandles($member_phids); 110 107 ··· 125 122 } 126 123 127 124 $curtain->newPanel() 128 - ->setHeaderText(pht('Status')) 129 - ->appendChild($status_view); 130 - 131 - $curtain->newPanel() 132 125 ->setHeaderText(pht('Managers')) 133 126 ->appendChild($member_list); 134 127 135 128 return $curtain; 136 129 } 137 130 138 - private function buildPaymentMethodsSection(PhortuneAccount $account) { 139 - $viewer = $this->getViewer(); 140 - 141 - $can_edit = PhabricatorPolicyFilter::hasCapability( 142 - $viewer, 143 - $account, 144 - PhabricatorPolicyCapability::CAN_EDIT); 145 - 146 - $id = $account->getID(); 147 - 148 - $header = id(new PHUIHeaderView()) 149 - ->setHeader(pht('Payment Methods')); 150 - 151 - $list = id(new PHUIObjectItemListView()) 152 - ->setUser($viewer) 153 - ->setFlush(true) 154 - ->setNoDataString( 155 - pht('No payment methods associated with this account.')); 156 - 157 - $methods = id(new PhortunePaymentMethodQuery()) 158 - ->setViewer($viewer) 159 - ->withAccountPHIDs(array($account->getPHID())) 160 - ->withStatuses( 161 - array( 162 - PhortunePaymentMethod::STATUS_ACTIVE, 163 - )) 164 - ->execute(); 165 - 166 - foreach ($methods as $method) { 167 - $id = $method->getID(); 168 - 169 - $item = new PHUIObjectItemView(); 170 - $item->setHeader($method->getFullDisplayName()); 171 - 172 - switch ($method->getStatus()) { 173 - case PhortunePaymentMethod::STATUS_ACTIVE: 174 - $item->setStatusIcon('fa-check green'); 175 - 176 - $disable_uri = $this->getApplicationURI('card/'.$id.'/disable/'); 177 - $item->addAction( 178 - id(new PHUIListItemView()) 179 - ->setIcon('fa-times') 180 - ->setHref($disable_uri) 181 - ->setDisabled(!$can_edit) 182 - ->setWorkflow(true)); 183 - break; 184 - case PhortunePaymentMethod::STATUS_DISABLED: 185 - $item->setStatusIcon('fa-ban lightbluetext'); 186 - $item->setDisabled(true); 187 - break; 188 - } 189 - 190 - $provider = $method->buildPaymentProvider(); 191 - $item->addAttribute($provider->getPaymentMethodProviderDescription()); 192 - 193 - $edit_uri = $this->getApplicationURI('card/'.$id.'/edit/'); 194 - 195 - $item->addAction( 196 - id(new PHUIListItemView()) 197 - ->setIcon('fa-pencil') 198 - ->setHref($edit_uri) 199 - ->setDisabled(!$can_edit) 200 - ->setWorkflow(!$can_edit)); 201 - 202 - $list->addItem($item); 203 - } 204 - 205 - return id(new PHUIObjectBoxView()) 206 - ->setHeader($header) 207 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 208 - ->setObjectList($list); 209 - } 210 - 211 131 private function buildInvoicesSection( 212 132 PhortuneAccount $account, 213 133 array $carts) { ··· 289 209 ->setTable($table); 290 210 } 291 211 292 - private function buildChargeHistorySection(PhortuneAccount $account) { 293 - $viewer = $this->getViewer(); 294 - 295 - $charges = id(new PhortuneChargeQuery()) 296 - ->setViewer($viewer) 297 - ->withAccountPHIDs(array($account->getPHID())) 298 - ->needCarts(true) 299 - ->setLimit(10) 300 - ->execute(); 301 - 302 - $phids = array(); 303 - foreach ($charges as $charge) { 304 - $phids[] = $charge->getProviderPHID(); 305 - $phids[] = $charge->getCartPHID(); 306 - $phids[] = $charge->getMerchantPHID(); 307 - $phids[] = $charge->getPaymentMethodPHID(); 308 - } 309 - 310 - $handles = $this->loadViewerHandles($phids); 311 - 312 - $charges_uri = $this->getApplicationURI($account->getID().'/charge/'); 313 - 314 - $table = id(new PhortuneChargeTableView()) 315 - ->setUser($viewer) 316 - ->setCharges($charges) 317 - ->setHandles($handles); 318 - 319 - $header = id(new PHUIHeaderView()) 320 - ->setHeader(pht('Recent Charges')) 321 - ->addActionLink( 322 - id(new PHUIButtonView()) 323 - ->setTag('a') 324 - ->setIcon('fa-list') 325 - ->setHref($charges_uri) 326 - ->setText(pht('View All Charges'))); 327 - 328 - return id(new PHUIObjectBoxView()) 329 - ->setHeader($header) 330 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 331 - ->setTable($table); 332 - } 333 - 334 - private function buildSubscriptionsSection(PhortuneAccount $account) { 335 - $viewer = $this->getViewer(); 336 - 337 - $subscriptions = id(new PhortuneSubscriptionQuery()) 338 - ->setViewer($viewer) 339 - ->withAccountPHIDs(array($account->getPHID())) 340 - ->setLimit(10) 341 - ->execute(); 342 - 343 - $subscriptions_uri = $this->getApplicationURI( 344 - $account->getID().'/subscription/'); 345 - 346 - $handles = $this->loadViewerHandles(mpull($subscriptions, 'getPHID')); 347 - 348 - $table = id(new PhortuneSubscriptionTableView()) 349 - ->setUser($viewer) 350 - ->setHandles($handles) 351 - ->setSubscriptions($subscriptions); 352 - 353 - $header = id(new PHUIHeaderView()) 354 - ->setHeader(pht('Recent Subscriptions')) 355 - ->addActionLink( 356 - id(new PHUIButtonView()) 357 - ->setTag('a') 358 - ->setIcon( 359 - id(new PHUIIconView()) 360 - ->setIcon('fa-list')) 361 - ->setHref($subscriptions_uri) 362 - ->setText(pht('View All Subscriptions'))); 363 - 364 - return id(new PHUIObjectBoxView()) 365 - ->setHeader($header) 366 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 367 - ->setTable($table); 368 - } 369 - 370 212 protected function buildApplicationCrumbs() { 371 213 $crumbs = parent::buildApplicationCrumbs(); 372 214 ··· 382 224 private function getStatusItemsForAccount( 383 225 PhortuneAccount $account, 384 226 array $invoices) { 227 + $viewer = $this->getViewer(); 385 228 386 229 assert_instances_of($invoices, 'PhortuneCart'); 387 - 388 230 $items = array(); 389 231 232 + $methods = id(new PhortunePaymentMethodQuery()) 233 + ->setViewer($viewer) 234 + ->withAccountPHIDs(array($account->getPHID())) 235 + ->withStatuses( 236 + array( 237 + PhortunePaymentMethod::STATUS_ACTIVE, 238 + )) 239 + ->execute(); 240 + 390 241 if ($invoices) { 391 242 $items[] = array( 392 - 'icon' => PHUIStatusItemView::ICON_WARNING, 393 - 'color' => 'yellow', 394 - 'target' => pht('Invoices'), 243 + 'severity' => PHUIInfoView::SEVERITY_ERROR, 395 244 'note' => pht('You have %d unpaid invoice(s).', count($invoices)), 396 - ); 397 - } else { 398 - $items[] = array( 399 - 'icon' => PHUIStatusItemView::ICON_ACCEPT, 400 - 'color' => 'green', 401 - 'target' => pht('Invoices'), 402 - 'note' => pht('This account has no unpaid invoices.'), 403 245 ); 404 246 } 405 247
+1
src/applications/phortune/view/PhortuneChargeTableView.php
··· 55 55 } 56 56 57 57 $table = id(new AphrontTableView($rows)) 58 + ->setNoDataString(pht('No charges found.')) 58 59 ->setHeaders( 59 60 array( 60 61 pht('ID'),