Ele Calendar mostra os compromissos do Dataverse do jeito que o Outlook faz — e tarefas, e qualquer outra tabela que o servidor registra — por dia, semana de trabalho, semana ou mês, ou como uma lista semanal. Sua barra de ferramentas se move entre intervalos e layouts, um dia corrido se transforma em + mais, e os compromissos ao mesmo tempo ficam lado a lado. Ele lê as linhas do intervalo na tela enquanto você se move até ele, passando pela mesma consulta e segurança de uma grade, e mostra seus dias e horários no fuso horário do usuário, conforme todas as datas no portal são mostradas. Ele vem como um pacote adicional em cada pilha, desenhado no seu tema Fluent UI.
<Calendar regarding={{ tableName: 'account', id: accountId }} /><Calendar Regarding="@(new TableRecordReference("account", accountId))" />As consultas sobre Schmeler and Sons, a demonstração da página de detalhes da conta mostra. Regarding Mantém o calendário para os compromissos em cerca de um registro.
Sem Regarding, o calendário mostra todas as linhas que o usuário pode ler das tabelas que ela mostra. Ele lê as tabelas que o servidor registra para calendários — notas e todas as tabelas de atividades, e quaisquer outras registradas — ForCalendars cada uma datada por sua própria coluna: um compromisso no início e fim, uma tarefa, ligação, carta ou fax na data de vencimento. Compromissos e tarefas aparecem inicialmente; os outros que o usuário pode ler são oferecidos no menu Mostrar da barra de ferramentas, desativados. DefaultTables (Reagir: defaultTables) escolhe os que são mostrados primeiro, e Tables (Reagir: tables) os que pode mostrar. O calendário adiciona seu alcance e o registro concernente como condições próprias, para que uma visualização possa restringir o que mostra, mas nunca ampliá-lo.
<Calendar defaultTables={['appointment', 'task', 'phonecall']} /><Calendar DefaultTables="@(["appointment", "task", "phonecall"])" />O calendário lista apenas os compromissos que o usuário pode ler e permite que ele mova apenas um para onde pode alterá-lo. Um portal geralmente fornece aos contatos os compromissos para os quais são convidadosoptionalattendees: RowsInvolvingContact e requiredattendees os lê através das listas de partidos do compromisso, sem torná-los próprios do contato.
// Os contatos interpretam os compromissos para os quais são convidados, seja como participantes obrigatórios ou opcionais.
builder.Services.AddTableAccess("appointment", t => t
.ForSignedInUsers()
.RowsInvolvingContact("requiredattendees", "optionalattendees")
.Allow(TableSecurityPermission.Read)
.ReadingAllColumns());
// Cada consulta que o usuário pode ler chega ao portal: ser convidado já diz que é para ele.
builder.Services.Configure<SecurityOptions>(options =>
options.PortalVisibility.UnfilteredActivities.Add("appointment"));
Como em outras atividades, um compromisso chega ao portal apenas quando sua descrição começa com *WEB*, a menos que sua tabela esteja em SecurityOptions.PortalVisibility.UnfilteredActivities. Um portal de calendário adiciona appointment lá, como acima, para que a equipe marque compromissos no Dynamics e Outlook como sempre faz.
O usuário da aplicação do portal também precisa ser lido sobre compromissos no Dataverse. O Dataverse concede a cada tipo de atividade por meio de um conjunto de privilégios, de modo que os compromissos são cobertos pelas atividades de leitura que o papel de Usuário da Aplicação Power Portals Pro já possui.
Uma ocorrência de uma consulta recorrente é mostrada como qualquer outra consulta, com o ícone de repetição ao lado do assunto. Clicar em uma pergunta se abrir essa ocorrência ou toda a série; mover ou redimensionar uma muda essa ocorrência sozinha. O calendário mostra as ocorrências que o Dataverse escreveu: O Dataverse escreve as de uma série com antecedência, no que diz respeito à janela de expansão do ambiente — doze meses por padrão — e as últimas à medida que o tempo passa, então uma série que nunca termina mostra um ano de ocorrências por vez.
Um compromisso é desenhado pela forma como mostra seu horário, conforme o Outlook o desenha: ocupado como uma tonalidade com uma barra ao lado, livre só com o bar, listrado provisório e fora do escritório em roxo, lido a partir de sua razão de status. Um compromisso concluído aparece como ocupado, um cancelado como livre com seu assunto riscado. Em um mês, quando um horário é um ponto ao lado, e nas linhas da agenda, apenas a cor aparece. Os compromissos que você fornece tomam ShowAs e Canceled (Reagir: showAs e canceled), e cada um é desenhado com uma classe — ppp-calendar-appointment-free, -busy, -tentative, -out-of-office e -canceled — para reformular.
Em um Editable calendário que carrega seus próprios compromissos, selecionar um horário abre um novo horário sobre ele, sobre o Regarding registro, e clicar em um horário abre seus dados como um formulário, salvo com a mesma segurança de tabela, linha e coluna de qualquer registro. Mover ou redimensionar uma linha a salva — seu início, seu fim e se leva dias inteiros — onde o usuário pode alterar a linha e essas colunas e ela não está concluída, cancelada ou inativa; uma linha cuja tabela mantém uma data, como a data de vencimento de uma tarefa, se move mas não redimensiona, e uma datada de quando foi criada permanece no lugar. Clicar em uma linha de outra tabela abre seu formulário: as colunas que seu registro mostra, ou seu próprio formulário para a tabela, dentro MultiTableForm do calendário (Reagir: forms). Os detalhes de um compromisso e o formulário de outra tabela abrem em um diálogo no centro, ou, com FormLocation (Reagir: formLocation), em um painel lateral à esquerda ou à direita. Seus participantes são editados com PartyListEdit, que ColumnEdit também usa para todas as listas de participantes — entre elas Para, De e Cópia. À medida que o usuário digita, sugere os contatos, contas e usuários que pode ler e vincular (Ler e Anexar) que têm um endereço de e-mail, uma tabela sem ambos nunca foi pesquisada; escolher um adiciona como um chip. Quando o ambiente permite mensagens para destinatários de e-mails não resolvidos — ou AllowUnresolvedEmailAddresses diz isso — um endereço de e-mail que não corresponde a nenhum registro é adicionado sozinho com Enter. O Regarding de um agendamento oferece as tabelas para as quais pode apontar cujos registros o usuário pode ler e linkar; RegardingTables (Reagir: regardingTables) as restringe aos que você nomeia. Gerencie OnRangeSelect para criar compromissos do seu próprio jeito, e SaveChange (Reagir: onAppointmentChange) salvar movimentos do seu próprio jeito.
<Calendar regarding={account} editable regardingTables={['account', 'contact']} />
{/* Anywhere a party list is edited */}
<PartyListEdit columnName="to" allowUnresolvedEmailAddresses /><Calendar Regarding="@account"
Editable="true"
RegardingTables="@(["account", "contact"])" />
<!-- Anywhere a party list is edited -->
<PartyListEdit ColumnName="to" AllowUnresolvedEmailAddresses="true" />Em um Editable calendário, o formulário de um compromisso oferece Repetir: diariamente ou durante a semana, em dias da semana, mensal ou anual — na data ou no dia da semana, como na segunda terça-feira — a cada poucos tempos, e nunca terminando, após várias vezes ou em uma data. O Dataverse apresenta as ocorrências no fuso horário do usuário, então uma reunião às dez fica nas dez em uma mudança de relógio. Uma série abre como uma forma própria, onde a forma como ela se repete pode ser alterada, e o Excluir de uma ocorrência oferece a exclusão dela ou de toda a série. Repetir é oferecido a usuários que podem criar recurringappointmentmaster registros — e, para um compromisso que já existe, alterar e excluir, já que ela se torna a série. Conceda a série assim como concede compromissos, e dê ao usuário do portal Leitura sobre Conexão no Dataverse: fazer uma consulta uma série lê suas conexões, e o Dataverse recusa o salvamento sem ela.
// Uma série é um registro de sua própria tabela; suas ocorrências são nomeações.
builder.Services.AddTableAccess("recurringappointmentmaster", t => t
.ForSignedInUsers()
.RowsOwnedByContact("requiredattendees")
.Allow(TableSecurityPermission.Read | TableSecurityPermission.Create
| TableSecurityPermission.Write | TableSecurityPermission.Delete)
.ReadingAllColumns()
.WritingAllColumns());
builder.Services.Configure<SecurityOptions>(options =>
options.PortalVisibility.UnfilteredActivities.Add("recurringappointmentmaster"));
Uma nova nomeação, ou uma alteração em uma, torna-se uma série na mesma transação que o restante do seu save: o save envia um AddRecurrenceRequest ao lado do próprio save, então o horário nunca é salvo sem sua série, nem a série sem ela. O Dataverse cria a série a partir da consulta, com seus participantes, e remove a consulta. Uma página que está construindo seu próprio formulário pode enviar o pedido da mesma forma.
Uma série que começou muda a partir de sua próxima ocorrência, como em Outlook: Dataverse mantém as ocorrências que terminaram como uma série própria, compartilhando as da série groupid, para que permaneçam como aconteceram. A contagem que uma série termina é de toda a série — o portal lê e salva com as ocorrências já mantidas — e uma série sem nenhuma mais para vir não pode mais ser alterada. Mudar o dia todo encaixa nos horários: ligado aos dias inteiros em que caem; desligado, nove horas no primeiro deles por meia hora. O Dataverse mantém um compromisso de dia inteiro como um dia; o portal mostra e salva no próprio dia do usuário, independentemente do fuso horário.
Passe Appointments em vez disso, e o calendário mostra esses em vez de ler Dataverse. Com Editable ativado, os compromissos podem ser movidos, redimensionados e criados selecionando um intervalo: SaveChange (Reagir: onAppointmentChange) salva um movimento, e retornar false coloca o horário de volta; OnRangeSelect recebe um intervalo selecionado e OnAppointmentClick um compromisso aberto.
<Calendar appointments={appointments}
editable
onAppointmentChange={saveMove}
onAppointmentClick={openAppointment} /><Calendar Appointments="appointments"
Editable="true"
SaveChange="SaveMoveAsync"
OnAppointmentClick="OpenAppointment" />Apoiar o ponteiro em um agendamento mostra seu assunto, quando e onde ele está, e clicar em um abre um diálogo com seus detalhes, lido do Dataverse como uma página de registro lê um registro — através da mesma tabela de acesso e segurança de colunas — e mostrado como somente leitura. Gerencie OnAppointmentClick (Reagir: onAppointmentClick) para fazer outra coisa com um clique, como abrir uma página própria. As linhas do calendário, suas dicas e o diálogo de detalhes podem ser desenhados do seu jeito: veja Renderização Personalizada.
Coloque seus próprios controles na barra de ferramentas com ToolbarItems (React: os filhos do calendário), à frente da caixa de busca, como estão os botões da barra de ferramentas da grade. A CalendarButton recebe o calendário ao clicar: o período que ele mostra, o registro sobre o qual se refere, e RefreshAsync CreateAppointmentAsync (React: createAppointment e refresh). NewAppointmentCalendarButton inicia um novo compromisso como a seleção de um horário — a partir da próxima meia hora, quando o período mostrado recebe hoje, e caso contrário, a partir das 8:00 do primeiro dia — e é mostrado apenas onde isso inicia algo: um Editable calendário cujo host gerencia OnRangeSelect, ou que carrega seus próprios compromissos para um usuário que possa criá-los.
<Calendar regarding={account} editable>
<NewAppointmentCalendarButton />
{/* Seu próprio botão, entregue o calendário ao clicar */}
<CalendarButton
label="Export"
icon={<ArrowDownloadRegular />}
onClick={(calendar) => exportAsync(calendar.start, calendar.end)}
/>
</Calendar><Calendar Regarding="@account" Editable="true">
<ToolbarItems>
<NewAppointmentCalendarButton />
<!-- Seu próprio botão, entregue o calendário ao clicar -->
<CalendarButton Label="Export"
Icon="@(new Icons.Regular.Size20.ArrowDownload())"
OnClick="@((CalendarContext calendar) => ExportAsync(calendar.Start, calendar.End))" />
</ToolbarItems>
</Calendar>O calendário organiza seus compromissos por horas de um dia, uma semana de trabalho ou uma semana, como um mês de dias, ou como uma lista de agendas, e sua barra de ferramentas tem um seletor para alternar entre eles. DefaultLayout (Reagir: defaultLayout) é o que ele abre em, uma semana, a menos que você escolha outra. Layouts (Reagir: layouts) mantém os que você nomeia, listados na sua ordem: nomeie um, e o selecionador vai e o calendário permanece nele. Cada layout tem uma página própria: Dia, Semana de Trabalho, Semana, Mês e Agenda.
<Calendar defaultLayout="month" layouts={['month', 'agenda']} /><Calendar DefaultLayout="CalendarLayout.Month"
Layouts="@([CalendarLayout.Month, CalendarLayout.Agenda])" />Oferecer visualizações em ViewIds — vistas do Dataverse, cada uma com sua própria tabela — MultiTableViewIds, visualizações de várias tabelas registradas ou AddMultiTableView mantidas no Dataverse, e CustomViewDefinitions, vistas definidas em código, e a barra de ferramentas tem um seletor para escolher o que o calendário mostra. DefaultViewId é o que ela abre. A caixa de busca encontra as colunas de busca de cada tabela como a busca de uma grade. Desligue-a com AllowSearch.
Com AllowFiltering, o menu Filtro da barra de ferramentas oferece filtros de Editar, que abrem os filtros das tabelas mostradas, uma aba para cada uma em ordem de nome, cada um do diálogo que o botão de Filtro da grade abre: condições nas colunas da tabela, aninhadas em grupos, e tabelas relacionadas para filtrar, sobre as colunas e tabelas que o usuário pode ler. As colunas de uma aba são lidas quando ela é aberta pela primeira vez. Os filtros substituem os da própria visualização até que o usuário escolha outra visualização. Está desativado por padrão, porque o usuário pode remover todos os filtros que a visualização possui.
Com AllowSavedViews (Reagir: allowSavedViews), um usuário logado pode salvar o que o calendário mostra — a visualização, o filtro, as tabelas mostradas e o layout — como uma visualização própria, escolher a visualização padrão e esconder as que não usar, no menu Filtro da barra de ferramentas. Uma visualização apenas dos compromissos também é oferecida nas grades de compromissos, e uma visão de várias tabelas nas linhas do tempo. Como as visualizações são salvas, alteradas e compartilhadas está na página de Visualizações Salvas .
<Calendar viewIds={[allAppointmentsViewId, scheduledViewId]}
defaultViewId={allAppointmentsViewId}
customViewDefinitions={teamsMeetings}
allowFiltering
allowSavedViews /><Calendar ViewIds="@([allAppointmentsViewId, scheduledViewId])"
DefaultViewId="allAppointmentsViewId"
CustomViewDefinitions="teamsMeetings"
AllowFiltering="true"
AllowSavedViews="true" />Reuniões, tarefas e ligações da Schmeler and Sons, por meio de duas visões definidas em código: Reuniões e tarefas, e Ainda por fazer — as tarefas e chamadas ainda não concluídas, cada consulta de tabela é sua. O menu Filtro ativa e desativa cada tabela, os filtros Editar têm uma aba para cada uma, e um visitante logado pode salvar o que o calendário mostra como uma visualização própria. Uma tarefa ou chamada se abre em um painel lateral à direita (FormLocation).
Nomeie um parâmetro de consulta em PersistedStateQueryParameter, e o calendário mantém seu layout, o período que mostra e a visualização de compromisso escolhida ali, então uma recarga ou um link compartilhado o abre onde foi deixado. O que ele abriria de qualquer forma fica de fora — a data enquanto o período mostrado inclui hoje, então um link para a semana atual continua seguindo hoje. A busca também é mantida quando você ativa IncludeSearchInPersistedState; ela é omitida por padrão, já que o que os usuários procuram pode ser sensível. Cada alteração substitui a entrada de histórico do navegador, então Voltar sai da página em vez de voltar a cada semana. Ambas as pilhas escrevem o mesmo valor, então um link feito em uma abre o mesmo calendário na outra.
<Calendar defaultLayout="month" persistedStateQueryParameter="calendarState" /><Calendar DefaultLayout="CalendarLayout.Month" PersistedStateQueryParameter="calendarState" />Uma visualização definida em código mantém o calendário com as reuniões realizadas no Teams, abrindo na agenda da semana, com uma altura definida.
O calendário é um complemento: PowerPortalsPro.Web.Blazor.Calendar no Blazor e @powerportalspro/react-calendar no React. Adicione o pacote ao lado do próprio framework para usá-lo.
npm install @powerportalspro/react-calendardotnet add package PowerPortalsPro.Web.Blazor.CalendarNome | Tipo | Padrão | Descrição |
|---|---|---|---|
AllowFiltering | bool | False | |
AllowSavedViews | bool | False | |
AllowSearch | bool | True | |
AppointmentDetails | RenderFragment? | ||
Appointments | IReadOnlyList<CalendarAppointment>? | ||
ChildContent | RenderFragment? | ||
CssClass | string? | ||
CustomViewDefinitions | List<MultiTableViewDefinition>? | ||
DefaultLayout | CalendarLayout | Week | |
DefaultTables | IEnumerable<string>? | ||
DefaultViewId | Guid? | ||
Editable | bool | False | |
FormLocation | DialogLocation | Center | |
Height | string | 600px | |
IncludeSearchInPersistedState | bool | False | |
Layouts | IReadOnlyList<CalendarLayout>? | ||
MatchParties | bool? | ||
MultiTableViewIds | IEnumerable<Guid>? | ||
PersistedStateQueryParameter | string? | ||
Regarding | TableRecordReference? | ||
RegardingTables | IReadOnlyList<string>? | ||
SaveChange | Func<CalendarAppointmentChange, Task<bool>>? | ||
SavedViewsKey | string? | ||
Series | MultiTableSeries? | ||
ShowRecordLinks | bool | True | |
SignInUrl | string | Account/Login | |
Tables | IEnumerable<string>? | ||
ToolbarItems | RenderFragment? | ||
TooltipTemplate | RenderFragment<CalendarAppointment>? | ||
ViewIds | IEnumerable<Guid>? | ||
ViewSort | ViewSort | NameAscending |
AllowFilteringAllowSavedViewsAllowSearchAppointmentDetailsAppointmentsChildContentCssClassCustomViewDefinitionsDefaultLayoutDefaultTablesDefaultViewIdEditableFormLocationHeightIncludeSearchInPersistedStateLayoutsMatchPartiesMultiTableViewIdsPersistedStateQueryParameterRegardingRegardingTablesSaveChangeSavedViewsKeySeriesShowRecordLinksSignInUrlTablesToolbarItemsTooltipTemplateViewIdsViewSortNome | Tipo | Descrição |
|---|---|---|
OnAppointmentClick | EventCallback<string> | |
OnRangeSelect | EventCallback<CalendarRangeSelection> |
OnAppointmentClickOnRangeSelectNome | Parâmetros | Tipo | Descrição |
|---|---|---|---|
CreateAppointmentAsync | DateTimeOffset? start DateTimeOffset? end bool allDay | Task | |
LoadAppointmentsAsync | DateTimeOffset start DateTimeOffset end | Task<IReadOnlyList<CalendarAppointment>> | |
OnAppointmentChangeAsync | CalendarAppointmentChange change | Task<bool> | |
OnAppointmentClickAsync | string id string subject bool recurring string table | Task | |
OnRangeChanged | RangeChanged range | void | |
OnRangeSelectAsync | DateTimeOffset start DateTimeOffset end bool allDay | Task | |
RefreshAsync | Task | ||
RenderTooltip | string id | int |
CreateAppointmentAsyncLoadAppointmentsAsyncOnAppointmentChangeAsyncOnAppointmentClickAsyncOnRangeChangedOnRangeSelectAsyncRefreshAsyncRenderTooltip