Skip to content

Form submissions browser #382

@ng-druid

Description

@ng-druid

When viewing a form provide a tab below that opens a sheet below and displays the submissions associated with the panel page form. For now only show this if the panel page is owned by the user.

Create search template or just use the standard api.


Create new component forms/form-submissions. This component will use a mat-nav-list like panel-selector component to list form submissions for a form. A button will be be placed bottom center of the rendered panel page. The button will appear for owners of the panel page for now. In the future more configurable based on read permissions. To populate the submissions nav list we will create either an api end-point or directly hit opensearch. The simplest approach might just be to use a dedicated end-point for now and not fiddle with opensearch security or needing a search template, etc. We will add a new entity with crud set-up for either rest or opensearch depending on appraoch.

We can either match against formId or panelPageId. As long as that data point is added as a hidden form input to the panel page form. Although we could just use the derived index since each forms submissions are stored in a separate index anyway. That is probably simplest. So our form submssions component will require an input for panelPageId. Given the panel page id. Can forms relay on injecting something that has the objects repo info or do we need new configuration for forms module specifically for the forms index prefix? ie. rollthecloudinc__spearhead-canva-objects__{panelPageId}

I think the easiest way to do it is to inject panels settings into the component since the objectsRootUrl is available there already. We just need to implement a simple algroithm to extract the github owner/repo. From there we can derive the index name. The dynamic index will require a custom api solution probably. So we need to add something , api end-point to hedge.

We also have access to the team/brand, org to safely secure the data. We just need to add something that restricts reading form submissions based on rules that reference claim values. ie. brand/team == claims[brand/team]

import { Component, OnInit, Input, Inject} from '@angular/core';
import { UntypedFormBuilder, UntypedFormControl, Validators, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
import * as uuid from 'uuid';
import { AttributeValue } from '@rollthecloudinc/attributes';
import { SITE_NAME } from '@rollthecloudinc/utils';
import { PanelPage, PanelPageListItem, LayoutSetting, PanelContentHandler } from '@rollthecloudinc/panels';
import { EntityServices, EntityCollectionService } from '@ngrx/data';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { MatBottomSheetRef } from '@angular/material/bottom-sheet';
import { CONTENT_PLUGIN, ContentPlugin } from '@rollthecloudinc/content';
import { ContentSelectorComponent } from '../../../components/content-selector/content-selector.component';
import { Observable } from 'rxjs';

@Component({
  selector: 'classifieds-ui-panel-selector',
  templateUrl: './panel-selector.component.html',
  styleUrls: ['./panel-selector.component.scss']
})
export class PanelSelectorComponent implements OnInit {

  @Input()
  panelFormGroup: UntypedFormGroup;

  selectedIndex: number = 0;

  panels$: Observable<Array<PanelPageListItem>>;

  panelPagesService: EntityCollectionService<PanelPage>;
  panelPageListItemsService: EntityCollectionService<PanelPageListItem>;

  // private contentPlugin: ContentPlugin;

  constructor(
    // @Inject(CONTENT_PLUGIN) contentPlugins: Array<ContentPlugin>,
    @Inject(SITE_NAME) private siteName: string,
    private bottomSheetRef: MatBottomSheetRef<ContentSelectorComponent>,
    private handler: PanelContentHandler,
    private dialog: MatDialog,
    private fb: UntypedFormBuilder,
    es: EntityServices
  ) {
    this.panelPagesService = es.getEntityCollectionService('PanelPage');
    this.panelPageListItemsService = es.getEntityCollectionService('PanelPageListItem');
    // this.contentPlugin = contentPlugins.find(p => p.name === 'panel');
  }

  ngOnInit(): void {
  }

  onNewSelect() {
    const name = uuid.v4();
    const newPanel = new PanelPage({ id: undefined, layoutType: 'grid', displayType: 'page', site: this.siteName, gridItems: [], panels: [], layoutSetting: new LayoutSetting(), rowSettings: [] });
    (this.panelFormGroup.get('panes') as UntypedFormArray).push(this.fb.group({
      contentPlugin: 'panel',
      name: name,
      label: name,
      rule: new UntypedFormControl(''),
      settings: this.fb.array(this.handler.buildSettings(newPanel).map(s => this.convertToGroup(s)))
    }));
    this.bottomSheetRef.dismiss();
  }

  onLinkSelect() {
    this.selectedIndex = 1;
    this.panels$ = this.panelPageListItemsService.getWithQuery(`site=${encodeURIComponent(this.siteName)}`);
  }

  onItemSelect(panel: string) {
    const name = uuid.v4();
    //this.panelPagesService.getByKey(panel).subscribe(p => {
      //this.dialog.open(this.contentPlugin.editorComponent, { data: { panelFormGroup: this.panelFormGroup, pane: undefined, paneIndex: undefined, panelPage: p } });
      (this.panelFormGroup.get('panes') as UntypedFormArray).push(this.fb.group({
        contentPlugin: 'panel',
        name: name,
        label: name,
        rule: new UntypedFormControl(''),
        linkedPageId: new UntypedFormControl(panel, Validators.required),
        locked: new UntypedFormControl(true),
        // settings: this.fb.array(this.handler.buildSettings(p).map(s => this.convertToGroup(s)))
        settings: this.fb.array([])
      }));
      this.bottomSheetRef.dismiss();
    //});
  }

  convertToGroup(setting: AttributeValue): UntypedFormGroup {

    const fg = this.fb.group({
      name: new UntypedFormControl(setting.name, Validators.required),
      type: new UntypedFormControl(setting.type, Validators.required),
      displayName: new UntypedFormControl(setting.displayName, Validators.required),
      value: new UntypedFormControl(setting.value, Validators.required),
      computedValue: new UntypedFormControl(setting.value, Validators.required),
      attributes: new UntypedFormArray([])
    });

    if(setting.attributes && setting.attributes.length > 0) {
      setting.attributes.forEach(s => {
        (fg.get('attributes') as UntypedFormArray).push(this.convertToGroup(s));
      })
    }

    return fg;

  }

}
<mat-tab-group mat-align-tabs="start" [selectedIndex]="selectedIndex">
  <mat-tab label="Type">
    <mat-nav-list>
      <a mat-list-item mat-list-item (click)="onNewSelect()">New Panel</a>
      <a mat-list-item mat-list-item (click)="onLinkSelect()">Link Panel</a>
    </mat-nav-list>
  </mat-tab>
  <mat-tab label="Search">
    <ng-template matTabContent>
      <mat-nav-list>
        <a *ngFor="let panel of (panels$ | async)" mat-list-item mat-list-item (click)="onItemSelect(panel.id)">
          <span mat-line>{{ panel.title }} [{{ panel.id }}]</span>
        </a>
      </mat-nav-list>
    </ng-template>
  </mat-tab>
</mat-tab-group>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions