Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit 938c738

Browse files
committed
webui: Migrate user page to React
1 parent f721170 commit 938c738

File tree

4 files changed

+88
-115
lines changed

4 files changed

+88
-115
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ webui/js/discussion-comments.js
6464
webui/js/discussion-create-mr.js
6565
webui/js/discussion-list.js
6666
webui/js/markdown-editor.js
67+
webui/js/user-page.js
6768

6869
# Local secrets
6970
.env

webui/jsx/app.js

+9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import DiscussionComments from "./discussion-comments";
1515
import DiscussionCreateMr from "./discussion-create-mr";
1616
import DiscussionList from "./discussion-list";
1717
import MarkdownEditor from "./markdown-editor";
18+
import UserPage from "./user-page";
1819

1920
{
2021
const rootNode = document.getElementById("db-header-root");
@@ -148,3 +149,11 @@ import MarkdownEditor from "./markdown-editor";
148149
});
149150

150151
}
152+
153+
{
154+
const rootNode = document.getElementById("user-page");
155+
if (rootNode) {
156+
const root = ReactDOM.createRoot(rootNode);
157+
root.render(<UserPage />);
158+
}
159+
}

webui/jsx/user-page.js

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const React = require("react");
2+
const ReactDOM = require("react-dom");
3+
4+
function DatabasePanel({data}) {
5+
const [isExpanded, setExpanded] = React.useState(false);
6+
7+
return (
8+
<div className="panel panel-default">
9+
<div className="panel-heading">
10+
<h3 className="panel-title">
11+
<a className="blackLink" href={"/" + userData.name + "/" + data.Database}>{data.Database}</a>
12+
<span className="pull-right">
13+
<a className="blackLink" onClick={() => setExpanded(!isExpanded)}><i className={isExpanded ? "fa fa-minus" : "fa fa-plus"}></i></a>
14+
</span>
15+
</h3>
16+
</div>
17+
<div className="panel-body">
18+
{data.OneLineDesc !== "" ? <p>{data.OneLineDesc}</p> : null}
19+
<p>
20+
<strong>Updated: </strong><span title={new Date(data.RepoModified).toLocaleString()} className="text-info">{getTimePeriod(data.RepoModified, false)}</span>&nbsp;&nbsp;
21+
<strong>Licence: </strong><span className="text-info">{data.LicenceURL === "" ? data.Licence : <a href={data.LicenceURL}>{data.Licence}</a>}</span>&nbsp;&nbsp;
22+
<strong>Size: </strong><span className="text-info">{Math.floor(data.Size / 1024).toLocaleString()} KB</span>
23+
</p>
24+
{isExpanded ? (<>
25+
<p>
26+
{data.IsLive ? null : <><strong>Commit ID: </strong><span className="text-info">{data.CommitID.substring(0, 8)}</span>&nbsp;&nbsp;</>}
27+
<strong>Contributors: </strong><span className="text-info"><a className="blackLink" href={"/contributors/" + userData.name + "/" + data.Database}>{data.Contributors}</a></span>&nbsp;&nbsp;
28+
<strong>Watchers: </strong><span className="text-info"><a className="blackLink" href={"/watchers/" + userData.name + "/" + data.Database}>{data.Watchers}</a></span>&nbsp;&nbsp;
29+
<strong>Stars: </strong><span className="text-info"><a className="blackLink" href={"/stars/" + userData.name + "/" + data.Database}>{data.Stars}</a></span>&nbsp;&nbsp;
30+
{data.IsLive ? null : <><strong>Forks: </strong><span className="text-info"><a className="blackLink" href={"/forks/" + userData.name + "/" + data.Database}>{data.Forks}</a></span>&nbsp;&nbsp;</>}
31+
<strong>Discussions: </strong><span className="text-info"><a className="blackLink" href={"/discuss/" + userData.name + "/" + data.Database}>{data.Discussions}</a></span>&nbsp;&nbsp;
32+
{data.IsLive ? null : <><strong>MRs: </strong><span className="text-info"><a className="blackLink" href={"/merge/" + userData.name + "/" + data.Database}>{data.MRs}</a></span>&nbsp;&nbsp;</>}
33+
{data.IsLive ? null : <><strong>Branches: </strong><span className="text-info"><a className="blackLink" href={"/branches/" + userData.name + "/" + data.Database}>{data.Branches}</a></span>&nbsp;&nbsp;</>}
34+
{data.IsLive ? null : <><strong>Releases: </strong><span className="text-info"><a className="blackLink" href={"/releases/" + userData.name + "/" + data.Database}>{data.Releases}</a></span>&nbsp;&nbsp;</>}
35+
{data.IsLive ? null : <><strong>Tags: </strong><span className="text-info"><a className="blackLink" href={"/tags/" + userData.name + "/" + data.Database}>{data.Tags}</a></span>&nbsp;</>}
36+
</p>
37+
{data.SourceURL === "" ? null : <p><strong>Source: </strong><span className="text-info"><a className="blackLink" href={data.SourceURL}>{data.SourceURL}</a></span></p>}
38+
</>) : null}
39+
</div>
40+
</div>
41+
);
42+
}
43+
44+
function DatabasePanelGroup({title, noDatabasesMessage, databases}) {
45+
const databaseRows = databases === null ? null : databases.map(d => DatabasePanel({data: d}));
46+
47+
return (<>
48+
<h3>{title}</h3>
49+
{databaseRows ? databaseRows : (<h4><em>{noDatabasesMessage}</em></h4>)}
50+
</>);
51+
}
52+
53+
export default function UserPage() {
54+
return (<>
55+
<h2>
56+
{userData.avatarUrl ? <img src={userData.avatarUrl} height="48" width="48" style={{border: "1px solid #8c8c8c"}} /> : null}&nbsp;
57+
{userData.name + (userData.fullName ? ": " + userData.fullName : "")}'s <span data-cy="userpg">public projects</span>
58+
</h2>
59+
<div className="row">
60+
<div className="col-md-6">
61+
<DatabasePanelGroup title="Public standard databases" noDatabasesMessage="No public standard databases yet" databases={userData.databases} />
62+
</div>
63+
<div className="col-md-6">
64+
<DatabasePanelGroup title="Public live databases" noDatabasesMessage="No public live databases yet" databases={userData.liveDatabases} />
65+
</div>
66+
</div>
67+
</>);
68+
}

