Skip to content

Commit 35747cb

Browse files
FIX (formatting): Fix formatting issues
1 parent 4afa0e9 commit 35747cb

File tree

14 files changed

+234
-218
lines changed

14 files changed

+234
-218
lines changed

backend/internal/features/notifiers/model.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
discord_notifier "postgresus-backend/internal/features/notifiers/models/discord"
77
"postgresus-backend/internal/features/notifiers/models/email_notifier"
88
slack_notifier "postgresus-backend/internal/features/notifiers/models/slack"
9+
teams_notifier "postgresus-backend/internal/features/notifiers/models/teams"
910
telegram_notifier "postgresus-backend/internal/features/notifiers/models/telegram"
1011
webhook_notifier "postgresus-backend/internal/features/notifiers/models/webhook"
11-
teams_notifier "postgresus-backend/internal/features/notifiers/models/teams"
1212

1313
"github.com/google/uuid"
1414
)
@@ -21,12 +21,12 @@ type Notifier struct {
2121
LastSendError *string `json:"lastSendError" gorm:"column:last_send_error;type:text"`
2222

2323
// specific notifier
24-
TelegramNotifier *telegram_notifier.TelegramNotifier `json:"telegramNotifier" gorm:"foreignKey:NotifierID"`
25-
EmailNotifier *email_notifier.EmailNotifier `json:"emailNotifier" gorm:"foreignKey:NotifierID"`
26-
WebhookNotifier *webhook_notifier.WebhookNotifier `json:"webhookNotifier" gorm:"foreignKey:NotifierID"`
27-
SlackNotifier *slack_notifier.SlackNotifier `json:"slackNotifier" gorm:"foreignKey:NotifierID"`
28-
DiscordNotifier *discord_notifier.DiscordNotifier `json:"discordNotifier" gorm:"foreignKey:NotifierID"`
29-
TeamsNotifier *teams_notifier.TeamsNotifier `gorm:"foreignKey:NotifierID;constraint:OnDelete:CASCADE" json:"teamsNotifier,omitempty"`
24+
TelegramNotifier *telegram_notifier.TelegramNotifier `json:"telegramNotifier" gorm:"foreignKey:NotifierID"`
25+
EmailNotifier *email_notifier.EmailNotifier `json:"emailNotifier" gorm:"foreignKey:NotifierID"`
26+
WebhookNotifier *webhook_notifier.WebhookNotifier `json:"webhookNotifier" gorm:"foreignKey:NotifierID"`
27+
SlackNotifier *slack_notifier.SlackNotifier `json:"slackNotifier" gorm:"foreignKey:NotifierID"`
28+
DiscordNotifier *discord_notifier.DiscordNotifier `json:"discordNotifier" gorm:"foreignKey:NotifierID"`
29+
TeamsNotifier *teams_notifier.TeamsNotifier `json:"teamsNotifier,omitempty" gorm:"foreignKey:NotifierID;constraint:OnDelete:CASCADE"`
3030
}
3131

3232
func (n *Notifier) TableName() string {

backend/internal/features/notifiers/models/teams/model.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
)
1414

1515
type TeamsNotifier struct {
16-
NotifierID uuid.UUID `gorm:"type:uuid;primaryKey;column:notifier_id" json:"notifierId"`
16+
NotifierID uuid.UUID `gorm:"type:uuid;primaryKey;column:notifier_id" json:"notifierId"`
1717
WebhookURL string `gorm:"type:text;not null;column:power_automate_url" json:"powerAutomateUrl"`
1818
}
1919

@@ -32,28 +32,33 @@ func (n *TeamsNotifier) Validate() error {
3232
return nil
3333
}
3434

35-
type сardAttachment struct {
35+
type cardAttachment struct {
3636
ContentType string `json:"contentType"`
3737
Content interface{} `json:"content"`
3838
}
3939

4040
type payload struct {
4141
Title string `json:"title"`
4242
Text string `json:"text"`
43-
Attachments []сardAttachment `json:"attachments,omitempty"`
43+
Attachments []cardAttachment `json:"attachments,omitempty"`
4444
}
4545

4646
func (n *TeamsNotifier) Send(logger *slog.Logger, heading, message string) error {
4747
if err := n.Validate(); err != nil {
4848
return err
4949
}
5050

51-
card := map[string]interface{}{
51+
card := map[string]any{
5252
"type": "AdaptiveCard",
5353
"version": "1.4",
54-
"body": []interface{}{
55-
map[string]interface{}{"type": "TextBlock", "size": "Medium", "weight": "Bolder", "text": heading},
56-
map[string]interface{}{"type": "TextBlock", "wrap": true, "text": message},
54+
"body": []any{
55+
map[string]any{
56+
"type": "TextBlock",
57+
"size": "Medium",
58+
"weight": "Bolder",
59+
"text": heading,
60+
},
61+
map[string]any{"type": "TextBlock", "wrap": true, "text": message},
5762
},
5863
}
5964

@@ -76,10 +81,16 @@ func (n *TeamsNotifier) Send(logger *slog.Logger, heading, message string) error
7681
if err != nil {
7782
return err
7883
}
79-
defer resp.Body.Close()
84+
85+
defer func() {
86+
if closeErr := resp.Body.Close(); closeErr != nil {
87+
logger.Error("failed to close response body", "error", closeErr)
88+
}
89+
}()
8090

8191
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
8292
return fmt.Errorf("teams webhook returned status %d", resp.StatusCode)
8393
}
94+
8495
return nil
8596
}

backend/internal/features/notifiers/repository.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ func (r *NotifierRepository) Save(notifier *Notifier) (*Notifier, error) {
4141
}
4242
}
4343

44-
4544
if notifier.ID == uuid.Nil {
4645
if err := tx.
4746
Omit(
@@ -70,7 +69,6 @@ func (r *NotifierRepository) Save(notifier *Notifier) (*Notifier, error) {
7069
}
7170
}
7271

73-
7472
switch notifier.NotifierType {
7573
case NotifierTypeTelegram:
7674
if notifier.TelegramNotifier != nil {
@@ -207,7 +205,6 @@ func (r *NotifierRepository) Delete(notifier *Notifier) error {
207205
}
208206
}
209207

210-
211208
return tx.Delete(notifier).Error
212209
})
213210
}

frontend/src/entity/notifiers/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ export type { DiscordNotifier } from './models/discord/DiscordNotifier';
1919
export { validateDiscordNotifier } from './models/discord/validateDiscordNotifier';
2020

2121
export type { TeamsNotifier } from './models/teams/TeamsNotifier';
22-
export { validateTeamsNotifier } from './models/teams/validateTeamsNotifier';
22+
export { validateTeamsNotifier } from './models/teams/validateTeamsNotifier';

frontend/src/entity/notifiers/models/Notifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import type { NotifierType } from './NotifierType';
22
import type { DiscordNotifier } from './discord/DiscordNotifier';
33
import type { EmailNotifier } from './email/EmailNotifier';
44
import type { SlackNotifier } from './slack/SlackNotifier';
5+
import type { TeamsNotifier } from './teams/TeamsNotifier';
56
import type { TelegramNotifier } from './telegram/TelegramNotifier';
67
import type { WebhookNotifier } from './webhook/WebhookNotifier';
7-
import type { TeamsNotifier } from './teams/TeamsNotifier';
88

