fix: update styles in various components to use dynamic theming and improve layout consistency
This commit is contained in:
@ -12,7 +12,8 @@
|
|||||||
"test": "(tstest test/ --logfile --timeout 60)",
|
"test": "(tstest test/ --logfile --timeout 60)",
|
||||||
"start": "(node --max_old_space_size=250 ./cli.js)",
|
"start": "(node --max_old_space_size=250 ./cli.js)",
|
||||||
"startTs": "(node cli.ts.js)",
|
"startTs": "(node cli.ts.js)",
|
||||||
"build": "(tsbuild tsfolders --allowimplicitany && tsbundle website --production)"
|
"build": "(tsbuild tsfolders --allowimplicitany && npm run bundle)",
|
||||||
|
"bundle": "(tsbundle website --production)"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.6.4",
|
"@git.zone/tsbuild": "^2.6.4",
|
||||||
@ -29,7 +30,7 @@
|
|||||||
"@api.global/typedserver": "^3.0.74",
|
"@api.global/typedserver": "^3.0.74",
|
||||||
"@api.global/typedsocket": "^3.0.0",
|
"@api.global/typedsocket": "^3.0.0",
|
||||||
"@apiclient.xyz/cloudflare": "^6.4.1",
|
"@apiclient.xyz/cloudflare": "^6.4.1",
|
||||||
"@design.estate/dees-catalog": "^1.8.8",
|
"@design.estate/dees-catalog": "^1.8.13",
|
||||||
"@design.estate/dees-element": "^2.0.42",
|
"@design.estate/dees-element": "^2.0.42",
|
||||||
"@push.rocks/projectinfo": "^5.0.1",
|
"@push.rocks/projectinfo": "^5.0.1",
|
||||||
"@push.rocks/qenv": "^6.1.0",
|
"@push.rocks/qenv": "^6.1.0",
|
||||||
|
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -24,8 +24,8 @@ importers:
|
|||||||
specifier: ^6.4.1
|
specifier: ^6.4.1
|
||||||
version: 6.4.1
|
version: 6.4.1
|
||||||
'@design.estate/dees-catalog':
|
'@design.estate/dees-catalog':
|
||||||
specifier: ^1.8.8
|
specifier: ^1.8.13
|
||||||
version: 1.8.8
|
version: 1.8.13
|
||||||
'@design.estate/dees-element':
|
'@design.estate/dees-element':
|
||||||
specifier: ^2.0.42
|
specifier: ^2.0.42
|
||||||
version: 2.0.42
|
version: 2.0.42
|
||||||
@ -344,8 +344,8 @@ packages:
|
|||||||
'@dabh/diagnostics@2.0.3':
|
'@dabh/diagnostics@2.0.3':
|
||||||
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
|
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
|
||||||
|
|
||||||
'@design.estate/dees-catalog@1.8.8':
|
'@design.estate/dees-catalog@1.8.13':
|
||||||
resolution: {integrity: sha512-so0Jju95vZGsNUKi/ze1bHoK1LOgkCuU+xeiWDMfUpGkJA8OE9wPJmy5hSyIecc352JtlhOkgmTh/XxFTGpkQg==}
|
resolution: {integrity: sha512-ZsGaioZZlo4Z12VIVeE5KF1BrwDbDfiqI7DCr0Cl0wuQtZdHtrGbvbevQTxTXj9c5FlzU450eAs23sMAeRreJg==}
|
||||||
|
|
||||||
'@design.estate/dees-comms@1.0.27':
|
'@design.estate/dees-comms@1.0.27':
|
||||||
resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==}
|
resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==}
|
||||||
@ -5087,7 +5087,7 @@ snapshots:
|
|||||||
enabled: 2.0.0
|
enabled: 2.0.0
|
||||||
kuler: 2.0.0
|
kuler: 2.0.0
|
||||||
|
|
||||||
'@design.estate/dees-catalog@1.8.8':
|
'@design.estate/dees-catalog@1.8.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-domtools': 2.3.2
|
'@design.estate/dees-domtools': 2.3.2
|
||||||
'@design.estate/dees-element': 2.0.42
|
'@design.estate/dees-element': 2.0.42
|
||||||
|
@ -41,17 +41,17 @@ export class OpsViewConfig extends DeesElement {
|
|||||||
shared.viewHostCss,
|
shared.viewHostCss,
|
||||||
css`
|
css`
|
||||||
.configSection {
|
.configSection {
|
||||||
background: white;
|
background: ${cssManager.bdTheme('#fff', '#222')};
|
||||||
border: 1px solid #e9ecef;
|
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sectionHeader {
|
.sectionHeader {
|
||||||
background: #f8f9fa;
|
background: ${cssManager.bdTheme('#f8f9fa', '#1a1a1a')};
|
||||||
padding: 16px 24px;
|
padding: 16px 24px;
|
||||||
border-bottom: 1px solid #e9ecef;
|
border-bottom: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -60,7 +60,7 @@ export class OpsViewConfig extends DeesElement {
|
|||||||
.sectionTitle {
|
.sectionTitle {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333;
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.sectionContent {
|
.sectionContent {
|
||||||
@ -74,7 +74,7 @@ export class OpsViewConfig extends DeesElement {
|
|||||||
.fieldLabel {
|
.fieldLabel {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@ -82,11 +82,11 @@ export class OpsViewConfig extends DeesElement {
|
|||||||
.fieldValue {
|
.fieldValue {
|
||||||
font-family: 'Consolas', 'Monaco', monospace;
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #333;
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
background: #f8f9fa;
|
background: ${cssManager.bdTheme('#f8f9fa', '#1a1a1a')};
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #e9ecef;
|
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.configEditor {
|
.configEditor {
|
||||||
@ -95,9 +95,9 @@ export class OpsViewConfig extends DeesElement {
|
|||||||
font-family: 'Consolas', 'Monaco', monospace;
|
font-family: 'Consolas', 'Monaco', monospace;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border: 1px solid #e9ecef;
|
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #f8f9fa;
|
background: ${cssManager.bdTheme('#f8f9fa', '#1a1a1a')};
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,30 +108,30 @@ export class OpsViewConfig extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
background: #fff3cd;
|
background: ${cssManager.bdTheme('#fff3cd', '#4a4a1a')};
|
||||||
border: 1px solid #ffeaa7;
|
border: 1px solid ${cssManager.bdTheme('#ffeaa7', '#666633')};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
color: #856404;
|
color: ${cssManager.bdTheme('#856404', '#ffcc66')};
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.errorMessage {
|
.errorMessage {
|
||||||
background: #fee;
|
background: ${cssManager.bdTheme('#fee', '#4a1f1f')};
|
||||||
border: 1px solid #fcc;
|
border: 1px solid ${cssManager.bdTheme('#fcc', '#6a2f2f')};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
color: #c00;
|
color: ${cssManager.bdTheme('#c00', '#ff6666')};
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loadingMessage {
|
.loadingMessage {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@ -64,21 +64,20 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emailContainer {
|
.emailLayout {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: 280px 1fr;
|
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
display: flex;
|
flex-shrink: 0;
|
||||||
flex-direction: column;
|
width: 280px;
|
||||||
gap: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainContent {
|
.mainArea {
|
||||||
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
@ -107,22 +106,22 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: white;
|
background: ${cssManager.bdTheme('#fff', '#222')};
|
||||||
border: 1px solid #e9ecef;
|
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emailHeader {
|
.emailHeader {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
border-bottom: 1px solid #e9ecef;
|
border-bottom: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.emailSubject {
|
.emailSubject {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
color: #333;
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.emailMeta {
|
.emailMeta {
|
||||||
@ -130,7 +129,7 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.emailMetaRow {
|
.emailMetaRow {
|
||||||
@ -155,8 +154,8 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 16px 24px;
|
padding: 16px 24px;
|
||||||
border-top: 1px solid #e9ecef;
|
border-top: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
background: #fafafa;
|
background: ${cssManager.bdTheme('#fafafa', '#1a1a1a')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.emptyState {
|
.emptyState {
|
||||||
@ -165,7 +164,7 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: #999;
|
color: ${cssManager.bdTheme('#999', '#666')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.emptyIcon {
|
.emptyIcon {
|
||||||
@ -177,65 +176,81 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
.emptyText {
|
.emptyText {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.email-read {
|
||||||
|
color: ${cssManager.bdTheme('#999', '#666')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-unread {
|
||||||
|
color: ${cssManager.bdTheme('#1976d2', '#4a90e2')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-icon {
|
||||||
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
if (this.selectedEmail) {
|
||||||
|
return html`
|
||||||
|
<ops-sectionheading>Emails</ops-sectionheading>
|
||||||
|
<div class="emailLayout">
|
||||||
|
<div class="sidebar">
|
||||||
|
<dees-windowbox>
|
||||||
|
<dees-button @click=${() => this.selectedEmail = null} type="secondary" style="width: 100%;">
|
||||||
|
<dees-icon name="arrowLeft" slot="iconSlot"></dees-icon>
|
||||||
|
Back to List
|
||||||
|
</dees-button>
|
||||||
|
<dees-menu style="margin-top: 16px;">
|
||||||
|
<dees-menu-item
|
||||||
|
.active=${this.selectedFolder === 'inbox'}
|
||||||
|
@click=${() => { this.selectFolder('inbox'); this.selectedEmail = null; }}
|
||||||
|
.iconName=${'inbox'}
|
||||||
|
.label=${'Inbox'}
|
||||||
|
.badgeText=${this.getEmailCount('inbox') > 0 ? String(this.getEmailCount('inbox')) : ''}
|
||||||
|
></dees-menu-item>
|
||||||
|
<dees-menu-item
|
||||||
|
.active=${this.selectedFolder === 'sent'}
|
||||||
|
@click=${() => { this.selectFolder('sent'); this.selectedEmail = null; }}
|
||||||
|
.iconName=${'paperPlane'}
|
||||||
|
.label=${'Sent'}
|
||||||
|
.badgeText=${this.getEmailCount('sent') > 0 ? String(this.getEmailCount('sent')) : ''}
|
||||||
|
></dees-menu-item>
|
||||||
|
<dees-menu-item
|
||||||
|
.active=${this.selectedFolder === 'draft'}
|
||||||
|
@click=${() => { this.selectFolder('draft'); this.selectedEmail = null; }}
|
||||||
|
.iconName=${'file'}
|
||||||
|
.label=${'Drafts'}
|
||||||
|
.badgeText=${this.getEmailCount('draft') > 0 ? String(this.getEmailCount('draft')) : ''}
|
||||||
|
></dees-menu-item>
|
||||||
|
<dees-menu-item
|
||||||
|
.active=${this.selectedFolder === 'trash'}
|
||||||
|
@click=${() => { this.selectFolder('trash'); this.selectedEmail = null; }}
|
||||||
|
.iconName=${'trash'}
|
||||||
|
.label=${'Trash'}
|
||||||
|
.badgeText=${this.getEmailCount('trash') > 0 ? String(this.getEmailCount('trash')) : ''}
|
||||||
|
></dees-menu-item>
|
||||||
|
</dees-menu>
|
||||||
|
</dees-windowbox>
|
||||||
|
</div>
|
||||||
|
<div class="mainArea">
|
||||||
|
${this.renderEmailPreview()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ops-sectionheading>Emails</ops-sectionheading>
|
<ops-sectionheading>Emails</ops-sectionheading>
|
||||||
|
|
||||||
<div class="emailContainer">
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<dees-windowbox>
|
|
||||||
<dees-button @click=${() => this.openComposeModal()} type="highlighted" style="width: 100%;">
|
|
||||||
<dees-icon name="penToSquare" slot="iconSlot"></dees-icon>
|
|
||||||
Compose
|
|
||||||
</dees-button>
|
|
||||||
|
|
||||||
<dees-menu style="margin-top: 16px;">
|
|
||||||
<dees-menu-item
|
|
||||||
.active=${this.selectedFolder === 'inbox'}
|
|
||||||
@click=${() => this.selectFolder('inbox')}
|
|
||||||
.iconName=${'inbox'}
|
|
||||||
.label=${'Inbox'}
|
|
||||||
.badgeText=${this.getEmailCount('inbox') > 0 ? String(this.getEmailCount('inbox')) : ''}
|
|
||||||
></dees-menu-item>
|
|
||||||
<dees-menu-item
|
|
||||||
.active=${this.selectedFolder === 'sent'}
|
|
||||||
@click=${() => this.selectFolder('sent')}
|
|
||||||
.iconName=${'paperPlane'}
|
|
||||||
.label=${'Sent'}
|
|
||||||
.badgeText=${this.getEmailCount('sent') > 0 ? String(this.getEmailCount('sent')) : ''}
|
|
||||||
></dees-menu-item>
|
|
||||||
<dees-menu-item
|
|
||||||
.active=${this.selectedFolder === 'draft'}
|
|
||||||
@click=${() => this.selectFolder('draft')}
|
|
||||||
.iconName=${'file'}
|
|
||||||
.label=${'Drafts'}
|
|
||||||
.badgeText=${this.getEmailCount('draft') > 0 ? String(this.getEmailCount('draft')) : ''}
|
|
||||||
></dees-menu-item>
|
|
||||||
<dees-menu-item
|
|
||||||
.active=${this.selectedFolder === 'trash'}
|
|
||||||
@click=${() => this.selectFolder('trash')}
|
|
||||||
.iconName=${'trash'}
|
|
||||||
.label=${'Trash'}
|
|
||||||
.badgeText=${this.getEmailCount('trash') > 0 ? String(this.getEmailCount('trash')) : ''}
|
|
||||||
></dees-menu-item>
|
|
||||||
</dees-menu>
|
|
||||||
</dees-windowbox>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div class="mainContent">
|
|
||||||
${this.selectedEmail ? this.renderEmailPreview() : this.renderEmailListView()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderEmailListView() {
|
|
||||||
return html`
|
|
||||||
<!-- Toolbar -->
|
<!-- Toolbar -->
|
||||||
<div class="emailToolbar">
|
<div class="emailToolbar" style="margin-bottom: 16px;">
|
||||||
|
<dees-button @click=${() => this.openComposeModal()} type="highlighted">
|
||||||
|
<dees-icon name="penToSquare" slot="iconSlot"></dees-icon>
|
||||||
|
Compose
|
||||||
|
</dees-button>
|
||||||
|
|
||||||
<dees-input-text
|
<dees-input-text
|
||||||
class="searchBox"
|
class="searchBox"
|
||||||
placeholder="Search emails..."
|
placeholder="Search emails..."
|
||||||
@ -246,20 +261,50 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
</dees-input-text>
|
</dees-input-text>
|
||||||
|
|
||||||
<dees-button @click=${() => this.refreshEmails()}>
|
<dees-button @click=${() => this.refreshEmails()}>
|
||||||
${this.isLoading ? html`<dees-spinner size="small"></dees-spinner>` : html`<dees-icon name="arrowsRotate"></dees-icon>`}
|
${this.isLoading ? html`<dees-spinner slot="iconSlot" size="small"></dees-spinner>` : html`<dees-icon slot="iconSlot" name="arrowsRotate"></dees-icon>`}
|
||||||
|
Refresh
|
||||||
</dees-button>
|
</dees-button>
|
||||||
|
|
||||||
<dees-button @click=${() => this.markAllAsRead()}>
|
<dees-button @click=${() => this.markAllAsRead()}>
|
||||||
<dees-icon name="envelopeOpen"></dees-icon>
|
<dees-icon name="envelopeOpen" slot="iconSlot"></dees-icon>
|
||||||
Mark all read
|
Mark all read
|
||||||
</dees-button>
|
</dees-button>
|
||||||
|
|
||||||
|
<div style="margin-left: auto; display: flex; gap: 8px;">
|
||||||
|
<dees-button-group>
|
||||||
|
<dees-button
|
||||||
|
@click=${() => this.selectFolder('inbox')}
|
||||||
|
.type=${this.selectedFolder === 'inbox' ? 'highlighted' : 'normal'}
|
||||||
|
>
|
||||||
|
Inbox ${this.getEmailCount('inbox') > 0 ? `(${this.getEmailCount('inbox')})` : ''}
|
||||||
|
</dees-button>
|
||||||
|
<dees-button
|
||||||
|
@click=${() => this.selectFolder('sent')}
|
||||||
|
.type=${this.selectedFolder === 'sent' ? 'highlighted' : 'normal'}
|
||||||
|
>
|
||||||
|
Sent
|
||||||
|
</dees-button>
|
||||||
|
<dees-button
|
||||||
|
@click=${() => this.selectFolder('draft')}
|
||||||
|
.type=${this.selectedFolder === 'draft' ? 'highlighted' : 'normal'}
|
||||||
|
>
|
||||||
|
Drafts ${this.getEmailCount('draft') > 0 ? `(${this.getEmailCount('draft')})` : ''}
|
||||||
|
</dees-button>
|
||||||
|
<dees-button
|
||||||
|
@click=${() => this.selectFolder('trash')}
|
||||||
|
.type=${this.selectedFolder === 'trash' ? 'highlighted' : 'normal'}
|
||||||
|
>
|
||||||
|
Trash
|
||||||
|
</dees-button>
|
||||||
|
</dees-button-group>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Email List -->
|
|
||||||
${this.renderEmailList()}
|
${this.renderEmailList()}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private renderEmailList() {
|
private renderEmailList() {
|
||||||
const filteredEmails = this.getFilteredEmails();
|
const filteredEmails = this.getFilteredEmails();
|
||||||
|
|
||||||
@ -276,12 +321,12 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
<dees-table
|
<dees-table
|
||||||
.data=${filteredEmails}
|
.data=${filteredEmails}
|
||||||
.displayFunction=${(email: IEmail) => ({
|
.displayFunction=${(email: IEmail) => ({
|
||||||
'Status': html`<dees-icon name="${email.read ? 'envelopeOpen' : 'envelope'}" style="color: ${email.read ? '#999' : '#1976d2'}"></dees-icon>`,
|
'Status': html`<dees-icon name="${email.read ? 'envelopeOpen' : 'envelope'}" class="${email.read ? 'email-read' : 'email-unread'}"></dees-icon>`,
|
||||||
From: email.from,
|
From: email.from,
|
||||||
Subject: html`<strong style="${!email.read ? 'font-weight: 600' : ''}">${email.subject}</strong>`,
|
Subject: html`<strong style="${!email.read ? 'font-weight: 600' : ''}">${email.subject}</strong>`,
|
||||||
Date: this.formatDate(email.date),
|
Date: this.formatDate(email.date),
|
||||||
'Attach': html`
|
'Attach': html`
|
||||||
${email.attachments?.length ? html`<dees-icon name="paperclip" style="color: #666"></dees-icon>` : ''}
|
${email.attachments?.length ? html`<dees-icon name="paperclip" class="attachment-icon"></dees-icon>` : ''}
|
||||||
`,
|
`,
|
||||||
})}
|
})}
|
||||||
.dataActions=${[
|
.dataActions=${[
|
||||||
@ -365,11 +410,7 @@ export class OpsViewEmails extends DeesElement {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="emailActions">
|
<div class="emailActions">
|
||||||
<dees-button @click=${() => this.selectedEmail = null} type="secondary">
|
<div style="display: flex; gap: 8px;">
|
||||||
<dees-icon name="arrowLeft" slot="iconSlot"></dees-icon>
|
|
||||||
Back to List
|
|
||||||
</dees-button>
|
|
||||||
<div style="margin-left: auto; display: flex; gap: 8px;">
|
|
||||||
<dees-button @click=${() => this.replyToEmail(this.selectedEmail!)}>
|
<dees-button @click=${() => this.replyToEmail(this.selectedEmail!)}>
|
||||||
<dees-icon name="reply" slot="iconSlot"></dees-icon>
|
<dees-icon name="reply" slot="iconSlot"></dees-icon>
|
||||||
Reply
|
Reply
|
||||||
|
@ -48,7 +48,7 @@ export class OpsViewLogs extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logContainer {
|
.logContainer {
|
||||||
background: #1e1e1e;
|
background: ${cssManager.bdTheme('#f8f9fa', '#1e1e1e')};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
max-height: 600px;
|
max-height: 600px;
|
||||||
@ -63,7 +63,7 @@ export class OpsViewLogs extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logTimestamp {
|
.logTimestamp {
|
||||||
color: #7a7a7a;
|
color: ${cssManager.bdTheme('#7a7a7a', '#7a7a7a')};
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,33 +76,33 @@ export class OpsViewLogs extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logLevel.debug {
|
.logLevel.debug {
|
||||||
color: #6a9955;
|
color: ${cssManager.bdTheme('#6a9955', '#6a9955')};
|
||||||
background: rgba(106, 153, 85, 0.1);
|
background: ${cssManager.bdTheme('rgba(106, 153, 85, 0.1)', 'rgba(106, 153, 85, 0.1)')};
|
||||||
}
|
}
|
||||||
.logLevel.info {
|
.logLevel.info {
|
||||||
color: #569cd6;
|
color: ${cssManager.bdTheme('#569cd6', '#569cd6')};
|
||||||
background: rgba(86, 156, 214, 0.1);
|
background: ${cssManager.bdTheme('rgba(86, 156, 214, 0.1)', 'rgba(86, 156, 214, 0.1)')};
|
||||||
}
|
}
|
||||||
.logLevel.warn {
|
.logLevel.warn {
|
||||||
color: #ce9178;
|
color: ${cssManager.bdTheme('#ce9178', '#ce9178')};
|
||||||
background: rgba(206, 145, 120, 0.1);
|
background: ${cssManager.bdTheme('rgba(206, 145, 120, 0.1)', 'rgba(206, 145, 120, 0.1)')};
|
||||||
}
|
}
|
||||||
.logLevel.error {
|
.logLevel.error {
|
||||||
color: #f44747;
|
color: ${cssManager.bdTheme('#f44747', '#f44747')};
|
||||||
background: rgba(244, 71, 71, 0.1);
|
background: ${cssManager.bdTheme('rgba(244, 71, 71, 0.1)', 'rgba(244, 71, 71, 0.1)')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.logCategory {
|
.logCategory {
|
||||||
color: #c586c0;
|
color: ${cssManager.bdTheme('#c586c0', '#c586c0')};
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logMessage {
|
.logMessage {
|
||||||
color: #d4d4d4;
|
color: ${cssManager.bdTheme('#333', '#d4d4d4')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.noLogs {
|
.noLogs {
|
||||||
color: #7a7a7a;
|
color: ${cssManager.bdTheme('#7a7a7a', '#7a7a7a')};
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
}
|
}
|
||||||
|
@ -74,14 +74,11 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.controlBar {
|
.controlBar {
|
||||||
background: white;
|
|
||||||
border: 1px solid #e9ecef;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 16px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controlGroup {
|
.controlGroup {
|
||||||
@ -92,7 +89,7 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
|
|
||||||
.controlLabel {
|
.controlLabel {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,28 +111,28 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.protocolBadge.http {
|
.protocolBadge.http {
|
||||||
background: #e3f2fd;
|
background: ${cssManager.bdTheme('#e3f2fd', '#1a2c3a')};
|
||||||
color: #1976d2;
|
color: ${cssManager.bdTheme('#1976d2', '#5a9fd4')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocolBadge.https {
|
.protocolBadge.https {
|
||||||
background: #e8f5e9;
|
background: ${cssManager.bdTheme('#e8f5e9', '#1a3a1a')};
|
||||||
color: #388e3c;
|
color: ${cssManager.bdTheme('#388e3c', '#66bb6a')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocolBadge.tcp {
|
.protocolBadge.tcp {
|
||||||
background: #fff3e0;
|
background: ${cssManager.bdTheme('#fff3e0', '#3a2a1a')};
|
||||||
color: #f57c00;
|
color: ${cssManager.bdTheme('#f57c00', '#ff9933')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocolBadge.smtp {
|
.protocolBadge.smtp {
|
||||||
background: #f3e5f5;
|
background: ${cssManager.bdTheme('#f3e5f5', '#2a1a3a')};
|
||||||
color: #7b1fa2;
|
color: ${cssManager.bdTheme('#7b1fa2', '#ba68c8')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocolBadge.dns {
|
.protocolBadge.dns {
|
||||||
background: #e0f2f1;
|
background: ${cssManager.bdTheme('#e0f2f1', '#1a3a3a')};
|
||||||
color: #00796b;
|
color: ${cssManager.bdTheme('#00796b', '#4db6ac')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusBadge {
|
.statusBadge {
|
||||||
@ -148,18 +145,18 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.statusBadge.success {
|
.statusBadge.success {
|
||||||
background: #e8f5e9;
|
background: ${cssManager.bdTheme('#e8f5e9', '#1a3a1a')};
|
||||||
color: #388e3c;
|
color: ${cssManager.bdTheme('#388e3c', '#66bb6a')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusBadge.error {
|
.statusBadge.error {
|
||||||
background: #ffebee;
|
background: ${cssManager.bdTheme('#ffebee', '#3a1a1a')};
|
||||||
color: #d32f2f;
|
color: ${cssManager.bdTheme('#d32f2f', '#ff6666')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusBadge.warning {
|
.statusBadge.warning {
|
||||||
background: #fff3e0;
|
background: ${cssManager.bdTheme('#fff3e0', '#3a2a1a')};
|
||||||
color: #f57c00;
|
color: ${cssManager.bdTheme('#f57c00', '#ff9933')};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@ -44,7 +44,7 @@ export class OpsViewOverview extends DeesElement {
|
|||||||
margin: 32px 0 16px 0;
|
margin: 32px 0 16px 0;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333;
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.chartGrid {
|
.chartGrid {
|
||||||
@ -57,15 +57,15 @@ export class OpsViewOverview extends DeesElement {
|
|||||||
.loadingMessage {
|
.loadingMessage {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.errorMessage {
|
.errorMessage {
|
||||||
background-color: #fee;
|
background-color: ${cssManager.bdTheme('#fee', '#4a1f1f')};
|
||||||
border: 1px solid #fcc;
|
border: 1px solid ${cssManager.bdTheme('#fcc', '#6a2f2f')};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
color: #c00;
|
color: ${cssManager.bdTheme('#c00', '#ff6666')};
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
cssManager,
|
cssManager,
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
||||||
|
|
||||||
@customElement('ops-view-security')
|
@customElement('ops-view-security')
|
||||||
export class OpsViewSecurity extends DeesElement {
|
export class OpsViewSecurity extends DeesElement {
|
||||||
@ -45,7 +46,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
border-bottom: 2px solid #e9ecef;
|
border-bottom: 2px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
@ -55,29 +56,33 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab:hover {
|
.tab:hover {
|
||||||
color: #333;
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab.active {
|
.tab.active {
|
||||||
color: #2196F3;
|
color: ${cssManager.bdTheme('#2196F3', '#4a90e2')};
|
||||||
border-bottom-color: #2196F3;
|
border-bottom-color: ${cssManager.bdTheme('#2196F3', '#4a90e2')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.securityGrid {
|
h2 {
|
||||||
display: grid;
|
margin: 32px 0 16px 0;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
font-size: 24px;
|
||||||
gap: 16px;
|
font-weight: 600;
|
||||||
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
|
}
|
||||||
|
|
||||||
|
dees-statsgrid {
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.securityCard {
|
.securityCard {
|
||||||
background: white;
|
background: ${cssManager.bdTheme('#fff', '#222')};
|
||||||
border: 1px solid #e9ecef;
|
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -85,18 +90,18 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.securityCard.alert {
|
.securityCard.alert {
|
||||||
border-color: #f44336;
|
border-color: ${cssManager.bdTheme('#f44336', '#ff6666')};
|
||||||
background: #ffebee;
|
background: ${cssManager.bdTheme('#ffebee', '#4a1f1f')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.securityCard.warning {
|
.securityCard.warning {
|
||||||
border-color: #ff9800;
|
border-color: ${cssManager.bdTheme('#ff9800', '#ffaa33')};
|
||||||
background: #fff3e0;
|
background: ${cssManager.bdTheme('#fff3e0', '#4a3a1f')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.securityCard.success {
|
.securityCard.success {
|
||||||
border-color: #4caf50;
|
border-color: ${cssManager.bdTheme('#4caf50', '#66cc66')};
|
||||||
background: #e8f5e9;
|
background: ${cssManager.bdTheme('#e8f5e9', '#1f3f1f')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardHeader {
|
.cardHeader {
|
||||||
@ -109,7 +114,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
.cardTitle {
|
.cardTitle {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #333;
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardStatus {
|
.cardStatus {
|
||||||
@ -120,18 +125,18 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-critical {
|
.status-critical {
|
||||||
background: #f44336;
|
background: ${cssManager.bdTheme('#f44336', '#ff6666')};
|
||||||
color: white;
|
color: ${cssManager.bdTheme('#fff', '#fff')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-warning {
|
.status-warning {
|
||||||
background: #ff9800;
|
background: ${cssManager.bdTheme('#ff9800', '#ffaa33')};
|
||||||
color: white;
|
color: ${cssManager.bdTheme('#fff', '#fff')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-good {
|
.status-good {
|
||||||
background: #4caf50;
|
background: ${cssManager.bdTheme('#4caf50', '#66cc66')};
|
||||||
color: white;
|
color: ${cssManager.bdTheme('#fff', '#fff')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.metricValue {
|
.metricValue {
|
||||||
@ -142,7 +147,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
|
|
||||||
.metricLabel {
|
.metricLabel {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionButton {
|
.actionButton {
|
||||||
@ -159,7 +164,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-bottom: 1px solid #e9ecef;
|
border-bottom: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.blockedIpItem:last-child {
|
.blockedIpItem:last-child {
|
||||||
@ -173,12 +178,12 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
|
|
||||||
.blockReason {
|
.blockReason {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: ${cssManager.bdTheme('#666', '#999')};
|
||||||
}
|
}
|
||||||
|
|
||||||
.blockTime {
|
.blockTime {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #999;
|
color: ${cssManager.bdTheme('#999', '#666')};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
@ -243,36 +248,60 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
|
|
||||||
private renderOverview(metrics: any) {
|
private renderOverview(metrics: any) {
|
||||||
const threatLevel = this.calculateThreatLevel(metrics);
|
const threatLevel = this.calculateThreatLevel(metrics);
|
||||||
|
const threatScore = this.getThreatScore(metrics);
|
||||||
|
|
||||||
|
const tiles: IStatsTile[] = [
|
||||||
|
{
|
||||||
|
id: 'threatLevel',
|
||||||
|
title: 'Threat Level',
|
||||||
|
value: threatScore,
|
||||||
|
type: 'gauge',
|
||||||
|
icon: 'shield',
|
||||||
|
gaugeOptions: {
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
thresholds: [
|
||||||
|
{ value: 0, color: '#ef4444' },
|
||||||
|
{ value: 30, color: '#f59e0b' },
|
||||||
|
{ value: 70, color: '#22c55e' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
description: `Status: ${threatLevel.toUpperCase()}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'blockedThreats',
|
||||||
|
title: 'Blocked Threats',
|
||||||
|
value: metrics.blockedIPs.length + metrics.spamDetected,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'userShield',
|
||||||
|
color: '#ef4444',
|
||||||
|
description: 'Total threats blocked today',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'activeSessions',
|
||||||
|
title: 'Active Sessions',
|
||||||
|
value: 0,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'users',
|
||||||
|
color: '#22c55e',
|
||||||
|
description: 'Current authenticated sessions',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'authFailures',
|
||||||
|
title: 'Auth Failures',
|
||||||
|
value: metrics.authenticationFailures,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'lockOpen',
|
||||||
|
color: metrics.authenticationFailures > 10 ? '#ef4444' : '#f59e0b',
|
||||||
|
description: 'Failed login attempts today',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="securityGrid">
|
<dees-statsgrid
|
||||||
<div class="securityCard ${threatLevel}">
|
.tiles=${tiles}
|
||||||
<div class="cardHeader">
|
.minTileWidth=${200}
|
||||||
<h3 class="cardTitle">Threat Level</h3>
|
></dees-statsgrid>
|
||||||
<span class="cardStatus status-${threatLevel === 'alert' ? 'critical' : threatLevel === 'warning' ? 'warning' : 'good'}">
|
|
||||||
${threatLevel.toUpperCase()}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="metricValue">${this.getThreatScore(metrics)}/100</div>
|
|
||||||
<div class="metricLabel">Overall security score</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="securityCard">
|
|
||||||
<div class="cardHeader">
|
|
||||||
<h3 class="cardTitle">Blocked Threats</h3>
|
|
||||||
</div>
|
|
||||||
<div class="metricValue">${metrics.blockedIPs.length + metrics.spamDetected}</div>
|
|
||||||
<div class="metricLabel">Total threats blocked today</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="securityCard">
|
|
||||||
<div class="cardHeader">
|
|
||||||
<h3 class="cardTitle">Active Sessions</h3>
|
|
||||||
</div>
|
|
||||||
<div class="metricValue">${0}</div>
|
|
||||||
<div class="metricLabel">Current authenticated sessions</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Recent Security Events</h2>
|
<h2>Recent Security Events</h2>
|
||||||
<dees-table
|
<dees-table
|
||||||
@ -320,20 +349,32 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private renderAuthentication(metrics: any) {
|
private renderAuthentication(metrics: any) {
|
||||||
return html`
|
const tiles: IStatsTile[] = [
|
||||||
<div class="securityGrid">
|
{
|
||||||
<div class="securityCard">
|
id: 'authFailures',
|
||||||
<h3 class="cardTitle">Authentication Statistics</h3>
|
title: 'Authentication Failures',
|
||||||
<div class="metricValue">${metrics.authenticationFailures}</div>
|
value: metrics.authenticationFailures,
|
||||||
<div class="metricLabel">Failed authentication attempts today</div>
|
type: 'number',
|
||||||
</div>
|
icon: 'lockOpen',
|
||||||
|
color: metrics.authenticationFailures > 10 ? '#ef4444' : '#f59e0b',
|
||||||
|
description: 'Failed authentication attempts today',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'successfulLogins',
|
||||||
|
title: 'Successful Logins',
|
||||||
|
value: 0,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'lock',
|
||||||
|
color: '#22c55e',
|
||||||
|
description: 'Successful logins today',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
<div class="securityCard">
|
return html`
|
||||||
<h3 class="cardTitle">Successful Logins</h3>
|
<dees-statsgrid
|
||||||
<div class="metricValue">${0}</div>
|
.tiles=${tiles}
|
||||||
<div class="metricLabel">Successful logins today</div>
|
.minTileWidth=${200}
|
||||||
</div>
|
></dees-statsgrid>
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Recent Login Attempts</h2>
|
<h2>Recent Login Attempts</h2>
|
||||||
<dees-table
|
<dees-table
|
||||||
@ -352,32 +393,50 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private renderEmailSecurity(metrics: any) {
|
private renderEmailSecurity(metrics: any) {
|
||||||
|
const tiles: IStatsTile[] = [
|
||||||
|
{
|
||||||
|
id: 'malware',
|
||||||
|
title: 'Malware Detection',
|
||||||
|
value: metrics.malwareDetected,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'virusSlash',
|
||||||
|
color: metrics.malwareDetected > 0 ? '#ef4444' : '#22c55e',
|
||||||
|
description: 'Malware detected',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'phishing',
|
||||||
|
title: 'Phishing Detection',
|
||||||
|
value: metrics.phishingDetected,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'fishFins',
|
||||||
|
color: metrics.phishingDetected > 0 ? '#ef4444' : '#22c55e',
|
||||||
|
description: 'Phishing attempts detected',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'suspicious',
|
||||||
|
title: 'Suspicious Activities',
|
||||||
|
value: metrics.suspiciousActivities,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'triangleExclamation',
|
||||||
|
color: metrics.suspiciousActivities > 5 ? '#ef4444' : '#f59e0b',
|
||||||
|
description: 'Suspicious activities detected',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'spam',
|
||||||
|
title: 'Spam Detection',
|
||||||
|
value: metrics.spamDetected,
|
||||||
|
type: 'number',
|
||||||
|
icon: 'ban',
|
||||||
|
color: '#f59e0b',
|
||||||
|
description: 'Spam emails blocked',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="securityGrid">
|
<dees-statsgrid
|
||||||
<div class="securityCard">
|
.tiles=${tiles}
|
||||||
<h3 class="cardTitle">Malware Detection</h3>
|
.minTileWidth=${200}
|
||||||
<div class="metricValue">${metrics.malwareDetected}</div>
|
></dees-statsgrid>
|
||||||
<div class="metricLabel">Malware detected</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="securityCard">
|
|
||||||
<h3 class="cardTitle">Phishing Detection</h3>
|
|
||||||
<div class="metricValue">${metrics.phishingDetected}</div>
|
|
||||||
<div class="metricLabel">Phishing attempts detected</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="securityCard">
|
|
||||||
<h3 class="cardTitle">Suspicious Activities</h3>
|
|
||||||
<div class="metricValue">${metrics.suspiciousActivities}</div>
|
|
||||||
<div class="metricLabel">Suspicious activities detected</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="securityCard">
|
|
||||||
<h3 class="cardTitle">Spam Detection</h3>
|
|
||||||
<div class="metricValue">${metrics.spamDetected}</div>
|
|
||||||
<div class="metricLabel">Spam emails blocked</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Email Security Configuration</h2>
|
<h2>Email Security Configuration</h2>
|
||||||
<div class="securityCard">
|
<div class="securityCard">
|
||||||
|
@ -21,14 +21,10 @@ export class OpsSectionHeading extends DeesElement {
|
|||||||
font-family: 'Cal Sans', 'Inter', sans-serif;
|
font-family: 'Cal Sans', 'Inter', sans-serif;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #111;
|
color: ${cssManager.bdTheme('#111', '#fff')};
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([theme="dark"]) .heading {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user