Skip to content

Commit

Permalink
webui: Migrate user page to React
Browse files Browse the repository at this point in the history
  • Loading branch information
MKleusberg committed Apr 26, 2023
1 parent f721170 commit 938c738
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 115 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ webui/js/discussion-comments.js
webui/js/discussion-create-mr.js
webui/js/discussion-list.js
webui/js/markdown-editor.js
webui/js/user-page.js

# Local secrets
.env
Expand Down
9 changes: 9 additions & 0 deletions webui/jsx/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import DiscussionComments from "./discussion-comments";
import DiscussionCreateMr from "./discussion-create-mr";
import DiscussionList from "./discussion-list";
import MarkdownEditor from "./markdown-editor";
import UserPage from "./user-page";

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

}

{
const rootNode = document.getElementById("user-page");
if (rootNode) {
const root = ReactDOM.createRoot(rootNode);
root.render(<UserPage />);
}
}
68 changes: 68 additions & 0 deletions webui/jsx/user-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const React = require("react");
const ReactDOM = require("react-dom");

function DatabasePanel({data}) {
const [isExpanded, setExpanded] = React.useState(false);

return (
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title">
<a className="blackLink" href={"/" + userData.name + "/" + data.Database}>{data.Database}</a>
<span className="pull-right">
<a className="blackLink" onClick={() => setExpanded(!isExpanded)}><i className={isExpanded ? "fa fa-minus" : "fa fa-plus"}></i></a>
</span>
</h3>
</div>
<div className="panel-body">
{data.OneLineDesc !== "" ? <p>{data.OneLineDesc}</p> : null}
<p>
<strong>Updated: </strong><span title={new Date(data.RepoModified).toLocaleString()} className="text-info">{getTimePeriod(data.RepoModified, false)}</span>&nbsp;&nbsp;
<strong>Licence: </strong><span className="text-info">{data.LicenceURL === "" ? data.Licence : <a href={data.LicenceURL}>{data.Licence}</a>}</span>&nbsp;&nbsp;
<strong>Size: </strong><span className="text-info">{Math.floor(data.Size / 1024).toLocaleString()} KB</span>
</p>
{isExpanded ? (<>
<p>
{data.IsLive ? null : <><strong>Commit ID: </strong><span className="text-info">{data.CommitID.substring(0, 8)}</span>&nbsp;&nbsp;</>}
<strong>Contributors: </strong><span className="text-info"><a className="blackLink" href={"/contributors/" + userData.name + "/" + data.Database}>{data.Contributors}</a></span>&nbsp;&nbsp;
<strong>Watchers: </strong><span className="text-info"><a className="blackLink" href={"/watchers/" + userData.name + "/" + data.Database}>{data.Watchers}</a></span>&nbsp;&nbsp;
<strong>Stars: </strong><span className="text-info"><a className="blackLink" href={"/stars/" + userData.name + "/" + data.Database}>{data.Stars}</a></span>&nbsp;&nbsp;
{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;</>}
<strong>Discussions: </strong><span className="text-info"><a className="blackLink" href={"/discuss/" + userData.name + "/" + data.Database}>{data.Discussions}</a></span>&nbsp;&nbsp;
{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;</>}
{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;</>}
{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;</>}
{data.IsLive ? null : <><strong>Tags: </strong><span className="text-info"><a className="blackLink" href={"/tags/" + userData.name + "/" + data.Database}>{data.Tags}</a></span>&nbsp;</>}
</p>
{data.SourceURL === "" ? null : <p><strong>Source: </strong><span className="text-info"><a className="blackLink" href={data.SourceURL}>{data.SourceURL}</a></span></p>}
</>) : null}
</div>
</div>
);
}

function DatabasePanelGroup({title, noDatabasesMessage, databases}) {
const databaseRows = databases === null ? null : databases.map(d => DatabasePanel({data: d}));

return (<>
<h3>{title}</h3>
{databaseRows ? databaseRows : (<h4><em>{noDatabasesMessage}</em></h4>)}
</>);
}

export default function UserPage() {
return (<>
<h2>
{userData.avatarUrl ? <img src={userData.avatarUrl} height="48" width="48" style={{border: "1px solid #8c8c8c"}} /> : null}&nbsp;
{userData.name + (userData.fullName ? ": " + userData.fullName : "")}'s <span data-cy="userpg">public projects</span>
</h2>
<div className="row">
<div className="col-md-6">
<DatabasePanelGroup title="Public standard databases" noDatabasesMessage="No public standard databases yet" databases={userData.databases} />
</div>
<div className="col-md-6">
<DatabasePanelGroup title="Public live databases" noDatabasesMessage="No public live databases yet" databases={userData.liveDatabases} />
</div>
</div>
</>);
}
125 changes: 10 additions & 115 deletions webui/templates/user.html
Original file line number Diff line number Diff line change
@@ -1,125 +1,20 @@
[[ define "userPage" ]]
<!doctype html>
<html ng-app="DBHub" ng-controller="userView">
<html>
[[ template "head" . ]]
<body>
[[ template "header" . ]]
<div>
<div class="row" style="margin-bottom: 10px;">
<div class="col-md-12">
<h2 id="viewuser" style="margin-top: 10px;">
<div class="pull-left">
[[ 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>
</div>
<div class="pull-right">
[[ if or (.DBRows) (.PublicLiveDBS) ]]
<button type="button" class="btn btn-default" ng-click="toggleCollapsed()">{{ titleCollapsed }}</button>
[[ end ]]
</div>
</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="pull-left" style="padding: 8px 0;">
<h3 style="display: inline; vertical-align: middle;">Public standard databases</h3>
</div>
[[ if .DBRows ]]
<table class="table table-striped table-responsive profileTable" data-cy="pubdbtbl">
<tr ng-repeat="row in db.Databases">
<td>
<h4><a class="blackLink" href="/{{ meta.Owner + '/' + row.Database }}">{{ row.Database }}</a></h4>
<div ng-if="row.OneLineDesc != ''" style="padding-bottom: 5px;">{{ row.OneLineDesc }}</div>
<b>Updated:</b> <span title="{{ row.RepoModified | date : 'medium' }}" style="color: grey;">{{ getTimePeriodTxt(row.RepoModified, false) }}</span> &nbsp;
<b>Licence:</b>
<span ng-if="row.LicenceURL == ''">{{ row.Licence }}</span>
<span ng-if="row.LicenceURL != ''"><a class="blackLink" href="{{ row.LicenceURL }}">{{ row.Licence }}</a></span> &nbsp;
<b>Size:</b> {{ row.Size / 1024 | number : 0 }} KB &nbsp;
<div uib-collapse="isCollapsed" style="padding-top: 5px;">
<b>Commit ID:</b> {{ row.CommitID | limitTo: 8 }} &nbsp;
<b>Contributors:</b> <a class="blackLink" href="/contributors/{{ meta.Owner }}/{{ row.Database }}">{{ row.Contributors }}</a>
<b>Watchers:</b> {{ row.Watchers }} &nbsp;
<b>Stars:</b> <a class="blackLink" href="/stars/{{ meta.Owner + '/' + row.Database }}">{{ row.Stars }}</a> &nbsp;
<b>Forks:</b> <a class="blackLink" href="/forks/{{ meta.Owner + '/' + row.Database }}">{{ row.Forks }}</a> &nbsp;
<b>Discussions:</b> <a class="blackLink" href="/discuss/{{ meta.Owner + '/' + row.Database }}">{{ row. Discussions }}</a> &nbsp;
<b>MRs:</b> {{ row.MRs }} &nbsp;
<b>Branches:</b> <a class="blackLink" href="/branches/{{ meta.Owner + '/' + row.Database }}">{{ row.Branches }}</a> &nbsp;
<b>Releases:</b> <a class="blackLink" href="/releases/{{ meta.Owner + '/' + row.Database }}">{{ row.Releases }}</a> &nbsp;
<b>Tags:</b> <a class="blackLink" href="/tags/{{ meta.Owner + '/' + row.Database }}">{{ row.Tags }}</a><br />
<div ng-if="row.SourceURL != ''" style="padding-top: 5px;"><b>Source:</b> <a class="blackLink" href="{{ row.SourceURL }}" ng-bind="row.SourceURL"></a></div>
</div>
</td>
</tr>
</table>
[[ else ]]
<table class="table table-striped table-responsive profileTable" data-cy="pubdbtbl">
<tr>
<td>
<h4>No public standard databases yet</h4>
</td>
</tr>
</table>
[[ end ]]
</div>
<div class="col-md-6">
<div class="pull-left" style="padding: 8px 0;">
<h3 style="display: inline; vertical-align: middle;">Public live databases (<span style="color: blue">in beta testing</span>)</h3>
</div>
[[ if .PublicLiveDBS ]]
<table class="table table-striped table-responsive profileTable" data-cy="publivedbstbl">
<tr ng-repeat="row in publivedbs">
<td style="border: 1px solid #ddd">
<h4><a class="blackLink" href="/{{ row.Owner + '/' + row.Database }}" data-cy="livedb-row{{ $index }}">{{ row.Owner }}/{{ row.Database }}</a></h4>
<b>Size:</b> {{ row.Size / 1024 | number : 0 }} KB &nbsp;
<span ng-if="row.SourceURL != ''" style="padding-top: 5px;"><b>Source:</b> <a class="blackLink" href="{{ row.SourceURL }}" ng-bind="row.SourceURL"></a></span>
<div uib-collapse="isCollapsed" style="padding-top: 5px;">
<b>Contributors:</b> <a class="blackLink" href="/contributors/{{ meta.Owner }}/{{ row.Database }}">{{ row.Contributors }}</a>
<b>Watchers:</b> {{ row.Watchers }} &nbsp;
<b>Stars:</b> <a class="blackLink" href="/stars/{{ meta.Owner + '/' + row.Database }}">{{ row.Stars }}</a> &nbsp;
<b>Discussions:</b> <a class="blackLink" href="/discuss/{{ meta.Owner + '/' + row.Database }}">{{ row. Discussions }}</a> &nbsp;
</div>
</td>
</tr>
</table>
[[ else ]]
<table class="table table-striped table-responsive profileTable" data-cy="publivedbstbl">
<tr>
<td>
<h4>No public live databases yet</h4>
</td>
</tr>
</table>
[[ end ]]
</div>
</div>
</div>
[[ template "footer" . ]]
<div id="user-page"></div>
<script>
let app = angular.module('DBHub', ['ui.bootstrap', 'ngSanitize']);
app.controller('userView', function($scope) {
$scope.meta = { Owner: "[[ .UserName ]]" };
$scope.db = { Databases: [[ .DBRows ]] };
$scope.publivedbs = [[ .PublicLiveDBS ]];

// Returns a nicely presented "time elapsed" string
$scope.getTimePeriodTxt = function(date1, includeOn) {
return getTimePeriod(date1, includeOn)
};

// Toggle whether to show databases collapsed or not
$scope.isCollapsed = true;
$scope.titleCollapsed = "Expand all";
$scope.toggleCollapsed = function() {
if ($scope.isCollapsed === true) {
$scope.isCollapsed = false;
$scope.titleCollapsed = "Collapse all";
} else {
$scope.isCollapsed = true;
$scope.titleCollapsed = "Expand all";
}
};
});
const userData = {
avatarUrl: "[[ .UserAvatarURL ]]",
name: "[[ .UserName ]]",
fullName: "[[ .FullName ]]",
databases: [[ .DBRows ]],
liveDatabases: [[ .PublicLiveDBS ]],
};
</script>
[[ template "footer" . ]]
</body>
</html>
[[ end ]]

1 comment on commit 938c738

@justinclift
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now live in production. 😄

Please sign in to comment.