-
Notifications
You must be signed in to change notification settings - Fork 36
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
Add "default" initialize property to QCBX #6037
base: production
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! 🥳
My comments are primarily about code style, improving the code that was already there, and ways you could maybe make this even better for both dev and user if you wanted to.
Nothing strikes me as too pressing, and certainly not required (though still worth consideration hopefully).
Are you planning on adding automated tests to this PR, or will that be later? 👀
I'm a fan of the defaults, and I love the potential of the feature.
I find it a little unfortunate that we have to expose the concept of IDs to the user here: that will certainly require some documentation on the feature and won't be initially intuitive. Hopefully this is a feature that'll save users lots of time and configured infrequently!
@specify/ux-testing
Does this solve the most commonly reported use case for #3994?
Do most users have just a single record they want to set as default for a field?
specifyweb/frontend/js_src/lib/components/QueryComboBox/index.tsx
Outdated
Show resolved
Hide resolved
specifyweb/frontend/js_src/lib/components/QueryComboBox/index.tsx
Outdated
Show resolved
Hide resolved
@@ -61,6 +61,7 @@ export type FieldTypes = { | |||
readonly hasViewButton: boolean; | |||
readonly typeSearch: string | undefined; | |||
readonly searchView: string | undefined; | |||
readonly defaultRecordId: string | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(optional)
If it's possible, can you include the respected default values (CURRENT_USER, CURRENT_AGENT, and BLANK) into this type?
That way, the default values will be present when using Intellisense with this property.
And arguably even more helpful, if the feature needs to be expanded/worked-on in the future, including the defaults in the type definition provides another clear pathway to investigate the feature, an alternative to searching the Code/GitHub/Speciforum for the property name alone.
@@ -246,6 +247,7 @@ const processFieldType: { | |||
: getProperty('viewBtn')?.toLowerCase() === 'true', | |||
typeSearch: getProperty('name'), | |||
searchView: getProperty('searchView'), | |||
defaultRecordId: getProperty('defaultRecordId'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(just a note)
If desired, you can do whatever additional parsing here that you need!
For example, you can check if the value here is one of the defaults and if not, then try and parse it as an integer and otherwise return undefined.
That way, when working with defaultRecordId
later down the line, you already know if it's supposed to be converted to a resource_uri, is one of the defaults, etc.
If you do change how the defaultRecordId is parsed, don't forget to modify the type definition accordingly and other places it's used (like the syncer).
@@ -862,6 +862,7 @@ const queryComboBoxSpec = ( | |||
syncers.maybe(syncers.toBoolean), | |||
syncers.default<boolean>(true) | |||
), | |||
defaultRecordId: syncers.xmlAttribute('initialize defaultRecordId', 'skip'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(also a note, building on the above comment)
Whatever parsing behavior you implement in the form parsing code should also be reflected here in the Syncer as well (the Syncer is in charge of converting xml to json and vice-versa; for ease of use for visual editor).
One benefit of working with the Syncer is that it's also in charge of emitting errors to the user while they are using the CodeMirror text editor.
For example the following error when trying to render a to-many
relationship with a QueryComboBox:
Screen.Recording.2025-01-07.at.3.20.14.AM.mov
Is caused because of the following console.error statement on the QueryComboBox syncer!:
specify7/specifyweb/frontend/js_src/lib/components/FormEditor/viewSpec.ts
Lines 820 to 836 in c55f4dd
field: pipe( | |
rawFieldSpec(table).field, | |
syncer( | |
({ parsed, ...rest }) => { | |
if ( | |
parsed?.some( | |
(field) => field.isRelationship && relationshipIsToMany(field) | |
) | |
) | |
console.error( | |
'Unable to render a to-many relationship as a querycbx. Use a Subview instead' | |
); | |
return { parsed, ...rest }; | |
}, | |
(value) => value | |
) | |
), |
Maybe you want to check the value: is one of the defaults, the default is being used correctly1, a valid number and a record exists with the ID, etc.
Footnotes
-
We know CURRENT_AGENT and CURRENT_USER should only be used for relationships to Agent and Specifyuser (respectively): currently a user can technically use the defaults in any QueryComboBox ↩
Thanks for the in-depth review Jason!
I definitely want to give that a shot when I am back in the office.
Another idea @maxpatiiuk had in #3994 (comment) was to possibly use the record API url directly, and that would draw focus away from the ID itself. |
Separated Default QCBX logic
Triggered by 007ce67 on branch refs/heads/issue-3994-2
Fixes #3994
Adds ability for a QCBX to have a user-defined default selected record.
The following property on a QCBX can be set to a specify api uri:
initialize='default=/api/specify/agent/1/'
It can also be set to
CURRENT_AGENT
CURRENT_USER
BLANK
(Can be used to override hardcoded defaults, like with cataloger)Notes:
"currentSpecifyUserName"
under the hood, but I chose to go with the sp6 convention of all caps.Checklist
self-explanatory (or properly documented)
Testing instructions
default=/api/specify/TABLE/ID/
to the QCBX 'initialize' property. (Replace TABLE and ID)CURRENT_AGENT
, make sure it resolves to the agent belonging to the current logged-in user.CURRENT_USER
, make sure it resolves to the current logged-in user.BLANK
, make sure it no longer fills in the current agent.