Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add Ionic 4 Support #20

Merged
merged 17 commits into from
Apr 28, 2019
Merged
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
29 changes: 11 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# The Ionic JHipster Starter 🤓
# [BETA] The Ionic4 JHipster Starter 🤓

> Because Ionic Apps need some JHipster 💙 too!

Expand All @@ -10,9 +10,7 @@
The Ionic JHipster Starter is designed to be used with a JHipster backend that uses JWT Authentication.
You can create a project with it directly, or use [Ionic for JHipster](https://github.com/oktadeveloper/generator-jhipster-ionic).

This project provides a base template of functionality for an Ionic app. The Ionic for JHipster module provides entity generation and additional features that require logic to install (e.g. OAuth authentication).

This project is in a beta state, see its [v1.0 milestone](https://github.com/oktadeveloper/ionic-jhipster-starter/milestone/2) for progress towards a release.
This project provides a base template of functionality for an Ionic app. The Ionic for JHipster module provides ~~entity generation and additional features that require logic to install (e.g. OAuth authentication)~~.

[![Build Status][travis-image]][travis-url]

Expand All @@ -29,7 +27,7 @@ This project is in a beta state, see its [v1.0 milestone](https://github.com/okt
To use this starter, install the latest version of the Ionic CLI and run:

```bash
ionic start ionic4j oktadeveloper/jhipster
ionic start ionic4j fleboulch/jhipster
```

You can also install it using the [Ionic for JHipster Module](https://github.com/oktadeveloper/generator-jhipster-ionic):
Expand All @@ -39,11 +37,7 @@ npm install -g generator-jhipster-ionic
yo jhipster-ionic
```

This module allows you to generate entities using:

```bash
yo jhipster-ionic:entity <name>
```
~~This module allows you to generate entities using:~~

### Tips

Expand All @@ -59,27 +53,26 @@ The emulator runs on port 8080, so you will need to change your backend to run o
```
{jhipster-project}/src/main/resources/config/application-dev.yml
{jhipster-project}/webpack/webpack.dev.js
{ionic-project}/src/providers/api/api.ts
{ionic-project}/src/environments/environment{.prod}.ts
```

## Pages

The Ionic JHipster Starter comes with a variety of ready-made pages.

## Providers
## Services

The Ionic JHipster Starter comes with some basic implementations of common providers.
The Ionic JHipster Starter comes with some basic implementations of common services.

### User

The `User` provider is used to authenticate users through its
The `User` service is used to authenticate users through its
`login(accountInfo)` and `#(accountInfo)` methods, which perform `POST`
requests to an API endpoint that you will need to configure.

### Api

The `Api` provider is a simple CRUD frontend to an API. Simply put the root of
your API url in the Api class and call get/post/put/patch/delete.
The `Api` service is a simple CRUD frontend to an API.

## i18n

Expand Down Expand Up @@ -154,7 +147,7 @@ npm run e2e

The [Protractor configuration](test/protractor.conf.js) uses [serve](https://www.npmjs.com/package/serve) to serve up the contents of `www` on port 8100 before running its tests.

Apache-2.0 © [Okta](https://developer.okta.com/)
Apache-2.0

[travis-image]: https://travis-ci.org/oktadeveloper/ionic-jhipster-starter.svg?branch=master
[travis-url]: https://travis-ci.org/oktadeveloper/ionic-jhipster-starter
[travis-url]: https://travis-ci.org/oktadeveloper/ionic-jhipster-starter
42 changes: 21 additions & 21 deletions ionic.starter.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "JHipster Starter",
"baseref": "fc4e95672c34e8462f4deffa543e4702a890b97f",
"welcome": "Welcome to the \u001b[34m\u001b[1mIonic\u001b[22m\u001b[39m \u001b[32m\u001b[1mJ\u001b[22m\u001b[39m\u001b[31m\u001b[1mHipster\u001b[22m\u001b[39m Starter!\n\nThe Ionic JHipster Starter ships with login and # that will work with a JHipster backend (with JWT Authentication). \n\nFor more details, please see the project's README: \u001b[1mhttps://github.com/oktadeveloper/ionic-jhipster-starter/blob/master/README.md\u001b[22m",
"baseref": "a1abd0df2aaa0ab46c8c6495e1f63e07c4f7c977",
"welcome": "Welcome to the \u001b[34m\u001b[1mIonic\u001b[22m\u001b[39m \u001b[32m\u001b[1mJ\u001b[22m\u001b[39m\u001b[31m\u001b[1mHipster\u001b[22m\u001b[39m Starter!\n\nThe Ionic JHipster Starter ships with login and # that will work with a JHipster backend (with JWT Authentication). \n\nFor more details, please see the project's README: \u001b[1mhttps://github.com/fleboulch/ionic-jhipster-starter/blob/master/README.md\u001b[22m",
"packageJson": {
"scripts": {
"test": "jest",
Expand All @@ -13,30 +13,30 @@
"e2e-update": "webdriver-manager update --standalone false --gecko false"
},
"dependencies": {
"@ionic-native/camera": "4.6.0",
"@ngx-translate/core": "8.0.0",
"@ngx-translate/http-loader": "2.0.0",
"@ionic-native/camera": "5.3.0",
"@ngx-translate/core": "11.0.1",
"@ngx-translate/http-loader": "4.0.0",
"ngx-webstorage": "2.0.1",
"ng-jhipster": "0.4.5"
"ng-jhipster": "0.9.3"
},
"devDependencies": {
"generator-jhipster": "^4.10.2",
"@types/node": "8.0.0",
"@types/jest": "22.2.3",
"typescript": "2.8.1",
"html-loader": "0.5.1",
"ionic-mocks-jest": "1.0.3",
"istanbul-instrumenter-loader": "3.0.0",
"jasmine": "3.1.0",
"jasmine-spec-reporter": "4.1.0",
"jest": "22.4.3",
"jest-localstorage-mock": "2.2.0",
"jest-preset-angular": "5.2.1",
"generator-jhipster": "^5.8.2",
"@types/node": "11.12.2",
"@types/jest": "24.0.11",
"typescript": "3.1.1",
"html-loader": "0.5.5",
"ionic-mocks-jest": "1.3.3",
"istanbul-instrumenter-loader": "3.0.1",
"jasmine": "3.3.1",
"jasmine-spec-reporter": "4.2.1",
"jest": "24.5.0",
"jest-localstorage-mock": "2.4.0",
"jest-preset-angular": "7.0.1",
"null-loader": "0.1.1",
"protractor": "5.1.1",
"protractor": "5.4.2",
"node-http-server": "8.1.2",
"ts-loader": "4.2.0",
"ts-node": "6.0.0"
"ts-loader": "5.3.3",
"ts-node": "8.0.3"
},
"cordova": {
"plugins": {
Expand Down
15 changes: 15 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
{ path: '', loadChildren: './pages/welcome/welcome.module#WelcomePageModule' },
{ path: 'tabs', loadChildren: './pages/tabs/tabs.module#TabsPageModule' },
{ path: 'login', loadChildren: './pages/#/#.module#LoginPageModule' },
{ path: '#', loadChildren: './pages/#/#.module##PageModule' },
{ path: 'accessdenied', redirectTo: '', pathMatch: 'full' }
];
@NgModule({
imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
exports: [RouterModule]
})
export class AppRoutingModule {}
3 changes: 3 additions & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>
104 changes: 41 additions & 63 deletions src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,45 @@
import { async, TestBed } from '@angular/core/testing';
import { Config, IonicModule, Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { ConfigMock, PlatformMock, SplashScreenMock, StatusBarMock } from 'ionic-mocks-jest';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { MyApp } from './app.component';
import { IonicStorageModule, Storage } from '@ionic/storage';

import * as en from '../assets/i18n/en.json';
import { provideSettings } from './app.module';
import { Settings } from '../providers/providers';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';

const TRANSLATIONS = {
EN: en
};

class JsonTranslationLoader implements TranslateLoader {
getTranslation(code: string = ''): Observable<object> {
const uppercased = code.toUpperCase();
return of(TRANSLATIONS[uppercased]);
}
}

describe('MyApp Component', () => {
let fixture;
let component;

beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [MyApp],
imports: [
IonicModule.forRoot(MyApp),
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: JsonTranslationLoader }
}),
IonicStorageModule.forRoot({
name: 'storage',
driverOrder: ['localstorage'],
})],
providers: [
{provide: StatusBar, useFactory: () => StatusBarMock.instance()},
{provide: SplashScreen, useFactory: () => SplashScreenMock.instance()},
{provide: Platform, useFactory: () => PlatformMock.instance()},
{provide: Config, useFactory: () => ConfigMock.instance()},
{provide: Settings, useFactory: provideSettings, deps: [Storage]}
]
});
})
);

beforeEach(() => {
fixture = TestBed.createComponent(MyApp);
component = fixture.componentInstance;
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TestBed, async } from '@angular/core/testing';

import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';

describe('AppComponent', () => {
let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy;

beforeEach(async(() => {
statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']);
splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
platformReadySpy = Promise.resolve();
platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy });

TestBed.configureTestingModule({
declarations: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{ provide: StatusBar, useValue: statusBarSpy },
{ provide: SplashScreen, useValue: splashScreenSpy },
{ provide: Platform, useValue: platformSpy }
]
}).compileComponents();
}));

it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});

it('should be created', () => {
expect(component instanceof MyApp).toBe(true);
it('should initialize the app', async () => {
TestBed.createComponent(AppComponent);
expect(platformSpy.ready).toHaveBeenCalled();
await platformReadySpy;
expect(statusBarSpy.styleDefault).toHaveBeenCalled();
expect(splashScreenSpy.hide).toHaveBeenCalled();
});

it('should show tabs page', () => {
expect(component.rootPage).toEqual('TabsPage');
});
});
// TODO: add more tests!
});
77 changes: 24 additions & 53 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,45 @@
import { Component, ViewChild } from '@angular/core';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { Component } from '@angular/core';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { Platform } from '@ionic/angular';
import { TranslateService } from '@ngx-translate/core';
import { Config, Nav, Platform } from 'ionic-angular';
import { MainPage } from '../pages/pages';
import { Settings } from '../providers/providers';

