Software empresarial · Novo recurso

Sistema de design Red Hat PatternFly.

Use PatternFly para criar um espaço de trabalho operacional: referências semânticas de tokens, cartões de serviço selecionáveis, seleção em massa com três estados, revisão do escopo e código nativo completo de React.

Guia OpenDesign8 capítulos38 entradas de referênciaGuia de aplicação original
01

Prévia da interface do sistema de design Red Hat PatternFly

Pesquise na galeria de serviços, selecione serviços individualmente ou todos os visíveis, confira o total de réplicas, revise a seleção e confirme um plano local.

Selecione serviços e revise o escopo da manutençãoAbrir exemplo completo
PatternFly nativo React 6.6.1 com Gallery/Card e estado de seleção em massa originais. Apenas dados operacionais de exemplo. · Referência de implementação
02

Referência de design do sistema de design Red Hat PatternFly

PatternFly React 6.6.1 e @patternfly/react-tokens 6.6.1. Abaixo são exibidas as resoluções selecionadas dos tokens publicados do tema claro. Os componentes nativos e pf-v6-theme-dark resolvem os estilos escuros; os dados de exemplo dos serviços e o layout são escolhas da aplicação.

Papéis semânticos de superfície e texto

Fonte
Nome / RegraValor / ConfiguraçãoUso
--pf-t--global--background--color--primary--defaultrgb(255, 255, 255, 0.6000)Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--background--color--secondary--defaultrgb(199, 199, 199, 0.3000)Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--text--color--regular#151515 Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--text--color--subtle#383838 Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--text--color--disabled#a3a3a3 Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--color--brand--default#004d99 Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--color--brand--hover#003366 Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--color--brand--accent--default#ee0000 Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.
--pf-t--global--color--brand--subtle--default#e0f0ff Use o papel semântico do tema ativo; o vermelho de destaque da marca não é a cor universal das ações primárias.

Papéis de status

Fonte
Nome / RegraValor / ConfiguraçãoUso
--pf-t--global--color--status--success--default#204d00 Combine a intenção do status com um rótulo textual. Estes valores do tema claro não substituem as variantes nativas de Label ou Alert.
--pf-t--global--color--status--warning--default#73480b Combine a intenção do status com um rótulo textual. Estes valores do tema claro não substituem as variantes nativas de Label ou Alert.
--pf-t--global--color--status--danger--default#731f00 Combine a intenção do status com um rótulo textual. Estes valores do tema claro não substituem as variantes nativas de Label ou Alert.
--pf-t--global--color--status--info--default#3d2785 Combine a intenção do status com um rótulo textual. Estes valores do tema claro não substituem as variantes nativas de Label ou Alert.
--pf-t--global--color--status--custom--default#004d4d Combine a intenção do status com um rótulo textual. Estes valores do tema claro não substituem as variantes nativas de Label ou Alert.
--pf-t--global--color--status--unread--default#0066cc Combine a intenção do status com um rótulo textual. Estes valores do tema claro não substituem as variantes nativas de Label ou Alert.

Tipografia de corpo e títulos

Fonte
Nome / RegraValor / ConfiguraçãoUso
--pf-t--global--font--size--body--default0.875remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--body--lg1remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--heading--h11.5remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--heading--h21.25remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--heading--h31.125remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--heading--h41remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--heading--h51remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.
--pf-t--global--font--size--heading--h61remUse deliberadamente o papel tipográfico e o nível semântico do título. O tamanho visual não determina a estrutura do documento.

Escala de espaçamento

Fonte
Nome / RegraValor / ConfiguraçãoUso
--pf-t--global--spacer--xs0.25remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--sm0.5remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--md1remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--lg1.5remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--xl2remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--2xl3remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--3xl4remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.
--pf-t--global--spacer--4xl5remUse a escala de espaçamento nomeada para grupos e controles; os valores em rem acompanham o tamanho da fonte raiz definido pelo usuário.

Forma e foco

Fonte
Nome / RegraValor / ConfiguraçãoUso
--pf-t--global--border--radius--tiny4pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
--pf-t--global--border--radius--small6pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
--pf-t--global--border--radius--medium16pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
--pf-t--global--border--radius--large24pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
--pf-t--global--border--radius--pill999pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
--pf-t--global--border--radius--control--form-element6pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
--pf-t--global--border--radius--action--default999pxUse a forma apropriada ao componente, em vez de aplicar o raio de pílula a todas as superfícies.
03

Guia completo do sistema de design Red Hat PatternFly

Um guia prático para escolher, aplicar e avaliar este sistema em uma interface real.

DESIGN-red-hat-patternfly.md

Orientações completas, um ponto de partida para a implementação e links para o código-fonte.

Baixar o guia

Layout operacional do sistema de design Red Hat PatternFly

Uma coleção com contexto operacional persistente

A galeria de serviços permite que um operador compare integridade, localização e utilização, enquanto um painel de escopo separado registra o conjunto escolhido. A seleção não é igual aos resultados da pesquisa atual. Um serviço que deixa de aparecer por causa de um filtro continua selecionado até ser removido deliberadamente. Essa distinção é essencial para uma operação em massa com consequências que vão além do que está visível na tela.

Com base neste guia de OpenDesign

Use a hierarquia nativa de componentes

Gallery organiza as colunas responsivas dos cartões, Card separa cada serviço, Label identifica o status e Progress exibe uma porcentagem de exemplo com seu título. A página não imita um console de infraestrutura com retângulos coloridos aleatórios. O modelo de dados, os controles e o estado de revisão estão implementados no exemplo completo de React.

Papéis semânticos de cor e tema do sistema de design Red Hat PatternFly

A marca principal e o destaque vermelho são distintos

PatternFly v6 exporta papéis separados para marca, destaque, texto, plano de fundo e status. O snapshot selecionado do tema claro inclui blue brand-default e red brand-accent-default. Tratar toda ação em destaque como vermelho da Red Hat eliminaria essas distinções. Os componentes nativos Button e Label usam os papéis do sistema apropriados para cada variante.

Aplique o tema escuro ao documento

O exemplo alterna pf-v6-theme-dark no elemento do documento. As superfícies e o texto da aplicação usam propriedades semânticas --pf-t--global, permitindo que o tema também resolva suas cores. Não fixe valores do tema claro em cartões personalizados esperando que uma classe de tema no documento os atualize.

Tipografia e metadados dos serviços no sistema de design Red Hat PatternFly

Separe o tamanho visual da semântica dos títulos

headingLevel h1 de Title define o título da página, enquanto seu tamanho controla o destaque visual. Body-default é 0.875rem neste snapshot do pacote. Os rótulos dos cartões, os status e os valores numéricos de utilização continuam legíveis sem transformar cada valor em um título. A lista de definições dos metadados mantém explícitos os totais de réplicas e os IDs dos serviços.

Evite rótulos operacionais ambíguos

A utilização de exemplo é identificada como dado de exemplo tanto no componente quanto no rodapé. Uma barra de progresso sem contexto pode ser confundida com uma tarefa de implantação ou uma operação de carregamento. A legenda explica o que a porcentagem representa, enquanto o rótulo Label informa separadamente se a capacidade está saudável ou precisa de revisão.

Seleção em massa e galeria do sistema de design Red Hat PatternFly

Use os três estados da caixa de seleção

O controle Select visible é true quando todos os serviços visíveis estão selecionados, false quando nenhum está selecionado e null quando apenas alguns estão selecionados. PatternFly Checkbox oferece suporte ao valor indeterminado null. A aplicação calcula esse estado a partir da coleção filtrada; não usa um booleano separado que possa divergir das seleções das linhas.

  1. Selecione um serviço e confira o estado de seleção parcial.
  2. Selecione todos os serviços visíveis no momento.
  3. Pesquise um nome e confirme que as seleções ocultas continuam no escopo.
  4. Revise o conjunto exato e o total de réplicas.
  5. Confirme o plano local e confira o resultado.

Use o conjunto selecionado como fonte da verdade

Espaçamento e cartões responsivos do sistema de design Red Hat PatternFly

Use tokens semânticos para a estrutura da página

O plano de fundo, o texto regular e os metadados sutis do exemplo usam propriedades semânticas de CSS do pacote de tokens publicado. A escala de espaçamento nativa vai de xs a 4xl, enquanto a aplicação usa 24px entre a coleção e o painel de escopo. Esse valor explícito de composição é independente da referência do token.

Permita que a galeria reorganize o layout antes de reduzir o conteúdo

