- Notifications
You must be signed in to change notification settings - Fork16
Topcoder Admin App - Add Terms Management Final fix#1133
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:feat/system-admin
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Conversation
} | ||
.dialogLoadingSpinnerContainer { | ||
position: absolute; |
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.
Consider using a more descriptive class name for.dialogLoadingSpinnerContainer
to clearly indicate its purpose or context within the dialog.
left: 0; | ||
.spinner { | ||
background: none; |
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.
The.spinner
class currently only setsbackground: none;
. If there are additional styles needed for the spinner, consider adding them here for clarity and completeness.
const onSubmit = useCallback( | ||
(data: FormAddTermUser) => { | ||
props.doAddTermUser( | ||
data.handle?.value ?? 0, |
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.
Consider checking ifdata.handle
is defined before accessingvalue
andlabel
to avoid potential runtime errors.
onBlur={controlProps.field.onBlur} | ||
classNameWrapper={styles.inputField} | ||
disabled={props.isAdding} | ||
dirty |
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.
Thedirty
prop inFieldHandleSelect
is set to true, but it is not clear if this prop is necessary or used within the component. Verify if this prop is needed and remove it if it is not used.
placeholder?: string | ||
readonly value?: SelectOption | ||
readonly value?: SelectOption | null |
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.
Consider updating the type definition forvalue
toSelectOption | null
in any other related interfaces or components that might be affected by this change to ensure consistency across the codebase.
@@ -16,8 +16,9 @@ import styles from './FieldSingleSelectAsync.module.scss' | |||
interface Props { | |||
label?: string | |||
className?: string | |||
classNameWrapper?: string |
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.
Consider adding a description for the newclassNameWrapper
prop in the component's documentation or prop types to clarify its purpose and usage.
align-items: center; | ||
justify-content: center; | ||
height: 64px; | ||
left: $sp-8; |
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.
Consider using a more descriptive variable name instead of$sp-8
to improve readability and maintainability.
justify-content: center; | ||
height: 64px; | ||
left: $sp-8; | ||
bottom: $sp-8; |
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.
Consider using a more descriptive variable name instead of$sp-8
to improve readability and maintainability.
} | ||
@include ltelg { | ||
left: $sp-4; |
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.
Consider using a more descriptive variable name instead of$sp-4
to improve readability and maintainability.
@include ltelg { | ||
left: $sp-4; | ||
bottom: $sp-4; |
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.
Consider using a more descriptive variable name instead of$sp-4
to improve readability and maintainability.
*/ | ||
const onSubmit = useCallback( | ||
(data: FormAddTerm) => { | ||
const requestBody = _.pickBy(data, _.identity) |
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.
Consider adding error handling for thedoAddTerm
anddoUpdateTerm
functions to manage potential failures during the term addition or update process.
const agreeabilityTypeId = watch('agreeabilityTypeId') | ||
useEffect(() => { | ||
// check to enable/disable 'Docusign Template ID' and 'URL' fields |
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.
The useEffect dependency array should includegetValues
andsetValue
to ensure that the effect runs correctly when these functions change.
}, [agreeabilityTypeId]) | ||
useEffect(() => { | ||
if (termInfo) { |
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.
The useEffect dependency array should includereset
to ensure that the effect runs correctly when this function changes.
<Button | ||
primary | ||
onClick={function onClick() { | ||
setShowEditor(prev => !prev) |
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.
Consider using a more descriptive function name for theonClick
handler to improve readability and maintainability.
.fields { | ||
display: flex; | ||
gap: 15px; |
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.
Consider using a variable for thegap
value instead of a hardcoded15px
to maintain consistency and ease of updates across the stylesheet.
.blockBottom { | ||
display: flex; | ||
gap: 10px; |
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.
Consider using a variable for thegap
value instead of a hardcoded10px
to maintain consistency and ease of updates across the stylesheet.
.blockBottom { | ||
display: flex; | ||
gap: 10px; | ||
margin-top: 3px; |
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.
Consider using a variable for themargin-top
value instead of a hardcoded3px
to maintain consistency and ease of updates across the stylesheet.
label='Title' | ||
placeholder='Enter' | ||
tabIndex={0} | ||
onChange={_.noop} |
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.
TheonChange
prop is set to_.noop
, which means it does nothing. If this is intentional, consider removing it to avoid confusion.
secondary | ||
onClick={function onClick() { | ||
reset(defaultValues) | ||
setTimeout(() => { |
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.
ThesetTimeout
function is used without a delay parameter. If the intention is to executeonSubmit
asynchronously, consider specifying a delay or using a different approach to ensure clarity.
color: $blue-110; | ||
&:hover { | ||
color: $blue-110; |
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.
The&:hover
selector is setting the same color as the default link color. Consider using a different color for hover to provide visual feedback to users.
} | ||
.tableCell { | ||
white-space: break-spaces !important; |
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.
Using!important
can make the CSS harder to maintain. Consider refactoring the CSS to avoid using!important
if possible.
.tableCell { | ||
white-space: break-spaces !important; | ||
text-align: left !important; |
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.
Using!important
can make the CSS harder to maintain. Consider refactoring the CSS to avoid using!important
if possible.
totalPages: number | ||
page: number | ||
setPage: Dispatch<SetStateAction<number>> | ||
colWidth: colWidthType | 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.
Consider providing a default value forcolWidth
to avoid potential undefined behavior.
page: number | ||
setPage: Dispatch<SetStateAction<number>> | ||
colWidth: colWidthType | undefined | ||
setColWidth: Dispatch<SetStateAction<colWidthType>> | 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.
Consider providing a default value forsetColWidth
to avoid potential undefined behavior.
type: 'element', | ||
}, | ||
], | ||
// eslint-disable-next-line react-hooks/exhaustive-deps |
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.
The dependency array foruseMemo
is empty, which means the memoized value will never update. Ensure this is intentional, or consider adding dependencies if the columns need to update based on props or state changes.
...column, | ||
className: '', | ||
label: `${column.label as string} label`, | ||
mobileType: 'label', |
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.
The label for mobile columns is being suffixed with 'label'. Ensure this is the intended behavior, as it might lead to redundancy in the UI.
.fields { | ||
display: grid; | ||
grid-template-columns: repeat(4, minmax(0, 1fr)); | ||
gap: 15px 30px; |
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.
Consider using CSS variables or a pre-defined spacing variable for the gap values to maintain consistency across the application.
display: flex; | ||
justify-content: flex-end; | ||
align-items: flex-start; | ||
gap: 15px; |
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.
Consider using CSS variables or a pre-defined spacing variable for the gap values to maintain consistency across the application.
label='User Id' | ||
placeholder='Enter' | ||
tabIndex={0} | ||
onChange={_.noop} |
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.
TheonChange
handler is set to_.noop
, which means it does nothing. If this is intentional, consider removing theonChange
prop entirely to avoid confusion.
label='Handle' | ||
placeholder='Enter' | ||
tabIndex={0} | ||
onChange={_.noop} |
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.
Similar to the previous comment, theonChange
handler is set to_.noop
. If no action is needed on change, consider omitting this prop.
onClick={function onClick() { | ||
reset(defaultValues) | ||
setTimeout(() => { | ||
onSubmit(defaultValues) |
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.
ThesetTimeout
function is used without a delay parameter, which defaults to 0. This might be unnecessary if the intention is to executeonSubmit
immediately afterreset
. Consider removingsetTimeout
if no delay is needed.
} | ||
.tableCell { | ||
white-space: break-spaces !important; |
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.
Using!important
can make it difficult to override styles in the future. Consider if this is necessary or if the specificity of the selector can be increased instead.
.tableCell { | ||
white-space: break-spaces !important; | ||
text-align: left !important; |
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.
Using!important
can make it difficult to override styles in the future. Consider if this is necessary or if the specificity of the selector can be increased instead.
props.forceSelect(item.userId) | ||
}) | ||
} | ||
}, [isSelectAll, props.datas]) |
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.
Consider addingprops.forceUnSelect
andprops.forceSelect
to the dependency array oftoggleSelectAll
to ensure that the latest versions of these functions are used.
] | ||
}), | ||
[columns], | ||
) |
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.
Consider addingprops.isRemovingBool
andprops.isRemoving
to the dependency array ofcolumnsMobile
to ensure that the latest values are used.
// extend body ultra small and override it | ||
font-size: 14px; | ||
line-height: 19px; | ||
line-height: $error-line-height; |
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.
Theline-height
property is defined twice on this line. Consider removing the redundantline-height: 19px;
to avoid confusion and ensure consistency.
const elementRef = useRef<HTMLTextAreaElement>(null) | ||
const easyMDE = useRef<any>(null) | ||
/** |
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.
Consider specifying the type foreasyMDE
instead of usingany
to improve type safety and maintainability.
}, | ||
[], | ||
) | ||
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.
ThegetState
function uses a lot of string manipulation and regular expressions. Consider adding unit tests to ensure its correctness and robustness.
* Handle toggle block | ||
*/ | ||
const toggleBlock = useCallback( | ||
(editor: any, type: string, startChars: any, endCharsInput?: any) => { |
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.
ThetoggleBlock
function is complex and handles multiple cases. Consider breaking it down into smaller functions to improve readability and maintainability.
/** | ||
* Show hint after '@' | ||
*/ | ||
const completeAfter = useCallback((cm: CodeMirror.Editor) => { |
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.
ThecompleteAfter
function directly manipulates the editor content. Ensure that this behavior is well-tested to prevent unexpected side effects.
}, []) | ||
useOnComponentDidMount(() => { | ||
easyMDE.current = new EasyMDE({ |
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.
TheuseOnComponentDidMount
hook initializes theEasyMDE
editor. Ensure that the dependencies are correctly managed to prevent potential memory leaks or unexpected behavior.
uploadImage: false, | ||
}) | ||
easyMDE.current.codemirror.on('change', (cm: CodeMirror.Editor) => { |
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.
Consider adding error handling for thechange
andblur
events to gracefully handle any potential issues during these events.
@import '@libs/ui/styles/includes'; | ||
.form-input-textarea { | ||
@include font-roboto; |
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.
Thefont-roboto
mixin should be checked to ensure it is correctly imported and available in the context of this file. If it is not defined in the included files, this will cause a compilation error.
border: none; | ||
outline: none; | ||
resize: vertical; | ||
margin-left: calc(-1 * $border); |
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.
The use ofcalc(-1 * $border)
formargin-left
should be verified to ensure that$border
is defined and that this calculation results in the intended layout. If$border
is not defined or is not a numeric value, this could lead to unexpected behavior.
useEffect(() => { | ||
if (!initValue) { | ||
setInitValue(props.value as string) |
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.
ThesetInitValue
function is called only wheninitValue
is falsy, which means it will not update ifprops.value
changes after the initial render. Consider whether this behavior is intended or if you need to updateinitValue
wheneverprops.value
changes.
{...props} | ||
dirty={!!props.dirty} | ||
disabled={!!props.disabled} | ||
label={props.label || props.name} |
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.
Thelabel
prop defaults toprops.name
ifprops.label
is not provided. Ensure thatprops.name
is always a suitable fallback for the label, as it might not always be user-friendly.
@@ -16,14 +16,19 @@ | |||
display: flex; | |||
gap: 15px; | |||
justify-content: flex-end; | |||
flex-wrap: wrap; |
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.
Consider ifflex-wrap: wrap;
is necessary here. If the container's content is not expected to exceed the container's width, this property might be redundant.
@include ltemd { | ||
grid-template-columns: 1fr; | ||
display: flex; |
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.
Thedisplay: flex;
property is being set within the@include ltemd
media query. Ensure that this change is intended, as it overrides thedisplay: grid;
property set earlier. This could affect the layout significantly.
@@ -14,7 +14,7 @@ | |||
padding: $sp-4; | |||
} | |||
&.isPlatformPage { | |||
&.isPlatformGamificationAdminPage { |
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.
The class name change fromisPlatformPage
toisPlatformGamificationAdminPage
should be verified across the codebase to ensure that all references to this class are updated accordingly. This will prevent any potential styling issues due to mismatched class names.
@@ -1,11 +1,10 @@ | |||
import { FC, PropsWithChildren, useContext } from 'react' | |||
import cn from 'classnames' | |||
import { platformRouteId } from '~/apps/admin/src/config/routes.config' | |||
import {gamificationAdminRouteId,platformRouteId, rootRoute } from '~/apps/admin/src/config/routes.config' |
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.
The import statement forgamificationAdminRouteId
androotRoute
has been added, but it's not clear if these are used in the current file. Please ensure that all imported modules are utilized to avoid unnecessary imports.
import { ContentLayout } from '~/libs/ui' | ||
import { routerContext, RouterContextData } from '~/libs/core' | ||
import { platformSkillRouteId } from '~/apps/admin/src/platform/routes.config' | ||
import { AppSubdomain, EnvironmentConfig } from '~/config' | ||
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.
The import statement forAppSubdomain
andEnvironmentConfig
has been removed. Verify if these are no longer needed in the file, as removing them might affect the functionality if they were used elsewhere in the code.
@@ -39,8 +38,8 @@ export const Layout: FC<LayoutProps> = props => ( | |||
</ContentLayout> | |||
) | |||
export const PlatformLayout: FC<LayoutProps> = props => ( | |||
<Layout classes={{ mainClass: styles.isPlatformPage }}> | |||
export const PlatformGamificationAdminLayout: FC<LayoutProps> = props => ( |
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.
The component namePlatformGamificationAdminLayout
is quite long and may reduce readability. Consider using a shorter, more concise name if possible.
export constPlatformLayout: FC<LayoutProps> = props => ( | ||
<Layout classes={{ mainClass: styles.isPlatformPage }}> | ||
export constPlatformGamificationAdminLayout: FC<LayoutProps> = props => ( | ||
<Layout classes={{ mainClass: styles.isPlatformGamificationAdminPage }}> |
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.
Ensure thatstyles.isPlatformGamificationAdminPage
is defined in your styles module. If it is not, this could lead to runtime errors.
const skillManagementRouteId = EnvironmentConfig.SUBDOMAIN === AppSubdomain.admin | ||
? `/${platformRouteId}/${platformSkillRouteId}` | ||
: `/${AppSubdomain.admin}/${platformRouteId}/${platformSkillRouteId}` | ||
const platformBasePath = `${rootRoute}/${platformRouteId}/${gamificationAdminRouteId}` |
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.
The variableplatformBasePath
is declared but never used in the code. Consider removing it if it's not needed, or ensure it is used appropriately if it is required for functionality.
.startsWith(platformBaseRouteId.toLowerCase())) { | ||
return { Layout:PlatformLayout } | ||
.startsWith(platformBasePath.toLowerCase())) { | ||
return { Layout:PlatformGamificationAdminLayout } |
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.
The change fromPlatformLayout
toPlatformGamificationAdminLayout
should be verified to ensure that it aligns with the intended functionality of the terms management feature. Make sure thatPlatformGamificationAdminLayout
provides the necessary layout and components required for the admin interface.
@@ -20,6 +21,7 @@ export const PageWrapper: FC<PropsWithChildren<Props>> = props => ( | |||
<PageTitle>{props.pageTitle}</PageTitle> | |||
<PageHeader> | |||
<h3 className={styles.textTitle}>{props.pageTitle}</h3> | |||
{props.pageSubTitle} |
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.
Consider wrappingprops.pageSubTitle
in a conditional check to ensure it is not undefined or null before rendering. This will prevent potential rendering issues ifpageSubTitle
is not provided.
*/ | ||
const doUpdateTerm = useCallback( | ||
(data: Partial<FormAddTerm>, callBack: () => void) => { | ||
setIsAdding(true) |
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.
Suggestion
Consider using a more descriptive variable name instead of reusingisAdding
for the update operation. This can help improve code readability and avoid confusion, asisAdding
is also used in thedoAddTerm
function.
Example
You could introduce a new state variable likeisUpdating
for the update operation:
const[isUpdating,setIsUpdating]=useState(false);
And then use it in thedoUpdateTerm
function:
setIsUpdating(true);...setIsUpdating(false);
Reasoning
This change will make it clear that the state is specifically related to the update operation, rather than the add operation.
type: TermsActionType.FETCH_TERMS_INIT, | ||
}) | ||
let filter = `page=${pagRequest}&perPage=${TABLE_PAGINATION_ITEM_PER_PAGE}` | ||
if (filterCriteria?.searchKey) { |
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.
Consider usingconst
instead oflet
for thefilter
variable since it is not reassigned.
let filter = `page=${pagRequest}&perPage=${TABLE_PAGINATION_ITEM_PER_PAGE}` | ||
if (filterCriteria?.searchKey) { | ||
filter += `&title=${filterCriteria?.searchKey}` | ||
} |
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.
The optional chaining operator?.
is used twice onfilterCriteria?.searchKey
. The second usage is redundant because iffilterCriteria
is undefined, the first check will already prevent accessingsearchKey
.
type: TermsActionType.FETCH_TERMS_DONE, | ||
}) | ||
success() | ||
window.scrollTo({ left: 0, top: 0 }) |
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.
Thewindow.scrollTo
function is called with an object. Ensure that this behavior is intended and supported across all target browsers.
} from '../models' | ||
import { handleError } from '../utils' | ||
import { | ||
addUserTerm, |
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.
Consider renamingaddUserTerm
toaddTermUser
for consistency with other function names likeremoveTermUser
.
} | ||
| { | ||
type: typeof TermsActionType.FETCH_TERMS_USERS_DONE | ||
payload: { |
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.
The payload type here could be more specific. Consider defining a type for the payload to improve type safety and readability.
| typeof TermsActionType.REMOVE_TERMS_USERS_DONE | ||
| typeof TermsActionType.REMOVE_TERMS_USERS_INIT | ||
| typeof TermsActionType.REMOVE_TERMS_USERS_FAILED | ||
payload: number |
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.
The payload type here is a number, which is inconsistent with the other actions that use objects. Consider using a consistent structure for all action payloads.
const requestSuccess = (data: number[], totalPages: number): void => { | ||
dispatch({ | ||
payload: { | ||
data: data.map(item => ({ |
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.
Consider using a more descriptive variable name thanitem
to improve code readability.
&& filterCriteria?.userId.toString() | ||
.trim() | ||
) { | ||
filter += `&userId=${filterCriteria.userId}` |
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.
ThetoString().trim()
method chain is repeated multiple times. Consider extracting this logic into a utility function to improve code readability and maintainability.
if (filterCriteria?.handle && filterCriteria?.handle.trim()) { | ||
if ( | ||
filterCriteria?.userId |
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.
The conditionfilterCriteria?.userId && filterCriteria?.userId.toString().trim()
is repeated. Consider extracting this logic into a utility function or variable to avoid repetition.
) | ||
useEffect(() => { | ||
_.forEach(state.datas, termUser => { |
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.
The dependency array for thisuseEffect
is missing some dependencies likeloadUser
,setPage
, andreloadData
. Ensure all dependencies are included to avoid potential bugs.
@@ -99,6 +100,7 @@ export function useTableFilterBackend<T>( | |||
return { | |||
page, | |||
reloadData: doSearchDatas, |
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.
The functiondoSearchDatas
seems to be used here, but its definition or import is not visible in this diff. Ensure thatdoSearchDatas
is correctly defined or imported in the file to avoid runtime errors.
@@ -3,5 +3,13 @@ | |||
*/ | |||
export interface UserTerm { | |||
id: string | |||
legacyId: number |
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.
Consider using a consistent type for IDs. Ifid
is astring
, ensurelegacyId
andtypeId
are alsostring
unless there's a specific reason for them to benumber
.
title: string | ||
url: string | ||
agreeabilityTypeId: string |
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.
TheagreeabilityTypeId
is astring
, buttypeId
is anumber
. Ensure consistency in ID types unless there's a specific reason for the difference.
> => { | ||
const result = await xhrGetPaginatedAsync<{ | ||
result: number[] | ||
}>(`${EnvironmentConfig.API.V5}/terms/${termId}/users?${filter ?? ''}`) |
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.
The filter parameter is appended directly to the URL without any encoding. Consider usingencodeURIComponent
to ensure that the filter string is safely included in the URL.
@@ -20,14 +27,14 @@ import { FormAddSSOLoginData } from '../models/FormAddSSOLoginData.model' | |||
*/ | |||
export const getMemberSuggestionsByHandle = async ( | |||
handle: string, | |||
): Promise<Array<{ handle: string; userId: number }>> => { | |||
): Promise<Array<MemberInfo>> => { |
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.
The typeMemberInfo
should be defined or imported if not already done. Ensure thatMemberInfo
includes the propertieshandle
anduserId
as expected by the function.
@@ -38,13 +45,13 @@ export const getMemberSuggestionsByHandle = async ( | |||
*/ | |||
export const getMembersByHandle = async ( | |||
handles: string[], | |||
): Promise<Array<{ handle: string }>> => { | |||
): Promise<Array<MemberInfo>> => { |
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.
The return type of the function has been changed fromArray<{ handle: string }>
toArray<MemberInfo>
. Ensure that theMemberInfo
type is correctly defined and includes all necessary fields such ashandle
and any other fields expected from the API response.
*/ | ||
export const getProfile = async (handle: string): Promise<MemberInfo> => { | ||
if (!handle) { | ||
return Promise.reject(new Error('Handle must be specified.')) |
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.
The check for an empty handle should throw an error instead of returning a rejected promise. Consider usingthrow new Error('Handle must be specified.')
for better readability and consistency.
const result = await xhrGetAsync<ApiV3Response<MemberInfo>>( | ||
`${EnvironmentConfig.API.V3}/members/${handle}`, | ||
) | ||
return result.result.content |
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.
Consider adding error handling for thexhrGetAsync
call to manage potential network or API errors gracefully.
* @param units units | ||
* @returns file size | ||
*/ | ||
export function humanFileSize(inputBytes: number, units: string[]): string { |
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.
Consider adding input validation forinputBytes
andunits
to ensure they are of expected types and values. For example,inputBytes
should be a non-negative number, andunits
should be a non-empty array.
*/ | ||
export function humanFileSize(inputBytes: number, units: string[]): string { | ||
let bytes = inputBytes | ||
if (Math.abs(bytes) < 1024) { |
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.
The conditionMath.abs(bytes) < 1024
assumes thatunits
has at least one element. Consider adding a check to ensureunits
is not empty before accessingunits[0]
.
u += 1 | ||
} while (Math.abs(bytes) >= 1024 && u < units.length) | ||
return `${bytes.toFixed(1)}${units[u]}` |
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.
ThetoFixed(1)
method is used here, which will round the number to one decimal place. Consider whether this level of precision is appropriate for all use cases, or if it should be configurable.
FormUsersFilters, | ||
} from '../models' | ||
import { FormEditUserStatus } from '../models/FormEditUserStatus.model' | ||
import { FormAddRoleMembers } from '../models/FormAddRoleMembers.type' | ||
import { FormAddSSOLoginData } from '../models/FormAddSSOLoginData.model' | ||
import { FormAddTermUser } from '../models/FormAddTermUser.model' | ||
const docusignTypeId |
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.
The variabledocusignTypeId
is declared but not initialized properly. Consider usingconst docusignTypeId = EnvironmentConfig.ADMIN.AGREE_FOR_DOCUSIGN_TEMPLATE;
to ensure proper initialization.
*/ | ||
export const formAddTermUserSchema: Yup.ObjectSchema<FormAddTermUser> | ||
= Yup.object({ | ||
handle: Yup.object() |
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.
Thehandle
field is defined as an object, but the error message 'Handle is required.' might be misleading if the object itself is present but one of its properties is missing. Consider specifying which part of the handle is required in the error message.
label: Yup.string() | ||
.required('Label is required.'), | ||
value: Yup.number() | ||
.typeError('Invalid number.') |
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.
The error message 'Invalid number.' for thevalue
field might not be clear to users. Consider providing more context, such as 'Value must be a valid number.'
docusignTemplateId: Yup.string() | ||
.trim() | ||
.when('agreeabilityTypeId', (agreeabilityTypeId, schema) => { | ||
if (agreeabilityTypeId[0] === docusignTypeId) { |
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.
Consider checking ifagreeabilityTypeId
is an array before accessing its first element with[0]
. This will prevent potential runtime errors ifagreeabilityTypeId
is not an array.
.required('Type is required.'), | ||
url: Yup.string() | ||
.trim() | ||
.url('Invalid url.') |
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.
Theurl
validation should be required if the URL is a mandatory field. Consider changing.optional()
to.required('URL is required.')
if applicable.
className?: string | ||
} | ||
export const TermsAddPage: FC<Props> = (props: Props) => { |
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.
Consider using destructuring forprops
to directly extractclassName
. This can make the code cleaner and more readable. For example:export const TermsAddPage: FC<Props> = ({ className }) => {
} | ||
.removeSelectionButtonContainer { | ||
padding: 20px 0 30px $sp-8; |
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.
The padding value20px 0 30px $sp-8
mixes fixed pixel values with a variable$sp-8
. Consider using consistent units for padding values to maintain uniformity and scalability.
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
bottom: 50px; |
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.
Thebottom: 50px;
value is a fixed pixel measurement. Consider using a variable or relative unit to ensure responsiveness and adaptability across different screen sizes.
} | ||
export const TermsUsersPage: FC<Props> = (props: Props) => { | ||
const [showDialogAddUser, setShowDialogAddUser] = useState<boolean>() |
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.
Consider initializingshowDialogAddUser
with a default value likefalse
instead ofundefined
to avoid potential issues with undefined state.
export const TermsUsersPage: FC<Props> = (props: Props) => { | ||
const [showDialogAddUser, setShowDialogAddUser] = useState<boolean>() | ||
useAutoScrollTopWhenInit() | ||
const { id = '' }: { id?: string } = useParams<{ |
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.
The destructuring ofuseParams
could be simplified by directly usingconst { id = '' } = useParams();
without specifying the type again, as TypeScript can infer the type from the hook.
icon={PlusIcon} | ||
iconToLeft | ||
label='Add User' | ||
onClick={function onClick() { |
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.
TheonClick
function can be simplified by using an arrow function:onClick={() => setShowDialogAddUser(true)}
.
variant='danger' | ||
disabled={!hasSelected || isRemovingBool} | ||
size='lg' | ||
onClick={function onClick() { |
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.
TheonClick
function can be simplified by using an arrow function:onClick={() => doRemoveTermUsers(selectedDatasArray, unselectAll)}
.
{showDialogAddUser && termInfo && ( | ||
<DialogAddTermUser | ||
open | ||
setOpen={function setOpen() { |
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.
ThesetOpen
function can be simplified by using an arrow function:setOpen={() => { if (!isAdding) setShowDialogAddUser(false); }}
.
onBlur={() => setStateHasFocus(false)} | ||
onBlur={() => { | ||
setStateHasFocus(false) | ||
props.onBlur?.() |
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.
Consider adding a check to ensureprops.onBlur
is a function before calling it. This can prevent potential runtime errors ifonBlur
is not a function. For example, you could usetypeof props.onBlur === 'function' && props.onBlur()
.
@@ -156,6 +157,7 @@ const InputSelectReact: FC<InputSelectReactProps> = props => { | |||
backspaceRemovesValue | |||
isDisabled={props.disabled} | |||
filterOption={props.filterOption} | |||
isLoading={props.isLoading} |
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.
Consider providing a default value forprops.isLoading
to avoid potential issues if the prop is not passed. This can be done by setting a default value in the component's defaultProps or using a default parameter in the function signature.
@@ -10,7 +10,6 @@ | |||
outline: none; | |||
resize: vertical; | |||
margin-left: calc(-1 * $border); | |||
overflow: hidden; | |||
padding: $border; |
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.
Removingoverflow: hidden;
might cause the textarea to display scrollbars if the content exceeds the visible area. Ensure that this change aligns with the intended design and user experience for the textarea component.
@@ -5170,6 +5184,11 @@ | |||
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.7.tgz#400a76809fd08c2bbd9e25f3be06ea38c8e0a1d3" | |||
integrity sha512-eEAhnz21CwvKVW+YvRvcTuFKNU9CV1qH+opcgVK3pIMI6YZzDm6gc8o2vHjldFk6MGKt5pueSB7IOpvpx5Qekw== | |||
"@types/marked@^4.0.7": |
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.
It seems like a new entry for@types/marked@^4.0.7
has been added. Ensure that this addition is intentional and necessary for the project, as it might introduce changes in type definitions that could affect the codebase.
gap: 10px; | ||
} | ||
.fieldAreaContainer { |
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.
The new class.fieldAreaContainer
is added but not used in this diff. Ensure that it is utilized in the component or remove it if unnecessary.
import styles from './BundledEditor.module.scss' | ||
export const BundledEditor: FC<any> = (props: any) => ( |
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.
Usingany
as the type forprops
is not recommended because it defeats the purpose of TypeScript's type checking. Consider defining a specific type or interface for the props thatBundledEditor
expects.
@@ -0,0 +1,78 @@ | |||
import { FC, FocusEvent, useEffect, useRef, useState } from 'react' |
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.
TheuseRef
hook is imported but not used in the current code. If it's not needed, consider removing it to keep the imports clean.
import { FormInputAutocompleteOption, InputWrapper } from '~/libs/ui' | ||
import { BundledEditor } from './BundledEditor' |
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.
The import path for the editor component has changed from./Editor
to./BundledEditor
. Ensure thatBundledEditor
provides the same functionality or intended improvements over the previousEditor
component.
const FieldHtmlEditor: FC<FieldHtmlEditorProps> = ( | ||
props: FieldHtmlEditorProps, | ||
) => { | ||
const editorRef = useRef<any>(null) |
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.
Usingany
for theeditorRef
type can lead to potential type safety issues. Consider specifying a more precise type for the ref, such asReact.RefObject<EditorType>
whereEditorType
is the expected type of the editor instance.
hideInlineErrors={props.hideInlineErrors} | ||
> | ||
<BundledEditor | ||
onInit={function onInit(_evt: any, editor: any) { |
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.
Consider specifying the types for_evt
andeditor
instead of usingany
to improve type safety.
onInit={function onInit(_evt: any, editor: any) { | ||
(editorRef.current = editor) | ||
}} | ||
onChange={function onChange() { |
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.
TheonChange
function does not use the_evt
parameter. Consider removing it if it's not needed.
+ '}', | ||
height: 400, | ||
menubar: false, | ||
plugins: ['table', 'link', 'textcolor', 'contextmenu'], |
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.
Thesource_view
option is not a valid TinyMCE configuration option. Consider removing or correcting it.
import 'tinymce/skins/ui/oxide/skin' // Editor styles | ||
import 'tinymce/skins/content/default/content' // Content styles, including inline UI like fake cursors | ||
import 'tinymce/skins/ui/oxide/content' | ||
import 'tinymce/plugins/table/plugin.min.js' |
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.
Thetable
plugin import has been moved but not commented out. Ensure this change is intentional and that the plugin is still required.
import 'tinymce/skins/content/default/content' // Content styles, including inline UI like fake cursors | ||
import 'tinymce/skins/ui/oxide/content' | ||
import 'tinymce/plugins/table/plugin.min.js' | ||
import 'tinymce/plugins/link/plugin.min.js' |
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.
Thelink
plugin import has been moved but not commented out. Verify if this change is necessary and that the plugin is still needed.
import 'tinymce/skins/ui/oxide/content' | ||
import 'tinymce/plugins/table/plugin.min.js' | ||
import 'tinymce/plugins/link/plugin.min.js' | ||
// import 'tinymce/plugins/advlist/plugin.min.js' // importing the plugin js. |
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.
Consider removing the commented-out imports if they are no longer needed to keep the code clean and maintainable.
https://www.topcoder.com/challenges/1acf18a6-af38-4583-9c37-d2fc18d23fa1