Frontend
This document is still under development.
This documentation is primarily intended for software developers.
First things first, the GitHub repository can be found here, the Gropius component for issue tracking can be found here.
Technology Stack
- JavaScript Framework: Vue
- Programming Languages: mainly TypeScript and standard HTML within Vue components
- UI Library: Vuetify
- Package Manager: Yarn -- Instructions for the most important yarn commands can be found in the README.md in the repository.
- Tooling: ESLint, Prettier, GraphQL Codegen
Repository Structure
/src/
: The source codeassets/
: assets to include in the website. Currently unused.components/
: Single-File Components that can be reused -- this is basically an internal UI components library.graphql/
: Source code files that form the GraphQL client for the calls to the gateway.layouts/
: SFCs responsible for the general layout of a page of the web application.plugins/
: Source code related to the plugins of the web application: Vuetify, Vue Router, and Pinia.router/
: The app-specific logic of the router is implemented here, enabling navigation between the many views.store/
: The Pinia store manages the state of the application, including data and UI state, in a centralized and reactive manner, facilitating state manipulation and sharing across components.strings/
: The string resources of the application, such as error messages.styles/
: Files dedicated to styling the web application -- this has been left untouched since the initialization of the repository.util/
: Utility source code.views/
: SFCs, each of which represents a single web page and therefore a route of the Vue Router.
Files That Play An Important Role
codegen.yaml
src/graphql/client.ts
src/router/index.ts
src/store/app.ts
src/util/errorHandler.ts
src/layouts/default/TheDefaultLayout.vue
Hierarchy Of The Layout Components
src/layouts/default/TheDefaultLayout.vue
src/layouts/default/TheAppBar.vue
- ...
src/layouts/default/TheViewPlaceHolder.vue
v-main
router-view
src/components/Notifications.vue
The Vue Router places the current route's view (one of the views in src/views
) into router-view
.
Some remarks regarding the aforementioned components:
- Each page is an instance of src/layouts/default/TheDefaultLayout.vue.
- The default layout comprises the app bar, two navigation drawers (one left, one right), and a placeholder for the actual view.
src/components/Notifications.vue
serves as the notification center of the application and only becomes visible when a notification is pushed to the user.- The Vue Router maps routes to
src/views
and places the current route's view into the router-view component.
Important Components
The most important components are:
- The Pinia store
- The GraphQL client
- The error handler
The Pinia store
The role of the Pinia Store in Vue is to manage the state of the application in a centralized and reactive manner, facilitating state manipulation and sharing across components.
The store manages:
- login state
- the active user role
- the user's shopping cart
- the notification queue
The GraphQL client
- GraphQL queries and mutations can be found in the
.graphql
files where the name of the file is one of the bounded contexts of the microservice landscape. For example, ´catalog.graphql` contains the queries and mutations for calling the catalog service. src/graphql/generated.ts
has to be generated by runningyarn codegen
; based oncodegen.yaml
, the file then gets generated.src/graphql/client.ts
resembles the interface to make calls to the Gateway via its functionuseClient()
. The following code snippet taken fromsrc/views/ProductView.vue
shows how to useuseClient()
:
/**
* The GraphQL client to use for all GraphQL requests.
*/
const client = useClient();
/**
* Gets the "entire" product from the catalog service.
*/
const product = asyncComputed(
async () => {
return client.getProduct({
id: id.value
});
},
null,
{
onError: (e) => pushErrorNotification(errorMessages.getProduct, e),
shallow: false
}
);
Note that the GraphQL query "behind" getProduct()
has been defined in src/graphql/catalog.graphql
.
The error handler
src/util/errorHandler.ts
provides intuitive helper functions for wrapping synchronous as well as asynchronous actions into try-catch
blocks in order to push an error notification if the actions fails.
/**
* Requests the restocking of the selected product variant.
*/
async function restock() {
if (activeUserRoleIsEitherAdminOrEmployee.value && canRestock) {
await awaitActionAndPushErrorIfNecessary(() => {
return client.createProductItemBatch({
input: {
productVariantId: selectedProductVariantId.value,
number: parseInt(amount.value as string),
},
})
}, errorMessages.createProductItemBatch)
emit('restocked')
}
}
In this code example awaitActionAndPushErrorIfNecessary()
(one of the error handler's functions) is called with two arguments:
- the asynchronous action
- the error message if the action fails: errorMessages.createProductItemBatch
Whenever the failure of a function call should be communicated to the user, use one of the error handler's functions.
Technical Debt
This section is written from the personal perspective of the main frontend developer during the time of the EnPro.
Sadly, there is already some technical debt. Why? Because at the beginning of the project I was still a complete beginner when it came to frontend development with Vue, TypeScript, and JavaScript in general. Some things I only understood and learned to use properly over time meaning issue by issue. As we did not have the time to refactor everything as soon as possible, we had to prioritize the implementation of additional features to ensure that the frontend would be at least somehow feature-complete at the end of the project.
Having said this, what kind of technical debt are we talking about?
- Clones regarding the composition of smaller UI components. That means more custom SFCs could be extracted from the given DOM landscape.
- A slight overuse of
v-if
within SFCs instead of making good use of Vue's slot mechanism. See this Gropius issue. - Using events instead of custom models. See this Gropius issue.
- "Many" dialogs have been implemented by now and the coding style regarding source code file structure, member naming, and event handling has deviated over time.
Coding Guidelines
- Every
const
variable orref
,interface
(or similar construct), as well as everyfunction
, must be accompanied by a JSDoc comment.