Skip to content

Commit

Permalink
Icon cosmetic fixes and avatar component (#778)
Browse files Browse the repository at this point in the history
* remove exception exposure in profile views

* use composition (with mixins) instead of inheritence to implement to_representation method and remove black fields

* fix manifest router url patterns

* fix styles for icons

* add avatar component

* use avatar component in profile feature
  • Loading branch information
dpgraham4401 authored Aug 23, 2024
1 parent 802318e commit cda3bc5
Show file tree
Hide file tree
Showing 21 changed files with 175 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function ManifestCancelBtn() {
}}
>
<span>Cancel </span>
<FaTrash />
<FaTrash className="tw-inline" />
</HtButton>
);
}
2 changes: 1 addition & 1 deletion client/app/components/Manifest/Actions/ManifestEditBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function ManifestEditBtn({ children: _unused, ...props }: ManifestEditBtn
return (
<HtButton {...props} variant="info" type="button" name="edit" onClick={handleClick}>
<span>Edit </span>
<FaPenToSquare />
<FaPenToSquare className="tw-inline" />
</HtButton>
);
}
2 changes: 1 addition & 1 deletion client/app/components/Manifest/Actions/ManifestSaveBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function ManifestSaveBtn({ children: _unused, ...props }: ManifestSaveBtn
return (
<HtButton variant="success" type="submit" name="save" {...props}>
<span>Save </span>
<FaFloppyDisk />
<FaFloppyDisk className="tw-inline" />
</HtButton>
);
}
10 changes: 5 additions & 5 deletions client/app/components/RcraSite/RcraSiteDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ export function RcraSiteDetails({ handler }: RcraSiteDetailsProps) {
<Col>
<div className="mb-0">
<p className="fw-bold">
Can e-Sign:{' '}
<span>Can e-Sign: </span>
{handler.canEsign ? (
<FaCircleCheck className="text-success align-text-bottom" />
<FaCircleCheck className="text-success align-text-bottom tw-inline" />
) : (
<FaCircleXmark className="text-danger align-text-bottom" />
<FaCircleXmark className="text-danger align-text-bottom tw-inline" />
)}
</p>
</div>
<p className="fw-bold">
Has registered e-Manifest user:{' '}
{handler.hasRegisteredEmanifestUser ? (
<FaCircleCheck className="text-success align-text-bottom" />
<FaCircleCheck className="text-success align-text-bottom tw-inline" />
) : (
<FaCircleXmark className="text-danger align-text-bottom" />
<FaCircleXmark className="text-danger align-text-bottom tw-inline" />
)}
</p>
</Col>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ export function SyncManifestBtn({
if (siteId) syncSiteManifest(siteId);
}}
>
{`Sync Manifest `}
<FaSync className={syncInProgress ? 'tw-spin' : ''} />
<span>Sync Manifest </span>
<FaSync className={syncInProgress ? 'tw-spin tw-inline' : 'tw-inline'} />
</RcraApiUserBtn>
);
}
19 changes: 11 additions & 8 deletions client/app/components/User/UserInfoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { zodResolver } from '@hookform/resolvers/zod';
import React, { createRef, useState } from 'react';
import { Button, Col, Form, Row } from 'react-bootstrap';
import { useForm } from 'react-hook-form';
import { FaUser } from 'react-icons/fa';
import { z } from 'zod';
import { HtForm } from '~/components/legacyUi';
import { Spinner } from '~/components/ui';
import { Avatar, AvatarFallback, AvatarImage, Spinner } from '~/components/ui';
import { HaztrakUser, ProfileSlice, useUpdateUserMutation } from '~/store';
import { FaUser } from 'react-icons/fa';

