From 4ed7ac6616a9b6a94d81d1e2437165f13d960df9 Mon Sep 17 00:00:00 2001 From: William Allen <16820599+williamjallen@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:58:31 -0400 Subject: [PATCH] Migrate `user.php` frontend from AngularJS to Vue --- app/Http/Controllers/AdminController.php | 1 - app/Http/Controllers/CoverageController.php | 1 - .../ManageMeasurementsController.php | 2 +- .../ManageProjectRolesController.php | 3 +- app/Http/Controllers/ProjectController.php | 3 - app/Http/Controllers/SiteController.php | 3 +- app/Http/Controllers/SubProjectController.php | 1 - .../SubscribeProjectController.php | 7 +- app/Http/Controllers/UserController.php | 3 +- app/cdash/public/api/v1/manageBuildGroup.php | 1 - app/cdash/public/api/v1/manageOverview.php | 1 - app/cdash/public/css/common.css | 4 - app/cdash/public/js/controllers/user.js | 75 -- app/cdash/public/js/oauth2.js | 2 +- resources/js/app.js | 2 + resources/js/components/EditProject.vue | 4 +- resources/js/components/UserHomepage.vue | 804 ++++++++++++++++++ resources/js/components/shared/ApiLoader.js | 4 +- resources/views/admin/user.blade.php | 397 +-------- resources/views/components/header.blade.php | 2 +- routes/web.php | 3 +- tests/Feature/RouteAccessTest.php | 2 +- 22 files changed, 825 insertions(+), 500 deletions(-) delete mode 100644 app/cdash/public/js/controllers/user.js create mode 100644 resources/js/components/UserHomepage.vue diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 265a84fab2..7a7bf2ae74 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -130,7 +130,6 @@ public function upgrade() @set_time_limit(0); $xml = begin_XML_for_XSLT(); - $xml .= 'user.php'; $xml .= 'CDash'; $xml .= 'Maintenance'; diff --git a/app/Http/Controllers/CoverageController.php b/app/Http/Controllers/CoverageController.php index 8ea33bcaf8..1e0ce01b08 100644 --- a/app/Http/Controllers/CoverageController.php +++ b/app/Http/Controllers/CoverageController.php @@ -54,7 +54,6 @@ public function manageCoverage(): View|RedirectResponse } $xml = begin_XML_for_XSLT(); - $xml .= 'user.php'; $xml .= 'CDash'; $xml .= 'Coverage'; diff --git a/app/Http/Controllers/ManageMeasurementsController.php b/app/Http/Controllers/ManageMeasurementsController.php index 0dde7d69c5..c3a1284b86 100644 --- a/app/Http/Controllers/ManageMeasurementsController.php +++ b/app/Http/Controllers/ManageMeasurementsController.php @@ -31,7 +31,7 @@ public function apiGet(): JsonResponse // Menu $menu_response = []; - $menu_response['back'] = 'user.php'; + $menu_response['back'] = '/user'; $response['menu'] = $menu_response; $response['hidenav'] = true; diff --git a/app/Http/Controllers/ManageProjectRolesController.php b/app/Http/Controllers/ManageProjectRolesController.php index 95a0974a65..068ac38ea0 100644 --- a/app/Http/Controllers/ManageProjectRolesController.php +++ b/app/Http/Controllers/ManageProjectRolesController.php @@ -54,7 +54,6 @@ public function viewPage(): View|RedirectResponse } $xml = begin_XML_for_XSLT(); - $xml .= 'user.php'; $xml .= 'CDash'; $xml .= 'Project Roles'; @@ -493,7 +492,7 @@ private function register_user($projectid, $email, $firstName, $lastName, $repos // Send the email $text = 'Hello' . $prefix . $firstName . ",\n\n"; $text .= 'You have been registered to CDash because you have access to the source repository for ' . $projectname . "\n"; - $text .= 'To access your CDash account: ' . $currentURI . "/user.php\n"; + $text .= 'To access your CDash account: ' . $currentURI . "/user\n"; $text .= 'Your login is: ' . $email . "\n"; $text .= 'Your password is: ' . $pass . "\n\n"; $text .= 'Generated by CDash.'; diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php index 46cf75a360..3b0e78b2a9 100644 --- a/app/Http/Controllers/ProjectController.php +++ b/app/Http/Controllers/ProjectController.php @@ -45,9 +45,6 @@ public function apiCreateProject(): JsonResponse get_dashboard_JSON($this->project->GetName(), null, $response); } $response['hidenav'] = 1; - $menu =[]; - $menu['back'] = 'user.php'; - $response['menu'] = $menu; $nRepositories = 0; $repositories_response = []; diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index 74bafa472c..55c7b84b56 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -103,7 +103,6 @@ public function editSite(): View|RedirectResponse $userid = Auth::id(); $xml = begin_XML_for_XSLT(); - $xml .= 'user.php'; $xml .= 'CDash'; $xml .= 'Claim sites'; @@ -138,7 +137,7 @@ public function editSite(): View|RedirectResponse DELETE FROM site2user WHERE siteid=? AND userid=? ', [intval($_GET['siteid']), $userid]); - return redirect('/user.php'); + return redirect('/user'); } if ($updatesite || $geolocation) { diff --git a/app/Http/Controllers/SubProjectController.php b/app/Http/Controllers/SubProjectController.php index a008cfee46..dcd9500706 100644 --- a/app/Http/Controllers/SubProjectController.php +++ b/app/Http/Controllers/SubProjectController.php @@ -32,7 +32,6 @@ public function apiManageSubProject(): JsonResponse $pageTimer = new PageTimer(); $response = begin_JSON_response(); - $response['backurl'] = 'user.php'; $response['menutitle'] = 'CDash'; $response['menusubtitle'] = 'SubProjects'; $response['title'] = 'Manage SubProjects'; diff --git a/app/Http/Controllers/SubscribeProjectController.php b/app/Http/Controllers/SubscribeProjectController.php index 03272cfb9a..722ea9f4c5 100644 --- a/app/Http/Controllers/SubscribeProjectController.php +++ b/app/Http/Controllers/SubscribeProjectController.php @@ -24,7 +24,6 @@ public function subscribeProject(): View|RedirectResponse $user = Auth::user(); $xml = begin_XML_for_XSLT(); - $xml .= 'user.php'; $xml .= 'CDash'; $xml .= 'Subscription'; @@ -111,7 +110,7 @@ public function subscribeProject(): View|RedirectResponse GROUP BY build.siteid ) ', [$user->id, $user->id]); - return redirect('user.php?note=unsubscribedtoproject'); + return redirect('/user?note=unsubscribedtoproject'); } elseif ($UpdateSubscription) { $emailcategory_update = intval($_POST['emailcategory_update'] ?? 0); $emailcategory_configure = intval($_POST['emailcategory_configure'] ?? 0); @@ -174,7 +173,7 @@ public function subscribeProject(): View|RedirectResponse $LabelEmail->UpdateLabels(null); } // Redirect - return redirect('user.php'); + return redirect('/user'); } elseif ($Subscribe) { $emailcategory_update = intval($_POST['emailcategory_update'] ?? 0); $emailcategory_configure = intval($_POST['emailcategory_configure'] ?? 0); @@ -258,7 +257,7 @@ public function subscribeProject(): View|RedirectResponse $UserProject->AddCredential($credential); } } - return redirect('user.php?note=subscribedtoproject'); + return redirect('/user?note=subscribedtoproject'); } // XML diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 2e85691d37..832ccab7b3 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -334,7 +334,6 @@ public function edit(): View { $xml = begin_XML_for_XSLT(); $xml .= 'CDash - My Profile'; - $xml .= 'user.php'; $xml .= 'CDash'; $xml .= 'My Profile'; @@ -522,7 +521,7 @@ public function recoverPassword(): View $password = generate_password(10); $currentURI = $config->getBaseUrl(); - $url = $currentURI . '/user.php'; + $url = $currentURI . '/user'; $text = "Hello,\n\n You have asked to recover your password for CDash.\n\n"; $text .= 'Your new password is: ' . $password . "\n"; diff --git a/app/cdash/public/api/v1/manageBuildGroup.php b/app/cdash/public/api/v1/manageBuildGroup.php index d06106f8f1..6790002127 100644 --- a/app/cdash/public/api/v1/manageBuildGroup.php +++ b/app/cdash/public/api/v1/manageBuildGroup.php @@ -37,7 +37,6 @@ $userid = $user->id; $response = begin_JSON_response(); -$response['backurl'] = 'user.php'; $response['menutitle'] = 'CDash'; $response['menusubtitle'] = 'Build Groups'; $response['title'] = 'Build Groups'; diff --git a/app/cdash/public/api/v1/manageOverview.php b/app/cdash/public/api/v1/manageOverview.php index 187d66c2de..bc20330d93 100644 --- a/app/cdash/public/api/v1/manageOverview.php +++ b/app/cdash/public/api/v1/manageOverview.php @@ -25,7 +25,6 @@ $pageTimer = new PageTimer(); $response = begin_JSON_response(); -$response['backurl'] = 'user.php'; $response['menutitle'] = 'CDash'; $response['menusubtitle'] = 'Overview'; $response['hidenav'] = 1; diff --git a/app/cdash/public/css/common.css b/app/cdash/public/css/common.css index 99919c7c9d..cab9348e33 100644 --- a/app/cdash/public/css/common.css +++ b/app/cdash/public/css/common.css @@ -635,10 +635,6 @@ textarea { padding: 4px; } -.bordertop { - border-top: 1px solid black; -} - .missing {background-color: #dfdfdf; } .tabb tbody tr.odd td.missing, .striped.tabb tbody tr:nth-child(odd) td.missing { diff --git a/app/cdash/public/js/controllers/user.js b/app/cdash/public/js/controllers/user.js deleted file mode 100644 index dbe2d0f7a1..0000000000 --- a/app/cdash/public/js/controllers/user.js +++ /dev/null @@ -1,75 +0,0 @@ -CDash.controller('UserController', ["$scope", "$http", "$timeout", "apiLoader", function UserController($scope, $http, $timeout, apiLoader) { - apiLoader.loadPageData($scope, 'api/v1/user.php'); - - $scope.generateToken = function() { - const parameters = { - description: $scope.cdash.tokendescription, - scope: $scope.cdash.tokenscope === 'full_access' ? 'full_access' : 'submit_only', - projectid: $scope.cdash.tokenscope === 'full_access' - || $scope.cdash.tokenscope === 'submit_only' ? -1 : $scope.cdash.tokenscope - }; - $http.post('/api/authtokens/create', parameters) - .then(function success(s) { - const authtoken = s.data.token; - authtoken.copied = false; - authtoken.raw_token = s.data.raw_token; - - $scope.cdash.projects.forEach(project => { - if (project.id === authtoken.projectid) { - authtoken.projectname = project.name; - } - }); - - // A terrible hack to format the date the same way the DB returns them on initial page load - authtoken.expires = authtoken.expires.replace('T', ' '); - - $scope.cdash.authtokens.push(authtoken); - }, function error(e) { - $scope.cdash.message = e.data.error; - }); - }; - - $scope.copyTokenSuccess = function(token) { - token.copied = true; - token.showcheck = true; - $timeout(function() { - token.showcheck = false; - }, 2000); - }; - - $scope.revokeToken = function(authtoken) { - $http({ - url: `/api/authtokens/delete/${authtoken.hash}`, - method: 'DELETE', - }).then(function success() { - // Remove this token from our list. - let index = -1; - for(let i = 0, len = $scope.cdash.authtokens.length; i < len; i++) { - if ($scope.cdash.authtokens[i].hash === authtoken.hash) { - index = i; - break; - } - } - if (index > -1) { - $scope.cdash.authtokens.splice(index, 1); - } - }, function error(e) { - $scope.cdash.message = e.data.error; - }); - }; - - $scope.finishSetup = function() { - if ($scope.cdash.allow_full_access_tokens) { - $scope.cdash.tokenscope = 'full_access'; - } - else if ($scope.cdash.allow_submit_only_tokens) { - $scope.cdash.tokenscope = 'submit_only'; - } - else if ($scope.cdash.projects.length > 0) { - $scope.cdash.tokenscope = $scope.cdash.projects[0].id.toString(); - } - else { - $scope.cdash.tokenscope = ''; - } - } -}]); diff --git a/app/cdash/public/js/oauth2.js b/app/cdash/public/js/oauth2.js index 8911ed45a6..8498e8b979 100644 --- a/app/cdash/public/js/oauth2.js +++ b/app/cdash/public/js/oauth2.js @@ -2,7 +2,7 @@ function oauth2(type) { var requestedURI = document.URL; // Don't send the user back to the login page if that's where they came from. if (requestedURI.indexOf('login') !== -1) { - requestedURI = 'user.php'; + requestedURI = 'user'; } requestedURI = encodeURIComponent(requestedURI); diff --git a/resources/js/app.js b/resources/js/app.js index 342d4ab438..6eaac34c5c 100755 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -10,6 +10,7 @@ import BuildNotes from "./components/BuildNotes"; import BuildSummary from "./components/BuildSummary"; import BuildUpdate from "./components/BuildUpdate"; import EditProject from "./components/EditProject"; +import UserHomepage from "./components/UserHomepage"; import ManageAuthTokens from "./components/ManageAuthTokens.vue"; import ManageMeasurements from "./components/ManageMeasurements"; import Monitor from "./components/Monitor"; @@ -25,6 +26,7 @@ const cdash_components = { BuildSummary, BuildUpdate, EditProject, + UserHomepage, ManageAuthTokens, ManageMeasurements, Monitor, diff --git a/resources/js/components/EditProject.vue b/resources/js/components/EditProject.vue index 1b6c545514..10f6071058 100644 --- a/resources/js/components/EditProject.vue +++ b/resources/js/components/EditProject.vue @@ -2381,8 +2381,8 @@ export default { this.$axios .delete('/api/v1/project.php', { data: parameters}) .then(response => { - // Redirect to user.php - window.location = this.$baseURL + '/user.php'; + // Redirect to /user + window.location = this.$baseURL + '/user'; }); } }, diff --git a/resources/js/components/UserHomepage.vue b/resources/js/components/UserHomepage.vue new file mode 100644 index 0000000000..bd8df599a1 --- /dev/null +++ b/resources/js/components/UserHomepage.vue @@ -0,0 +1,804 @@ + + + + + diff --git a/resources/js/components/shared/ApiLoader.js b/resources/js/components/shared/ApiLoader.js index 2077e86783..8bc0e41a13 100644 --- a/resources/js/components/shared/ApiLoader.js +++ b/resources/js/components/shared/ApiLoader.js @@ -1,5 +1,5 @@ export default { - loadPageData: function (vm, endpoint_path) { + loadPageData: function (vm, endpoint_path) { vm.start = new Date().getTime(); vm.$axios .get(endpoint_path) @@ -47,5 +47,5 @@ export default { vm.errored = true }) .finally(() => vm.loading = false) - }, + }, } diff --git a/resources/views/admin/user.blade.php b/resources/views/admin/user.blade.php index 26eeed194d..f5852bb5aa 100644 --- a/resources/views/admin/user.blade.php +++ b/resources/views/admin/user.blade.php @@ -1,401 +1,10 @@ @extends('cdash', [ - 'angular' => true, - 'angular_controller' => 'UserController' + 'vue' => true, + 'title' => 'My Profile' ]) @section('main_content') @verbatim - - - - - - -
-
{{::cdash.message}}
-
- - -
- - - - - - - - - - - - - - - - - - - - - - - - -

