docassemble icon indicating copy to clipboard operation
docassemble copied to clipboard

Add way to have `default screen parts` content be additive

Open plocket opened this issue 3 years ago • 2 comments

When an interview includes default screen parts like under and pre, that value overwrites all previous values setting that specifier. This is problematic when trying to collaborate. To describe an example of the particular situation we're facing currently:

We're building a package other projects can use. Our package needs to be able to include html somewhere on the page that uses user_info data. The only way we've found to do that so far is to put it in a default screen parts part. Unfortunately, that can be very easily and unknowingly overwritten by dependents that use the package.

There might be other ways to address the specific problem above, like giving js access to the user info or adding a default screen parts specifier that will always be there, is additive, and exclusively holds invisible content. In the past, though, I've run into other situations where the overriding content behavior is limiting.

One way to address this is to allow default screen parts content be additive. I realize that it needs to be backwards compatible so that developers don't run into unexpected behavior.

One possible suggestion is to add the ability to set overwriting to False. That way we could if dependents overwrite content, we could give them a way to deal with problems when they come up. The below is a bit awkward and I'm pretty skeptical about it being the final implementation, but this is one draft of what this might look like:

# `pre` will be overwritten in these files
include:
  - file1.yml
  - file2.yml
---
default screen parts:
  pre: |
    Some content that will overwrite the content in the previously included files
---
default screen parts:
  pre:
    overwrite: False
    content: |
       Some other content that will be added to the content in the previous block
---
# Files that I know will not overwrite the `pre` content
include:
  - file3.yml
---

plocket avatar Jul 29 '21 13:07 plocket

No matter what, you are going to need to teach users of your package to write special syntax in order to define their pre content in a certain way so that they do not overwrite the pre content that your package already provides.

So if you have to do that anyway, you could tell your users to define their pre content using a template instead of default screen parts. You could have this in file1.yml:

default screen parts:
  pre: |
    Copyright (c) 2021 ABC Inc.  ${ top_of_screen_content }
---
template: top_of_screen_content
content: ""

Your documentation would say "if you want content to appear at the top of the screen, define the template top_of_screen_content"

template: top_of_screen_content
content: |
  This interview may not be used for any unlawful purpose.

The template in file1.yml would just be a fallback in case the user didn't define a template.

Users of your package would still have the freedom to use default screen parts directly if they wanted to override your content.

An advantage of doing it this way is that you as the package author now have control over exactly how the user's "pre" content combines with yours. Do you want an inline append, or a new paragraph? Maybe you want to prepend their content, or maybe you want their content to be inside a div. Maybe you want to strip newlines out of their content. There are so many different ways that content from two sources can be combined. This approach gives you a lot of flexibility.

Alternatively, you could also give users of your package the option of incorporating your content. In file1.yml, you could do:

default screen parts:
  pre: |
    ${ boilerplate_pre }
---
template: boilerplate_pre
content: |
  Copyright (c) 2021 ABC Inc.

Then, your documentation could instruct users to define a default screen parts that includes ${ boilerplate_pre } in the place where the user wants it. And the user could choose to override it, too.

You could also instruct the user to append a template to a variable. In file1.yml you could do:

default screen parts:
  pre: |
    % for part in top_of_screen_content:
    ${ part }
    % endfor
---
template: boilerplate_pre
content: |
  Copyright (c) 2021 ABC Inc.
---
mandatory: True
code: |
  top_of_screen_content = [boilerplate_pre]

Then your instruction to the user would be to write a mandatory code block that appends one or more templates to an array, e.g.,

template: my_pre
content: |
  This interview may not be used for any unlawful purpose.
---
mandatory: True
code: |
  top_of_screen_content.append(my_pre)

This could be helpful if there is a situation where your package is package A and then package B incorporates package A and then package C incorporates package B and then package D incorporates package C. Each package could append its own thing to top_of_screen_content.

This method is what WordPress, Drupal, and Emacs do in situations like this.

jhpyle avatar Jul 30 '21 11:07 jhpyle

I do see the advantages in that method. It's very modular. As a developer, though, I'd love to at least have the option to just add onto previous content. That is, to have a variable that represents that content and then be able to put my content around it. That way, if I can't do anything else and if the module creator hasn't accounted for all this, I can still retain what was there.

Sorry if this moves the goal posts a bit. I'm thinking through this trying to better articulate the need that I see.

plocket avatar Aug 13 '21 11:08 plocket