Kinetic introduces a suite of opinionated admin tools that internal teams can use to manage and run their stores on Open Commerce.
Clone the project
git clone https://github.com/reactioncommerce/kinetic.git
Install pnpm
npm install -g pnpm
Go to the project directory
cd kinetic
Install dependencies
pnpm install
Start the server
pnpm run dev
To run this project, you will need to add API endpoint environment variable to your .env file. For example:
VITE_API_URL=http://localhost:3000/graphql
To run tests, run the following command
pnpm run test
Kinetic have a level of extensibility and allow users to add custom plugins as well as enable and disable built-in features.
- Create a new folder inside the pages directory, this folder should contain all of your plugin implementations.
- Define a new
RouteObject
inside the routes definition. - To add your plugin to the application sidebar, provide a custom sidebar props for
AppLayout
component inside the routes object.
Note: The AppLayout
component is used to render the Sidebar
, AppBar
, and PageLayout
. It all comes with a default value to render core features of Kinetic
Example:
// routes.tsx
{
// ... routes object
path: "/",
element:
<AppLayout
sidebar={{
plugins: [
{
text: "Plugins",
key: "plugins",
subItems: [
{
text: "Store Pickup",
icon: <AbcOutlined fontSize = "small" />,
to: "/pickup",
key: "storePickup"
}
]
}
]
}}
/>
}
- If you want to disable or custom a core feature in the sidebar, extends the
CORE_FEATURES
from theSidebar
component, modify it and apply to theAppLayout
. For example, we want to hide the default Orders from the core features and provide our custom Orders page
// routes.tsx
import { CORE_FEATURES, FEATURE_KEYS } from "@components/Sidebar";
{
// ... routes object
path: "/",
element:
<AppLayout
sidebar={{
coreFeatures: CORE_FEATURES.filter((sidebarItem) => sidebarItem.key !== FEATURE_KEYS.orders),
plugins: [
{
text: "Plugins",
key: "plugins",
subItems: [
{
text: "Custom Orders",
icon: <AbcOutlined fontSize = "small" />,
to: "/pickup",
key: "storePickup"
}
]
}
]
}}
/>
}
There is an example Customer plugin inside examples folder. We're going to disable the default customer feature and replace with this custom plugin.
All the features entry points are declared inside the routes file.
To include our custom plugin into the app, we need to declare the entry point in the routes file. Please modify the routes file:
// in routes.tsx
// ... other import statements
import SupportAgentIcon from "@mui/icons-material/SupportAgent";
import { CORE_FEATURES, FEATURE_KEYS, ItemProps } from "@components/Sidebar";
// import our feature as a lazy imported components for code splitting
const Customers = lazy(() => import("./examples/Customers"));
export const routes: RouteObject[] = [
{
// ... routes object
path: "/",
- element: <AppLayout/>,
// define custom plugin sidebar item and turn off default customer feature in the sidebar
element:
<AppLayout
sidebar={{
plugins: [{
text: "Plugins",
key: "custom-plugins",
subItems: [
{
key: "customers",
icon: <SupportAgentIcon fontSize="small"/>,
text: "Customers",
to: "plugins/customers"
}
]
}],
coreFeatures: CORE_FEATURES.filter((sidebarItem) => sidebarItem.key !== FEATURE_KEYS.customers)
}}
/>,
children: [
{
path: "plugins/customers",
element: <Customers />
},
// ... other routes,
]
}
]
Now, start the application and you will see the Customer option under the Plugins sidebar item. Click on that option and you should see the example custom plugin.
Every registered user belongs to a dedicated group with configured permissions (except the admin who is the first user of the system, this user is automatically assigned to multiple groups with special permissions). We can change the permissions of a group on the group setting page.
When you add custom pages, they are accessible to the users by default. To make them only accessible to users with proper permissions, you can use the PermissionGuard
component.
For example, only users with reading accounts permission can access the Customers page, add the permission check at the route level.
// in routes.tsx
// ... other import statements
import SupportAgentIcon from "@mui/icons-material/SupportAgent";
import { CORE_FEATURES, FEATURE_KEYS, ItemProps } from "@components/Sidebar";
import { PermissionGuard } from "@components/PermissionGuard";
const Customers = lazy(() => import("./examples/Customers"));
export const routes: RouteObject[] = [
{
// ... routes object
path: "/",
element:
<AppLayout
sidebar={{
plugins: [{
text: "Plugins",
key: "custom-plugins",
subItems: [
{
key: "customers",
icon: <SupportAgentIcon fontSize="small"/>,
text: "Customers",
to: "plugins/customers"
}
]
}],
coreFeatures: CORE_FEATURES.filter((sidebarItem) => sidebarItem.key !== FEATURE_KEYS.customers)
}}
/>,
children: [
{
path: "plugins/customers",
- element: <Customers />
element: <PermissionGuard permissions={["reaction:legacy:accounts/read"]}><Customers /></PermissionGuard>
},
// ... other routes,
]
}
]
Please note that, we can use PermissionGuard
at any level of the app to guard the UI components. Normally, we would want to add at the entry point in the route definition.
Alternatively, if you would prefer modifying the component itself, you can call the hook usePermission
in the custom page. For example, we want to enforce only users with adding accounts permission can see the Add
button in the customers page.
// in src/examples/Customers/index.tsx
// ... other import statements
import { usePermission } from "@components/PermissionGuard";
const Customers = () => {
const { pagination, handlePaginationChange } = useTableState();
const canAddCustomer = usePermission(["reaction:legacy:accounts/create"]);
...
return (
<Container maxWidth={false} sx={{ padding: "20px 30px" }}>
<TableContainer>
- <TableHeader title="Customers" action={<TableAction>Add</TableAction>}/>
<TableHeader title="Customers" action={canAddCustomer ? <TableAction>Add</TableAction> : undefined}/>
...
</TableContainer>
</Container>
);
};
We use the Developer Certificate of Origin (DCO) in lieu of a Contributor License Agreement for all contributions to Reaction Commerce open source projects. We request that contributors agree to the terms of the DCO and indicate that agreement by signing all commits made to Reaction Commerce projects by adding a line with your name and email address to every Git commit message contributed:
Signed-off-by: Jane Doe <[email protected]>
You can sign your commit automatically with Git by using git commit -s
if you have your user.name
and user.email
set as part of your Git configuration.
We ask that you use your real name (please no anonymous contributions or pseudonyms). By signing your commit you are certifying that you have the right have the right to submit it under the open source license used by that particular Reaction Commerce project. You must use your real name (no pseudonyms or anonymous contributions are allowed.)
We use the Probot DCO GitHub app to check for DCO signoffs of every commit.
If you forget to sign your commits, the DCO bot will remind you and give you detailed instructions for how to amend your commits to add a signature.
This Project is Apache 2.0 Licensed