https://github.com/absaoss/inception
https://github.com/absaoss/inception
Last synced: 10 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/absaoss/inception
- Owner: AbsaOSS
- License: apache-2.0
- Created: 2021-08-27T09:51:46.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-02-28T08:47:02.000Z (almost 4 years ago)
- Last Synced: 2024-04-26T19:03:48.480Z (almost 2 years ago)
- Language: Java
- Size: 3.87 MB
- Stars: 2
- Watchers: 13
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Absa Inception Framework
## Overview
The Absa Inception Framework enables the rapid development of applications with a Java
back-end and Angular front-end.
## Quickstart for MacOS
### Setup a development environment on MacOS
Complete the following steps to setup a development environment on MacOS.
1. Install the Xcode Command Line Tools by executing the following command in a Terminal
window.
```
xcode-select --install
```
2. Install Homebrew by executing the following command in a Terminal window.
```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
3. Install OpenJDK 11 by executing the following commands in a Terminal window.
```
brew install openjdk
```
4. Install Apache Maven by executing the following command in a Terminal window.
```
brew install maven
```
5. Install jenv by executing the following commands in a Terminal window.
```
brew install jenv
```
6. Add the following lines to your .zshrc or .bash_profile file to enable jenv and restart
your Terminal.
```
export PATH="$HOME/.jenv/bin:$PATH"
eval "$(jenv init -)"
```
7. Set OpenJDK 17 as the default java verison by executing the following commands in a
Terminal window.
```
Intel Mac:
jenv add /usr/local/opt/openjdk/libexec/openjdk.jdk/Contents/Home
jenv global 17
sudo ln -s /usr/local/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk
M1 Mac:
jenv add /opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home
jenv global 17
sudo ln -s /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk
```
8. Install the maven plugin for jenv by executing the following command in a Terminal
window.
```
jenv enable-plugin maven
```
9. Install Postgres by executing the following command in a Terminal window.
```
brew install postgres
```
10. Install liquibase by executing the following commands in a Terminal window.
```
brew install liquibase
```
11. Install npm by executing the following commands in a Terminal window.
```
brew install npm
```
12. Install the Angular CLI 13 globally by executing the following command in a Terminal
window.
```
npm install -g @angular/cli@13
```
13. Execute the following command to change to the more conservative tilde (~) patch
update approach for dependencies for npm.
```
npm config set save-prefix="~"
```
### Setup MailSlurper on MacOS
MailSlurper is a handy SMTP mail server useful for local and team application development.
Mails sent by an application running locally on a developer's machine can be viewed using
a web interface. This is useful when developing and testing an application locally.
Complete the following steps to setup MailSlurper on MacOS.
1. Download the MailSlurper package from *https://github.com/mailslurper/mailslurper/releases*.
2. Extract the MailSlurper package.
3. Edit the *config.json* file and set the *wwwPort* value to *8090*.
4. Launch the *createcredentials* binary in a Terminal window and enter the username as
*inception* and password as *inception* when prompted.
**NOTE:** You may need to enable the execution of the *mailslurper* binary under
*System Preferences > Security & Privacy > General*
5. Launch the *mailslurper* binary in a Terminal window.
**NOTE:** You may need to enable the execution of the *mailslurper* binary under
*System Preferences > Security & Privacy > General*
### Checkout and build the Absa Inception Framework on MacOS
Complete the following steps to checkout and build the Absa Inception Framework on MacOS.
1. Checkout the Absa Inception Framework by executing the following command in a Terminal
window.
```
git clone https://github.com/AbsaOSS/inception.git
```
2. Build and install the Java components of the Absa Inception Framework by executing the
following commands in the *inception/src* directory in a Terminal window.
```
mvn clean compile package install
```
2. Build the Angular components of the Absa Inception Framework by executing the
following commands in the *inception/src/inception-angular* directory in a Terminal
window.
```
npm i
ng build
cd dist/ngx-inception
npm link
```
3. To launch the *demo* back-end application, execute the following command
in the *src/demo/target* directory in a Terminal window, after building
the Java components of the Absa Inception Framework.
```
java -jar demo-1.3.0-SNAPSHOT.jar
```
4. To launch the *demo* front-end application, execute the following command
in the *inception/src/inception-angular* directory in a Terminal window, after building
the Angular components of the Absa Inception Framework.
```
ng serve --host 0.0.0.0
```
## Quickstart for Windows
### Setup a development environment on Windows
1. Download the Git for Windows package from *https://git-scm.com/download/win* and
install it.
Select the following options when installing Git:
```
Use the native Windows Secure Channel library
Checkout Windows-style, commit Unix-style line endings
Use MinTTY (the default terminal of MSYS2)
Default (fast-forward or merge)
Git Credential Manager
Enable file system caching
```
2. Download the OpenJDK 17 package from *https://adoptium.net/* and install it.
3. Download the Maven package from *https://maven.apache.org* and install it.
**NOTE:** Ensure that Maven is on the path.
**NOTE:** Add the proxy settings to the *~/.m2/settings.xml* file if required.
4. Download the Node.js and npm package from *https://www.npmjs.com/get-npm* and install
it.
**NOTE:** Set the proxy for NPM if required.
5. Install the Angular CLI 13 globally by executing the following command in a Git Bash
window.
```
npm install -g @angular/cli@13
```
6. Execute the following command to change to the more conservative tilde (~) patch
update approach for dependencies for npm.
```
npm config set save-prefix="~"
```
### Checkout and build the Absa Inception Framework on Windows
Complete the following steps to setup a development environment on Windows.
1. Checkout the Absa Inception Framework by executing the following command in a Terminal
window.
```
git clone https://github.com/AbsaOSS/inception.git
```
2. Build the Java components of the Absa Inception Framework by executing the
following commands in the *inception/src* directory in a Terminal window.
```
mvn clean compile package
```
2. Build the Angular components of the Absa Inception Framework by executing the
following commands in the *inception/src/inception-angular* directory in a Terminal
window.
```
npm i
ng build
cd dist/ngx-inception
npm link
```
3. To launch the *demo* back-end application, execute the following command
in the *src/demo/target* directory in a Terminal window, after building
the Java components of the Absa Inception Framework.
```
java -jar demo-1.3.0-SNAPSHOT.jar
```
4. To launch the *demo* front-end application, execute the following command
in the *inception/src/inception-angular* directory in a Terminal window, after building
the Angular components of the Absa Inception Framework.
```
ng serve --host 0.0.0.0
```
## Creating a new application based on the Absa Inception Framework
Complete the following steps to create a new application based on the Absa Inception Framework.
1. Select a name for the new application, e.g. demo, and create the top-level directory
for the application with the same name. The directory **MUST** be created under the
same directory that the Absa Inception Framework project was cloned into. This allows
the Absa Inception Framework to be installed as an npm dependency using a relative path,
which is required when working with a snapshot of the framework.
2. Execute the following commands under the top-level directory for the new application
to create the project directory structure.
```
mkdir -p src/main/java
mkdir -p src/main/java-templates
mkdir -p src/main/resources/META-INF
mkdir -p src/test/java
mkdir -p src/test/resources
```
3. Setup the Spring Boot back-end for the application.
1. Execute the following commands under the top-level directory for the new application
to generate the RSA keypair used to sign and verify OAuth2 JWTs issued by the
application.
```
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 | openssl pkcs8 -topk8 -nocrypt -outform pem > src/main/resources/META-INF/oauth2-jwt-key
openssl pkey -pubout -inform pem -outform pem -in src/main/resources/META-INF/oauth2-jwt-key -out src/main/resources/META-INF/oauth2-jwt-key.pub
```
2. Create the *pom.xml* file under the top-level directory for the new application with the following contents,
changing the *groupId*, *artifactId*, *version*, *name* and *description* values
as appropriate.
**NOTE:** If you do not require all the capabilities provided by the Inception
Framework you can remove the appropriate dependencies from the *pom.xml* file, e.g.
removing the *inception-reporting-rs* dependency will remove the JasperReports-based
reporting functionality.
```
4.0.0
demo
demo
1.0.0-SNAPSHOT
demo
africa.absa
inception
1.3.0
africa.absa
inception-api
africa.absa
inception-application
africa.absa
inception-jta
africa.absa
inception-codes-api
africa.absa
inception-config-api
africa.absa
inception-error-api
africa.absa
inception-mail-api
africa.absa
inception-oauth2-authorization-server
africa.absa
inception-oauth2-resource-server
africa.absa
inception-reporting-api
africa.absa
inception-scheduler-api
africa.absa
inception-security-api
com.h2database
h2
org.postgresql
postgresql
org.springframework.boot
spring-boot-starter-data-jpa
africa.absa
inception-test
test
org.springframework.boot
spring-boot-maven-plugin
com.github.eirslett
frontend-maven-plugin
1.12.1
src/main/frontend
v16.14.0
8.3.1
install node and npm
install-node-and-npm
npm install
npm
npm run build
npm
run build
```
3. Create the class and resource packages for the application. The classes and
resources for the application will be created under these packages, e.g. the Spring
Boot application class, the in-memory H2 database scripts for the application, etc.
```
mkdir -p src/main/java/demo
mkdir -p src/main/resources/demo
```
4. Add the Spring Boot Configuration class using the naming convention ***ApplicationName*Configuration**,
e.g. *src/main/java/demo/DemoConfiguration.java*.
```
package demo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
/**
* The DemoConfiguration class.
*/
@Configuration
@ComponentScan(
basePackages = {"africa.absa.inception", "demo"})
@EnableJpaRepositories(
entityManagerFactoryRef = "applicationEntityManagerFactory",
basePackages = {"demo"})
public class DemoConfiguration {}
```
5. Add the Spring Boot Application class using the naming convention ***ApplicationName*Application**,
e.g. *src/main/java/demo/DemoApplication.java*, which extends the
Absa Inception Framework application class (africa.absa.inception.application.Application).
```
package demo;
import africa.absa.inception.application.Application;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
/**
* The DemoApplication provides the implementation of the Absa Inception Framework
* application class for the demo application.
*/
@SpringBootApplication
public class DemoApplication extends Application {
/* Logger */
private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);
/**
* Constructs a new DemoApplication.
*
* @param applicationContext the Spring application context
*/
public DemoApplication(
ApplicationContext applicationContext) {
super(applicationContext);
}
/**
* The main method.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
6. Add the Liquibase changelog for the application using the naming convention
**src/main/resources/db/*application-name*.changelog.xml**, e.g.
*src/main/resources/db/demo.changelog.xml*, to the project. This file will
contain all the Liquibase changesets used to initialize both the in-memory H2
database and the environment-specific databases for the application.
The in-memory H2 database allows developers to run the application locally while
developing the application and is also used to execute all Junit tests for the
application as part of the build process.
**NOTE:** You need to update the *changeSet id* and the *application schema* name.
```
CREATE SCHEMA IF NOT EXISTS demo
CREATE SCHEMA IF NOT EXISTS demo
CREATE SCHEMA demo
```
7. Add the Spring application configuration file, *src/main/resources/application.yml*,
changing the *spring.application.name* value to the name of the application.
**NOTE:** You need to update the *spring.application.name* property.
```
server:
port: 8080
inception:
application:
data-source:
class-name: org.h2.jdbcx.JdbcDataSource
url: jdbc:h2:mem:application;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
min-pool-size: 5
max-pool-size: 10
debug:
enabled: true
oauth2:
authorization-server:
jwt:
rsa-private-key-location: classpath:META-INF/oauth2-jwt-key
rsa-public-key-location: classpath:META-INF/oauth2-jwt-key.pub
resource-server:
jwt:
rsa-public-key-location: classpath:META-INF/oauth2-jwt-key.pub
spring:
application:
name: demo
springdoc:
writer-with-order-by-keys: true
```
4. Setup the Angular front-end for the application.
1. Execute the following command under the *src/main* directory to create the new
Angular frontend.
```
ng new --skip-git --routing --style scss frontend
```
2. Edit the *src/main/frontend/angular.json* file and add the fontawesome path to the
*styles* array as shown below.
```
{
...
"projects": {
"frontend": {
...
"architect": {
"build": {
...
"options": {
...
"styles": [
"node_modules/@fortawesome/fontawesome-free/css/all.css",
"src/styles.scss"
],
...
},
...
}
```
3. Edit the *src/main/frontend/angular.json* file and add the *preserveSymlinks* option
with a value of *true*, add the *aot* option with a value of *true*, and change
the *outputPath* option to *../../../target/classes/static* as shown below. This
will result in the Angular font-end being packaged as part of the Spring Boot
application as a set of static resources.
```
{
...
"projects": {
"frontend": {
...
"architect": {
"build": {
...
"options": {
"preserveSymlinks": true,
"aot": true,
"outputPath": "../../../target/classes/static",
...
},
...
}
```
4. Edit the *src/main/frontend/angular.json* file and set the *maximumWarning** to
*2mb* and *maximumError* to *4mb* as shown below.
```
{
...
"projects": {
"frontend": {
...
"architect": {
"build": {
...
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "4mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
...
}
```
5. Execute the following commands under the *src/main/frontend* directory to install the
dependencies for the *ngx-inception* library.
```
npm install --save @angular/cdk@13
npm install --save @angular/localize@13
npm install --save @angular/material@13
npm install --save @angular/material-moment-adapter@13
npm install --save @auth0/angular-jwt@5
npm install --save @fortawesome/fontawesome-free@5
npm install --save bootstrap@4
npm install --save moment@2
npm install --save ngx-perfect-scrollbar@10
npm install --save es6-template-string@1
npm install --save uuid@8
npm install --save-dev @types/uuid@8
npm install --save-dev codelyzer
```
6. Execute the following command under the *src/main/frontend* directory to install the
*ngx-inception* library dependency.
```
npm install --save @absaoss/ngx-inception@1.2
```
7. Add the path mapping for the ngx-inception library to the *src/main/frontend/tsconfig.app.json* file.
```
"compilerOptions": {
...,
"paths": {
"@absaoss/ngx-inception/*": [
"./node_modules/@absaoss/ngx-inception/*"
]
}
},
```
8. Edit the *src/main/frontend/src/polyfills.ts* file and add the line below under the
*APPLICATION IMPORTS* section.
```
import '@angular/localize/init';
```
9. Add the *BrowserAnimationsModule* and Absa Inception Framework imports to the
*src/main/frontend/src/app/app.module.ts* file.
```
...
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
CoreModule, InceptionAppModule, InceptionConfig, NavigationBadge, NavigationItem, NavigationTitle
} from '@absaoss/ngx-inception/core';
import {environment} from "../environments/environment";
...
```
10. Add the *ngxInceptionConfig* to the *src/main/frontend/src/app/app.module.ts* file.
**NOTE:** If the application has a logged out landing page, which unauthenticated
users can access, then the *logoutRedirectUri* should be changed to the URL for this
page.
```
...
const ngxInceptionConfig: InceptionConfig = {
// Application Information
applicationId: 'demo',
applicationVersion: '1.0.0',
// OAuth Token URL
oauthTokenUrl: environment.inception_oauthTokenUrl,
// Logout redirect URI
logoutRedirectUri: '/login',
// Inception API URLs
codesApiUrlPrefix: environment.inception_codesApiUrlPrefix,
configApiUrlPrefix: environment.inception_configApiUrlPrefix,
errorApiUrlPrefix: environment.inception_errorApiUrlPrefix,
mailApiUrlPrefix: environment.inception_mailApiUrlPrefix,
partyApiUrlPrefix: environment.inception_partyApiUrlPrefix,
partyReferenceApiUrlPrefix: environment.inception_partyReferenceApiUrlPrefix,
referenceApiUrlPrefix: environment.inception_referenceApiUrlPrefix,
reportingApiUrlPrefix: environment.inception_reportingApiUrlPrefix,
schedulerApiUrlPrefix: environment.inception_schedulerApiUrlPrefix,
securityApiUrlPrefix: environment.inception_securityApiUrlPrefix,
// Flags
forgottenPasswordEnabled: true,
userProfileEnabled: true
};
@NgModule({
...
```
11. Add the *BrowserAnimationsModule* and *CoreModule.forRoot(ngxInceptionConfig)*
module imports to the *@NgModule* annotation in
the *src/main/frontend/src/app/app.module.ts* file.
```
@NgModule({
bootstrap: [AppComponent],
declarations: [AppComponent
],
imports: [
AppRoutingModule,
BrowserAnimationsModule,
BrowserModule,
CoreModule.forRoot(ngxInceptionConfig)
]
})
```
12. Change the *AppModule* class so that it extends the *InceptionAppModule* class, then
implement the *initNavigation* method. The *initNavigation* method specifies which
Absa Inception Framework and application-specific views to include in the navigation.
```
export class AppModule extends InceptionAppModule {
constructor() {
super();
}
/**
* Initialise the navigation for the application.
*
* @returns The navigation for the application.
*/
protected initNavigation(): NavigationItem[] {
const navigation: NavigationItem[] = [];
navigation.push(new NavigationItem('fa fa-tachometer-alt', 'Dashboard', '/dashboard',
['ROLE_Administrator', 'FUNCTION_Dashboard.Dashboard'], undefined, undefined, undefined));
navigation.push(new NavigationItem('fa fa-cogs', 'Administration', '/administration',
['ROLE_Administrator', 'FUNCTION_Codes.CodeAdministration', 'FUNCTION_Config.ConfigAdministration',
'FUNCTION_Security.GroupAdministration', 'FUNCTION_Security.TenantAdministration',
'FUNCTION_Security.ResetUserPassword', 'FUNCTION_Security.UserAdministration',
'FUNCTION_Security.UserDirectoryAdministration', 'FUNCTION_Security.UserGroups',
'FUNCTION_Scheduler.SchedulerAdministration', 'FUNCTION_Scheduler.JobAdministration',
'FUNCTION_Mail.MailAdministration', 'FUNCTION_Mail.MailTemplateAdministration'
], [new NavigationItem('fa fa-shield-alt', 'Security', '/administration/security',
['ROLE_Administrator', 'FUNCTION_Security.GroupAdministration', 'FUNCTION_Security.TenantAdministration',
'FUNCTION_Security.ResetUserPassword', 'FUNCTION_Security.UserAdministration',
'FUNCTION_Security.UserDirectoryAdministration', 'FUNCTION_Security.UserGroups'
], [new NavigationItem('fas fa-user', 'Users', '/administration/security/users',
['ROLE_Administrator', 'FUNCTION_Security.ResetUserPassword', 'FUNCTION_Security.UserAdministration',
'FUNCTION_Security.UserGroups'
]), new NavigationItem('fas fa-users', 'Groups', '/administration/security/groups',
['ROLE_Administrator', 'FUNCTION_Security.GroupAdministration']),
new NavigationItem('far fa-building', 'Tenants', '/administration/security/tenants',
['ROLE_Administrator', 'FUNCTION_Security.TenantAdministration']),
new NavigationItem('far fa-address-book', 'User Directories', '/administration/security/user-directories',
['ROLE_Administrator', 'FUNCTION_Security.UserDirectoryAdministration'])
]), new NavigationItem('fa fa-cog', 'System', '/administration/system',
['ROLE_Administrator', 'FUNCTION_Codes.CodeAdministration',
'FUNCTION_Configuration.ConfigurationAdministration', 'FUNCTION_Mail.MailAdministration',
'FUNCTION_Mail.MailTemplateAdministration', 'FUNCTION_Scheduler.SchedulerAdministration',
'FUNCTION_Scheduler.JobAdministration'
], [new NavigationItem('fa fa-list', 'Codes', '/administration/system/code-categories',
['ROLE_Administrator', 'FUNCTION_Codes.CodeAdministration']),
new NavigationItem('fa fa-list', 'Config', '/administration/system/config',
['ROLE_Administrator', 'FUNCTION_Config.ConfigAdministration']),
new NavigationItem('fas fa-envelope', 'Mail', '/administration/system/mail',
['ROLE_Administrator', 'FUNCTION_Mail.MailAdministration', 'FUNCTION_Mail.MailTemplateAdministration'
], [new NavigationItem('fas fa-envelope-open-text', 'Mail Templates',
'/administration/system/mail/mail-templates',
['ROLE_Administrator', 'FUNCTION_Mail.MailAdministration', 'FUNCTION_Mail.MailTemplateAdministration'
])
]), new NavigationItem('fas fa-clock', 'Scheduler', '/administration/system/scheduler',
['ROLE_Administrator', 'FUNCTION_Scheduler.SchedulerAdministration', 'FUNCTION_Scheduler.JobAdministration'
], [new NavigationItem('fas fa-cogs', 'Jobs', '/administration/system/scheduler/jobs',
['ROLE_Administrator', 'FUNCTION_Scheduler.SchedulerAdministration',
'FUNCTION_Scheduler.JobAdministration'
])
]), new NavigationItem('fas fa-file-invoice', 'Reporting', '/administration/system/reporting',
['ROLE_Administrator', 'FUNCTION_Reporting.ReportingAdministration',
'FUNCTION_Reporting.ReportDefinitionAdministration'
], [new NavigationItem('far fa-copy', 'Report Definitions',
'/administration/system/reporting/report-definitions',
['ROLE_Administrator', 'FUNCTION_Reporting.ReportingAdministration',
'FUNCTION_Reporting.ReportDefinitionAdministration'
])
])
])
]));
return navigation;
}
}
```
13. Create the *src/main/frontend/src/app/views/administration* directory.
```
mkdir -p src/main/frontend/src/app/views/administration
```
14. Create the *src/main/frontend/src/app/views/administration/administration.component.ts* file with the
following contents.
```
import {Component} from '@angular/core';
/**
* The AdministrationComponent class implements the administration component.
*/
@Component({
template: `Administration
`
})
export class AdministrationComponent {
constructor() {
}
}
```
15. Create the wrapper modules for the Absa Inception Framework modules:
1. Create the *src/main/frontend/src/app/views/wrappers* directory.
```
mkdir -p src/main/frontend/src/app/views/wrappers
```
2. Create the *src/main/frontend/src/app/views/wrappers/codes-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {CodesViewsModule} from '@absaoss/ngx-inception/codes';
@NgModule({
imports: [CodesViewsModule]
})
export class CodesViewsWrapperModule {
}
```
3. Create the *src/main/frontend/src/app/views/wrappers/config-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {ConfigViewsModule} from '@absaoss/ngx-inception/config';
@NgModule({
imports: [ConfigViewsModule]
})
export class ConfigViewsWrapperModule {
}
```
4. Create the *src/main/frontend/src/app/views/wrappers/error-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {ErrorViewsModule} from '@absaoss/ngx-inception/error';
@NgModule({
imports: [ErrorViewsModule]
})
export class ErrorViewsWrapperModule {
}
```
5. Create the *src/main/frontend/src/app/views/wrappers/login-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {LoginViewsModule} from '@absaoss/ngx-inception/login';
@NgModule({
imports: [LoginViewsModule]
})
export class LoginViewsWrapperModule {
}
```
6. Create the *src/main/frontend/src/app/views/wrappers/mail-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {MailViewsModule} from '@absaoss/ngx-inception/mail';
@NgModule({
imports: [MailViewsModule]
})
export class MailViewsWrapperModule {
}
```
7. Create the *src/main/frontend/src/app/views/wrappers/reporting-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {ReportingViewsModule} from '@absaoss/ngx-inception/reporting';
@NgModule({
imports: [ReportingViewsModule]
})
export class ReportingViewsWrapperModule {
}
```
8. Create the *src/main/frontend/src/app/views/wrappers/scheduler-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {SchedulerViewsModule} from '@absaoss/ngx-inception/scheduler';
@NgModule({
imports: [SchedulerViewsModule]
})
export class SchedulerViewsWrapperModule {
}
```
9. Create the *src/main/frontend/src/app/views/wrappers/security-views-wrapper.module.ts* file with the
following contents.
```
import {NgModule} from '@angular/core';
import {SecurityViewsModule} from '@absaoss/ngx-inception/security';
@NgModule({
imports: [SecurityViewsModule]
})
export class SecurityViewsWrapperModule {
}
```
16. Create the *src/main/frontend/src/app/views/administration/administration.module.ts* file with the
following contents.
```
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {CodeCategoriesTitleResolver} from '@absaoss/ngx-inception/codes';
import {ConfigsTitleResolver} from '@absaoss/ngx-inception/config';
import {MailTitleResolver} from '@absaoss/ngx-inception/mail';
import {ReportingTitleResolver} from '@absaoss/ngx-inception/reporting';
import {SchedulerTitleResolver} from '@absaoss/ngx-inception/scheduler';
import {SecurityTitleResolver} from '@absaoss/ngx-inception/security';
import {AdministrationTitleResolver} from './administration-title-resolver';
import {AdministrationComponent} from './administration.component';
import {SystemTitleResolver} from './system-title-resolver';
const routes: Routes = [{
path: '',
pathMatch: 'full',
component: AdministrationComponent,
resolve: {
title: AdministrationTitleResolver
}
}, {
path: 'security',
resolve: {
title: SecurityTitleResolver
},
loadChildren: () => import('../wrappers/security-views-wrapper.module').then(m => m.SecurityViewsWrapperModule)
}, {
path: 'system',
resolve: {
title: SystemTitleResolver
},
children: [{
path: 'code-categories',
resolve: {
title: CodeCategoriesTitleResolver
},
loadChildren: () => import('../wrappers/codes-views-wrapper.module').then(m => m.CodesViewsWrapperModule)
}, {
path: 'config',
resolve: {
title: ConfigsTitleResolver
},
loadChildren: () => import('../wrappers/config-views-wrapper.module').then(
m => m.ConfigViewsWrapperModule)
}, {
path: 'mail',
resolve: {
title: MailTitleResolver
},
loadChildren: () => import('../wrappers/mail-views-wrapper.module').then(m => m.MailViewsWrapperModule)
}, {
path: 'scheduler',
resolve: {
title: SchedulerTitleResolver
},
loadChildren: () => import('../wrappers/scheduler-views-wrapper.module').then(m => m.SchedulerViewsWrapperModule)
}, {
path: 'reporting',
resolve: {
title: ReportingTitleResolver
},
loadChildren: () => import('../wrappers/reporting-views-wrapper.module').then(m => m.ReportingViewsWrapperModule)
}
]
}
];
@NgModule({
imports: [CommonModule, RouterModule.forChild(routes)
],
declarations: [AdministrationComponent],
providers: [
// Resolvers
CodeCategoriesTitleResolver, ConfigsTitleResolver, MailTitleResolver, ReportingTitleResolver,
SchedulerTitleResolver, SecurityTitleResolver, SystemTitleResolver
]
})
export class AdministrationModule {
}
```
17. Create the *src/main/frontend/src/app/views/administration/administration-title-resolver.ts* file with
the following contents.
```
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';
import {Observable, of} from 'rxjs';
/**
* The AdministrationTitleResolver class provides the route data resolver that resolves the
* title for the "Administration" route in the navigation hierarchy.
*/
@Injectable()
export class AdministrationTitleResolver implements Resolve {
/**
* Constructs a new AdministrationTitleResolver.
*/
constructor() {
}
/**
* Resolve the title.
*
* @param activatedRouteSnapshot The activate route snapshot.
* @param routerStateSnapshot The router state snapshot.
*/
resolve(activatedRouteSnapshot: ActivatedRouteSnapshot,
routerStateSnapshot: RouterStateSnapshot): Observable {
return of('Administration');
}
}
```
18. Create the *src/main/frontend/src/app/views/administration/system-title-resolver.ts* file with the
following contents.
```
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router';
import {Observable, of} from 'rxjs';
/**
* The SystemTitleResolver class provides the route data resolver that resolves the
* title for the "System" route in the navigation hierarchy.
*/
@Injectable()
export class SystemTitleResolver implements Resolve {
/**
* Constructs a new SystemTitleResolver.
*/
constructor() {
}
/**
* Resolve the title.
*
* @param activatedRouteSnapshot The activate route snapshot.
* @param routerStateSnapshot The router state snapshot.
*/
resolve(activatedRouteSnapshot: ActivatedRouteSnapshot,
routerStateSnapshot: RouterStateSnapshot): Observable {
return of('System');
}
}
```
19. Create the *src/main/frontend/src/app/views/dashboard* directory.
```
mkdir -p src/main/frontend/src/app/views/dashboard
```
20. Create the *src/main/frontend/src/app/views/dashboard/dashboard.component.ts* file with the following
contents.
```
import {Component} from '@angular/core';
/**
* The DashboardComponent class implements the dashboard component.
*/
@Component({
template: `Dashboard
`
})
export class DashboardComponent {
constructor() {
}
}
```
21. Create the *src/main/frontend/src/app/views/dashboard/dashboard.module.ts* file with the following
contents.
```
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {DashboardComponent} from './dashboard.component';
const routes: Routes = [{
path: '',
component: DashboardComponent
}
];
@NgModule({
imports: [CommonModule,
RouterModule.forChild(routes)
],
declarations: [DashboardComponent]
})
export class DashboardModule {
}
```
22. Replace the contents of the *src/main/frontend/src/app/app-routing.module.ts* file with the following.
```
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {
AdminContainerComponent, CanActivateFunctionGuard, NotFoundComponent, SimpleContainerComponent
} from '@absaoss/ngx-inception/core';
import {UserProfileComponent} from '@absaoss/ngx-inception/security';
import {AdministrationTitleResolver} from './views/administration/administration-title-resolver';
export const routes: Routes = [{
path: '',
pathMatch: 'full',
redirectTo: 'dashboard',
}, {
path: '',
component: AdminContainerComponent,
children: [{
path: 'profile',
component: UserProfileComponent
},
{
path: 'dashboard',
canActivate: [CanActivateFunctionGuard
],
data: {
title: 'Dashboard',
authorities: ['ROLE_Administrator', 'FUNCTION_Dashboard.Dashboard']
},
loadChildren: () => import('./views/dashboard/dashboard.module').then(m => m.DashboardModule)
}, {
path: 'administration',
resolve: {
title: AdministrationTitleResolver
},
loadChildren: () => import('./views/administration/administration.module').then(m => m.AdministrationModule)
}
]
},
// Login route
{
path: 'login',
component: SimpleContainerComponent,
loadChildren: () => import('./views/wrappers/login-views-wrapper.module').then(m => m.LoginViewsWrapperModule)
},
// Send Error Report route
{
path: 'error',
component: SimpleContainerComponent,
loadChildren: () => import('./views/wrappers/error-views-wrapper.module').then(m => m.ErrorViewsWrapperModule)
},
// Default route for invalid paths
{
path: '**',
component: NotFoundComponent
}
];
@NgModule({
// Tracing should only be enabled for DEBUG purposes
imports: [
// Angular modules
RouterModule.forRoot(routes, {enableTracing: false})
],
exports: [RouterModule],
providers: [AdministrationTitleResolver]
})
export class AppRoutingModule {
}
```
23. Delete the *src/main/frontend/src/app/app.component.html*,
*src/main/frontend/src/app/app.component.scss*, and
*src/main/frontend/src/app/app.component.spec.ts* files.
```
rm -f src/main/frontend/src/app/app.component.html
rm -f src/main/frontend/src/app/app.component.scss
rm -f src/main/frontend/src/app/app.component.spec.ts
```
24. Replace the contents of the *src/main/frontend/src/app/app.component.ts* file with the following.
```
import {Component, OnDestroy, OnInit} from '@angular/core';
import {NavigationEnd, Router} from '@angular/router';
import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';
@Component({
// tslint:disable-next-line
selector: 'body',
template: `
`
})
export class AppComponent implements OnInit, OnDestroy {
// tslint:disable-next-line
private unsubscribe$: Subject = new Subject();
constructor(private router: Router) {
}
ngOnDestroy(): void {
this.unsubscribe$.complete();
}
ngOnInit(): void {
this.router.events.pipe(takeUntil(this.unsubscribe$)).subscribe((evt) => {
if (!(evt instanceof NavigationEnd)) {
return;
}
window.scrollTo(0, 0);
});
}
}
```
25. Create the *src/main/frontend/src/assets/images* and *src/main/frontend/src/assets/scss* directories.
```
mkdir -p src/main/frontend/src/assets/images
mkdir -p src/main/frontend/src/assets/scss
```
26. Copy the image for the logo to *src/main/frontend/src/assets/images/logo.png* and the image for the
logo symbol to *src/main/frontend/src/assets/images/logo-symbol.png*.
NOTE: If you do not have application-specific logo and logo symbol images then you can
copy the ones from the *ngx-inception*
```
cp src/main/frontend/node_modules/@absaoss/ngx-inception/assets/images/logo.png src/main/frontend/src/assets/images/logo.png
cp src/main/frontend/node_modules/@absaoss/ngx-inception/assets/images/logo-symbol.png src/main/frontend/src/assets/images/logo-symbol.png
```
27. Replace the contents of the *src/main/frontend/src/styles.scss* file with the following.
```
@import "./node_modules/@absaoss/ngx-inception/assets/scss/default-theme";
.brand-full {
display: inline-block;
width: 100px;
height: 13px;
background-image: url("assets/images/logo.png");
background-size: 100% auto;
background-repeat: no-repeat;
}
.brand-minimized {
display: inline-block;
width: 30px;
height: 30px;
background-image: url("assets/images/logo-symbol.png");
background-size: 100% auto;
background-repeat: no-repeat;
}
.logo-login {
background-image: url("assets/images/logo.png");
}
span.copyright-name:before
{
content: "My Company";
}
```
28. Replace the contents of the *src/main/frontend/src/environments/environment.ts* file with the following.
```
export const environment = {
production: false,
// Inception API endpoints
inception_oauthTokenUrl: 'http://localhost:8080/oauth/token',
inception_codesApiUrlPrefix: 'http://localhost:8080/api/codes',
inception_configApiUrlPrefix: 'http://localhost:8080/api/config',
inception_errorApiUrlPrefix: 'http://localhost:8080/api/error',
inception_mailApiUrlPrefix: 'http://localhost:8080/api/mail',
inception_partyApiUrlPrefix: 'http://localhost:8080/api/party',
inception_partyReferenceApiUrlPrefix: 'http://localhost:8080/api/party/reference',
inception_referenceApiUrlPrefix: 'http://localhost:8080/api/reference',
inception_reportingApiUrlPrefix: 'http://localhost:8080/api/reporting',
inception_schedulerApiUrlPrefix: 'http://localhost:8080/api/scheduler',
inception_securityApiUrlPrefix: 'http://localhost:8080/api/security',
};
/*
* For easier debugging in development mode, we import the following file to ignore
* zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*/
import 'zone.js/plugins/zone-error';
```
29. Replace the contents of the *src/main/frontend/src/environments/environment.prod.ts* file with the following.
```
export const environment = {
production: true,
// Inception API endpoints
inception_oauthTokenUrl: '/oauth/token',
inception_codesApiUrlPrefix: '/api/codes',
inception_configApiUrlPrefix: '/api/config',
inception_errorApiUrlPrefix: '/api/error',
inception_mailApiUrlPrefix: '/api/mail',
inception_partyApiUrlPrefix: '/api/party',
inception_partyReferenceApiUrlPrefix: '/api/party/reference',
inception_referenceApiUrlPrefix: '/api/reference',
inception_reportingApiUrlPrefix: '/api/reporting',
inception_schedulerApiUrlPrefix: '/api/scheduler',
inception_securityApiUrlPrefix: '/api/security',
};
```
5. Execute the following command under the *src* directory to build the new application.
```
mvn package
```
## Upgrading the Absa Inception Framework
### Upgrading to version 1.3 of the Absa Inception Framework
In version 1.3 of the Inception Framework the *created* and *updated* timestamps were
removed from a number of tables.
Execute the following commands against your existing databases to remove the obsolete columns.
```
ALTER TABLE codes.code_categories DROP COLUMN IF EXISTS created;
ALTER TABLE codes.code_categories DROP COLUMN IF EXISTS updated;
ALTER TABLE codes.code_categories ADD COLUMN IF NOT EXISTS last_modified timestamp;
ALTER TABLE codes.codes DROP COLUMN IF EXISTS created;
ALTER TABLE codes.codes DROP COLUMN IF EXISTS updated;
ALTER TABLE config.config DROP COLUMN IF EXISTS created;
ALTER TABLE config.config DROP COLUMN IF EXISTS updated;
ALTER TABLE mail.mail_templates DROP COLUMN IF EXISTS created;
ALTER TABLE mail.mail_templates DROP COLUMN IF EXISTS updated;
ALTER TABLE mail.mail_templates ADD COLUMN IF NOT EXISTS last_modified timestamp;
ALTER TABLE scheduler.jobs DROP COLUMN IF EXISTS created;
ALTER TABLE scheduler.jobs DROP COLUMN IF EXISTS updated;
ALTER TABLE scheduler.job_parameters DROP COLUMN IF EXISTS created;
ALTER TABLE scheduler.job_parameters DROP COLUMN IF EXISTS updated;
ALTER TABLE reporting.report_definitions DROP COLUMN IF EXISTS created;
ALTER TABLE reporting.report_definitions DROP COLUMN IF EXISTS updated;
ALTER TABLE security.tenants DROP COLUMN IF EXISTS created;
ALTER TABLE security.tenants DROP COLUMN IF EXISTS updated;
ALTER TABLE security.user_directories DROP COLUMN IF EXISTS created;
ALTER TABLE security.user_directories DROP COLUMN IF EXISTS updated;
ALTER TABLE security.users DROP COLUMN IF EXISTS created;
ALTER TABLE security.users DROP COLUMN IF EXISTS updated;
ALTER TABLE security.groups DROP COLUMN IF EXISTS created;
ALTER TABLE security.groups DROP COLUMN IF EXISTS updated;
ALTER TABLE demo.vehicles DROP COLUMN IF EXISTS created;
ALTER TABLE demo.vehicles DROP COLUMN IF EXISTS updated;
ALTER TABLE demo.vehicle_attributes DROP COLUMN IF EXISTS created;
ALTER TABLE demo.vehicle_attributes DROP COLUMN IF EXISTS updated;
UPDATE codes.code_categories SET last_modified = NOW();
UPDATE mail.mail_templates SET last_modified = NOW();
```