NocoBase 0.20: Suporte para Múltiplas Fontes de Dados

NocoBase 0.20 introduz suporte para múltiplas fontes de dados, ajustes no gerenciamento de coleções, chaves primárias não-ID, interfaces de usuário e permissões aprimoradas, e novos nós de fluxo de trabalho para maior flexibilidade e desempenho.

NocoBase team |

Novos Recursos

Suporte a Múltiplas Fontes de Dados

Adicionado o plugin ”Gerenciador de Fontes de Dados”, usado para gerenciar todas as coleções e campos das fontes de dados. O plugin Gerenciador de Fontes de Dados fornece uma interface centralizada para gerenciar fontes de dados e não oferece a capacidade de acessar as fontes de dados. Ele precisa ser usado em conjunto com vários plugins de fonte de dados. As fontes de dados atualmente suportadas incluem:

Além disso, mais fontes de dados podem ser estendidas, podendo ser tipos comuns de bancos de dados ou plataformas que fornecem APIs (SDKs).

Gerenciador de Fontes de Dados

Ajuste no Gerenciamento de Coleções

Moveu o original “Gerenciador de Coleções” para “Fonte de Dados > Banco de Dados Principal > Configuração”.

Configuração do Banco de Dados Principal

Suporte para Campos Não-ID como Chave Primária e Restrições de Relacionamento

Ao criar uma coleção, você pode optar por não criar um campo ID.

Campos Predefinidos

Campos inteiros podem ser usados como chaves primárias.

Campos inteiros podem ser usados como chaves primárias

Campos de texto de linha única também podem ser usados como chaves primárias.

Campos de texto de linha única também podem ser usados como chaves primárias

As restrições de relacionamento suportam a seleção de outros campos com índice Único definido como campos não-chave primária.

Ajuste na Ordenação por Arrastar e Soltar

Adicionado um campo do tipo “Ordenação”. Os campos de ordenação não são mais gerados automaticamente ao criar coleções e precisam ser criados manualmente.

Ao selecionar um campo como grupo, o agrupamento será feito antes da ordenação.

Ao ativar a ordenação por arrastar e soltar no bloco de tabela, você precisa selecionar o campo de ordenação.

Ao criar um bloco Kanban, você precisa selecionar o campo de ordenação.

Ajuste nas Interfaces de Usuário e Permissão

Adicionada interface de gerenciamento de usuários e unificado o gerenciamento de usuários e funções sob um único menu.

Ajustada a interface de gerenciamento de funções para facilitar o gerenciamento de funções associadas a usuários, permissões, departamentos, etc.

Movido o original “Permissões de Ação” para a aba “Fonte de Dados”.

Plugin de Departamento

Organize usuários por departamentos, defina relações hierárquicas, vincule funções para controlar permissões e use departamentos como variáveis em fluxos de trabalho e expressões.

Fluxo de Trabalho: Aprovação

O plugin de aprovação fornece tipos de fluxo de trabalho dedicados (gatilhos) “Iniciar Aprovação” e nós de “Aprovação” para este processo. Combinado com as tabelas de dados personalizadas e blocos personalizados exclusivos do NocoBase, vários cenários de aprovação podem ser rápida e flexivelmente criados e gerenciados.

Configuração de aprovação

Configuração de Aprovação

Processo de aprovação

Processo de Aprovação

Mais detalhes podem ser encontrados na documentação: Aprovação de Fluxo de Trabalho

Fluxo de Trabalho: Nó de Finalização de Processo

Este nó finaliza imediatamente a execução atual do fluxo de trabalho quando executado e termina com o status configurado no nó. É tipicamente usado para controle de fluxo lógico específico, para sair do fluxo de trabalho atual após atender certas condições lógicas, sem continuar com o processamento subsequente. Pode ser comparado ao comando return em linguagens de programação, usado para sair da função atualmente em execução.

Mais detalhes podem ser encontrados na documentação: Nó de Finalização de Processo

Fluxo de Trabalho: Nó de Variável Personalizada

