Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TTAHUB-955] Generic Report #1523

Draft
wants to merge 937 commits into
base: main
Choose a base branch
from
Draft

Conversation

GarrettEHill
Copy link
Collaborator

Description of change

How to test

Issue(s)

Checklists

Every PR

  • Meets issue criteria
  • JIRA ticket status updated
  • Code is meaningfully tested
  • Meets accessibility standards (WCAG 2.1 Levels A, AA)
  • API Documentation updated
  • Boundary diagram updated
  • Logical Data Model updated
  • Architectural Decision Records written for major infrastructure decisions
  • UI review complete

Production Deploy

  • Staging smoke test completed

After merge/deploy

  • Update JIRA ticket status

JOIN "ValidFor" v
ON s."validForId" = v.id
AND v.name = 'collaborator'
WHERE s.name = 'approved' -- TODO: this is terminal, which could lock editing, but the others statuses make even less sense for events
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hardwarehuman The collaborator statusId should be left null for any non-approving user

src/constants.js Outdated Show resolved Hide resolved
@@ -305,6 +305,8 @@
"csv-parse": "^4.14.1",
"csv-stringify": "^5.6.2",
"cucumber-html-reporter": "^5.2.0",
"deepmerge": "^4.3.1",
"dot-wild": "^3.0.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dot-wild is a little worrying to me, there are security related issues on the repo and it hasn't been updated in 6 years

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more files down, I see it would be difficult to replace as it seems to be deeply intertwined with the approach we took here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://security.snyk.io/package/npm/dot-wild I don't see any vulnerabilities. What issues do you see?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It had not been updated in 6 years, agreed. But it works great.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewatermethod What concerns do you have other then it has not been touched in 6 years?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to this: wadackel/dot-wild#18

* @param value2 - The second value to compare.
* @returns True if the values are deeply equal, false otherwise.
*/
const isDeepEqual = (value1: any, value2: any): boolean => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lodash has this I think if you want to just use theirs

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"isEqual"

* @param value - The value to be checked.
* @returns A boolean indicating whether the value is an object or not.
*/
const isObject = (value: any): boolean => (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is equivalent to "isPlainObject" from lodash if we don't want to maintain our own (we're already using lodash all over the place, so it wouldn't be adding a dependency)


// Get the column information using the describe method
const getColumnInformation = async (model: typeof Model) => {
const tableDetails = await model.describe();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think this needs a try/catch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, what do you propose we do in the catch? Log, call the handleErrors, something else?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on whether you think it makes sense to return an empty array or blow up

model: typeof Model,
type,
) => {
const modelData = await getColumnInformation(model);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you think this needs a try/catch?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't iterate this question out for each of these functions, but same question for the rest of the stuff in this file, especially the ones that could have rejected promises in the middle, or ones with a bunch of second-level object property accessing.

Once this builds successfully, I'm also curious about the test coverage with all these nested if statements. It's possible some of this could be simplified if we find paths of code that are so unlikely as to not need tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great thought. I don't know. I have tests for some if it. But I don't know how to see coverage when I am still failing lint as a whole.

@thewatermethod
Copy link
Collaborator

Scanning ahead, I noticed a bunch of empty files - I'm assuming those aren't to be deleted (i.e. still a WIP)?

[DataTypes.JSON.key]: 'object',
[DataTypes.JSONB.key]: 'object',
[DataTypes.NOW.key]: undefined,
[DataTypes.BLOB.key]: undefined,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So these undefined mappings simply don't have a corresponding value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the list is all the types defined in the sequelize.DataTypes. but many are very rarely ever used in any context, and not in our context. The only one that is marked as unknow that we use on any table we use is DataType.ARRAY. To have a mapping for that I would also need to identify the type of the item in the array. So I think this is a not going to be as problem as all the tables in this PR don't use the array datatype.

* @param {string} input - The PascalCase string to convert.
* @returns {string} - The converted camelCase string.
*/
const pascalToCamelCase = (input) => (input
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_.camelCase(input)


const findAll = async (
data: { validFor: typeof ENTITY_TYPE[keyof typeof ENTITY_TYPE] },
) => genericEnum.findAll(Reasons, data);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many of these functions could be made generic, IE, we only need a separate findAll for reasons and status if they are doing something besides passing a model through.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, in this case, I believe the tablename should be Reason (singular)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a generic implementation, these functions call it. They pass into it the "unique" thing each needs. How would you change it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const findAll = async (
  model: ModelType, data: { validFor: typeof ENTITY_TYPE[keyof typeof ENTITY_TYPE] },
) => genericEnum.findAll(model, data);

etc

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discussed this on a call - clarified that what I'd really be after is no middleman function at all, IE we just call genericEnum.findAll where appropriate. Also stressed that it's a personal preference thing rather than a "make this change right now" kind of suggestion.

* */

//---------------------------------------------------------------------------------
await queryInterface.createTable('Foiaable', {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prob havent gotten there yet but how do we use Foiaable and validFor tables?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdamAdHocTeam
Foiaable table identifies which columns for which tables are "read-only" after the isFoiaable flag is set. This allows some values to still be updated while maintaining the integrity of other columns.

ValidFor is used in conjunction with many of the enum-esk tables to allow similar enums to be located in the same table. Like "Statuses" hold the valid statuses for Training Events, Training Sessions, Goals, Objectives, and Collaborators. So they all reside in the same table and have the mapsTo construct to allow extensibility without each requiring their own table.

Future-future plan would be to have an admin page to manage these enum-esk values. Think Audience, national centers, participants, reasons, roles, statuses, support types, target populations, and topics. Let them manage the values. Then the UI and data just run off the admin maintained data. Again, future-future plan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants