rollthecloudinc / quell

Climate aware CMS breaking web apps free from carbon emissions.
https://demo.carbonfreed.app/pages/create-panel-page
GNU General Public License v3.0
14 stars 1 forks source link

Form Building #6

Open verti-go opened 3 years ago

verti-go commented 3 years ago

Build forms with formly.

Add formly module

Expose a few formly types.

Use formly with panels to layout forms.

Save panel pages as second level entities using dynamic schema.

Page can act as "bundle" or "type" that groups instances together which share the same dynamic schema / structure.

For example, a blog page can be created as a form. The form panel page would include all the fields for creating a "blog post". User can hit the page and fill out form. Save the form. Now we have 2 levels of info. One being the blog post type. The blog post type defines the structure of all derivatives. Through the page that someone built without any coding others can create derivatives by filling out he form fields specified by the creator of the root page.

Instead of panel pages just being a way to create pages for display. They are a means to create new "entities" based on a structure defined by a page.

We use formly for the front-end interface. Convert that data to attributes for persistence.

Panel pages that can act as forms for saving data.

Utilizing formly for rendering fields. Attributes for data storage.

pluggable storage mechanism based on page type.

page derivative -> map to plugin page storage

Replace persistence with plugin.

Right now persistence occurs through ngrx data.


Form bindings are being lost for pages as forms. Not surprising. This is happening for attributes as well. So we need to figure out why attributes are losing the binding. Than see if once that is fixed it fixes it for Formly fields as well. Small price to pay for replacing everything with plugins which is the cause.

Dynamic components require injection of the control container. No other means to bind.


Allow formly fields to be rendered using data sources like rest.

Right now compatibility is hard coded into rest. I think we need to extract that out to be more flexible.


Implement page derivative persistence.

derivativeId should be set to the page id that the page was derived from.


I think a plugin will be needed for each type. This will make it easy for others to extend with their own custom types.


Validation integration


repeating section - nested panel can be repeated section - how to define?

I think repeating section can be achieved using a panel style. Create "Repeating Section" style form form displayType. When repeating section is selected the nested. Actually I don't think that will work... hm

Maybe create new plugin content type for repeated section.

data table integration -- ag or ng? --- separate module that plugs in - can probably be used for other integrations as well.


Migrate vocabularies into project so that they can be used to define static data sources. Possibly create custom type for formly using vocabularies.


Add display type options

form:


Next steps:

Implement formly repeating section Add option to disable field Add option to hide field = hidden field -- like for "type". Investigate validation options Investigate expression options Investigate media upload -- would be neat to have media browser... could media browser be built from panel pages...

verti-go commented 3 years ago

Fixed binding issue. Implemented basic formly module.

verti-go commented 3 years ago

All material types implemented with exception of autocomplete. Next step is to create kitchen sink page with example of each type. I would also like to create a checkbox group type.

verti-go commented 3 years ago

The Date type value is not being converted to a value attribute. Need to debug that and resolve.

verti-go commented 3 years ago

Nested panels render with formly fields but state changes that update redux not occurring. Also when submit is pressed on the master page error occurs, data not populating from nested panel pages.

verti-go commented 3 years ago

Fixed nested form panel pages.

The nested page needs its display type to be set to form for now. I just show that now so it can be selected when editing nested inline panel pages.

ng-druid commented 3 years ago

Using nested panel page form as a template for repeating inside an array of values.

Business -- addresses (repeater) ---- ...

Similar to rest.

Rest takes a data source -- create a separate pane for each item.

Instead of our data source being a http request it is something else. It is something that can be altered and changed.

ng-druid commented 3 years ago

Display types might need settings.

Allow nested form to be multiplied?

A nested form has a setting that allows it to be used as a repeating data object.

ng-druid commented 3 years ago

PagePage:displaySettings

form -> min and max?

