dragontheory / D7460N-with-db

Your data your way. Fast, easy, and secure.
https://d7460n-app-with-resizer.pages.dev/
2 stars 1 forks source link

Form: HTML/CSS #19

Open dragontheory opened 2 years ago

dragontheory commented 2 years ago

CRUD operations for aside panel

CRUD Workflow:

  1. Users type in a search
  2. Search results appear in main panel
  3. Users click a search result to see details in aside panel
  4. User edits data in aside panel
  5. When user edits something in aside panel, the same data in the main panel also changes (mimic-into https://activecss.org/manual/mimic-into.html)?
  6. Data isn't save to the DB until the save button is clicked.

Form Workflow:

  1. Combine non-editable content styles with edit-in-place form elements to avoid building both.
  2. Form elements initially assume normal content styles (as if content is not editable)
  3. Text is selectable but not editable
  4. Users click "Edit" button and the form elements assume editable for styles
  5. Text is now editable until user clicks "Save" button

Example HTML structure for each collapsable section:

<input id="powerstats" type="checkbox" />
<label for="powerstats">
  <panel-title>POWER STATS : :</panel-title>
  <panel-meta>[ 6 ]</panel-meta>
</label>
<panel-list>
  <list-item>
    <list-cell>Intelligence</list-cell>
    <list-cell>
      <input type="text" id="intelligence" name="intelligence" value="38" required />
    </list-cell>
  </list-item>
  <list-item>
    <list-cell>Strength</list-cell>
    <list-cell>
      <input type="text" id="strength" name="strength" value="100" required />
    </list-cell>
  </list-item>
  <list-item>
    <list-cell>Speed</list-cell>
    <list-cell>
      <input type="text" id="speed" name="speed" value="17" required />
    </list-cell>
  </list-item>
  <list-item>
    <list-cell>Durability</list-cell>
    <list-cell>
      <input type="text" id="durability" name="durability" value="80" required />
    </list-cell>
  </list-item>
  <list-item>
    <list-cell>Power</list-cell>
    <list-cell>
      <input type="text" id="power" name="power" value="24" required />
    </list-cell>
  </list-item>
  <list-item>
    <list-cell>Combat</list-cell>
    <list-cell>
      <input type="text" id="combat" name="combat" value="64" required />
    </list-cell>
  </list-item>
</panel-list>

CSS: [ same as the Filter panel ]

label,
panel-header {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: 1fr;
  align-items: start;
  cursor: pointer;
}

app-panel > input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  z-index: -1;
}
app-panel > input[type="checkbox"] + label + panel-list {
  max-height: 0;
}

app-panel > input[type="checkbox"]:checked + label + panel-list {max-height: 100%;}
bob2517 commented 2 years ago

In order to make sure that the user is editing the latest data, it is custom to fetch the latest data from the server before drawing the form, so that step should be in there at "3.5". It's just a way of mitigating problems of multiple users editing the same record. The user may have been looking at his page for a few hours and then clicked edit. But Dave edited the record half an hour ago. Hence the need to fetch the very latest data from the server before editing.

Additionally: CRUD 7 Send form to server 8 Confirm saved successfully or show field errors from the server or any other errors, like "no internet". 9 Update any display areas with the correct data from the server if form cancelled.

dragontheory commented 2 years ago

Are you returning just the text strings or some of the HTML elements around the text string?

I was thinking of using contenteditable. Since it's a boolean, it really fits well with my plans to change as little as possible (if anything at all), other than CSS styling, when switching to and and from editable and non-editable states. Trying to be DRY.

In keeping things more consistent, it may also help you if you are returning HTML.

WDYT?

bob2517 commented 2 years ago

Use input fields. If you want a select dropdown or radio button, or even implement a wysiwyg editor like tinyMCE, then it becomes possible. Contenteditable is too limited for anything more than a text string.

I'm returning HTML. I'll put in an option to draw different types of input fields depending on what type they are. Simplez. Done it before like this loads of times and it works well.

