Skip to content

Commit dd43646

Browse files
authored
Merge pull request #524 from IABTechLab/aul-UID2-5549-ui-refactor
New Admin UI
2 parents 779e34b + 883c084 commit dd43646

39 files changed

+4349
-2100
lines changed

README.md

Lines changed: 171 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ When running locally, set the `is_auth_disabled` flag to `true` in [local-config
2121

2222
If you want to test with Okta OAuth, set the `is_auth_disabled` flag to `false`, and fill in the `okta_client_secret` with the value under "Okta localhost deployment" in 1Password.
2323

24-
### Working on the UI
25-
26-
Per the above setup steps, the UI runs on `http://localhost:8089/`. To see your local UI changes reflected in the browser, you will need to hard reload (`Crtl+Shift+R`) while on the specific web page you have changed.
27-
2824
## V2 API
2925

3026
The v2 API is based on individual route provider classes. Each class should provide exactly one endpoint and must implement IRouteProvider or IBlockingRouteProvider.
@@ -36,3 +32,174 @@ The v2 API is based on individual route provider classes. Each class should prov
3632
IRouteProvider requires a `getHandler` method, which should return a valid handler function - see `GetClientSideKeypairsBySite.java`. This method *must* be annotated with the Path, Method, and Roles annotations.
3733

3834
The route handler will automatically be wrapped by the Auth middleware based on the roles specified in the Roles annotation.
35+
36+
## Working on the UI
37+
Per the above setup steps, the UI runs on `http://localhost:8089/`. To see your local UI changes reflected in the browser, you will need to hard reload (`Crtl+Shift+R`) while on the specific web page you have changed.
38+
39+
### Page setup
40+
```html
41+
<html>
42+
<head>
43+
<!-- We use Unicode symbols for icons so need UTF-8 -->
44+
<meta charset="UTF-8">
45+
<link rel="stylesheet" href="/css/style.css">
46+
</head>
47+
<body>
48+
49+
<div class="main-content">
50+
<!-- Operations and controls will be added by `initializeOperations` here -->
51+
<div class="operations-container"></div>
52+
53+
<!-- Both success and error output will be added by `initializeOutput` here -->
54+
<div class="output-container"></div>
55+
</div>
56+
57+
<script type="module">
58+
document.addEventListener('DOMContentLoaded', function () {
59+
import { initializeOperations } from '/js/component/operations.js';
60+
import { initializeOutput } from '/js/component/output.js';
61+
62+
const operationConfig = {
63+
read: [ // Read-only operations (don't modify data)
64+
// See Operations example below
65+
],
66+
write: [ // Write operations (modify data)
67+
// ...
68+
],
69+
danger: [ // Dangerous operations (require explicit confirmation modal)
70+
// ...
71+
]
72+
}
73+
74+
initializeOperations(operationConfig);
75+
initializeOutput();
76+
});
77+
}
78+
</script>
79+
</body>
80+
</html>
81+
```
82+
83+
### Operations
84+
```javascript
85+
const myOperation = {
86+
id: 'operationId', // Required: Unique identifier
87+
title: 'Operation Title', // Required: Display name
88+
role: 'maintainer', // Required: `maintainer`, `elevated` or `superuser`
89+
inputs: [ // Optional: Inputs (see below)
90+
{
91+
name: 'field1', // Value of this input will be available as property matching name on `inputs` object below.
92+
label: 'Field 1', // Shown on the UI above the field
93+
type: 'text' // Optional, text by default
94+
}
95+
],
96+
description: 'text', // Optional: Description will appear within the accordion
97+
confirmationText: 'text', // Optional: Danger zone confirmation text, will replace stock text if used. Only works in danger zone.
98+
apiCall: { // Optional: API configuration
99+
method: 'POST',
100+
url: '', // Either hardcore URL here or use `getUrl` below.
101+
getUrl: (inputs) => { // Either construct a URL from the inputs or use `url` above.
102+
return `/api/my/api?field1=${encodeURIComponent(inputs.field1)}`
103+
},
104+
getPayload: (inputs) => { // Optional: Construct a JS object that will be sent as body
105+
return { field1: inputs.field1 };
106+
}
107+
},
108+
preProcess: async (inputs) => inputs, // Optional: Run before getUrl/getPayload and the API call
109+
postProcess: async (data, inputs) => data // Optional: Run after apiCall, if you want to adjust the response
110+
};
111+
112+
```
113+
114+
### Inputs
115+
- Inputs on the same page that share a `name` will have their values synced.
116+
117+
#### text (default)
118+
Basic small text input
119+
```javascript
120+
const myText = {
121+
name: 'fieldName',
122+
label: 'Field Label',
123+
required: true, // Optional: Exclude button won't be enabled until all fields with requireds are filled. Default false.
124+
size: 2, // Optional: grid span 1-3, grid has 3 columns. Default 1.
125+
placeholder: 'Enter text', // Optional
126+
defaultValue: 'default' // Optional
127+
};
128+
```
129+
130+
#### multi-line
131+
A larger multi-line text input box
132+
```javascript
133+
const myTextArea = {
134+
name: 'textArea',
135+
type: 'multi-line',
136+
label: 'Multi-line Text',
137+
placeholder: 'Enter text...',
138+
defaultValue: 'default text'
139+
};
140+
```
141+
142+
#### number
143+
Number-specific input, won't allow non-number text
144+
```javascript
145+
const myNum = {
146+
name: 'numField',
147+
type: 'number',
148+
label: 'Number Field'
149+
};
150+
```
151+
152+
#### date
153+
Date-specific input with date picker
154+
```javascript
155+
const myDate = {
156+
name: 'dateField',
157+
type: 'date',
158+
defaultValue: '2024-01-01'
159+
};
160+
```
161+
162+
#### checkbox
163+
```javascript
164+
const myCheckbox = {
165+
name: 'boolField',
166+
type: 'checkbox',
167+
label: 'Is it true?',
168+
defaultValue: true
169+
};
170+
```
171+
172+
#### select
173+
Dropdown to select one option from a list
174+
```javascript
175+
const myDropdown = {
176+
name: 'Dropdown',
177+
type: 'select',
178+
label: 'Select Option',
179+
options: [
180+
'simple', // Can pass as string if option values are same as UI text
181+
{ value: 'val', label: 'Display' } // Or as Objects if they are different
182+
],
183+
defaultValue: 'val'
184+
};
185+
```
186+
187+
#### multi-select
188+
Multiple checkboxes to allow selecting more than one option
189+
190+
```javascript
191+
const myMultiSelect = {
192+
name: 'Multi Select',
193+
type: 'multi-select',
194+
label: 'Multiple Options',
195+
required: true,
196+
options: [
197+
{
198+
value: 'OPTION_1',
199+
label: 'Option One',
200+
hint: 'Tooltip explanation' // Optional, appear as info icons next to options
201+
}
202+
],
203+
defaultValue: ['OPTION_1'] // Array or comma-separated string
204+
}
205+
```

0 commit comments

Comments
 (0)