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

Commit c88e03c

Browse files
committed
webui: Migrate database settings page to use React
Also remove custom CSS code from the page. This also affects some other parts of the site, mostly tables, but makes the page design more Bootstrap standard and easier to maintain.
1 parent fe06757 commit c88e03c

File tree

11 files changed

+472
-664
lines changed

11 files changed

+472
-664
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-settings.js
5657
webui/js/database-view.js
5758
webui/js/db-header.js
5859
webui/js/markdown-editor.js

cypress/e2e/1-webui/database_sharing.cy.js

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ describe('database sharing', () => {
1010
cy.get('[data-cy="settingslink"]').click()
1111
cy.get('[data-cy="usernameinput"]').type('second')
1212
cy.get('[data-cy="adduserbtn"]').click()
13-
cy.get('[data-cy="sharedropdown-second"]').click()
14-
cy.get('[data-cy="sharero-second"]').click()
13+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').click()
14+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read only').click({force: true})
1515

1616
cy.get('[data-cy="usernameinput"]').type('third')
1717
cy.get('[data-cy="adduserbtn"]').click()
18-
cy.get('[data-cy="sharedropdown-third"]').click()
19-
cy.get('[data-cy="sharerw-third"]').click({force: true})
18+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').click()
19+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
2020
cy.get('[data-cy="savebtn"]').click()
2121
cy.wait(waitTime)
2222

@@ -25,13 +25,13 @@ describe('database sharing', () => {
2525
cy.get('[data-cy="settingslink"]').click()
2626
cy.get('[data-cy="usernameinput"]').type('second')
2727
cy.get('[data-cy="adduserbtn"]').click()
28-
cy.get('[data-cy="sharedropdown-second"]').click()
29-
cy.get('[data-cy="sharero-second"]').click()
28+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').click()
29+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read only').click({force: true})
3030

3131
cy.get('[data-cy="usernameinput"]').type('third')
3232
cy.get('[data-cy="adduserbtn"]').click()
33-
cy.get('[data-cy="sharedropdown-third"]').click()
34-
cy.get('[data-cy="sharerw-third"]').click({force: true})
33+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').click()
34+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
3535
cy.get('[data-cy="savebtn"]').click()
3636
cy.wait(waitTime)
3737

@@ -45,13 +45,13 @@ describe('database sharing', () => {
4545

4646
cy.get('[data-cy="usernameinput"]').type('second')
4747
cy.get('[data-cy="adduserbtn"]').click()
48-
cy.get('[data-cy="sharedropdown-second"]').click()
49-
cy.get('[data-cy="sharerw-second"]').click({force: true})
48+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').click()
49+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
5050

5151
cy.get('[data-cy="usernameinput"]').type('third')
5252
cy.get('[data-cy="adduserbtn"]').click()
53-
cy.get('[data-cy="sharedropdown-third"]').click()
54-
cy.get('[data-cy="sharero-third"]').click()
53+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').click()
54+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read only').click({force: true})
5555
cy.get('[data-cy="savebtn"]').click()
5656
cy.wait(waitTime)
5757

@@ -64,13 +64,13 @@ describe('database sharing', () => {
6464

6565
cy.get('[data-cy="usernameinput"]').type('default')
6666
cy.get('[data-cy="adduserbtn"]').click()
67-
cy.get('[data-cy="sharedropdown-default"]').click()
68-
cy.get('[data-cy="sharerw-default"]').click({force: true})
67+
cy.get('input[name="shareperm-default"]').parents('.react-dropdown-select').click()
68+
cy.get('input[name="shareperm-default"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
6969

7070
cy.get('[data-cy="usernameinput"]').type('third')
7171
cy.get('[data-cy="adduserbtn"]').click()
72-
cy.get('[data-cy="sharedropdown-third"]').click()
73-
cy.get('[data-cy="sharero-third"]').click()
72+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').click()
73+
cy.get('input[name="shareperm-third"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read only').click({force: true})
7474
cy.get('[data-cy="savebtn"]').click()
7575
cy.wait(waitTime)
7676

@@ -84,13 +84,13 @@ describe('database sharing', () => {
8484

8585
cy.get('[data-cy="usernameinput"]').type('default')
8686
cy.get('[data-cy="adduserbtn"]').click()
87-
cy.get('[data-cy="sharedropdown-default"]').click()
88-
cy.get('[data-cy="sharerw-default"]').click({force: true})
87+
cy.get('input[name="shareperm-default"]').parents('.react-dropdown-select').click()
88+
cy.get('input[name="shareperm-default"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
8989

9090
cy.get('[data-cy="usernameinput"]').type('first')
9191
cy.get('[data-cy="adduserbtn"]').click()
92-
cy.get('[data-cy="sharedropdown-first"]').click()
93-
cy.get('[data-cy="sharero-first"]').click()
92+
cy.get('input[name="shareperm-first"]').parents('.react-dropdown-select').click()
93+
cy.get('input[name="shareperm-first"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read only').click({force: true})
9494
cy.get('[data-cy="savebtn"]').click()
9595
cy.wait(waitTime)
9696

@@ -104,13 +104,13 @@ describe('database sharing', () => {
104104

105105
cy.get('[data-cy="usernameinput"]').type('first')
106106
cy.get('[data-cy="adduserbtn"]').click()
107-
cy.get('[data-cy="sharedropdown-first"]').click()
108-
cy.get('[data-cy="sharerw-first"]').click({force: true})
107+
cy.get('input[name="shareperm-first"]').parents('.react-dropdown-select').click()
108+
cy.get('input[name="shareperm-first"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
109109

110110
cy.get('[data-cy="usernameinput"]').type('second')
111111
cy.get('[data-cy="adduserbtn"]').click()
112-
cy.get('[data-cy="sharedropdown-second"]').click()
113-
cy.get('[data-cy="sharero-second"]').click()
112+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').click()
113+
cy.get('input[name="shareperm-second"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read only').click({force: true})
114114
cy.get('[data-cy="savebtn"]').click()
115115
cy.wait(waitTime)
116116

cypress/e2e/1-webui/settings.cy.js

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,56 +53,56 @@ describe('settings', () => {
5353
// appear to revert to the default setting. Not sure if this is gotcha we should change or not (?)
5454
it('default table or view', () => {
5555
cy.visit('settings/default/Assembly%20Election%202017.sqlite')
56-
cy.get('[data-cy="deftblname"]').should('contain.text', 'Candidate_Information')
57-
cy.get('[data-cy="deftbldropdown"]').click()
58-
cy.get('[data-cy="tbl-Constituency_Turnout_Information"]').click()
56+
cy.get('[name="selectdefaulttable"]').should('have.value', 'Candidate_Information')
57+
cy.get('[name="selectdefaulttable"]').parents('.react-dropdown-select').click()
58+
cy.get('[name="selectdefaulttable"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Constituency_Turnout_Information').click({force: true})
5959
cy.get('[data-cy="savebtn"]').click()
6060
cy.get('[data-cy="settingslink"]').click()
61-
cy.get('[data-cy="deftblname"]').should('contain.text', 'Constituency_Turnout_Information')
61+
cy.get('[name="selectdefaulttable"]').should('have.value', 'Constituency_Turnout_Information')
6262
})
6363

6464
// Default branch
6565
it('default branch', () => {
6666
cy.visit('settings/default/Assembly%20Election%202017.sqlite')
67-
cy.get('[data-cy="defbranchname"]').should('contain.text', 'main')
68-
cy.get('[data-cy="defbranchdropdown"]').click()
69-
cy.get('[data-cy="branch-stuff"]').click()
67+
cy.get('[name="selectbranch"]').should('have.value', 'main')
68+
cy.get('[name="selectbranch"]').parents('.react-dropdown-select').click()
69+
cy.get('[name="selectbranch"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('stuff').click({force: true})
7070
cy.get('[data-cy="savebtn"]').click()
7171
cy.get('[data-cy="settingslink"]').click()
72-
cy.get('[data-cy="defbranchname"]').should('contain.text', 'stuff')
72+
cy.get('[name="selectbranch"]').should('have.value', 'stuff')
7373
})
7474

7575
// Source URL
7676
it('source url', () => {
7777
cy.visit('settings/default/Assembly%20Election%202017.sqlite')
78-
cy.get('[data-cy="srcurlinput"]').should('have.value', 'http://data.nicva.org/dataset/assembly-election-2017')
79-
cy.get('[data-cy="srcurlinput"]').type('{selectall}{backspace}https://example.org')
78+
cy.get('[data-cy="sourceurl"]').should('have.value', 'http://data.nicva.org/dataset/assembly-election-2017')
79+
cy.get('[data-cy="sourceurl"]').type('{selectall}{backspace}https://example.org')
8080
cy.get('[data-cy="savebtn"]').click()
8181
cy.get('[data-cy="settingslink"]').click()
82-
cy.get('[data-cy="srcurlinput"]').should('have.value', 'https://example.org')
83-
cy.get('[data-cy="srcurlinput"]').type('{selectall}{backspace}http://data.nicva.org/dataset/assembly-election-2017')
82+
cy.get('[data-cy="sourceurl"]').should('have.value', 'https://example.org')
83+
cy.get('[data-cy="sourceurl"]').type('{selectall}{backspace}http://data.nicva.org/dataset/assembly-election-2017')
8484
cy.get('[data-cy="savebtn"]').click()
8585
})
8686

8787
// Licence
8888
it('licence', () => {
8989
// Test the main branch
9090
cy.visit('settings/default/Assembly%20Election%202017.sqlite')
91-
cy.get('[data-cy="main-licname"]').should('contain.text', 'CC-BY-SA-4.0')
92-
cy.get('[data-cy="main-licdropdown"]').click()
93-
cy.get('[data-cy="lic-main-Not specified"]').click()
91+
cy.get('[name="main-licence"]').should('have.value', 'CC-BY-SA-4.0')
92+
cy.get('[name="main-licence"]').parents('.react-dropdown-select').click()
93+
cy.get('[name="main-licence"]').parents('.react-dropdown-select').find('.react-dropdown-select-dropdown').find('span').contains('Not specified').click({force: true})
9494
cy.get('[data-cy="savebtn"]').click()
9595
cy.get('[data-cy="settingslink"]').click()
96-
cy.get('[data-cy="main-licname"]').should('contain.text', 'Not specified')
96+
cy.get('[name="main-licence"]').should('have.value', 'Not specified')
9797

9898
// Test the 2nd branch
99-
cy.get('[data-cy="stuff-licname"]').should('contain.text', 'CC-BY-SA-4.0')
100-
cy.get('[data-cy="stuff-licdropdown"]').click()
99+
cy.get('[name="stuff-licence"]').should('have.value', 'CC-BY-SA-4.0')
100+
cy.get('[name="stuff-licence"]').parents('.react-dropdown-select').click()
101101
// Note - scrollIntoView() seems like it should work instead of forcing this click on Firefox. But it doesn't.
102-
cy.get('[data-cy="lic-stuff-CC0"]').click({force: true}) // Firefox sizing seems to have this *slightly* clipped, but otherwise usable
102+
cy.get('[name="stuff-licence"]').parents('.react-dropdown-select').find('.react-dropdown-select-dropdown').find('span').contains('CC0').click({force: true}) // Firefox sizing seems to have this *slightly* clipped, but otherwise usable
103103
cy.get('[data-cy="savebtn"]').click()
104104
cy.get('[data-cy="settingslink"]').click()
105-
cy.get('[data-cy="stuff-licname"]').should('contain.text', 'CC0')
105+
cy.get('[name="stuff-licence"]').should('have.value', 'CC0')
106106
})
107107

108108
// Share Database
@@ -134,8 +134,8 @@ describe('settings', () => {
134134
cy.get('[data-cy="adduserbtn"]').click()
135135
cy.wait(waitTime)
136136

137-
cy.get('[data-cy="sharedropdown-first"]').click()
138-
cy.get('[data-cy="sharerw-first"]').click({force: true})
137+
cy.get('[name="shareperm-first"]').parents('.react-dropdown-select').click()
138+
cy.get('[name="shareperm-first"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
139139

140140
cy.get('[data-cy="usernameinput"]').type('second')
141141
cy.get('[data-cy="adduserbtn"]').click()
@@ -145,20 +145,20 @@ describe('settings', () => {
145145
cy.get('[data-cy="adduserbtn"]').click()
146146
cy.wait(waitTime)
147147

148-
cy.get('[data-cy="sharedropdown-third"]').click()
149-
cy.get('[data-cy="sharerw-third"]').click({force: true})
148+
cy.get('[name="shareperm-third"]').parents('.react-dropdown-select').click()
149+
cy.get('[name="shareperm-third"]').parents('.react-dropdown-select').find('.react-dropdown-select-item').contains('Read and write').click({force: true})
150150

151151
cy.get('[data-cy="savebtn"]').click()
152152
cy.get('[data-cy="settingslink"]').click()
153153

154154
cy.get('[data-cy="shareuser-first"]').should('contain.text', 'first')
155-
cy.get('[data-cy="shareperm-first"]').should('contain.text', 'Read and write')
155+
cy.get('[name="shareperm-first"]').should('have.value', 'Read and write')
156156

157157
cy.get('[data-cy="shareuser-second"]').should('contain.text', 'second')
158-
cy.get('[data-cy="shareperm-second"]').should('contain.text', 'Read only')
158+
cy.get('[name="shareperm-second"]').should('have.value', 'Read only')
159159

160160
cy.get('[data-cy="shareuser-third"]').should('contain.text', 'third')
161-
cy.get('[data-cy="shareperm-third"]').should('contain.text', 'Read and write')
161+
cy.get('[name="shareperm-third"]').should('have.value', 'Read and write')
162162

163163
// Switch to the different users and verify they have read access to the database
164164
cy.request("/x/test/switchfirst")
@@ -182,22 +182,23 @@ describe('settings', () => {
182182
// Full description
183183
it('full description', () => {
184184
cy.visit('settings/default/Assembly%20Election%202017.sqlite')
185-
cy.get('[data-cy="rendereddiv"]').should('contain.text', 'No full description')
186-
cy.get('[data-cy="edittab"]').click()
187-
cy.get('[data-cy="desctext"]').should('contain.text', 'No full description')
188-
cy.get('[data-cy="desctext"]').type('{selectall}{backspace}Some new description')
189-
cy.get('[data-cy="renderedtab"]').click()
190-
cy.get('[data-cy="rendereddiv"]').should('contain.text', 'Some new description')
185+
cy.get('[data-cy="fulldesc-preview"]').should('contain.text', 'No full description')
186+
cy.get('[data-cy="fulldesc-edit-tab"]').click()
187+
cy.get('[data-cy="fulldesc"]').should('contain.text', 'No full description')
188+
cy.get('[data-cy="fulldesc"]').type('{selectall}{backspace}Some new description')
189+
cy.get('[data-cy="fulldesc-preview-tab"]').click()
190+
cy.get('[data-cy="fulldesc-preview"]').should('contain.text', 'Some new description')
191191
cy.get('[data-cy="savebtn"]').click()
192192
cy.get('[data-cy="settingslink"]').click()
193-
cy.get('[data-cy="rendereddiv"]').should('contain.text', 'Some new description')
193+
cy.get('[data-cy="fulldesc-preview"]').should('contain.text', 'Some new description')
194194
})
195195

196196
// Delete database
197197
it('delete database', () => {
198198
cy.visit('settings/default/Assembly%20Election%202017.sqlite')
199199
cy.get('[data-cy="delbtn"]').click()
200-
cy.get('[data-cy="confirmbtn"]').click()
200+
cy.wait(waitTime) // Some animation played here
201+
cy.get('button[label="Yes, delete it"]').click()
201202
cy.get('[data-cy="pubdbs"]').should('not.contain', 'Assembly Election 2017.sqlite')
202203
cy.get('[data-cy="privdbs"]').should('not.contain', 'Assembly Election 2017.sqlite')
203204
})

webui/css/local.css

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -130,48 +130,6 @@
130130
margin-bottom: 0;
131131
}
132132

133-
.settingsTable {
134-
border-collapse: separate;
135-
border: 1px solid #DDD;
136-
border-radius: 7px;
137-
margin-bottom: 5px;
138-
margin-top: 10px;
139-
}
140-
141-
.settingsTable > tbody > tr > th {
142-
border: none;
143-
border-bottom: 1px solid #DDD;
144-
vertical-align: middle;
145-
}
146-
147-
.settingsTable > tbody > tr:last-of-type > th {
148-
border: none;
149-
}
150-
151-
.settingsTable > tbody > tr > td {
152-
border: none;
153-
border-bottom: 1px solid #DDD;
154-
border-left: 1px solid #DDD;
155-
}
156-
157-
.settingsTable > tbody > tr:last-of-type > td {
158-
border-bottom: none;
159-
}
160-
161-
.table > thead > tr > th {
162-
background-color: #dcdcdc;
163-
border-bottom: 2px solid #ddd;
164-
vertical-align: middle;
165-
}
166-
167-
.tableRow {
168-
border-bottom: 1px solid #ddd;
169-
}
170-
171-
.tableRow:last-of-type {
172-
border-bottom: none;
173-
}
174-
175133
#contents h1, #contents h2, #contents h3, #contents h4, #contents h5, #contents h6 {
176134
margin-top: 0;
177135
}

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 DatabaseSettings from "./database-settings";
89
import DatabaseView from "./database-view";
910
import DbHeader from "./db-header";
1011
import MarkdownEditor from "./markdown-editor";
@@ -33,6 +34,14 @@ import MarkdownEditor from "./markdown-editor";
3334
}
3435
}
3536

37+
{
38+
const rootNode = document.getElementById("database-settings");
39+
if (rootNode) {
40+
const root = ReactDOM.createRoot(rootNode);
41+
root.render(<DatabaseSettings />);
42+
}
43+
}
44+
3645
{
3746
const rootNode = document.getElementById("database-view");
3847
if (rootNode) {

0 commit comments

Comments
 (0)