webui/templates/user.html

+10-115
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,20 @@
11
[[ define "userPage" ]]
22
<!doctype html>
3-
<html ng-app="DBHub" ng-controller="userView">
3+
<html>
44
[[ template "head" . ]]
55
<body>
66
[[ template "header" . ]]
7-
<div>
8-
<div class="row" style="margin-bottom: 10px;">
9-
<div class="col-md-12">
10-
<h2 id="viewuser" style="margin-top: 10px;">
11-
<div class="pull-left">
12-
[[ if .UserAvatarURL ]]<img src="[[ .UserAvatarURL ]]" height="48" width="48" style="border: 1px solid #8c8c8c;"/>[[ end ]] [[ .UserName ]][[ if .FullName ]] : [[ .FullName ]][[ end ]]'s <span data-cy="userpg">public projects</span>
13-
</div>
14-
<div class="pull-right">
15-
[[ if or (.DBRows) (.PublicLiveDBS) ]]
16-
<button type="button" class="btn btn-default" ng-click="toggleCollapsed()">{{ titleCollapsed }}</button>
17-
[[ end ]]
18-
</div>
19-
</h2>
20-
</div>
21-
</div>
22-
<div class="row">
23-
<div class="col-md-6">
24-
<div class="pull-left" style="padding: 8px 0;">
25-
<h3 style="display: inline; vertical-align: middle;">Public standard databases</h3>
26-
</div>
27-
[[ if .DBRows ]]
28-
<table class="table table-striped table-responsive profileTable" data-cy="pubdbtbl">
29-
<tr ng-repeat="row in db.Databases">
30-
<td>
31-
<h4><a class="blackLink" href="/{{ meta.Owner + '/' + row.Database }}">{{ row.Database }}</a></h4>
32-
<div ng-if="row.OneLineDesc != ''" style="padding-bottom: 5px;">{{ row.OneLineDesc }}</div>
33-
<b>Updated:</b> <span title="{{ row.RepoModified | date : 'medium' }}" style="color: grey;">{{ getTimePeriodTxt(row.RepoModified, false) }}</span> &nbsp;
34-
<b>Licence:</b>
35-
<span ng-if="row.LicenceURL == ''">{{ row.Licence }}</span>
36-
<span ng-if="row.LicenceURL != ''"><a class="blackLink" href="{{ row.LicenceURL }}">{{ row.Licence }}</a></span> &nbsp;
37-
<b>Size:</b> {{ row.Size / 1024 | number : 0 }} KB &nbsp;
38-
<div uib-collapse="isCollapsed" style="padding-top: 5px;">
39-
<b>Commit ID:</b> {{ row.CommitID | limitTo: 8 }} &nbsp;
40-
<b>Contributors:</b> <a class="blackLink" href="/contributors/{{ meta.Owner }}/{{ row.Database }}">{{ row.Contributors }}</a>
41-
<b>Watchers:</b> {{ row.Watchers }} &nbsp;
42-
<b>Stars:</b> <a class="blackLink" href="/stars/{{ meta.Owner + '/' + row.Database }}">{{ row.Stars }}</a> &nbsp;
43-
<b>Forks:</b> <a class="blackLink" href="/forks/{{ meta.Owner + '/' + row.Database }}">{{ row.Forks }}</a> &nbsp;
44-
<b>Discussions:</b> <a class="blackLink" href="/discuss/{{ meta.Owner + '/' + row.Database }}">{{ row. Discussions }}</a> &nbsp;
45-
<b>MRs:</b> {{ row.MRs }} &nbsp;
46-
<b>Branches:</b> <a class="blackLink" href="/branches/{{ meta.Owner + '/' + row.Database }}">{{ row.Branches }}</a> &nbsp;
47-
<b>Releases:</b> <a class="blackLink" href="/releases/{{ meta.Owner + '/' + row.Database }}">{{ row.Releases }}</a> &nbsp;
48-
<b>Tags:</b> <a class="blackLink" href="/tags/{{ meta.Owner + '/' + row.Database }}">{{ row.Tags }}</a><br />
49-
<div ng-if="row.SourceURL != ''" style="padding-top: 5px;"><b>Source:</b> <a class="blackLink" href="{{ row.SourceURL }}" ng-bind="row.SourceURL"></a></div>
50-
</div>
51-
</td>
52-
</tr>
53-
</table>
54-
[[ else ]]
55-
<table class="table table-striped table-responsive profileTable" data-cy="pubdbtbl">
56-
<tr>
57-
<td>
58-
<h4>No public standard databases yet</h4>
59-
</td>
60-
</tr>
61-
</table>
62-
[[ end ]]
63-
</div>
64-
<div class="col-md-6">
65-
<div class="pull-left" style="padding: 8px 0;">
66-
<h3 style="display: inline; vertical-align: middle;">Public live databases (<span style="color: blue">in beta testing</span>)</h3>
67-
</div>
68-
[[ if .PublicLiveDBS ]]
69-
<table class="table table-striped table-responsive profileTable" data-cy="publivedbstbl">
70-
<tr ng-repeat="row in publivedbs">
71-
<td style="border: 1px solid #ddd">
72-
<h4><a class="blackLink" href="/{{ row.Owner + '/' + row.Database }}" data-cy="livedb-row{{ $index }}">{{ row.Owner }}/{{ row.Database }}</a></h4>
73-
<b>Size:</b> {{ row.Size / 1024 | number : 0 }} KB &nbsp;
74-
<span ng-if="row.SourceURL != ''" style="padding-top: 5px;"><b>Source:</b> <a class="blackLink" href="{{ row.SourceURL }}" ng-bind="row.SourceURL"></a></span>
75-
<div uib-collapse="isCollapsed" style="padding-top: 5px;">
76-
<b>Contributors:</b> <a class="blackLink" href="/contributors/{{ meta.Owner }}/{{ row.Database }}">{{ row.Contributors }}</a>
77-
<b>Watchers:</b> {{ row.Watchers }} &nbsp;
78-
<b>Stars:</b> <a class="blackLink" href="/stars/{{ meta.Owner + '/' + row.Database }}">{{ row.Stars }}</a> &nbsp;
79-
<b>Discussions:</b> <a class="blackLink" href="/discuss/{{ meta.Owner + '/' + row.Database }}">{{ row. Discussions }}</a> &nbsp;
80-
</div>
81-
</td>
82-
</tr>
83-
</table>
84-
[[ else ]]
85-
<table class="table table-striped table-responsive profileTable" data-cy="publivedbstbl">
86-
<tr>
87-
<td>
88-
<h4>No public live databases yet</h4>
89-
</td>
90-
</tr>
91-
</table>
92-
[[ end ]]
93-
</div>
94-
</div>
95-
</div>
96-
[[ template "footer" . ]]
7+
<div id="user-page"></div>
978
<script>
98-
let app = angular.module('DBHub', ['ui.bootstrap', 'ngSanitize']);
99-
app.controller('userView', function($scope) {
100-
$scope.meta = { Owner: "[[ .UserName ]]" };
101-
$scope.db = { Databases: [[ .DBRows ]] };
102-
$scope.publivedbs = [[ .PublicLiveDBS ]];
103-
104-
// Returns a nicely presented "time elapsed" string
105-
$scope.getTimePeriodTxt = function(date1, includeOn) {
106-
return getTimePeriod(date1, includeOn)
107-
};
108-
109-
// Toggle whether to show databases collapsed or not
110-
$scope.isCollapsed = true;
111-
$scope.titleCollapsed = "Expand all";
112-
$scope.toggleCollapsed = function() {
113-
if ($scope.isCollapsed === true) {
114-
$scope.isCollapsed = false;
115-
$scope.titleCollapsed = "Collapse all";
116-
} else {
117-
$scope.isCollapsed = true;
118-
$scope.titleCollapsed = "Expand all";
119-
}
120-
};
121-
});
9+
const userData = {
10+
avatarUrl: "[[ .UserAvatarURL ]]",
11+
name: "[[ .UserName ]]",
12+
fullName: "[[ .FullName ]]",
13+
databases: [[ .DBRows ]],
14+
liveDatabases: [[ .PublicLiveDBS ]],
15+
};
12216
</script>
17+
[[ template "footer" . ]]
12318
</body>
12419
</html>
12520
[[ end ]]

0 commit comments

Comments
 (0)