rustploy-gui 0.1.2

Rustploy — desktop client (glacier-ui) for the Rustploy PaaS daemon
// Detalhe de um serviço: cabeçalho com ações (deploy, stop, reload) e as abas
// General (fonte), Connection, Domains, Environment, Deployments, Logs e
// Advanced.
component {
  resources {
    link(rel = import, href = "service/logs.gvb", as = ServiceLogsTab)
    link(rel = import, href = "service/general.gvb", as = ServiceGeneralTab)
    link(rel = import, href = "service/connection.gvb", as = ServiceConnectionTab)
    link(rel = import, href = "service/environment.gvb", as = ServiceEnvironmentTab)
    link(rel = import, href = "service/domains.gvb", as = ServiceDomainsTab)
    link(rel = import, href = "service/migrar.gvb", as = ServiceMigrarTab)
    link(rel = import, href = "service/databases.gvb", as = ServiceDatabasesTab)
    link(rel = import, href = "service/deployments.gvb", as = ServiceDeploymentsTab)
    link(rel = import, href = "service/healthcheck.gvb", as = ServiceHealthcheckTab)
    link(rel = import, href = "service/advanced.gvb", as = ServiceAdvancedTab)

    style """
      /* Cabeçalho + ações */
      .svc_head      { width: fill; align-y: start; }
      .svc_title_row { width: fill; spacing: 14; align-y: center; }
      .svc_title     { width: fill; }
      /* Sub-linha de status (badge + timer) logo abaixo do nome. */
      .svc_substatus { spacing: 10; align-y: center; }
      .tabs_scroll   { width: fill; }
      .tabs_main     { width: shrink; spacing: 4; }
      .svc_actions   { spacing: 10; align-y: center; }
      .btn_blue      { color: var(--blue); padding: 11 22; border-radius: 5 }
      /* Corpo: conteúdo da aba + painel lateral */
      .svc_body      { width: fill; height: fill; spacing: 20; }
      .svc_main      { width: fill; height: fill; spacing: 16; }
      .svc_aside     { width: 360; height: fill; spacing: 16; }
      .svc_err       { size: 13; color: var(--error); }
      /* Connection (pares chave/valor) */
      .kv_key        { width: fill; size: 13; color: var(--muted); }
      .kv_val        { size: 16; bold: true; color: var(--text); }
      .select        { width: fill; padding: 12 14; background: var(--raised); border-radius: 4; border-width: 1; border-color: #30363D; color: var(--text-2); }
      /* Deployments (lista + build log) */
      .col_dep_id    { width: 130; }
      .col_dep_start { width: fill; }
      .dep_image     { size: 11; color: var(--faint); padding: 2 0 0 0; }
      .dep_wrap      { width: fill; height: fill; spacing: 8; }
      .dep_list_scroll { width: fill; height: 240; }
      .dep_actions   { spacing: 8; align-y: center; }
      .dep_logs_btn  { color: var(--border); padding: 5 12; border-radius: 3 }
      .dep_del_btn   { color: var(--danger); padding: 5 12; border-radius: 3 }
      .label_cap_fill { width: fill; size: 11; bold: true; color: var(--faint); }
      /* Logs (aba Logs = launcher da janela isolada; painel usado só p/ layout) */
      .log_panel     { width: fill; height: fill; background: var(--surface); border-radius: 6; border-width: 1; border-color: var(--border); padding: 14 16; spacing: 8; }
      .log_body      { width: fill; spacing: 2; }
      .log_line      { width: fill; spacing: 12; }
      .log_time      { width: 76; size: 11; color: var(--faint); }
      .log_text      { width: fill; size: 12; color: #9DA7B3; }
      /* Painel lateral */
      .aside_panel   { width: fill; background: var(--surface); border-radius: 6; border-width: 1; border-color: var(--border); padding: 18; spacing: 8; }
      .aside_panel_fill { width: fill; height: fill; background: var(--surface); border-radius: 6; border-width: 1; border-color: var(--border); padding: 14 16; spacing: 8; }
      /* Responsivo: estreita o painel lateral e aperta o corpo (glacier-ui 0.9.0+). */
      @media (max-width: 900) {
        .svc_aside { width: 240; }
        .svc_body  { spacing: 12; }
      }
      @media (max-width: 560) {
        .svc_aside { width: 170; }
      }
    """
  }

  column(class = content) {
    // ── Header: nome + estado + ações ──────────────────────────────────
    row(class = svc_head) {
      column(class = header_titles) {
        row(class = svc_title_row) {
          button(
            class = btn_ghost,
            on_click = open_project:@svc_project_id,
            text = "‹ @svc_project",
          )

          text(class = "title svc_title", content = "@svc_name")
        }

        row(class = svc_substatus) {
          rp-badge(color = @svc_status_color, label = @svc_status_label)

          row(class = badge, if = @svc_deploy_running, equals = true) {
            text(class = state_dot, color = #58A6FF, content = "⏱")

            text(
              class = badge_lbl,
              color = #58A6FF,
              content = "@svc_deploy_elapsed",
            )
          }
        }

        text(
          if = @svc_action_msg,
          not_equals = "",
          class = muted,
          color = @svc_action_color,
          content = "@svc_action_msg",
        )

        row(class = "svc_actions svc_actions_compact") {
          button(
            class = btn_primary,
            on_click = svc_deploy,
            text = "▶",
            tooltip = Deploy,
          )

          button(
            class = btn_blue,
            on_click = svc_reload,
            text = "⟳",
            tooltip = Reload,
          )

          button(
            class = btn_blue,
            on_click = svc_rebuild,
            text = "⚙",
            tooltip = Rebuild,
          )

          button(
            class = btn_danger,
            on_click = svc_stop,
            text = "■",
            tooltip = Stop,
          )
        }
      }

      row(class = "svc_actions svc_actions_full") {
        button(class = btn_primary, on_click = svc_deploy, text = Deploy)
        button(class = btn_blue, on_click = svc_reload, text = Reload)
        button(class = btn_blue, on_click = svc_rebuild, text = Rebuild)
        button(class = btn_danger, on_click = svc_stop, text = Stop)
      }
    }

    // ── Abas ───────────────────────────────────────────────────────────
    scroll(class = tabs_scroll, direction = horizontal) {
      row(class = tabs_main) {
        TabButton(
          label = General,
          current = @tab,
          target = general,
          action = tab:general,
        )

        TabButton(
          label = Connection,
          current = @tab,
          target = connection,
          action = tab:connection,
        )

        TabButton(
          label = Environment,
          current = @tab,
          target = environment,
          action = tab:environment,
        )

        TabButton(
          label = Domains,
          current = @tab,
          target = domains,
          action = tab:domains,
        )

        TabButton(
          label = Deployments,
          current = @tab,
          target = deployments,
          action = tab:deployments,
        )

        if @svc_shared == "true" {
          TabButton(
            label = Databases,
            current = @tab,
            target = databases,
            action = tab:databases,
          )
        }

        if @svc_can_migrate == "true" {
          TabButton(
            label = Migrar,
            current = @tab,
            target = migrar,
            action = tab:migrar,
          )
        }

        TabButton(
          label = Healthcheck,
          current = @tab,
          target = healthcheck,
          action = tab:healthcheck,
        )

        TabButton(
          label = Logs,
          current = @tab,
          target = logs,
          action = tab:logs,
        )

        TabButton(
          label = Advanced,
          current = @tab,
          target = advanced,
          action = tab:advanced,
        )
      }
    }

    hr

    // ── Corpo: conteúdo da aba + painel lateral ────────────────────────
    row(class = svc_body) {
      column(class = svc_main) {
        text(
          if = @svc_error,
          not_equals = "",
          class = svc_err,
          content = "@svc_error",
        )
        ServiceGeneralTab(if = @tab, equals = general)
        ServiceConnectionTab(if = @tab, equals = connection)
        ServiceEnvironmentTab(if = @tab, equals = environment)
        ServiceDomainsTab(if = @tab, equals = domains)
        ServiceMigrarTab(if = @tab, equals = migrar)
        ServiceDatabasesTab(if = @tab, equals = databases)
        ServiceDeploymentsTab(if = @tab, equals = deployments)
        ServiceHealthcheckTab(if = @tab, equals = healthcheck)
        ServiceLogsTab(if = @tab, equals = logs)
        ServiceAdvancedTab(if = @tab, equals = advanced)
      }

      column(class = svc_aside) {
        column(class = aside_panel) {
          text(class = label_cap, content = "STATUS")
          rp-badge(color = @svc_status_color, label = @svc_status_label)
          text(class = label_cap, content = "UPTIME")
          text(class = kv_val, content = "@daemon_uptime")
          text(class = label_cap, content = "SERVICES")
          text(class = kv_val, content = "@services_label")
        }

        column(class = aside_panel_fill) {
          text(class = label_cap, content = "LOGS")

          text(
            class = muted,
            content = "Runtime e build logs abrem em janelas próprias (isoladas).",
          )

          row(class = env_add) {
            button(
              class = tab,
              on_click = open_logs_window,
              text = "Logs de runtime",
            )
          }
        }
      }
    }
  }
}