-
Notifications
You must be signed in to change notification settings - Fork 4
Switch RemoteXDA slices to Controllers using Generic Components #953
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
base: master
Are you sure you want to change the base?
Changes from all commits
61c6285
aad1067
16efe7c
94e3bdb
213e6b4
099a869
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ interface IProps<T extends U> { | |
| MinSelection?: number, | ||
| children?: React.ReactNode, | ||
| DisableConfirm?: boolean | ||
| Filters?: Search.IFilter<T>[] | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -64,8 +65,9 @@ export default function ControllerSelectPopup<T extends U>(props: IProps<T>) { | |
| }, [props.Selection]) | ||
|
|
||
| React.useEffect(() => { | ||
| setFilters([]); // initialize filter list, which should add additional filters | ||
| }, []) | ||
| if (props.Filters != null) setFilters(props.Filters) | ||
|
|
||
| else setFilters([]); // initialize filter list, which should add additional filters | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is necessary to make sure the Filters passed into ControllerSelectPopup are reflected in the Searchbar. Without this change, the Filters passed into ControllerSelectPopup aren't reflected in the Searchbar, even after different filters are added or removed.
Comment on lines
67
to
+69
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On master, Something like: const [searchFilters, setSearchFilters] = React.useState<Search.IFilter<T>[]>([]);
const baseFilters = useStringMemonization(props.BaseFilters ?? []);
const filters = React.useMemo(() => [...baseFilters, ...searchFilters], [baseFilters, searchFilters]);Then the |
||
| }, [props.Filters]) | ||
|
|
||
| function AddCurrentList() { | ||
| const updatedData = selectedData.concat(data); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //****************************************************************************************************** | ||
| // GenericInfo.tsx - Gbtc | ||
| // | ||
| // Copyright © 2026, Grid Protection Alliance. All Rights Reserved. | ||
| // | ||
| // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See | ||
| // the NOTICE file distributed with this work for additional information regarding copyright ownership. | ||
| // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this | ||
| // file except in compliance with the License. You may obtain a copy of the License at: | ||
| // | ||
| // http://opensource.org/licenses/MIT | ||
| // | ||
| // Unless agreed to in writing, the subject software distributed under the License is distributed on an | ||
| // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the | ||
| // License for the specific language governing permissions and limitations. | ||
| // | ||
| // Code Modification History: | ||
| // ---------------------------------------------------------------------------------------------------- | ||
| // 09/10/2026 - Natalie Beatty | ||
| // Generated original version of source code. | ||
| // | ||
| //****************************************************************************************************** | ||
|
|
||
| import * as React from 'react'; | ||
| import { ToolTip } from '@gpa-gemstone/react-forms'; | ||
| import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; | ||
| import { useRecordContext } from './RecordContext'; | ||
|
|
||
| interface IProps<T> { | ||
| /** | ||
| * Forms to display within the tab. | ||
| */ | ||
| Forms: Array<(record: T, setter: React.Dispatch<React.SetStateAction<T>>, setErrors: React.Dispatch<React.SetStateAction<string[]>>, setChanged: React.Dispatch<React.SetStateAction<string[]>>) => React.ReactNode> | ||
| /** | ||
| * Determine whether the user has permissions to edit the record. | ||
| */ | ||
| HasPermissions: () => boolean | ||
| } | ||
|
|
||
| /** | ||
| * A generic tab for record of type T for viewing and editing fields of the record. | ||
| * @param props | ||
| * @returns | ||
| */ | ||
| function GenericInfo<T,>({ | ||
| Forms, | ||
| HasPermissions | ||
| }: React.PropsWithChildren<IProps<T>>) { | ||
| const [hover, setHover] = React.useState<('None' | 'Clear' | 'Submit')>('None'); | ||
| const context = useRecordContext<T>(); | ||
|
|
||
| return ( | ||
| <div className="card" style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}> | ||
| <div className="card-header"> | ||
| <div className="row"> | ||
| <div className="col"> | ||
| <h4>{context.RecordType} Information:</h4> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| <div className="card-body" style={{ flex: 1, overflowY: 'auto' }}> | ||
| { | ||
| Forms.map((form) => { | ||
| return form(context.SelectedRecord, context.SetSelectedRecord, context.SetErrors, context.SetWarnings) | ||
| }) | ||
| } | ||
| </div> | ||
| <div className="card-footer"> | ||
| <div className="btn-group mr-2"> | ||
| <button className={"btn btn-primary" + (context.Warnings.length == 0 || context.Errors.length > 0 ? ' disabled' : '')} onClick={() => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if (context.Warnings.length > 0 && context.Errors.length == 0) { | ||
| context.Patch(); | ||
| } | ||
| }} | ||
|
Comment on lines
+70
to
+74
|
||
| onMouseEnter={() => setHover('Submit')} onMouseLeave={() => setHover('None')} data-tooltip={"Update"} | ||
| >Save Changes</button> | ||
| </div> | ||
| <ToolTip Show={hover == 'Submit' && context.Errors.length > 0} Position={'top'} Target={"Update"}> | ||
| {context.Errors.map((t, i) => <p key={`a_${i}`}><ReactIcons.CrossMark Color="var(--danger)" /> {t}</p>)} | ||
| </ToolTip> | ||
| <ToolTip Show={hover == 'Submit' && !HasPermissions()} Position={'top'} Target={"Update"}> | ||
| <p>Your role does not have permission. Please contact your Administrator if you believe this to be in error.</p> | ||
| </ToolTip> | ||
| <div className="btn-group mr-2"> | ||
| <button className="btn btn-warning" onClick={() => { | ||
| if (context.Warnings.length > 0) { | ||
| context.ClearChanges(); | ||
| } | ||
| } | ||
| } disabled={context.Warnings.length == 0} | ||
| onMouseEnter={() => setHover('Clear')} onMouseLeave={() => setHover('None')} data-tooltip={"Clr"} | ||
| >Clear Changes</button> | ||
| </div> | ||
| <ToolTip Show={hover == 'Clear' && context.Warnings.length > 0} Position={'top'} Target={"Clr"}> | ||
| {context.Warnings.map((t, i) => <p key={`a_${i}`}><ReactIcons.Warning Color="var(--warning)" /> {t}</p>)} | ||
| </ToolTip> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default GenericInfo; | ||
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.
GenericForm.tsxis added to the csproj here, but the file isn't in the PR.