refactor(ui): modernize hub layout, certificate cards and dialogs
This commit is contained in:
+11
-3
@@ -3,6 +3,7 @@ package br.com.cybercore.signer.ui.components;
|
||||
import br.com.cybercore.signer.core.domain.CertificateStatus;
|
||||
import br.com.cybercore.signer.core.domain.CertificateType;
|
||||
import br.com.cybercore.signer.core.domain.ManagedCertificate;
|
||||
import javafx.scene.Node;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -34,24 +35,31 @@ public final class CertificateCardNode extends VBox {
|
||||
setCursor(javafx.scene.Cursor.HAND);
|
||||
setSpacing(8);
|
||||
|
||||
// Linha 1: Nome do Titular e Badge A1/A3
|
||||
// Linha 1: Ícone + Nome do Titular e Badge A1/A3
|
||||
HBox topRow = new HBox(10);
|
||||
topRow.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
Node certIcon = Icons.certificates(Icons.SIZE_20);
|
||||
|
||||
String rawName = certificate.commonName() != null ? certificate.commonName() : certificate.alias();
|
||||
String cleanTitle = rawName != null && rawName.contains(":") ? rawName.split(":")[0].trim() : (rawName != null ? rawName.trim() : "Certificado Digital");
|
||||
Label titleLabel = new Label(cleanTitle);
|
||||
titleLabel.getStyleClass().add("cert-title");
|
||||
HBox.setHgrow(titleLabel, Priority.ALWAYS);
|
||||
|
||||
Label badgeLabel = new Label("[" + certificate.type().getCode() + "]");
|
||||
HBox titleBox = new HBox(8, certIcon, titleLabel);
|
||||
titleBox.setAlignment(Pos.CENTER_LEFT);
|
||||
HBox.setHgrow(titleBox, Priority.ALWAYS);
|
||||
|
||||
String badgeText = certificate.type() == CertificateType.A1 ? "A1 • SOFTWARE" : "A3 • TOKEN";
|
||||
Label badgeLabel = new Label(badgeText);
|
||||
if (certificate.type() == CertificateType.A1) {
|
||||
badgeLabel.getStyleClass().add("cert-badge-a1");
|
||||
} else {
|
||||
badgeLabel.getStyleClass().add("cert-badge-a3");
|
||||
}
|
||||
|
||||
topRow.getChildren().addAll(titleLabel, badgeLabel);
|
||||
topRow.getChildren().addAll(titleBox, badgeLabel);
|
||||
|
||||
// Linha 2: Documento (CPF / CNPJ) e Emissor
|
||||
HBox midRow = new HBox(12);
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import javafx.scene.text.FontWeight;
|
||||
import javafx.scene.text.Text;
|
||||
|
||||
/**
|
||||
* Fábrica de ícones e grafismos vetoriais SVG nítidos e escaláveis para a interface Serpro do CyberCore Signer.
|
||||
* Fábrica de ícones e grafismos vetoriais SVG nítidos e escaláveis para a interface do CyberCore Signer.
|
||||
* Integra-se ao AssetManager para carregar dinamicamente arquivos .svg ou .png da pasta 'assets/icons/'.
|
||||
*/
|
||||
public final class SvgIcons {
|
||||
|
||||
+36
-28
@@ -1,6 +1,7 @@
|
||||
package br.com.cybercore.signer.ui.view;
|
||||
|
||||
import br.com.cybercore.signer.ui.CyberCoreUiConstants;
|
||||
import br.com.cybercore.signer.ui.components.Icons;
|
||||
import br.com.cybercore.signer.ui.components.SvgIcons;
|
||||
import br.com.cybercore.signer.ui.theme.ThemeManager;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -9,6 +10,7 @@ import javafx.scene.Node;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
@@ -57,7 +59,7 @@ public final class MainAppView {
|
||||
}
|
||||
|
||||
private void initLayout() {
|
||||
root.getStyleClass().addAll("cyber-root", "serpro-root");
|
||||
root.getStyleClass().add("cyber-root");
|
||||
root.setAlignment(Pos.TOP_CENTER);
|
||||
|
||||
// 1. Barra Superior Moderna com Identidade CyberCore, Status do Agente e Alternador de Tema
|
||||
@@ -69,37 +71,44 @@ public final class MainAppView {
|
||||
mainContent.setAlignment(Pos.CENTER);
|
||||
VBox.setVgrow(mainContent, Priority.ALWAYS);
|
||||
|
||||
// --- Hub Central de Ações (Grid 3 colunas x 2 linhas) ---
|
||||
// --- Hub Central de Ações (Grid 3 colunas x 2 linhas responsivo) ---
|
||||
GridPane actionGrid = new GridPane();
|
||||
actionGrid.setHgap(12);
|
||||
actionGrid.setVgap(12);
|
||||
actionGrid.setAlignment(Pos.CENTER);
|
||||
HBox.setHgrow(actionGrid, Priority.ALWAYS);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ColumnConstraints col = new ColumnConstraints();
|
||||
col.setHgrow(Priority.ALWAYS);
|
||||
col.setPercentWidth(33.33);
|
||||
actionGrid.getColumnConstraints().add(col);
|
||||
}
|
||||
|
||||
// Linha 0: Operações de Assinatura
|
||||
actionGrid.add(createActionButton(SvgIcons.pdfIcon(), "Assinar\nPDF", () -> trigger(onSignPdf)), 0, 0);
|
||||
actionGrid.add(createActionButton(SvgIcons.xmlIcon(), "Assinar\nXML", () -> trigger(onSignXml)), 1, 0);
|
||||
actionGrid.add(createActionButton(SvgIcons.attachedIcon(), "Assinatura\nAtachada", () -> trigger(onAttachedSign)), 2, 0);
|
||||
actionGrid.add(createActionButton(Icons.pdf(Icons.SIZE_40), "Assinar\nPDF", () -> trigger(onSignPdf)), 0, 0);
|
||||
actionGrid.add(createActionButton(Icons.xml(Icons.SIZE_40), "Assinar\nXML", () -> trigger(onSignXml)), 1, 0);
|
||||
actionGrid.add(createActionButton(Icons.attached(Icons.SIZE_40), "Assinatura\nAtachada", () -> trigger(onAttachedSign)), 2, 0);
|
||||
|
||||
// Linha 1: Identidade Visual, Auditoria e Saída
|
||||
actionGrid.add(createActionButton(SvgIcons.sealIcon(), "Gerenciar\nSelos", () -> trigger(onManageSeals)), 0, 1);
|
||||
actionGrid.add(createActionButton(SvgIcons.validateIcon(), "Validar\nAssinatura", () -> trigger(onValidateSignature)), 1, 1);
|
||||
actionGrid.add(createActionButton(SvgIcons.exitIcon(), "Sair do\nAgente", () -> trigger(onExit)), 2, 1);
|
||||
actionGrid.add(createActionButton(Icons.seal(Icons.SIZE_40), "Gerenciar\nSelos", () -> trigger(onManageSeals)), 0, 1);
|
||||
actionGrid.add(createActionButton(Icons.validate(Icons.SIZE_40), "Validar\nAssinatura", () -> trigger(onValidateSignature)), 1, 1);
|
||||
actionGrid.add(createActionButton(Icons.exit(Icons.SIZE_40), "Sair do\nAgente", () -> trigger(onExit)), 2, 1);
|
||||
|
||||
// --- Painel Lateral Direito (Ferramentas, Certificados e Diagnóstico) ---
|
||||
VBox sideColumn = new VBox(10);
|
||||
sideColumn.getStyleClass().add("cyber-side-column");
|
||||
sideColumn.setPrefWidth(195);
|
||||
sideColumn.setMinWidth(190);
|
||||
sideColumn.setMaxWidth(210);
|
||||
sideColumn.setPrefWidth(210);
|
||||
sideColumn.setMinWidth(180);
|
||||
sideColumn.setMaxWidth(230);
|
||||
sideColumn.setAlignment(Pos.TOP_CENTER);
|
||||
|
||||
sideColumn.getChildren().addAll(
|
||||
createSideButton(SvgIcons.logsIcon(), "Logs", () -> trigger(onLogs)),
|
||||
createSideButton(SvgIcons.settingsIcon(), "Configurações", () -> trigger(onSettings)),
|
||||
createSideButton(SvgIcons.tutorialIcon(), "Tutorial", () -> trigger(onTutorial)),
|
||||
createSideButton(SvgIcons.certificatesIcon(), "Certificados", () -> trigger(onCertificates)),
|
||||
createSideButton(SvgIcons.aboutIcon(), "Sobre", () -> trigger(onAbout))
|
||||
createSideButton(Icons.logs(Icons.SIZE_24), "Logs", () -> trigger(onLogs)),
|
||||
createSideButton(Icons.settings(Icons.SIZE_24), "Configurações", () -> trigger(onSettings)),
|
||||
createSideButton(Icons.tutorial(Icons.SIZE_24), "Tutorial", () -> trigger(onTutorial)),
|
||||
createSideButton(Icons.certificates(Icons.SIZE_24), "Certificados", () -> trigger(onCertificates)),
|
||||
createSideButton(Icons.about(Icons.SIZE_24), "Sobre", () -> trigger(onAbout))
|
||||
);
|
||||
|
||||
// Espaçador elástico e Rodapé de status local
|
||||
@@ -112,13 +121,13 @@ public final class MainAppView {
|
||||
|
||||
HBox brandFooter = new HBox(6);
|
||||
brandFooter.setAlignment(Pos.CENTER);
|
||||
Node smallLogo = SvgIcons.cyberShieldLogo(16);
|
||||
Node smallLogo = Icons.shield(Icons.SIZE_16);
|
||||
Label lblBrandFoot = new Label("CyberCore");
|
||||
lblBrandFoot.getStyleClass().addAll("cyber-version-label", "text-bold");
|
||||
brandFooter.getChildren().addAll(smallLogo, lblBrandFoot);
|
||||
|
||||
Label lblVersion = new Label("v" + CyberCoreUiConstants.APP_VERSION);
|
||||
lblVersion.getStyleClass().addAll("cyber-version-label", "serpro-version-label");
|
||||
lblVersion.getStyleClass().add("cyber-version-label");
|
||||
|
||||
footerBox.getChildren().addAll(brandFooter, lblVersion);
|
||||
sideColumn.getChildren().add(footerBox);
|
||||
@@ -174,13 +183,13 @@ public final class MainAppView {
|
||||
brandRow.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
Label lblAssinador = new Label("ASSINADOR");
|
||||
lblAssinador.getStyleClass().addAll("cyber-brand-title", "serpro-header-title", "cyber-brand-prefix");
|
||||
lblAssinador.getStyleClass().addAll("cyber-brand-title", "cyber-brand-prefix");
|
||||
|
||||
Label lblSep = new Label("|");
|
||||
lblSep.getStyleClass().add("cyber-brand-separator");
|
||||
|
||||
Label lblBrand = new Label("CyberCore");
|
||||
lblBrand.getStyleClass().addAll("cyber-brand-title", "serpro-header-brand", "text-bold");
|
||||
lblBrand.getStyleClass().addAll("cyber-brand-title", "text-bold");
|
||||
|
||||
brandRow.getChildren().addAll(lblAssinador, lblSep, lblBrand);
|
||||
|
||||
@@ -215,7 +224,7 @@ public final class MainAppView {
|
||||
HBox content = new HBox(8);
|
||||
content.setAlignment(Pos.CENTER);
|
||||
|
||||
Node icon = dark ? SvgIcons.sunIcon(15) : SvgIcons.moonIcon(15);
|
||||
Node icon = dark ? Icons.sun(16) : Icons.moon(16);
|
||||
StackPane iconBox = new StackPane(icon);
|
||||
iconBox.setPrefSize(18, 18);
|
||||
iconBox.setMinSize(18, 18);
|
||||
@@ -231,17 +240,16 @@ public final class MainAppView {
|
||||
|
||||
private Button createActionButton(Node icon, String text, Runnable onAction) {
|
||||
Button btn = new Button();
|
||||
btn.getStyleClass().addAll("cyber-action-card", "serpro-action-btn");
|
||||
btn.setPrefWidth(162);
|
||||
btn.setMinWidth(158);
|
||||
btn.setPrefHeight(68);
|
||||
btn.getStyleClass().add("cyber-action-card");
|
||||
btn.setMaxWidth(Double.MAX_VALUE);
|
||||
btn.setPrefHeight(72);
|
||||
btn.setMinHeight(68);
|
||||
|
||||
HBox content = new HBox(12);
|
||||
content.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
Label lbl = new Label(text);
|
||||
lbl.getStyleClass().addAll("cyber-action-text", "serpro-action-text");
|
||||
lbl.getStyleClass().add("cyber-action-text");
|
||||
lbl.setWrapText(true);
|
||||
lbl.setAlignment(Pos.CENTER_LEFT);
|
||||
HBox.setHgrow(lbl, Priority.ALWAYS);
|
||||
@@ -266,7 +274,7 @@ public final class MainAppView {
|
||||
|
||||
private Button createSideButton(Node icon, String text, Runnable onAction) {
|
||||
Button btn = new Button();
|
||||
btn.getStyleClass().addAll("cyber-side-card", "serpro-side-btn");
|
||||
btn.getStyleClass().add("cyber-side-card");
|
||||
btn.setPrefHeight(42);
|
||||
btn.setMinHeight(42);
|
||||
btn.setMaxWidth(Double.MAX_VALUE);
|
||||
@@ -275,7 +283,7 @@ public final class MainAppView {
|
||||
content.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
Label lbl = new Label(text);
|
||||
lbl.getStyleClass().addAll("cyber-side-text", "serpro-side-text");
|
||||
lbl.getStyleClass().add("cyber-side-text");
|
||||
lbl.setWrapText(false);
|
||||
lbl.setAlignment(Pos.CENTER_LEFT);
|
||||
HBox.setHgrow(lbl, Priority.ALWAYS);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/* CyberCore Signer - Modo Diagnóstico: Remoção de sombras/efeitos visuais dinâmicos */
|
||||
|
||||
.cyber-action-card,
|
||||
.serpro-action-btn,
|
||||
.cyber-side-card,
|
||||
.serpro-side-btn,
|
||||
.cyber-header-bar,
|
||||
.theme-toggle-btn,
|
||||
.cyber-status-badge {
|
||||
@@ -11,11 +9,8 @@
|
||||
}
|
||||
|
||||
.theme-light .cyber-action-card:hover,
|
||||
.theme-light .serpro-action-btn:hover,
|
||||
.theme-dark .cyber-action-card:hover,
|
||||
.theme-dark .serpro-action-btn:hover,
|
||||
.cyber-side-card:hover,
|
||||
.serpro-side-btn:hover,
|
||||
.theme-toggle-btn:hover {
|
||||
-fx-effect: null !important;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@
|
||||
========================================================================== */
|
||||
|
||||
.cyber-root,
|
||||
.serpro-root,
|
||||
.dialog-container {
|
||||
-fx-background-color: -fx-color-background;
|
||||
-fx-text-fill: -fx-color-text;
|
||||
@@ -220,8 +219,7 @@
|
||||
3. HUB DE AÇÕES E PAINEL LATERAL
|
||||
========================================================================== */
|
||||
|
||||
.cyber-action-card,
|
||||
.serpro-action-btn {
|
||||
.cyber-action-card {
|
||||
-fx-background-color: -fx-color-surface;
|
||||
-fx-border-color: -fx-color-border;
|
||||
-fx-border-width: 1.2px;
|
||||
@@ -236,20 +234,17 @@
|
||||
-fx-effect: dropshadow(three-pass-box, -fx-color-shadow, 6, 0, 0, 2);
|
||||
}
|
||||
|
||||
.cyber-action-card:hover,
|
||||
.serpro-action-btn:hover {
|
||||
.cyber-action-card:hover {
|
||||
-fx-background-color: -fx-color-surface-hover;
|
||||
-fx-border-color: -fx-color-primary;
|
||||
-fx-effect: dropshadow(three-pass-box, -fx-color-shadow-hover, 10, 0, 0, 4);
|
||||
}
|
||||
|
||||
.cyber-action-card:pressed,
|
||||
.serpro-action-btn:pressed {
|
||||
.cyber-action-card:pressed {
|
||||
-fx-background-color: -fx-color-surface-active;
|
||||
}
|
||||
|
||||
.cyber-action-text,
|
||||
.serpro-action-text {
|
||||
.cyber-action-text {
|
||||
-fx-font-size: 13px;
|
||||
-fx-font-weight: bold;
|
||||
-fx-text-fill: -fx-color-text;
|
||||
@@ -266,8 +261,7 @@
|
||||
-fx-effect: dropshadow(three-pass-box, -fx-color-shadow, 4, 0, 0, 1);
|
||||
}
|
||||
|
||||
.cyber-side-card,
|
||||
.serpro-side-btn {
|
||||
.cyber-side-card {
|
||||
-fx-background-color: transparent;
|
||||
-fx-border-color: transparent;
|
||||
-fx-border-width: 1px;
|
||||
@@ -279,26 +273,22 @@
|
||||
-fx-max-width: Infinity;
|
||||
}
|
||||
|
||||
.cyber-side-card:hover,
|
||||
.serpro-side-btn:hover {
|
||||
.cyber-side-card:hover {
|
||||
-fx-background-color: -fx-color-surface-hover;
|
||||
-fx-border-color: -fx-color-border-subtle;
|
||||
}
|
||||
|
||||
.cyber-side-card:pressed,
|
||||
.serpro-side-btn:pressed {
|
||||
.cyber-side-card:pressed {
|
||||
-fx-background-color: -fx-color-surface-active;
|
||||
}
|
||||
|
||||
.cyber-side-text,
|
||||
.serpro-side-text {
|
||||
.cyber-side-text {
|
||||
-fx-font-size: 13px;
|
||||
-fx-text-fill: -fx-color-text;
|
||||
-fx-font-weight: 500;
|
||||
}
|
||||
|
||||
.cyber-version-label,
|
||||
.serpro-version-label {
|
||||
.cyber-version-label {
|
||||
-fx-font-size: 11px;
|
||||
-fx-text-fill: -fx-color-text-muted;
|
||||
}
|
||||
@@ -567,7 +557,8 @@
|
||||
-fx-text-fill: -fx-color-text-muted;
|
||||
}
|
||||
|
||||
.cert-badge-a1 {
|
||||
.cert-badge-a1,
|
||||
.badge-a1 {
|
||||
-fx-background-color: -fx-color-primary-subtle;
|
||||
-fx-border-color: -fx-color-primary;
|
||||
-fx-border-radius: 4px;
|
||||
@@ -578,7 +569,8 @@
|
||||
-fx-padding: 2px 8px;
|
||||
}
|
||||
|
||||
.cert-badge-a3 {
|
||||
.cert-badge-a3,
|
||||
.badge-a3 {
|
||||
-fx-background-color: -fx-color-warning-subtle;
|
||||
-fx-border-color: -fx-color-warning-border;
|
||||
-fx-border-radius: 4px;
|
||||
@@ -595,7 +587,8 @@
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.cert-status-unavailable {
|
||||
.cert-status-unavailable,
|
||||
.cert-status-expired {
|
||||
-fx-text-fill: -fx-color-error;
|
||||
-fx-font-size: 11px;
|
||||
-fx-font-weight: bold;
|
||||
|
||||
Reference in New Issue
Block a user