My Projects

Project NameActionsBuildsBuilds per daySuccess Last 24hErrors Last 24hWarnings Last 24h
- {{::project.name}} - - - subscribe - - - claimsite - - - editproject - - - subproject - - - managegroups - - - manageusers - - - managecoverage - - - {{::project.nbuilds}} - - {{::project.average_builds}} - - {{::project.success}} - - {{::project.error}} - - {{::project.warning}} -
-
-
- - -
- - - - - - - - - - - - - - - - -

My Sites

Site - - {{::project.name}} - -
- - {{::site.name}} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
N - {{::project.nightly.update}} - - {{::project.nightly.configure}} - - {{::project.nightly.error}} - - {{::project.nightly.testfail}} - - {{::project.nightly.date}} -
C - {{::project.continuous.update}} - - {{::project.continuous.configure}} - - {{::project.continuous.error}} - - {{::project.continuous.testfail}} - - {{::project.continuous.date}} -
E - {{::project.experimental.update}} - - {{::project.experimental.configure}} - - {{::project.experimental.error}} - - {{::project.experimental.testfail}} - - {{::project.experimental.date}} -
-
-
-
- - -
- - - - - - - - - - -

Public projects

- {{::project.name}} - - - Subscribe to this project - -
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

My Authentication Tokens