99
export interface Notifier {
1010
id: string;

frontend/src/entity/notifiers/models/getNotifierLogoFromType.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const getNotifierLogoFromType = (type: NotifierType) => {
1313
case NotifierType.DISCORD:
1414
return '/icons/notifiers/discord.svg';
1515
case NotifierType.TEAMS:
16-
return '/icons/notifiers/teams.svg';
16+
return '/icons/notifiers/teams.svg';
1717
default:
1818
return '';
1919
}

frontend/src/entity/notifiers/models/getNotifierNameFromType.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const getNotifierNameFromType = (type: NotifierType) => {
1313
case NotifierType.DISCORD:
1414
return 'Discord';
1515
case NotifierType.TEAMS:
16-
return 'Teams';
16+
return 'Teams';
1717
default:
1818
return '';
1919
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export interface TeamsNotifier {
2-
/** Power Automate HTTP endpoint:
3-
* trigger = "When an HTTP request is received"
4-
* e.g. https://prod-00.westeurope.logic.azure.com/workflows/...
5-
*/
6-
powerAutomateUrl: string;
2+
/** Power Automate HTTP endpoint:
3+
* trigger = "When an HTTP request is received"
4+
* e.g. https://prod-00.westeurope.logic.azure.com/workflows/...
5+
*/
6+
powerAutomateUrl: string;
77
}
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import type { TeamsNotifier } from './TeamsNotifier';
22

33
export const validateTeamsNotifier = (notifier: TeamsNotifier): boolean => {
4-
if (!notifier?.powerAutomateUrl) {
5-
return false;
6-
}
4+
if (!notifier?.powerAutomateUrl) {
5+
return false;
6+
}
77

8-
try {
9-
const u = new URL(notifier.powerAutomateUrl);
10-
if (u.protocol !== 'http:' && u.protocol !== 'https:') return false;
11-
} catch {
12-
return false;
13-
}
8+
try {
9+
const u = new URL(notifier.powerAutomateUrl);
10+
if (u.protocol !== 'http:' && u.protocol !== 'https:') return false;
11+
} catch {
12+
return false;
13+
}
1414

15-
return true;
15+
return true;
1616
};

frontend/src/features/databases/ui/DatabaseCardComponent.tsx

Lines changed: 91 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,106 @@ import { InfoCircleOutlined } from '@ant-design/icons';
22
import dayjs from 'dayjs';
33
import { useEffect, useState } from 'react';
44

5+
import { type BackupConfig, backupConfigApi } from '../../../entity/backups';
56
import { type Database, DatabaseType } from '../../../entity/databases';
67
import { HealthStatus } from '../../../entity/databases/model/HealthStatus';
7-
import { getUserShortTimeFormat } from '../../../shared/time/getUserTimeFormat';
8-
9-
10-
import { type BackupConfig, backupConfigApi } from '../../../entity/backups';
118
import { getStorageLogoFromType } from '../../../entity/storages/models/getStorageLogoFromType';
9+
import { getUserShortTimeFormat } from '../../../shared/time/getUserTimeFormat';
1210

1311
interface Props {
14-
database: Database;
15-
selectedDatabaseId?: string;
16-
setSelectedDatabaseId: (databaseId: string) => void;
12+
database: Database;
13+
selectedDatabaseId?: string;
14+
setSelectedDatabaseId: (databaseId: string) => void;
1715
}
1816

1917
export const DatabaseCardComponent = ({
20-
database,
21-
selectedDatabaseId,
22-
setSelectedDatabaseId,
23-
}: Props) => {
24-
let databaseIcon = '';
25-
let databaseType = '';
26-
27-
if (database.type === DatabaseType.POSTGRES) {
28-
databaseIcon = '/icons/databases/postgresql.svg';
29-
databaseType = 'PostgreSQL';
30-
}
31-
32-
const [storage, setStorage] = useState<BackupConfig['storage']>();
33-
34-
35-
useEffect(() => {
36-
if (!database.id) return;
37-
let ignore = false;
38-
39-
backupConfigApi.getBackupConfigByDbID(database.id).then((res) => {
40-
if (!ignore) setStorage(res?.storage);
41-
});
42-
43-
return () => {
44-
ignore = true;
45-
};
46-
}, [database.id]);
47-
48-
return (
49-
<div
50-
className={`mb-3 cursor-pointer rounded p-3 shadow ${selectedDatabaseId === database.id ? 'bg-blue-100' : 'bg-white'}`}
51-
onClick={() => setSelectedDatabaseId(database.id)}
52-
>
53-
<div className="flex">
54-
<div className="mb-1 font-bold">{database.name}</div>
55-
56-
{database.healthStatus && (
57-
<div className="ml-auto pl-1">
58-
<div
59-
className={`rounded px-[6px] py-[2px] text-[10px] text-white ${
60-
database.healthStatus === HealthStatus.AVAILABLE ? 'bg-green-500' : 'bg-red-500'
61-
}`}
62-
>
63-
{database.healthStatus === HealthStatus.AVAILABLE ? 'Available' : 'Unavailable'}
64-
</div>
65-
</div>
66-
)}
67-
</div>
68-
69-
<div className="mb flex items-center">
70-
<div className="text-sm text-gray-500">Database type: {databaseType}</div>
71-
<img src={databaseIcon} alt="databaseIcon" className="ml-1 h-4 w-4" />
18+
database,
19+
selectedDatabaseId,
20+
setSelectedDatabaseId,
21+
}: Props) => {
22+
let databaseIcon = '';
23+
let databaseType = '';
24+
25+
if (database.type === DatabaseType.POSTGRES) {
26+
databaseIcon = '/icons/databases/postgresql.svg';
27+
databaseType = 'PostgreSQL';
28+
}
29+
30+
const [storage, setStorage] = useState<BackupConfig['storage']>();
31+
32+
useEffect(() => {
33+
if (!database.id) return;
34+
let ignore = false;
35+
36+
backupConfigApi.getBackupConfigByDbID(database.id).then((res) => {
37+
if (!ignore) setStorage(res?.storage);
38+
});
39+
40+
return () => {
41+
ignore = true;
42+
};
43+
}, [database.id]);
44+
45+
return (
46+
<div
47+
className={`mb-3 cursor-pointer rounded p-3 shadow ${selectedDatabaseId === database.id ? 'bg-blue-100' : 'bg-white'}`}
48+
onClick={() => setSelectedDatabaseId(database.id)}
49+
>
50+
<div className="flex">
51+
<div className="mb-1 font-bold">{database.name}</div>
52+
53+
{database.healthStatus && (
54+
<div className="ml-auto pl-1">
55+
<div
56+
className={`rounded px-[6px] py-[2px] text-[10px] text-white ${
57+
database.healthStatus === HealthStatus.AVAILABLE ? 'bg-green-500' : 'bg-red-500'
58+
}`}
59+
>
60+
{database.healthStatus === HealthStatus.AVAILABLE ? 'Available' : 'Unavailable'}
7261
</div>
73-
<div data-e2e="card-storage-marker" className="text-[10px] opacity-50">[card v2]</div>
74-
75-
{storage && (
76-
<div className="mt-3 mb-1 text-xs text-gray-500">
77-
<span className="font-bold">Storage: </span>
78-
<span className="inline-flex items-center">
79-
{storage.name} {storage.type && ( <img src={getStorageLogoFromType(storage.type)}
80-
alt="storageIcon" className="ml-1 h-4 w-4" /> )}
81-
</span> </div> )}
82-
83-
{database.lastBackupTime && (
84-
<div className="mt-3 mb-1 text-xs text-gray-500">
85-
<span className="font-bold">Last backup</span>
86-
<br />
87-
{dayjs(database.lastBackupTime).format(getUserShortTimeFormat().format)} (
88-
{dayjs(database.lastBackupTime).fromNow()})
89-
</div>
62+
</div>
63+
)}
64+
</div>
65+
66+
<div className="mb flex items-center">
67+
<div className="text-sm text-gray-500">Database type: {databaseType}</div>
68+
<img src={databaseIcon} alt="databaseIcon" className="ml-1 h-4 w-4" />
69+
</div>
70+
<div data-e2e="card-storage-marker" className="text-[10px] opacity-50">
71+
[card v2]
72+
</div>
73+
74+
{storage && (
75+
<div className="mt-3 mb-1 text-xs text-gray-500">
76+
<span className="font-bold">Storage: </span>
77+
<span className="inline-flex items-center">
78+
{storage.name}{' '}
79+
{storage.type && (
80+
<img
81+
src={getStorageLogoFromType(storage.type)}
82+
alt="storageIcon"
83+
className="ml-1 h-4 w-4"
84+
/>
9085
)}
86+
</span>{' '}
87+
</div>
88+
)}
89+
90+
{database.lastBackupTime && (
91+
<div className="mt-3 mb-1 text-xs text-gray-500">
92+
<span className="font-bold">Last backup</span>
93+
<br />
94+
{dayjs(database.lastBackupTime).format(getUserShortTimeFormat().format)} (
95+
{dayjs(database.lastBackupTime).fromNow()})
96+
</div>
97+
)}
9198

92-
{database.lastBackupErrorMessage && (
93-
<div className="mt-1 flex items-center text-sm text-red-600 underline">
94-
<InfoCircleOutlined className="mr-1" style={{ color: 'red' }} />
95-
Has backup error
96-
</div>
97-
)}
99+
{database.lastBackupErrorMessage && (
100+
<div className="mt-1 flex items-center text-sm text-red-600 underline">
101+
<InfoCircleOutlined className="mr-1" style={{ color: 'red' }} />
102+
Has backup error
98103
</div>
99-
);
100-
};
104+
)}
105+
</div>
106+
);
107+
};

0 commit comments

Comments
 (0)