ng-druid commented 3 years ago
<ng-container [ngSwitch]="panelPage?.layoutType">
  <ng-container *ngSwitchCase="'grid'">
    <ng-container [ngSwitch]="panelPage?.displayType">
      <ng-container *ngSwitchCase="'form'">
        <form *ngIf="!nested" [formGroup]="pageForm" (ngSubmit)="submit()">
          <classifieds-ui-grid-layout [dashboard]="panelPage?.gridItems" [displayMainControls]="false" [displayItemHeader]="false" [options]="options">
            <ng-template #innerGridItem let-i="i">
              <classifieds-ui-render-panel [formControl]="panelsArray.controls[i]" (heightChange)="onHeightChange($event, i)" [panel]="panelPage.panels[i]" [nested]="nested" [contexts]="contexts" [resolvedContext]="resolvedContext" [contextChanged]="contextChanged" [displayType]="panelPage.displayType"></classifieds-ui-render-panel>
            </ng-template>
          </classifieds-ui-grid-layout>
          <button type="submit">Submit</button>
        </form>
      </ng-container>
      <ng-container *ngSwitchCase="'page'">
        <classifieds-ui-grid-layout [dashboard]="panelPage?.gridItems" [displayMainControls]="false" [displayItemHeader]="false" [options]="options">
          <ng-template #innerGridItem let-i="i">
            <classifieds-ui-render-panel fxFlex (heightChange)="onHeightChange($event, i)" [panel]="panelPage.panels[i]" [nested]="nested" [contexts]="contexts" [resolvedContext]="resolvedContext" [contextChanged]="contextChanged" [displayType]="panelPage.displayType"></classifieds-ui-render-panel>
          </ng-template>
        </classifieds-ui-grid-layout>
      </ng-container>
    </ng-container>
  </ng-container>
  <ng-container *ngSwitchCase="'gridless'">
    <ng-container [ngSwitch]="panelPage?.displayType">
      <ng-container *ngSwitchCase="'form'">
        <form *ngIf="!nested" [formGroup]="pageForm" (ngSubmit)="submit()">
          <ng-container><ng-template classifiedsUiLayoutRendererHost></ng-template></ng-container>
          <button type="submit">Submit</button>
        </form>
        <div class="nested-form-wrapper" *ngIf="nested" [formGroup]="pageForm">
          <ng-container><ng-template classifiedsUiLayoutRendererHost></ng-template></ng-container>
        </div>
      </ng-container>
      <ng-container *ngSwitchCase="'page'">
        <ng-container><ng-template classifiedsUiLayoutRendererHost></ng-template></ng-container>
      </ng-container>
    </ng-container>
  </ng-container>
  <ng-container *ngSwitchCase="'split'">
    <ng-container [ngSwitch]="panelPage?.displayType">
      <ng-container *ngSwitchCase="'form'">
        <form *ngIf="!nested" [formGroup]="pageForm" (ngSubmit)="submit()">
          <ng-container><ng-template classifiedsUiLayoutRendererHost></ng-template></ng-container>
          <button type="submit">Submit</button>
        </form>
        <div class="nested-form-wrapper" *ngIf="nested" [formGroup]="pageForm">
          <ng-container><ng-template classifiedsUiLayoutRendererHost></ng-template></ng-container>
        </div>
      </ng-container>
      <ng-container *ngSwitchCase="'page'">
        <ng-container><ng-template classifiedsUiLayoutRendererHost></ng-template></ng-container>
      </ng-container>
    </ng-container>
  </ng-container>
</ng-container>

<ng-template #renderPanelTpl let-i="i">
  <ng-container [formGroup]="pageForm">
    <ng-container formArrayName="panels">
      <classifieds-ui-render-panel [formControlName]="i" [panel]="panelPage.panels[i]" [nested]="nested" [contexts]="contexts" [resolvedContext]="resolvedContext" [contextChanged]="contextChanged" [displayType]="panelPage.displayType" [indexPosition]="i" [css]="filteredCss"></classifieds-ui-render-panel>
    </ng-container>
  </ng-container>
</ng-template>

Layouts -> display type -> display type actually needs a separate renderer now.

ng-druid commented 3 years ago

displaytype module

pages

<- factory page && form -> registers page and form

layout HAS display type? - layout "compatible" with specific display types?

windbeneathyourwings commented 3 years ago

Repeating Sections

Two options so far.

Use formly repeating section. primary disadvantage of this is that other content can not be placed between inputs. I think this would require a new style like "repeating section". A style handler would than extract all formly panes and pass them as an array for a new repeating section renderer for formly I'm thinking. Actually no content needs to go between things.

The other options is to forgo formly and handle the add, delete, addition manually. This would require. No this is not a good option. To much work. Lets just do it with formly for now. If we need to we can come back to making this work with a proprietary approach.

windbeneathyourwings commented 3 years ago

The approach which has been chosen for repeating sections / embedding entities is going to be based on binding to datasources rather the using formly repeating sections. This provides much more flexibility in terms of maintaining all the features of nested panel pages for embedded entities.

windbeneathyourwings commented 3 years ago

Storing the entity makes more sense than storing the panel page form with all the settings. The panel page form with all the settings especially when nested forms are used is very difficult to navigate. The form service has been modified to better interpret / transform a panel page form to a meaningful object literal of properties included nesting forms and forms attached to datasources.

Datasources are being used for repeating fields / groups of fields. This is being done using datasources instead of formly fields to maintain compatibility with all the other panel page features. Two caveats I have seen with this is adding a new item to the array can be slow. Currently no great method exists to populate repeating group from context and override via edit/delete of items in the group. The current workable dev example uses a datasource that references a global state with an array that can be manipulated via bridge. The other problem with the current approach is when the global state changes for the data source the entire panel is re-rendered. There are work arounds for maintaining the entered data but it can still be a little jarring. This might also need to be invested because it directly impacts websocket integration the same way. There will be times things need to be added and removed from an array/datasource without re-rendering the entire panel like a chat. This is going to be tricky because right now the panel is built to re-render not individual panes within a panel

It could be worth investigating using formly for repeating fields and possible ways to integrate panel layout features.

A known gap with the current work is the date time value is always undefined. Need to diagnose and fix integration with date time.

windbeneathyourwings commented 3 years ago

Add validation and expressions to editor. Add alternative views for options in overlays.