I'll commit to the branch in a minute - it's pretty much working now, in terms of separate the data from the HTML.

dragontheory commented 2 years ago

Use input fields. If you want a select dropdown or radio button, or even implement a wysiwyg editor like tinyMCE, then it becomes possible. Contenteditable is too limited for anything more than a text string.

Ok. Sounds good.

dragontheory commented 2 years ago

OK. Pushed first iteration of the form.

It shows up in the panel right away because, it is working as designed. The <panel-list> element is not empty so it assigns the .aside class to the body.

dragontheory commented 2 years ago

That is just the first section. Everything else is identical.

dragontheory commented 2 years ago

Each section will eventually be accordion drop downs.

bob2517 commented 2 years ago

Great - I'll start working with this. Work will slow down over the week due to regular work, but the target is to get the pagination finished by the end of Saturday, with Sunday as fallback.

dragontheory commented 2 years ago

OK. Sounds good. I tend to go with the least amount of markup needed. It doesn't even have a form element wrapper. If you need it, let me know and I will put it in.

bob2517 commented 2 years ago

Yeah, you can do when you get a moment. You can leave out the submit location and stuff like that. It's not urgent though, just let me know when there is something new to grab.

dragontheory commented 2 years ago

Also, if it's possible, (using mimic, I think?) I would like when users change the data in the aside panel, the same data changes (live as they type) in the row in the center panel. #5 in the CRUD workflow above. That is, if the same data is represented in the row in the center panel. It may not be. If not, then that's cool too.

dragontheory commented 2 years ago

Yeah, you can do when you get a moment. You can leave out the submit location and stuff like that. It's not urgent though, just let me know when there is something new to grab.

OK. Very good.

bob2517 commented 2 years ago

Also, if it's possible, (using mimic, I think?) I would like when users change the data in the aside panel, the same data changes (live as they type) in the row in the center panel

Yep, I can do that with mimic. It's a case after that of putting the content back if the form is cancelled. Don't worry technically how to do that part, but you will need to decide on the reset or cancel mechanism.

bob2517 commented 2 years ago

PS you've got an extra \</panel-list> under the bottom aside because the indentation is out on the first aside closing panel-list tag under the profile-avatar bit. I've fixed it on the branch but you might want to fix it in the main.

bob2517 commented 2 years ago

Would you have any objection to self-hosting the fonts in the project? I'm getting lots of lags from the CDN... No worries if not. I can sort it out if yes.

bob2517 commented 2 years ago

Re the cancel/reset mechanism, if you don't want buttons you could copy the todo app functionality for a more modern feel. On that, the enter key is the submit, if you click away from the field it submits. But when you press escape it cancels.

That may be a cleaner way. It will look quite seamless.

Will need a way to handle the display of save/internet errors though.

Ps. I've put the edit fields on the branch with the profile-avatar. I'll let you style that image and I'll copy over the CSS when that's ready. Easy enough to scale down a larger image if needed. It's currently using "md", let me know if you want to use the "lg".

I'm going to retire now, but that's great work today. Will catch up later.

bob2517 commented 2 years ago

PPS. The [ 843 ] next to power stats - is that the total power?

dragontheory commented 2 years ago

PPS. The [ 843 ] next to power stats - is that the total power?

No. That is supposed to be the count of the number of stats inside the Power stats accordion. It is technically yet another list. I thought if we are counting them, might as well display them... So it should be [ 6 ].

dragontheory commented 2 years ago

Re the cancel/reset mechanism, if you don't want buttons you could copy the todo app functionality for a more modern feel. On that, the enter key is the submit, if you click away from the field it submits. But when you press escape it cancels.

Agreed. I've done that sort of thing in the past but users actually didn't like it. They said it was too fast and wasn't obvious what they should do. They said they were afraid to click anything. So I went back to the traditional edit, save, reset buttons.

dragontheory commented 2 years ago

