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

Commit 525691d

Browse files
committed
webui: Migration commits page to React
1 parent 29b4dc6 commit 525691d

File tree

5 files changed

+150
-163
lines changed

5 files changed

+150
-163
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ webui/js/dbhub.js*
5353
webui/js/app.js
5454
webui/js/auth.js
5555
webui/js/branches.js
56+
webui/js/database-commits.js
5657
webui/js/database-settings.js
5758
webui/js/database-tags.js
5859
webui/js/database-view.js

webui/jsx/app.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import ModalImage from "react-modal-image";
55

66
import Auth from "./auth";
77
import BranchesTable from "./branches";
8+
import DatabaseCommits from "./database-commits";
89
import DatabaseSettings from "./database-settings";
910
import DatabaseTags from "./database-tags";
1011
import DatabaseView from "./database-view";
@@ -37,6 +38,14 @@ import MarkdownEditor from "./markdown-editor";
3738
}
3839
}
3940

41+
{
42+
const rootNode = document.getElementById("database-commits");
43+
if (rootNode) {
44+
const root = ReactDOM.createRoot(rootNode);
45+
root.render(<DatabaseCommits />);
46+
}
47+
}
48+
4049
{
4150
const rootNode = document.getElementById("database-settings");
4251
if (rootNode) {

webui/jsx/database-commits.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const React = require("react");
2+
const ReactDOM = require("react-dom");
3+
4+
import Select from "react-dropdown-select";
5+
6+
function DatabaseCommitRow({data, index, branch, setStatusMessage, setStatusMessageColour}) {
7+
const [commitIndex, setCommitIndex] = React.useState(Number(index));
8+
9+
// Bounce to the page for creating branches
10+
function createBranch() {
11+
window.location = "/createbranch/" + meta.owner + "/" + meta.database + "?commit=" + data.id;
12+
}
13+
14+
// Bounce to the page for creating tags
15+
function createTag() {
16+
window.location = "/createtag/" + meta.owner + "/" + meta.database + "?commit=" + data.id;
17+
}
18+
19+
// Bounce to the page for viewing changes
20+
function viewChanges() {
21+
window.location = "/diffs/" + meta.owner + "/" + meta.database + "?commit_a=" + commitData[commitIndex + 1].id + "&commit_b=" + data.id;
22+
}
23+
24+
// Delete a commit from the viewed branch
25+
function deleteCommit() {
26+
fetch("/x/deletecommit/", {
27+
method: "post",
28+
headers: {
29+
"Content-Type": "application/x-www-form-urlencoded"
30+
},
31+
body: new URLSearchParams({
32+
"branch": branch,
33+
"commit": data.id,
34+
"dbname": meta.database,
35+
"username": meta.owner
36+
}),
37+
}).then((response) => {
38+
if (!response.ok) {
39+
return Promise.reject(response);
40+
}
41+
42+
window.location = "/commits/" + meta.owner + "/" + meta.database + "?branch=" + branch;
43+
})
44+
.catch((error) => {
45+
// The delete failed, so display the returned error message
46+
setStatusMessageColour("red");
47+
setStatusMessage("Error: " + error.text());
48+
});
49+
}
50+
51+
// Is this the last and/or head commit?
52+
const isHeadCommit = data.id == commitData[0].id;
53+
const isLastCommit = data.id == commitData[commitData.length - 1].id;
54+
55+
return (
56+
<tr>
57+
<td>
58+
{meta.owner === authInfo.loggedInUser ? <p><button className="btn btn-primary" onClick={() => createBranch()} data-cy="createbranchbtn">Create Branch</button></p> : null}
59+
{isLastCommit === false ? <p><button className="btn btn-primary" onClick={() => viewChanges()} data-cy="viewchangesbtn">View Changes</button></p> : null}
60+
{meta.owner === authInfo.loggedInUser ? <p><button className="btn btn-primary" onClick={() => createTag()} data-cy="createtagrelbtn">Create Tag or Release</button></p> : null}
61+
{meta.owner === authInfo.loggedInUser && isHeadCommit && !isLastCommit ? <p><button className="btn btn-danger" onClick={() => deleteCommit()} data-cy="delcommitbtn">Delete Commit</button></p> : null}
62+
</td>
63+
<td dangerouslySetInnerHTML={{__html: data.message}}>
64+
</td>
65+
<td>
66+
{data.avatar_url !== "" ? <img src={data.avatar_url} height="30" width="30" style={{border: "1px solid #8c8c8c"}} /> : null}&nbsp;
67+
<a className="blackLink" href={"/" + data.author_user_name}>{data.author_name}</a>
68+
</td>
69+
<td>
70+
<span title={new Date(data.timestamp).toLocaleString()}>{getTimePeriod(data.timestamp, false)}</span>
71+
</td>
72+
<td>
73+
<a className="blackLink" href={"/" + meta.owner + "/" + meta.database + "?branch=" + branch + "&commit=" + data.id} data-cy="commitlnk">{data.id.substring(0, 8)}</a>
74+
</td>
75+
</tr>
76+
);
77+
}
78+
79+
export default function DatabaseCommits() {
80+
const urlParams = new URL(window.location.href).searchParams;
81+
82+
const [statusMessage, setStatusMessage] = React.useState("");
83+
const [statusMessageColour, setStatusMessageColour] = React.useState("");
84+
const [branch, setBranch] = React.useState(urlParams.get("branch") ? urlParams.get("branch") : meta.defaultBranch);
85+
86+
// Change the branch being viewed
87+
function changeBranch(branchName) {
88+
window.location = "/commits/" + meta.owner + "/" + meta.database + "?branch=" + branchName;
89+
}
90+
91+
// Prepare branch names
92+
let branches = [];
93+
for (const [name, data] of Object.entries(branchData)) {
94+
branches.push({name: name});
95+
}
96+
97+
// Render commit rows
98+
let rows = [];
99+
for (const [index, data] of Object.entries(commitData)) {
100+
rows.push(<DatabaseCommitRow data={data} index={index} branch={branch} />);
101+
}
102+
103+
return (<>
104+
<div className="row">
105+
<div className="col-md-12 text-center">
106+
<span data-cy="commithist">Commit history for branch</span>&nbsp;
107+
<div style={{display: "inline-block"}}>
108+
<Select name="branchname" required={true} labelField="name" valueField="name" onChange={(values) => changeBranch(values[0].name)} options={branches} values={[{name: branch}]} />
109+
</div>
110+
</div>
111+
</div>
112+
{statusMessage !== "" ? (
113+
<div className="row">
114+
<div className="col-md-12">
115+
<div style={{textAlign: "center", paddingBottom: "8px"}}>
116+
<h4 style={{color: statusMessageColour}}>{statusMessage}</h4>
117+
</div>
118+
</div>
119+
</div>
120+
) : null}
121+
<table id="contents" className="table table-striped table-responsive">
122+
<thead>
123+
<tr>
124+
<th>Actions</th><th>Message</th><th>Author</th><th>Date</th><th>Commit ID</th>
125+
</tr>
126+
</thead>
127+
<tbody>
128+
{rows}
129+
</tbody>
130+
</table>
131+
</>);
132+
}

webui/pages.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ func commitsPage(w http.ResponseWriter, r *http.Request) {
9797
Tree com.DBTree `json:"tree"`
9898
}
9999
var pageData struct {
100-
Branch string
101-
Branches []string
100+
Branches map[string]com.BranchEntry
102101
DB com.SQLiteDBinfo
103102
History []HistEntry
104103
PageMeta PageMetaInfo
@@ -134,7 +133,7 @@ func commitsPage(w http.ResponseWriter, r *http.Request) {
134133
}
135134

136135
// Read the branch heads list from the database
137-
branches, err := com.GetBranches(dbName.Owner, dbName.Database)
136+
pageData.Branches, err = com.GetBranches(dbName.Owner, dbName.Database)
138137
if err != nil {
139138
errorPage(w, r, http.StatusInternalServerError, err.Error())
140139
return
@@ -146,7 +145,7 @@ func commitsPage(w http.ResponseWriter, r *http.Request) {
146145
}
147146

148147
// Work out the head commit ID for the requested branch
149-
headCom, ok := branches[branchName]
148+
headCom, ok := pageData.Branches[branchName]
150149
if !ok {
151150
// Unknown branch
152151
errorPage(w, r, http.StatusInternalServerError, fmt.Sprintf("Branch '%s' not found", branchName))
@@ -253,12 +252,6 @@ func commitsPage(w http.ResponseWriter, r *http.Request) {
253252
return
254253
}
255254

256-
// Fill out the metadata
257-
pageData.Branch = branchName
258-
for i := range branches {
259-
pageData.Branches = append(pageData.Branches, i)
260-
}
261-
262255
// Render the page
263256
t := tmpl.Lookup("commitsPage")
264257
err = t.Execute(w, pageData)

webui/templates/commits.html

Lines changed: 5 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,167 +1,19 @@
11
[[ define "commitsPage" ]]
22
<!doctype html>
3-
<html ng-app="DBHub" ng-controller="commitsView">
3+
<html>
44
[[ template "head" . ]]
55
<body>
66
[[ template "header" . ]]
77
<div>
88
<div id="db-header-root"></div>
9-
<div class="row">
10-
<div class="col-md-12">
11-
<div style="text-align: center; margin: 1% 0">
12-
<span data-cy="commithist">Commit history for branch</span>
13-
<span class="dropdown">
14-
<span class="btn-group" uib-dropdown keyboard-nav="true">
15-
<button id="branchname" type="button" class="btn" data-cy="branchdropdown">{{ meta.Branch }}</button>
16-
17-
<button type="button" uib-dropdown-toggle class="btn btn-default">
18-
<span class="caret"></span>
19-
</button>
20-
<ul uib-dropdown-menu class="dropdown-menu" role="menu">
21-
<li ng-repeat="row in meta.Branches" role="menuitem" ng-click="changeBranch(row)" data-cy="commit-{{ row }}">
22-
<a href="">{{ row }}</a>
23-
</li>
24-
</ul>
25-
</span>
26-
</span>
27-
</div>
28-
</div>
29-
</div>
30-
<div class="row" ng-if="statusMessage != ''">
31-
<div class="col-md-12">
32-
<div style="text-align: center; padding-bottom: 8px;">
33-
<h4 style="color: red;">&nbsp;{{ statusMessage }}</h4>
34-
</div>
35-
</div>
36-
</div>
37-
<div class="row">
38-
<div class="col-md-12">
39-
<div style="border: 1px solid #DDD; border-radius: 7px; margin-bottom: 10px; padding: 0;">
40-
<table id="contents" class="table table-striped table-responsive" style="margin: 0;">
41-
<thead>
42-
<tr>
43-
[[ if eq .DB.Info.Owner .PageMeta.LoggedInUser ]]
44-
<th>Actions</th>
45-
[[ end ]]
46-
<th width="25%" colspan="2">Author</th><th>Date</th><th>Commit ID</th>
47-
</tr>
48-
</thead>
49-
<tbody>
50-
<tr ng-repeat-start="row in meta.History">
51-
[[ if eq .DB.Info.Owner .PageMeta.LoggedInUser ]]
52-
<td style="border-style: none;">
53-
<button class="btn btn-primary" ng-click="createBranch(row.id)" data-cy="createbranchbtn">Create Branch</button>
54-
</td>
55-
[[ end ]]
56-
<td width="15%" style="border-style: none;">
57-
<img ng-if="row.avatar_url != ''" ng-attr-src="{{ decodeAmp(row.avatar_url) }}" height="30" width="30" style="border: 1px solid #8c8c8c;"/>
58-
<a class="blackLink" href="/{{ row.author_user_name }}">{{ row.author_name }}</a>
59-
</td>
60-
<td width="10%" style="border-style: none;">&nbsp;</td>
61-
<td style="border-style: none;">
62-
<span title="{{ row.timestamp | date : 'medium' }}">{{ getTimePeriodTxt(row.timestamp, false) }}</span>
63-
</td>
64-
<td style="border-style: none; font-family: Monospace; font-size: large; text-align: left; vertical-align: text-bottom;">
65-
<a class="blackLink" href="/[[ .DB.Info.Owner ]]/[[ .DB.Info.Database ]]?branch={{ meta.Branch }}&commit={{ row.id }}">{{ row.id }}</a>
66-
</td>
67-
</tr>
68-
<tr ng-repeat-end class="tableRow">
69-
<td style="border-style: none;">
70-
<span ng-if="row.id != lastCommit">
71-
<button class="btn btn-primary" ng-click="viewChanges(meta.History[$index + 1].id, row.id)">View Changes</button>
72-
<br /><br />
73-
</span>
74-
[[ if eq .DB.Info.Owner .PageMeta.LoggedInUser ]]
75-
<button class="btn btn-primary" ng-click="createTag(row.id)" data-cy="createtagrelbtn">Create Tag or Release</button>
76-
<span ng-if="(row.id == headCommit) && (row.id != lastCommit)">
77-
<br /><br />
78-
<button class="btn btn-danger" ng-click="deleteCommit(row.id)" data-cy="delcommitbtn">Delete Commit</button>
79-
</span>&nbsp;
80-
[[ end ]]
81-
</td>
82-
<td width="15%" style="border-style: none;">&nbsp;</td>
83-
<td colspan="3" style="border-style: none; vertical-align: top;">
84-
<span ng-bind-html="row.message"></span>
85-
</td>
86-
</tr>
87-
</tbody>
88-
</table>
89-
</div>
90-
</div>
91-
</div>
9+
<div id="database-commits"></div>
9210
</div>
9311
[[ template "script_db_header" . ]]
94-
[[ template "footer" . ]]
9512
<script>
96-
let app = angular.module('DBHub', ['ui.bootstrap', 'ngSanitize']);
97-
app.controller('commitsView', function($scope, $http, $httpParamSerializerJQLike) {
98-
$scope.meta = {
99-
Branch: "[[ .Branch ]]",
100-
Branches: [[ .Branches ]],
101-
History: [[ .History ]]
102-
}
103-
104-
// Take note of the first and last commit IDs, so we can compare against them
105-
let numCommits = $scope.meta.History.length;
106-
$scope.headCommit = $scope.meta.History[0].id;
107-
$scope.lastCommit = $scope.meta.History[numCommits - 1].id;
108-
109-
// Change the branch being viewed
110-
$scope.changeBranch = function(branchName){
111-
window.location = "/commits/[[ .DB.Info.Owner ]]/[[ .DB.Info.Database ]]?branch=" + branchName;
112-
};
113-
114-
// Bounce to the page for creating branches
115-
$scope.createBranch = function(commit){
116-
window.location = "/createbranch/[[ .DB.Info.Owner ]]/[[ .DB.Info.Database ]]?commit=" + commit;
117-
};
118-
119-
// Bounce to the page for creating tags
120-
$scope.createTag = function(commit){
121-
window.location = "/createtag/[[ .DB.Info.Owner ]]/[[ .DB.Info.Database ]]?commit=" + commit;
122-
};
123-
124-
// Bounce to the page for viewing changes
125-
$scope.viewChanges = function(commit_a, commit_b){
126-
window.location = "/diffs/[[ .DB.Info.Owner ]]/[[ .DB.Info.Database ]]?commit_a=" + commit_a + "&commit_b=" + commit_b;
127-
};
128-
129-
// Change \u0026 to &
130-
$scope.decodeAmp = function(str) {
131-
return decodeURIComponent(str);
132-
};
133-
134-
// Delete a commit from the viewed branch
135-
$scope.statusMessage = "";
136-
$scope.deleteCommit = function(commit) {
137-
$http({
138-
method: "POST",
139-
url: "/x/deletecommit/",
140-
data: $httpParamSerializerJQLike({
141-
"branch": $scope.meta.Branch,
142-
"commit": commit,
143-
"dbname": [[ .DB.Info.Database ]],
144-
"username": [[ .DB.Info.Owner ]]
145-
}),
146-
headers: { "Content-Type": "application/x-www-form-urlencoded" }
147-
}).then(function success(response) {
148-
// The delete was successful, so reload the page
149-
let status = response.status;
150-
if (status === 200) {
151-
window.location = '/commits/[[ .DB.Info.Owner ]]/[[ .DB.Info.Database ]]?branch=' + $scope.meta.Branch;
152-
}
153-
}, function failure(response) {
154-
// The delete failed, so display the returned error message
155-
$scope.statusMessage = "Error: " + response.data;
156-
});
157-
};
158-
159-
// Returns a nicely presented "time elapsed" string
160-
$scope.getTimePeriodTxt = function(date1, includeOn) {
161-
return getTimePeriod(date1, includeOn)
162-
};
163-
});
13+
const commitData = [[ .History ]];
14+
const branchData = [[ .Branches ]];
16415
</script>
16+
[[ template "footer" . ]]
16517
</body>
16618
</html>
16719
[[ end ]]

0 commit comments

Comments
 (0)