Variáveis podem ser declaradas no fluxo de trabalho ou valores podem ser atribuídos a variáveis declaradas anteriormente, tipicamente usado para armazenar dados temporários no fluxo de trabalho. É adequado para cenários onde os resultados do cálculo precisam ser armazenados para uso posterior fora do branch (como loops, paralelismo, etc.).

Mais detalhes podem ser encontrados na documentação: Nó de Variável Personalizada

Fluxo de Trabalho: Interceptador de Requisição

O plugin interceptador de requisição fornece um mecanismo para interceptar operações em formulários, onde o evento de interceptação é acionado após a operação de formulário correspondente ser submetida e antes de ser processada. Se um nó “Finalizar Processo” for executado no fluxo de processo subsequente após o acionamento, ou se outros nós falharem na execução (erros ou outras execuções incompletas), a operação do formulário será interceptada; caso contrário, a operação agendada será executada normalmente. Pode ser usado para validação de negócios ou verificações lógicas para aprovar ou interceptar operações de criação, atualização e exclusão submetidas pelo cliente.

Mais detalhes podem ser encontrados na documentação: Interceptador de Requisição

Fluxo de Trabalho: Nó de Mensagem de Resposta

O nó de mensagem de resposta é usado para fornecer feedback ao cliente com mensagens personalizadas em tipos específicos de fluxos de trabalho (como interceptação de requisição e eventos de formulário).

Configuração do nó

Mensagem de aviso

Mais detalhes podem ser encontrados na documentação: Nó de Mensagem de Resposta

Mudanças Incompatíveis

APIs com Nomes Conflitantes

Nesta mudança de kernel, algumas APIs da nova versão entram em conflito com os nomes da versão antiga. Essas APIs conflitantes da versão antiga serão mantidas nesta versão, mas serão uniformemente sufixadas com _deprecated.

API OriginalAPI ObsoletaNova API
CollectionProviderCollectionProvider_deprecatedCollectionProvider
useCollectionuseCollection_deprecateduseCollection
useCollectionFielduseCollectionField_deprecateduseCollectionField
useCollectionManageruseCollectionManager_deprecateduseCollectionManager
useContext(CollectionManagerContext)useCollectionManager_deprecateduseCollectionManager

Se você está usando as APIs relacionadas acima, você tem duas maneiras de mudar:

  • Substituição simples: Substitua a API original pela que tem o sufixo _deprecated, por exemplo, substitua useCollection() por useRecord_deprecated().
  • Use a nova API de acordo com a nova documentação: Embora os nomes das novas APIs sejam os mesmos das APIs antigas, há diferenças nos parâmetros e valores de retorno. Você precisa consultar a nova documentação

para ajustar o código correspondente.

Outras APIs que Requerem Ajuste

  • registerTemplate() mudou para app.dataSourceManager.addCollectionTemplates()
  • registerField() mudou para app.dataSourceManager.addFieldInterfaces()
  • registerGroup() mudou para app.dataSourceManager.addFieldInterfaceGroups()
  • useContext(CollectionManagerContext) mudou para useCollectionManager_deprecated()
  • Estender coleções usando ExtendCollectionsProvider
  • RecordProvider requer a passagem explícita do parâmetro parent quando necessário

Exemplos de Mudança

Extensão de Template de Coleção

Definição

Anteriormente definido como um objeto, agora precisa ser alterado para uma classe. Por exemplo:

Antes:

import { ICollectionTemplate } from '@nocobase/client';

const calendar: ICollectionTemplate = {
  name: 'calendar',
  title: 'Calendar collection',
  order: 2,
  color: 'orange',
  // ...
}

Agora:

import { CollectionTemplate } from '@nocobase/client';

class CalendarCollectionTemplate extends CollectionTemplate {
  name = 'calendar';
  title = 'Calendar collection';
  order = 2;
  color = 'orange';
}

As propriedades do objeto original tornam-se membros da classe.

Registro

Anteriormente registrado através de registerTemplate, agora precisa ser registrado através do dataSourceManager.addCollectionTemplates do plugin. Por exemplo:

Antes:

import { registerTemplate } from '@nocobase/client';
import { calendar } from './calendar'