Would you have any objection to self-hosting the fonts in the project? I'm getting lots of lags from the CDN... No worries if not. I can sort it out if yes.

Also agreed. I was testing Google out to see how performant they are. Also less files for me to have to worry about and be charged to host. They are by far the largest files in the entire application. But ultimately this project, at least for mywork, will be behind the company firewall. So I will have to self host the fonts.

dragontheory commented 2 years ago

What do you think about forcing numbers only for fields that accept numbers only?

Example:

<input type="text" onkeypress="return /[0-9]/i.test(event.key)" />
dragontheory commented 2 years ago

I'm going to retire now, but that's great work today. Will catch up later.

OK. Thanks for all your help! Have a great evening and a great week!

bob2517 commented 2 years ago

So it should be [ 6 ].

Ok - I can auto-count those.

So I went back to the traditional edit, save, reset buttons.

Yeah - I must admit that I prefer those too for things like this. So we need an edit link, add record link (?), save and cancel?

What do you think about forcing numbers only for fields that accept numbers only?

Example:

<input type="text" onkeypress="return /[0-9]/i.test(event.key)" />

Yeah, sure. Could be a type number field too. Dunno if the arrows on that can be styled though.

bob2517 commented 2 years ago

So I will have to self host the fonts.

OK - I'll download them and put them into the assets folder under fonts/.

dragontheory commented 2 years ago

Added the HTML structure [ and CSS ] for each section for the aside/details/profile panel in the description above.

dragontheory commented 2 years ago

Added a second section to the form HTML to demonstrate how collapsable sections work.

bob2517 commented 2 years ago

I've added the appearance section API data, updated with your new stuff, and updated the branch. I've downloaded Oxanium but couldn't find how to download Agency-FB easily, so I left that.

I could simplify the whole project by using reactive variables for the aside fields, but to do that I would have to hard-code the input fields, like you have been doing, rather than dynamically drawing them. That way, the panels would update as soon as the ajax was fetched, without any re-rendering required. The code would look cleaner. I'm very tempted to do it. There's a flicker when rendering the aside panels, and it would be good to sort that out without being forced to resort to a fade effect. It would speed rendering time up too. Will think it over and maybe do a version of it on Wednesday.

bob2517 commented 2 years ago

With reactive variables the code would end up looking like this, sorta:

        <label for="powerstats">
          <panel-title>POWER STATS : :</panel-title>
          <panel-meta title="Number of stats">[ 6 ]</panel-meta>
        </label>
        <panel-list>
          <list-item>
            <list-cell>Intelligence</list-cell>
            <list-cell>
              <input type="text" id="intelligence" name="intelligence" value="{{$item.power.intelligence}}" required />
            </list-cell>
          </list-item>

Whenever the $item.power.intelligence variable was updated, with a new ajax call, the $item.power.intelligence would change in the input field automatically. It is a very targeted replacement too - only the variable value itself updates, not the surrounding DOM.

The easiest example for it is here: https://activecss.org/manual/simple-clock.html

Imagine that concept, but each field in the aside panel would automatically update when its variable changed.

It's like the observe paradigm, but for variables. Funnily enough, I named them reactive variables, and you know that I'm going to change the observe event to :react. So they are similar concepts.

Because the API fields are always constant and the display never changes, this would seem to be the best solution.

I think it would work - I've not tested it in an input field value attribute before though - I need to test it. I know the technique works in style attributes and other attributes.

dragontheory commented 2 years ago

Just so I understand... you would not be returning HTML. Just the values?

That sounds great to me.... what's the downside to that?

I would like to be able to handle datasets with different form fields though.

I was thinking that doing supers is good because it's a rich dataset to demo how all that data would look like in the app. But also makes things look not serious. Cartoony like...

When I had the real guy's picture showing, the app looked more official. Now with A-Bomb showing, the app sort of looks Cartoony...

WDYT?

dragontheory commented 2 years ago

not the surrounding DOM.

