Code Monkey home page Code Monkey logo

hexbook-semantic's People

Contributors

bharbron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

hexbook-semantic's Issues

Implement deletion of tables

On the Tables screen, add a dropdown menu to each table card with a "Delete this table" option. Add an event handler to that menu option to trigger deletion of the table.

From the perspective of the store, deleting a table should do the following:

  • Set entities.tables.byId[<id of the deleted table>] to undefined
  • Remove the table id from entities.tables.allIds
  • Delete all tableEntries associated with the table from the store
  • Delete all templates associated with the table from the store
  • There shouldn't be a need to drill down any further than that. I.e. we don't need to delete tagWeights or entryDetails associated with associated tableEntries. Those are things that never get queried directly in the application, so we don't have to worry about them still showing up in allIds arrays or anything. Remove them if it straightforward to do so, but it is not a requirement.

SPIKE: Investigate chromium --print-to-pdf option for generating our PDF

Stumbled across something recently. Apparently chrome/chromium/headless-chrome has a build in --print-to-pdf option which is designed to print/save an HTML page as a PDF. More importantly, it sounds like it might support some of the the CSS "printed media" options such as page breaks and columns.

This might not be as good as PrinceXML when it comes to "nice" layout (avoiding mid-block page breaks, etc.), but might be a much easier and "good enough" option to explore. And since ElectronJS runs inside an instance of Chromium, its an option that should be effectively "built-in" for us.

Do some investigation. Mockup some examples. etc.

Separate template plugins into their own directory

We should move all plugin templates out of src/components/templateplugins.js and into their own folder src/plugins/templates/. We should also make each template plugin type a separate file, e.g. index.js, randomtable.js, etc.

Implement deletion of tableEntries

In the table details screen, implement a way of clicking checkboxes to select multiple table entries, or clicking the checkbox at the top of the datatable to select all table entries. Add a dropdown menu with a "Delete selected entryies" option. Add an event handler to that option to trigger deletion of the selected table entries.

From the perspective of the Redux store, deleting a table entry should do the following:

  • Remove the id of the tableEntry from entities.tables.byId[id of the related table].tableEntries
  • Set entities.tableEntries.byId[id of the table entry] to undefined
  • Remove the table entry ID from entities.tableEntries.allIds
  • Not mandatory, but should be easy enough to do that its worth it: delete any tagWeights associated with the tableEntry
  • Also not mandatory, but easy enough to do and keeps the store clean: delete any associated entryDetailsGroup and the associated entryDetails
  • The above two are not mandatory because nothing in the application should be querying tagWeight or entryDetails directly. They are only queried via tableEntries. So if the tableEntry is gone, it shouldn't matter if those are still there. But it is a good idea to keep the store cleaned up and small, so its worth removing them if it can be done easily.

Eliminate any remaining uses of SingleLineAdder

Eliminate any uses of SingleLineAdder. Everything should be moved to SingleLineAdderV2, including proper input validation and display of validation errors.

(I think the tables screen is the only place still using SingleLineAdder)

Once everything has been moved to SingleLineAdderV2, delete SingleLineAdder from src/components/forms and rename SingleLineAdderV2 to SingleLineAdder

Update Hexes screen so it uses a full table object

Currently the Hexes screen hardcodes a bunch of things based on the assumption that it is always operating on the 'HEX' table, and we know how that table is arranged.

Update this so that it actually uses a selector to the the 'HEX' table object and use that to process.

For example, it should be creating its labels based on values queried from inside an actual table object, not based on hardcoding HEX as the name of the table.

Likewise, add template labels to this screen that are based on template info found in the table object

Think about final UI design

Getting really close to having basic functionality -- adding objects, editing objects -- complete. Getting ready to start implementing secondary and more complex functionality: deleting objects, importing/exporting objects.

We really need to think about how we are going to expose all of these actions in the UI. My initial thinking was dropdown menus for secondary actions, but that doesn't seem like it would work well with the card-based UI we've selected.

Perhaps something more in-line with "correct" card UI, where actions are listed at the bottom?

image

Make terrain required and territory optional for hexes

For the various places where terrain and territory can be input for a hex (adder at the bottom of the Hexes screen, modal for bulk inputting hexes, editing a single hex), make it so that terrain is a required field and territory is an optional field.

This will require updating related handleChange validation, handleSubmit validation, etc.

We will also need to update reducers for tableEntries so that they only store a value in addTags if the value was given. (Note that addTags[0] corresponds to terrain, addTags[1] to territory).

