feat: Aggiunto supporto a PWA

This commit is contained in:
Maicol Battistini 2022-01-06 17:19:59 +01:00
parent 636c7ac68e
commit 4744f9434f
No known key found for this signature in database
GPG Key ID: 4FDB0F87CDB1D34A
8 changed files with 128 additions and 67 deletions

View File

@ -72,7 +72,8 @@
"stylelint-config-idiomatic-order": "^8.1.0",
"stylelint-config-recommended-scss": "^5.0.2",
"stylelint-config-standard": "^24.0.0",
"stylelint-scss": "^4.1.0"
"stylelint-scss": "^4.1.0",
"vite-plugin-pwa": "^0.11.12"
},
"publishConfig": {
"access": "public"

View File

@ -59,6 +59,7 @@ specifiers:
stylelint-config-recommended-scss: ^5.0.2
stylelint-config-standard: ^24.0.0
stylelint-scss: ^4.1.0
vite-plugin-pwa: ^0.11.12
dependencies:
'@inertiajs/inertia': 0.10.1
@ -121,6 +122,7 @@ devDependencies:
stylelint-config-recommended-scss: 5.0.2
stylelint-config-standard: 24.0.0
stylelint-scss: 4.1.0
vite-plugin-pwa: 0.11.12
packages:

View File

@ -19,3 +19,8 @@
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
<IfModule mod_mime.c>
# Manifest file
AddType application/manifest+json webmanifest
</IfModule>

View File

@ -10,10 +10,14 @@ import cash from 'cash-dom';
import Mithril from 'mithril';
// noinspection SpellCheckingInspection
import redaxios from 'redaxios';
import {registerSW} from 'virtual:pwa-register';
import type router from 'ziggy-js';
import {type Page} from './Components';
import {__ as translator} from './utils';
import {
__ as translator,
showSnackbar
} from './utils';
// Variabili globali
declare global {
@ -66,3 +70,17 @@ $('#logout-button')
await redaxios.post(route('auth.logout'));
window.location.href = route('auth.login');
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const updateSW = registerSW({
async onNeedRefresh() {
const action = await showSnackbar(__('Aggiornamento del frontend disponibile!'), false, __('Ricarica'), __('Annulla'));
if (action === 'action') {
await updateSW();
}
},
onOfflineReady() {
// eslint-disable-next-line no-void
void showSnackbar(__('È ora possibile lavorare offline!'), false);
}
}) as (reloadPage?: boolean) => Promise<void>;

View File

@ -39,52 +39,46 @@ export async function showSnackbar(
actionText = 'OK',
cancelText: string | false = false,
closeOtherSnackbars = true
): Promise<unknown> {
if (closeOtherSnackbars) {
const snackbars = document.querySelectorAll('mwc-snackbar');
): Promise<string | 'action' | 'dismiss' | undefined> {
return new Promise((resolve, reject) => {
if (closeOtherSnackbars) {
const snackbars = document.querySelectorAll('mwc-snackbar');
for (const snackbar of snackbars) {
if (snackbar.open) {
snackbar.close();
for (const snackbar of snackbars) {
if (snackbar.open) {
snackbar.close();
}
snackbar.remove();
}
snackbar.remove();
}
}
const snackbar = document.createElement('mwc-snackbar');
snackbar.labelText = labelText;
snackbar.timeoutMs = timeoutMs || -1;
const snackbar = document.createElement('mwc-snackbar');
snackbar.labelText = labelText;
snackbar.timeoutMs = timeoutMs || -1;
if (actionText) {
const button = document.createElement('mwc-button');
button.label = actionText;
button.slot = 'action';
snackbar.append(button);
}
if (actionText) {
const button = document.createElement('mwc-button');
button.label = actionText;
button.slot = 'action';
snackbar.append(button);
}
if (cancelText) {
const button = document.createElement('mwc-button');
button.label = cancelText;
button.slot = 'cancel';
snackbar.append(button);
}
if (cancelText) {
const button = document.createElement('mwc-button');
button.label = cancelText;
button.slot = 'cancel';
snackbar.append(button);
}
document.body.append(snackbar);
document.body.append(snackbar);
snackbar.addEventListener('MDCSnackbar:closed', (event: Event & Partial<{detail: {reason?: string}}>) => {
snackbar.close();
resolve(event.detail?.reason);
});
// eslint-disable-next-line unicorn/consistent-function-scoping
const response = (value?: boolean) => value;
// noinspection JSUnusedLocalSymbols
const reasonPromise = new Promise((resolve, reject) => {});
snackbar.addEventListener('MDCSnackbar:closed', (event: Event & Partial<{detail: {reason?: string}}>) => {
response(event?.detail?.reason === 'action' ?? false);
snackbar.show();
});
snackbar.show();
snackbar.addEventListener('MDCSnackbar:closed', () => {
snackbar.remove();
});
return reasonPromise;
}
export function getFormData(form: Cash) {
return Object.fromEntries<string | File>(new FormData(form[0] as HTMLFormElement));

View File

@ -7,10 +7,10 @@
<link rel="apple-touch-icon" sizes="180x180" href="{{vite_asset('images/favicon/apple-touch-icon.png')}}">
<link rel="icon" type="image/png" sizes="32x32" href="{{vite_asset('images/favicon/favicon-32x32.png')}}">
<link rel="icon" type="image/png" sizes="16x16" href="{{vite_asset('images/favicon/favicon-16x16.png')}}">
<link rel="manifest" href="{{vite_asset('images/favicon/site.webmanifest')}}">
<link rel="mask-icon" href="{{vite_asset('images/favicon/safari-pinned-tab.svg')}}" color="#da532c">
<link rel="mask-icon" href="{{vite_asset('images/favicon/safari-pinned-tab.svg')}}" color="#3f3f3f">
<link rel="shortcut icon" href="{{vite_asset('images/favicon/favicon.ico')}}">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="msapplication-config" content="{{vite_asset('images/favicon/browserconfig.xml')}}">
<meta name="theme-color" content="#ffffff">
<meta name="theme-color" content="#3f3f3f">
<meta name="description" content="Your app description">
</head>

View File

@ -1,26 +1,27 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"strictPropertyInitialization": false,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": [
"esnext",
"dom",
"dom.iterable"
],
"types": [
"vite/client"
],
"baseUrl": "."
},
"include": [
"resources/**/*"
]
"compilerOptions": {
"experimentalDecorators": true,
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"strictPropertyInitialization": false,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": [
"esnext",
"dom",
"dom.iterable"
],
"types": [
"vite/client",
"vite-plugin-pwa/client"
],
"baseUrl": "."
},
"include": [
"resources/**/*"
]
}

View File

@ -1,5 +1,45 @@
/* eslint-disable import/no-extraneous-dependencies */
import osmConfig from '@openstamanager/vite-config';
import {defineConfig} from 'laravel-vite';
import {VitePWA} from 'vite-plugin-pwa';
export default defineConfig(osmConfig());
export default defineConfig(osmConfig({
plugins: [
VitePWA({
includeAssets: [
'images/favicon/favicon.ico',
'../robots.txt',
'images/favicon/apple-touch-icon.png',
'images/*.png'
],
manifest: {
name: 'OpenSTAManager',
short_name: 'OSM',
description: 'Il software gestionale open source per l\'assistenza tecnica e la fatturazione',
categories: ['business', 'productivity'],
display: 'minimal-ui',
theme_color: '#3f3f3f',
background_color: '#fffff',
icons: [
{
src: 'android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: 'android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: 'android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable',
}
]
},
useCredentials: true
})
]
}));