I like that. It fits along with JAMstack architecture, delivering all static resources upfront and allow me to see in the code what is being delivered. And it lends me thecontrol I need for layout and patern design. Most DEVs would not allow me to do this part of the form.

bob2517 commented 2 years ago

But also makes things look not serious. Cartoony like...

Yeah, that's the downside. If you can find a suitable API, then I'm fine with replacing what is there.

That sounds great to me.... what's the downside to that? I would like to be able to handle datasets with different form fields though.

Yeah, I need to mull it over. If I can combine both techniques and draw these dynamically based on a JSON schema and yet have them reactive... It should be possible in ACSS - need to get it straight in my head what the technique would be. I think by adjusting the schema slightly it might be possible. Even then, I need to test it with input fields. I don't know how practical that is going to be, seeing as how the input fields are changeable by the user. Could use a different attribute to store the original value too. I dunno - will think about it and play around with the idea on Wednesday.

bob2517 commented 2 years ago

Just so I understand... you would not be returning HTML. Just the values?

Yes - you are only going to get the values - I wasn't planning on giving you the HTML for the forms anyway. Regardless of the method that is taken to draw the form fields, you will be drawing the form.

Re the input field auto-updating. Reactive variables currently only work on elements with closing tags. I'll take a look at that though - it should be relatively trivial to make it work with single tag elements. If it looks like it's going to impact the finishing of the pagination by the end of the weekend though, I'm not going to do it - I'll work with what we have so far - maybe revisit it later on.

bob2517 commented 2 years ago

Experiments with utilising an input value as a reactive variable...

The good news is that the theory will work, but only if the input element is fresh and hasn't been altered in any way since it was drawn. This is to do with the different between an attribute and a property. An input field has both an attribute, the value, and the property, which is the thing which stores the value of what is being typed. They are two separate things.

Once the input field has been typed in, changes to the value attribute no longer affect the value displayed.

However, if the property has not in any way been changed by someone typing, updating the value by changing the contents of the value attribute also updates the visible property.

I could update the core to set up reactive variables to also update properties when appropriate, for things like input fields. I can't think of any reason why anyone wouldn't want this behaviour. Like I update the element, and if it also has a property that is the same, I could update the property too.

Anyway - there you go. I think it can be done, but it may not be for this right now because I don't want to get distracted by core work. It can be worked around, and I've tested the concept, by having a specific edit button that turns off the disabled state, and then after saving or cancelling a particular edit, and it would then redraw the new input fields or the old input field over the top of the old one, in a fresh disabled state. That would do the job. But if we are doing that, it could be argued that it's not worth doing it and making the code overly complicated - we may as well just redraw the whole lot and save typing that extra code. But we do solve the flicker issue, because there aren't any noticeable rendering issues when input fields get replaced with new ones, that I could see anyway.

I can err sometimes in making something perfect at the expense of over-complicating the code. The end result can be amazing, but it's harder to read. I don't really want to do that on your project.

I'll see how it goes and how much time we have later on and maybe come back later to reactive properties. I still think it's the optimum solution, and could be a fresh and easy paradigm specifically for CRUD forms, but I'm going to park it to one side for the moment and start nailing the plan for the pagination!!!

dragontheory commented 2 years ago

OK. That sounds good.

I'm still not clear on the difference between this and ACSS mimic.

Editing the data in a form text input element, and as you type it shows up in another element somewhere else on the page, is very intuitive as to what exactly is being edited. Plus it's super cool.

I would love to use mimic so that the text in the center panel changes as they edit data in the aside panel form.

If it can't be used on a form element, there is always my favorite contenteditable! lol

bob2517 commented 2 years ago

Yeah mimic is still going to be used for that. It is indeed super cool.

I'm talking about redrawing the input fields in the aside panels when someone clicks on a new row. Rather than redraw all the input fields each time, I was looking at just changing the values in the input fields - just the values, and not touching the surrounding DOM or even the input field HTML.