In addition to just making more sense (ever hex should have a terrain, but isn't necessarily going to be part of anybody's territory) it also simplifies how we work with tableEntries.addTags. We'll no longer need to keep placeholder undefined values in that array if terrain was empty.

Update tables selectors to return "full" table objects

Would like to update the tables selectors so that they return more "full" tables. I.e. follow all references-by-id and insert the relevant data.

Especially important is getting full information on attached templates and their template plugins, as we'll need that information for displaying attached template tags.

Since tables reference templates and templates reference tables, need to be careful not to introduce any infinite loops.

Also update any view code that uses the returned data to make sure it still works.

Improve consistency of selector names

Our selector names are currently all over the place. Decide on a naming scheme and update selector names to match.

Suggest the following:

getByIdTables => returns a lookup object for all tables in the store. can lookup by ID. all tables are "full" -- all refefences-by-id are followed and details filled in.

Use this instead of getTablesById, which leads to confusion over whether its returning a lookup object or returning a single table for a provided ID

If we need a selector for querying a single object, use this naming schema:

getTableById => returns state.entities.tables.byId[given ID]. return object is "full" -- all references-by-id are followed and details filled in.

We should be able to remove any Full from the names, as the assumption should be that all selectors return a "full" object, i.e. one whose references-by-id have been followed and the details filled in.

Update documentation

Documentation around the schema has fallen a little out of data, mostly related to actual implementation of templates, template plugins, and books. Get it up-to-date.

Rethink the way we're handling state for editing template properties and metadata

We have an interesting situation with the EditTemplateModal. In order to know whether to enable the SAVE button, allow submission of changes, etc. the modal component needs to know whether all of the input in the modal is valid, including the template properties and metadata.

However, the structure of the properties and the metadata varies depending on which template plugin is being used. So the EditTemplateModal component cannot do validation of properties and metadata itself. We have to trust that task to the specific template plugin.

This leads to a situation where the parent component can't control the value props of the child component, but needs to know their state. The parent modal needs to know whether properties and metadata are in a "valid" state, and needs to know their values for when the modal submits. But actual control of those needs to be done in the child, because only the individual template plugin knows anything about the structure of that data, what fields to show, what values are needed, whether values are "valid", etc.

Right now, I'm working around this by having the template plugins updating both the usual, asynchronous local state, and a synchronously updated copy of the state. That copy is then sent up to the parent component via an onChange handler.

This feels like a hack though, and is probably not best practice for React. Let's do some research, find out what other people have done in this case in React, and possibly rework this. It is functional right now, but buts a lot of responsibility on the writer of template plugins to make sure they're updating everything in two different copies of the state.

Template Edit Modal

Create a modal for editing templates. The trickiest part of this is going to be the fact that the section for editing properties and the section for editing metadata are going to vary quite a bit depending on which template plugin is being used.

Do something similar to what we did with the template plugin "preview" -- store the actual function in the store under state.ui.templatePlugins..

Create "Inline Index" template plugin

Create a new template plugin for an "Inline Index". This will be similar to the existing "Index" template, except for each table entry, it will display text, entryDetails, and references all on a single line.

For now, can just implement the Preview, EditProperties, and EditMetadata parts of this. (We haven't implemented any finalization processing for template plugins yet.) The Preview will require some string manipulation trickery. We want to ensure that each text, entryDetail, and references item is separated by a period and single space. But we need to ensure we don't end up with, for example, two periods followed by a space, a space followed by a period followed by a space, a question mark followed by a period, followed by a space, etc.

The string manipulation that we use on the preview will also be used for the eventual finalization processing.

change handler for inputTemplateModal

Implement the change handler for the inputTemplateModal

Make sure there is no collision of the template name with existing template names. May require making a getByNameTemplates() selector.

Implement periodic persistence of state to file

It would be helpful if the project state was periodically persisted to a file. So, for example, if a user was to close the application without manually saving their file, the application would open exactly where they left off.

There appear to be React modules out there already that support this.

Implement "Save to File"

Implement a way of saving a project to a file. This will likely involve getting all "full" tables, tags, templates, books, etc. from the state via selectors, converting all of that to JSON, and writing to file.

Update all selectors so they take `state` instead of `stateEntities`, `stateTables`, etc.

Currently, most of our selectors take stateEntities as an argument, which points to entities in the redux store.

A major point of using selectors is to make sure the view needs to know as little bit about the underlying structure of the data store as possible. Asking the view containers to specify state.entities, state.entities.tables, or state.ui goes against that principle. The containers should only need to know about the state -- not what anything looks like under that. So they should only be able to pass state, and our selectors should be able to work from that.

Nothing is currently broken, but let's correct this as it's much better coding practice.

Update tables so they have an array of templates instead of a single template

We actually want our tables to be able to be attached to more than one template.

To accomplish this, we need to update the state.entities.tables schema (and all code that works with it) to have an array of templates instead of a single template.

This will include making sure we loop through the array of templates when displaying template labels, etc.

Templates should still be attached to only a single table, so state.entities.templates can remain unchanged.

Change widgets for BookContentSettings

In the BookContentSettings component, we are currently using a custom component where you click a pencil icon, it turns the current setting value into a dropdown, you select the value, it update the state, and the dropdown turns back into text of the new setting value.

It's nifty, but it doesn't work too well. Some weird bugs with it (mostly related to onBlur() not working as expected). We could try to fix those bugs, but instead, let's just use a straightforward Semantic <Form><Form.Group><Form.Select /></Form.Group></Form> for this. It will look good, be easy to understand, and functional.

Set up testing framework

New to Javascript, React, Redux, Electron development. Could really use help setting up a testing framework. Not looking for somebody to implement full test coverage of all existing components, reducers, etc. But help getting an automated testing framework and a couple examples of tests for components and reducers would be invaluable.

Create "Random Table" template plugin

Create a new template plugin for formatting tables as "Random Tables". You can see a mockup example at the bottom of the Templates screen. Basically, print each table entry on a single line. Only include the text for the table entry, not any template details. The number on the left of the table should be aggregating based on the weight of each item. Essentially, we're building a "you can roll dice against this" table.

For now, only need to implement the Preview, EditProperties, and EditMetadata for this plugin. (We have not implemented any finalization processors for any plugins yet.)

Implement deletion of hexes

On the hex screen, implement a method of clicking checkboxes to select multiple hexes, or clicking the checkbox at the top of the hex map to select all hexes. Then add an event handler on the "Delete Selected Hex[es]" option in the dropdown menu. This should delete all the selected hexes.

Deletion of the hexes should look like this from the perspective of the Redux store:

  • Set tableEntries.byId.id to "undefined" for each of the selected hexes
  • Remove the hex id from tableEntries.allIds
  • Do not delete any associated tags
  • Do update the terrainHexes and territoryHexes values of any tags to reflect any hexes being removed
  • Delete any entryDetailsGroup and associated entryDetails from any hexes that were overriding the global hex definition. In other words, if entryDetailsGroup is not HEX for the deleted hex, we will need to delete the entryDetails.

Books screen

Break down the Books screen mockup into smaller components. Will probably have BookCard components, BookSummary, BookConfiguration, etc.

Update EditMetadata for Index plugin so it displays lines using the selected formatting

Currently the EditMetadata component of the Index template plugin displays the entryDetails part of the metadata as a <List> component.

To make this easier to understand the effects of selecting different formatting options, update this so it displays each line using the actual, selected formatting option for that line, i.e. <h1>, <h2>, <p>, etc.

Update selectors.tables.getTables() so it doesn't filter out 'HEX'

Currently the selectors.tables.getTables() selector filters out any tables whose ID is 'HEX'. This is because we are using this selector on the tables screen and don't want to manage the 'HEX' table there. (We manage it on the Hexes screen instead).

To make this selector better do what we'd expect from the name, we really should have it return the 'HEX' table as well. I expect we'll want to use this selector at some point to operate on all tables, including 'HEX'.

Update this selector so it doesn't filter out 'HEX'. Also update the tables screen so the filtering out of 'HEX' happens there instead.

Name and fix-in-place the initial Book

Rename the initial Book 'Hex Book', change its ID to 'HEX' (for consistency with the rest of the store), and update the Book components so that this book cannot be renamed or have the 'HEX' template removed from the first position in the book.

Still allow other settings (page size, etc.) to be changed. Allow other templates to be added to the book.

Update books selectors so that this book appears first in the getBooks array.

Update regexes to support all Latin characters

In src/constats/regex.js there are currently a bunch of validation regexes that do checking on A-Za-z. I'd actually like to be able to support the full Latin charset (i.e. accented characters) in these. Need to figure out the proper regex for doing so.

Note: There are 2 places we do not want to support accented characters. The CODE on tables and the name of tags. Those should continue to allow only A-Za-z

Spike: Figure out how to create an auto-suggestion popup for CODEs and tags

When inputting result text for table entries, the expectation is that users will type things like:

There is a [[LANDMARK]] on the horizon

A [[RANDOM_ENCOUNTER:+night,-day]] is hidden in the darkness

Where [[LANDMARK]] means that the token will be replaced with the result of a random roll on the LANDMARK table. And +night,-day means that the night tag will be added to the filter chain and the day tag will be removed from the filter tag.

It would be really nice if we provided a list of auto-suggestions to users as they type.

e.g. They type A [[RAN, and we display a popup with all tables whose CODEs start with RAN. Or they've typed [[LANDMARK:+ni and we display a popup with all tags whose names start with ni. The user would be able to click on a suggestion to auto-complete the text.

As a reference, think how suggestions for emojis works in Slack.

handleSubmit for TemplateInputModal

Add a submit handler for TemplateInputModal. Gather the submitted template name, description, plugin, and table, dispatch them as an ADD_TEMPLATE action, create the reducers for adding them to the store.

Acceptance criteria should be that the new template appears on the Templates screen.

Document the crap out of everything

There's basically no documentation for this project. This makes it really hard for other people to work on it. At a minimum, document the following:

  • How to get the app running in a dev environment
  • How to package for production
  • What the data schema looks like
  • Expectations about how responsibilities are shared between actions, reducers, and selectors
  • The expected workflow of the app, i.e. what each screen does
  • What the intended final output of the application is

Integer inputs can't be blanked out

Input fields that are coded to only accept integer input -- mostly the weight and limit fields on the table entry screens -- are currently unable to be "blanked out"

Example:

Edit a table entry. If it's current weight is "1", you cannot backspace to delete the 1 in order to type in a different integer. The field does not allow itself to become blank.

(As a workaround, you can Select All on the field and overwrite the existing integer with a new one.)

Replace .map() with .forEach() where preferable

Downside of learning as I code: using some things incorrectly. There's a lot of places in code where I'm iterating over arrays using .map() where I should be using .forEach() (or maybe even .reduce()) instead. Basically, it's anyplace where I'm not actually trying to build a new array, I'm just trying to perform an action on each item in an array.

Fix this! Bad javascript abounds!

Remove input modification from Table Entry Modal

Currently, the Table Entry Modal does "input modification" on some of its fields. Example: The code field automatically capitalizes any letters that are entered (since we want the table CODE to always be all caps). However, there is an issue where input modification like this causes unexpected behavior with the input cursor. For example, if you try to insert new text in the middle of an existing input field, the cursor jumps to the end of the input after the first character is entered.

For now, disabled all "input modications" for input fields on the Table Entry Modal. For fields like CODE where we require the value to be all uppercase, ensure we perform .toUpperCase() before dispatching the value to any actions.

Add Book Modal

Create a modal, actions, and reducers for adding a new book.

Re-separate byId and allIds reducers for Tags

In general, most of the reducers for our data model are split into separate "byId" and "allIds" reducers to conform with Redux best practices for normalized data: https://redux.js.org/recipes/structuringreducers/updatingnormalizeddata

Example: To handle the state.entities.tables part of the schema, there is a tables.byId reducer that manages state.entities.tables.byId and an tables.allIds reducer that handles state.entities.tables.allIds

A while back, I had merged the byId and allIds reducers for tags. The thinking was that we would only know if we could remove a tag ID from state.entities.tags.allIds if we knew certain things about data stored inside the tag in state.entities.tags.byId. So I joined them to allow that information to be shared.

Now that I have changed the design so we delete tags only if a used manually clicks to delete one, there is no need for allIds to know anything about byIds when considering whether or not to remove a tag ID.

We should separate these into two separate reducers again to maintain consistency across the app.

Implement deletion of templates

We need a process for deleting templates. Probably this will take the form of a "Delete Template" button or drop-down menu option in the EditTemplateModal. It will also involve implementing the DELETE_TEMPLATE action across all relevant reducers. This includes the tables reducer, as we will need to remove references to the deleted table.

We should not allow the id = HEX template to be deleted.

Actions & reducers for "loading" objects

Make actions, action creators, and reducer for "loading" an object. E.g. We get a "full" table, tag, template, etc. from a file, load the object and all of its referenced objects into the state.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.