registerTemplate('calendar', calendar);

Agora:

import { Plugin } from '@nocobase/client';
import { CalendarCollectionTemplate } from './calendar'

export class CalendarPluginClient extends Plugin {
  async load() {
    this.app.dataSourceManager.addCollectionTemplates([CalendarCollectionTemplate]);
  }
}

Extensão de Interface de Campo

Definição

Anteriormente definido como um objeto, agora precisa ser alterado para uma classe. Por exemplo:

Antes:

import { IField } from '@nocobase/client';

const attachment: IField = {
  name: 'attachment',
  type: 'object',
  group: 'media',
  title: 'Attachment',
  // ...
}

Agora:

import { CollectionFieldInterface } from '@nocobase/client';

class AttachmentFieldInterface extends CollectionFieldInterface {
  name = 'attachment';
  type = 'object';
  group = 'media';
  title = 'Attachment';
  // ...
}

As propriedades do objeto original tornam-se membros da classe.

Registro

Anteriormente registrado através de registerField, agora precisa ser registrado através do dataSourceManager.addFieldInterfaces do plugin e não requer a passagem de CollectionManagerProvider novamente. Por exemplo:

Antes:

import { registerField } from '@nocobase/client';
import { attachment } from './attachment'

- registerField(attachment.group, 'attachment', attachment);

export const FileManagerProvider: FC = (props) => {
  return (
-   <CollectionManagerProvider interfaces={{ attachment }}>
      <SchemaComponentOptions scope={hooks} components={{ UploadActionInitializer }}>
        {props.children}
      </SchemaComponentOptions>
-   </CollectionManagerProvider>
  );
};

Agora:

import { Plugin } from '@nocobase/client';
import { AttachmentFieldInterface } from './attachment'

export class FilPlugin extends Plugin {
  async load() {
    this.app.dataSourceManager.addFieldInterfaces([AttachmentFieldInterface]);
  }
}

Extensão de Grupo de Interface de Campo

Anteriormente registrado através de registerGroup, agora precisa ser registrado através do dataSourceManager.addFieldInterfaceGroups do plugin. Por exemplo:

- import { registerGroup, Plugin } from '@nocobase/client';
+ import { Plugin } from '@nocobase/client';

- registerGroup('map', {
-        label: 'Map-based geometry',
-        order: 10
- })

export class MapPlugin extends Plugin {
  async load() {
+    this.app.dataSourceManager.addFieldInterfaceGroups({
+      map: {
+        label: generateNTemplate('Map-based geometry'),
+        order: 51,
+      },
+    });
  }
}

useContext(CollectionManagerContext) Mudou para useCollectionManager_deprecated()

- const ctx = useContext(CollectionManagerContext);
+ const ctx = useCollectionManager_deprecated();

Estender Coleções, Use ExtendCollectionsProvider em Vez de CollectionManagerProvider

const Demo = () => {
-  <CollectionManagerProvider collections={[apiKeysCollection]}>
+  <ExtendCollectionsProvider collections={[apiKeysCollection]}>
...
-  </CollectionManagerProvider>
+  </ExtendCollectionsProvider>
}

Mudanças no RecordProvider

Anteriormente, quando a propriedade parent não era passada, o valor do último RecordProvider era automaticamente recuperado como parent. Agora, o parent precisa ser passado explicitamente, e quando o parent não é passado, o valor do parent será undefined.

- <RecordProvider record={recordData}>
+ <RecordProvider record={recordData} parent={parentRecordData}>
...
</RecordProvider>

Se não houver bagagem histórica, você também pode usar diretamente CollectionRecordProvider para substituir.

- <RecordProvider record={recordData}>
+ <CollectionRecordProvider record={recordData} parent={parentRecordData}>
...
- </RecordProvider>
+ </CollectionRecordProvider>

⚠️Diferença Entre RecordProvider e CollectionRecordProvider

  • RecordProvider está obsoleto e será removido no futuro.
  • RecordProvider carrega o antigo RecordContext, enquanto CollectionRecordProvider não.
× View Image