Struktura programu z widokami i repozytorium
This commit is contained in:
commit
d42be59ec6
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
node_modules
|
||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
|
||||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
32
frontend/generated/index.ts
Normal file
32
frontend/generated/index.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* This file is auto-generated by Vaadin.
|
||||||
|
* If you want to customize the entry point, you can copy this file or create
|
||||||
|
* your own `index.ts` in your frontend directory.
|
||||||
|
* By default, the `index.ts` file should be in `./frontend/` folder.
|
||||||
|
*
|
||||||
|
* NOTE:
|
||||||
|
* - You need to restart the dev-server after adding the new `index.ts` file.
|
||||||
|
* After that, all modifications to `index.ts` are recompiled automatically.
|
||||||
|
* - `index.js` is also supported if you don't want to use TypeScript.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// import Vaadin client-router to handle client-side and server-side navigation
|
||||||
|
import { Router } from '@vaadin/router';
|
||||||
|
|
||||||
|
// import Flow module to enable navigation to Vaadin server-side views
|
||||||
|
import { Flow } from 'Frontend/generated/jar-resources/Flow.js';
|
||||||
|
|
||||||
|
const { serverSideRoutes } = new Flow({
|
||||||
|
imports: () => import('../../target/frontend/generated-flow-imports.js')
|
||||||
|
});
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
// for client-side, place routes below (more info https://vaadin.com/docs/v15/flow/typescript/creating-routes.html)
|
||||||
|
|
||||||
|
// for server-side, the next magic line sends all unmatched routes:
|
||||||
|
...serverSideRoutes // IMPORTANT: this must be the last entry in the array
|
||||||
|
];
|
||||||
|
|
||||||
|
// Vaadin router needs an outlet in the index.html page to display views
|
||||||
|
const router = new Router(document.querySelector('#outlet'));
|
||||||
|
router.setRoutes(routes);
|
74
frontend/generated/jar-resources/Flow.d.ts
vendored
Normal file
74
frontend/generated/jar-resources/Flow.d.ts
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
export interface FlowConfig {
|
||||||
|
imports?: () => void;
|
||||||
|
}
|
||||||
|
interface AppConfig {
|
||||||
|
productionMode: boolean;
|
||||||
|
appId: string;
|
||||||
|
uidl: any;
|
||||||
|
clientRouting: boolean;
|
||||||
|
}
|
||||||
|
interface AppInitResponse {
|
||||||
|
appConfig: AppConfig;
|
||||||
|
pushScript?: string;
|
||||||
|
}
|
||||||
|
interface Router {
|
||||||
|
render: (ctx: NavigationParameters, shouldUpdateHistory: boolean) => Promise<void>;
|
||||||
|
}
|
||||||
|
interface HTMLRouterContainer extends HTMLElement {
|
||||||
|
onBeforeEnter?: (ctx: NavigationParameters, cmd: PreventAndRedirectCommands, router: Router) => void | Promise<any>;
|
||||||
|
onBeforeLeave?: (ctx: NavigationParameters, cmd: PreventCommands, router: Router) => void | Promise<any>;
|
||||||
|
serverConnected?: (cancel: boolean, url?: NavigationParameters) => void;
|
||||||
|
}
|
||||||
|
interface FlowRoute {
|
||||||
|
action: (params: NavigationParameters) => Promise<HTMLRouterContainer>;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
export interface NavigationParameters {
|
||||||
|
pathname: string;
|
||||||
|
search: string;
|
||||||
|
}
|
||||||
|
export interface PreventCommands {
|
||||||
|
prevent: () => any;
|
||||||
|
}
|
||||||
|
export interface PreventAndRedirectCommands extends PreventCommands {
|
||||||
|
redirect: (route: string) => any;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Client API for flow UI operations.
|
||||||
|
*/
|
||||||
|
export declare class Flow {
|
||||||
|
config: FlowConfig;
|
||||||
|
response?: AppInitResponse;
|
||||||
|
pathname: string;
|
||||||
|
container: HTMLRouterContainer;
|
||||||
|
private isActive;
|
||||||
|
private baseRegex;
|
||||||
|
private appShellTitle;
|
||||||
|
constructor(config?: FlowConfig);
|
||||||
|
/**
|
||||||
|
* Return a `route` object for vaadin-router in an one-element array.
|
||||||
|
*
|
||||||
|
* The `FlowRoute` object `path` property handles any route,
|
||||||
|
* and the `action` returns the flow container without updating the content,
|
||||||
|
* delaying the actual Flow server call to the `onBeforeEnter` phase.
|
||||||
|
*
|
||||||
|
* This is a specific API for its use with `vaadin-router`.
|
||||||
|
*/
|
||||||
|
get serverSideRoutes(): [FlowRoute];
|
||||||
|
loadingStarted(): void;
|
||||||
|
loadingFinished(): void;
|
||||||
|
private get action();
|
||||||
|
private flowLeave;
|
||||||
|
private flowNavigate;
|
||||||
|
private getFlowRoutePath;
|
||||||
|
private getFlowRouteQuery;
|
||||||
|
private flowInit;
|
||||||
|
private loadScript;
|
||||||
|
private injectAppIdScript;
|
||||||
|
private flowInitClient;
|
||||||
|
private flowInitUi;
|
||||||
|
private addConnectionIndicator;
|
||||||
|
private offlineStubAction;
|
||||||
|
private isFlowClientLoaded;
|
||||||
|
}
|
||||||
|
export {};
|
324
frontend/generated/jar-resources/Flow.js
Normal file
324
frontend/generated/jar-resources/Flow.js
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
import { ConnectionIndicator, ConnectionState } from '@vaadin/common-frontend';
|
||||||
|
class FlowUiInitializationError extends Error {
|
||||||
|
}
|
||||||
|
// flow uses body for keeping references
|
||||||
|
const flowRoot = window.document.body;
|
||||||
|
const $wnd = window;
|
||||||
|
/**
|
||||||
|
* Client API for flow UI operations.
|
||||||
|
*/
|
||||||
|
export class Flow {
|
||||||
|
constructor(config) {
|
||||||
|
this.response = undefined;
|
||||||
|
this.pathname = '';
|
||||||
|
// flag used to inform Testbench whether a server route is in progress
|
||||||
|
this.isActive = false;
|
||||||
|
this.baseRegex = /^\//;
|
||||||
|
flowRoot.$ = flowRoot.$ || [];
|
||||||
|
this.config = config || {};
|
||||||
|
// TB checks for the existence of window.Vaadin.Flow in order
|
||||||
|
// to consider that TB needs to wait for `initFlow()`.
|
||||||
|
$wnd.Vaadin = $wnd.Vaadin || {};
|
||||||
|
$wnd.Vaadin.Flow = $wnd.Vaadin.Flow || {};
|
||||||
|
$wnd.Vaadin.Flow.clients = {
|
||||||
|
TypeScript: {
|
||||||
|
isActive: () => this.isActive
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Regular expression used to remove the app-context
|
||||||
|
const elm = document.head.querySelector('base');
|
||||||
|
this.baseRegex = new RegExp(`^${
|
||||||
|
// IE11 does not support document.baseURI
|
||||||
|
(document.baseURI || (elm && elm.href) || '/').replace(/^https?:\/\/[^/]+/i, '')}`);
|
||||||
|
this.appShellTitle = document.title;
|
||||||
|
// Put a vaadin-connection-indicator in the dom
|
||||||
|
this.addConnectionIndicator();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Return a `route` object for vaadin-router in an one-element array.
|
||||||
|
*
|
||||||
|
* The `FlowRoute` object `path` property handles any route,
|
||||||
|
* and the `action` returns the flow container without updating the content,
|
||||||
|
* delaying the actual Flow server call to the `onBeforeEnter` phase.
|
||||||
|
*
|
||||||
|
* This is a specific API for its use with `vaadin-router`.
|
||||||
|
*/
|
||||||
|
get serverSideRoutes() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
path: '(.*)',
|
||||||
|
action: this.action
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
loadingStarted() {
|
||||||
|
// Make Testbench know that server request is in progress
|
||||||
|
this.isActive = true;
|
||||||
|
$wnd.Vaadin.connectionState.loadingStarted();
|
||||||
|
}
|
||||||
|
loadingFinished() {
|
||||||
|
// Make Testbench know that server request has finished
|
||||||
|
this.isActive = false;
|
||||||
|
$wnd.Vaadin.connectionState.loadingFinished();
|
||||||
|
}
|
||||||
|
get action() {
|
||||||
|
// Return a function which is bound to the flow instance, thus we can use
|
||||||
|
// the syntax `...serverSideRoutes` in vaadin-router.
|
||||||
|
return async (params) => {
|
||||||
|
// Store last action pathname so as we can check it in events
|
||||||
|
this.pathname = params.pathname;
|
||||||
|
if ($wnd.Vaadin.connectionState.online) {
|
||||||
|
try {
|
||||||
|
await this.flowInit();
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error instanceof FlowUiInitializationError) {
|
||||||
|
// error initializing Flow: assume connection lost
|
||||||
|
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTION_LOST;
|
||||||
|
return this.offlineStubAction();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// insert an offline stub
|
||||||
|
return this.offlineStubAction();
|
||||||
|
}
|
||||||
|
// When an action happens, navigation will be resolved `onBeforeEnter`
|
||||||
|
this.container.onBeforeEnter = (ctx, cmd) => this.flowNavigate(ctx, cmd);
|
||||||
|
// For covering the 'server -> client' use case
|
||||||
|
this.container.onBeforeLeave = (ctx, cmd) => this.flowLeave(ctx, cmd);
|
||||||
|
return this.container;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Send a remote call to `JavaScriptBootstrapUI` to check
|
||||||
|
// whether navigation has to be cancelled.
|
||||||
|
async flowLeave(ctx, cmd) {
|
||||||
|
// server -> server, viewing offline stub, or browser is offline
|
||||||
|
const { connectionState } = $wnd.Vaadin;
|
||||||
|
if (this.pathname === ctx.pathname || !this.isFlowClientLoaded() || connectionState.offline) {
|
||||||
|
return Promise.resolve({});
|
||||||
|
}
|
||||||
|
// 'server -> client'
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.loadingStarted();
|
||||||
|
// The callback to run from server side to cancel navigation
|
||||||
|
this.container.serverConnected = (cancel) => {
|
||||||
|
resolve(cmd && cancel ? cmd.prevent() : {});
|
||||||
|
this.loadingFinished();
|
||||||
|
};
|
||||||
|
// Call server side to check whether we can leave the view
|
||||||
|
flowRoot.$server.leaveNavigation(this.getFlowRoutePath(ctx), this.getFlowRouteQuery(ctx));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Send the remote call to `JavaScriptBootstrapUI` to render the flow
|
||||||
|
// route specified by the context
|
||||||
|
async flowNavigate(ctx, cmd) {
|
||||||
|
if (this.response) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.loadingStarted();
|
||||||
|
// The callback to run from server side once the view is ready
|
||||||
|
this.container.serverConnected = (cancel, redirectContext) => {
|
||||||
|
if (cmd && cancel) {
|
||||||
|
resolve(cmd.prevent());
|
||||||
|
}
|
||||||
|
else if (cmd && cmd.redirect && redirectContext) {
|
||||||
|
resolve(cmd.redirect(redirectContext.pathname));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.container.style.display = '';
|
||||||
|
resolve(this.container);
|
||||||
|
}
|
||||||
|
this.loadingFinished();
|
||||||
|
};
|
||||||
|
// Call server side to navigate to the given route
|
||||||
|
flowRoot.$server.connectClient(this.container.localName, this.container.id, this.getFlowRoutePath(ctx), this.getFlowRouteQuery(ctx), this.appShellTitle, history.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No server response => offline or erroneous connection
|
||||||
|
return Promise.resolve(this.container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getFlowRoutePath(context) {
|
||||||
|
return decodeURIComponent(context.pathname).replace(this.baseRegex, '');
|
||||||
|
}
|
||||||
|
getFlowRouteQuery(context) {
|
||||||
|
return (context.search && context.search.substring(1)) || '';
|
||||||
|
}
|
||||||
|
// import flow client modules and initialize UI in server side.
|
||||||
|
async flowInit(serverSideRouting = false) {
|
||||||
|
// Do not start flow twice
|
||||||
|
if (!this.isFlowClientLoaded()) {
|
||||||
|
// show flow progress indicator
|
||||||
|
this.loadingStarted();
|
||||||
|
// Initialize server side UI
|
||||||
|
this.response = await this.flowInitUi(serverSideRouting);
|
||||||
|
// Enable or disable server side routing
|
||||||
|
this.response.appConfig.clientRouting = !serverSideRouting;
|
||||||
|
const { pushScript, appConfig } = this.response;
|
||||||
|
if (typeof pushScript === 'string') {
|
||||||
|
await this.loadScript(pushScript);
|
||||||
|
}
|
||||||
|
const { appId } = appConfig;
|
||||||
|
// Load bootstrap script with server side parameters
|
||||||
|
const bootstrapMod = await import('./FlowBootstrap');
|
||||||
|
await bootstrapMod.init(this.response);
|
||||||
|
// Load custom modules defined by user
|
||||||
|
if (typeof this.config.imports === 'function') {
|
||||||
|
this.injectAppIdScript(appId);
|
||||||
|
await this.config.imports();
|
||||||
|
}
|
||||||
|
// Load flow-client module
|
||||||
|
const clientMod = await import('./FlowClient');
|
||||||
|
await this.flowInitClient(clientMod);
|
||||||
|
if (!serverSideRouting) {
|
||||||
|
// we use a custom tag for the flow app container
|
||||||
|
const tag = `flow-container-${appId.toLowerCase()}`;
|
||||||
|
this.container = document.createElement(tag);
|
||||||
|
flowRoot.$[appId] = this.container;
|
||||||
|
this.container.id = appId;
|
||||||
|
}
|
||||||
|
// hide flow progress indicator
|
||||||
|
this.loadingFinished();
|
||||||
|
}
|
||||||
|
// It might be that components created from server expect that their content has been rendered.
|
||||||
|
// Appending eagerly the container we avoid these kind of errors.
|
||||||
|
// Note that the client router will move this container to the outlet if the navigation succeed
|
||||||
|
if (this.container && !this.container.isConnected) {
|
||||||
|
this.container.style.display = 'none';
|
||||||
|
document.body.appendChild(this.container);
|
||||||
|
}
|
||||||
|
return this.response;
|
||||||
|
}
|
||||||
|
async loadScript(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.onload = () => resolve();
|
||||||
|
script.onerror = reject;
|
||||||
|
script.src = url;
|
||||||
|
document.body.appendChild(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
injectAppIdScript(appId) {
|
||||||
|
const appIdWithoutHashCode = appId.substring(0, appId.lastIndexOf('-'));
|
||||||
|
const scriptAppId = document.createElement('script');
|
||||||
|
scriptAppId.type = 'module';
|
||||||
|
scriptAppId.setAttribute('data-app-id', appIdWithoutHashCode);
|
||||||
|
document.body.append(scriptAppId);
|
||||||
|
}
|
||||||
|
// After the flow-client javascript module has been loaded, this initializes flow UI
|
||||||
|
// in the browser.
|
||||||
|
async flowInitClient(clientMod) {
|
||||||
|
clientMod.init();
|
||||||
|
// client init is async, we need to loop until initialized
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
// client `isActive() == true` while initializing or processing
|
||||||
|
const initializing = Object.keys($wnd.Vaadin.Flow.clients)
|
||||||
|
.filter((key) => key !== 'TypeScript')
|
||||||
|
.reduce((prev, id) => prev || $wnd.Vaadin.Flow.clients[id].isActive(), false);
|
||||||
|
if (!initializing) {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 5);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Returns the `appConfig` object
|
||||||
|
async flowInitUi(serverSideRouting) {
|
||||||
|
// appConfig was sent in the index.html request
|
||||||
|
const initial = $wnd.Vaadin && $wnd.Vaadin.TypeScript && $wnd.Vaadin.TypeScript.initial;
|
||||||
|
if (initial) {
|
||||||
|
$wnd.Vaadin.TypeScript.initial = undefined;
|
||||||
|
return Promise.resolve(initial);
|
||||||
|
}
|
||||||
|
// send a request to the `JavaScriptBootstrapHandler`
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
const httpRequest = xhr;
|
||||||
|
const serverRoutingParam = serverSideRouting ? '&serverSideRouting' : '';
|
||||||
|
const requestPath = `?v-r=init&location=${encodeURIComponent(this.getFlowRoutePath(location))}&query=${encodeURIComponent(this.getFlowRouteQuery(location))}${serverRoutingParam}`;
|
||||||
|
httpRequest.open('GET', requestPath);
|
||||||
|
httpRequest.onerror = () => reject(new FlowUiInitializationError(`Invalid server response when initializing Flow UI.
|
||||||
|
${httpRequest.status}
|
||||||
|
${httpRequest.responseText}`));
|
||||||
|
httpRequest.onload = () => {
|
||||||
|
const contentType = httpRequest.getResponseHeader('content-type');
|
||||||
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
||||||
|
resolve(JSON.parse(httpRequest.responseText));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
httpRequest.onerror();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
httpRequest.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Create shared connection state store and connection indicator
|
||||||
|
addConnectionIndicator() {
|
||||||
|
// add connection indicator to DOM
|
||||||
|
ConnectionIndicator.create();
|
||||||
|
// Listen to browser online/offline events and update the loading indicator accordingly.
|
||||||
|
// Note: if flow-client is loaded, it instead handles the state transitions.
|
||||||
|
$wnd.addEventListener('online', () => {
|
||||||
|
if (!this.isFlowClientLoaded()) {
|
||||||
|
// Send an HTTP HEAD request for sw.js to verify server reachability.
|
||||||
|
// We do not expect sw.js to be cached, so the request goes to the
|
||||||
|
// server rather than being served from local cache.
|
||||||
|
// Require network-level failure to revert the state to CONNECTION_LOST
|
||||||
|
// (HTTP error code is ok since it still verifies server's presence).
|
||||||
|
$wnd.Vaadin.connectionState.state = ConnectionState.RECONNECTING;
|
||||||
|
const http = new XMLHttpRequest();
|
||||||
|
http.open('HEAD', 'sw.js');
|
||||||
|
http.onload = () => {
|
||||||
|
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTED;
|
||||||
|
};
|
||||||
|
http.onerror = () => {
|
||||||
|
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTION_LOST;
|
||||||
|
};
|
||||||
|
// Postpone request to reduce potential net::ERR_INTERNET_DISCONNECTED
|
||||||
|
// errors that sometimes occurs even if browser says it is online
|
||||||
|
setTimeout(() => http.send(), 50);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$wnd.addEventListener('offline', () => {
|
||||||
|
if (!this.isFlowClientLoaded()) {
|
||||||
|
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTION_LOST;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async offlineStubAction() {
|
||||||
|
const offlineStub = document.createElement('iframe');
|
||||||
|
const offlineStubPath = './offline-stub.html';
|
||||||
|
offlineStub.setAttribute('src', offlineStubPath);
|
||||||
|
offlineStub.setAttribute('style', 'width: 100%; height: 100%; border: 0');
|
||||||
|
this.response = undefined;
|
||||||
|
let onlineListener;
|
||||||
|
const removeOfflineStubAndOnlineListener = () => {
|
||||||
|
if (onlineListener !== undefined) {
|
||||||
|
$wnd.Vaadin.connectionState.removeStateChangeListener(onlineListener);
|
||||||
|
onlineListener = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
offlineStub.onBeforeEnter = (ctx, _cmds, router) => {
|
||||||
|
onlineListener = () => {
|
||||||
|
if ($wnd.Vaadin.connectionState.online) {
|
||||||
|
removeOfflineStubAndOnlineListener();
|
||||||
|
router.render(ctx, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$wnd.Vaadin.connectionState.addStateChangeListener(onlineListener);
|
||||||
|
};
|
||||||
|
offlineStub.onBeforeLeave = (_ctx, _cmds, _router) => {
|
||||||
|
removeOfflineStubAndOnlineListener();
|
||||||
|
};
|
||||||
|
return offlineStub;
|
||||||
|
}
|
||||||
|
isFlowClientLoaded() {
|
||||||
|
return this.response !== undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=Flow.js.map
|
1
frontend/generated/jar-resources/Flow.js.map
Normal file
1
frontend/generated/jar-resources/Flow.js.map
Normal file
File diff suppressed because one or more lines are too long
1
frontend/generated/jar-resources/FlowBootstrap.d.ts
vendored
Normal file
1
frontend/generated/jar-resources/FlowBootstrap.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const init: (appInitResponse: any) => void;
|
262
frontend/generated/jar-resources/FlowBootstrap.js
Normal file
262
frontend/generated/jar-resources/FlowBootstrap.js
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/* This is a copy of the regular `BootstrapHandler.js` in the flow-server
|
||||||
|
module, but with the following modifications:
|
||||||
|
- The main function is exported as an ES module for lazy initialization.
|
||||||
|
- Application configuration is passed as a parameter instead of using
|
||||||
|
replacement placeholders as in the regular bootstrapping.
|
||||||
|
- It reuses `Vaadin.Flow.clients` if exists.
|
||||||
|
- Fixed lint errors.
|
||||||
|
*/
|
||||||
|
const init = function (appInitResponse) {
|
||||||
|
window.Vaadin = window.Vaadin || {};
|
||||||
|
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||||
|
|
||||||
|
var apps = {};
|
||||||
|
var widgetsets = {};
|
||||||
|
|
||||||
|
var log;
|
||||||
|
if (typeof window.console === undefined || !window.location.search.match(/[&?]debug(&|$)/)) {
|
||||||
|
/* If no console.log present, just use a no-op */
|
||||||
|
log = function () {};
|
||||||
|
} else if (typeof window.console.log === 'function') {
|
||||||
|
/* If it's a function, use it with apply */
|
||||||
|
log = function () {
|
||||||
|
window.console.log.apply(window.console, arguments);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
/* In IE, its a native function for which apply is not defined, but it works
|
||||||
|
without a proper 'this' reference */
|
||||||
|
log = window.console.log;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isInitializedInDom = function (appId) {
|
||||||
|
var appDiv = document.getElementById(appId);
|
||||||
|
if (!appDiv) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < appDiv.childElementCount; i++) {
|
||||||
|
var className = appDiv.childNodes[i].className;
|
||||||
|
/* If the app div contains a child with the class
|
||||||
|
'v-app-loading' we have only received the HTML
|
||||||
|
but not yet started the widget set
|
||||||
|
(UIConnector removes the v-app-loading div). */
|
||||||
|
if (className && className.indexOf('v-app-loading') != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Needed for Testbench compatibility, but prevents any Vaadin 7 app from
|
||||||
|
* bootstrapping unless the legacy vaadinBootstrap.js file is loaded before
|
||||||
|
* this script.
|
||||||
|
*/
|
||||||
|
window.Vaadin = window.Vaadin || {};
|
||||||
|
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Needed for wrapping custom javascript functionality in the components (i.e. connectors)
|
||||||
|
*/
|
||||||
|
window.Vaadin.Flow.tryCatchWrapper = function (originalFunction, component) {
|
||||||
|
return function () {
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const result = originalFunction.apply(this, arguments);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`There seems to be an error in ${component}:
|
||||||
|
${error.message}
|
||||||
|
Please submit an issue to https://github.com/vaadin/flow-components/issues/new/choose`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.Vaadin.Flow.initApplication) {
|
||||||
|
window.Vaadin.Flow.clients = window.Vaadin.Flow.clients || {};
|
||||||
|
|
||||||
|
window.Vaadin.Flow.initApplication = function (appId, config) {
|
||||||
|
var testbenchId = appId.replace(/-\d+$/, '');
|
||||||
|
|
||||||
|
if (apps[appId]) {
|
||||||
|
if (
|
||||||
|
window.Vaadin &&
|
||||||
|
window.Vaadin.Flow &&
|
||||||
|
window.Vaadin.Flow.clients &&
|
||||||
|
window.Vaadin.Flow.clients[testbenchId] &&
|
||||||
|
window.Vaadin.Flow.clients[testbenchId].initializing
|
||||||
|
) {
|
||||||
|
throw new Error('Application ' + appId + ' is already being initialized');
|
||||||
|
}
|
||||||
|
if (isInitializedInDom(appId)) {
|
||||||
|
throw new Error('Application ' + appId + ' already initialized');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log('init application', appId, config);
|
||||||
|
|
||||||
|
window.Vaadin.Flow.clients[testbenchId] = {
|
||||||
|
isActive: function () {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
initializing: true,
|
||||||
|
productionMode: mode
|
||||||
|
};
|
||||||
|
|
||||||
|
var getConfig = function (name) {
|
||||||
|
var value = config[name];
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Export public data */
|
||||||
|
var app = {
|
||||||
|
getConfig: getConfig
|
||||||
|
};
|
||||||
|
apps[appId] = app;
|
||||||
|
|
||||||
|
if (!window.name) {
|
||||||
|
window.name = appId + '-' + Math.random();
|
||||||
|
}
|
||||||
|
|
||||||
|
var widgetset = 'client';
|
||||||
|
widgetsets[widgetset] = {
|
||||||
|
pendingApps: []
|
||||||
|
};
|
||||||
|
if (widgetsets[widgetset].callback) {
|
||||||
|
log('Starting from bootstrap', appId);
|
||||||
|
widgetsets[widgetset].callback(appId);
|
||||||
|
} else {
|
||||||
|
log('Setting pending startup', appId);
|
||||||
|
widgetsets[widgetset].pendingApps.push(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return app;
|
||||||
|
};
|
||||||
|
window.Vaadin.Flow.getAppIds = function () {
|
||||||
|
var ids = [];
|
||||||
|
for (var id in apps) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(apps, id)) {
|
||||||
|
ids.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
};
|
||||||
|
window.Vaadin.Flow.getApp = function (appId) {
|
||||||
|
return apps[appId];
|
||||||
|
};
|
||||||
|
window.Vaadin.Flow.registerWidgetset = function (widgetset, callback) {
|
||||||
|
log('Widgetset registered', widgetset);
|
||||||
|
var ws = widgetsets[widgetset];
|
||||||
|
if (ws && ws.pendingApps) {
|
||||||
|
ws.callback = callback;
|
||||||
|
for (var i = 0; i < ws.pendingApps.length; i++) {
|
||||||
|
var appId = ws.pendingApps[i];
|
||||||
|
log('Starting from register widgetset', appId);
|
||||||
|
callback(appId);
|
||||||
|
}
|
||||||
|
ws.pendingApps = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.Vaadin.Flow.getBrowserDetailsParameters = function () {
|
||||||
|
var params = {};
|
||||||
|
|
||||||
|
/* Screen height and width */
|
||||||
|
params['v-sh'] = window.screen.height;
|
||||||
|
params['v-sw'] = window.screen.width;
|
||||||
|
/* Browser window dimensions */
|
||||||
|
params['v-wh'] = window.innerHeight;
|
||||||
|
params['v-ww'] = window.innerWidth;
|
||||||
|
/* Body element dimensions */
|
||||||
|
params['v-bh'] = document.body.clientHeight;
|
||||||
|
params['v-bw'] = document.body.clientWidth;
|
||||||
|
|
||||||
|
/* Current time */
|
||||||
|
var date = new Date();
|
||||||
|
params['v-curdate'] = date.getTime();
|
||||||
|
|
||||||
|
/* Current timezone offset (including DST shift) */
|
||||||
|
var tzo1 = date.getTimezoneOffset();
|
||||||
|
|
||||||
|
/* Compare the current tz offset with the first offset from the end
|
||||||
|
of the year that differs --- if less that, we are in DST, otherwise
|
||||||
|
we are in normal time */
|
||||||
|
var dstDiff = 0;
|
||||||
|
var rawTzo = tzo1;
|
||||||
|
for (var m = 12; m > 0; m--) {
|
||||||
|
date.setUTCMonth(m);
|
||||||
|
var tzo2 = date.getTimezoneOffset();
|
||||||
|
if (tzo1 != tzo2) {
|
||||||
|
dstDiff = tzo1 > tzo2 ? tzo1 - tzo2 : tzo2 - tzo1;
|
||||||
|
rawTzo = tzo1 > tzo2 ? tzo1 : tzo2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Time zone offset */
|
||||||
|
params['v-tzo'] = tzo1;
|
||||||
|
|
||||||
|
/* DST difference */
|
||||||
|
params['v-dstd'] = dstDiff;
|
||||||
|
|
||||||
|
/* Time zone offset without DST */
|
||||||
|
params['v-rtzo'] = rawTzo;
|
||||||
|
|
||||||
|
/* DST in effect? */
|
||||||
|
params['v-dston'] = tzo1 != rawTzo;
|
||||||
|
|
||||||
|
/* Time zone id (if available) */
|
||||||
|
try {
|
||||||
|
params['v-tzid'] = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
} catch (err) {
|
||||||
|
params['v-tzid'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Window name */
|
||||||
|
if (window.name) {
|
||||||
|
params['v-wn'] = window.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detect touch device support */
|
||||||
|
var supportsTouch = false;
|
||||||
|
try {
|
||||||
|
document.createEvent('TouchEvent');
|
||||||
|
supportsTouch = true;
|
||||||
|
} catch (e) {
|
||||||
|
/* Chrome and IE10 touch detection */
|
||||||
|
supportsTouch = 'ontouchstart' in window || typeof navigator.msMaxTouchPoints !== 'undefined';
|
||||||
|
}
|
||||||
|
params['v-td'] = supportsTouch;
|
||||||
|
|
||||||
|
/* Device Pixel Ratio */
|
||||||
|
params['v-pr'] = window.devicePixelRatio;
|
||||||
|
|
||||||
|
if (navigator.platform) {
|
||||||
|
params['v-np'] = navigator.platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stringify each value (they are parsed on the server side) */
|
||||||
|
Object.keys(params).forEach(function (key) {
|
||||||
|
var value = params[key];
|
||||||
|
if (typeof value !== 'undefined') {
|
||||||
|
params[key] = value.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
log('Flow bootstrap loaded');
|
||||||
|
if (appInitResponse.appConfig.productionMode && typeof window.__gwtStatsEvent != 'function') {
|
||||||
|
window.Vaadin.Flow.gwtStatsEvents = [];
|
||||||
|
window.__gwtStatsEvent = function (event) {
|
||||||
|
window.Vaadin.Flow.gwtStatsEvents.push(event);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var config = appInitResponse.appConfig;
|
||||||
|
var mode = appInitResponse.appConfig.productionMode;
|
||||||
|
window.Vaadin.Flow.initApplication(config.appId, config);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { init };
|
1
frontend/generated/jar-resources/FlowClient.d.ts
vendored
Normal file
1
frontend/generated/jar-resources/FlowClient.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const init: () => void;
|
1100
frontend/generated/jar-resources/FlowClient.js
Normal file
1100
frontend/generated/jar-resources/FlowClient.js
Normal file
File diff suppressed because one or more lines are too long
14
frontend/generated/jar-resources/License.d.ts
vendored
Normal file
14
frontend/generated/jar-resources/License.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
export interface Product {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
export interface ProductAndMessage {
|
||||||
|
message: string;
|
||||||
|
messageHtml?: string;
|
||||||
|
product: Product;
|
||||||
|
}
|
||||||
|
export declare const findAll: (element: Element | ShadowRoot | Document, tags: string[]) => Element[];
|
||||||
|
export declare const licenseCheckOk: (data: Product) => void;
|
||||||
|
export declare const licenseCheckFailed: (data: ProductAndMessage) => void;
|
||||||
|
export declare const licenseCheckNoKey: (data: ProductAndMessage) => void;
|
||||||
|
export declare const licenseInit: () => void;
|
110
frontend/generated/jar-resources/License.js
Normal file
110
frontend/generated/jar-resources/License.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
const noLicenseFallbackTimeout = 1000;
|
||||||
|
export const findAll = (element, tags) => {
|
||||||
|
const lightDom = Array.from(element.querySelectorAll(tags.join(', ')));
|
||||||
|
const shadowDom = Array.from(element.querySelectorAll('*'))
|
||||||
|
.filter((e) => e.shadowRoot)
|
||||||
|
.flatMap((e) => findAll(e.shadowRoot, tags));
|
||||||
|
return [...lightDom, ...shadowDom];
|
||||||
|
};
|
||||||
|
let licenseCheckListener = false;
|
||||||
|
const showNoLicenseFallback = (element, productAndMessage) => {
|
||||||
|
if (!licenseCheckListener) {
|
||||||
|
// When a license check has succeeded, refresh so that all elements are properly shown again
|
||||||
|
window.addEventListener('message', (e) => {
|
||||||
|
if (e.data === 'validate-license') {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
licenseCheckListener = true;
|
||||||
|
}
|
||||||
|
const overlay = element._overlayElement;
|
||||||
|
if (overlay) {
|
||||||
|
if (overlay.shadowRoot) {
|
||||||
|
const defaultSlot = overlay.shadowRoot.querySelector('slot:not([name])');
|
||||||
|
if (defaultSlot && defaultSlot.assignedElements().length > 0) {
|
||||||
|
showNoLicenseFallback(defaultSlot.assignedElements()[0], productAndMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showNoLicenseFallback(overlay, productAndMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const htmlMessage = productAndMessage.messageHtml
|
||||||
|
? productAndMessage.messageHtml
|
||||||
|
: `${productAndMessage.message} <p>Component: ${productAndMessage.product.name} ${productAndMessage.product.version}</p>`.replace(/https:([^ ]*)/g, "<a href='https:$1'>https:$1</a>");
|
||||||
|
if (element.isConnected) {
|
||||||
|
element.outerHTML = `<no-license style="display:flex;align-items:center;text-align:center;justify-content:center;"><div>${htmlMessage}</div></no-license>`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const productTagNames = {};
|
||||||
|
const productChecking = {};
|
||||||
|
const productMissingLicense = {};
|
||||||
|
const productCheckOk = {};
|
||||||
|
const key = (product) => {
|
||||||
|
return `${product.name}_${product.version}`;
|
||||||
|
};
|
||||||
|
const checkLicenseIfNeeded = (cvdlElement) => {
|
||||||
|
var _a;
|
||||||
|
const { cvdlName, version } = cvdlElement.constructor;
|
||||||
|
const product = { name: cvdlName, version };
|
||||||
|
const tagName = cvdlElement.tagName.toLowerCase();
|
||||||
|
productTagNames[cvdlName] = (_a = productTagNames[cvdlName]) !== null && _a !== void 0 ? _a : [];
|
||||||
|
productTagNames[cvdlName].push(tagName);
|
||||||
|
const failedLicenseCheck = productMissingLicense[key(product)];
|
||||||
|
if (failedLicenseCheck) {
|
||||||
|
// Has been checked and the check failed
|
||||||
|
setTimeout(() => showNoLicenseFallback(cvdlElement, failedLicenseCheck), noLicenseFallbackTimeout);
|
||||||
|
}
|
||||||
|
if (productMissingLicense[key(product)] || productCheckOk[key(product)]) {
|
||||||
|
// Already checked
|
||||||
|
}
|
||||||
|
else if (!productChecking[key(product)]) {
|
||||||
|
// Has not been checked
|
||||||
|
productChecking[key(product)] = true;
|
||||||
|
window.Vaadin.devTools.checkLicense(product);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const licenseCheckOk = (data) => {
|
||||||
|
productCheckOk[key(data)] = true;
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.debug('License check ok for', data);
|
||||||
|
};
|
||||||
|
export const licenseCheckFailed = (data) => {
|
||||||
|
const productName = data.product.name;
|
||||||
|
productMissingLicense[key(data.product)] = data;
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('License check failed for', productName);
|
||||||
|
const tags = productTagNames[productName];
|
||||||
|
if ((tags === null || tags === void 0 ? void 0 : tags.length) > 0) {
|
||||||
|
findAll(document, tags).forEach((element) => {
|
||||||
|
setTimeout(() => showNoLicenseFallback(element, productMissingLicense[key(data.product)]), noLicenseFallbackTimeout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const licenseCheckNoKey = (data) => {
|
||||||
|
const keyUrl = data.message;
|
||||||
|
const productName = data.product.name;
|
||||||
|
data.messageHtml = `No license found. <a target=_blank onclick="javascript:window.open(this.href);return false;" href="${keyUrl}">Go here to start a trial or retrieve your license.</a>`;
|
||||||
|
productMissingLicense[key(data.product)] = data;
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('No license found when checking', productName);
|
||||||
|
const tags = productTagNames[productName];
|
||||||
|
if ((tags === null || tags === void 0 ? void 0 : tags.length) > 0) {
|
||||||
|
findAll(document, tags).forEach((element) => {
|
||||||
|
setTimeout(() => showNoLicenseFallback(element, productMissingLicense[key(data.product)]), noLicenseFallbackTimeout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const licenseInit = () => {
|
||||||
|
// Process already registered elements
|
||||||
|
window.Vaadin.devTools.createdCvdlElements.forEach((element) => {
|
||||||
|
checkLicenseIfNeeded(element);
|
||||||
|
});
|
||||||
|
// Handle new elements directly
|
||||||
|
window.Vaadin.devTools.createdCvdlElements = {
|
||||||
|
push: (element) => {
|
||||||
|
checkLicenseIfNeeded(element);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=License.js.map
|
1
frontend/generated/jar-resources/License.js.map
Normal file
1
frontend/generated/jar-resources/License.js.map
Normal file
File diff suppressed because one or more lines are too long
284
frontend/generated/jar-resources/comboBoxConnector.js
Normal file
284
frontend/generated/jar-resources/comboBoxConnector.js
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
||||||
|
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
|
||||||
|
import { ComboBoxPlaceholder } from '@vaadin/combo-box/src/vaadin-combo-box-placeholder.js';
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const tryCatchWrapper = function (callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Combo Box');
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Vaadin.Flow.comboBoxConnector = {
|
||||||
|
initLazy: (comboBox) =>
|
||||||
|
tryCatchWrapper(function (comboBox) {
|
||||||
|
// Check whether the connector was already initialized for the ComboBox
|
||||||
|
if (comboBox.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
comboBox.$connector = {};
|
||||||
|
|
||||||
|
// holds pageIndex -> callback pairs of subsequent indexes (current active range)
|
||||||
|
const pageCallbacks = {};
|
||||||
|
let cache = {};
|
||||||
|
let lastFilter = '';
|
||||||
|
const placeHolder = new window.Vaadin.ComboBoxPlaceholder();
|
||||||
|
|
||||||
|
const serverFacade = (() => {
|
||||||
|
// Private variables
|
||||||
|
let lastFilterSentToServer = '';
|
||||||
|
let dataCommunicatorResetNeeded = false;
|
||||||
|
|
||||||
|
// Public methods
|
||||||
|
const needsDataCommunicatorReset = () => (dataCommunicatorResetNeeded = true);
|
||||||
|
const getLastFilterSentToServer = () => lastFilterSentToServer;
|
||||||
|
const requestData = (startIndex, endIndex, params) => {
|
||||||
|
const count = endIndex - startIndex;
|
||||||
|
const filter = params.filter;
|
||||||
|
|
||||||
|
comboBox.$server.setRequestedRange(startIndex, count, filter);
|
||||||
|
lastFilterSentToServer = filter;
|
||||||
|
if (dataCommunicatorResetNeeded) {
|
||||||
|
comboBox.$server.resetDataCommunicator();
|
||||||
|
dataCommunicatorResetNeeded = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
needsDataCommunicatorReset,
|
||||||
|
getLastFilterSentToServer,
|
||||||
|
requestData
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
const clearPageCallbacks = (pages = Object.keys(pageCallbacks)) => {
|
||||||
|
// Flush and empty the existing requests
|
||||||
|
pages.forEach((page) => {
|
||||||
|
pageCallbacks[page]([], comboBox.size);
|
||||||
|
delete pageCallbacks[page];
|
||||||
|
|
||||||
|
// Empty the comboBox's internal cache without invoking observers by filling
|
||||||
|
// the filteredItems array with placeholders (comboBox will request for data when it
|
||||||
|
// encounters a placeholder)
|
||||||
|
const pageStart = parseInt(page) * comboBox.pageSize;
|
||||||
|
const pageEnd = pageStart + comboBox.pageSize;
|
||||||
|
const end = Math.min(pageEnd, comboBox.filteredItems.length);
|
||||||
|
for (let i = pageStart; i < end; i++) {
|
||||||
|
comboBox.filteredItems[i] = placeHolder;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
comboBox.dataProvider = function (params, callback) {
|
||||||
|
if (params.pageSize != comboBox.pageSize) {
|
||||||
|
throw 'Invalid pageSize';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comboBox._clientSideFilter) {
|
||||||
|
// For clientside filter we first make sure we have all data which we also
|
||||||
|
// filter based on comboBox.filter. While later we only filter clientside data.
|
||||||
|
|
||||||
|
if (cache[0]) {
|
||||||
|
performClientSideFilter(cache[0], params.filter, callback);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// If client side filter is enabled then we need to first ask all data
|
||||||
|
// and filter it on client side, otherwise next time when user will
|
||||||
|
// input another filter, eg. continue to type, the local cache will be only
|
||||||
|
// what was received for the first filter, which may not be the whole
|
||||||
|
// data from server (keep in mind that client side filter is enabled only
|
||||||
|
// when the items count does not exceed one page).
|
||||||
|
params.filter = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterChanged = params.filter !== lastFilter;
|
||||||
|
if (filterChanged) {
|
||||||
|
cache = {};
|
||||||
|
lastFilter = params.filter;
|
||||||
|
this._filterDebouncer = Debouncer.debounce(this._filterDebouncer, timeOut.after(500), () => {
|
||||||
|
if (serverFacade.getLastFilterSentToServer() === params.filter) {
|
||||||
|
// Fixes the case when the filter changes
|
||||||
|
// to something else and back to the original value
|
||||||
|
// within debounce timeout, and the
|
||||||
|
// DataCommunicator thinks it doesn't need to send data
|
||||||
|
serverFacade.needsDataCommunicatorReset();
|
||||||
|
}
|
||||||
|
if (params.filter !== lastFilter) {
|
||||||
|
throw new Error("Expected params.filter to be '" + lastFilter + "' but was '" + params.filter + "'");
|
||||||
|
}
|
||||||
|
// Remove the debouncer before clearing page callbacks.
|
||||||
|
// This makes sure that they are executed.
|
||||||
|
this._filterDebouncer = undefined;
|
||||||
|
// Call the method again after debounce.
|
||||||
|
clearPageCallbacks();
|
||||||
|
comboBox.dataProvider(params, callback);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postpone the execution of new callbacks if there is an active debouncer.
|
||||||
|
// They will be executed when the page callbacks are cleared within the debouncer.
|
||||||
|
if (this._filterDebouncer) {
|
||||||
|
pageCallbacks[params.page] = callback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache[params.page]) {
|
||||||
|
// This may happen after skipping pages by scrolling fast
|
||||||
|
commitPage(params.page, callback);
|
||||||
|
} else {
|
||||||
|
pageCallbacks[params.page] = callback;
|
||||||
|
const maxRangeCount = Math.max(params.pageSize * 2, 500); // Max item count in active range
|
||||||
|
const activePages = Object.keys(pageCallbacks).map((page) => parseInt(page));
|
||||||
|
const rangeMin = Math.min(...activePages);
|
||||||
|
const rangeMax = Math.max(...activePages);
|
||||||
|
|
||||||
|
if (activePages.length * params.pageSize > maxRangeCount) {
|
||||||
|
if (params.page === rangeMin) {
|
||||||
|
clearPageCallbacks([String(rangeMax)]);
|
||||||
|
} else {
|
||||||
|
clearPageCallbacks([String(rangeMin)]);
|
||||||
|
}
|
||||||
|
comboBox.dataProvider(params, callback);
|
||||||
|
} else if (rangeMax - rangeMin + 1 !== activePages.length) {
|
||||||
|
// Wasn't a sequential page index, clear the cache so combo-box will request for new pages
|
||||||
|
clearPageCallbacks();
|
||||||
|
} else {
|
||||||
|
// The requested page was sequential, extend the requested range
|
||||||
|
const startIndex = params.pageSize * rangeMin;
|
||||||
|
const endIndex = params.pageSize * (rangeMax + 1);
|
||||||
|
|
||||||
|
serverFacade.requestData(startIndex, endIndex, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
comboBox.$connector.clear = tryCatchWrapper((start, length) => {
|
||||||
|
const firstPageToClear = Math.floor(start / comboBox.pageSize);
|
||||||
|
const numberOfPagesToClear = Math.ceil(length / comboBox.pageSize);
|
||||||
|
|
||||||
|
for (let i = firstPageToClear; i < firstPageToClear + numberOfPagesToClear; i++) {
|
||||||
|
delete cache[i];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
comboBox.$connector.filter = tryCatchWrapper(function (item, filter) {
|
||||||
|
filter = filter ? filter.toString().toLowerCase() : '';
|
||||||
|
return comboBox._getItemLabel(item, comboBox.itemLabelPath).toString().toLowerCase().indexOf(filter) > -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
comboBox.$connector.set = tryCatchWrapper(function (index, items, filter) {
|
||||||
|
if (filter != serverFacade.getLastFilterSentToServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index % comboBox.pageSize != 0) {
|
||||||
|
throw 'Got new data to index ' + index + ' which is not aligned with the page size of ' + comboBox.pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index === 0 && items.length === 0 && pageCallbacks[0]) {
|
||||||
|
// Makes sure that the dataProvider callback is called even when server
|
||||||
|
// returns empty data set (no items match the filter).
|
||||||
|
cache[0] = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstPageToSet = index / comboBox.pageSize;
|
||||||
|
const updatedPageCount = Math.ceil(items.length / comboBox.pageSize);
|
||||||
|
|
||||||
|
for (let i = 0; i < updatedPageCount; i++) {
|
||||||
|
let page = firstPageToSet + i;
|
||||||
|
let slice = items.slice(i * comboBox.pageSize, (i + 1) * comboBox.pageSize);
|
||||||
|
|
||||||
|
cache[page] = slice;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
comboBox.$connector.updateData = tryCatchWrapper(function (items) {
|
||||||
|
const itemsMap = new Map(items.map((item) => [item.key, item]));
|
||||||
|
|
||||||
|
comboBox.filteredItems = comboBox.filteredItems.map((item) => {
|
||||||
|
return itemsMap.get(item.key) || item;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
comboBox.$connector.updateSize = tryCatchWrapper(function (newSize) {
|
||||||
|
if (!comboBox._clientSideFilter) {
|
||||||
|
// FIXME: It may be that this size set is unnecessary, since when
|
||||||
|
// providing data to combobox via callback we may use data's size.
|
||||||
|
// However, if this size reflect the whole data size, including
|
||||||
|
// data not fetched yet into client side, and combobox expect it
|
||||||
|
// to be set as such, the at least, we don't need it in case the
|
||||||
|
// filter is clientSide only, since it'll increase the height of
|
||||||
|
// the popup at only at first user filter to this size, while the
|
||||||
|
// filtered items count are less.
|
||||||
|
comboBox.size = newSize;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
comboBox.$connector.reset = tryCatchWrapper(function () {
|
||||||
|
clearPageCallbacks();
|
||||||
|
cache = {};
|
||||||
|
comboBox.clearCache();
|
||||||
|
});
|
||||||
|
|
||||||
|
comboBox.$connector.confirm = tryCatchWrapper(function (id, filter) {
|
||||||
|
if (filter != serverFacade.getLastFilterSentToServer()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're done applying changes from this batch, resolve pending
|
||||||
|
// callbacks
|
||||||
|
let activePages = Object.getOwnPropertyNames(pageCallbacks);
|
||||||
|
for (let i = 0; i < activePages.length; i++) {
|
||||||
|
let page = activePages[i];
|
||||||
|
|
||||||
|
if (cache[page]) {
|
||||||
|
commitPage(page, pageCallbacks[page]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let server know we're done
|
||||||
|
comboBox.$server.confirmUpdate(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
const commitPage = tryCatchWrapper(function (page, callback) {
|
||||||
|
let data = cache[page];
|
||||||
|
|
||||||
|
if (comboBox._clientSideFilter) {
|
||||||
|
performClientSideFilter(data, comboBox.filter, callback);
|
||||||
|
} else {
|
||||||
|
// Remove the data if server-side filtering, but keep it for client-side
|
||||||
|
// filtering
|
||||||
|
delete cache[page];
|
||||||
|
|
||||||
|
// FIXME: It may be that we ought to provide data.length instead of
|
||||||
|
// comboBox.size and remove updateSize function.
|
||||||
|
callback(data, comboBox.size);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Perform filter on client side (here) using the items from specified page
|
||||||
|
// and submitting the filtered items to specified callback.
|
||||||
|
// The filter used is the one from combobox, not the lastFilter stored since
|
||||||
|
// that may not reflect user's input.
|
||||||
|
const performClientSideFilter = tryCatchWrapper(function (page, filter, callback) {
|
||||||
|
let filteredItems = page;
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
filteredItems = page.filter((item) => comboBox.$connector.filter(item, filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(filteredItems, filteredItems.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent setting the custom value as the 'value'-prop automatically
|
||||||
|
comboBox.addEventListener(
|
||||||
|
'custom-value-set',
|
||||||
|
tryCatchWrapper((e) => e.preventDefault())
|
||||||
|
);
|
||||||
|
})(comboBox)
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
window.Vaadin.ComboBoxPlaceholder = ComboBoxPlaceholder;
|
40
frontend/generated/jar-resources/confirmDialogConnector.js
Normal file
40
frontend/generated/jar-resources/confirmDialogConnector.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
(function () {
|
||||||
|
function copyClassName(dialog) {
|
||||||
|
const overlay = dialog._overlayElement;
|
||||||
|
if (overlay) {
|
||||||
|
overlay.className = dialog.className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((records) => {
|
||||||
|
records.forEach((mutation) => {
|
||||||
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||||
|
copyClassName(mutation.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Vaadin.Flow.confirmDialogConnector = {
|
||||||
|
initLazy: function (dialog) {
|
||||||
|
if (dialog.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.$connector = {};
|
||||||
|
|
||||||
|
dialog.addEventListener('opened-changed', (e) => {
|
||||||
|
if (e.detail.value) {
|
||||||
|
copyClassName(dialog);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(dialog, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['class']
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy initial class
|
||||||
|
copyClassName(dialog);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
117
frontend/generated/jar-resources/contextMenuConnector.js
Normal file
117
frontend/generated/jar-resources/contextMenuConnector.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
(function () {
|
||||||
|
function tryCatchWrapper(callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Context Menu');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContainer(appId, nodeId) {
|
||||||
|
try {
|
||||||
|
return window.Vaadin.Flow.clients[appId].getByNodeId(nodeId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Could not get node %s from app %s', nodeId, appId);
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the connector for a context menu element.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} contextMenu
|
||||||
|
* @param {string} appId
|
||||||
|
*/
|
||||||
|
function initLazy(contextMenu, appId) {
|
||||||
|
if (contextMenu.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMenu.$connector = {
|
||||||
|
/**
|
||||||
|
* Generates and assigns the items to the context menu.
|
||||||
|
*
|
||||||
|
* @param {number} nodeId
|
||||||
|
*/
|
||||||
|
generateItems: tryCatchWrapper((nodeId) => {
|
||||||
|
const items = generateItemsTree(appId, nodeId);
|
||||||
|
|
||||||
|
contextMenu.items = items;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an items tree compatible with the context-menu web component
|
||||||
|
* by traversing the given Flow DOM tree of context menu item nodes
|
||||||
|
* whose root node is identified by the `nodeId` argument.
|
||||||
|
*
|
||||||
|
* The app id is required to access the store of Flow DOM nodes.
|
||||||
|
*
|
||||||
|
* @param {string} appId
|
||||||
|
* @param {number} nodeId
|
||||||
|
*/
|
||||||
|
function generateItemsTree(appId, nodeId) {
|
||||||
|
const container = getContainer(appId, nodeId);
|
||||||
|
if (!container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(container.children).map((child) => {
|
||||||
|
const item = {
|
||||||
|
component: child,
|
||||||
|
checked: child._checked,
|
||||||
|
theme: child.__theme
|
||||||
|
};
|
||||||
|
if (child.localName == 'vaadin-context-menu-item' && child._containerNodeId) {
|
||||||
|
item.children = generateItemsTree(appId, child._containerNodeId);
|
||||||
|
}
|
||||||
|
child._item = item;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the checked state for a context menu item.
|
||||||
|
*
|
||||||
|
* This method is supposed to be called when the context menu item is closed,
|
||||||
|
* so there is no need for triggering a re-render eagarly.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} component
|
||||||
|
* @param {boolean} checked
|
||||||
|
*/
|
||||||
|
function setChecked(component, checked) {
|
||||||
|
if (component._item) {
|
||||||
|
component._item.checked = checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the theme for a context menu item.
|
||||||
|
*
|
||||||
|
* This method is supposed to be called when the context menu item is closed,
|
||||||
|
* so there is no need for triggering a re-render eagarly.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} component
|
||||||
|
* @param {string | undefined | null} theme
|
||||||
|
*/
|
||||||
|
function setTheme(component, theme) {
|
||||||
|
if (component._item) {
|
||||||
|
component._item.theme = theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Vaadin.Flow.contextMenuConnector = {
|
||||||
|
initLazy(...args) {
|
||||||
|
return tryCatchWrapper(initLazy)(...args);
|
||||||
|
},
|
||||||
|
|
||||||
|
generateItemsTree(...args) {
|
||||||
|
return tryCatchWrapper(generateItemsTree)(...args);
|
||||||
|
},
|
||||||
|
|
||||||
|
setChecked(...args) {
|
||||||
|
return tryCatchWrapper(setChecked)(...args);
|
||||||
|
},
|
||||||
|
|
||||||
|
setTheme(...args) {
|
||||||
|
return tryCatchWrapper(setTheme)(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
@ -0,0 +1,70 @@
|
|||||||
|
import * as Gestures from '@vaadin/component-base/src/gestures.js';
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
function tryCatchWrapper(callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Context Menu Target');
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(target) {
|
||||||
|
if (target.$contextMenuTargetConnector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.$contextMenuTargetConnector = {
|
||||||
|
openOnHandler: tryCatchWrapper(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.$contextMenuTargetConnector.openEvent = e;
|
||||||
|
let detail = {};
|
||||||
|
if (target.getContextMenuBeforeOpenDetail) {
|
||||||
|
detail = target.getContextMenuBeforeOpenDetail(e);
|
||||||
|
}
|
||||||
|
target.dispatchEvent(
|
||||||
|
new CustomEvent('vaadin-context-menu-before-open', {
|
||||||
|
detail: detail
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
|
||||||
|
updateOpenOn: tryCatchWrapper(function (eventType) {
|
||||||
|
this.removeListener();
|
||||||
|
this.openOnEventType = eventType;
|
||||||
|
|
||||||
|
customElements.whenDefined('vaadin-context-menu').then(
|
||||||
|
tryCatchWrapper(() => {
|
||||||
|
if (Gestures.gestures[eventType]) {
|
||||||
|
Gestures.addListener(target, eventType, this.openOnHandler);
|
||||||
|
} else {
|
||||||
|
target.addEventListener(eventType, this.openOnHandler);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
|
||||||
|
removeListener: tryCatchWrapper(function () {
|
||||||
|
if (this.openOnEventType) {
|
||||||
|
if (Gestures.gestures[this.openOnEventType]) {
|
||||||
|
Gestures.removeListener(target, this.openOnEventType, this.openOnHandler);
|
||||||
|
} else {
|
||||||
|
target.removeEventListener(this.openOnEventType, this.openOnHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
openMenu: tryCatchWrapper(function (contextMenu) {
|
||||||
|
contextMenu.open(this.openEvent);
|
||||||
|
}),
|
||||||
|
|
||||||
|
removeConnector: tryCatchWrapper(function () {
|
||||||
|
this.removeListener();
|
||||||
|
target.$contextMenuTargetConnector = undefined;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Vaadin.Flow.contextMenuTargetConnector = {
|
||||||
|
init(...args) {
|
||||||
|
return tryCatchWrapper(init)(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
150
frontend/generated/jar-resources/copy-to-clipboard.js
Normal file
150
frontend/generated/jar-resources/copy-to-clipboard.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var deselectCurrent = function () {
|
||||||
|
var selection = document.getSelection();
|
||||||
|
if (!selection.rangeCount) {
|
||||||
|
return function () {};
|
||||||
|
}
|
||||||
|
var active = document.activeElement;
|
||||||
|
|
||||||
|
var ranges = [];
|
||||||
|
for (var i = 0; i < selection.rangeCount; i++) {
|
||||||
|
ranges.push(selection.getRangeAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (active.tagName.toUpperCase()) { // .toUpperCase handles XHTML
|
||||||
|
case 'INPUT':
|
||||||
|
case 'TEXTAREA':
|
||||||
|
active.blur();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
active = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
selection.removeAllRanges();
|
||||||
|
return function () {
|
||||||
|
selection.type === 'Caret' &&
|
||||||
|
selection.removeAllRanges();
|
||||||
|
|
||||||
|
if (!selection.rangeCount) {
|
||||||
|
ranges.forEach(function(range) {
|
||||||
|
selection.addRange(range);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
active &&
|
||||||
|
active.focus();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var clipboardToIE11Formatting = {
|
||||||
|
"text/plain": "Text",
|
||||||
|
"text/html": "Url",
|
||||||
|
"default": "Text"
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultMessage = "Copy to clipboard: #{key}, Enter";
|
||||||
|
|
||||||
|
function format(message) {
|
||||||
|
var copyKey = (/mac os x/i.test(navigator.userAgent) ? "⌘" : "Ctrl") + "+C";
|
||||||
|
return message.replace(/#{\s*key\s*}/g, copyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function copy(text, options) {
|
||||||
|
var debug,
|
||||||
|
message,
|
||||||
|
reselectPrevious,
|
||||||
|
range,
|
||||||
|
selection,
|
||||||
|
mark,
|
||||||
|
success = false;
|
||||||
|
if (!options) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
debug = options.debug || false;
|
||||||
|
try {
|
||||||
|
reselectPrevious = deselectCurrent();
|
||||||
|
|
||||||
|
range = document.createRange();
|
||||||
|
selection = document.getSelection();
|
||||||
|
|
||||||
|
mark = document.createElement("span");
|
||||||
|
mark.textContent = text;
|
||||||
|
// reset user styles for span element
|
||||||
|
mark.style.all = "unset";
|
||||||
|
// prevents scrolling to the end of the page
|
||||||
|
mark.style.position = "fixed";
|
||||||
|
mark.style.top = 0;
|
||||||
|
mark.style.clip = "rect(0, 0, 0, 0)";
|
||||||
|
// used to preserve spaces and line breaks
|
||||||
|
mark.style.whiteSpace = "pre";
|
||||||
|
// do not inherit user-select (it may be `none`)
|
||||||
|
mark.style.webkitUserSelect = "text";
|
||||||
|
mark.style.MozUserSelect = "text";
|
||||||
|
mark.style.msUserSelect = "text";
|
||||||
|
mark.style.userSelect = "text";
|
||||||
|
mark.addEventListener("copy", function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (options.format) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (typeof e.clipboardData === "undefined") { // IE 11
|
||||||
|
debug && console.warn("unable to use e.clipboardData");
|
||||||
|
debug && console.warn("trying IE specific stuff");
|
||||||
|
window.clipboardData.clearData();
|
||||||
|
var format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting["default"]
|
||||||
|
window.clipboardData.setData(format, text);
|
||||||
|
} else { // all other browsers
|
||||||
|
e.clipboardData.clearData();
|
||||||
|
e.clipboardData.setData(options.format, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (options.onCopy) {
|
||||||
|
e.preventDefault();
|
||||||
|
options.onCopy(e.clipboardData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.appendChild(mark);
|
||||||
|
|
||||||
|
range.selectNodeContents(mark);
|
||||||
|
selection.addRange(range);
|
||||||
|
|
||||||
|
var successful = document.execCommand("copy");
|
||||||
|
if (!successful) {
|
||||||
|
throw new Error("copy command was unsuccessful");
|
||||||
|
}
|
||||||
|
success = true;
|
||||||
|
} catch (err) {
|
||||||
|
debug && console.error("unable to copy using execCommand: ", err);
|
||||||
|
debug && console.warn("trying IE specific stuff");
|
||||||
|
try {
|
||||||
|
window.clipboardData.setData(options.format || "text", text);
|
||||||
|
options.onCopy && options.onCopy(window.clipboardData);
|
||||||
|
success = true;
|
||||||
|
} catch (err) {
|
||||||
|
debug && console.error("unable to copy using clipboardData: ", err);
|
||||||
|
debug && console.error("falling back to prompt");
|
||||||
|
message = format("message" in options ? options.message : defaultMessage);
|
||||||
|
window.prompt(message, text);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (selection) {
|
||||||
|
if (typeof selection.removeRange == "function") {
|
||||||
|
selection.removeRange(range);
|
||||||
|
} else {
|
||||||
|
selection.removeAllRanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mark) {
|
||||||
|
document.body.removeChild(mark);
|
||||||
|
}
|
||||||
|
reselectPrevious();
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
159
frontend/generated/jar-resources/datepickerConnector.js
Normal file
159
frontend/generated/jar-resources/datepickerConnector.js
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import dateFnsFormat from 'date-fns/format';
|
||||||
|
import dateFnsParse from 'date-fns/parse';
|
||||||
|
import dateFnsIsValid from 'date-fns/isValid';
|
||||||
|
import { extractDateParts, parseDate as _parseDate } from '@vaadin/date-picker/src/vaadin-date-picker-helper.js';
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const tryCatchWrapper = function (callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Date Picker');
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Vaadin.Flow.datepickerConnector = {
|
||||||
|
initLazy: (datepicker) =>
|
||||||
|
tryCatchWrapper(function (datepicker) {
|
||||||
|
// Check whether the connector was already initialized for the datepicker
|
||||||
|
if (datepicker.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
datepicker.$connector = {};
|
||||||
|
|
||||||
|
const createLocaleBasedDateFormat = function (locale) {
|
||||||
|
try {
|
||||||
|
// Check whether the locale is supported or not
|
||||||
|
new Date().toLocaleDateString(locale);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('The locale is not supported, using default locale setting(en-US).');
|
||||||
|
return 'M/d/yyyy';
|
||||||
|
}
|
||||||
|
|
||||||
|
// format test date and convert to date-fns pattern
|
||||||
|
const testDate = new Date(Date.UTC(1234, 4, 6));
|
||||||
|
let pattern = testDate.toLocaleDateString(locale, { timeZone: 'UTC' });
|
||||||
|
pattern = pattern
|
||||||
|
// escape date-fns pattern letters by enclosing them in single quotes
|
||||||
|
.replace(/([a-zA-Z]+)/g, "'$1'")
|
||||||
|
// insert date placeholder
|
||||||
|
.replace('06', 'dd')
|
||||||
|
.replace('6', 'd')
|
||||||
|
// insert month placeholder
|
||||||
|
.replace('05', 'MM')
|
||||||
|
.replace('5', 'M')
|
||||||
|
// insert year placeholder
|
||||||
|
.replace('1234', 'yyyy');
|
||||||
|
const isValidPattern = pattern.includes('d') && pattern.includes('M') && pattern.includes('y');
|
||||||
|
if (!isValidPattern) {
|
||||||
|
console.warn('The locale is not supported, using default locale setting(en-US).');
|
||||||
|
return 'M/d/yyyy';
|
||||||
|
}
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFormatterAndParser = tryCatchWrapper(function (formats) {
|
||||||
|
if (!formats || formats.length === 0) {
|
||||||
|
throw new Error('Array of custom date formats is null or empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getShortYearFormat(format) {
|
||||||
|
if (format.includes('yyyy') && !format.includes('yyyyy')) {
|
||||||
|
return format.replace('yyyy', 'yy');
|
||||||
|
}
|
||||||
|
if (format.includes('YYYY') && !format.includes('YYYYY')) {
|
||||||
|
return format.replace('YYYY', 'YY');
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isShortYearFormat(format) {
|
||||||
|
if (format.includes('y')) {
|
||||||
|
return !format.includes('yyy');
|
||||||
|
}
|
||||||
|
if (format.includes('Y')) {
|
||||||
|
return !format.includes('YYY');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(dateParts) {
|
||||||
|
const format = formats[0];
|
||||||
|
const date = _parseDate(`${dateParts.year}-${dateParts.month + 1}-${dateParts.day}`);
|
||||||
|
|
||||||
|
return dateFnsFormat(date, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDate(dateString) {
|
||||||
|
const referenceDate = _getReferenceDate();
|
||||||
|
for (let format of formats) {
|
||||||
|
// We first try to match the date with the shorter version.
|
||||||
|
const shortYearFormat = getShortYearFormat(format);
|
||||||
|
if (shortYearFormat) {
|
||||||
|
const shortYearFormatDate = dateFnsParse(dateString, shortYearFormat, referenceDate);
|
||||||
|
if (dateFnsIsValid(shortYearFormatDate)) {
|
||||||
|
let yearValue = shortYearFormatDate.getFullYear();
|
||||||
|
// The last parsed year check handles the case where a four-digit year is parsed, then formatted
|
||||||
|
// as a two-digit year, and then parsed again. In this case we want to keep the century of the
|
||||||
|
// originally parsed year, instead of using the century of the reference date.
|
||||||
|
if (
|
||||||
|
datepicker.$connector._lastParsedYear &&
|
||||||
|
yearValue === datepicker.$connector._lastParsedYear % 100
|
||||||
|
) {
|
||||||
|
yearValue = datepicker.$connector._lastParsedYear;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
day: shortYearFormatDate.getDate(),
|
||||||
|
month: shortYearFormatDate.getMonth(),
|
||||||
|
year: yearValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const date = dateFnsParse(dateString, format, referenceDate);
|
||||||
|
|
||||||
|
if (dateFnsIsValid(date)) {
|
||||||
|
let yearValue = date.getFullYear();
|
||||||
|
if (
|
||||||
|
datepicker.$connector._lastParsedYear &&
|
||||||
|
yearValue % 100 === datepicker.$connector._lastParsedYear % 100 &&
|
||||||
|
isShortYearFormat(format)
|
||||||
|
) {
|
||||||
|
yearValue = datepicker.$connector._lastParsedYear;
|
||||||
|
} else {
|
||||||
|
datepicker.$connector._lastParsedYear = yearValue;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
day: date.getDate(),
|
||||||
|
month: date.getMonth(),
|
||||||
|
year: yearValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
datepicker.$connector._lastParsedYear = undefined;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
formatDate: formatDate,
|
||||||
|
parseDate: parseDate
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function _getReferenceDate() {
|
||||||
|
const { referenceDate } = datepicker.i18n;
|
||||||
|
return referenceDate ? new Date(referenceDate.year, referenceDate.month - 1, referenceDate.day) : new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
datepicker.$connector.updateI18n = tryCatchWrapper(function (locale, i18n) {
|
||||||
|
// Either use custom formats specified in I18N, or create format from locale
|
||||||
|
const hasCustomFormats = i18n && i18n.dateFormats && i18n.dateFormats.length > 0;
|
||||||
|
if (i18n && i18n.referenceDate) {
|
||||||
|
i18n.referenceDate = extractDateParts(new Date(i18n.referenceDate));
|
||||||
|
}
|
||||||
|
const usedFormats = hasCustomFormats ? i18n.dateFormats : [createLocaleBasedDateFormat(locale)];
|
||||||
|
const formatterAndParser = createFormatterAndParser(usedFormats);
|
||||||
|
|
||||||
|
// Merge current web component I18N settings with new I18N settings and the formatting and parsing functions
|
||||||
|
datepicker.i18n = Object.assign({}, datepicker.i18n, i18n, formatterAndParser);
|
||||||
|
});
|
||||||
|
})(datepicker)
|
||||||
|
};
|
||||||
|
})();
|
38
frontend/generated/jar-resources/dialogConnector.js
Normal file
38
frontend/generated/jar-resources/dialogConnector.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
(function () {
|
||||||
|
function copyClassName(dialog) {
|
||||||
|
const overlay = dialog.$.overlay;
|
||||||
|
if (overlay) {
|
||||||
|
overlay.className = dialog.className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((records) => {
|
||||||
|
records.forEach((mutation) => {
|
||||||
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||||
|
copyClassName(mutation.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Vaadin.Flow.dialogConnector = {
|
||||||
|
initLazy: function (dialog) {
|
||||||
|
if (dialog.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialog.$connector = {};
|
||||||
|
|
||||||
|
dialog.addEventListener('opened-changed', (e) => {
|
||||||
|
if (e.detail.value) {
|
||||||
|
copyClassName(dialog);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(dialog, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['class']
|
||||||
|
});
|
||||||
|
|
||||||
|
copyClassName(dialog);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
1
frontend/generated/jar-resources/dndConnector-es6.js
Normal file
1
frontend/generated/jar-resources/dndConnector-es6.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './dndConnector.js';
|
110
frontend/generated/jar-resources/dndConnector.js
Normal file
110
frontend/generated/jar-resources/dndConnector.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
window.Vaadin = window.Vaadin || {};
|
||||||
|
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||||
|
window.Vaadin.Flow.dndConnector = {
|
||||||
|
__ondragenterListener: function (event) {
|
||||||
|
// TODO filter by data type
|
||||||
|
// TODO prevent dropping on itself (by default)
|
||||||
|
const effect = event.currentTarget['__dropEffect'];
|
||||||
|
if (!event.currentTarget.hasAttribute('disabled')) {
|
||||||
|
if (effect) {
|
||||||
|
event.dataTransfer.dropEffect = effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect && effect !== 'none') {
|
||||||
|
/* #7108: if drag moves on top of drop target's children, first another ondragenter event
|
||||||
|
* is fired and then a ondragleave event. This happens again once the drag
|
||||||
|
* moves on top of another children, or back on top of the drop target element.
|
||||||
|
* Thus need to "cancel" the following ondragleave, to not remove class name.
|
||||||
|
* Drop event will happen even when dropped to a child element. */
|
||||||
|
if (event.currentTarget.classList.contains('v-drag-over-target')) {
|
||||||
|
event.currentTarget['__skip-leave'] = true;
|
||||||
|
} else {
|
||||||
|
event.currentTarget.classList.add('v-drag-over-target');
|
||||||
|
}
|
||||||
|
// enables browser specific pseudo classes (at least FF)
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation(); // don't let parents know
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
__ondragoverListener: function (event) {
|
||||||
|
// TODO filter by data type
|
||||||
|
// TODO filter by effectAllowed != dropEffect due to Safari & IE11 ?
|
||||||
|
if (!event.currentTarget.hasAttribute('disabled')) {
|
||||||
|
const effect = event.currentTarget['__dropEffect'];
|
||||||
|
if (effect) {
|
||||||
|
event.dataTransfer.dropEffect = effect;
|
||||||
|
}
|
||||||
|
// allows the drop && don't let parents know
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
__ondragleaveListener: function (event) {
|
||||||
|
if (event.currentTarget['__skip-leave']) {
|
||||||
|
event.currentTarget['__skip-leave'] = false;
|
||||||
|
} else {
|
||||||
|
event.currentTarget.classList.remove('v-drag-over-target');
|
||||||
|
}
|
||||||
|
// #7109 need to stop or any parent drop target might not get highlighted,
|
||||||
|
// as ondragenter for it is fired before the child gets dragleave.
|
||||||
|
event.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
|
__ondropListener: function (event) {
|
||||||
|
const effect = event.currentTarget['__dropEffect'];
|
||||||
|
if (effect) {
|
||||||
|
event.dataTransfer.dropEffect = effect;
|
||||||
|
}
|
||||||
|
event.currentTarget.classList.remove('v-drag-over-target');
|
||||||
|
// prevent browser handling && don't let parents know
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDropTarget: function (element) {
|
||||||
|
if (element['__active']) {
|
||||||
|
element.addEventListener('dragenter', this.__ondragenterListener, false);
|
||||||
|
element.addEventListener('dragover', this.__ondragoverListener, false);
|
||||||
|
element.addEventListener('dragleave', this.__ondragleaveListener, false);
|
||||||
|
element.addEventListener('drop', this.__ondropListener, false);
|
||||||
|
} else {
|
||||||
|
element.removeEventListener('dragenter', this.__ondragenterListener, false);
|
||||||
|
element.removeEventListener('dragover', this.__ondragoverListener, false);
|
||||||
|
element.removeEventListener('dragleave', this.__ondragleaveListener, false);
|
||||||
|
element.removeEventListener('drop', this.__ondropListener, false);
|
||||||
|
element.classList.remove('v-drag-over-target');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** DRAG SOURCE METHODS: */
|
||||||
|
|
||||||
|
__dragstartListener: function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.dataTransfer.setData('text/plain', '');
|
||||||
|
if (event.currentTarget.hasAttribute('disabled')) {
|
||||||
|
event.preventDefault();
|
||||||
|
} else {
|
||||||
|
if (event.currentTarget['__effectAllowed']) {
|
||||||
|
event.dataTransfer.effectAllowed = event.currentTarget['__effectAllowed'];
|
||||||
|
}
|
||||||
|
event.currentTarget.classList.add('v-dragged');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
__dragendListener: function (event) {
|
||||||
|
event.currentTarget.classList.remove('v-dragged');
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDragSource: function (element) {
|
||||||
|
if (element['draggable']) {
|
||||||
|
element.addEventListener('dragstart', this.__dragstartListener, false);
|
||||||
|
element.addEventListener('dragend', this.__dragendListener, false);
|
||||||
|
} else {
|
||||||
|
element.removeEventListener('dragstart', this.__dragstartListener, false);
|
||||||
|
element.removeEventListener('dragend', this.__dragendListener, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
155
frontend/generated/jar-resources/flow-component-renderer.js
Normal file
155
frontend/generated/jar-resources/flow-component-renderer.js
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import '@polymer/polymer/lib/elements/dom-if.js';
|
||||||
|
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
||||||
|
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
||||||
|
import { idlePeriod } from '@polymer/polymer/lib/utils/async.js';
|
||||||
|
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||||
|
|
||||||
|
class FlowComponentRenderer extends PolymerElement {
|
||||||
|
static get template() {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
animation: 1ms flow-component-renderer-appear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flow-component-renderer-appear {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<slot></slot>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get is() {
|
||||||
|
return 'flow-component-renderer';
|
||||||
|
}
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
nodeid: Number,
|
||||||
|
appid: String,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static get observers() {
|
||||||
|
return ['_attachRenderedComponentIfAble(appid, nodeid)'];
|
||||||
|
}
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
super.ready();
|
||||||
|
this.addEventListener('click', function (event) {
|
||||||
|
if (
|
||||||
|
this.firstChild &&
|
||||||
|
typeof this.firstChild.click === 'function' &&
|
||||||
|
event.target === this
|
||||||
|
) {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.firstChild.click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.addEventListener('animationend', this._onAnimationEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
_asyncAttachRenderedComponentIfAble() {
|
||||||
|
this._debouncer = Debouncer.debounce(this._debouncer, idlePeriod, () =>
|
||||||
|
this._attachRenderedComponentIfAble()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_attachRenderedComponentIfAble() {
|
||||||
|
if (!this.nodeid || !this.appid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const renderedComponent = this._getRenderedComponent();
|
||||||
|
if (this.firstChild) {
|
||||||
|
if (!renderedComponent) {
|
||||||
|
this._asyncAttachRenderedComponentIfAble();
|
||||||
|
} else if (this.firstChild !== renderedComponent) {
|
||||||
|
this.replaceChild(renderedComponent, this.firstChild);
|
||||||
|
this._defineFocusTarget();
|
||||||
|
this.onComponentRendered();
|
||||||
|
} else {
|
||||||
|
this._defineFocusTarget();
|
||||||
|
this.onComponentRendered();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (renderedComponent) {
|
||||||
|
this.appendChild(renderedComponent);
|
||||||
|
this._defineFocusTarget();
|
||||||
|
this.onComponentRendered();
|
||||||
|
} else {
|
||||||
|
this._asyncAttachRenderedComponentIfAble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getRenderedComponent() {
|
||||||
|
try {
|
||||||
|
return window.Vaadin.Flow.clients[this.appid].getByNodeId(this.nodeid);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
'Could not get node %s from app %s',
|
||||||
|
this.nodeid,
|
||||||
|
this.appid
|
||||||
|
);
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
onComponentRendered() {
|
||||||
|
// subclasses can override this method to execute custom logic on resize
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setting the `focus-target` attribute to the first focusable descendant
|
||||||
|
starting from the firstChild necessary for the focus to be delegated
|
||||||
|
within the flow-component-renderer when used inside a vaadin-grid cell */
|
||||||
|
_defineFocusTarget() {
|
||||||
|
var focusable = this._getFirstFocusableDescendant(this.firstChild);
|
||||||
|
if (focusable !== null) {
|
||||||
|
focusable.setAttribute('focus-target', 'true');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getFirstFocusableDescendant(node) {
|
||||||
|
if (this._isFocusable(node)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (node.hasAttribute && (node.hasAttribute('disabled') || node.hasAttribute('hidden'))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!node.children) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < node.children.length; i++) {
|
||||||
|
var focusable = this._getFirstFocusableDescendant(node.children[i]);
|
||||||
|
if (focusable !== null) {
|
||||||
|
return focusable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isFocusable(node) {
|
||||||
|
if (
|
||||||
|
node.hasAttribute &&
|
||||||
|
typeof node.hasAttribute === 'function' &&
|
||||||
|
(node.hasAttribute('disabled') || node.hasAttribute('hidden'))
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.tabIndex === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAnimationEnd(e) {
|
||||||
|
// ShadyCSS applies scoping suffixes to animation names
|
||||||
|
// To ensure that child is attached once element is unhidden
|
||||||
|
// for when it was filtered out from, eg, ComboBox
|
||||||
|
// https://github.com/vaadin/vaadin-flow-components/issues/437
|
||||||
|
if (e.animationName.indexOf('flow-component-renderer-appear') === 0) {
|
||||||
|
this._attachRenderedComponentIfAble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.customElements.define(FlowComponentRenderer.is, FlowComponentRenderer);
|
1185
frontend/generated/jar-resources/gridConnector.js
Normal file
1185
frontend/generated/jar-resources/gridConnector.js
Normal file
File diff suppressed because it is too large
Load Diff
1
frontend/generated/jar-resources/index.d.ts
vendored
Normal file
1
frontend/generated/jar-resources/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './Flow';
|
2
frontend/generated/jar-resources/index.js
Normal file
2
frontend/generated/jar-resources/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './Flow';
|
||||||
|
//# sourceMappingURL=index.js.map
|
1
frontend/generated/jar-resources/index.js.map
Normal file
1
frontend/generated/jar-resources/index.js.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/main/frontend/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC","sourcesContent":["export * from './Flow';\n"]}
|
166
frontend/generated/jar-resources/ironListConnector.js
Normal file
166
frontend/generated/jar-resources/ironListConnector.js
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
||||||
|
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
|
||||||
|
|
||||||
|
window.Vaadin.Flow.ironListConnector = {
|
||||||
|
initLazy: function (list) {
|
||||||
|
// Check whether the connector was already initialized for the Iron list
|
||||||
|
if (list.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const extraItemsBuffer = 20;
|
||||||
|
|
||||||
|
let lastRequestedRange = [0, 0];
|
||||||
|
|
||||||
|
list.$connector = {};
|
||||||
|
list.$connector.placeholderItem = { __placeholder: true };
|
||||||
|
|
||||||
|
const updateRequestedItem = function () {
|
||||||
|
/*
|
||||||
|
* TODO Iron list seems to do a small index adjustment after scrolling
|
||||||
|
* has stopped. This causes a redundant request to be sent to make a
|
||||||
|
* corresponding minimal change to the buffer. We should avoid these
|
||||||
|
* requests by making the logic skip doing a request if the available
|
||||||
|
* buffer is within some tolerance compared to the requested buffer.
|
||||||
|
*/
|
||||||
|
let firstNeededItem = list._virtualStart;
|
||||||
|
let lastNeededItem = list._virtualEnd;
|
||||||
|
|
||||||
|
let first = Math.max(0, firstNeededItem - extraItemsBuffer);
|
||||||
|
let last = Math.min(lastNeededItem + extraItemsBuffer, list.items.length);
|
||||||
|
|
||||||
|
if (lastRequestedRange[0] != first || lastRequestedRange[1] != last) {
|
||||||
|
lastRequestedRange = [first, last];
|
||||||
|
const count = 1 + last - first;
|
||||||
|
list.$server.setRequestedRange(first, count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let requestDebounce;
|
||||||
|
const scheduleUpdateRequest = function () {
|
||||||
|
requestDebounce = Debouncer.debounce(requestDebounce, timeOut.after(10), updateRequestedItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure all items that iron list will be looking at are actually defined.
|
||||||
|
* If this is not done, the component will keep looking ahead through the
|
||||||
|
* array until finding enough present items to render. In our case, that's
|
||||||
|
* a really slow way of achieving nothing since the rest of the array is
|
||||||
|
* empty.
|
||||||
|
*/
|
||||||
|
const originalAssign = list._assignModels;
|
||||||
|
list._assignModels = function () {
|
||||||
|
const tempItems = [];
|
||||||
|
const start = list._virtualStart;
|
||||||
|
const count = Math.min(list.items.length, list._physicalCount);
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
if (list.items[start + i] === undefined) {
|
||||||
|
tempItems.push(i);
|
||||||
|
list.items[start + i] = list.$connector.placeholderItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
originalAssign.apply(list, arguments);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Keep track of placeholder items in the "active" range and
|
||||||
|
* avoid deleting them so that the next pass will be faster. Instead,
|
||||||
|
* the end of each pass should only delete placeholders that are no
|
||||||
|
* longer needed.
|
||||||
|
*/
|
||||||
|
for (let i = 0; i < tempItems.length; i++) {
|
||||||
|
delete list.items[start + tempItems[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we need to do anything once things have settled down.
|
||||||
|
* This method is called multiple times in sequence for the same user
|
||||||
|
* action, but we only want to do the check once.
|
||||||
|
*/
|
||||||
|
scheduleUpdateRequest();
|
||||||
|
};
|
||||||
|
|
||||||
|
list.items = [];
|
||||||
|
|
||||||
|
list.$connector.set = function (index, items) {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const itemsIndex = index + i;
|
||||||
|
list.items[itemsIndex] = items[i];
|
||||||
|
}
|
||||||
|
// Do a full render since dirty detection for splices is broken
|
||||||
|
list._render();
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.updateData = function (items) {
|
||||||
|
// Find the items by key inside the list update them
|
||||||
|
const oldItems = list.items;
|
||||||
|
const mapByKey = {};
|
||||||
|
let leftToUpdate = items.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
mapByKey[item.key] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < oldItems.length; i++) {
|
||||||
|
const oldItem = oldItems[i];
|
||||||
|
const newItem = mapByKey[oldItem.key];
|
||||||
|
if (newItem) {
|
||||||
|
list.items[i] = newItem;
|
||||||
|
list.notifyPath('items.' + i);
|
||||||
|
leftToUpdate--;
|
||||||
|
if (leftToUpdate == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.clear = function (index, length) {
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const itemsIndex = index + i;
|
||||||
|
delete list.items[itemsIndex];
|
||||||
|
|
||||||
|
// Most likely a no-op since the affected index isn't in view
|
||||||
|
list.notifyPath('items.' + itemsIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.updateSize = function (newSize) {
|
||||||
|
const delta = newSize - list.items.length;
|
||||||
|
if (delta > 0) {
|
||||||
|
list.items.length = newSize;
|
||||||
|
|
||||||
|
list.notifySplices('items', [
|
||||||
|
{
|
||||||
|
index: newSize - delta,
|
||||||
|
removed: [],
|
||||||
|
addedCount: delta,
|
||||||
|
object: list.items,
|
||||||
|
type: 'splice'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
} else if (delta < 0) {
|
||||||
|
const removed = list.items.slice(newSize, list.items.length);
|
||||||
|
list.items.splice(newSize);
|
||||||
|
list.notifySplices('items', [
|
||||||
|
{
|
||||||
|
index: newSize,
|
||||||
|
removed: removed,
|
||||||
|
addedCount: 0,
|
||||||
|
object: list.items,
|
||||||
|
type: 'splice'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.setPlaceholderItem = function (placeholderItem) {
|
||||||
|
if (!placeholderItem) {
|
||||||
|
placeholderItem = {};
|
||||||
|
}
|
||||||
|
placeholderItem.__placeholder = true;
|
||||||
|
list.$connector.placeholderItem = placeholderItem;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
12
frontend/generated/jar-resources/ironListStyles.js
Normal file
12
frontend/generated/jar-resources/ironListStyles.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import '@polymer/polymer/lib/elements/custom-style.js';
|
||||||
|
const $_documentContainer = document.createElement('template');
|
||||||
|
|
||||||
|
$_documentContainer.innerHTML = `<style>
|
||||||
|
/* Fixes zero width in flex layouts */
|
||||||
|
iron-list {
|
||||||
|
flex: auto;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
</style>`;
|
||||||
|
|
||||||
|
document.head.appendChild($_documentContainer.content);
|
108
frontend/generated/jar-resources/lit-renderer.ts
Normal file
108
frontend/generated/jar-resources/lit-renderer.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* eslint-disable no-restricted-syntax */
|
||||||
|
/* eslint-disable max-params */
|
||||||
|
import { html, render } from 'lit';
|
||||||
|
|
||||||
|
type RenderRoot = HTMLElement & { __litRenderer?: Renderer; _$litPart$?: any };
|
||||||
|
|
||||||
|
type ItemModel = { item: any; index: number };
|
||||||
|
|
||||||
|
type Renderer = ((root: RenderRoot, rendererOwner: HTMLElement, model: ItemModel) => void) & { __rendererId?: string };
|
||||||
|
|
||||||
|
type Component = HTMLElement & { [key: string]: Renderer | undefined };
|
||||||
|
|
||||||
|
const _window = window as any;
|
||||||
|
_window.Vaadin = _window.Vaadin || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns the component a renderer function which uses Lit to render
|
||||||
|
* the given template expression inside the render root element.
|
||||||
|
*
|
||||||
|
* @param component The host component to which the renderer runction is to be set
|
||||||
|
* @param rendererName The name of the renderer function
|
||||||
|
* @param templateExpression The content of the template literal passed to Lit for rendering.
|
||||||
|
* @param returnChannel A channel to the server.
|
||||||
|
* Calling it will end up invoking a handler in the server-side LitRenderer.
|
||||||
|
* @param clientCallables A list of function names that can be called from within the template literal.
|
||||||
|
* @param propertyNamespace LitRenderer-specific namespace for properties.
|
||||||
|
* Needed to avoid property name collisions between renderers.
|
||||||
|
*/
|
||||||
|
_window.Vaadin.setLitRenderer = (
|
||||||
|
component: Component,
|
||||||
|
rendererName: string,
|
||||||
|
templateExpression: string,
|
||||||
|
returnChannel: (name: string, itemKey: string, args: any[]) => void,
|
||||||
|
clientCallables: string[],
|
||||||
|
propertyNamespace: string,
|
||||||
|
) => {
|
||||||
|
// Dynamically created function that renders the templateExpression
|
||||||
|
// inside the given root element using Lit
|
||||||
|
const renderFunction = Function(`
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const [render, html, returnChannel] = arguments;
|
||||||
|
|
||||||
|
return (root, {item, index}, itemKey) => {
|
||||||
|
${clientCallables
|
||||||
|
.map((clientCallable) => {
|
||||||
|
// Map all the client-callables as inline functions so they can be accessed from the template literal
|
||||||
|
return `
|
||||||
|
const ${clientCallable} = (...args) => {
|
||||||
|
if (itemKey !== undefined) {
|
||||||
|
returnChannel('${clientCallable}', itemKey, args[0] instanceof Event ? [] : [...args]);
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
})
|
||||||
|
.join('')}
|
||||||
|
|
||||||
|
render(html\`${templateExpression}\`, root)
|
||||||
|
}
|
||||||
|
`)(render, html, returnChannel);
|
||||||
|
|
||||||
|
const renderer: Renderer = (root, _, { index, item }) => {
|
||||||
|
// Clean up the root element of any existing content
|
||||||
|
// (and Lit's _$litPart$ property) from other renderers
|
||||||
|
// TODO: Remove once https://github.com/vaadin/web-components/issues/2235 is done
|
||||||
|
if (root.__litRenderer !== renderer) {
|
||||||
|
root.innerHTML = '';
|
||||||
|
delete root._$litPart$;
|
||||||
|
root.__litRenderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map a new item that only includes the properties defined by
|
||||||
|
// this specific LitRenderer instance. The renderer instance specific
|
||||||
|
// "propertyNamespace" prefix is stripped from the property name at this point:
|
||||||
|
//
|
||||||
|
// item: { key: "2", lr_3_lastName: "Tyler"}
|
||||||
|
// ->
|
||||||
|
// mappedItem: { lastName: "Tyler" }
|
||||||
|
const mappedItem: { [key: string]: any } = {};
|
||||||
|
for (const key in item) {
|
||||||
|
if (key.startsWith(propertyNamespace)) {
|
||||||
|
mappedItem[key.replace(propertyNamespace, '')] = item[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFunction(root, { index, item: mappedItem }, item.key);
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer.__rendererId = propertyNamespace;
|
||||||
|
component[rendererName] = renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the renderer function with the given name from the component
|
||||||
|
* if the propertyNamespace matches the renderer's id.
|
||||||
|
*
|
||||||
|
* @param component The host component whose renderer function is to be removed
|
||||||
|
* @param rendererName The name of the renderer function
|
||||||
|
* @param rendererId The rendererId of the function to be removed
|
||||||
|
*/
|
||||||
|
_window.Vaadin.unsetLitRenderer = (component: Component, rendererName: string, rendererId: string) => {
|
||||||
|
// The check for __rendererId property is necessary since the renderer function
|
||||||
|
// may get overridden by another renderer, for example, by one coming from
|
||||||
|
// vaadin-template-renderer. We don't want LitRenderer registration cleanup to
|
||||||
|
// unintentionally remove the new renderer.
|
||||||
|
if (component[rendererName]?.__rendererId === rendererId) {
|
||||||
|
component[rendererName] = undefined;
|
||||||
|
}
|
||||||
|
};
|
40
frontend/generated/jar-resources/loginOverlayConnector.js
Normal file
40
frontend/generated/jar-resources/loginOverlayConnector.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
(function () {
|
||||||
|
function copyClassName(loginOverlay) {
|
||||||
|
const overlayWrapper = loginOverlay.$.vaadinLoginOverlayWrapper;
|
||||||
|
if (overlayWrapper) {
|
||||||
|
overlayWrapper.className = loginOverlay.className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((records) => {
|
||||||
|
records.forEach((mutation) => {
|
||||||
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||||
|
copyClassName(mutation.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Vaadin.Flow.loginOverlayConnector = {
|
||||||
|
initLazy: function (loginOverlay) {
|
||||||
|
if (loginOverlay.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loginOverlay.$connector = {};
|
||||||
|
|
||||||
|
loginOverlay.addEventListener('opened-changed', (e) => {
|
||||||
|
if (e.detail.value) {
|
||||||
|
copyClassName(loginOverlay);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(loginOverlay, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['class']
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy initial class
|
||||||
|
copyClassName(loginOverlay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
9
frontend/generated/jar-resources/lumo-includes.ts
Normal file
9
frontend/generated/jar-resources/lumo-includes.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { color } from '@vaadin/vaadin-lumo-styles/color.js';
|
||||||
|
import { typography } from '@vaadin/vaadin-lumo-styles/typography.js';
|
||||||
|
|
||||||
|
const tpl = document.createElement('template');
|
||||||
|
tpl.innerHTML = `<style>
|
||||||
|
${color.cssText}
|
||||||
|
${typography.cssText}
|
||||||
|
</style>`;
|
||||||
|
document.head.appendChild(tpl.content);
|
9
frontend/generated/jar-resources/material-includes.ts
Normal file
9
frontend/generated/jar-resources/material-includes.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { colorLight } from '@vaadin/vaadin-material-styles';
|
||||||
|
import { typography } from '@vaadin/vaadin-material-styles';
|
||||||
|
|
||||||
|
const tpl = document.createElement('template');
|
||||||
|
tpl.innerHTML = `<style>
|
||||||
|
${colorLight.cssText}
|
||||||
|
${typography.cssText}
|
||||||
|
</style>`;
|
||||||
|
document.head.appendChild(tpl.content);
|
111
frontend/generated/jar-resources/menubarConnector.js
Normal file
111
frontend/generated/jar-resources/menubarConnector.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2022 Vaadin Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
import './contextMenuConnector.js';
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const tryCatchWrapper = function (callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Menu Bar');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the connector for a menu bar element.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} menubar
|
||||||
|
* @param {string} appId
|
||||||
|
*/
|
||||||
|
function initLazy(menubar, appId) {
|
||||||
|
if (menubar.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((records) => {
|
||||||
|
const hasChangedAttributes = records.some((entry) => {
|
||||||
|
const oldValue = entry.oldValue;
|
||||||
|
const newValue = entry.target.getAttribute(entry.attributeName);
|
||||||
|
return oldValue !== newValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasChangedAttributes) {
|
||||||
|
menubar.$connector.generateItems();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
menubar.$connector = {
|
||||||
|
/**
|
||||||
|
* Generates and assigns the items to the menu bar.
|
||||||
|
*
|
||||||
|
* When the method is called without providing a node id,
|
||||||
|
* the previously generated items tree will be used.
|
||||||
|
* That can be useful if you only want to sync the disabled and hidden properties of root items.
|
||||||
|
*
|
||||||
|
* @param {number | undefined} nodeId
|
||||||
|
*/
|
||||||
|
generateItems: tryCatchWrapper((nodeId) => {
|
||||||
|
if (!menubar.shadowRoot) {
|
||||||
|
// workaround for https://github.com/vaadin/flow/issues/5722
|
||||||
|
setTimeout(() => menubar.$connector.generateItems(nodeId));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeId) {
|
||||||
|
menubar.__generatedItems = window.Vaadin.Flow.contextMenuConnector.generateItemsTree(appId, nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
let items = menubar.__generatedItems || [];
|
||||||
|
|
||||||
|
// Propagate disabled state from items to parent buttons
|
||||||
|
items.forEach((item) => (item.disabled = item.component.disabled));
|
||||||
|
|
||||||
|
// Remove hidden items entirely from the array. Just hiding them
|
||||||
|
// could cause the overflow button to be rendered without items.
|
||||||
|
//
|
||||||
|
// The items-prop needs to be set even when all items are visible
|
||||||
|
// to update the disabled state and re-render buttons.
|
||||||
|
items = items.filter((item) => !item.component.hidden);
|
||||||
|
|
||||||
|
// Observe for hidden and disabled attributes in case they are changed by Flow.
|
||||||
|
// When a change occurs, the observer will re-generate items on top of the existing tree
|
||||||
|
// to sync the new attribute values with the corresponding properties in the items array.
|
||||||
|
items.forEach((item) => {
|
||||||
|
observer.observe(item.component, {
|
||||||
|
attributeFilter: ['hidden', 'disabled'],
|
||||||
|
attributeOldValue: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
menubar.items = items;
|
||||||
|
|
||||||
|
// Propagate click events from the menu buttons to the item components
|
||||||
|
menubar._buttons.forEach((button) => {
|
||||||
|
if (button.item && button.item.component) {
|
||||||
|
button.addEventListener('click', (e) => {
|
||||||
|
if (e.composedPath().indexOf(button.item.component) === -1) {
|
||||||
|
button.item.component.click();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Vaadin.Flow.menubarConnector = {
|
||||||
|
initLazy(...args) {
|
||||||
|
return tryCatchWrapper(initLazy)(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
41
frontend/generated/jar-resources/messageListConnector.js
Normal file
41
frontend/generated/jar-resources/messageListConnector.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2022 Vaadin Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const tryCatchWrapper = function (callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Message List');
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Vaadin.Flow.messageListConnector = {
|
||||||
|
setItems: (list, items, locale) =>
|
||||||
|
tryCatchWrapper(function (list, items, locale) {
|
||||||
|
const formatter = new Intl.DateTimeFormat(locale, {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric'
|
||||||
|
});
|
||||||
|
list.items = items.map((item) =>
|
||||||
|
item.time
|
||||||
|
? Object.assign(item, {
|
||||||
|
time: formatter.format(new Date(item.time))
|
||||||
|
})
|
||||||
|
: item
|
||||||
|
);
|
||||||
|
})(list, items, locale)
|
||||||
|
};
|
||||||
|
})();
|
38
frontend/generated/jar-resources/notificationConnector.js
Normal file
38
frontend/generated/jar-resources/notificationConnector.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
(function () {
|
||||||
|
function copyClassName(notification) {
|
||||||
|
const card = notification._card;
|
||||||
|
if (card) {
|
||||||
|
card.className = notification.className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver((records) => {
|
||||||
|
records.forEach((mutation) => {
|
||||||
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||||
|
copyClassName(mutation.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Vaadin.Flow.notificationConnector = {
|
||||||
|
initLazy: function (notification) {
|
||||||
|
if (notification.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
notification.$connector = {};
|
||||||
|
|
||||||
|
notification.addEventListener('opened-changed', (e) => {
|
||||||
|
if (e.detail.value) {
|
||||||
|
copyClassName(notification);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(notification, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ['class']
|
||||||
|
});
|
||||||
|
|
||||||
|
copyClassName(notification);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
36
frontend/generated/jar-resources/selectConnector.js
Normal file
36
frontend/generated/jar-resources/selectConnector.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
(function () {
|
||||||
|
const tryCatchWrapper = function (callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Select');
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Vaadin.Flow.selectConnector = {
|
||||||
|
initLazy: (select) =>
|
||||||
|
tryCatchWrapper(function (select) {
|
||||||
|
const _findListBoxElement = tryCatchWrapper(function () {
|
||||||
|
for (let i = 0; i < select.childElementCount; i++) {
|
||||||
|
const child = select.children[i];
|
||||||
|
if ('VAADIN-SELECT-LIST-BOX' === child.tagName.toUpperCase()) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// do not init this connector twice for the given select
|
||||||
|
if (select.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.$connector = {};
|
||||||
|
|
||||||
|
select.renderer = tryCatchWrapper(function (root) {
|
||||||
|
const listBox = _findListBoxElement();
|
||||||
|
if (listBox) {
|
||||||
|
if (root.firstChild) {
|
||||||
|
root.removeChild(root.firstChild);
|
||||||
|
}
|
||||||
|
root.appendChild(listBox);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(select)
|
||||||
|
};
|
||||||
|
})();
|
11
frontend/generated/jar-resources/tooltip.ts
Normal file
11
frontend/generated/jar-resources/tooltip.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Tooltip } from '@vaadin/tooltip';
|
||||||
|
|
||||||
|
const _window = window as any;
|
||||||
|
_window.Vaadin = _window.Vaadin || {};
|
||||||
|
_window.Vaadin.Flow = _window.Vaadin.Flow || {};
|
||||||
|
|
||||||
|
_window.Vaadin.Flow.tooltip = {
|
||||||
|
setDefaultHideDelay: (hideDelay: number) => Tooltip.setDefaultHideDelay(hideDelay),
|
||||||
|
setDefaultFocusDelay: (focusDelay: number) => Tooltip.setDefaultFocusDelay(focusDelay),
|
||||||
|
setDefaultHoverDelay: (hoverDelay: number) => Tooltip.setDefaultHoverDelay(hoverDelay),
|
||||||
|
}
|
77
frontend/generated/jar-resources/vaadin-big-decimal-field.js
Normal file
77
frontend/generated/jar-resources/vaadin-big-decimal-field.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2022 Vaadin Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
let memoizedTemplate;
|
||||||
|
|
||||||
|
customElements.whenDefined('vaadin-text-field').then(() => {
|
||||||
|
|
||||||
|
class BigDecimalFieldElement extends customElements.get('vaadin-text-field') {
|
||||||
|
|
||||||
|
static get template() {
|
||||||
|
if (!memoizedTemplate) {
|
||||||
|
memoizedTemplate = super.template.cloneNode(true);
|
||||||
|
memoizedTemplate.innerHTML +=
|
||||||
|
`<style>
|
||||||
|
:host {
|
||||||
|
width: 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([dir="rtl"]) [part="input-field"] {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([dir="rtl"]) [part="input-field"] ::slotted(input) {
|
||||||
|
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em) !important;
|
||||||
|
}
|
||||||
|
</style>`;
|
||||||
|
}
|
||||||
|
return memoizedTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get is() {
|
||||||
|
return 'vaadin-big-decimal-field';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
_decimalSeparator: {
|
||||||
|
type: String,
|
||||||
|
value: '.',
|
||||||
|
observer: '__decimalSeparatorChanged'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
super.ready();
|
||||||
|
this.inputElement.setAttribute('inputmode', 'decimal');
|
||||||
|
}
|
||||||
|
|
||||||
|
__decimalSeparatorChanged(separator, oldSeparator) {
|
||||||
|
this.allowedCharPattern = '[\\d-+' + separator + ']';
|
||||||
|
|
||||||
|
if (this.value && oldSeparator) {
|
||||||
|
this.value = this.value.split(oldSeparator).join(separator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define(BigDecimalFieldElement.is, BigDecimalFieldElement);
|
||||||
|
|
||||||
|
});
|
||||||
|
})();
|
119
frontend/generated/jar-resources/vaadin-dev-tools.d.ts
vendored
Normal file
119
frontend/generated/jar-resources/vaadin-dev-tools.d.ts
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { LitElement } from 'lit';
|
||||||
|
import { Product } from './License';
|
||||||
|
interface Feature {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
moreInfoLink: string;
|
||||||
|
requiresServerRestart: boolean;
|
||||||
|
enabled: boolean;
|
||||||
|
}
|
||||||
|
declare enum ConnectionStatus {
|
||||||
|
ACTIVE = "active",
|
||||||
|
INACTIVE = "inactive",
|
||||||
|
UNAVAILABLE = "unavailable",
|
||||||
|
ERROR = "error"
|
||||||
|
}
|
||||||
|
export declare class Connection extends Object {
|
||||||
|
static HEARTBEAT_INTERVAL: number;
|
||||||
|
status: ConnectionStatus;
|
||||||
|
webSocket?: WebSocket;
|
||||||
|
constructor(url?: string);
|
||||||
|
onHandshake(): void;
|
||||||
|
onReload(): void;
|
||||||
|
onConnectionError(_: string): void;
|
||||||
|
onStatusChange(_: ConnectionStatus): void;
|
||||||
|
onMessage(message: any): void;
|
||||||
|
handleMessage(msg: any): void;
|
||||||
|
handleError(msg: any): void;
|
||||||
|
setActive(yes: boolean): void;
|
||||||
|
setStatus(status: ConnectionStatus): void;
|
||||||
|
private send;
|
||||||
|
setFeature(featureId: string, enabled: boolean): void;
|
||||||
|
sendTelemetry(browserData: any): void;
|
||||||
|
sendLicenseCheck(product: Product): void;
|
||||||
|
}
|
||||||
|
declare enum MessageType {
|
||||||
|
LOG = "log",
|
||||||
|
INFORMATION = "information",
|
||||||
|
WARNING = "warning",
|
||||||
|
ERROR = "error"
|
||||||
|
}
|
||||||
|
interface Message {
|
||||||
|
id: number;
|
||||||
|
type: MessageType;
|
||||||
|
message: string;
|
||||||
|
details?: string;
|
||||||
|
link?: string;
|
||||||
|
persistentId?: string;
|
||||||
|
dontShowAgain: boolean;
|
||||||
|
deleted: boolean;
|
||||||
|
}
|
||||||
|
export declare class VaadinDevTools extends LitElement {
|
||||||
|
static BLUE_HSL: import("lit").CSSResult;
|
||||||
|
static GREEN_HSL: import("lit").CSSResult;
|
||||||
|
static GREY_HSL: import("lit").CSSResult;
|
||||||
|
static YELLOW_HSL: import("lit").CSSResult;
|
||||||
|
static RED_HSL: import("lit").CSSResult;
|
||||||
|
static MAX_LOG_ROWS: number;
|
||||||
|
static get styles(): import("lit").CSSResult;
|
||||||
|
static DISMISSED_NOTIFICATIONS_IN_LOCAL_STORAGE: string;
|
||||||
|
static ACTIVE_KEY_IN_SESSION_STORAGE: string;
|
||||||
|
static TRIGGERED_KEY_IN_SESSION_STORAGE: string;
|
||||||
|
static TRIGGERED_COUNT_KEY_IN_SESSION_STORAGE: string;
|
||||||
|
static AUTO_DEMOTE_NOTIFICATION_DELAY: number;
|
||||||
|
static HOTSWAP_AGENT: string;
|
||||||
|
static JREBEL: string;
|
||||||
|
static SPRING_BOOT_DEVTOOLS: string;
|
||||||
|
static BACKEND_DISPLAY_NAME: Record<string, string>;
|
||||||
|
static get isActive(): boolean;
|
||||||
|
static notificationDismissed(persistentId: string): boolean;
|
||||||
|
url?: string;
|
||||||
|
liveReloadDisabled?: boolean;
|
||||||
|
backend?: string;
|
||||||
|
springBootLiveReloadPort?: number;
|
||||||
|
expanded: boolean;
|
||||||
|
messages: Message[];
|
||||||
|
splashMessage?: string;
|
||||||
|
notifications: Message[];
|
||||||
|
frontendStatus: ConnectionStatus;
|
||||||
|
javaStatus: ConnectionStatus;
|
||||||
|
private tabs;
|
||||||
|
private activeTab;
|
||||||
|
private serverInfo;
|
||||||
|
private features;
|
||||||
|
private unreadErrors;
|
||||||
|
private root;
|
||||||
|
private javaConnection?;
|
||||||
|
private frontendConnection?;
|
||||||
|
private nextMessageId;
|
||||||
|
private disableEventListener?;
|
||||||
|
private transitionDuration;
|
||||||
|
elementTelemetry(): void;
|
||||||
|
openWebSocketConnection(): void;
|
||||||
|
getDedicatedWebSocketUrl(): string | undefined;
|
||||||
|
getSpringBootWebSocketUrl(location: any): string;
|
||||||
|
connectedCallback(): void;
|
||||||
|
format(o: any): string;
|
||||||
|
catchErrors(): void;
|
||||||
|
disconnectedCallback(): void;
|
||||||
|
toggleExpanded(): void;
|
||||||
|
showSplashMessage(msg: string | undefined): void;
|
||||||
|
demoteSplashMessage(): void;
|
||||||
|
checkLicense(productInfo: Product): void;
|
||||||
|
log(type: MessageType, message: string, details?: string, link?: string): void;
|
||||||
|
showNotification(type: MessageType, message: string, details?: string, link?: string, persistentId?: string): void;
|
||||||
|
dismissNotification(id: number): void;
|
||||||
|
findNotificationIndex(id: number): number;
|
||||||
|
toggleDontShowAgain(id: number): void;
|
||||||
|
setActive(yes: boolean): void;
|
||||||
|
getStatusColor(status: ConnectionStatus | undefined): import("lit").CSSResult;
|
||||||
|
renderMessage(messageObject: Message): import("lit-html").TemplateResult<1>;
|
||||||
|
render(): import("lit-html").TemplateResult<1>;
|
||||||
|
renderLog(): import("lit-html").TemplateResult<1>;
|
||||||
|
activateLog(): void;
|
||||||
|
renderInfo(): import("lit-html").TemplateResult<1>;
|
||||||
|
private renderFeatures;
|
||||||
|
copyInfoToClipboard(): void;
|
||||||
|
toggleFeatureFlag(e: Event, feature: Feature): void;
|
||||||
|
}
|
||||||
|
export {};
|
1477
frontend/generated/jar-resources/vaadin-dev-tools.js
Normal file
1477
frontend/generated/jar-resources/vaadin-dev-tools.js
Normal file
File diff suppressed because it is too large
Load Diff
1
frontend/generated/jar-resources/vaadin-dev-tools.js.map
Normal file
1
frontend/generated/jar-resources/vaadin-dev-tools.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,156 @@
|
|||||||
|
import '@vaadin/grid/vaadin-grid-column.js';
|
||||||
|
import { GridColumn } from '@vaadin/grid/src/vaadin-grid-column.js';
|
||||||
|
{
|
||||||
|
class GridFlowSelectionColumnElement extends GridColumn {
|
||||||
|
|
||||||
|
static get is() {
|
||||||
|
return 'vaadin-grid-flow-selection-column';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically sets the width of the column based on the column contents when this is set to `true`.
|
||||||
|
*/
|
||||||
|
autoWidth: {
|
||||||
|
type: Boolean,
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Width of the cells for this column.
|
||||||
|
*/
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
value: '56px'
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flex grow ratio for the cell widths. When set to 0, cell width is fixed.
|
||||||
|
*/
|
||||||
|
flexGrow: {
|
||||||
|
type: Number,
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When true, all the items are selected.
|
||||||
|
*/
|
||||||
|
selectAll: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
notify: true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to display the select all checkbox in indeterminate state,
|
||||||
|
* which means some, but not all, items are selected
|
||||||
|
*/
|
||||||
|
indeterminate: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
notify: true
|
||||||
|
},
|
||||||
|
|
||||||
|
selectAllHidden: Boolean
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._boundOnSelectEvent = this._onSelectEvent.bind(this);
|
||||||
|
this._boundOnDeselectEvent = this._onDeselectEvent.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get observers() {
|
||||||
|
return [
|
||||||
|
'_onHeaderRendererOrBindingChanged(_headerRenderer, _headerCell, path, header, selectAll, indeterminate, selectAllHidden)'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (this._grid) {
|
||||||
|
this._grid.addEventListener('select', this._boundOnSelectEvent);
|
||||||
|
this._grid.addEventListener('deselect', this._boundOnDeselectEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
if (this._grid) {
|
||||||
|
this._grid.removeEventListener('select', this._boundOnSelectEvent);
|
||||||
|
this._grid.removeEventListener('deselect', this._boundOnDeselectEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the Select All checkbox to the header cell.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
_defaultHeaderRenderer(root, _column) {
|
||||||
|
let checkbox = root.firstElementChild;
|
||||||
|
if (!checkbox) {
|
||||||
|
checkbox = document.createElement('vaadin-checkbox');
|
||||||
|
checkbox.id = 'selectAllCheckbox';
|
||||||
|
checkbox.setAttribute('aria-label', 'Select All');
|
||||||
|
checkbox.classList.add('vaadin-grid-select-all-checkbox');
|
||||||
|
checkbox.addEventListener('click', this._onSelectAllClick.bind(this));
|
||||||
|
root.appendChild(checkbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checked = this.selectAll;
|
||||||
|
checkbox.hidden = this.selectAllHidden;
|
||||||
|
checkbox.checked = checked;
|
||||||
|
checkbox.indeterminate = this.indeterminate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the Select Row checkbox to the body cell.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
_defaultRenderer(root, _column, { item, selected }) {
|
||||||
|
let checkbox = root.firstElementChild;
|
||||||
|
if (!checkbox) {
|
||||||
|
checkbox = document.createElement('vaadin-checkbox');
|
||||||
|
checkbox.setAttribute('aria-label', 'Select Row');
|
||||||
|
checkbox.addEventListener('click', this._onSelectClick.bind(this));
|
||||||
|
root.appendChild(checkbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox.__item = item;
|
||||||
|
checkbox.checked = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSelectClick(e) {
|
||||||
|
e.currentTarget.checked ? this._grid.$connector.doDeselection([e.currentTarget.__item], true) : this._grid.$connector.doSelection([e.currentTarget.__item], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSelectAllClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (this._grid.hasAttribute('disabled')) {
|
||||||
|
e.currentTarget.checked = !e.currentTarget.checked;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.selectAll ? this.$server.deselectAll() : this.$server.selectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
_onSelectEvent(e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
_onDeselectEvent(e) {
|
||||||
|
if (e.detail.userOriginated) {
|
||||||
|
this.selectAll = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define(GridFlowSelectionColumnElement.is, GridFlowSelectionColumnElement);
|
||||||
|
|
||||||
|
Vaadin.GridFlowSelectionColumnElement = GridFlowSelectionColumnElement;
|
||||||
|
}
|
183
frontend/generated/jar-resources/vaadin-time-picker/helpers.js
Normal file
183
frontend/generated/jar-resources/vaadin-time-picker/helpers.js
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
// map from unicode eastern arabic number characters to arabic numbers
|
||||||
|
const EASTERN_ARABIC_DIGIT_MAP = {
|
||||||
|
'\\u0660': '0',
|
||||||
|
'\\u0661': '1',
|
||||||
|
'\\u0662': '2',
|
||||||
|
'\\u0663': '3',
|
||||||
|
'\\u0664': '4',
|
||||||
|
'\\u0665': '5',
|
||||||
|
'\\u0666': '6',
|
||||||
|
'\\u0667': '7',
|
||||||
|
'\\u0668': '8',
|
||||||
|
'\\u0669': '9'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes the given string so it can be safely used in a regexp.
|
||||||
|
*
|
||||||
|
* @param {string} string
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
function escapeRegExp(string) {
|
||||||
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses eastern arabic number characters to arabic numbers (0-9)
|
||||||
|
*
|
||||||
|
* @param {string} digits
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
function parseEasternArabicDigits(digits) {
|
||||||
|
return digits.replace(/[\u0660-\u0669]/g, function (char) {
|
||||||
|
const unicode = '\\u0' + char.charCodeAt(0).toString(16);
|
||||||
|
return EASTERN_ARABIC_DIGIT_MAP[unicode];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} locale
|
||||||
|
* @param {Date} testTime
|
||||||
|
* @return {string | null}
|
||||||
|
*/
|
||||||
|
function getAmOrPmString(locale, testTime) {
|
||||||
|
const testTimeString = testTime.toLocaleTimeString(locale);
|
||||||
|
|
||||||
|
// AM/PM string is anything from one letter in eastern arabic to standard two letters,
|
||||||
|
// to having space in between, dots ...
|
||||||
|
// cannot disqualify whitespace since some locales use a. m. / p. m.
|
||||||
|
// TODO when more scripts support is added (than Arabic), need to exclude those numbers too
|
||||||
|
const amOrPmRegExp = /[^\d\u0660-\u0669]/;
|
||||||
|
|
||||||
|
const matches =
|
||||||
|
// In most locales, the time ends with AM/PM:
|
||||||
|
testTimeString.match(new RegExp(`${amOrPmRegExp.source}+$`, 'g')) ||
|
||||||
|
// In some locales, the time starts with AM/PM e.g in Chinese:
|
||||||
|
testTimeString.match(new RegExp(`^${amOrPmRegExp.source}+`, 'g'));
|
||||||
|
|
||||||
|
return matches && matches[0].trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} locale
|
||||||
|
* @return {string | null}
|
||||||
|
*/
|
||||||
|
export function getSeparator(locale) {
|
||||||
|
let timeString = TEST_PM_TIME.toLocaleTimeString(locale);
|
||||||
|
|
||||||
|
// Since the next regex picks first non-number-whitespace,
|
||||||
|
// need to discard possible PM from beginning (eg. chinese locale)
|
||||||
|
const pmString = getPmString(locale);
|
||||||
|
if (pmString && timeString.startsWith(pmString)) {
|
||||||
|
timeString = timeString.replace(pmString, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const matches = timeString.match(/[^\u0660-\u0669\s\d]/);
|
||||||
|
return matches && matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for either an AM or PM token in the given time string
|
||||||
|
* depending on what is provided in `amOrPmString`.
|
||||||
|
*
|
||||||
|
* The search is case and space insensitive.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* `searchAmOrPmToken('1 P M', 'PM')` => `'P M'`
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* `searchAmOrPmToken('1 a.m.', 'A. M.')` => `a.m.`
|
||||||
|
*
|
||||||
|
* @param {string} timeString
|
||||||
|
* @param {string} amOrPmString
|
||||||
|
* @return {string | null}
|
||||||
|
*/
|
||||||
|
export function searchAmOrPmToken(timeString, amOrPmString) {
|
||||||
|
if (!amOrPmString) return null;
|
||||||
|
|
||||||
|
// Create a regexp string for searching for AM/PM without space-sensitivity.
|
||||||
|
const tokenRegExpString = amOrPmString.split(/\s*/).map(escapeRegExp).join('\\s*');
|
||||||
|
|
||||||
|
// Create a regexp without case-sensitivity.
|
||||||
|
const tokenRegExp = new RegExp(tokenRegExpString, 'i');
|
||||||
|
|
||||||
|
// Match the regexp against the time string.
|
||||||
|
const tokenMatches = timeString.match(tokenRegExp);
|
||||||
|
if (tokenMatches) {
|
||||||
|
return tokenMatches[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TEST_PM_TIME = new Date('August 19, 1975 23:15:30');
|
||||||
|
|
||||||
|
export const TEST_AM_TIME = new Date('August 19, 1975 05:15:30');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} locale
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export function getPmString(locale) {
|
||||||
|
return getAmOrPmString(locale, TEST_PM_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} locale
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export function getAmString(locale) {
|
||||||
|
return getAmOrPmString(locale, TEST_AM_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} digits
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
export function parseDigitsIntoInteger(digits) {
|
||||||
|
return parseInt(parseEasternArabicDigits(digits));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} milliseconds
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
export function parseMillisecondsIntoInteger(milliseconds) {
|
||||||
|
milliseconds = parseEasternArabicDigits(milliseconds);
|
||||||
|
// digits are either .1 .01 or .001 so need to "shift"
|
||||||
|
if (milliseconds.length === 1) {
|
||||||
|
milliseconds += '00';
|
||||||
|
} else if (milliseconds.length === 2) {
|
||||||
|
milliseconds += '0';
|
||||||
|
}
|
||||||
|
return parseInt(milliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} timeString
|
||||||
|
* @param {number} milliseconds
|
||||||
|
* @param {string} amString
|
||||||
|
* @param {string} pmString
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export function formatMilliseconds(timeString, milliseconds, amString, pmString) {
|
||||||
|
// might need to inject milliseconds between seconds and AM/PM
|
||||||
|
let cleanedTimeString = timeString;
|
||||||
|
if (timeString.endsWith(amString)) {
|
||||||
|
cleanedTimeString = timeString.replace(' ' + amString, '');
|
||||||
|
} else if (timeString.endsWith(pmString)) {
|
||||||
|
cleanedTimeString = timeString.replace(' ' + pmString, '');
|
||||||
|
}
|
||||||
|
if (milliseconds) {
|
||||||
|
let millisecondsString = milliseconds < 10 ? '0' : '';
|
||||||
|
millisecondsString += milliseconds < 100 ? '0' : '';
|
||||||
|
millisecondsString += milliseconds;
|
||||||
|
cleanedTimeString += '.' + millisecondsString;
|
||||||
|
} else {
|
||||||
|
cleanedTimeString += '.000';
|
||||||
|
}
|
||||||
|
if (timeString.endsWith(amString)) {
|
||||||
|
cleanedTimeString = cleanedTimeString + ' ' + amString;
|
||||||
|
} else if (timeString.endsWith(pmString)) {
|
||||||
|
cleanedTimeString = cleanedTimeString + ' ' + pmString;
|
||||||
|
}
|
||||||
|
return cleanedTimeString;
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
import {
|
||||||
|
TEST_PM_TIME,
|
||||||
|
formatMilliseconds,
|
||||||
|
parseMillisecondsIntoInteger,
|
||||||
|
parseDigitsIntoInteger,
|
||||||
|
getAmString,
|
||||||
|
getPmString,
|
||||||
|
getSeparator,
|
||||||
|
searchAmOrPmToken
|
||||||
|
} from './helpers.js';
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const tryCatchWrapper = function (callback) {
|
||||||
|
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Time Picker');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute callback when predicate returns true.
|
||||||
|
// Try again later if predicate returns false.
|
||||||
|
function when(predicate, callback, timeout = 0) {
|
||||||
|
if (predicate()) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
setTimeout(() => when(predicate, callback, 200), timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Vaadin.Flow.timepickerConnector = {
|
||||||
|
initLazy: (timepicker) =>
|
||||||
|
tryCatchWrapper(function (timepicker) {
|
||||||
|
// Check whether the connector was already initialized for the timepicker
|
||||||
|
if (timepicker.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timepicker.$connector = {};
|
||||||
|
|
||||||
|
timepicker.$connector.setLocale = tryCatchWrapper(function (locale) {
|
||||||
|
// capture previous value if any
|
||||||
|
let previousValueObject;
|
||||||
|
if (timepicker.value && timepicker.value !== '') {
|
||||||
|
previousValueObject = timepicker.i18n.parseTime(timepicker.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check whether the locale is supported by the browser or not
|
||||||
|
TEST_PM_TIME.toLocaleTimeString(locale);
|
||||||
|
} catch (e) {
|
||||||
|
locale = 'en-US';
|
||||||
|
// FIXME should do a callback for server to throw an exception ?
|
||||||
|
throw new Error(
|
||||||
|
'vaadin-time-picker: The locale ' +
|
||||||
|
locale +
|
||||||
|
' is not supported, falling back to default locale setting(en-US).'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 24 or 12 hour clock, if latter then what are the am/pm strings ?
|
||||||
|
const pmString = getPmString(locale);
|
||||||
|
const amString = getAmString(locale);
|
||||||
|
|
||||||
|
// 2. What is the separator ?
|
||||||
|
const separator = getSeparator(locale);
|
||||||
|
|
||||||
|
const includeSeconds = function () {
|
||||||
|
return timepicker.step && timepicker.step < 60;
|
||||||
|
};
|
||||||
|
|
||||||
|
const includeMilliSeconds = function () {
|
||||||
|
return timepicker.step && timepicker.step < 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
let cachedTimeString;
|
||||||
|
let cachedTimeObject;
|
||||||
|
|
||||||
|
timepicker.i18n = {
|
||||||
|
formatTime: tryCatchWrapper(function (timeObject) {
|
||||||
|
if (!timeObject) return;
|
||||||
|
|
||||||
|
const timeToBeFormatted = new Date();
|
||||||
|
timeToBeFormatted.setHours(timeObject.hours);
|
||||||
|
timeToBeFormatted.setMinutes(timeObject.minutes);
|
||||||
|
timeToBeFormatted.setSeconds(timeObject.seconds !== undefined ? timeObject.seconds : 0);
|
||||||
|
|
||||||
|
// the web component expects the correct granularity used for the time string,
|
||||||
|
// thus need to format the time object in correct granularity by passing the format options
|
||||||
|
let localeTimeString = timeToBeFormatted.toLocaleTimeString(locale, {
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
second: includeSeconds() ? 'numeric' : undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// milliseconds not part of the time format API
|
||||||
|
if (includeMilliSeconds()) {
|
||||||
|
localeTimeString = formatMilliseconds(localeTimeString, timeObject.milliseconds, amString, pmString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return localeTimeString;
|
||||||
|
}),
|
||||||
|
|
||||||
|
parseTime: tryCatchWrapper(function (timeString) {
|
||||||
|
if (timeString && timeString === cachedTimeString && cachedTimeObject) {
|
||||||
|
return cachedTimeObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeString) {
|
||||||
|
// when nothing is returned, the component shows the invalid state for the input
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const amToken = searchAmOrPmToken(timeString, amString);
|
||||||
|
const pmToken = searchAmOrPmToken(timeString, pmString);
|
||||||
|
|
||||||
|
const numbersOnlyTimeString = timeString
|
||||||
|
.replace(amToken || '', '')
|
||||||
|
.replace(pmToken || '', '')
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
// A regexp that allows to find the numbers with optional separator and continuing searching after it.
|
||||||
|
const numbersRegExp = new RegExp('([\\d\\u0660-\\u0669]){1,2}(?:' + separator + ')?', 'g');
|
||||||
|
|
||||||
|
let hours = numbersRegExp.exec(numbersOnlyTimeString);
|
||||||
|
if (hours) {
|
||||||
|
hours = parseDigitsIntoInteger(hours[0].replace(separator, ''));
|
||||||
|
// handle 12 am -> 0
|
||||||
|
// do not do anything if am & pm are not used or if those are the same,
|
||||||
|
// as with locale bg-BG there is always ч. at the end of the time
|
||||||
|
if (amToken !== pmToken) {
|
||||||
|
if (hours === 12 && amToken) {
|
||||||
|
hours = 0;
|
||||||
|
}
|
||||||
|
if (hours !== 12 && pmToken) {
|
||||||
|
hours += 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const minutes = numbersRegExp.exec(numbersOnlyTimeString);
|
||||||
|
const seconds = minutes && numbersRegExp.exec(numbersOnlyTimeString);
|
||||||
|
// detecting milliseconds from input, expects am/pm removed from end, eg. .0 or .00 or .000
|
||||||
|
const millisecondRegExp = /[[\.][\d\u0660-\u0669]{1,3}$/;
|
||||||
|
// reset to end or things can explode
|
||||||
|
let milliseconds = seconds && includeMilliSeconds() && millisecondRegExp.exec(numbersOnlyTimeString);
|
||||||
|
// handle case where last numbers are seconds and . is the separator (invalid regexp match)
|
||||||
|
if (milliseconds && milliseconds['index'] <= seconds['index']) {
|
||||||
|
milliseconds = undefined;
|
||||||
|
}
|
||||||
|
// hours is a number at this point, others are either arrays or null
|
||||||
|
// the string in [0] from the arrays includes the separator too
|
||||||
|
cachedTimeObject = hours !== undefined && {
|
||||||
|
hours: hours,
|
||||||
|
minutes: minutes ? parseDigitsIntoInteger(minutes[0].replace(separator, '')) : 0,
|
||||||
|
seconds: seconds ? parseDigitsIntoInteger(seconds[0].replace(separator, '')) : 0,
|
||||||
|
milliseconds:
|
||||||
|
minutes && seconds && milliseconds
|
||||||
|
? parseMillisecondsIntoInteger(milliseconds[0].replace('.', ''))
|
||||||
|
: 0
|
||||||
|
};
|
||||||
|
cachedTimeString = timeString;
|
||||||
|
return cachedTimeObject;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
if (previousValueObject) {
|
||||||
|
when(
|
||||||
|
() => timepicker.$,
|
||||||
|
() => {
|
||||||
|
const newValue = timepicker.i18n.formatTime(previousValueObject);
|
||||||
|
// FIXME works but uses private API, needs fixes in web component
|
||||||
|
if (timepicker.inputElement.value !== newValue) {
|
||||||
|
timepicker.inputElement.value = newValue;
|
||||||
|
timepicker.$.comboBox.value = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(timepicker)
|
||||||
|
};
|
||||||
|
})();
|
130
frontend/generated/jar-resources/virtualListConnector.js
Normal file
130
frontend/generated/jar-resources/virtualListConnector.js
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
||||||
|
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
|
||||||
|
|
||||||
|
window.Vaadin.Flow.virtualListConnector = {
|
||||||
|
initLazy: function (list) {
|
||||||
|
// Check whether the connector was already initialized for the virtual list
|
||||||
|
if (list.$connector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const extraItemsBuffer = 20;
|
||||||
|
|
||||||
|
let lastRequestedRange = [0, 0];
|
||||||
|
|
||||||
|
list.$connector = {};
|
||||||
|
list.$connector.placeholderItem = { __placeholder: true };
|
||||||
|
|
||||||
|
const updateRequestedItem = function () {
|
||||||
|
/*
|
||||||
|
* TODO virtual list seems to do a small index adjustment after scrolling
|
||||||
|
* has stopped. This causes a redundant request to be sent to make a
|
||||||
|
* corresponding minimal change to the buffer. We should avoid these
|
||||||
|
* requests by making the logic skip doing a request if the available
|
||||||
|
* buffer is within some tolerance compared to the requested buffer.
|
||||||
|
*/
|
||||||
|
const visibleIndexes = [...list.children]
|
||||||
|
.filter((el) => '__virtualListIndex' in el)
|
||||||
|
.map((el) => el.__virtualListIndex);
|
||||||
|
const firstNeededItem = Math.min(...visibleIndexes);
|
||||||
|
const lastNeededItem = Math.max(...visibleIndexes);
|
||||||
|
|
||||||
|
let first = Math.max(0, firstNeededItem - extraItemsBuffer);
|
||||||
|
let last = Math.min(lastNeededItem + extraItemsBuffer, list.items.length);
|
||||||
|
|
||||||
|
if (lastRequestedRange[0] != first || lastRequestedRange[1] != last) {
|
||||||
|
lastRequestedRange = [first, last];
|
||||||
|
const count = 1 + last - first;
|
||||||
|
list.$server.setRequestedRange(first, count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const scheduleUpdateRequest = function () {
|
||||||
|
list.__requestDebounce = Debouncer.debounce(list.__requestDebounce, timeOut.after(50), updateRequestedItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
requestAnimationFrame(() => updateRequestedItem);
|
||||||
|
|
||||||
|
// Add an observer function that will invoke on virtualList.renderer property
|
||||||
|
// change and then patches it with a wrapper renderer
|
||||||
|
list.patchVirtualListRenderer = function () {
|
||||||
|
if (!list.renderer || list.renderer.__virtualListConnectorPatched) {
|
||||||
|
// The list either doesn't have a renderer yet or it's already been patched
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalRenderer = list.renderer;
|
||||||
|
|
||||||
|
const renderer = (root, list, model) => {
|
||||||
|
root.__virtualListIndex = model.index;
|
||||||
|
|
||||||
|
if (model.item === undefined) {
|
||||||
|
originalRenderer.call(list, root, list, {
|
||||||
|
...model,
|
||||||
|
item: list.$connector.placeholderItem
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
originalRenderer.call(list, root, list, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we need to do anything once things have settled down.
|
||||||
|
* This method is called multiple times in sequence for the same user
|
||||||
|
* action, but we only want to do the check once.
|
||||||
|
*/
|
||||||
|
scheduleUpdateRequest();
|
||||||
|
};
|
||||||
|
renderer.__virtualListConnectorPatched = true;
|
||||||
|
renderer.__rendererId = originalRenderer.__rendererId;
|
||||||
|
|
||||||
|
list.renderer = renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
list._createPropertyObserver('renderer', 'patchVirtualListRenderer', true);
|
||||||
|
list.patchVirtualListRenderer();
|
||||||
|
|
||||||
|
list.items = [];
|
||||||
|
|
||||||
|
list.$connector.set = function (index, items) {
|
||||||
|
list.items.splice(index, items.length, ...items);
|
||||||
|
list.items = [...list.items];
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.clear = function (index, length) {
|
||||||
|
// How many items, starting from "index", should be set as undefined
|
||||||
|
const clearCount = Math.min(length, list.items.length - index);
|
||||||
|
list.$connector.set(index, [...Array(clearCount)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.updateData = function (items) {
|
||||||
|
const updatedItemsMap = items.reduce((map, item) => {
|
||||||
|
map[item.key] = item;
|
||||||
|
return map;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
list.items = list.items.map((item) => {
|
||||||
|
// Items can be undefined if they are outside the viewport
|
||||||
|
if (!item) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
// Replace existing item with updated item,
|
||||||
|
// return existing item as fallback if it was not updated
|
||||||
|
return updatedItemsMap[item.key] || item;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.updateSize = function (newSize) {
|
||||||
|
const delta = newSize - list.items.length;
|
||||||
|
if (delta > 0) {
|
||||||
|
list.items = [...list.items, ...Array(delta)];
|
||||||
|
} else if (delta < 0) {
|
||||||
|
list.items = list.items.slice(0, newSize);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
list.$connector.setPlaceholderItem = function (placeholderItem = {}) {
|
||||||
|
placeholderItem.__placeholder = true;
|
||||||
|
list.$connector.placeholderItem = placeholderItem;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
11
frontend/generated/vaadin-featureflags.ts
Normal file
11
frontend/generated/vaadin-featureflags.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
window.Vaadin = window.Vaadin || {};
|
||||||
|
window.Vaadin.featureFlags = window.Vaadin.featureFlags || {};
|
||||||
|
window.Vaadin.featureFlags.exampleFeatureFlag = false;
|
||||||
|
window.Vaadin.featureFlags.hillaPush = false;
|
||||||
|
window.Vaadin.featureFlags.hillaEngine = false;
|
||||||
|
window.Vaadin.featureFlags.oldLicenseChecker = false;
|
||||||
|
window.Vaadin.featureFlags.collaborationEngineBackend = false;
|
||||||
|
window.Vaadin.featureFlags.webpackForFrontendBuild = false;
|
||||||
|
window.Vaadin.featureFlags.enforceFieldValidation = false;
|
||||||
|
export {};
|
5
frontend/generated/vaadin.ts
Normal file
5
frontend/generated/vaadin.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import './vaadin-featureflags.ts';
|
||||||
|
|
||||||
|
import './index';
|
||||||
|
|
||||||
|
import 'Frontend/generated/jar-resources/vaadin-dev-tools.js';
|
31
frontend/generated/vite-devmode.ts
Normal file
31
frontend/generated/vite-devmode.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
if (import.meta.hot) {
|
||||||
|
// @ts-ignore
|
||||||
|
const hot = import.meta.hot;
|
||||||
|
|
||||||
|
const isLiveReloadDisabled = () => {
|
||||||
|
// Checks if live reload is disabled in the debug window
|
||||||
|
return sessionStorage.getItem('vaadin.live-reload.active') === 'false';
|
||||||
|
};
|
||||||
|
|
||||||
|
const preventViteReload = (payload: any) => {
|
||||||
|
// Changing the path prevents Vite from reloading
|
||||||
|
payload.path = '/_fake/path.html';
|
||||||
|
};
|
||||||
|
|
||||||
|
let pendingNavigationTo: string | undefined = undefined;
|
||||||
|
|
||||||
|
window.addEventListener('vaadin-router-go', (routerEvent: any) => {
|
||||||
|
pendingNavigationTo = routerEvent.detail.pathname + routerEvent.detail.search;
|
||||||
|
});
|
||||||
|
hot.on('vite:beforeFullReload', (payload: any) => {
|
||||||
|
if (isLiveReloadDisabled()) {
|
||||||
|
preventViteReload(payload);
|
||||||
|
}
|
||||||
|
if (pendingNavigationTo) {
|
||||||
|
// Force reload with the new URL
|
||||||
|
location.href = pendingNavigationTo;
|
||||||
|
preventViteReload(payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
23
frontend/index.html
Normal file
23
frontend/index.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
This file is auto-generated by Vaadin.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
body, #outlet {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!-- index.ts is included here automatically (either by the dev server or during the build) -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- This outlet div is where the views are rendered -->
|
||||||
|
<div id="outlet"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
316
mvnw
vendored
Normal file
316
mvnw
vendored
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Maven Start Up Batch script
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# M2_HOME - location of maven2's installed home dir
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||||
|
. /usr/local/etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||||
|
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
if [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||||
|
else
|
||||||
|
export JAVA_HOME="/Library/Java/Home"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=`java-config --jre-home`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$M2_HOME" ] ; then
|
||||||
|
## resolve links - $0 may be a link to maven's home
|
||||||
|
PRG="$0"
|
||||||
|
|
||||||
|
# need this for relative symlinks
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG="`dirname "$PRG"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
saveddir=`pwd`
|
||||||
|
|
||||||
|
M2_HOME=`dirname "$PRG"`/..
|
||||||
|
|
||||||
|
# make it fully qualified
|
||||||
|
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||||
|
|
||||||
|
cd "$saveddir"
|
||||||
|
# echo Using m2 at $M2_HOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="`which javac`"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=`which readlink`
|
||||||
|
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||||
|
fi
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="`\\unset -f command; \\command -v java`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Path not specified to find_maven_basedir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
basedir="$1"
|
||||||
|
wdir="$1"
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||||
|
if [ -d "${wdir}" ]; then
|
||||||
|
wdir=`cd "$wdir/.."; pwd`
|
||||||
|
fi
|
||||||
|
# end of workaround
|
||||||
|
done
|
||||||
|
echo "${basedir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "$(tr -s '\n' ' ' < "$1")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||||
|
if [ -z "$BASE_DIR" ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
##########################################################################################
|
||||||
|
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||||
|
fi
|
||||||
|
if [ -n "$MVNW_REPOURL" ]; then
|
||||||
|
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
else
|
||||||
|
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
fi
|
||||||
|
while IFS="=" read key value; do
|
||||||
|
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||||
|
esac
|
||||||
|
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Downloading from: $jarUrl"
|
||||||
|
fi
|
||||||
|
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||||
|
if $cygwin; then
|
||||||
|
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found wget ... using wget"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
elif command -v curl > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found curl ... using curl"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
else
|
||||||
|
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Falling back to using Java to download"
|
||||||
|
fi
|
||||||
|
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||||
|
# For Cygwin, switch paths to Windows format before running javac
|
||||||
|
if $cygwin; then
|
||||||
|
javaClass=`cygpath --path --windows "$javaClass"`
|
||||||
|
fi
|
||||||
|
if [ -e "$javaClass" ]; then
|
||||||
|
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
# Compiling the Java class
|
||||||
|
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||||
|
fi
|
||||||
|
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
# Running the downloader
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Running MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
##########################################################################################
|
||||||
|
# End of extension
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo $MAVEN_PROJECTBASEDIR
|
||||||
|
fi
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||||
|
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||||
|
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
# work with both Windows and non-Windows executions.
|
||||||
|
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||||
|
export MAVEN_CMD_LINE_ARGS
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
$MAVEN_DEBUG_OPTS \
|
||||||
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
|
"-Dmaven.home=${M2_HOME}" \
|
||||||
|
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
188
mvnw.cmd
vendored
Normal file
188
mvnw.cmd
vendored
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Maven Start Up Batch script
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM M2_HOME - location of maven2's installed home dir
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM set title of command window
|
||||||
|
title %0
|
||||||
|
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||||
|
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
@REM ==== END VALIDATION ====
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
|
||||||
|
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
|
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||||
|
)
|
||||||
|
|
||||||
|
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
if exist %WRAPPER_JAR% (
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Found %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
if not "%MVNW_REPOURL%" == "" (
|
||||||
|
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
)
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||||
|
echo Downloading from: %DOWNLOAD_URL%
|
||||||
|
)
|
||||||
|
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$webclient = new-object System.Net.WebClient;"^
|
||||||
|
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||||
|
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||||
|
"}"^
|
||||||
|
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||||
|
"}"
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Finished downloading %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@REM End of extension
|
||||||
|
|
||||||
|
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
@REM work with both Windows and non-Windows executions.
|
||||||
|
set MAVEN_CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
%MAVEN_JAVA_EXE% ^
|
||||||
|
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||||
|
%MAVEN_OPTS% ^
|
||||||
|
%MAVEN_DEBUG_OPTS% ^
|
||||||
|
-classpath %WRAPPER_JAR% ^
|
||||||
|
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||||
|
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||||
|
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
cmd /C exit /B %ERROR_CODE%
|
12371
package-lock.json
generated
Normal file
12371
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
360
package.json
Normal file
360
package.json
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
{
|
||||||
|
"name": "no-name",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"dependencies": {
|
||||||
|
"@polymer/iron-icon": "3.0.1",
|
||||||
|
"@polymer/iron-iconset-svg": "3.0.1",
|
||||||
|
"@polymer/iron-list": "3.1.0",
|
||||||
|
"@polymer/iron-meta": "3.0.1",
|
||||||
|
"@polymer/iron-resizable-behavior": "3.0.1",
|
||||||
|
"@polymer/polymer": "3.5.1",
|
||||||
|
"@vaadin/accordion": "23.3.5",
|
||||||
|
"@vaadin/app-layout": "23.3.5",
|
||||||
|
"@vaadin/avatar": "23.3.5",
|
||||||
|
"@vaadin/avatar-group": "23.3.5",
|
||||||
|
"@vaadin/bundles": "23.3.5",
|
||||||
|
"@vaadin/button": "23.3.5",
|
||||||
|
"@vaadin/checkbox": "23.3.5",
|
||||||
|
"@vaadin/checkbox-group": "23.3.5",
|
||||||
|
"@vaadin/combo-box": "23.3.5",
|
||||||
|
"@vaadin/common-frontend": "0.0.17",
|
||||||
|
"@vaadin/component-base": "23.3.5",
|
||||||
|
"@vaadin/confirm-dialog": "23.3.5",
|
||||||
|
"@vaadin/context-menu": "23.3.5",
|
||||||
|
"@vaadin/custom-field": "23.3.5",
|
||||||
|
"@vaadin/date-picker": "23.3.5",
|
||||||
|
"@vaadin/date-time-picker": "23.3.5",
|
||||||
|
"@vaadin/details": "23.3.5",
|
||||||
|
"@vaadin/dialog": "23.3.5",
|
||||||
|
"@vaadin/email-field": "23.3.5",
|
||||||
|
"@vaadin/field-base": "23.3.5",
|
||||||
|
"@vaadin/field-highlighter": "23.3.5",
|
||||||
|
"@vaadin/form-layout": "23.3.5",
|
||||||
|
"@vaadin/grid": "23.3.5",
|
||||||
|
"@vaadin/horizontal-layout": "23.3.5",
|
||||||
|
"@vaadin/icon": "23.3.5",
|
||||||
|
"@vaadin/icons": "23.3.5",
|
||||||
|
"@vaadin/input-container": "23.3.5",
|
||||||
|
"@vaadin/integer-field": "23.3.5",
|
||||||
|
"@vaadin/item": "23.3.5",
|
||||||
|
"@vaadin/list-box": "23.3.5",
|
||||||
|
"@vaadin/lit-renderer": "23.3.5",
|
||||||
|
"@vaadin/login": "23.3.5",
|
||||||
|
"@vaadin/menu-bar": "23.3.5",
|
||||||
|
"@vaadin/message-input": "23.3.5",
|
||||||
|
"@vaadin/message-list": "23.3.5",
|
||||||
|
"@vaadin/multi-select-combo-box": "23.3.5",
|
||||||
|
"@vaadin/notification": "23.3.5",
|
||||||
|
"@vaadin/number-field": "23.3.5",
|
||||||
|
"@vaadin/password-field": "23.3.5",
|
||||||
|
"@vaadin/polymer-legacy-adapter": "23.3.5",
|
||||||
|
"@vaadin/progress-bar": "23.3.5",
|
||||||
|
"@vaadin/radio-group": "23.3.5",
|
||||||
|
"@vaadin/router": "1.7.4",
|
||||||
|
"@vaadin/scroller": "23.3.5",
|
||||||
|
"@vaadin/select": "23.3.5",
|
||||||
|
"@vaadin/split-layout": "23.3.5",
|
||||||
|
"@vaadin/tabs": "23.3.5",
|
||||||
|
"@vaadin/tabsheet": "23.3.5",
|
||||||
|
"@vaadin/text-area": "23.3.5",
|
||||||
|
"@vaadin/text-field": "23.3.5",
|
||||||
|
"@vaadin/time-picker": "23.3.5",
|
||||||
|
"@vaadin/tooltip": "23.3.5",
|
||||||
|
"@vaadin/upload": "23.3.5",
|
||||||
|
"@vaadin/vaadin-accordion": "23.3.5",
|
||||||
|
"@vaadin/vaadin-app-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-avatar": "23.3.5",
|
||||||
|
"@vaadin/vaadin-button": "23.3.5",
|
||||||
|
"@vaadin/vaadin-checkbox": "23.3.5",
|
||||||
|
"@vaadin/vaadin-combo-box": "23.3.5",
|
||||||
|
"@vaadin/vaadin-confirm-dialog": "23.3.5",
|
||||||
|
"@vaadin/vaadin-context-menu": "23.3.5",
|
||||||
|
"@vaadin/vaadin-custom-field": "23.3.5",
|
||||||
|
"@vaadin/vaadin-date-picker": "23.3.5",
|
||||||
|
"@vaadin/vaadin-date-time-picker": "23.3.5",
|
||||||
|
"@vaadin/vaadin-details": "23.3.5",
|
||||||
|
"@vaadin/vaadin-development-mode-detector": "2.0.5",
|
||||||
|
"@vaadin/vaadin-dialog": "23.3.5",
|
||||||
|
"@vaadin/vaadin-form-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-grid": "23.3.5",
|
||||||
|
"@vaadin/vaadin-icon": "23.3.5",
|
||||||
|
"@vaadin/vaadin-icons": "23.3.5",
|
||||||
|
"@vaadin/vaadin-item": "23.3.5",
|
||||||
|
"@vaadin/vaadin-list-box": "23.3.5",
|
||||||
|
"@vaadin/vaadin-list-mixin": "23.3.5",
|
||||||
|
"@vaadin/vaadin-login": "23.3.5",
|
||||||
|
"@vaadin/vaadin-lumo-styles": "23.3.5",
|
||||||
|
"@vaadin/vaadin-material-styles": "23.3.5",
|
||||||
|
"@vaadin/vaadin-menu-bar": "23.3.5",
|
||||||
|
"@vaadin/vaadin-messages": "23.3.5",
|
||||||
|
"@vaadin/vaadin-notification": "23.3.5",
|
||||||
|
"@vaadin/vaadin-ordered-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-overlay": "23.3.5",
|
||||||
|
"@vaadin/vaadin-progress-bar": "23.3.5",
|
||||||
|
"@vaadin/vaadin-radio-button": "23.3.5",
|
||||||
|
"@vaadin/vaadin-select": "23.3.5",
|
||||||
|
"@vaadin/vaadin-split-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-tabs": "23.3.5",
|
||||||
|
"@vaadin/vaadin-template-renderer": "23.3.5",
|
||||||
|
"@vaadin/vaadin-text-field": "23.3.5",
|
||||||
|
"@vaadin/vaadin-themable-mixin": "23.3.5",
|
||||||
|
"@vaadin/vaadin-time-picker": "23.3.5",
|
||||||
|
"@vaadin/vaadin-upload": "23.3.5",
|
||||||
|
"@vaadin/vaadin-usage-statistics": "2.1.2",
|
||||||
|
"@vaadin/vaadin-virtual-list": "23.3.5",
|
||||||
|
"@vaadin/vertical-layout": "23.3.5",
|
||||||
|
"@vaadin/virtual-list": "23.3.5",
|
||||||
|
"construct-style-sheets-polyfill": "3.1.0",
|
||||||
|
"date-fns": "2.29.3",
|
||||||
|
"lit": "2.6.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-replace": "3.1.0",
|
||||||
|
"@rollup/pluginutils": "4.1.0",
|
||||||
|
"async": "3.2.2",
|
||||||
|
"glob": "7.2.3",
|
||||||
|
"mkdirp": "1.0.4",
|
||||||
|
"rollup-plugin-brotli": "3.1.0",
|
||||||
|
"strip-css-comments": "5.0.0",
|
||||||
|
"transform-ast": "2.4.4",
|
||||||
|
"typescript": "4.9.3",
|
||||||
|
"vite": "3.2.5",
|
||||||
|
"vite-plugin-checker": "0.5.1",
|
||||||
|
"workbox-build": "6.5.4",
|
||||||
|
"workbox-core": "6.5.4",
|
||||||
|
"workbox-precaching": "6.5.4"
|
||||||
|
},
|
||||||
|
"vaadin": {
|
||||||
|
"dependencies": {
|
||||||
|
"@polymer/iron-icon": "3.0.1",
|
||||||
|
"@polymer/iron-iconset-svg": "3.0.1",
|
||||||
|
"@polymer/iron-list": "3.1.0",
|
||||||
|
"@polymer/iron-meta": "3.0.1",
|
||||||
|
"@polymer/iron-resizable-behavior": "3.0.1",
|
||||||
|
"@polymer/polymer": "3.5.1",
|
||||||
|
"@vaadin/accordion": "23.3.5",
|
||||||
|
"@vaadin/app-layout": "23.3.5",
|
||||||
|
"@vaadin/avatar": "23.3.5",
|
||||||
|
"@vaadin/avatar-group": "23.3.5",
|
||||||
|
"@vaadin/bundles": "23.3.5",
|
||||||
|
"@vaadin/button": "23.3.5",
|
||||||
|
"@vaadin/checkbox": "23.3.5",
|
||||||
|
"@vaadin/checkbox-group": "23.3.5",
|
||||||
|
"@vaadin/combo-box": "23.3.5",
|
||||||
|
"@vaadin/common-frontend": "0.0.17",
|
||||||
|
"@vaadin/component-base": "23.3.5",
|
||||||
|
"@vaadin/confirm-dialog": "23.3.5",
|
||||||
|
"@vaadin/context-menu": "23.3.5",
|
||||||
|
"@vaadin/custom-field": "23.3.5",
|
||||||
|
"@vaadin/date-picker": "23.3.5",
|
||||||
|
"@vaadin/date-time-picker": "23.3.5",
|
||||||
|
"@vaadin/details": "23.3.5",
|
||||||
|
"@vaadin/dialog": "23.3.5",
|
||||||
|
"@vaadin/email-field": "23.3.5",
|
||||||
|
"@vaadin/field-base": "23.3.5",
|
||||||
|
"@vaadin/field-highlighter": "23.3.5",
|
||||||
|
"@vaadin/form-layout": "23.3.5",
|
||||||
|
"@vaadin/grid": "23.3.5",
|
||||||
|
"@vaadin/horizontal-layout": "23.3.5",
|
||||||
|
"@vaadin/icon": "23.3.5",
|
||||||
|
"@vaadin/icons": "23.3.5",
|
||||||
|
"@vaadin/input-container": "23.3.5",
|
||||||
|
"@vaadin/integer-field": "23.3.5",
|
||||||
|
"@vaadin/item": "23.3.5",
|
||||||
|
"@vaadin/list-box": "23.3.5",
|
||||||
|
"@vaadin/lit-renderer": "23.3.5",
|
||||||
|
"@vaadin/login": "23.3.5",
|
||||||
|
"@vaadin/menu-bar": "23.3.5",
|
||||||
|
"@vaadin/message-input": "23.3.5",
|
||||||
|
"@vaadin/message-list": "23.3.5",
|
||||||
|
"@vaadin/multi-select-combo-box": "23.3.5",
|
||||||
|
"@vaadin/notification": "23.3.5",
|
||||||
|
"@vaadin/number-field": "23.3.5",
|
||||||
|
"@vaadin/password-field": "23.3.5",
|
||||||
|
"@vaadin/polymer-legacy-adapter": "23.3.5",
|
||||||
|
"@vaadin/progress-bar": "23.3.5",
|
||||||
|
"@vaadin/radio-group": "23.3.5",
|
||||||
|
"@vaadin/router": "1.7.4",
|
||||||
|
"@vaadin/scroller": "23.3.5",
|
||||||
|
"@vaadin/select": "23.3.5",
|
||||||
|
"@vaadin/split-layout": "23.3.5",
|
||||||
|
"@vaadin/tabs": "23.3.5",
|
||||||
|
"@vaadin/tabsheet": "23.3.5",
|
||||||
|
"@vaadin/text-area": "23.3.5",
|
||||||
|
"@vaadin/text-field": "23.3.5",
|
||||||
|
"@vaadin/time-picker": "23.3.5",
|
||||||
|
"@vaadin/tooltip": "23.3.5",
|
||||||
|
"@vaadin/upload": "23.3.5",
|
||||||
|
"@vaadin/vaadin-accordion": "23.3.5",
|
||||||
|
"@vaadin/vaadin-app-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-avatar": "23.3.5",
|
||||||
|
"@vaadin/vaadin-button": "23.3.5",
|
||||||
|
"@vaadin/vaadin-checkbox": "23.3.5",
|
||||||
|
"@vaadin/vaadin-combo-box": "23.3.5",
|
||||||
|
"@vaadin/vaadin-confirm-dialog": "23.3.5",
|
||||||
|
"@vaadin/vaadin-context-menu": "23.3.5",
|
||||||
|
"@vaadin/vaadin-custom-field": "23.3.5",
|
||||||
|
"@vaadin/vaadin-date-picker": "23.3.5",
|
||||||
|
"@vaadin/vaadin-date-time-picker": "23.3.5",
|
||||||
|
"@vaadin/vaadin-details": "23.3.5",
|
||||||
|
"@vaadin/vaadin-development-mode-detector": "2.0.5",
|
||||||
|
"@vaadin/vaadin-dialog": "23.3.5",
|
||||||
|
"@vaadin/vaadin-form-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-grid": "23.3.5",
|
||||||
|
"@vaadin/vaadin-icon": "23.3.5",
|
||||||
|
"@vaadin/vaadin-icons": "23.3.5",
|
||||||
|
"@vaadin/vaadin-item": "23.3.5",
|
||||||
|
"@vaadin/vaadin-list-box": "23.3.5",
|
||||||
|
"@vaadin/vaadin-list-mixin": "23.3.5",
|
||||||
|
"@vaadin/vaadin-login": "23.3.5",
|
||||||
|
"@vaadin/vaadin-lumo-styles": "23.3.5",
|
||||||
|
"@vaadin/vaadin-material-styles": "23.3.5",
|
||||||
|
"@vaadin/vaadin-menu-bar": "23.3.5",
|
||||||
|
"@vaadin/vaadin-messages": "23.3.5",
|
||||||
|
"@vaadin/vaadin-notification": "23.3.5",
|
||||||
|
"@vaadin/vaadin-ordered-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-overlay": "23.3.5",
|
||||||
|
"@vaadin/vaadin-progress-bar": "23.3.5",
|
||||||
|
"@vaadin/vaadin-radio-button": "23.3.5",
|
||||||
|
"@vaadin/vaadin-select": "23.3.5",
|
||||||
|
"@vaadin/vaadin-split-layout": "23.3.5",
|
||||||
|
"@vaadin/vaadin-tabs": "23.3.5",
|
||||||
|
"@vaadin/vaadin-template-renderer": "23.3.5",
|
||||||
|
"@vaadin/vaadin-text-field": "23.3.5",
|
||||||
|
"@vaadin/vaadin-themable-mixin": "23.3.5",
|
||||||
|
"@vaadin/vaadin-time-picker": "23.3.5",
|
||||||
|
"@vaadin/vaadin-upload": "23.3.5",
|
||||||
|
"@vaadin/vaadin-usage-statistics": "2.1.2",
|
||||||
|
"@vaadin/vaadin-virtual-list": "23.3.5",
|
||||||
|
"@vaadin/vertical-layout": "23.3.5",
|
||||||
|
"@vaadin/virtual-list": "23.3.5",
|
||||||
|
"construct-style-sheets-polyfill": "3.1.0",
|
||||||
|
"date-fns": "2.29.3",
|
||||||
|
"lit": "2.6.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-replace": "3.1.0",
|
||||||
|
"@rollup/pluginutils": "4.1.0",
|
||||||
|
"async": "3.2.2",
|
||||||
|
"glob": "7.2.3",
|
||||||
|
"mkdirp": "1.0.4",
|
||||||
|
"rollup-plugin-brotli": "3.1.0",
|
||||||
|
"strip-css-comments": "5.0.0",
|
||||||
|
"transform-ast": "2.4.4",
|
||||||
|
"typescript": "4.9.3",
|
||||||
|
"vite": "3.2.5",
|
||||||
|
"vite-plugin-checker": "0.5.1",
|
||||||
|
"workbox-build": "6.5.4",
|
||||||
|
"workbox-core": "6.5.4",
|
||||||
|
"workbox-precaching": "6.5.4"
|
||||||
|
},
|
||||||
|
"hash": "4fbd84d097de8f423b32ad784ed7600eba86a880677dae141a768b1c60913627"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@vaadin/bundles": "$@vaadin/bundles",
|
||||||
|
"@vaadin/accordion": "$@vaadin/accordion",
|
||||||
|
"@vaadin/app-layout": "$@vaadin/app-layout",
|
||||||
|
"@vaadin/avatar": "$@vaadin/avatar",
|
||||||
|
"@vaadin/avatar-group": "$@vaadin/avatar-group",
|
||||||
|
"@vaadin/button": "$@vaadin/button",
|
||||||
|
"@vaadin/checkbox": "$@vaadin/checkbox",
|
||||||
|
"@vaadin/checkbox-group": "$@vaadin/checkbox-group",
|
||||||
|
"@vaadin/combo-box": "$@vaadin/combo-box",
|
||||||
|
"@vaadin/component-base": "$@vaadin/component-base",
|
||||||
|
"@vaadin/confirm-dialog": "$@vaadin/confirm-dialog",
|
||||||
|
"@vaadin/context-menu": "$@vaadin/context-menu",
|
||||||
|
"@vaadin/custom-field": "$@vaadin/custom-field",
|
||||||
|
"@vaadin/date-picker": "$@vaadin/date-picker",
|
||||||
|
"@vaadin/date-time-picker": "$@vaadin/date-time-picker",
|
||||||
|
"@vaadin/details": "$@vaadin/details",
|
||||||
|
"@vaadin/dialog": "$@vaadin/dialog",
|
||||||
|
"@vaadin/email-field": "$@vaadin/email-field",
|
||||||
|
"@vaadin/field-base": "$@vaadin/field-base",
|
||||||
|
"@vaadin/field-highlighter": "$@vaadin/field-highlighter",
|
||||||
|
"@vaadin/form-layout": "$@vaadin/form-layout",
|
||||||
|
"@vaadin/grid": "$@vaadin/grid",
|
||||||
|
"@vaadin/horizontal-layout": "$@vaadin/horizontal-layout",
|
||||||
|
"@vaadin/icon": "$@vaadin/icon",
|
||||||
|
"@vaadin/icons": "$@vaadin/icons",
|
||||||
|
"@vaadin/input-container": "$@vaadin/input-container",
|
||||||
|
"@vaadin/integer-field": "$@vaadin/integer-field",
|
||||||
|
"@polymer/iron-icon": "$@polymer/iron-icon",
|
||||||
|
"@polymer/iron-iconset-svg": "$@polymer/iron-iconset-svg",
|
||||||
|
"@polymer/iron-list": "$@polymer/iron-list",
|
||||||
|
"@polymer/iron-meta": "$@polymer/iron-meta",
|
||||||
|
"@polymer/iron-resizable-behavior": "$@polymer/iron-resizable-behavior",
|
||||||
|
"@vaadin/item": "$@vaadin/item",
|
||||||
|
"@vaadin/list-box": "$@vaadin/list-box",
|
||||||
|
"@vaadin/lit-renderer": "$@vaadin/lit-renderer",
|
||||||
|
"@vaadin/login": "$@vaadin/login",
|
||||||
|
"@vaadin/menu-bar": "$@vaadin/menu-bar",
|
||||||
|
"@vaadin/message-input": "$@vaadin/message-input",
|
||||||
|
"@vaadin/message-list": "$@vaadin/message-list",
|
||||||
|
"@vaadin/multi-select-combo-box": "$@vaadin/multi-select-combo-box",
|
||||||
|
"@vaadin/notification": "$@vaadin/notification",
|
||||||
|
"@vaadin/number-field": "$@vaadin/number-field",
|
||||||
|
"@vaadin/password-field": "$@vaadin/password-field",
|
||||||
|
"@vaadin/polymer-legacy-adapter": "$@vaadin/polymer-legacy-adapter",
|
||||||
|
"@vaadin/progress-bar": "$@vaadin/progress-bar",
|
||||||
|
"@vaadin/radio-group": "$@vaadin/radio-group",
|
||||||
|
"@vaadin/scroller": "$@vaadin/scroller",
|
||||||
|
"@vaadin/select": "$@vaadin/select",
|
||||||
|
"@vaadin/split-layout": "$@vaadin/split-layout",
|
||||||
|
"@vaadin/tabs": "$@vaadin/tabs",
|
||||||
|
"@vaadin/tabsheet": "$@vaadin/tabsheet",
|
||||||
|
"@vaadin/text-area": "$@vaadin/text-area",
|
||||||
|
"@vaadin/text-field": "$@vaadin/text-field",
|
||||||
|
"@vaadin/time-picker": "$@vaadin/time-picker",
|
||||||
|
"@vaadin/tooltip": "$@vaadin/tooltip",
|
||||||
|
"@vaadin/upload": "$@vaadin/upload",
|
||||||
|
"@vaadin/vaadin-accordion": "$@vaadin/vaadin-accordion",
|
||||||
|
"@vaadin/vaadin-app-layout": "$@vaadin/vaadin-app-layout",
|
||||||
|
"@vaadin/vaadin-avatar": "$@vaadin/vaadin-avatar",
|
||||||
|
"@vaadin/vaadin-button": "$@vaadin/vaadin-button",
|
||||||
|
"@vaadin/vaadin-checkbox": "$@vaadin/vaadin-checkbox",
|
||||||
|
"@vaadin/vaadin-combo-box": "$@vaadin/vaadin-combo-box",
|
||||||
|
"@vaadin/vaadin-confirm-dialog": "$@vaadin/vaadin-confirm-dialog",
|
||||||
|
"@vaadin/vaadin-context-menu": "$@vaadin/vaadin-context-menu",
|
||||||
|
"@vaadin/vaadin-custom-field": "$@vaadin/vaadin-custom-field",
|
||||||
|
"@vaadin/vaadin-date-picker": "$@vaadin/vaadin-date-picker",
|
||||||
|
"@vaadin/vaadin-date-time-picker": "$@vaadin/vaadin-date-time-picker",
|
||||||
|
"@vaadin/vaadin-details": "$@vaadin/vaadin-details",
|
||||||
|
"@vaadin/vaadin-development-mode-detector": "$@vaadin/vaadin-development-mode-detector",
|
||||||
|
"@vaadin/vaadin-dialog": "$@vaadin/vaadin-dialog",
|
||||||
|
"@vaadin/vaadin-form-layout": "$@vaadin/vaadin-form-layout",
|
||||||
|
"@vaadin/vaadin-grid": "$@vaadin/vaadin-grid",
|
||||||
|
"@vaadin/vaadin-icon": "$@vaadin/vaadin-icon",
|
||||||
|
"@vaadin/vaadin-icons": "$@vaadin/vaadin-icons",
|
||||||
|
"@vaadin/vaadin-item": "$@vaadin/vaadin-item",
|
||||||
|
"@vaadin/vaadin-list-box": "$@vaadin/vaadin-list-box",
|
||||||
|
"@vaadin/vaadin-list-mixin": "$@vaadin/vaadin-list-mixin",
|
||||||
|
"@vaadin/vaadin-login": "$@vaadin/vaadin-login",
|
||||||
|
"@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles",
|
||||||
|
"@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles",
|
||||||
|
"@vaadin/vaadin-menu-bar": "$@vaadin/vaadin-menu-bar",
|
||||||
|
"@vaadin/vaadin-messages": "$@vaadin/vaadin-messages",
|
||||||
|
"@vaadin/vaadin-notification": "$@vaadin/vaadin-notification",
|
||||||
|
"@vaadin/vaadin-ordered-layout": "$@vaadin/vaadin-ordered-layout",
|
||||||
|
"@vaadin/vaadin-overlay": "$@vaadin/vaadin-overlay",
|
||||||
|
"@vaadin/vaadin-progress-bar": "$@vaadin/vaadin-progress-bar",
|
||||||
|
"@vaadin/vaadin-radio-button": "$@vaadin/vaadin-radio-button",
|
||||||
|
"@vaadin/router": "$@vaadin/router",
|
||||||
|
"@vaadin/vaadin-select": "$@vaadin/vaadin-select",
|
||||||
|
"@vaadin/vaadin-split-layout": "$@vaadin/vaadin-split-layout",
|
||||||
|
"@vaadin/vaadin-tabs": "$@vaadin/vaadin-tabs",
|
||||||
|
"@vaadin/vaadin-template-renderer": "$@vaadin/vaadin-template-renderer",
|
||||||
|
"@vaadin/vaadin-text-field": "$@vaadin/vaadin-text-field",
|
||||||
|
"@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin",
|
||||||
|
"@vaadin/vaadin-time-picker": "$@vaadin/vaadin-time-picker",
|
||||||
|
"@vaadin/vaadin-upload": "$@vaadin/vaadin-upload",
|
||||||
|
"@vaadin/vaadin-usage-statistics": "$@vaadin/vaadin-usage-statistics",
|
||||||
|
"@vaadin/vaadin-virtual-list": "$@vaadin/vaadin-virtual-list",
|
||||||
|
"@vaadin/vertical-layout": "$@vaadin/vertical-layout",
|
||||||
|
"@vaadin/virtual-list": "$@vaadin/virtual-list",
|
||||||
|
"@vaadin/common-frontend": "$@vaadin/common-frontend",
|
||||||
|
"construct-style-sheets-polyfill": "$construct-style-sheets-polyfill",
|
||||||
|
"lit": "$lit",
|
||||||
|
"@polymer/polymer": "$@polymer/polymer",
|
||||||
|
"date-fns": "$date-fns"
|
||||||
|
}
|
||||||
|
}
|
96
pom.xml
Normal file
96
pom.xml
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.7.8</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>edu.janmod</groupId>
|
||||||
|
<artifactId>SvarTalk</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>SvarTalk</name>
|
||||||
|
<description>Projekt komunikatora</description>
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<vaadin.version>23.3.5</vaadin.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.vaadin</groupId>
|
||||||
|
<artifactId>vaadin-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.vaadin</groupId>
|
||||||
|
<artifactId>vaadin-bom</artifactId>
|
||||||
|
<version>${vaadin.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>production</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.vaadin</groupId>
|
||||||
|
<artifactId>vaadin-maven-plugin</artifactId>
|
||||||
|
<version>${vaadin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>frontend</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-frontend</goal>
|
||||||
|
<goal>build-frontend</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<productionMode>true</productionMode>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
</project>
|
78
src/main/java/edu/janmod/SvarTalk/MainView.java
Normal file
78
src/main/java/edu/janmod/SvarTalk/MainView.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package edu.janmod.SvarTalk;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.Component;
|
||||||
|
import com.vaadin.flow.component.Key;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
|
import com.vaadin.flow.component.grid.Grid;
|
||||||
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
|
import com.vaadin.flow.component.textfield.EmailField;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.component.html.H1;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.data.binder.Binder;
|
||||||
|
import com.vaadin.flow.data.binder.ValidationException;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
|
||||||
|
@Route("")
|
||||||
|
public class MainView extends VerticalLayout {
|
||||||
|
|
||||||
|
private PersonRepository repository;
|
||||||
|
private TextField firstName = new TextField("Imię");
|
||||||
|
private TextField lastName = new TextField("Nazwisko");
|
||||||
|
private EmailField email = new EmailField("Email");
|
||||||
|
private Grid<Person> grid = new Grid<>(Person.class);
|
||||||
|
private Binder<Person> binder = new Binder<>(Person.class);
|
||||||
|
|
||||||
|
public MainView(PersonRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
|
||||||
|
grid.setColumns("firstName", "lastName", "email");
|
||||||
|
add(getForm(), grid);
|
||||||
|
refreshGrid();
|
||||||
|
|
||||||
|
|
||||||
|
/*var button = new Button("Przycisk");
|
||||||
|
var textField = new TextField();
|
||||||
|
|
||||||
|
add(new HorizontalLayout(textField, button));
|
||||||
|
|
||||||
|
button.addClickListener(e -> {
|
||||||
|
add(new Paragraph("Hello, " + textField.getValue()));
|
||||||
|
textField.clear();
|
||||||
|
});*/
|
||||||
|
/* add(new H1("Hello!")); */
|
||||||
|
}
|
||||||
|
|
||||||
|
private Component getForm() {
|
||||||
|
var layout = new HorizontalLayout();
|
||||||
|
layout.setAlignItems(Alignment.BASELINE);
|
||||||
|
|
||||||
|
var addButton = new Button("Add");
|
||||||
|
addButton.addClickShortcut(Key.ENTER);
|
||||||
|
addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
|
layout.add(firstName, lastName, email, addButton);
|
||||||
|
|
||||||
|
binder.bindInstanceFields(this);
|
||||||
|
|
||||||
|
addButton.addClickListener(click -> {
|
||||||
|
try{
|
||||||
|
var person = new Person();
|
||||||
|
binder.writeBean(person);
|
||||||
|
repository.save(person);
|
||||||
|
binder.readBean(new Person());
|
||||||
|
refreshGrid();
|
||||||
|
|
||||||
|
}catch(ValidationException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshGrid() {
|
||||||
|
grid.setItems(repository.findAll());
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/edu/janmod/SvarTalk/Person.java
Normal file
41
src/main/java/edu/janmod/SvarTalk/Person.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package edu.janmod.SvarTalk;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Person {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
}
|
7
src/main/java/edu/janmod/SvarTalk/PersonRepository.java
Normal file
7
src/main/java/edu/janmod/SvarTalk/PersonRepository.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package edu.janmod.SvarTalk;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface PersonRepository extends JpaRepository<Person, Long> {
|
||||||
|
|
||||||
|
}
|
13
src/main/java/edu/janmod/SvarTalk/SvarTalkApplication.java
Normal file
13
src/main/java/edu/janmod/SvarTalk/SvarTalkApplication.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package edu.janmod.SvarTalk;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class SvarTalkApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SvarTalkApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1
src/main/resources/application.properties
Normal file
1
src/main/resources/application.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
package edu.janmod.SvarTalk;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class SvarTalkApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
tsconfig.json
Normal file
37
tsconfig.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// This TypeScript configuration file is generated by vaadin-maven-plugin.
|
||||||
|
// This is needed for TypeScript compiler to compile your TypeScript code in the project.
|
||||||
|
// It is recommended to commit this file to the VCS.
|
||||||
|
// You might want to change the configurations to fit your preferences
|
||||||
|
// For more information about the configurations, please refer to http://www.typescriptlang.org/docs/handbook/tsconfig-json.html
|
||||||
|
{
|
||||||
|
"flow_version": "23.3.0.1",
|
||||||
|
"compilerOptions": {
|
||||||
|
"sourceMap": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"inlineSources": true,
|
||||||
|
"module": "esNext",
|
||||||
|
"target": "es2020",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"baseUrl": "frontend",
|
||||||
|
"paths": {
|
||||||
|
"@vaadin/flow-frontend": ["generated/jar-resources"],
|
||||||
|
"@vaadin/flow-frontend/*": ["generated/jar-resources/*"],
|
||||||
|
"Frontend/*": ["*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"frontend/**/*",
|
||||||
|
"types.d.ts"
|
||||||
|
],
|
||||||
|
"exclude": []
|
||||||
|
}
|
10
types.d.ts
vendored
Normal file
10
types.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// This TypeScript modules definition file is generated by vaadin-maven-plugin.
|
||||||
|
// You can not directly import your different static files into TypeScript,
|
||||||
|
// This is needed for TypeScript compiler to declare and export as a TypeScript module.
|
||||||
|
// It is recommended to commit this file to the VCS.
|
||||||
|
// You might want to change the configurations to fit your preferences
|
||||||
|
declare module '*.css' {
|
||||||
|
import { CSSResultGroup } from 'lit';
|
||||||
|
const content: CSSResultGroup;
|
||||||
|
export default content;
|
||||||
|
}
|
9
vite.config.ts
Normal file
9
vite.config.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { UserConfigFn } from 'vite';
|
||||||
|
import { overrideVaadinConfig } from './vite.generated';
|
||||||
|
|
||||||
|
const customConfig: UserConfigFn = (env) => ({
|
||||||
|
// Here you can add custom Vite parameters
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
});
|
||||||
|
|
||||||
|
export default overrideVaadinConfig(customConfig);
|
639
vite.generated.ts
Normal file
639
vite.generated.ts
Normal file
@ -0,0 +1,639 @@
|
|||||||
|
/**
|
||||||
|
* NOTICE: this is an auto-generated file
|
||||||
|
*
|
||||||
|
* This file has been generated by the `flow:prepare-frontend` maven goal.
|
||||||
|
* This file will be overwritten on every run. Any custom changes should be made to vite.config.ts
|
||||||
|
*/
|
||||||
|
import path from 'path';
|
||||||
|
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
||||||
|
import * as net from 'net';
|
||||||
|
|
||||||
|
import { processThemeResources } from './target/plugins/application-theme-plugin/theme-handle.js';
|
||||||
|
import { rewriteCssUrls } from './target/plugins/theme-loader/theme-loader-utils.js';
|
||||||
|
import settings from './target/vaadin-dev-server-settings.json';
|
||||||
|
import { defineConfig, mergeConfig, PluginOption, ResolvedConfig, UserConfigFn, OutputOptions, AssetInfo, ChunkInfo } from 'vite';
|
||||||
|
import { getManifest } from 'workbox-build';
|
||||||
|
|
||||||
|
import * as rollup from 'rollup';
|
||||||
|
import brotli from 'rollup-plugin-brotli';
|
||||||
|
import replace from '@rollup/plugin-replace';
|
||||||
|
import checker from 'vite-plugin-checker';
|
||||||
|
import postcssLit from './target/plugins/rollup-plugin-postcss-lit-custom/rollup-plugin-postcss-lit.js';
|
||||||
|
|
||||||
|
const appShellUrl = '.';
|
||||||
|
|
||||||
|
const frontendFolder = path.resolve(__dirname, settings.frontendFolder);
|
||||||
|
const themeFolder = path.resolve(frontendFolder, settings.themeFolder);
|
||||||
|
const statsFolder = path.resolve(__dirname, settings.statsOutput);
|
||||||
|
const frontendBundleFolder = path.resolve(__dirname, settings.frontendBundleOutput);
|
||||||
|
const jarResourcesFolder = path.resolve(__dirname, settings.jarResourcesFolder);
|
||||||
|
const generatedFlowImportsFolder = path.resolve(__dirname, settings.generatedFlowImportsFolder);
|
||||||
|
const themeResourceFolder = path.resolve(__dirname, settings.themeResourceFolder);
|
||||||
|
|
||||||
|
const statsFile = path.resolve(statsFolder, 'stats.json');
|
||||||
|
|
||||||
|
const projectStaticAssetsFolders = [
|
||||||
|
path.resolve(__dirname, 'src', 'main', 'resources', 'META-INF', 'resources'),
|
||||||
|
path.resolve(__dirname, 'src', 'main', 'resources', 'static'),
|
||||||
|
frontendFolder
|
||||||
|
];
|
||||||
|
|
||||||
|
// Folders in the project which can contain application themes
|
||||||
|
const themeProjectFolders = projectStaticAssetsFolders.map((folder) => path.resolve(folder, settings.themeFolder));
|
||||||
|
|
||||||
|
const themeOptions = {
|
||||||
|
devMode: false,
|
||||||
|
// The following matches folder 'frontend/generated/themes/'
|
||||||
|
// (not 'frontend/themes') for theme in JAR that is copied there
|
||||||
|
themeResourceFolder: path.resolve(themeResourceFolder, settings.themeFolder),
|
||||||
|
themeProjectFolders: themeProjectFolders,
|
||||||
|
projectStaticAssetsOutputFolder: path.resolve(__dirname, settings.staticOutput),
|
||||||
|
frontendGeneratedFolder: path.resolve(frontendFolder, settings.generatedFolder)
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasExportedWebComponents = existsSync(path.resolve(frontendFolder, 'web-component.html'));
|
||||||
|
|
||||||
|
// Block debug and trace logs.
|
||||||
|
console.trace = () => {};
|
||||||
|
console.debug = () => {};
|
||||||
|
|
||||||
|
function injectManifestToSWPlugin(): rollup.Plugin {
|
||||||
|
const rewriteManifestIndexHtmlUrl = (manifest) => {
|
||||||
|
const indexEntry = manifest.find((entry) => entry.url === 'index.html');
|
||||||
|
if (indexEntry) {
|
||||||
|
indexEntry.url = appShellUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { manifest, warnings: [] };
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'vaadin:inject-manifest-to-sw',
|
||||||
|
async transform(code, id) {
|
||||||
|
if (/sw\.(ts|js)$/.test(id)) {
|
||||||
|
const { manifestEntries } = await getManifest({
|
||||||
|
globDirectory: frontendBundleFolder,
|
||||||
|
globPatterns: ['**/*'],
|
||||||
|
globIgnores: ['**/*.br'],
|
||||||
|
manifestTransforms: [rewriteManifestIndexHtmlUrl],
|
||||||
|
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024, // 100mb,
|
||||||
|
});
|
||||||
|
|
||||||
|
return code.replace('self.__WB_MANIFEST', JSON.stringify(manifestEntries));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSWPlugin(opts): PluginOption {
|
||||||
|
let config: ResolvedConfig;
|
||||||
|
const devMode = opts.devMode;
|
||||||
|
|
||||||
|
const swObj = {}
|
||||||
|
|
||||||
|
async function build(action: 'generate' | 'write', additionalPlugins: rollup.Plugin[] = []) {
|
||||||
|
const includedPluginNames = [
|
||||||
|
'alias',
|
||||||
|
'vite:resolve',
|
||||||
|
'vite:esbuild',
|
||||||
|
'rollup-plugin-dynamic-import-variables',
|
||||||
|
'vite:esbuild-transpile',
|
||||||
|
'vite:terser',
|
||||||
|
]
|
||||||
|
const plugins: rollup.Plugin[] = config.plugins.filter((p) => {
|
||||||
|
return includedPluginNames.includes(p.name)
|
||||||
|
});
|
||||||
|
plugins.push(
|
||||||
|
replace({
|
||||||
|
values: {
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(config.mode),
|
||||||
|
...config.define,
|
||||||
|
},
|
||||||
|
preventAssignment: true
|
||||||
|
})
|
||||||
|
);
|
||||||
|
if (additionalPlugins) {
|
||||||
|
plugins.push(...additionalPlugins);
|
||||||
|
}
|
||||||
|
const bundle = await rollup.rollup({
|
||||||
|
input: path.resolve(settings.clientServiceWorkerSource),
|
||||||
|
plugins
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await bundle[action]({
|
||||||
|
file: path.resolve(frontendBundleFolder, 'sw.js'),
|
||||||
|
format: 'es',
|
||||||
|
exports: 'none',
|
||||||
|
sourcemap: config.command === 'serve' || config.build.sourcemap,
|
||||||
|
inlineDynamicImports: true,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await bundle.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'vaadin:build-sw',
|
||||||
|
enforce: 'post',
|
||||||
|
async configResolved(resolvedConfig) {
|
||||||
|
config = resolvedConfig;
|
||||||
|
},
|
||||||
|
async buildStart() {
|
||||||
|
if (devMode) {
|
||||||
|
const { output } = await build('generate');
|
||||||
|
swObj.code = output[0].code;
|
||||||
|
swObj.map = output[0].map;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async load(id) {
|
||||||
|
if (id.endsWith('sw.js')) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async transform(_code, id) {
|
||||||
|
if (id.endsWith('sw.js')) {
|
||||||
|
return swObj;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async closeBundle() {
|
||||||
|
await build('write', [
|
||||||
|
injectManifestToSWPlugin(),
|
||||||
|
brotli(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function statsExtracterPlugin(): PluginOption {
|
||||||
|
return {
|
||||||
|
name: 'vaadin:stats',
|
||||||
|
enforce: 'post',
|
||||||
|
async writeBundle(options: OutputOptions, bundle: { [fileName: string]: AssetInfo | ChunkInfo }) {
|
||||||
|
const modules = Object.values(bundle).flatMap((b) => (b.modules ? Object.keys(b.modules) : []));
|
||||||
|
const nodeModulesFolders = modules.filter((id) => id.includes('node_modules'));
|
||||||
|
const npmModules = nodeModulesFolders
|
||||||
|
.map((id) => id.replace(/.*node_modules./, ''))
|
||||||
|
.map((id) => {
|
||||||
|
const parts = id.split('/');
|
||||||
|
if (id.startsWith('@')) {
|
||||||
|
return parts[0] + '/' + parts[1];
|
||||||
|
} else {
|
||||||
|
return parts[0];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sort()
|
||||||
|
.filter((value, index, self) => self.indexOf(value) === index);
|
||||||
|
|
||||||
|
mkdirSync(path.dirname(statsFile), { recursive: true });
|
||||||
|
writeFileSync(statsFile, JSON.stringify({ npmModules }, null, 1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function vaadinBundlesPlugin(): PluginOption {
|
||||||
|
type ExportInfo =
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
namespace?: string;
|
||||||
|
source: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ExposeInfo = {
|
||||||
|
exports: ExportInfo[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type PackageInfo = {
|
||||||
|
version: string;
|
||||||
|
exposes: Record<string, ExposeInfo>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type BundleJson = {
|
||||||
|
packages: Record<string, PackageInfo>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const disabledMessage = 'Vaadin component dependency bundles are disabled.';
|
||||||
|
|
||||||
|
const modulesDirectory = path.resolve(__dirname, 'node_modules').replace(/\\/g, '/');
|
||||||
|
|
||||||
|
let vaadinBundleJson: BundleJson;
|
||||||
|
|
||||||
|
function parseModuleId(id: string): { packageName: string; modulePath: string } {
|
||||||
|
const [scope, scopedPackageName] = id.split('/', 3);
|
||||||
|
const packageName = scope.startsWith('@') ? `${scope}/${scopedPackageName}` : scope;
|
||||||
|
const modulePath = `.${id.substring(packageName.length)}`;
|
||||||
|
return {
|
||||||
|
packageName,
|
||||||
|
modulePath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExports(id: string): string[] | undefined {
|
||||||
|
const { packageName, modulePath } = parseModuleId(id);
|
||||||
|
const packageInfo = vaadinBundleJson.packages[packageName];
|
||||||
|
|
||||||
|
if (!packageInfo) return;
|
||||||
|
|
||||||
|
const exposeInfo: ExposeInfo = packageInfo.exposes[modulePath];
|
||||||
|
if (!exposeInfo) return;
|
||||||
|
|
||||||
|
const exportsSet = new Set<string>();
|
||||||
|
for (const e of exposeInfo.exports) {
|
||||||
|
if (typeof e === 'string') {
|
||||||
|
exportsSet.add(e);
|
||||||
|
} else {
|
||||||
|
const { namespace, source } = e;
|
||||||
|
if (namespace) {
|
||||||
|
exportsSet.add(namespace);
|
||||||
|
} else {
|
||||||
|
const sourceExports = getExports(source);
|
||||||
|
if (sourceExports) {
|
||||||
|
sourceExports.forEach((e) => exportsSet.add(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.from(exportsSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExportBinding(binding: string) {
|
||||||
|
return binding === 'default' ? '_default as default' : binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getImportAssigment(binding: string) {
|
||||||
|
return binding === 'default' ? 'default: _default' : binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'vaadin:bundles',
|
||||||
|
enforce: 'pre',
|
||||||
|
apply(config, { command }) {
|
||||||
|
if (command !== 'serve') return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const vaadinBundleJsonPath = require.resolve('@vaadin/bundles/vaadin-bundle.json');
|
||||||
|
vaadinBundleJson = JSON.parse(readFileSync(vaadinBundleJsonPath, { encoding: 'utf8' }));
|
||||||
|
} catch (e: unknown) {
|
||||||
|
if (typeof e === 'object' && (e as { code: string }).code === 'MODULE_NOT_FOUND') {
|
||||||
|
vaadinBundleJson = { packages: {} };
|
||||||
|
console.info(`@vaadin/bundles npm package is not found, ${disabledMessage}`);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionMismatches: Array<{ name: string; bundledVersion: string; installedVersion: string }> = [];
|
||||||
|
for (const [name, packageInfo] of Object.entries(vaadinBundleJson.packages)) {
|
||||||
|
let installedVersion: string | undefined = undefined;
|
||||||
|
try {
|
||||||
|
const { version: bundledVersion } = packageInfo;
|
||||||
|
const installedPackageJsonFile = path.resolve(modulesDirectory, name, 'package.json');
|
||||||
|
const packageJson = JSON.parse(readFileSync(installedPackageJsonFile, { encoding: 'utf8' }));
|
||||||
|
installedVersion = packageJson.version;
|
||||||
|
if (installedVersion && installedVersion !== bundledVersion) {
|
||||||
|
versionMismatches.push({
|
||||||
|
name,
|
||||||
|
bundledVersion,
|
||||||
|
installedVersion
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// ignore package not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (versionMismatches.length) {
|
||||||
|
console.info(`@vaadin/bundles has version mismatches with installed packages, ${disabledMessage}`);
|
||||||
|
console.info(`Packages with version mismatches: ${JSON.stringify(versionMismatches, undefined, 2)}`);
|
||||||
|
vaadinBundleJson = { packages: {} };
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
async config(config) {
|
||||||
|
return mergeConfig(
|
||||||
|
{
|
||||||
|
optimizeDeps: {
|
||||||
|
exclude: [
|
||||||
|
// Vaadin bundle
|
||||||
|
'@vaadin/bundles',
|
||||||
|
...Object.keys(vaadinBundleJson.packages)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
config
|
||||||
|
);
|
||||||
|
},
|
||||||
|
load(rawId) {
|
||||||
|
const [path, params] = rawId.split('?');
|
||||||
|
if (!path.startsWith(modulesDirectory)) return;
|
||||||
|
|
||||||
|
const id = path.substring(modulesDirectory.length + 1);
|
||||||
|
const bindings = getExports(id);
|
||||||
|
if (bindings === undefined) return;
|
||||||
|
|
||||||
|
const cacheSuffix = params ? `?${params}` : '';
|
||||||
|
const bundlePath = `@vaadin/bundles/vaadin.js${cacheSuffix}`;
|
||||||
|
|
||||||
|
return `import { init as VaadinBundleInit, get as VaadinBundleGet } from '${bundlePath}';
|
||||||
|
await VaadinBundleInit('default');
|
||||||
|
const { ${bindings.map(getImportAssigment).join(', ')} } = (await VaadinBundleGet('./node_modules/${id}'))();
|
||||||
|
export { ${bindings.map(getExportBinding).join(', ')} };`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function themePlugin(opts): PluginOption {
|
||||||
|
const fullThemeOptions = {...themeOptions, devMode: opts.devMode };
|
||||||
|
return {
|
||||||
|
name: 'vaadin:theme',
|
||||||
|
config() {
|
||||||
|
processThemeResources(fullThemeOptions, console);
|
||||||
|
},
|
||||||
|
configureServer(server) {
|
||||||
|
function handleThemeFileCreateDelete(themeFile, stats) {
|
||||||
|
if (themeFile.startsWith(themeFolder)) {
|
||||||
|
const changed = path.relative(themeFolder, themeFile)
|
||||||
|
console.debug('Theme file ' + (!!stats ? 'created' : 'deleted'), changed);
|
||||||
|
processThemeResources(fullThemeOptions, console);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.watcher.on('add', handleThemeFileCreateDelete);
|
||||||
|
server.watcher.on('unlink', handleThemeFileCreateDelete);
|
||||||
|
},
|
||||||
|
handleHotUpdate(context) {
|
||||||
|
const contextPath = path.resolve(context.file);
|
||||||
|
const themePath = path.resolve(themeFolder);
|
||||||
|
if (contextPath.startsWith(themePath)) {
|
||||||
|
const changed = path.relative(themePath, contextPath);
|
||||||
|
|
||||||
|
console.debug('Theme file changed', changed);
|
||||||
|
|
||||||
|
if (changed.startsWith(settings.themeName)) {
|
||||||
|
processThemeResources(fullThemeOptions, console);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async resolveId(id, importer) {
|
||||||
|
// force theme generation if generated theme sources does not yet exist
|
||||||
|
// this may happen for example during Java hot reload when updating
|
||||||
|
// @Theme annotation value
|
||||||
|
if (path.resolve(themeOptions.frontendGeneratedFolder, "theme.js") === importer &&
|
||||||
|
!existsSync(path.resolve(themeOptions.frontendGeneratedFolder, id))) {
|
||||||
|
console.debug('Generate theme file ' + id + ' not existing. Processing theme resource');
|
||||||
|
processThemeResources(fullThemeOptions, console);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!id.startsWith(settings.themeFolder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const location of [themeResourceFolder, frontendFolder]) {
|
||||||
|
const result = await this.resolve(path.resolve(location, id));
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async transform(raw, id, options) {
|
||||||
|
// rewrite urls for the application theme css files
|
||||||
|
const [bareId, query] = id.split('?');
|
||||||
|
if (!bareId?.startsWith(themeFolder) || !bareId?.endsWith('.css')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [themeName] = bareId.substring(themeFolder.length + 1).split('/');
|
||||||
|
return rewriteCssUrls(raw, path.dirname(bareId), path.resolve(themeFolder, themeName), console, opts);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function lenientLitImportPlugin(): PluginOption {
|
||||||
|
return {
|
||||||
|
name: 'vaadin:lenient-lit-import',
|
||||||
|
async transform(code, id) {
|
||||||
|
const decoratorImports = [
|
||||||
|
/import (.*?) from (['"])(lit\/decorators)(['"])/,
|
||||||
|
/import (.*?) from (['"])(lit-element\/decorators)(['"])/
|
||||||
|
];
|
||||||
|
const directiveImports = [
|
||||||
|
/import (.*?) from (['"])(lit\/directives\/)([^\\.]*?)(['"])/,
|
||||||
|
/import (.*?) from (['"])(lit-html\/directives\/)([^\\.]*?)(['"])/
|
||||||
|
];
|
||||||
|
|
||||||
|
decoratorImports.forEach((decoratorImport) => {
|
||||||
|
let decoratorMatch;
|
||||||
|
while ((decoratorMatch = code.match(decoratorImport))) {
|
||||||
|
console.warn(
|
||||||
|
`Warning: the file ${id} imports from '${decoratorMatch[3]}' when it should import from '${decoratorMatch[3]}.js'`
|
||||||
|
);
|
||||||
|
code = code.replace(decoratorImport, 'import $1 from $2$3.js$4');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
directiveImports.forEach((directiveImport) => {
|
||||||
|
let directiveMatch;
|
||||||
|
while ((directiveMatch = code.match(directiveImport))) {
|
||||||
|
console.warn(
|
||||||
|
`Warning: the file ${id} imports from '${directiveMatch[3]}${directiveMatch[4]}' when it should import from '${directiveMatch[3]}${directiveMatch[4]}.js'`
|
||||||
|
);
|
||||||
|
code = code.replace(directiveImport, 'import $1 from $2$3$4.js$5');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function runWatchDog(watchDogPort, watchDogHost) {
|
||||||
|
const client = net.Socket();
|
||||||
|
client.setEncoding('utf8');
|
||||||
|
client.on('error', function (err) {
|
||||||
|
console.log('Watchdog connection error. Terminating vite process...', err);
|
||||||
|
client.destroy();
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
client.on('close', function () {
|
||||||
|
client.destroy();
|
||||||
|
runWatchDog(watchDogPort, watchDogHost);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.connect(watchDogPort, watchDogHost || 'localhost');
|
||||||
|
}
|
||||||
|
|
||||||
|
let spaMiddlewareForceRemoved = false;
|
||||||
|
|
||||||
|
const allowedFrontendFolders = [
|
||||||
|
frontendFolder,
|
||||||
|
path.resolve(generatedFlowImportsFolder), // Contains only generated-flow-imports
|
||||||
|
path.resolve(__dirname, 'node_modules')
|
||||||
|
];
|
||||||
|
|
||||||
|
function setHmrPortToServerPort(): PluginOption {
|
||||||
|
return {
|
||||||
|
name: 'set-hmr-port-to-server-port',
|
||||||
|
configResolved(config) {
|
||||||
|
if (config.server.strictPort && config.server.hmr !== false) {
|
||||||
|
if (config.server.hmr === true) config.server.hmr = {};
|
||||||
|
config.server.hmr = config.server.hmr || {};
|
||||||
|
config.server.hmr.clientPort = config.server.port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function showRecompileReason(): PluginOption {
|
||||||
|
return {
|
||||||
|
name: 'vaadin:why-you-compile',
|
||||||
|
handleHotUpdate(context) {
|
||||||
|
console.log('Recompiling because', context.file, 'changed');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const vaadinConfig: UserConfigFn = (env) => {
|
||||||
|
const devMode = env.mode === 'development';
|
||||||
|
|
||||||
|
if (devMode && process.env.watchDogPort) {
|
||||||
|
// Open a connection with the Java dev-mode handler in order to finish
|
||||||
|
// vite when it exits or crashes.
|
||||||
|
runWatchDog(process.env.watchDogPort, process.env.watchDogHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
root: frontendFolder,
|
||||||
|
base: '',
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@vaadin/flow-frontend': jarResourcesFolder,
|
||||||
|
Frontend: frontendFolder
|
||||||
|
},
|
||||||
|
preserveSymlinks: true
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
OFFLINE_PATH: settings.offlinePath,
|
||||||
|
VITE_ENABLED: 'true'
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
strictPort: true,
|
||||||
|
fs: {
|
||||||
|
allow: allowedFrontendFolders
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: frontendBundleFolder,
|
||||||
|
assetsDir: 'VAADIN/build',
|
||||||
|
rollupOptions: {
|
||||||
|
input: {
|
||||||
|
indexhtml: path.resolve(frontendFolder, 'index.html'),
|
||||||
|
|
||||||
|
...hasExportedWebComponents
|
||||||
|
? { webcomponenthtml: path.resolve(frontendFolder, 'web-component.html') }
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
entries: [
|
||||||
|
// Pre-scan entrypoints in Vite to avoid reloading on first open
|
||||||
|
'generated/vaadin.ts'
|
||||||
|
],
|
||||||
|
exclude: [
|
||||||
|
'@vaadin/router',
|
||||||
|
'@vaadin/vaadin-license-checker',
|
||||||
|
'@vaadin/vaadin-usage-statistics',
|
||||||
|
'workbox-core',
|
||||||
|
'workbox-precaching',
|
||||||
|
'workbox-routing',
|
||||||
|
'workbox-strategies'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
!devMode && brotli(),
|
||||||
|
devMode && vaadinBundlesPlugin(),
|
||||||
|
devMode && setHmrPortToServerPort(),
|
||||||
|
devMode && showRecompileReason(),
|
||||||
|
settings.offlineEnabled && buildSWPlugin({ devMode }),
|
||||||
|
!devMode && statsExtracterPlugin(),
|
||||||
|
themePlugin({devMode}),
|
||||||
|
lenientLitImportPlugin(),
|
||||||
|
postcssLit({
|
||||||
|
include: ['**/*.css', '**/*.css\?*'],
|
||||||
|
exclude: [
|
||||||
|
`${themeFolder}/**/*.css`,
|
||||||
|
`${themeFolder}/**/*.css\?*`,
|
||||||
|
`${themeResourceFolder}/**/*.css`,
|
||||||
|
`${themeResourceFolder}/**/*.css\?*`,
|
||||||
|
'**/*\?html-proxy*'
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: 'vaadin:force-remove-html-middleware',
|
||||||
|
transformIndexHtml: {
|
||||||
|
enforce: 'pre',
|
||||||
|
transform(_html, { server }) {
|
||||||
|
if (server && !spaMiddlewareForceRemoved) {
|
||||||
|
server.middlewares.stack = server.middlewares.stack.filter((mw) => {
|
||||||
|
const handleName = '' + mw.handle;
|
||||||
|
return !handleName.includes('viteHtmlFallbackMiddleware');
|
||||||
|
});
|
||||||
|
spaMiddlewareForceRemoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hasExportedWebComponents && {
|
||||||
|
name: 'vaadin:inject-entrypoints-to-web-component-html',
|
||||||
|
transformIndexHtml: {
|
||||||
|
enforce: 'pre',
|
||||||
|
transform(_html, { path, server }) {
|
||||||
|
if (path !== '/web-component.html') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: 'script',
|
||||||
|
attrs: { type: 'module', src: `/generated/vaadin-web-component.ts` },
|
||||||
|
injectTo: 'head'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vaadin:inject-entrypoints-to-index-html',
|
||||||
|
transformIndexHtml: {
|
||||||
|
enforce: 'pre',
|
||||||
|
transform(_html, { path, server }) {
|
||||||
|
if (path !== '/index.html') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scripts = [];
|
||||||
|
|
||||||
|
if (devMode) {
|
||||||
|
scripts.push({
|
||||||
|
tag: 'script',
|
||||||
|
attrs: { type: 'module', src: `/generated/vite-devmode.ts` },
|
||||||
|
injectTo: 'head'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
scripts.push({
|
||||||
|
tag: 'script',
|
||||||
|
attrs: { type: 'module', src: '/generated/vaadin.ts' },
|
||||||
|
injectTo: 'head'
|
||||||
|
});
|
||||||
|
return scripts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checker({
|
||||||
|
typescript: true
|
||||||
|
})
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const overrideVaadinConfig = (customConfig: UserConfigFn) => {
|
||||||
|
return defineConfig((env) => mergeConfig(vaadinConfig(env), customConfig(env)));
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user