A Gallery recebe uma largura mínima de item de 230px e um espaçamento entre itens. No breakpoint de 850px da aplicação, o painel de escopo passa para baixo da coleção. Em 500px, o preenchimento da página passa a 16px e a pesquisa ocupa toda a largura da barra de ferramentas. Essas são decisões de layout deste exemplo, não uma afirmação de que todos os produtos PatternFly usam esses breakpoints.

Red Hat PatternFly Revisão e estados de seleção do sistema de design

Não faça a seleção executar a operação

Marcar um serviço apenas o adiciona ao escopo. A opção Revisar seleção exibe um Alert informativo e uma ação de confirmação. Confirmar plano local informa os totais de serviços e réplicas selecionados, sem iniciar uma tarefa de manutenção. Alterar a seleção fecha o estado de revisão para impedir a confirmação silenciosa de um conjunto desatualizado.

Mantenha a recuperação da pesquisa separada da seleção

Uma consulta sem correspondências exibe um Alert informativo em linha com a opção Limpar pesquisa. Isso limpa apenas a consulta e mantém os serviços selecionados. Assim, a contagem de itens selecionados na barra de ferramentas e o painel de escopo continuam apresentando informações coerentes. Redefinir a seleção como efeito colateral de uma pesquisa vazia seria um comportamento destrutivo oculto.

Red Hat PatternFly Controles acessíveis e status do sistema de design

Identifique a seleção e use controles nativos

Cada Checkbox tem um id estável e um rótulo de serviço visível. SearchInput tem um nome acessível, Switch identifica a configuração de aparência e Revisar seleção fica desabilitado enquanto o conjunto estiver vazio. Progress nativo comunica seu valor e título. A página não depende de uma ação disponível apenas ao passar o cursor e oculta dentro de um cartão.

Mantenha os estados visíveis em palavras

A contagem da seleção usa uma região dinâmica com anúncios educados, o status do serviço aparece por escrito em um Label e o Alert final descreve o que aconteceu. Não use a cor como único indicador do escopo selecionado ou da integridade. Os testes com teclado devem abranger a seleção parcial, a filtragem que oculta um serviço selecionado e o retorno à coleção completa.

  • Uma caixa de seleção marcada indica inclusão, não um status de sucesso.
  • Um Label de status descreve o serviço, não se ele está selecionado.
  • Progress descreve a utilização de exemplo, não a conclusão de uma operação.

Red Hat PatternFly Integração do sistema de design React

Importe os estilos de redefinição e dos componentes uma única vez

O exemplo importa @patternfly/react-core/dist/styles/base.css no ponto de entrada. Os componentes nativos React fornecem seus estilos por meio do pacote. O CSS da aplicação está limitado a pf-example e faz referência ao namespace atual --pf-t--global; ele não sobrescreve os elementos internos dos componentes.

Adicione o agendamento real somente por trás de um contrato de serviço

Red Hat PatternFly Exemplos de componentes do sistema de design

main.jsx — galeria de serviços e revisão em lote

Composição completa com Gallery/Card/Checkbox/Progress nativos, escopo de seleção derivado e confirmação local.

jsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import {
  Alert,
  Button,
  Card,
  CardBody,
  CardTitle,
  Checkbox,
  Gallery,
  GalleryItem,
  Label,
  Progress,
  SearchInput,
  Switch,
  Title,
} from "@patternfly/react-core";
import "@patternfly/react-core/dist/styles/base.css";
import "./patternfly.css";
const services = [
  {
    id: "api",
    name: "Public API",
    region: "eu-west",
    replicas: 6,
    load: 62,
    status: "Healthy",
  },
  {
    id: "jobs",
    name: "Background jobs",
    region: "eu-west",
    replicas: 3,
    load: 81,
    status: "Review capacity",
  },
  {
    id: "search",
    name: "Search index",
    region: "us-east",
    replicas: 4,
    load: 44,
    status: "Healthy",
  },
  {
    id: "events",
    name: "Event stream",
    region: "us-east",
    replicas: 8,
    load: 72,
    status: "Healthy",
  },
];
function App() {
  const [query, setQuery] = useState(""),
    [selected, setSelected] = useState([]),
    [review, setReview] = useState(false),
    [notice, setNotice] = useState(""),
    [dark, setDark] = useState(false);
  const visible = services.filter((x) =>
    x.name.toLowerCase().includes(query.toLowerCase()),
  );
  const picked = services.filter((x) => selected.includes(x.id));
  const allVisible =
    visible.length > 0 && visible.every((x) => selected.includes(x.id));
  const someVisible = visible.some((x) => selected.includes(x.id));
  function choose(id, checked) {
    setSelected((v) =>
      checked ? [...new Set([...v, id])] : v.filter((x) => x !== id),
    );
    setReview(false);
  }
  function selectVisible(checked) {
    setSelected((v) =>
      checked
        ? [...new Set([...v, ...visible.map((x) => x.id)])]
        : v.filter((id) => !visible.some((x) => x.id === id)),
    );
    setReview(false);
  }
  return (
    <main className="pf-example">
      <header>
        <div>
          <span className="overline">PATTERNFLY · SERVICE OPERATIONS</span>
          <Title headingLevel="h1" size="2xl">
            Plan a maintenance review
          </Title>
          <p>
            Select services and inspect the combined scope before creating a
            local plan.
          </p>
        </div>
        <Switch
          id="dark-theme"
          label="Dark theme"
          isChecked={dark}
          onChange={(_, checked) => {
            setDark(checked);
            document.documentElement.classList.toggle(
              "pf-v6-theme-dark",
              checked,
            );
          }}
        />
      </header>
      <div className="service-toolbar">
        <SearchInput
          aria-label="Find a service"
          placeholder="Find a service"
          value={query}
          onChange={(_, value) => setQuery(value)}
          onClear={() => setQuery("")}
        />
        <Checkbox
          id="select-visible"
          label="Select visible"
          isChecked={allVisible ? true : someVisible ? null : false}
          isDisabled={!visible.length}
          onChange={(_, checked) => selectVisible(checked)}
        />
        <span aria-live="polite">{selected.length} selected</span>
        <Button isDisabled={!selected.length} onClick={() => setReview(true)}>
          Review selection
        </Button>
      </div>
      <div className="service-layout">
        <Gallery hasGutter minWidths={{ default: "230px" }}>
          {visible.map((s) => (
            <GalleryItem key={s.id}>
              <Card>
                <CardTitle>
                  <Checkbox
                    id={"select-" + s.id}
                    label={s.name}
                    isChecked={selected.includes(s.id)}
                    onChange={(_, checked) => choose(s.id, checked)}
                  />
                </CardTitle>
                <CardBody>
                  <div className="service-meta">
                    <Label color={s.status === "Healthy" ? "green" : "orange"}>
                      {s.status}
                    </Label>
                    <span>{s.region}</span>
                  </div>
                  <Progress
                    value={s.load}
                    title="Sample utilization"
                    measureLocation="outside"
                  />
                  <dl>
                    <dt>Replicas</dt>
                    <dd>{s.replicas}</dd>
                    <dt>Service ID</dt>
                    <dd>
                      <code>{s.id}</code>
                    </dd>
                  </dl>
                </CardBody>
              </Card>
            </GalleryItem>
          ))}
        </Gallery>
        <aside>
          <Card>
            <CardTitle>Maintenance scope</CardTitle>
            <CardBody>
              <p>
                {picked.length} services ·{" "}
                {picked.reduce((n, s) => n + s.replicas, 0)} replicas
              </p>
              {picked.length ? (
                <ul>
                  {picked.map((s) => (
                    <li key={s.id}>
                      {s.name}
                      <span>{s.region}</span>
                    </li>
                  ))}
                </ul>
              ) : (
                <p className="muted">Select a service to inspect its scope.</p>
              )}
              {review && (
                <div className="review">
                  <Alert
                    isInline
                    variant="info"
                    title="Review the selected services"
                  >
                    This is a fictional plan. No workload will be restarted.
                  </Alert>
                  <Button
                    onClick={() => {
                      setNotice(
                        `Local plan includes ${picked.length} services and ${picked.reduce((n, s) => n + s.replicas, 0)} replicas. No operation was scheduled.`,
                      );
                      setReview(false);
                    }}
                  >
                    Confirm local plan
                  </Button>
                </div>
              )}
            </CardBody>
          </Card>
        </aside>
      </div>
      {!visible.length && (
        <Alert isInline variant="info" title="No services match">
          <Button variant="link" onClick={() => setQuery("")}>
            Clear search
          </Button>
        </Alert>
      )}
      {notice && (
        <Alert isInline variant="success" title="Local plan recorded">
          {notice}
        </Alert>
      )}
      <footer>
        Native PatternFly 6.6.1 · service data and capacity figures are
        fictional, memory-only examples.
      </footer>
    </main>
  );
}
createRoot(document.getElementById("root")).render(<App />);

