Skip to content

Commit 169fdc7

Browse files
Fix for Auto-Recover being invasive
- Add `Buildable` interface - Add the `Hidable` abstract class for hiding elements - Add the `ButtonBuilder` for building custom buttons - Add the `AlertBuilder` abstract class for creating alerts, as well as a number of specific Alert types that can be built using this class - Prevent alert showing when not on record pages - Prevent modal showing when other alerts have values - Reword values in alert and modal - Update modal to show fields being changed
1 parent 89903ad commit 169fdc7

File tree

18 files changed

+394
-18
lines changed

18 files changed

+394
-18
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Hidable, Renderable } from 'util/renderable';
2+
import { AlertType } from './types';
3+
4+
export abstract class AlertBase extends Hidable implements Renderable<HTMLDivElement> {
5+
/**
6+
* Create an instance of AlertBase.
7+
* This class serves as a base for alert components.
8+
* It implements the Renderable interface, which requires a render method.
9+
* The render method should be implemented by subclasses to provide specific rendering logic.
10+
* @implements {Renderable<HTMLDivElement>}
11+
* @param {string} message - The message to be displayed in the alert.
12+
* @param {AlertType} type - The type of alert, which determines its styling and behavior.
13+
* @see Renderable
14+
* @see Hidable
15+
* @see AlertType
16+
* @example
17+
* const alert = new AlertBase('This is an alert message', AlertType.INFO);
18+
* document.body.appendChild(alert.render());
19+
*/
20+
constructor(private readonly message: string, private readonly type: AlertType, private readonly transparent: boolean = false) {
21+
super();
22+
}
23+
24+
/**
25+
* Render the alert as an HTMLDivElement.
26+
* @returns {HTMLDivElement} The rendered HTML element representing the alert.
27+
*/
28+
render(): HTMLDivElement {
29+
if(this.element) throw new Error('AlertBase.render() should not be called multiple times without resetting the element.');
30+
const alertDiv = document.createElement('div');
31+
alertDiv.classList.add('alert', `alert-${this.type}`);
32+
if(this.transparent) {
33+
alertDiv.classList.add('alert-no-bg');
34+
}
35+
for(const item of this.message.split('\n')) {
36+
const pDiv = document.createElement('p');
37+
pDiv.textContent = item;
38+
alertDiv.appendChild(pDiv);
39+
}
40+
this.element = alertDiv;
41+
return alertDiv;
42+
}
43+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, it, expect } from '@jest/globals';
2+
import { DangerAlert } from './dangerAlert';
3+
4+
describe('Error Alert Tests', () => {
5+
it('should display an error alert with the correct message', () => {
6+
const errorMessage = 'This is a test error message';
7+
const errorAlert = new DangerAlert(errorMessage);
8+
9+
const alert = errorAlert.render();
10+
11+
document.body.appendChild(alert);
12+
13+
expect(alert.classList.contains('alert-danger')).toBeTruthy();
14+
expect(alert.textContent).toContain(errorMessage);
15+
16+
document.body.removeChild(alert);
17+
});
18+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AlertBase } from "./alertBase";
2+
3+
export class DangerAlert extends AlertBase {
4+
/**
5+
* Create an instance of InfoAlert.
6+
* This class extends AlertBase to provide a specific implementation for info alerts.
7+
* It uses the 'info' alert type for styling and behavior.
8+
* @class
9+
* @public
10+
* @memberof alert.lib
11+
* @constructor
12+
* @param {string} message - The message to be displayed in the alert.
13+
*/
14+
constructor(message: string) {
15+
super(message, 'danger');
16+
}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, it, expect } from '@jest/globals';
2+
import { InfoAlert } from './infoAlert';
3+
4+
describe('Info Alert Tests', () => {
5+
it('should display an info alert with the correct message', () => {
6+
const infoMessage = 'This is a test info message';
7+
const infoAlert = new InfoAlert(infoMessage);
8+
9+
const alert = infoAlert.render();
10+
11+
document.body.appendChild(alert);
12+
13+
expect(alert.classList.contains('alert-info')).toBeTruthy();
14+
expect(alert.textContent).toContain(infoMessage);
15+
16+
document.body.removeChild(alert);
17+
});
18+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AlertBase } from './alertBase';
2+
3+
export class InfoAlert extends AlertBase {
4+
/**
5+
* Create an instance of InfoAlert.
6+
* This class extends AlertBase to provide a specific implementation for info alerts.
7+
* It uses the AlertType.INFO to set the alert type.
8+
* @class
9+
* @public
10+
* @memberof alert.lib
11+
* @constructor
12+
* @param {string} message - The message to be displayed in the info alert.
13+
*/
14+
constructor(message: string) {
15+
super(message, "info");
16+
}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, it, expect } from '@jest/globals';
2+
import { SuccessAlert } from './successAlert';
3+
4+
describe('Success Alert Tests', () => {
5+
it('should create a success alert', () => {
6+
const message = 'Operation completed successfully';
7+
const alert = new SuccessAlert(message);
8+
9+
const result = alert.render();
10+
11+
document.body.appendChild(result);
12+
13+
expect(result.classList.contains('alert-success')).toBeTruthy();
14+
expect(result.textContent).toBe(message);
15+
16+
document.body.removeChild(result);
17+
});
18+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AlertBase } from "./alertBase";
2+
3+
export class SuccessAlert extends AlertBase {
4+
/**
5+
* Create an instance of InfoAlert.
6+
* This class extends AlertBase to provide a specific implementation for info alerts.
7+
* It uses the 'info' alert type for styling and behavior.
8+
* @class
9+
* @public
10+
* @memberof alert.lib
11+
* @constructor
12+
* @param {string} message - The message to be displayed in the alert.
13+
*/
14+
constructor(message: string) {
15+
super(message, 'success', true);
16+
}
17+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type AlertType = 'info' | 'success' | 'warning' | 'danger';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, it, expect } from '@jest/globals';
2+
import { WarningAlert } from './warningAlert';
3+
4+
describe('Warning Alert Tests', () => {
5+
it('should create a warning alert', () => {
6+
const message = 'This is a warning message';
7+
const alert = new WarningAlert(message);
8+
9+
const result = alert.render();
10+
11+
document.body.appendChild(result);
12+
13+
expect(result.classList.contains('alert-warning')).toBe(true);
14+
expect(result.textContent).toBe(message);
15+
16+
document.body.removeChild(result);
17+
});
18+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AlertBase } from "./alertBase";
2+
3+
export class WarningAlert extends AlertBase {
4+
/**
5+
* Create an instance of InfoAlert.
6+
* This class extends AlertBase to provide a specific implementation for info alerts.
7+
* It uses the AlertType.INFO to set the alert type.
8+
* @class
9+
* @public
10+
* @memberof alert.lib
11+
* @constructor
12+
* @param {string} message - The message to be displayed in the info alert.
13+
*/
14+
constructor(message: string) {
15+
super(message, "warning");
16+
}
17+
}

0 commit comments

Comments
 (0)