Merge pull request #4657 from tsiegleauq/service-worker-addons
Service Worker Updates
This commit is contained in:
commit
e1b8e74e8d
@ -1,26 +1,20 @@
|
||||
{
|
||||
"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/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"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/**"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import { OperatorService } from './core/core-services/operator.service';
|
||||
import { ServertimeService } from './core/core-services/servertime.service';
|
||||
import { ThemeService } from './core/ui-services/theme.service';
|
||||
import { DataStoreUpgradeService } from './core/core-services/data-store-upgrade.service';
|
||||
import { UpdateService } from './core/ui-services/update.service';
|
||||
|
||||
/**
|
||||
* Angular's global App Component
|
||||
@ -38,6 +39,8 @@ export class AppComponent {
|
||||
* @param countUsersService to call the constructor of the CountUserService
|
||||
* @param configService to call the constructor of the ConfigService
|
||||
* @param loadFontService to call the constructor of the LoadFontService
|
||||
* @param dataStoreUpgradeService
|
||||
* @param update Service Worker Updates
|
||||
*/
|
||||
public constructor(
|
||||
translate: TranslateService,
|
||||
@ -50,7 +53,8 @@ export class AppComponent {
|
||||
countUsersService: CountUsersService, // Needed to register itself.
|
||||
configService: ConfigService,
|
||||
loadFontService: LoadFontService,
|
||||
dataStoreUpgradeService: DataStoreUpgradeService // to start it.
|
||||
dataStoreUpgradeService: DataStoreUpgradeService, // to start it.
|
||||
update: UpdateService
|
||||
) {
|
||||
// manually add the supported languages
|
||||
translate.addLangs(['en', 'de', 'cs']);
|
||||
|
18
client/src/app/core/ui-services/update.service.spec.ts
Normal file
18
client/src/app/core/ui-services/update.service.spec.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UpdateService } from './update.service';
|
||||
import { E2EImportsModule } from 'e2e-imports.module';
|
||||
|
||||
describe('UpdateService', () => {
|
||||
beforeEach(() =>
|
||||
TestBed.configureTestingModule({
|
||||
imports: [E2EImportsModule],
|
||||
providers: [UpdateService]
|
||||
})
|
||||
);
|
||||
|
||||
it('should be created', () => {
|
||||
const service: UpdateService = TestBed.get(UpdateService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
61
client/src/app/core/ui-services/update.service.ts
Normal file
61
client/src/app/core/ui-services/update.service.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { MatSnackBar } from '@angular/material';
|
||||
import { NotifyService } from '../core-services/notify.service';
|
||||
|
||||
/**
|
||||
* Handle Service Worker updates using the SwUpdate service form angular.
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UpdateService {
|
||||
private static NOTIFY_NAME = 'swCheckForUpdate';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Listens to available updates
|
||||
*
|
||||
* @param swUpdate Service Worker update service
|
||||
* @param matSnackBar Currently to show that an update is available
|
||||
*/
|
||||
public constructor(private swUpdate: SwUpdate, matSnackBar: MatSnackBar, private notify: NotifyService) {
|
||||
swUpdate.available.subscribe(() => {
|
||||
// TODO: Find a better solution OR make an update-bar like for history mode
|
||||
const ref = matSnackBar.open('A new update is available!', 'Refresh', {
|
||||
duration: 0
|
||||
});
|
||||
|
||||
// Enforces an update
|
||||
ref.onAction().subscribe(() => {
|
||||
this.swUpdate.activateUpdate().then(() => {
|
||||
document.location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Listen on requests from other users to check for updates.
|
||||
this.notify.getMessageObservable(UpdateService.NOTIFY_NAME).subscribe(() => {
|
||||
this.checkForUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger that to manually check for updates
|
||||
*/
|
||||
public checkForUpdate(): void {
|
||||
if (this.swUpdate.isEnabled) {
|
||||
this.swUpdate.checkForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a message to all clients initiating to check for updates. This method
|
||||
* can only be called by users with 'users.can_manage'. This will be checked by
|
||||
* the server.
|
||||
*/
|
||||
public initiateUpdateCheckForAllClients(): void {
|
||||
this.notify.sendToAllUsers(UpdateService.NOTIFY_NAME, {});
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<os-head-bar [nav]=false [goBack]=true>
|
||||
<os-head-bar [nav]="false" [goBack]="true">
|
||||
<div class="title-slot">
|
||||
<h2 translate>Legal notice</h2>
|
||||
</div>
|
||||
@ -7,9 +7,29 @@
|
||||
<os-legal-notice-content></os-legal-notice-content>
|
||||
|
||||
<mat-card class="os-card">
|
||||
<button type="button" mat-button (click)="resetCache()">
|
||||
<span translate>Reset cache</span>
|
||||
</button>
|
||||
<div>
|
||||
<button type="button" mat-button (click)="resetCache()">
|
||||
<span translate>Reset cache</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="button" mat-button (click)="checkForUpdate()">
|
||||
<span translate>Check for updates</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div *osPerms="'users.can_manage'">
|
||||
<button
|
||||
type="button"
|
||||
mat-button
|
||||
(click)="initiateUpdateCheckForAllClients()"
|
||||
matTooltip="{{ 'This will send an update notification to all active clients' | translate }}"
|
||||
>
|
||||
<span translate>Initiate update check for all clients</span>
|
||||
<mat-icon class="warning spacer-left-10">warning</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card>
|
||||
|
||||
<os-count-users></os-count-users>
|
||||
|
@ -1,14 +1,23 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { OpenSlidesService } from 'app/core/core-services/openslides.service';
|
||||
import { UpdateService } from 'app/core/ui-services/update.service';
|
||||
|
||||
@Component({
|
||||
selector: 'os-legal-notice',
|
||||
templateUrl: './legal-notice.component.html'
|
||||
})
|
||||
export class LegalNoticeComponent {
|
||||
public constructor(private openSlidesService: OpenSlidesService) {}
|
||||
public constructor(private openSlidesService: OpenSlidesService, private update: UpdateService) {}
|
||||
|
||||
public resetCache(): void {
|
||||
this.openSlidesService.reset();
|
||||
}
|
||||
|
||||
public checkForUpdate(): void {
|
||||
this.update.checkForUpdate();
|
||||
}
|
||||
|
||||
public initiateUpdateCheckForAllClients(): void {
|
||||
this.update.initiateUpdateCheckForAllClients();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Any
|
||||
from typing import Any, Dict
|
||||
|
||||
from ..utils.auth import async_has_perm
|
||||
from ..utils.constants import get_constants
|
||||
from ..utils.projector import get_projector_data
|
||||
from ..utils.websocket import (
|
||||
@ -44,19 +45,34 @@ class NotifyWebsocketClientMessage(BaseWebsocketClientMessage):
|
||||
},
|
||||
"required": ["name", "content"],
|
||||
}
|
||||
# Define a required permission for a notify message here. If the emitting user does not
|
||||
# have this permission, he will get an error message in response.
|
||||
notify_permissions: Dict[str, str] = {"swCheckForUpdate": "users.can_manage"}
|
||||
|
||||
async def receive_content(
|
||||
self, consumer: "ProtocollAsyncJsonWebsocketConsumer", content: Any, id: str
|
||||
) -> None:
|
||||
await consumer.channel_layer.group_send(
|
||||
"site",
|
||||
{
|
||||
"type": "send_notify",
|
||||
"incomming": content,
|
||||
"senderChannelName": consumer.channel_name,
|
||||
"senderUserId": consumer.scope["user"]["id"],
|
||||
},
|
||||
)
|
||||
# Check if the user is allowed to send this notify message
|
||||
perm = self.notify_permissions.get(content["name"])
|
||||
if perm is not None and not await async_has_perm(
|
||||
consumer.scope["user"]["id"], perm
|
||||
):
|
||||
await consumer.send_json(
|
||||
type="error",
|
||||
content=f"You need '{perm}' to send this message.",
|
||||
in_response=id,
|
||||
)
|
||||
else:
|
||||
# Forward to all other active site consumers to handle the notify message.
|
||||
await consumer.channel_layer.group_send(
|
||||
"site",
|
||||
{
|
||||
"type": "send_notify",
|
||||
"incomming": content,
|
||||
"senderChannelName": consumer.channel_name,
|
||||
"senderUserId": consumer.scope["user"]["id"],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class ConstantsWebsocketClientMessage(BaseWebsocketClientMessage):
|
||||
|
Loading…
Reference in New Issue
Block a user