Referência de código

  • Salve como src/main.jsx. Checkbox onChange recebe o evento e o valor marcado; isChecked pode ser null quando o conjunto está parcialmente selecionado.

patternfly.css — estrutura responsiva para operações

O layout personalizado da página usa tokens semânticos da v6 e mantém intactos os estilos nativos dos componentes.

css
body {
  margin: 0;
}
.pf-example {
  padding: 24px;
  background: var(--pf-t--global--background--color--secondary--default);
  color: var(--pf-t--global--text--color--regular);
  font-family: var(--pf-t--global--font--family--body);
}
.pf-example header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  margin-bottom: 24px;
}
.overline {
  font-size: 11px;
  letter-spacing: 0.07em;
  color: var(--pf-t--global--text--color--subtle);
}
.pf-example header h1 {
  margin: 8px 0;
}
.service-toolbar {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}
.service-toolbar > .pf-v6-c-search-input {
  width: 280px;
}
.service-toolbar > span {
  margin-left: auto;
}
.service-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px;
  gap: 24px;
  align-items: start;
}
.service-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  margin-bottom: 24px;
}
.service-layout dl {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 24px;
  font-size: 12px;
}
.service-layout dd {
  margin: 0;
}
.service-layout ul {
  padding: 0;
  list-style: none;
  margin: 16px 0;
}
.service-layout li {
  padding: 12px 0;
  border-bottom: 1px solid var(--pf-t--global--border--color--default);
}
.service-layout li span {
  display: block;
  font-size: 12px;
  color: var(--pf-t--global--text--color--subtle);
}
.muted {
  color: var(--pf-t--global--text--color--subtle);
  margin-top: 16px;
}
.review > .pf-v6-c-button {
  margin-top: 16px;
}
.pf-example > .pf-v6-c-alert {
  margin-top: 24px;
}
.pf-example footer {
  font-size: 12px;
  color: var(--pf-t--global--text--color--subtle);
  margin-top: 24px;
}
@media (max-width: 850px) {
  .service-layout {
    grid-template-columns: 1fr;
  }
  .pf-example header {
    align-items: start;
  }
  .service-toolbar > span {
    margin-left: 0;
  }
}
@media (max-width: 500px) {
  .pf-example {
    padding: 16px;
  }
  .pf-example header {
    flex-direction: column;
  }
  .service-toolbar {
    gap: 16px;
  }
  .service-toolbar > .pf-v6-c-search-input {
    width: 100%;
  }
}

Referência de código

  • Salve como src/patternfly.css. Os breakpoints da aplicação são explicitamente parte deste exemplo.
04

Red Hat PatternFly Configuração do agente para o sistema de design

Ponto de partida para implementação

Composição nativa de React 18.3.1 / PatternFly 6.6.1. O Vite requer uma versão compatível do Node.js. Os dados e as operações reais do serviço API continuam sendo responsabilidade da aplicação.

sh
npm create vite@latest patternfly-services -- --template react
cd patternfly-services
npm install
npm install [email protected] [email protected] @patternfly/[email protected]
# Replace src/main.jsx and add src/patternfly.css using the complete examples.
npm run dev

Um prompt para seu projeto

Prompt para agente de IA
Crie uma coleção de operações usando Gallery, Card, Checkbox, Progress, Label e Alert nativos do PatternFly 6.6.1. Use os tokens semânticos fornecidos e o exemplo completo. Mantenha a visibilidade filtrada separada dos IDs selecionados, calcule a seleção em lote parcial e exija a revisão do conjunto exato de itens afetados. Use respostas transparentes de processamento, falha ou sucesso quando um API real for adicionado. Preserve o reajuste do layout em dispositivos móveis e a navegação por teclado.
05

Red Hat PatternFly Fontes e escopo do sistema de design

Um guia de aplicação criado por OpenDesign e um exemplo fictício de planejamento de manutenção, usando PatternFly React 6.6.1 nativo. Os dados de utilização, região e número de réplicas são exemplos. A confirmação atualiza apenas o estado local; nenhum serviço é reiniciado ou agendado.