interface UserProfileProps {
user: HaztrakUser;
Expand Down Expand Up @@ -53,12 +53,15 @@ export function UserInfoForm({ user }: UserProfileProps) {
<Row>
<Col>
<div className="avatar-container d-flex justify-content-center">
<Button
onClick={() => fileRef.current?.click()}
className="bg-secondary rounded-circle border-0 shadow"
>
<FaUser size={32} className="m-3" />
</Button>
<button onClick={() => fileRef.current?.click()}>
<Avatar className="tw-h-40 tw-w-40">
{/* ToDo: pipe dream, we currently do not use avatar iamges */}
<AvatarImage src="" alt="avatar" />
<AvatarFallback>
<FaUser size={80} />
</AvatarFallback>
</Avatar>
</button>
</div>
<div className="d-flex justify-content-center">
<h2>{user.username}</h2>
Expand Down
8 changes: 4 additions & 4 deletions client/app/components/legacyUi/HtPaginate/HtPageBtns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export function HtPageBtns<T>({ table }: HtPageBtnsProps<T>) {
onClick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
>
<FaBackwardFast size={'lg'} />
<FaBackwardFast size={16} />
</Pagination.First>
<Pagination.Prev onClick={table.previousPage} disabled={!table.getCanPreviousPage()}>
<FaCaretLeft size={'lg'} />
<FaCaretLeft size={16} />
</Pagination.Prev>

{paginationRange.map((pageNumber, index) => {
Expand All @@ -58,13 +58,13 @@ export function HtPageBtns<T>({ table }: HtPageBtnsProps<T>) {
);
})}
<Pagination.Next onClick={table.nextPage} disabled={!table.getCanNextPage()}>
<FaCaretRight size="lg" />
<FaCaretRight size={16} />
</Pagination.Next>
<Pagination.Last
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
disabled={!table.getCanNextPage()}
>
<FaForwardFast size="lg" />
<FaForwardFast size={16} />
</Pagination.Last>
</Pagination>
</div>
Expand Down
8 changes: 4 additions & 4 deletions client/app/components/legacyUi/HtTooltip/HtTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactElement } from 'react';
import { forwardRef, ReactElement, Ref } from 'react';
import { OverlayTrigger, Tooltip, TooltipProps } from 'react-bootstrap';
import { FaInfoCircle } from 'react-icons/fa';

Expand All @@ -9,14 +9,14 @@ interface HtToolTipProps extends TooltipProps {
children: ReactElement;
}

export function HtTooltip(props: HtToolTipProps): ReactElement {
export const HtTooltip = forwardRef<Ref<any>, HtToolTipProps>((props, _ref) => {
const { children, text, ...rest } = props;
return (
<OverlayTrigger {...rest} delay={{ show: 250, hide: 400 }} overlay={<Tooltip>{text}</Tooltip>}>
{children}
</OverlayTrigger>
);
}
});

interface InfoTooltipProps {
message: string;
Expand All @@ -30,7 +30,7 @@ interface InfoTooltipProps {
export function InfoIconTooltip({ message }: InfoTooltipProps) {
return (
<HtTooltip text={message}>
<FaInfoCircle size={'2xs'} className={'pb-1 text-muted'} />
<FaInfoCircle size={12} className="text-muted tw-inline tw-align-top " />
</HtTooltip>
);
}
17 changes: 17 additions & 0 deletions client/app/components/ui/Avatar/Avatar.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { render } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { Avatar } from './Avatar';

describe('Avatar component', () => {
it('renders with default props', () => {
const { container } = render(<Avatar />);
expect(container.firstChild).toHaveClass(
'tw-relative tw-flex tw-h-10 tw-w-10 tw-shrink-0 tw-overflow-hidden tw-rounded-full'
);
});

it('applies additional class names', () => {
const { container } = render(<Avatar className="custom-class" />);
expect(container.firstChild).toHaveClass('custom-class');
});
});
48 changes: 48 additions & 0 deletions client/app/components/ui/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react';
import * as AvatarPrimitive from '@radix-ui/react-avatar';

import { cn } from '~/lib/utils';

const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
'tw-relative tw-flex tw-h-10 tw-w-10 tw-shrink-0 tw-overflow-hidden tw-rounded-full',
className
)}
{...props}
/>
));
Avatar.displayName = AvatarPrimitive.Root.displayName;

const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn('tw-aspect-square tw-h-full tw-w-full', className)}
{...props}
/>
));
AvatarImage.displayName = AvatarPrimitive.Image.displayName;

const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
'tw-flex tw-h-full tw-w-full tw-items-center tw-justify-center tw-rounded-full tw-bg-muted',
className
)}
{...props}
/>
));
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;

export { Avatar, AvatarImage, AvatarFallback };
8 changes: 4 additions & 4 deletions client/app/components/ui/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as React from 'react';
import { cn } from '~/lib/utils';

