diff --git a/.env.example b/.env.example
index 8844ac4245..d5848b55d2 100755
--- a/.env.example
+++ b/.env.example
@@ -63,10 +63,6 @@ DB_PASSWORD=secret
# This option is useful if you don't want the CDash's GitHub check to block merging.
#GITHUB_ALWAYS_PASS=false
-# API key for maps.google.com.
-# Set to a valid value to display maps of sites.
-#GOOGLE_MAP_API_KEY=null
-
# Maximum size of large text fields, in bytes. 0 for unlimited
#LARGE_TEXT_LIMIT=0
diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php
index ca5085cf98..2d112c291c 100644
--- a/app/Http/Controllers/SiteController.php
+++ b/app/Http/Controllers/SiteController.php
@@ -4,14 +4,11 @@
use App\Models\Site;
use App\Models\User;
-use App\Utils\TestingDay;
use CDash\Database;
use CDash\Model\Project;
use Illuminate\Http\RedirectResponse;
-use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
final class SiteController extends AbstractController
@@ -320,231 +317,10 @@ public function editSite(): View|RedirectResponse
->with('xsl_content', generate_XSLT($xml, base_path() . '/app/cdash/public/editSite', true));
}
- public function viewSite(int $siteid): View
+ public function viewSite(Site $site): View
{
- $db = Database::getInstance();
-
- $site = Site::findOrFail($siteid);
-
- $currenttime = $_GET['currenttime'] ?? null;
- if ($currenttime !== null) {
- $currenttime = (int) $currenttime;
-
- // Current timestamp is the beginning of the dashboard and we want the end
- $currenttimestamp = Carbon::createFromTimestamp($currenttime + 3600 * 24);
- } else {
- $currenttimestamp = Carbon::maxValue();
- }
-
- $siteinformation = $site->mostRecentInformation($currenttimestamp)->first();
-
- $xml = begin_XML_for_XSLT();
-
- $projectid = (int) ($_GET['project'] ?? 0);
-
- if ($projectid > 0) {
- $project = new Project();
- $project->Id = $projectid;
- $project->Fill();
- $xml .= 'index.php?project=' . urlencode($project->Name);
- $date = TestingDay::get($project, gmdate(FMT_DATETIME, $currenttime));
- $xml .= '&date=' . $date;
- $xml .= '';
- } else {
- $project = null;
- $xml .= 'index.php';
- }
- $xml .= "
CDash - {$site->name}";
- $xml .= "{$site->name}";
-
- $xml .= '';
- $xml .= 'CDash';
-
- $xml .= add_XML_value('baseURL', config('app.url'));
- $apikey = config('cdash.google_map_api_key');
-
- $MB = 1048576;
-
- $total_virtual_memory = $siteinformation?->totalvirtualmemory;
- if ($total_virtual_memory !== null) {
- $total_virtual_memory = getByteValueWithExtension($total_virtual_memory * $MB) . 'iB';
- }
-
- $total_physical_memory = $siteinformation?->totalphysicalmemory;
- if ($total_physical_memory !== null) {
- $total_physical_memory = getByteValueWithExtension($total_physical_memory * $MB) . 'iB';
- }
-
- $processor_clock_frequency = $siteinformation?->processorclockfrequency;
- if ($processor_clock_frequency !== null) {
- $processor_clock_frequency = getByteValueWithExtension($processor_clock_frequency * 10 ** 6, 1000) . 'Hz';
- }
-
- $xml .= add_XML_value('googlemapkey', $apikey);
- $xml .= '';
- $xml .= '';
- $xml .= add_XML_value('id', $site->id);
- $xml .= add_XML_value('name', $site->name);
- $xml .= add_XML_value('description', stripslashes($siteinformation->description ?? ''));
- $xml .= add_XML_value('processoris64bits', $siteinformation?->processoris64bits);
- $xml .= add_XML_value('processorvendor', $siteinformation?->processorvendor);
- $xml .= add_XML_value('processorvendorid', $siteinformation?->processorvendorid);
- $xml .= add_XML_value('processorfamilyid', $siteinformation?->processorfamilyid);
- $xml .= add_XML_value('processormodelid', $siteinformation?->processormodelid);
- $xml .= add_XML_value('processorcachesize', $siteinformation?->processorcachesize);
- $xml .= add_XML_value('numberlogicalcpus', $siteinformation?->numberlogicalcpus);
- $xml .= add_XML_value('numberphysicalcpus', $siteinformation?->numberphysicalcpus);
- $xml .= add_XML_value('totalvirtualmemory', $total_virtual_memory);
- $xml .= add_XML_value('totalphysicalmemory', $total_physical_memory);
- $xml .= add_XML_value('logicalprocessorsperphysical', $siteinformation?->logicalprocessorsperphysical);
- $xml .= add_XML_value('processorclockfrequency', $processor_clock_frequency);
- $xml .= add_XML_value('outoforder', $site->outoforder);
- if ($project !== null && $project->ShowIPAddresses) {
- $xml .= add_XML_value('ip', $site->ip);
- $xml .= add_XML_value('latitude', $site->latitude);
- $xml .= add_XML_value('longitude', $site->longitude);
- }
- $xml .= '';
-
- // List the claimers of the site
- $siteclaimer = $db->executePrepared('
- SELECT u.firstname, u.lastname, u.email
- FROM users as u, site2user
- WHERE
- u.id=site2user.userid
- AND site2user.siteid=?
- ORDER BY firstname
- ', [$siteid]);
- foreach ($siteclaimer as $sc) {
- $xml .= '';
- $xml .= add_XML_value('firstname', $sc['firstname']);
- $xml .= add_XML_value('lastname', $sc['lastname']);
- if (isset($_SESSION['cdash'])) {
- $xml .= add_XML_value('email', $sc['email']);
- }
- $xml .= '';
- }
-
- // Select projects that belong to this site
- $displayPage = 0;
- $projects = [];
- $site2project = $db->executePrepared('
- SELECT projectid, max(submittime) AS maxtime
- FROM build
- WHERE
- siteid=?
- AND projectid>0
- GROUP BY projectid
- ', [$siteid]);
-
- foreach ($site2project as $project_site) {
- $projectid = $project_site['projectid'];
-
- $project = new Project();
- $project->Id = $projectid;
- $project->Fill();
- if (Gate::allows('view-project', $project)) {
- $xml .= '';
- $xml .= add_XML_value('id', $projectid);
- $xml .= add_XML_value('submittime', $project_site['maxtime']);
- $xml .= add_XML_value('name', $project->Name);
- $xml .= add_XML_value('name_encoded', urlencode($project->Name));
- $xml .= '';
- $displayPage = 1; // if we have at least a valid project we display the page
- $projects[] = $projectid;
- }
- }
-
- // If the current site as only private projects we check that we have the right
- // to view the page
- if (!$displayPage) {
- abort(403, 'You cannot access this page');
- }
-
- // Compute the time for all the projects (faster than individually) average of the week
- if (config('database.default') == 'pgsql') {
- $timediff = 'EXTRACT(EPOCH FROM (build.submittime - buildupdate.starttime))';
- $timestampadd = "NOW()-INTERVAL'167 hours'";
- } else {
- $timediff = 'TIME_TO_SEC(TIMEDIFF(build.submittime, buildupdate.starttime))';
- $timestampadd = 'TIMESTAMPADD(' . qiv('HOUR') . ', -167, NOW())';
- }
-
- $testtime = $db->executePrepared("
- SELECT projectid, build.name AS buildname, build.type AS buildtype, SUM({$timediff}) AS elapsed
- FROM build, buildupdate, build2update
- WHERE
- build.submittime > {$timestampadd}
- AND build2update.buildid = build.id
- AND buildupdate.id = build2update.updateid
- AND build.siteid = ?
- GROUP BY projectid,buildname,buildtype
- ORDER BY elapsed
- ", [$siteid]);
-
- $xml .= '';
-
- echo pdo_error();
- $totalload = 0;
- foreach ($testtime as $tt) {
- $projectid = $tt['projectid'];
- $project = new Project();
- $project->Id = $projectid;
- $project->Fill();
- if (Gate::allows('view-project', $project)) {
- $timespent = round($tt['elapsed'] / 7.0); // average over 7 days
- $xml .= '';
- $xml .= add_XML_value('name', $tt['buildname']);
- $xml .= add_XML_value('project', $project->Name);
- $xml .= add_XML_value('type', $tt['buildtype']);
- $xml .= add_XML_value('time', $timespent);
- $totalload += $timespent;
- $xml .= '';
- }
- }
-
- // Compute the idle time
- $idletime = 24 * 3600 - $totalload;
- if ($idletime < 0) {
- $idletime = 0;
- }
- $xml .= '' . $idletime . '';
- $xml .= '';
-
- if (isset($_SESSION['cdash'])) {
- $xml .= '';
- $userid = Auth::id();
-
- // Check if the current user as a role in this project
- foreach ($projects as $projectid) {
- // TODO: (williamjallen) Optimize this loop to execute a constant number of queries
-
- $user2project = $db->executePrepared('SELECT role FROM user2project WHERE projectid=? and role>0', [$projectid]);
- if (count($user2project) > 0) {
- $xml .= add_XML_value('sitemanager', '1');
-
- $user2site = $db->executePrepared('SELECT * FROM site2user WHERE siteid=? and userid=?',
- [$siteid, $userid]);
- if (count($user2site) == 0) {
- $xml .= add_XML_value('siteclaimed', '0');
- } else {
- $xml .= add_XML_value('siteclaimed', '1');
- }
- break;
- }
- }
-
- $user = User::where('id', '=', $userid)->first();
- $xml .= add_XML_value('id', $userid);
- $xml .= add_XML_value('admin', $user->admin);
- $xml .= '';
- }
-
- $xml .= '';
-
- return $this->view('cdash', $site->name)
- ->with('xsl', true)
- ->with('xsl_content', generate_XSLT($xml, base_path() . '/app/cdash/public/viewSite', true));
+ return $this->view('site.view-site', $site->name)
+ ->with('site', $site);
}
/**
diff --git a/app/cdash/public/viewSite.xsl b/app/cdash/public/viewSite.xsl
deleted file mode 100644
index 8964236cb5..0000000000
--- a/app/cdash/public/viewSite.xsl
+++ /dev/null
@@ -1,155 +0,0 @@
-
-
-
-
-
-
-
- /editSite.php?siteid=
- Are you maintaining this site? [claim this site][edit site description]
-
-
-
-
-
- This site has been marked as temporarly out of order by its maintainer.
-
-
-
-
- No system information available at this time.
-
-
- Processor Speed:
-
- Processor Vendor:
-
- ()
-
-
-
- Number of CPUs:
-
-
- Number of Cores:
-
-
- Total Physical Memory:
-
-
-
-
- Description:
-
-
-
-
-
-
- Claimed by:
-
-
-
-
- mailto:
-
-
-
-
-
-
-
-
-
-
- IP address:
- Map:
-
-
- <script type="text/javascript">
- // Creates a marker whose info window displays the letter corresponding
- // to the given index.
- function createMarker(point,title)
- {
- var marker = new GMarker(point);
- GEvent.addListener(marker, "click", function()
- {
- marker.openInfoWindowHtml(title);
- });
- return marker;
- }
-
- function load() {
- if (GBrowserIsCompatible()) {
- var map = new GMap2(document.getElementById("map"));
-
-
- map.setCenter(new GLatLng(,),5);
- map.addControl(new GLargeMapControl());
- var point = new GLatLng(,);
- map.addOverlay(createMarker(point,''));
-
-
-
- map.setCenter(new GLatLng(0,0),1);
-
-
- }
- }
- </script>
-
-
-
-
-
-
-
-
-
- This site belongs to the following projects:
-
-
- /index.php?project=
-
-
- ()
-
-
-
-
- Time spent per project (computed from average data over one week):
-
-
-
-
-
diff --git a/app/cdash/tests/CMakeLists.txt b/app/cdash/tests/CMakeLists.txt
index c84f0e1912..2b9039f186 100644
--- a/app/cdash/tests/CMakeLists.txt
+++ b/app/cdash/tests/CMakeLists.txt
@@ -227,8 +227,12 @@ set_tests_properties(/Feature/GraphQL/BuildMeasurementTypeTest PROPERTIES DEPEND
add_laravel_test(/Feature/GraphQL/CoverageTypeTest)
set_tests_properties(/Feature/GraphQL/CoverageTypeTest PROPERTIES DEPENDS /Feature/GraphQL/BuildTypeTest)
+add_laravel_test(/Browser/Pages/SitesIdPageTest)
+set_tests_properties(/Browser/Pages/SitesIdPageTest PROPERTIES DEPENDS /Feature/GraphQL/BuildTypeTest)
+set_tests_properties(/Browser/Pages/SitesIdPageTest PROPERTIES RUN_SERIAL TRUE)
+
add_laravel_test(/Feature/PurgeUnusedProjectsCommand)
-set_tests_properties(/Feature/PurgeUnusedProjectsCommand PROPERTIES DEPENDS "/Feature/GraphQL/TestTypeTest;/Feature/GraphQL/TestMeasurementTypeTest;/Feature/GraphQL/NoteTypeTest;/Feature/GraphQL/BuildMeasurementTypeTest;/Feature/GraphQL/CoverageTypeTest")
+set_tests_properties(/Feature/PurgeUnusedProjectsCommand PROPERTIES DEPENDS "/Feature/GraphQL/TestTypeTest;/Feature/GraphQL/TestMeasurementTypeTest;/Feature/GraphQL/NoteTypeTest;/Feature/GraphQL/BuildMeasurementTypeTest;/Feature/GraphQL/CoverageTypeTest;/Browser/Pages/SitesIdPageTest")
add_laravel_test(/Browser/Pages/ProjectSitesPageTest)
set_tests_properties(/Browser/Pages/ProjectSitesPageTest PROPERTIES DEPENDS /Feature/PurgeUnusedProjectsCommand)
diff --git a/app/cdash/tests/test_projectwebpage.php b/app/cdash/tests/test_projectwebpage.php
index 13e797890c..a68d591771 100644
--- a/app/cdash/tests/test_projectwebpage.php
+++ b/app/cdash/tests/test_projectwebpage.php
@@ -4,7 +4,6 @@
// After including cdash_test_case.php, subsequent require_once calls are
// relative to the top of the CDash source tree
//
-use Illuminate\Support\Carbon;
require_once dirname(__FILE__) . '/cdash_test_case.php';
@@ -181,27 +180,6 @@ public function testSubmissionInDb()
$this->assertEqual($result[0], $expected);
}
- public function testProjectExperimentalLinkMachineName()
- {
- $content = $this->connect($this->url . '/api/v1/index.php?project=BatchmakeExample');
- $jsonobj = json_decode($content, true);
- if (count($jsonobj['buildgroups']) < 1) {
- $this->fail('No build found when expected');
- return;
- }
- $buildgroup = array_pop($jsonobj['buildgroups']);
- $siteid = $buildgroup['builds'][0]['siteid'];
-
- $content = $this->connect($this->url . "/sites/$siteid?project=4¤ttime=" . Carbon::now()->getTimestamp());
- if (!$content) {
- return;
- } elseif (!$this->findString($content, 'Total Physical Memory: 15MiB ')) {
- $this->assertTrue(false, 'The webpage does not match the expected content');
- return;
- }
- $this->assertTrue(true, 'The webpage matches the expected content');
- }
-
public function testProjectExperimentalLinkBuildSummary()
{
$content = $this->connect($this->url . '/api/v1/index.php?project=BatchmakeExample');
diff --git a/config/cdash.php b/config/cdash.php
index 3d6eda8a7a..05a919788f 100755
--- a/config/cdash.php
+++ b/config/cdash.php
@@ -54,7 +54,6 @@
'default_git_dir' => env('DEFAULT_GIT_DIRECTORY', '/cdash/_build'),
'default_project' => env('DEFAULT_PROJECT', null),
'delete_old_subprojects' => env('DELETE_OLD_SUBPROJECTS', true),
- 'google_map_api_key' => env('GOOGLE_MAP_API_KEY', null),
'github_always_pass' => env('GITHUB_ALWAYS_PASS', false),
'github_app_id' => env('GITHUB_APP_ID', null),
'github_private_key' => env('GITHUB_PRIVATE_KEY', null),
diff --git a/graphql/schema.graphql b/graphql/schema.graphql
index fd0f49580a..ce1d6343e0 100644
--- a/graphql/schema.graphql
+++ b/graphql/schema.graphql
@@ -426,7 +426,7 @@ type Site {
longitude: String!
"Every edit of this site's information."
- information: [SiteInformation!]! @hasMany(type: CONNECTION) @orderBy(column: "timestamp")
+ information: [SiteInformation!]! @hasMany(type: CONNECTION) @orderBy(column: "timestamp", direction: DESC)
"The most recent information we have about this site."
# TODO: Figure out how to support the date parameter. Perhaps it would be better to use a scope instead.
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 2077faf1fb..5dcdbe3762 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -2412,7 +2412,7 @@ parameters:
-
message: "#^Argument of an invalid type array\\|false supplied for foreach, only iterables are supported\\.$#"
- count: 4
+ count: 1
path: app/Http/Controllers/SiteController.php
-
@@ -2425,7 +2425,7 @@ parameters:
#^Call to deprecated function pdo_error\\(\\)\\:
04/01/2023$#
"""
- count: 2
+ count: 1
path: app/Http/Controllers/SiteController.php
-
@@ -2433,7 +2433,7 @@ parameters:
#^Call to deprecated method executePrepared\\(\\) of class CDash\\\\Database\\:
04/22/2023 Use Laravel query builder or Eloquent instead$#
"""
- count: 7
+ count: 2
path: app/Http/Controllers/SiteController.php
-
@@ -2454,33 +2454,13 @@ parameters:
count: 1
path: app/Http/Controllers/SiteController.php
- -
- message: "#^Cannot access property \\$admin on App\\\\Models\\\\User\\|null\\.$#"
- count: 1
- path: app/Http/Controllers/SiteController.php
-
-
message: "#^Cannot cast mixed to int\\.$#"
- count: 4
- path: app/Http/Controllers/SiteController.php
-
- -
- message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: app/Http/Controllers/SiteController.php
-
- message: "#^Dynamic call to static method Illuminate\\\\Database\\\\Eloquent\\\\Relations\\\\HasOne\\\\:\\:first\\(\\)\\.$#"
- count: 1
- path: app/Http/Controllers/SiteController.php
-
- -
- message: "#^Foreach overwrites \\$projectid with its value variable\\.$#"
- count: 1
- path: app/Http/Controllers/SiteController.php
-
- -
- message: "#^Loose comparison via \"\\=\\=\" is not allowed\\.$#"
+ message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
path: app/Http/Controllers/SiteController.php
@@ -2504,11 +2484,6 @@ parameters:
count: 1
path: app/Http/Controllers/SiteController.php
- -
- message: "#^Only booleans are allowed in a negated boolean, int given\\.$#"
- count: 1
- path: app/Http/Controllers/SiteController.php
-
-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 4
@@ -2529,11 +2504,6 @@ parameters:
count: 1
path: app/Http/Controllers/SiteController.php
- -
- message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\|false given\\.$#"
- count: 2
- path: app/Http/Controllers/SiteController.php
-
-
message: "#^Parameter \\#1 \\$value of function intval expects array\\|bool\\|float\\|int\\|resource\\|string\\|null, mixed given\\.$#"
count: 4
@@ -25898,7 +25868,7 @@ parameters:
-
message: "#^Cannot access offset 'buildgroups' on mixed\\.$#"
- count: 4
+ count: 2
path: app/cdash/tests/test_projectwebpage.php
-
@@ -25908,7 +25878,7 @@ parameters:
-
message: "#^Cannot access offset 'builds' on mixed\\.$#"
- count: 2
+ count: 1
path: app/cdash/tests/test_projectwebpage.php
-
@@ -25921,14 +25891,9 @@ parameters:
count: 1
path: app/cdash/tests/test_projectwebpage.php
- -
- message: "#^Cannot access offset 'siteid' on mixed\\.$#"
- count: 1
- path: app/cdash/tests/test_projectwebpage.php
-
-
message: "#^Cannot access offset 0 on mixed\\.$#"
- count: 5
+ count: 4
path: app/cdash/tests/test_projectwebpage.php
-
@@ -25941,11 +25906,6 @@ parameters:
count: 1
path: app/cdash/tests/test_projectwebpage.php
- -
- message: "#^Method ProjectWebPageTestCase\\:\\:testProjectExperimentalLinkMachineName\\(\\) has no return type specified\\.$#"
- count: 1
- path: app/cdash/tests/test_projectwebpage.php
-
-
message: "#^Method ProjectWebPageTestCase\\:\\:testSubmissionBatchmakeBuild\\(\\) has no return type specified\\.$#"
count: 1
@@ -26013,7 +25973,7 @@ parameters:
-
message: "#^Parameter \\#1 \\$array of function array_pop expects array, mixed given\\.$#"
- count: 2
+ count: 1
path: app/cdash/tests/test_projectwebpage.php
-
@@ -26028,7 +25988,7 @@ parameters:
-
message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, mixed given\\.$#"
- count: 3
+ count: 2
path: app/cdash/tests/test_projectwebpage.php
-
@@ -26041,11 +26001,6 @@ parameters:
count: 1
path: app/cdash/tests/test_projectwebpage.php
- -
- message: "#^Part \\$siteid \\(mixed\\) of encapsed string cannot be cast to string\\.$#"
- count: 1
- path: app/cdash/tests/test_projectwebpage.php
-
-
message: """
#^Call to deprecated method submission\\(\\) of class KWWebTestCase\\:
@@ -31888,6 +31843,11 @@ parameters:
count: 1
path: server.php
+ -
+ message: "#^Cannot access property \\$description on App\\\\Models\\\\SiteInformation\\|null\\.$#"
+ count: 1
+ path: tests/Browser/Pages/SitesIdPageTest.php
+
-
message: "#^Access to an undefined property CDash\\\\Model\\\\Build\\:\\:\\$Endime\\.$#"
count: 2
diff --git a/resources/js/vue/app.js b/resources/js/vue/app.js
index c470539c44..99ea2c7bf2 100755
--- a/resources/js/vue/app.js
+++ b/resources/js/vue/app.js
@@ -32,6 +32,7 @@ import AllProjects from './components/AllProjects.vue';
import SubProjectDependencies from './components/SubProjectDependencies.vue';
import BuildTestsPage from './components/BuildTestsPage.vue';
import ProjectSitesPage from './components/ProjectSitesPage.vue';
+import SitesIdPage from './components/SitesIdPage.vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import * as FA from '@fortawesome/fontawesome-svg-core';
@@ -62,6 +63,7 @@ const cdash_components = {
SubProjectDependencies,
BuildTestsPage,
ProjectSitesPage,
+ SitesIdPage,
};
/**
@@ -106,6 +108,9 @@ const apolloClient = new ApolloClient({
tests: relayStylePagination(),
},
},
+ Site: {
+ information: relayStylePagination(),
+ },
},
}),
uri: `${app.config.globalProperties.$baseURL}/graphql`,
diff --git a/resources/js/vue/components/SitesIdPage.vue b/resources/js/vue/components/SitesIdPage.vue
new file mode 100644
index 0000000000..7c4790a2a4
--- /dev/null
+++ b/resources/js/vue/components/SitesIdPage.vue
@@ -0,0 +1,427 @@
+
+
+
+
+
+ Site Details
+
+
+
+ No information available for this site.
+
+
+