@Component({
template: `<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Pages</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>

</ion-menu>
<ion-nav #content [root]="rootPage"></ion-nav>`
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class MyApp {
rootPage = MainPage;

@ViewChild(Nav) nav: Nav;

pages: any[] = [
{ title: 'Welcome', component: 'WelcomePage' },
{ title: 'Tabs', component: 'TabsPage' },
{ title: 'Login', component: 'LoginPage' },
{ title: '#', component: '#Page' },
{ title: 'Menu', component: 'MenuPage' },
{ title: 'Settings', component: 'SettingsPage' },
{ title: 'Entities', component: 'EntityPage' }
];
export class AppComponent {
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private translate: TranslateService
) {
this.initializeApp();
}

constructor(private translate: TranslateService, platform: Platform, settings: Settings, private config: Config,
private statusBar: StatusBar, private splashScreen: SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
this.initTranslate();
}

initTranslate() {
const enLang = 'en';

// Set the default language for translation strings, and the current language.
this.translate.setDefaultLang('en');
this.translate.setDefaultLang(enLang);

if (this.translate.getBrowserLang() !== undefined) {
this.translate.use(this.translate.getBrowserLang());
} else {
this.translate.use('en'); // Set your language here
this.translate.use(enLang); // Set your language here
}

this.translate.get(['BACK_BUTTON_TEXT']).subscribe(values => {
this.config.set('ios', 'backButtonText', values.BACK_BUTTON_TEXT);
});
}

openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
// this.translate.get(['BACK_BUTTON_TEXT']).subscribe(values => {
// this.config.set('ios', 'backButtonText', values.BACK_BUTTON_TEXT);
// });
}
}
Loading