-
DescriptionScopeExpiresRevoke
{{::authtoken.description}} - Full Access - - Submit Only{{::authtoken.projectname !== null && authtoken.projectname.length > 0 ? ' (' + authtoken.projectname + ')' : ''}} - {{::authtoken.expires}} - -
- Token for {{authtoken.description}}: {{authtoken.raw_token}} - - - Copy this token. It cannot be retrieved later if you leave this page! - - - - -
- - - - - - -
-
-
- - -
- - - - - - - - - -
-

Administration

-
- Start a new project -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Administration

-
- Create new project -
- Manage project roles -
- Manage subproject -
- Manage project groups -
- Manage project coverage -
- Manage banner message -
- Manage users -
- Manage authentication tokens -
- Maintenance -
- Site Statistics -
- User Statistics -
- Remove Builds -
- Monitor / Processing Statistics -
- - + @endverbatim @endsection diff --git a/resources/views/components/header.blade.php b/resources/views/components/header.blade.php index 6027449024..c27aff9e4c 100755 --- a/resources/views/components/header.blade.php +++ b/resources/views/components/header.blade.php @@ -10,7 +10,7 @@
All Dashboards @if(Auth::check()) - My CDash + My CDash @endif diff --git a/routes/web.php b/routes/web.php index 228ea34eab..5904550399 100755 --- a/routes/web.php +++ b/routes/web.php @@ -184,7 +184,8 @@ // The user must be logged in to access routes in this section. // Requests from users who are not logged in will be redirected to /login. Route::middleware(['auth'])->group(function () { - Route::get('/user.php', 'UserController@userPage'); + Route::get('/user', 'UserController@userPage'); + Route::permanentRedirect('/user.php', '/user'); // TODO: (williamjallen) send the POST route to a different function Route::match(['get', 'post'], '/profile', 'UserController@edit'); diff --git a/tests/Feature/RouteAccessTest.php b/tests/Feature/RouteAccessTest.php index db83556014..6e64544e51 100644 --- a/tests/Feature/RouteAccessTest.php +++ b/tests/Feature/RouteAccessTest.php @@ -52,7 +52,7 @@ protected function tearDown(): void private function protectedRoutes(): array { return [ - ['/user.php'], + ['/user'], ['/profile'], ['/subscribeProject.php'], ['/manageProjectRoles.php'],