Jul 29, 2021
0
Level 4
Pulling a dataset and only importing certain items
I am using an API to pull in a large data set, I am then rendering a table with HTML where users can tick which items they'd like to import.
Here is my controller
<?php
namespace App\Http\Controllers\Admin;
use App\Events\DealImportedFromHubspot;
use App\Http\Controllers\Controller;
use App\Hubspot\PipelineHubspot;
use App\Models\Deal;
use App\Models\DealStage;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
class DealImportController extends Controller
{
/**
* An array to store imported Deals
*
* @var array
*/
private $importedDeals = [];
/**
* Create a new controller instance.
*/
public function __construct()
{
$this->excludedDealStages = DealStage::excludeFromDealImport()->pluck('hubspot_id');
}
/**
* Display the page to start the import process.
*
* @return void
*/
public function index()
{
return view('pages.user.deal.import');
}
/**
* Check for Deals to import and then display a listing.
*
* @return void
*/
public function check()
{
$this->getDealsFromHubspot();
session()->put('deals', $this->importedDeals);
return view('pages.user.deal.import', [
'count' => count($this->importedDeals),
'deals' => $this->importedDeals,
]);
}
/**
* Import all selected Deals.
*
* @param \Illuminate\Http\Request $request
*
* @return void
*/
public function import(Request $request)
{
$request->validate([
'imports' => [
'required',
'array',
],
]);
if ($request->has('imports')) {
PipelineHubspot::import();
$selections = $request->get('imports');
$importedDeals = session()->get('deals');
foreach ($selections as $selection) {
foreach ($importedDeals as $deal) {
if ($selection == $deal['hs_object_id']) {
$this->syncDeal($deal);
}
}
}
session()->forget('deals');
return redirect()->route('admin.dashboard')->withSuccess(count($selections) . ' deals were imported');
}
}
/**
* Grab Deals from Hubspot by calling the Deals API and looping through the paginated data
*
* @param int $limit: the number of deals per page
* @param string $next: the link to the next page of results
*/
private function getDealsFromHubspot(?int $limit = 100, string $next = null)
{
$endpoint = 'https://api.hubapi.com/crm/v3/objects/deals';
$properties = [
'limit' => $limit,
'properties' => implode(',', Deal::HUBSPOT_DEAL_PROPERTIES),
'hapikey' => config('hubspot.api_key'),
'associations' => 'engagements',
];
// If there's another page, append the after parameter.
if ($next) {
$properties['after'] = $next;
}
$response = Http::get($endpoint, $properties);
if ($response->successful()) {
$data = $response->json();
// If there are results, get them.
if (isset($data['results'])) {
foreach ($data['results'] as $hubspotDeal) {
if (!$this->excludedDealStages->contains($hubspotDeal['properties']['dealstage'])) {
$this->importedDeals[] = $hubspotDeal['properties'];
}
}
}
// If there's paginate we need to call the function on itself
if (isset($data['paging']['next']['link'])) {
$this->getDealsFromHubspot(null, $data['paging']['next']['after']);
}
}
}
/**
* Sync the Deal data with a model instance.
* Generate the necessary links and send them back to HubSpot.
*
* @see App\Events\DealImportedFromHubspot
*
* @param array $data
*
* @return void
*/
private function syncDeal(array $data)
{
$excludedDealStages = DealStage::excludeFromDealImport()->pluck('hubspot_id');
if ($excludedDealStages->contains($data['dealstage'])) {
return false;
}
$deal = Deal::updateOrCreate([
'hubspot_id' => $data['hs_object_id'],
], [
'name' => $data['dealname'],
'deal_stage_id' => $data['dealstage'],
'hubspot_owner_id' => $data['hubspot_owner_id'] ?? null,
]);
event(new DealImportedFromHubspot($deal));
}
}
The issue I'm having is that when there's roughly a thousand or so, rendering the table will hang the browser.
I was wondering whether I should just use something like Vue as then I can store the selections, any pagination etc in the virtual DOM rather then checking and then reloading the page?
Please or to participate in this conversation.