Mimic is a slightly difference approach, it's more manual - you would have to specify which fields to update, but I don't think it's set up for value and properties anyway.

Reactive variables means that to update the screen you just update the variable and the screen changes. With mimic you type in an input field and something changes elsewhere. It's a little bit different. With reactive variables in input fields, all you would have to do is load the JSON and that's literally it. ACSS would then automatically convert it to variables, which would automatically update the input fields. No manual updating required.

Actually, you could iterate all the fields when a row was clicked and run a load of set-property and set-attribute commands on the already draw input fields. That's the other option. I think that may even be the easier solution rather than having to do a lot of core work. Yeah - that would be quick to do too.

Contenteditable is great until you try and work with it :) It's been a while though - maybe it's gotten better now. I remember wasting a lot of time trying to get something to work. But if you want this to work on CRUD forms, contenteditable isn't going to cut all the cheeses anyway, as it should support radios and checkboxes, etc.

Ok - way past my weeknight bedtime - goodnight!

dragontheory commented 2 years ago

So we need an edit link, add record link (?), save and cancel?

Added buttons to the top of the aside panel. Realizing that I may need to add buttons to each section... not sure.

I as I was adding buttons, I kept seeing the <list-item> <list-cell> design pattern over and over again. So I simplified the markup even more. That said, tweaks to styling is still needed.

Did not do an "add record" button yet because that involves designing the UI to support adding a new record. I have to think on how to do that. One of the most consistent complaints I've heard from users over the years has been "to many popups", referring to modals mostly for forms. That's one of the major reasons I wanted to have "edit in place" forms in the aside panel. Modals take users out of their context and workflow. But sometimes modals are appropriate. If users are creating new content, they are not searching. The intro section will swap out the search results section (inside the center panel) when users aren't searching so I will probably leverage the intro section for the "create record" form. Although it would be nice to be consistent and have the "create record" form in the same place as edit record form... hmmm...

Like I said, thinking about it...

dragontheory commented 2 years ago

@bob2517

May I use contenteditable for (only) text inputs? Much more malleable for spacing and aligning within CSS Grids, and styling for multiple themes.

bob2517 commented 2 years ago

Out of interest, have you done much work with contenteditables before?

I must say that I've probably wasted 4 weeks in total of my life working with those things in the past, trying to get cross-browser compatibility. I try and avoid them these days. Plus you lose any front-end input validation and label benefits. Plus they are not really a standard way to handle form data, and ACSS won't work with them directly regarding form submission.

But if you are keeping it basic, then it should be easy enough to keep an hidden input field up to date with the contents in preparation for form submits, if you really want to go that route.

If it is just to save time on the CSS though or want to avoid using an HTML tag for whatever reason, then I would steer you away from using contenteditables for the sake of a few lines of CSS or an extra tag, just based on prior experience of wasting a lot of time and what sort of problems can come up when you try to do anything with them. But if you promise not to ask me to work on any inevitable problems that will arise because of using them, then go for it - it is your project - maybe it will be fine :)

bob2517 commented 2 years ago

I would only force myself to use contenteditables if I had to have emojis displayed in there, or something like that. Which is why I spent a month on the problems... I had no choice. I dunno if it was actually a month - it felt like it - it was one problem after another...

dragontheory commented 2 years ago

lol. Sounds like a customer request...

Appreciate it. Thank you, but nah.

Too much work for everyone else.

Got to stop spending my time/energy on the minors and get to the majors.

Maybe I'll mess around with it later, after the crunch. Need to get something cleaned up to show for the 19th.

Since our dataset is static, maybe I'll just replace the form elements with static list-cells for now.

Thank you for the sound recommendation.

bob2517 commented 2 years ago

Ok cool :) Wise move. There is a reason why things like TinyMCE make a lot of money and are best left to people who have already done a lot of work with contenteditables. Yes I would focus on getting what it there into a good state and avoid getting into too many new things at this point. I think the UI will be easier to work with and things will get clearer once outstanding things are resolved.