const buttonVariants = cva(
'tw-text-md tw-inline-flex tw-items-center tw-justify-center tw-whitespace-nowrap tw-font-medium tw-ring-offset-background tw-transition-colors focus-visible:tw-outline-none focus-visible:tw-ring-2 focus-visible:tw-ring-ring focus-visible:tw-ring-offset-2 disabled:tw-pointer-events-none disabled:tw-opacity-50',
'tw-text-md tw-inline-flex tw-items-center tw-justify-center tw-whitespace-nowrap tw-p-2 tw-font-medium tw-ring-offset-background tw-transition-colors focus-visible:tw-outline-none focus-visible:tw-ring-2 focus-visible:tw-ring-ring focus-visible:tw-ring-offset-2 disabled:tw-pointer-events-none disabled:tw-opacity-50',
{
variants: {
variant: {
Expand All @@ -18,9 +18,9 @@ const buttonVariants = cva(
link: 'tw-text-primary tw-underline-offset-4 hover:tw-underline',
},
size: {
default: 'tw-h-10 tw-px-4 tw-py-2',
sm: 'tw-h-9 tw-rounded-md tw-px-3',
lg: 'tw-h-11 tw-rounded-md tw-px-8',
default: 'tw-h-10',
sm: 'tw-h-9 tw-px-3',
lg: 'tw-h-11 tw-px-8',
icon: 'tw-h-10 tw-w-10',
},
rounded: {
Expand Down
2 changes: 2 additions & 0 deletions client/app/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ export {
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './Card/Card';

export { Spinner } from './Spinner/Spinner';

export { Avatar, AvatarImage, AvatarFallback } from './Avatar/Avatar';
31 changes: 29 additions & 2 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@formkit/auto-animate": "^0.8.2",
"@hookform/error-message": "^2.0.1",
"@hookform/resolvers": "^3.7.0",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
Expand Down
9 changes: 0 additions & 9 deletions server/manifest/serializers/handler_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from rcrasite.serializers import RcraSiteSerializer
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from manifest.models import Handler, ManifestPhone, Transporter

Expand Down Expand Up @@ -95,11 +94,3 @@ class Meta:
"electronicSignaturesInfo",
"signed",
]

def to_internal_value(self, data):
"""Move fields related to rcra_site to an internal rcra_site dictionary."""
try:
internal = super().to_internal_value(data)
return internal
except ValidationError as exc:
raise exc
33 changes: 6 additions & 27 deletions server/manifest/serializers/manifest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from typing import Dict, override
from typing import Dict

from rcrasite.models import RcraStates
from rest_framework import serializers
Expand All @@ -18,33 +18,12 @@
TransporterSerializer,
)

logger = logging.getLogger(__name__)


class ManifestBaseSerializer(serializers.ModelSerializer):
def remove_empty_fields(self, data):
"""Remove empty fields when serializing"""
for field in self.fields:
try:
if data[field] is None:
data.pop(field)
except KeyError:
pass
return data
from .mixins import RemoveEmptyFieldsMixin

@override
def to_representation(self, instance):
data = super().to_representation(instance)
return self.remove_empty_fields(data)

def __str__(self):
return f"{self.__class__.__name__}"

def __repr__(self):
return f"<{self.__class__.__name__}({self.data})>"
logger = logging.getLogger(__name__)


class AdditionalInfoSerializer(ManifestBaseSerializer):
class AdditionalInfoSerializer(RemoveEmptyFieldsMixin, serializers.ModelSerializer):
originalManifestTrackingNumbers = serializers.JSONField(
allow_null=True,
required=False,
Expand Down Expand Up @@ -84,7 +63,7 @@ class Meta:
)


class ManifestSerializer(ManifestBaseSerializer):
class ManifestSerializer(RemoveEmptyFieldsMixin, serializers.ModelSerializer):
"""Manifest serializer"""

createdDate = serializers.DateTimeField(
Expand Down Expand Up @@ -276,7 +255,7 @@ class Meta:
]


class PortOfEntrySerializer(ManifestBaseSerializer):
class PortOfEntrySerializer(RemoveEmptyFieldsMixin, serializers.ModelSerializer):
"""
Serializer for Port Of Entry
"""
Expand Down
Loading

0 comments on commit cda3bc5

Please sign in to comment.