fix handle token login when loop and fix width column on task fix color default danger success scss, fix add timeout on php.ini, add scraping for execute from api, add check api for handle disabled button sync
This commit is contained in:
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enums\ImportDatasourceStatus;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Resources\ImportDatasourceResource;
|
use App\Http\Resources\ImportDatasourceResource;
|
||||||
use App\Models\ImportDatasource;
|
use App\Models\ImportDatasource;
|
||||||
|
use App\Traits\GlobalApiResponse;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class ImportDatasourceController extends Controller
|
class ImportDatasourceController extends Controller
|
||||||
{
|
{
|
||||||
|
use GlobalApiResponse;
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*/
|
*/
|
||||||
@@ -23,6 +27,19 @@ class ImportDatasourceController extends Controller
|
|||||||
return ImportDatasourceResource::collection($query->paginate());
|
return ImportDatasourceResource::collection($query->paginate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function checkImportDatasource(){
|
||||||
|
try{
|
||||||
|
$data = ImportDatasource::where("status",ImportDatasourceStatus::Processing->value )->count();
|
||||||
|
$result = [
|
||||||
|
"can_execute" => $data === 0,
|
||||||
|
"total_processing" => $data
|
||||||
|
];
|
||||||
|
return response()->json( $result , 200);
|
||||||
|
}catch(Exception $ex){
|
||||||
|
return response()->json(["message" => $ex->getMessage(), 500]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*/
|
*/
|
||||||
|
|||||||
61
app/Http/Controllers/Api/ScrapingController.php
Normal file
61
app/Http/Controllers/Api/ScrapingController.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enums\ImportDatasourceStatus;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\ImportDatasource;
|
||||||
|
use App\Traits\GlobalApiResponse;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ScrapingController extends Controller
|
||||||
|
{
|
||||||
|
use GlobalApiResponse;
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$check_datasource = ImportDatasource::where("status", ImportDatasourceStatus::Processing->value)->count();
|
||||||
|
if($check_datasource > 0){
|
||||||
|
return $this->resError("Failed to execute while processing another scraping");
|
||||||
|
}
|
||||||
|
|
||||||
|
// run service artisan command
|
||||||
|
Artisan::call("app:execute-scraping");
|
||||||
|
return $this->resSuccess("Success execute scraping service please wait");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(string $id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class ImportDatasource extends Model
|
class ImportDatasource extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
protected $table = 'import_datasources';
|
protected $table = 'import_datasources';
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'id',
|
'id',
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ class ServiceClient
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function makeRequest($url, $method = 'GET', $body = null, $headers = []){
|
public function makeRequest($url, $method = 'GET', $body = null, $headers = [], $timeout = 300){
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$headers = array_merge($this->headers, $headers);
|
$headers = array_merge($this->headers, $headers);
|
||||||
|
|
||||||
$options = [
|
$options = [
|
||||||
'headers' => $headers,
|
'headers' => $headers,
|
||||||
|
'timeout' => $timeout,
|
||||||
|
'connect_timeout' => 60
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($body) {
|
if ($body) {
|
||||||
|
|||||||
@@ -48,21 +48,13 @@ class ServiceSIMBG
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncIndexIntegration($uuid)
|
public function syncIndexIntegration($uuid, $token)
|
||||||
{
|
{
|
||||||
$clientHelper = new ServiceClient($this->simbg_host);
|
$clientHelper = new ServiceClient($this->simbg_host);
|
||||||
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
|
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/indeks-terintegrasi/";
|
||||||
$resToken = $this->getToken();
|
|
||||||
|
|
||||||
if (!isset($resToken) || empty($resToken->original['data']['token']['access'])) {
|
|
||||||
// Log error
|
|
||||||
Log::error("Token not retrieved for syncIndexIntegration", ['uuid' => $uuid]);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$apiToken = $resToken->original['data']['token']['access'];
|
|
||||||
$headers = [
|
$headers = [
|
||||||
'Authorization' => "Bearer " . $apiToken,
|
'Authorization' => "Bearer " . $token,
|
||||||
];
|
];
|
||||||
|
|
||||||
$res = $clientHelper->get($url, $headers);
|
$res = $clientHelper->get($url, $headers);
|
||||||
@@ -70,16 +62,16 @@ class ServiceSIMBG
|
|||||||
if (empty($res->original['success']) || !$res->original['success']) {
|
if (empty($res->original['success']) || !$res->original['success']) {
|
||||||
// Log error
|
// Log error
|
||||||
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $res->original['data']['data'] ?? null;
|
$data = $res->original['data']['data'] ?? null;
|
||||||
if (!$data) {
|
if (!$data) {
|
||||||
Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
Log::error("No valid data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PbgTaskIndexIntegrations::updateOrCreate(
|
$resultData = PbgTaskIndexIntegrations::updateOrCreate(
|
||||||
['pbg_task_uid' => $uuid],
|
['pbg_task_uid' => $uuid],
|
||||||
[
|
[
|
||||||
'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
|
'indeks_fungsi_bangunan' => $data['indeks_fungsi_bangunan'] ?? null,
|
||||||
@@ -93,19 +85,25 @@ class ServiceSIMBG
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Log success
|
// Log success
|
||||||
Log::info("syncIndexIntegration completed successfully", ['uuid' => $uuid]);
|
if ($resultData->wasRecentlyCreated) {
|
||||||
|
Log::info("integration created successfully", ['uuid' => $uuid]);
|
||||||
|
} else {
|
||||||
|
Log::info("integration updated successfully", ['uuid' => $uuid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncTaskList()
|
public function syncTaskList()
|
||||||
{
|
{
|
||||||
$clientHelper = new ServiceClient($this->simbg_host);
|
$clientHelper = new ServiceClient($this->simbg_host);
|
||||||
$resToken = $this->getToken();
|
$initResToken = $this->getToken();
|
||||||
|
|
||||||
$importDatasource = ImportDatasource::create([
|
$importDatasource = ImportDatasource::create([
|
||||||
'status' => ImportDatasourceStatus::Processing->value,
|
'status' => ImportDatasourceStatus::Processing->value,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (empty($resToken->original['data']['token']['access'])) {
|
if (empty($initResToken->original['data']['token']['access'])) {
|
||||||
$importDatasource->update([
|
$importDatasource->update([
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
'message' => 'Failed to retrieve token'
|
'message' => 'Failed to retrieve token'
|
||||||
@@ -113,14 +111,14 @@ class ServiceSIMBG
|
|||||||
return $this->resError("Failed to retrieve token");
|
return $this->resError("Failed to retrieve token");
|
||||||
}
|
}
|
||||||
|
|
||||||
$apiToken = $resToken->original['data']['token']['access'];
|
$apiToken = $initResToken->original['data']['token']['access'];
|
||||||
$headers = ['Authorization' => "Bearer " . $apiToken];
|
$headers = ['Authorization' => "Bearer " . $apiToken];
|
||||||
|
|
||||||
$url = "/api/pbg/v1/list/?page=1&size={$this->fetch_per_page}&sort=ASC";
|
$url = "/api/pbg/v1/list/?page=1&size={$this->fetch_per_page}&sort=ASC";
|
||||||
$initialResponse = $clientHelper->get($url, $headers);
|
$initialResponse = $clientHelper->get($url, $headers);
|
||||||
|
|
||||||
$totalPage = $initialResponse->original['data']['total_page'] ?? 0;
|
$totalPage = $initialResponse->original['data']['total_page'] ?? 0;
|
||||||
if ($totalPage === 0) {
|
if ($totalPage == 0) {
|
||||||
$importDatasource->update([
|
$importDatasource->update([
|
||||||
'status' => ImportDatasourceStatus::Failed->value,
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
'message' => 'Invalid response: no total_page'
|
'message' => 'Invalid response: no total_page'
|
||||||
@@ -132,14 +130,26 @@ class ServiceSIMBG
|
|||||||
|
|
||||||
for ($currentPage = 1; $currentPage <= $totalPage; $currentPage++) {
|
for ($currentPage = 1; $currentPage <= $totalPage; $currentPage++) {
|
||||||
$pageUrl = "/api/pbg/v1/list/?page={$currentPage}&size={$this->fetch_per_page}&sort=ASC";
|
$pageUrl = "/api/pbg/v1/list/?page={$currentPage}&size={$this->fetch_per_page}&sort=ASC";
|
||||||
$token = $this->getToken();
|
$getToken = $this->getToken();
|
||||||
|
if (empty($getToken->original['data']['token']['access'])) {
|
||||||
|
$importDatasource->update([
|
||||||
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
|
'message' => 'Failed to retrieve token'
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$token = $getToken->original['data']['token']['access'];
|
||||||
$headers = ['Authorization' => "Bearer " . $token];
|
$headers = ['Authorization' => "Bearer " . $token];
|
||||||
$response = $clientHelper->get($pageUrl, $headers);
|
$response = $clientHelper->get($pageUrl, $headers);
|
||||||
$tasks = $response->original['data']['data'] ?? [];
|
$tasks = $response->original['data']['data'] ?? [];
|
||||||
|
|
||||||
if (empty($tasks)) {
|
if (empty($tasks)) {
|
||||||
|
$importDatasource->update([
|
||||||
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
|
'message' => 'No data found on page'
|
||||||
|
]);
|
||||||
Log::warning("No data found on page", ['page' => $currentPage]);
|
Log::warning("No data found on page", ['page' => $currentPage]);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info("executed page", ['page' => $currentPage, 'total' => $totalPage]);
|
Log::info("executed page", ['page' => $currentPage, 'total' => $totalPage]);
|
||||||
@@ -170,15 +180,20 @@ class ServiceSIMBG
|
|||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->syncIndexIntegration($item['uid']);
|
$this->syncIndexIntegration($item['uid'], $token);
|
||||||
$this->syncTaskDetailSubmit($item['uid']);
|
$this->syncTaskDetailSubmit($item['uid'], $token);
|
||||||
$savedCount++;
|
$savedCount++;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$failedCount++;
|
$failedCount++;
|
||||||
|
$importDatasource->update([
|
||||||
|
'status' => ImportDatasourceStatus::Failed->value,
|
||||||
|
'message' => "Successfully processed: $savedCount, Failed: $failedCount"
|
||||||
|
]);
|
||||||
Log::error("Failed to process task", [
|
Log::error("Failed to process task", [
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'task' => $item,
|
'task' => $item,
|
||||||
]);
|
]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,21 +216,13 @@ class ServiceSIMBG
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function syncTaskDetailSubmit($uuid)
|
public function syncTaskDetailSubmit($uuid, $token)
|
||||||
{
|
{
|
||||||
$clientHelper = new ServiceClient($this->simbg_host);
|
$clientHelper = new ServiceClient($this->simbg_host);
|
||||||
$resToken = $this->getToken();
|
|
||||||
|
|
||||||
if (!isset($resToken) || empty($resToken->original['data']['token']['access'])) {
|
|
||||||
// Log error
|
|
||||||
Log::error("Token not retrieved for syncTaskDetailSubmit");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$apiToken = $resToken->original['data']['token']['access'];
|
|
||||||
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/submit/";
|
$url = "/api/pbg/v1/detail/" . $uuid . "/retribution/submit/";
|
||||||
$headers = [
|
$headers = [
|
||||||
'Authorization' => "Bearer " . $apiToken,
|
'Authorization' => "Bearer " . $token,
|
||||||
];
|
];
|
||||||
|
|
||||||
$res = $clientHelper->get($url, $headers);
|
$res = $clientHelper->get($url, $headers);
|
||||||
@@ -223,13 +230,13 @@ class ServiceSIMBG
|
|||||||
if (empty($res->original['success']) || !$res->original['success']) {
|
if (empty($res->original['success']) || !$res->original['success']) {
|
||||||
// Log error
|
// Log error
|
||||||
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $res->original['data']['data'] ?? [];
|
$data = $res->original['data']['data'] ?? [];
|
||||||
if (empty($data)) {
|
if (empty($data)) {
|
||||||
Log::error("No data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
Log::error("No data returned from API", ['url' => $url, 'uuid' => $uuid]);
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$detailCreatedAt = isset($data['created_at'])
|
$detailCreatedAt = isset($data['created_at'])
|
||||||
@@ -281,7 +288,8 @@ class ServiceSIMBG
|
|||||||
PbgTaskPrasarana::upsert($insertData, ['pbg_task_uid', 'prasarana_id']);
|
PbgTaskPrasarana::upsert($insertData, ['pbg_task_uid', 'prasarana_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info("syncTaskDetailSubmit completed successfully", ['uuid' => $uuid]);
|
Log::info("retribution and prasarana successfully", ['uuid' => $uuid]);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,6 @@ trait GlobalApiResponse
|
|||||||
'success' => true,
|
'success' => true,
|
||||||
'data' => $result
|
'data' => $result
|
||||||
];
|
];
|
||||||
|
|
||||||
if(!empty($message)){
|
|
||||||
$response['message'] = $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return response()->json($response, $code);
|
return response()->json($response, $code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ class UsersTable {
|
|||||||
url: `${GlobalConfig.apiHost}/api/users`,
|
url: `${GlobalConfig.apiHost}/api/users`,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
then: (data) =>
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ class RequestAssignment {
|
|||||||
new Grid({
|
new Grid({
|
||||||
columns: [
|
columns: [
|
||||||
"ID",
|
"ID",
|
||||||
"Name",
|
{name: "Name", width: "15%"},
|
||||||
"Condition",
|
{name: "Condition", width: "7%"},
|
||||||
"Registration Number",
|
"Registration Number",
|
||||||
"Document Number",
|
"Document Number",
|
||||||
"Address",
|
{name: "Address", width: "30%"},
|
||||||
"Status",
|
"Status",
|
||||||
"Function Type",
|
"Function Type",
|
||||||
"Consultation Type",
|
"Consultation Type",
|
||||||
"Due Date",
|
{name: "Due Date", width: "7%"},
|
||||||
],
|
],
|
||||||
search: {
|
search: {
|
||||||
server: {
|
server: {
|
||||||
@@ -40,7 +40,9 @@ class RequestAssignment {
|
|||||||
url: `${GlobalConfig.apiHost}/api/request-assignments`,
|
url: `${GlobalConfig.apiHost}/api/request-assignments`,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
then: (data) =>
|
then: (data) =>
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ class SyncronizeTask {
|
|||||||
console.log("cell data", cell);
|
console.log("cell data", cell);
|
||||||
return gridjs.html(`
|
return gridjs.html(`
|
||||||
<div class="d-flex justify-items-end gap-10">
|
<div class="d-flex justify-items-end gap-10">
|
||||||
<a href="/settings/general/${cell}/edit" class="btn btn-warning me-2">Update</a>
|
<a href="/settings/general/${cell}/edit" class="btn btn-yellow me-2">Update</a>
|
||||||
<button class="btn btn-delete btn-delete-global-settings" data-id="${cell}">Delete</button>
|
<button class="btn btn-red btn-delete btn-delete-global-settings" data-id="${cell}">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import GlobalConfig from "../../global-config.js";
|
|||||||
class SyncronizeTask {
|
class SyncronizeTask {
|
||||||
init() {
|
init() {
|
||||||
this.initTableImportDatasources();
|
this.initTableImportDatasources();
|
||||||
this.onSyncSubmit();
|
this.handleSubmitSync();
|
||||||
}
|
}
|
||||||
initTableImportDatasources() {
|
initTableImportDatasources() {
|
||||||
new Grid({
|
new Grid({
|
||||||
@@ -46,20 +46,71 @@ class SyncronizeTask {
|
|||||||
},
|
},
|
||||||
}).render(document.getElementById("table-import-datasources"));
|
}).render(document.getElementById("table-import-datasources"));
|
||||||
}
|
}
|
||||||
onSyncSubmit() {
|
handleSubmitSync() {
|
||||||
const form = document.getElementById("sync-form");
|
const button = document.getElementById("btn-sync-submit");
|
||||||
if (form) {
|
|
||||||
form.addEventListener("submit", function (event) {
|
// Check if the button should be enabled or disabled based on the status
|
||||||
event.preventDefault(); // Prevent the default form submission
|
fetch(`${GlobalConfig.apiHost}/api/import-datasource/check-datasource`, {
|
||||||
|
method: "GET",
|
||||||
const button = document.getElementById("btn-sync-submit");
|
headers: {
|
||||||
if (button) {
|
Authorization: `Bearer ${document
|
||||||
button.disabled = true;
|
.querySelector('meta[name="api-token"]')
|
||||||
button.innerText = "Processing...";
|
.getAttribute("content")}`,
|
||||||
}
|
"Content-Type": "application/json",
|
||||||
form.submit();
|
}
|
||||||
});
|
})
|
||||||
}
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Network response was not ok");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log("data check button sync", data.can_execute);
|
||||||
|
button.disabled = !data.can_execute;
|
||||||
|
|
||||||
|
// If the button is enabled, add click event to trigger sync
|
||||||
|
if (!button.disabled) {
|
||||||
|
button.addEventListener("click", function(e) {
|
||||||
|
button.disabled = true; // Disable button to prevent multiple clicks
|
||||||
|
button.textContent = "Syncing..."; // Change button text to show syncing
|
||||||
|
|
||||||
|
// Trigger the scraping API call
|
||||||
|
fetch(`${GlobalConfig.apiHost}/api/scraping`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${document
|
||||||
|
.querySelector('meta[name="api-token"]')
|
||||||
|
.getAttribute("content")}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Network response was not ok");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log("data sync button", data);
|
||||||
|
alert("Synchronization executed successfully");
|
||||||
|
window.location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Fetch error:", err);
|
||||||
|
alert("An error occurred during synchronization");
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
button.disabled = false; // Re-enable the button after the request is complete
|
||||||
|
button.textContent = "Sync Data"; // Reset button text
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Fetch error:", err);
|
||||||
|
alert("An error occurred while checking the datasource");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("DOMContentLoaded", function (e) {
|
document.addEventListener("DOMContentLoaded", function (e) {
|
||||||
|
|||||||
@@ -64,10 +64,10 @@ $blue: #1a80f8;
|
|||||||
$indigo: #53389f;
|
$indigo: #53389f;
|
||||||
$purple: #7e67fe;
|
$purple: #7e67fe;
|
||||||
$pink: #ff86c8;
|
$pink: #ff86c8;
|
||||||
$red: #ed321f;
|
$red: #bd1300;
|
||||||
$orange: #f0934e;
|
$orange: #f0934e;
|
||||||
$yellow: #fb9f68;
|
$yellow: #dfdc40;
|
||||||
$green: #21d760;
|
$green: #00c91b;
|
||||||
$teal: #040505;
|
$teal: #040505;
|
||||||
$cyan: #1ab0f8;
|
$cyan: #1ab0f8;
|
||||||
// scss-docs-end color-variables
|
// scss-docs-end color-variables
|
||||||
@@ -81,7 +81,7 @@ $purple: $purple;
|
|||||||
$pink: $pink;
|
$pink: $pink;
|
||||||
$danger: $red;
|
$danger: $red;
|
||||||
$orange: $orange;
|
$orange: $orange;
|
||||||
$warning: $orange;
|
$warning: $yellow;
|
||||||
$success: $green;
|
$success: $green;
|
||||||
$info: $cyan;
|
$info: $cyan;
|
||||||
$light: $gray-200;
|
$light: $gray-200;
|
||||||
|
|||||||
@@ -11,25 +11,25 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- App Search-->
|
<!-- App Search-->
|
||||||
<form class="app-search d-none d-md-block me-auto">
|
<!-- <form class="app-search d-none d-md-block me-auto">
|
||||||
<div class="position-relative">
|
<div class="position-relative">
|
||||||
<input type="search" class="form-control" placeholder="admin,widgets..."
|
<input type="search" class="form-control" placeholder="admin,widgets..."
|
||||||
autocomplete="off" value="">
|
autocomplete="off" value="">
|
||||||
<iconify-icon icon="solar:magnifer-outline" class="search-widget-icon"></iconify-icon>
|
<iconify-icon icon="solar:magnifer-outline" class="search-widget-icon"></iconify-icon>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<!-- Theme Color (Light/Dark) -->
|
<!-- Theme Color (Light/Dark) -->
|
||||||
<div class="topbar-item">
|
<!-- <div class="topbar-item">
|
||||||
<button type="button" class="topbar-button" id="light-dark-mode">
|
<button type="button" class="topbar-button" id="light-dark-mode">
|
||||||
<iconify-icon icon="solar:moon-outline"
|
<iconify-icon icon="solar:moon-outline"
|
||||||
class="fs-22 align-middle light-mode"></iconify-icon>
|
class="fs-22 align-middle light-mode"></iconify-icon>
|
||||||
<!-- <iconify-icon icon="solar:sun-2-outline"
|
<iconify-icon icon="solar:sun-2-outline"
|
||||||
class="fs-22 align-middle dark-mode"></iconify-icon> -->
|
class="fs-22 align-middle dark-mode"></iconify-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<!-- Notification -->
|
<!-- Notification -->
|
||||||
<div class="dropdown topbar-item">
|
<div class="dropdown topbar-item">
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
<!-- item-->
|
<!-- item-->
|
||||||
<h6 class="dropdown-header">Welcome!</h6>
|
<h6 class="dropdown-header">Welcome!</h6>
|
||||||
|
|
||||||
<a class="dropdown-item" href="#">
|
<!-- <a class="dropdown-item" href="#">
|
||||||
<iconify-icon icon="solar:user-outline"
|
<iconify-icon icon="solar:user-outline"
|
||||||
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">My
|
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">My
|
||||||
Account</span>
|
Account</span>
|
||||||
@@ -176,7 +176,7 @@
|
|||||||
<iconify-icon icon="solar:lock-keyhole-outline"
|
<iconify-icon icon="solar:lock-keyhole-outline"
|
||||||
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">Lock
|
class="align-middle me-2 fs-18"></iconify-icon><span class="align-middle">Lock
|
||||||
screen</span>
|
screen</span>
|
||||||
</a>
|
</a> -->
|
||||||
|
|
||||||
<div class="dropdown-divider my-1"></div>
|
<div class="dropdown-divider my-1"></div>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
@include('layouts.partials/page-title', ['title' => 'Se', 'subtitle' => 'Syncronize'])
|
@include('layouts.partials/page-title', ['title' => 'Se', 'subtitle' => 'Syncronize'])
|
||||||
|
|
||||||
<div class="row">
|
<div class="row d-flex justify-content-center">
|
||||||
@if (session('error'))
|
@if (session('error'))
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
{{ session('error') }}
|
{{ session('error') }}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="columns-md">
|
<div class="col-lg-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="{{ route('general.store') }}" method="POST">
|
<form action="{{ route('general.store') }}" method="POST">
|
||||||
@@ -51,5 +51,4 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
@vite(['resources/js/tables/common-table.js'])
|
|
||||||
@endsection
|
@endsection
|
||||||
@@ -10,10 +10,11 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12 col-xl-12 d-flex justify-content-end">
|
<div class="col-md-12 col-xl-12 d-flex justify-content-end">
|
||||||
<form action="{{route('settings.sync')}}" method="post" id="sync-form">
|
<!-- <form action="{{route('settings.sync')}}" method="post" id="sync-form">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="btn btn-success width-lg" id="btn-sync-submit">Sync SIMBG</button>
|
<button type="button" class="btn btn-success width-lg" id="btn-sync-submit">Sync SIMBG</button>
|
||||||
</form>
|
</form> -->
|
||||||
|
<button type="button" class="btn btn-success width-lg" id="btn-sync-submit">Sync SIMBG</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div id="table-import-datasources"></div>
|
<div id="table-import-datasources"></div>
|
||||||
|
|||||||
@@ -4,17 +4,11 @@ use App\Http\Controllers\Api\DashboardController;
|
|||||||
use App\Http\Controllers\Api\GlobalSettingsController;
|
use App\Http\Controllers\Api\GlobalSettingsController;
|
||||||
use App\Http\Controllers\Api\ImportDatasourceController;
|
use App\Http\Controllers\Api\ImportDatasourceController;
|
||||||
use App\Http\Controllers\Api\RequestAssignmentController;
|
use App\Http\Controllers\Api\RequestAssignmentController;
|
||||||
|
use App\Http\Controllers\Api\ScrapingController;
|
||||||
use App\Http\Controllers\Api\UsersController;
|
use App\Http\Controllers\Api\UsersController;
|
||||||
use App\Http\Controllers\Settings\SyncronizeController;
|
use App\Http\Controllers\Settings\SyncronizeController;
|
||||||
use App\Models\PbgTask;
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
// Route::get('/user', function (Request $request) {
|
|
||||||
// return $request->user();
|
|
||||||
// })->middleware('auth:sanctum');
|
|
||||||
|
|
||||||
Route::post('/login', [UsersController::class, 'login'])->name('api.user.login');
|
Route::post('/login', [UsersController::class, 'login'])->name('api.user.login');
|
||||||
Route::group(['middleware' => 'auth:sanctum'], function (){
|
Route::group(['middleware' => 'auth:sanctum'], function (){
|
||||||
// users
|
// users
|
||||||
@@ -25,7 +19,12 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
|
|||||||
Route::apiResource('global-settings', GlobalSettingsController::class);
|
Route::apiResource('global-settings', GlobalSettingsController::class);
|
||||||
|
|
||||||
// import datasource
|
// import datasource
|
||||||
Route::apiResource('import-datasource',ImportDatasourceController::class);
|
// Route::apiResource('import-datasource',ImportDatasourceController::class);
|
||||||
|
Route::controller(ImportDatasourceController::class)->group(function (){
|
||||||
|
Route::get('/import-datasource/check-datasource', 'checkImportDatasource')
|
||||||
|
->name('import-datasource.check');
|
||||||
|
Route::get('/import-datasource', 'index')->name('import-datasource.index');
|
||||||
|
});
|
||||||
|
|
||||||
// request assignments
|
// request assignments
|
||||||
Route::apiResource('request-assignments',RequestAssignmentController::class);
|
Route::apiResource('request-assignments',RequestAssignmentController::class);
|
||||||
@@ -37,6 +36,9 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
|
|||||||
Route::get('/all-task-documents', 'allTaskDocuments');
|
Route::get('/all-task-documents', 'allTaskDocuments');
|
||||||
Route::get('/pbg-task-documents', 'pbgTaskDocuments');
|
Route::get('/pbg-task-documents', 'pbgTaskDocuments');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// scraping
|
||||||
|
Route::apiResource('/scraping', ScrapingController::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user