Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions admin-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,6 @@
"./modules/quotation": {
"import": "./dist/modules/quotation.js"
},
"./modules/token": {
"import": "./dist/modules/token.js"
},
"./modules/warehousing-providers": {
"import": "./dist/modules/warehousing-providers.js"
},
Expand Down
21 changes: 19 additions & 2 deletions admin-ui/src/components/ui/form/ChoicesField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,24 @@ const ChoicesField = ({ multiple, options, ...props }: ChoicesFieldProps) => {
} = props;

const mappableValue =
typeof field.value === 'string' ? [field.value] : field.value;
typeof field.value === 'string'
? [field.value]
: Array.isArray(field.value)
? field.value
: [];

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (field.multiple) {
const clickedValue = event.target.value;
const newValues = event.target.checked
? [...mappableValue, clickedValue]
: mappableValue.filter((v) => v !== clickedValue);
field.setValue(newValues, true);
} else {
field.onChange(event);
}
};

const { className, hideLabel } = props;
return (
<div
Expand Down Expand Up @@ -67,7 +84,7 @@ const ChoicesField = ({ multiple, options, ...props }: ChoicesFieldProps) => {
disabled={field.disabled}
id={`${field.name}-${value}`}
name={field.name}
onChange={field.onChange}
onChange={handleChange}
type={field.multiple ? 'checkbox' : 'radio'}
/>
<span>{display}</span>
Expand Down
3 changes: 3 additions & 0 deletions admin-ui/src/components/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@ export {
ChartStyle,
} from './chart';
export type { ChartConfig } from './chart';

export { default as Table } from '../../modules/common/components/Table';
export { default as MediaAvatar } from '../../modules/common/components/MediaAvatar';
4 changes: 1 addition & 3 deletions admin-ui/src/modules/Auth/permissionConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,9 @@ export const checkAccess = (
pathname: string,
) => {
if (UNRESTRICTED_PAGES.includes(pathname)) return true;
if (pathname.startsWith('/ext/') || pathname === '/ext') return true;
if (!user?._id) return false;
if (user?.isGuest) return false;
if (pathname.startsWith('/ext/') || pathname === '/ext') {
return !!user?._id;
}
if (!ROUTE_ROLES[pathname]) {
if (process.env.NODE_ENV === 'development') {
console.warn(
Expand Down
19 changes: 19 additions & 0 deletions admin-ui/src/modules/accounts/components/LogInForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import useLoginWithPassword from '../hooks/useLoginWithPassword';
import useLoginWithWebAuthn from '../hooks/useLoginWithWebAuthn';
import { useCallback, useState } from 'react';
import useUnchainedContext from '../../UnchainedContext/useUnchainedContext';
import { usePlugins } from '../../plugins/PluginContext';

const GetCurrentStep = ({ step }) => {
const { formatMessage } = useIntl();
Expand Down Expand Up @@ -75,6 +76,11 @@ const LogInForm = () => {
const { logInWithPassword } = useLoginWithPassword();
const { loginWithWebAuthn } = useLoginWithWebAuthn();
const { singleSignOnURL } = useUnchainedContext();
const { manifests } = usePlugins();

const pluginLinks = manifests.flatMap(
(m) => (m.slots.links || []).filter((l) => l.showOnLoginPage),
);

const [step, setStep] = useState(1);

Expand Down Expand Up @@ -304,6 +310,19 @@ const LogInForm = () => {
</div>
</Form>
</FormWrapper>
{pluginLinks.length > 0 && (
<div className="mt-4 flex flex-wrap justify-center gap-3">
{pluginLinks.map((link) => (
<a
key={link.href}
href={link.href}
className="text-sm font-medium text-slate-950 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300"
>
{link.label} &rarr;
</a>
))}
</div>
)}
</div>
</div>
</>
Expand Down
2 changes: 1 addition & 1 deletion admin-ui/src/modules/apollo/utils/createApolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ const createApolloClient = ({
const apolloClient = new ApolloClient({
defaultOptions: {
watchQuery: {
fetchPolicy: 'cache-and-network',
errorPolicy: 'all',
fetchPolicy: 'cache-and-network',
},
},

Expand Down
12 changes: 11 additions & 1 deletion admin-ui/src/modules/common/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const LayoutContent = ({
skip: !hasRole(IRoleAction.ViewWorkQueue),
});

const isAuthenticated = !!currentUser?._id;
const { shopInfo } = useShopInfo();
const [hideNav, setHideNav] = useState(true);
const [narrowNav, setNarrowNav] = useState(false);
Expand Down Expand Up @@ -166,7 +167,6 @@ const LayoutContent = ({
_sortOrder: page.sortOrder as number | undefined,
});
});

if (children.length === 0) return [];

const nav = manifest.navigation;
Expand Down Expand Up @@ -380,6 +380,16 @@ const LayoutContent = ({
return 0;
});

if (!isAuthenticated) {
return (
<AuthWrapper>
<main className="container mx-auto max-w-7xl flex-1 px-4 py-5 pb-20 sm:px-6 md:px-8">
{React.cloneElement(children)}
</main>
</AuthWrapper>
);
}

return (
<AuthWrapper>
<CommandPalette />
Expand Down
84 changes: 50 additions & 34 deletions admin-ui/src/modules/common/components/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,38 @@ const ChildrenNav = ({ item, hasRole, onSelected, narrowView }) => {
</div>
{item.children
.filter((f) => !f?.requiredRole || hasRole(f.requiredRole))
.map((subItem) => (
<Link
key={subItem.name}
href={subItem.href}
className={clsx(
'block px-4 py-2 text-sm text-text-secondary hover:bg-surface-raised focus:outline-hidden focus:ring-2 focus:ring-focus-ring',
{
'bg-surface-raised text-text-primary':
router.pathname === subItem.href,
},
)}
onClick={() => {
setIsOpen(false);
onSelected?.();
}}
>
{subItem.name}
</Link>
))}
.map((subItem) => {
const className = clsx(
'block px-4 py-2 text-sm text-text-secondary hover:bg-surface-raised focus:outline-hidden focus:ring-2 focus:ring-focus-ring',
{
'bg-surface-raised text-text-primary':
router.pathname === subItem.href,
},
);
const handleClick = () => {
setIsOpen(false);
onSelected?.();
};
return subItem.external ? (
<a
key={subItem.name}
href={subItem.href}
className={className}
onClick={handleClick}
>
{subItem.name}
</a>
) : (
<Link
key={subItem.name}
href={subItem.href}
className={className}
onClick={handleClick}
>
{subItem.name}
</Link>
);
})}
</div>
</div>
)}
Expand Down Expand Up @@ -135,21 +148,24 @@ const ChildrenNav = ({ item, hasRole, onSelected, narrowView }) => {
<DisclosurePanel className="pl-6 space-y-1" onClick={onSelected}>
{item.children
.filter((f) => !f?.requiredRole || hasRole(f.requiredRole))
.map((subItem) => (
<Link
key={subItem.name}
href={subItem.href}
className={clsx(
'group flex w-full items-center rounded-md py-2 pl-5 pr-2 text-sm font-medium text-text-secondary hover:bg-surface-raised hover:text-text-primary focus:outline-hidden focus:ring-2 focus:ring-focus-ring',
{
'text-text-primary bg-surface-raised':
router.pathname === subItem.href,
},
)}
>
{subItem.name}
</Link>
))}
.map((subItem) => {
const className = clsx(
'group flex w-full items-center rounded-md py-2 pl-5 pr-2 text-sm font-medium text-text-secondary hover:bg-surface-raised hover:text-text-primary focus:outline-hidden focus:ring-2 focus:ring-focus-ring',
{
'text-text-primary bg-surface-raised':
router.pathname === subItem.href,
},
);
return subItem.external ? (
<a key={subItem.name} href={subItem.href} className={className}>
{subItem.name}
</a>
) : (
<Link key={subItem.name} href={subItem.href} className={className}>
{subItem.name}
</Link>
);
})}
</DisclosurePanel>
</>
)}
Expand Down
49 changes: 49 additions & 0 deletions admin-ui/src/modules/product/hooks/useProduct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,55 @@ const GetProductQuery = (inlineFragment = '') => gql`
__typename
}
}
... on TokenizedProduct {
texts {
_id
title
subtitle
description
}
contractConfiguration {
ercMetadataProperties
supply
}
simulatedStocks {
quantity
}
tokensCount
tokens {
_id
tokenSerialNumber
invalidatedDate
isInvalidateable
quantity
status
walletAddress
user {
_id
username
isGuest
primaryEmail {
address
verified
}
avatar {
_id
url
}
profile {
displayName
address {
firstName
lastName
}
}
lastContact {
emailAddress
telNumber
}
}
}
}
}
}
${ProductDetailFragment}
Expand Down
6 changes: 6 additions & 0 deletions admin-ui/src/modules/token/components/TokenList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const TokenList = ({ tokens }) => {
defaultMessage: 'Invalidated',
})}
</Table.Cell>
<Table.Cell>
{formatMessage({
id: 'token_cancelled',
defaultMessage: 'Cancelled',
})}
</Table.Cell>
</Table.Row>
{(tokens || []).map((token) => (
<TokenListItem token={token} key={token?._id} />
Expand Down
19 changes: 16 additions & 3 deletions admin-ui/src/pages/ext/[[...slug]].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import { usePlugins } from '../../modules/plugins/PluginContext';
import { PluginRuntimeProvider } from '../../modules/plugins/PluginRuntimeContext';
import PluginErrorBoundary from '../../modules/plugins/PluginErrorBoundary';
import useAuth from '../../modules/Auth/useAuth';
import useCurrentUser from '../../modules/accounts/hooks/useCurrentUser';
import Loading from '@/components/ui/Loading';

const PluginEntityPage = () => {
const router = useRouter();
const { slug } = router.query;
const { manifests, getComponent, loading } = usePlugins();
const { hasRole } = useAuth();
const { currentUser } = useCurrentUser();
const isAuthenticated = !!currentUser?._id;

if (loading) return <Loading />;

Expand All @@ -32,6 +35,10 @@ const PluginEntityPage = () => {
(e) => e.path.replace(/^\//, '') === pathStr,
);
if (entity) {
if (!isAuthenticated) {
router.replace('/log-in');
return <Loading />;
}
if (entity.requiredRole && !hasRole(entity.requiredRole)) {
router.replace('/403');
return <Loading />;
Expand Down Expand Up @@ -78,9 +85,15 @@ const PluginEntityPage = () => {
(p) => p.path.replace(/^\//, '') === pathStr,
);
if (page) {
if (page.requiredRole && !hasRole(page.requiredRole)) {
router.replace('/403');
return <Loading />;
if (page.requiredRole) {
if (!isAuthenticated) {
router.replace('/log-in');
return <Loading />;
}
if (!hasRole(page.requiredRole)) {
router.replace('/403');
return <Loading />;
}
}
const Component = getComponent(manifest.name, page.component);
if (Component)
Expand Down
Loading