Use OpenSlides as Progressive Web App (PWA).

This commit is contained in:
Emanuel Schütze 2019-01-16 14:04:15 +01:00
parent 460b3dcac9
commit f83f3fed46
18 changed files with 156 additions and 11 deletions

View File

@ -22,8 +22,14 @@
"main": "src/main.ts", "main": "src/main.ts",
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json", "tsConfig": "src/tsconfig.app.json",
"assets": ["src/favicon.ico", "src/assets"], "assets": [
"styles": ["src/styles.scss", "node_modules/material-design-icons/iconfont/material-icons.css"], "src/assets",
"src/manifest.json"
],
"styles": [
"src/styles.scss",
"node_modules/material-design-icons/iconfont/material-icons.css"
],
"scripts": [ "scripts": [
"node_modules/tinymce/tinymce.min.js", "node_modules/tinymce/tinymce.min.js",
"node_modules/tinymce/themes/modern/theme.js", "node_modules/tinymce/themes/modern/theme.js",
@ -58,7 +64,8 @@
"aot": true, "aot": true,
"extractLicenses": true, "extractLicenses": true,
"vendorChunk": false, "vendorChunk": false,
"buildOptimizer": true "buildOptimizer": true,
"serviceWorker": true
} }
} }
}, },
@ -86,11 +93,16 @@
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json", "tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js", "karmaConfig": "src/karma.conf.js",
"styles": ["src/styles.scss"], "styles": [
"src/styles.scss"
],
"scripts": [ "scripts": [
"node_modules/tinymce/tinymce.min.js" "node_modules/tinymce/tinymce.min.js"
], ],
"assets": ["src/favicon.ico", "src/assets"] "assets": [
"src/assets",
"src/manifest.json"
]
} }
}, },
"lint": { "lint": {
@ -98,7 +110,9 @@
"options": { "options": {
"tsConfig": "src/tsconfig.spec.json", "tsConfig": "src/tsconfig.spec.json",
"format": "stylish", "format": "stylish",
"exclude": ["**/node_modules/**"] "exclude": [
"**/node_modules/**"
]
} }
} }
} }
@ -123,7 +137,9 @@
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-devkit/build-angular:tslint",
"options": { "options": {
"tsConfig": "e2e/tsconfig.e2e.json", "tsConfig": "e2e/tsconfig.e2e.json",
"exclude": ["**/node_modules/**"] "exclude": [
"**/node_modules/**"
]
} }
} }
} }

26
client/ngsw-config.json Normal file
View File

@ -0,0 +1,26 @@
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.png",
"/index.html",
"/*.css",
"/*.js"
]
}
}, {
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**"
]
}
}
]
}

View File

@ -32,7 +32,9 @@
"@angular/material": "^7.1.0", "@angular/material": "^7.1.0",
"@angular/platform-browser": "^7.1.1", "@angular/platform-browser": "^7.1.1",
"@angular/platform-browser-dynamic": "^7.1.1", "@angular/platform-browser-dynamic": "^7.1.1",
"@angular/pwa": "^0.12.1",
"@angular/router": "^7.1.1", "@angular/router": "^7.1.1",
"@angular/service-worker": "^7.1.1",
"@ngx-pwa/local-storage": "^7.2.0", "@ngx-pwa/local-storage": "^7.2.0",
"@ngx-translate/core": "^11.0.1", "@ngx-translate/core": "^11.0.1",
"@ngx-translate/http-loader": "^4.0.0", "@ngx-translate/http-loader": "^4.0.0",

View File

@ -16,6 +16,10 @@ import { PruningTranslationLoader } from './core/pruning-loader';
import { LoginModule } from './site/login/login.module'; import { LoginModule } from './site/login/login.module';
import { AppLoadService } from './core/services/app-load.service'; import { AppLoadService } from './core/services/app-load.service';
// PWA
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
/** /**
* For the translation module. Loads a Custom 'translation loader' and provides it as loader. * For the translation module. Loads a Custom 'translation loader' and provides it as loader.
* @param http Just the HttpClient to load stuff * @param http Just the HttpClient to load stuff
@ -55,7 +59,8 @@ export function AppLoaderFactory(appLoadService: AppLoadService): () => Promise<
AppRoutingModule, AppRoutingModule,
CoreModule, CoreModule,
LoginModule, LoginModule,
PapaParseModule PapaParseModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
], ],
providers: [{ provide: APP_INITIALIZER, useFactory: AppLoaderFactory, deps: [AppLoadService], multi: true }], providers: [{ provide: APP_INITIALIZER, useFactory: AppLoaderFactory, deps: [AppLoadService], multi: true }],
bootstrap: [AppComponent] bootstrap: [AppComponent]

View File

@ -0,0 +1,17 @@
import { TestBed } from '@angular/core/testing';
import { PwaService } from './pwa.service';
import { E2EImportsModule } from 'e2e-imports.module';
describe('PwaService', () => {
beforeEach(() =>
TestBed.configureTestingModule({
imports: [E2EImportsModule]
})
);
it('should be created', () => {
const service: PwaService = TestBed.get(PwaService);
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,25 @@
import { Injectable } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';
/**
* Service for Progressive Web App options
*/
@Injectable({
providedIn: 'root'
})
export class PwaService {
public promptEvent;
public constructor(swUpdate: SwUpdate) {
// check if an update is available
swUpdate.available.subscribe(event => {
// TODO: ask user if app should update now
window.location.reload();
});
// install button
window.addEventListener('beforeinstallprompt', event => {
this.promptEvent = event;
});
}
}

View File

@ -48,7 +48,7 @@ export class ViewportService {
*/ */
public checkForChange(): void { public checkForChange(): void {
this.breakpointObserver this.breakpointObserver
.observe([Breakpoints.Small, Breakpoints.HandsetPortrait]) .observe([Breakpoints.Handset, '(min-width: 600px) and (max-width: 899.99px)'])
.subscribe((state: BreakpointState) => { .subscribe((state: BreakpointState) => {
if (state.matches) { if (state.matches) {
this.isMobile = true; this.isMobile = true;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

View File

@ -3,15 +3,18 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>OpenSlides 3</title> <title>OpenSlides</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="assets/img/favicon.png"> <link rel="icon" type="image/x-icon" href="assets/img/favicon.png">
<link rel="manifest" href="manifest.json" />
<meta name="theme-color" content="#317796">
</head> </head>
<body> <body>
<os-root></os-root> <os-root></os-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
</body> </body>
</html> </html>

51
client/src/manifest.json Normal file
View File

@ -0,0 +1,51 @@
{
"name": "OpenSlides",
"short_name": "OpenSlides",
"theme_color": "#317796",
"background_color": "#317796",
"display": "standalone",
"scope": "/",
"start_url": "/",
"icons": [
{
"src": "/assets/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/assets/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/assets/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "/assets/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/assets/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "/assets/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/assets/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/assets/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}