hotfix-feat(dataset): implement file upload with validation and error handling
- Implemented file upload functionality for datasets using multipart requests. - Added file size and type validation using VineJS. - Added file name length validation. - Added file scan to remove infected files. - Implemented aggregated upload limit to prevent exceeding the server's capacity. - Added error handling for file upload failures, including temporary file cleanup. - Updated the `DatasetController` to handle file uploads, validation, and database transactions. - Updated the `bodyparser.ts` config to process the file upload manually. - Updated the `api.ts` routes to fetch the statistic data. - Updated the `main.ts` store to fetch the statistic data. - Updated the `Dashboard.vue` to display the submitters only for administrator role. - Updated the `CardBoxWidget.vue` to display the submitters. - Updated the `ServerError.vue` to use the LayoutGuest.vue. - Updated the `AuthController.ts` and `start/routes.ts` to handle the database connection errors. - Updated the `app/exceptions/handler.ts` to handle the database connection errors. - Updated the `package.json` to use the correct version of the `@adonisjs/bodyparser`.
This commit is contained in:
parent
a25f8bf6f7
commit
b93e46207f
15 changed files with 637 additions and 200 deletions
|
@ -5,7 +5,7 @@ import BackupCode from '#models/backup_code';
|
|||
// import InvalidCredentialException from 'App/Exceptions/InvalidCredentialException';
|
||||
import { authValidator } from '#validators/auth';
|
||||
import hash from '@adonisjs/core/services/hash';
|
||||
|
||||
import db from '@adonisjs/lucid/services/db';
|
||||
import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider';
|
||||
// import { Authenticator } from '@adonisjs/auth';
|
||||
// import { LoginState } from 'Contracts/enums';
|
||||
|
@ -29,6 +29,10 @@ export default class AuthController {
|
|||
const { email, password } = request.only(['email', 'password']);
|
||||
|
||||
try {
|
||||
|
||||
await db.connection().rawQuery('SELECT 1')
|
||||
|
||||
|
||||
// // attempt to verify credential and login user
|
||||
// await auth.use('web').attempt(email, plainPassword);
|
||||
|
||||
|
@ -51,6 +55,9 @@ export default class AuthController {
|
|||
|
||||
await auth.use('web').login(user);
|
||||
} catch (error) {
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
throw error
|
||||
}
|
||||
// if login fails, return vague form message and redirect back
|
||||
session.flash('message', 'Your username, email, or password is incorrect');
|
||||
return response.redirect().back();
|
||||
|
|
|
@ -40,12 +40,28 @@ import path from 'path';
|
|||
import { Exception } from '@adonisjs/core/exceptions';
|
||||
import { MultipartFile } from '@adonisjs/core/types/bodyparser';
|
||||
import * as crypto from 'crypto';
|
||||
// import MimeType from '#models/mime_type';
|
||||
import { pipeline } from 'node:stream/promises';
|
||||
import { createWriteStream } from 'node:fs';
|
||||
import type { Multipart } from '@adonisjs/bodyparser';
|
||||
import * as fs from 'fs';
|
||||
import { join, isAbsolute } from 'node:path';
|
||||
import type { BodyParserConfig } from '#models/types';
|
||||
import { createId } from '@paralleldrive/cuid2';
|
||||
import { tmpdir } from 'node:os';
|
||||
import config from '@adonisjs/core/services/config';
|
||||
|
||||
interface Dictionary {
|
||||
[index: string]: string;
|
||||
}
|
||||
import vine, { SimpleMessagesProvider, errors } from '@vinejs/vine';
|
||||
|
||||
export default class DatasetController {
|
||||
/**
|
||||
* Bodyparser config
|
||||
*/
|
||||
config: BodyParserConfig = config.get('bodyparser');
|
||||
|
||||
public async index({ auth, request, inertia }: HttpContext) {
|
||||
const user = (await User.find(auth.user?.id)) as User;
|
||||
const page = request.input('page', 1);
|
||||
|
@ -401,22 +417,140 @@ export default class DatasetController {
|
|||
return response.redirect().back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tmp path for storing the files temporarly
|
||||
*/
|
||||
private getTmpPath(config: BodyParserConfig['multipart']): string {
|
||||
if (typeof config.tmpFileName === 'function') {
|
||||
const tmpPath = config.tmpFileName();
|
||||
return isAbsolute(tmpPath) ? tmpPath : join(tmpdir(), tmpPath);
|
||||
}
|
||||
|
||||
return join(tmpdir(), createId());
|
||||
}
|
||||
/**
|
||||
* Returns config for a given type
|
||||
*/
|
||||
private getConfigFor<K extends keyof BodyParserConfig>(type: K): BodyParserConfig[K] {
|
||||
const config = this.config[type];
|
||||
return config;
|
||||
}
|
||||
|
||||
private parseBytesSize(size: string): number {
|
||||
const units = {
|
||||
kb: 1024,
|
||||
mb: 1024 * 1024,
|
||||
gb: 1024 * 1024 * 1024,
|
||||
tb: 1024 * 1024 * 1024 * 1024,
|
||||
};
|
||||
|
||||
const match = size.match(/^(\d+)(kb|mb|gb|tb)$/i); // Regex to match size format
|
||||
|
||||
if (!match) {
|
||||
throw new Error('Invalid size format');
|
||||
}
|
||||
|
||||
const [, value, unit] = match;
|
||||
return parseInt(value) * units[unit.toLowerCase()];
|
||||
}
|
||||
|
||||
public async store({ auth, request, response, session }: HttpContext) {
|
||||
// node ace make:validator CreateDataset
|
||||
// At the top of the store() method, declare an array to hold temporary file paths
|
||||
const uploadedTmpFiles: string[] = [];
|
||||
// Aggregated limit example (adjust as needed)
|
||||
const multipartConfig = this.getConfigFor('multipart');
|
||||
const aggregatedLimit = multipartConfig.limit ? this.parseBytesSize(multipartConfig.limit) : 100 * 1024 * 1024;
|
||||
// const aggregatedLimit = 200 * 1024 * 1024;
|
||||
let totalUploadedSize = 0;
|
||||
|
||||
// Helper function to format bytes as human-readable text
|
||||
function formatBytes(bytes: number): string {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
// const enabledExtensions = await this.getEnabledExtensions();
|
||||
const multipart: Multipart = request.multipart;
|
||||
|
||||
multipart.onFile('files', { deferValidations: true }, async (part) => {
|
||||
// Attach an individual file size accumulator if needed
|
||||
let fileUploadedSize = 0;
|
||||
|
||||
// Simply accumulate the size in on('data') without performing the expensive check per chunk
|
||||
part.on('data', (chunk) => {
|
||||
// reporter(chunk);
|
||||
// Increase counters using the chunk length
|
||||
fileUploadedSize += chunk.length;
|
||||
});
|
||||
|
||||
// After the file is completely read, update the global counter and check aggregated limit
|
||||
part.on('end', () => {
|
||||
totalUploadedSize += fileUploadedSize;
|
||||
part.file.size = fileUploadedSize;
|
||||
// Record the temporary file path
|
||||
if (part.file.tmpPath) {
|
||||
uploadedTmpFiles.push(part.file.tmpPath);
|
||||
}
|
||||
|
||||
if (totalUploadedSize > aggregatedLimit) {
|
||||
// Clean up all temporary files if aggregate limit is exceeded
|
||||
uploadedTmpFiles.forEach((tmpPath) => {
|
||||
try {
|
||||
fs.unlinkSync(tmpPath);
|
||||
} catch (cleanupError) {
|
||||
console.error('Error cleaning up temporary file:', cleanupError);
|
||||
}
|
||||
});
|
||||
const error = new errors.E_VALIDATION_ERROR({
|
||||
'upload error': `Aggregated upload limit of ${formatBytes(aggregatedLimit)} exceeded. The total size of files being uploaded would exceed the limit.`,
|
||||
});
|
||||
request.multipart.abort(error);
|
||||
}
|
||||
});
|
||||
|
||||
part.on('error', (error) => {
|
||||
// fileUploadError = error;
|
||||
request.multipart.abort(error);
|
||||
});
|
||||
|
||||
// await pipeline(part, createWriteStream(filePath));
|
||||
// return { filePath };
|
||||
// Process file with error handling
|
||||
try {
|
||||
// Extract extension from the client file name, e.g. "Tethys 5 - Ampflwang_dataset.zip"
|
||||
const ext = path.extname(part.file.clientName).replace('.', '');
|
||||
// Attach the extracted extension to the file object for later use
|
||||
part.file.extname = ext;
|
||||
|
||||
const tmpPath = this.getTmpPath(multipartConfig);
|
||||
(part.file as any).tmpPath = tmpPath;
|
||||
|
||||
const writeStream = createWriteStream(tmpPath);
|
||||
await pipeline(part, writeStream);
|
||||
} catch (error) {
|
||||
request.multipart.abort(new errors.E_VALIDATION_ERROR({ 'upload error': error.message }));
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// Step 2 - Validate request body against the schema
|
||||
// await request.validate({ schema: newDatasetSchema, messages: this.messages });
|
||||
// await request.validate(CreateDatasetValidator);
|
||||
await request.validateUsing(createDatasetValidator);
|
||||
// console.log({ payload });
|
||||
await multipart.process();
|
||||
// // Instead of letting an error abort the controller, check if any error occurred
|
||||
// if (fileUploadError) {
|
||||
// // Flash the error and return an inertia view that shows the error message.
|
||||
// session.flash('errors', { 'upload error': [fileUploadError.message] });
|
||||
// return response.redirect().back();
|
||||
// }
|
||||
} catch (error) {
|
||||
// Step 3 - Handle errors
|
||||
// return response.badRequest(error.messages);
|
||||
throw error;
|
||||
// This is where you'd expect to catch any errors.
|
||||
session.flash('errors', error.messages);
|
||||
return response.redirect().back();
|
||||
}
|
||||
|
||||
let trx: TransactionClientContract | null = null;
|
||||
try {
|
||||
await request.validateUsing(createDatasetValidator);
|
||||
trx = await db.transaction();
|
||||
const user = (await User.find(auth.user?.id)) as User;
|
||||
|
||||
|
@ -425,6 +559,14 @@ export default class DatasetController {
|
|||
await trx.commit();
|
||||
console.log('Dataset and related models created successfully');
|
||||
} catch (error) {
|
||||
// Clean up temporary files if validation or later steps fail
|
||||
uploadedTmpFiles.forEach((tmpPath) => {
|
||||
try {
|
||||
fs.unlinkSync(tmpPath);
|
||||
} catch (cleanupError) {
|
||||
console.error('Error cleaning up temporary file:', cleanupError);
|
||||
}
|
||||
});
|
||||
if (trx !== null) {
|
||||
await trx.rollback();
|
||||
}
|
||||
|
@ -437,8 +579,12 @@ export default class DatasetController {
|
|||
return response.redirect().toRoute('dataset.list');
|
||||
// return response.redirect().back();
|
||||
}
|
||||
|
||||
private async createDatasetAndAssociations(user: User, request: HttpContext['request'], trx: TransactionClientContract) {
|
||||
private async createDatasetAndAssociations(
|
||||
user: User,
|
||||
request: HttpContext['request'],
|
||||
trx: TransactionClientContract,
|
||||
// uploadedFiles: Array<MultipartFile>,
|
||||
) {
|
||||
// Create a new instance of the Dataset model:
|
||||
const dataset = new Dataset();
|
||||
dataset.type = request.input('type');
|
||||
|
@ -1275,7 +1421,7 @@ export default class DatasetController {
|
|||
// This should be an array of collection ids.
|
||||
const collections: number[] = request.input('collections', []);
|
||||
|
||||
// Synchronize the dataset collections using the transaction.
|
||||
// Synchronize the dataset collections using the transaction.
|
||||
await dataset.useTransaction(trx).related('collections').sync(collections);
|
||||
|
||||
// Commit the transaction.await trx.commit()
|
||||
|
|
43
app/exceptions/db_handler.ts
Normal file
43
app/exceptions/db_handler.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
// import { Exception } from '@adonisjs/core/exceptions'
|
||||
import { HttpContext, ExceptionHandler } from '@adonisjs/core/http';
|
||||
|
||||
export default class DbHandlerException extends ExceptionHandler {
|
||||
// constructor() {
|
||||
// super(Logger)
|
||||
// }
|
||||
|
||||
async handle(error: any, ctx: HttpContext) {
|
||||
// Check for AggregateError type
|
||||
if (error.type === 'AggregateError' && error.aggregateErrors) {
|
||||
const dbErrors = error.aggregateErrors.some((err: any) => err.code === 'ECONNREFUSED' && err.port === 5432);
|
||||
|
||||
if (dbErrors) {
|
||||
return ctx.response.status(503).json({
|
||||
status: 'error',
|
||||
message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
|
||||
details: {
|
||||
code: error.code,
|
||||
type: error.type,
|
||||
ports: error.aggregateErrors.map((err: any) => ({
|
||||
port: err.port,
|
||||
address: err.address,
|
||||
})),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Handle simple ECONNREFUSED errors
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
return ctx.response.status(503).json({
|
||||
status: 'error',
|
||||
message: 'Database connection failed. Please ensure PostgreSQL is running.',
|
||||
code: error.code,
|
||||
});
|
||||
}
|
||||
|
||||
return super.handle(error, ctx);
|
||||
}
|
||||
|
||||
static status = 500;
|
||||
}
|
|
@ -46,6 +46,7 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
// return view.render('./errors/server-error', { error });
|
||||
// },
|
||||
// };
|
||||
|
||||
protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
|
||||
'404': (error, { inertia }) => {
|
||||
return inertia.render('Errors/ServerError', {
|
||||
|
@ -58,9 +59,47 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
return inertia.render('Errors/ServerError', {
|
||||
error: error.message,
|
||||
code: error.status,
|
||||
});
|
||||
});
|
||||
},
|
||||
// '500': (error, { inertia }) => {
|
||||
// return inertia.render('Errors/postgres_error', {
|
||||
// status: 'error',
|
||||
// message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
|
||||
// details: {
|
||||
// code: error.code,
|
||||
// type: error.status,
|
||||
// ports: error.errors.map((err: any) => ({
|
||||
// port: err.port,
|
||||
// address: err.address,
|
||||
// })),
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
'500..599': (error, { inertia }) => {
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
const dbErrors = error.errors.some((err: any) => err.code === 'ECONNREFUSED' && err.port === 5432);
|
||||
|
||||
if (dbErrors) {
|
||||
return inertia.render('Errors/postgres_error', {
|
||||
status: 'error',
|
||||
message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
|
||||
details: {
|
||||
code: error.code,
|
||||
type: error.status,
|
||||
ports: error.errors.map((err: any) => ({
|
||||
port: err.port,
|
||||
address: err.address,
|
||||
})),
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return inertia.render('Errors/ServerError', {
|
||||
error: error.message,
|
||||
code: error.status,
|
||||
});
|
||||
}
|
||||
},
|
||||
'500..599': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
|
||||
};
|
||||
|
||||
// constructor() {
|
||||
|
@ -68,7 +107,7 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
// }
|
||||
|
||||
public async handle(error: any, ctx: HttpContext) {
|
||||
const { response, request, session } = ctx;
|
||||
const { response, request, session, inertia } = ctx;
|
||||
|
||||
/**
|
||||
* Handle failed authentication attempt
|
||||
|
@ -82,6 +121,47 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
// return response.redirect('/dashboard');
|
||||
// }
|
||||
|
||||
// Handle Axios errors
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
const dbErrors = error.errors.some((err: any) => err.code === 'ECONNREFUSED' && err.port === 5432);
|
||||
|
||||
if (dbErrors) {
|
||||
// return ctx.response.status(503).json({
|
||||
// status: 'error',
|
||||
// message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
|
||||
// details: {
|
||||
// code: error.code,
|
||||
// type: error.status,
|
||||
// ports: error.errors.map((err: any) => ({
|
||||
// port: err.port,
|
||||
// address: err.address,
|
||||
// })),
|
||||
// },
|
||||
// });
|
||||
// return inertia.render('Errors/postgres_error', {
|
||||
// status: 'error',
|
||||
// message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
|
||||
// details: {
|
||||
// code: error.code,
|
||||
// type: error.status,
|
||||
// ports: error.errors.map((err: any) => ({
|
||||
// port: err.port,
|
||||
// address: err.address,
|
||||
// })),
|
||||
// },
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
// Handle simple ECONNREFUSED errors
|
||||
// if (error.code === 'ECONNREFUSED') {
|
||||
// return ctx.response.status(503).json({
|
||||
// status: 'error',
|
||||
// message: 'Database connection failed. Please ensure PostgreSQL is running.',
|
||||
// code: error.code,
|
||||
// });
|
||||
// }
|
||||
|
||||
// https://github.com/inertiajs/inertia-laravel/issues/56
|
||||
// let test = response.getStatus(); //200
|
||||
// let header = request.header('X-Inertia'); // true
|
||||
|
@ -98,12 +178,21 @@ export default class HttpExceptionHandler extends ExceptionHandler {
|
|||
// ->toResponse($request)
|
||||
// ->setStatusCode($response->status());
|
||||
}
|
||||
|
||||
// Handle simple ECONNREFUSED errors
|
||||
// if (error.code === 'ECONNREFUSED') {
|
||||
// return ctx.response.status(503).json({
|
||||
// status: 'error',
|
||||
// message: 'Database connection failed. Please ensure PostgreSQL is running.',
|
||||
// code: error.code,
|
||||
// });
|
||||
// }
|
||||
// Dynamically change the error templates based on the absence of X-Inertia header
|
||||
// if (!ctx.request.header('X-Inertia')) {
|
||||
// this.statusPages = {
|
||||
// '401..403': (error, { view }) => view.render('./errors/unauthorized', { error }),
|
||||
// '404': (error, { view }) => view.render('./errors/not-found', { error }),
|
||||
// '500..599': (error, { view }) => view.render('./errors/server-error', { error }),
|
||||
// '401..403': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
|
||||
// '404': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
|
||||
// '500..599': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
|
||||
// };
|
||||
// }
|
||||
|
||||
|
|
57
app/models/types.ts
Normal file
57
app/models/types.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Qs module config
|
||||
*/
|
||||
type QueryStringConfig = {
|
||||
depth?: number
|
||||
allowPrototypes?: boolean
|
||||
plainObjects?: boolean
|
||||
parameterLimit?: number
|
||||
arrayLimit?: number
|
||||
ignoreQueryPrefix?: boolean
|
||||
delimiter?: RegExp | string
|
||||
allowDots?: boolean
|
||||
charset?: 'utf-8' | 'iso-8859-1' | undefined
|
||||
charsetSentinel?: boolean
|
||||
interpretNumericEntities?: boolean
|
||||
parseArrays?: boolean
|
||||
comma?: boolean
|
||||
}
|
||||
/**
|
||||
* Base config used by all types
|
||||
*/
|
||||
type BodyParserBaseConfig = {
|
||||
encoding: string
|
||||
limit: string | number
|
||||
types: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Body parser config for parsing JSON requests
|
||||
*/
|
||||
export type BodyParserJSONConfig = BodyParserBaseConfig & {
|
||||
strict: boolean
|
||||
convertEmptyStringsToNull: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser config for parsing form data
|
||||
*/
|
||||
export type BodyParserFormConfig = BodyParserBaseConfig & {
|
||||
queryString: QueryStringConfig
|
||||
convertEmptyStringsToNull: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser config for parsing raw body (untouched)
|
||||
*/
|
||||
export type BodyParserRawConfig = BodyParserBaseConfig
|
||||
/**
|
||||
* Body parser config for all supported form types
|
||||
*/
|
||||
export type BodyParserConfig = {
|
||||
allowedMethods: string[]
|
||||
json: BodyParserJSONConfig
|
||||
form: BodyParserFormConfig
|
||||
raw: BodyParserRawConfig
|
||||
multipart: BodyParserMultipartConfig
|
||||
}
|
|
@ -128,7 +128,7 @@ allowedMethods: ['POST', 'PUT', 'PATCH', 'DELETE'],
|
|||
| projects/:id/file
|
||||
| ```
|
||||
*/
|
||||
processManually: [],
|
||||
processManually: ['/submitter/dataset/submit'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -185,8 +185,8 @@ allowedMethods: ['POST', 'PUT', 'PATCH', 'DELETE'],
|
|||
| and fields data.
|
||||
|
|
||||
*/
|
||||
// limit: '20mb',
|
||||
limit: env.get('UPLOAD_LIMIT', '513mb'),
|
||||
limit: '513mb',
|
||||
//limit: env.get('UPLOAD_LIMIT', '513mb'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
280
package-lock.json
generated
280
package-lock.json
generated
|
@ -9,7 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@adonisjs/auth": "^9.2.4",
|
||||
"@adonisjs/bodyparser": "^10.0.3",
|
||||
"@adonisjs/bodyparser": "^10.0.1",
|
||||
"@adonisjs/core": "^6.17.0",
|
||||
"@adonisjs/cors": "^2.2.1",
|
||||
"@adonisjs/drive": "^3.2.0",
|
||||
|
@ -1912,9 +1912,9 @@
|
|||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@humanwhocodes/retry": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
|
||||
"integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
|
||||
"integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18"
|
||||
|
@ -2541,9 +2541,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@pkgr/core": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
|
||||
"integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz",
|
||||
"integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
@ -2836,9 +2836,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.36.0.tgz",
|
||||
"integrity": "sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz",
|
||||
"integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -2849,9 +2849,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.36.0.tgz",
|
||||
"integrity": "sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz",
|
||||
"integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2862,9 +2862,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.36.0.tgz",
|
||||
"integrity": "sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz",
|
||||
"integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2875,9 +2875,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.36.0.tgz",
|
||||
"integrity": "sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz",
|
||||
"integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -2888,9 +2888,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.36.0.tgz",
|
||||
"integrity": "sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz",
|
||||
"integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2901,9 +2901,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.36.0.tgz",
|
||||
"integrity": "sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz",
|
||||
"integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -2914,9 +2914,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.36.0.tgz",
|
||||
"integrity": "sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz",
|
||||
"integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -2927,9 +2927,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.36.0.tgz",
|
||||
"integrity": "sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz",
|
||||
"integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
@ -2940,9 +2940,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.36.0.tgz",
|
||||
"integrity": "sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz",
|
||||
"integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2953,9 +2953,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.36.0.tgz",
|
||||
"integrity": "sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz",
|
||||
"integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -2966,9 +2966,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.36.0.tgz",
|
||||
"integrity": "sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz",
|
||||
"integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
|
@ -2979,9 +2979,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.36.0.tgz",
|
||||
"integrity": "sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz",
|
||||
"integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
|
@ -2992,9 +2992,22 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.36.0.tgz",
|
||||
"integrity": "sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz",
|
||||
"integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz",
|
||||
"integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
|
@ -3005,9 +3018,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.36.0.tgz",
|
||||
"integrity": "sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz",
|
||||
"integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
|
@ -3018,9 +3031,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.36.0.tgz",
|
||||
"integrity": "sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz",
|
||||
"integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -3031,9 +3044,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.36.0.tgz",
|
||||
"integrity": "sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz",
|
||||
"integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -3044,9 +3057,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.36.0.tgz",
|
||||
"integrity": "sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz",
|
||||
"integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
@ -3057,9 +3070,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.36.0.tgz",
|
||||
"integrity": "sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz",
|
||||
"integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
|
@ -3070,9 +3083,9 @@
|
|||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.36.0.tgz",
|
||||
"integrity": "sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz",
|
||||
"integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
@ -3128,9 +3141,9 @@
|
|||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/@swc/wasm": {
|
||||
"version": "1.11.11",
|
||||
"resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.11.11.tgz",
|
||||
"integrity": "sha512-mPwKhESXb/SHtKGEeTM+TwA7zrpn1tF2cf7GnUakJh07SeUdJeTGP+zadotUzqqAWzYNHHWcMcM3C8Wef1ObjQ==",
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.11.13.tgz",
|
||||
"integrity": "sha512-R3cpgAX/mxoPH9zNCwmWGOqtvQ9obRpf97Kw8FJu0HUsEcEG766ozxFgfzE9p4IwK7pKOvzYR+szDtIXlOQwdQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
|
@ -3536,9 +3549,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/leaflet": {
|
||||
"version": "1.9.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.16.tgz",
|
||||
"integrity": "sha512-wzZoyySUxkgMZ0ihJ7IaUIblG8Rdc8AbbZKLneyn+QjYsj5q1QU7TEKYqwTr10BGSzY5LI7tJk9Ifo+mEjdFRw==",
|
||||
"version": "1.9.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.17.tgz",
|
||||
"integrity": "sha512-IJ4K6t7I3Fh5qXbQ1uwL3CFVbCi6haW9+53oLWgdKlLP7EaS21byWFJxxqOx9y8I0AP0actXSJLVMbyvxhkUTA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -3567,9 +3580,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
|
||||
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
|
||||
"version": "22.13.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.12.tgz",
|
||||
"integrity": "sha512-ixiWrCSRi33uqBMRuICcKECW7rtgY43TbsHDpM2XK7lXispd48opW+0IXrBVxv9NMhaz/Ue9kyj6r3NTVyXm8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
|
@ -4075,9 +4088,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@vavite/multibuild/node_modules/@types/node": {
|
||||
"version": "18.19.80",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.80.tgz",
|
||||
"integrity": "sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ==",
|
||||
"version": "18.19.82",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.82.tgz",
|
||||
"integrity": "sha512-s6RBC3H0JGG5Xm2IOP2R0KKNZL2s46UGZZ1r21EF3+qL377EwJ+Bnf9PMatFnYtmYMNnzVLodD6EN7FZw0Vbxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
|
@ -5189,9 +5202,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001706",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz",
|
||||
"integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==",
|
||||
"version": "1.0.30001707",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz",
|
||||
"integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6354,9 +6367,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.122",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.122.tgz",
|
||||
"integrity": "sha512-EML1wnwkY5MFh/xUnCvY8FrhUuKzdYhowuZExZOfwJo+Zu9OsNCI23Cgl5y7awy7HrUHSwB1Z8pZX5TI34lsUg==",
|
||||
"version": "1.5.123",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz",
|
||||
"integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
|
@ -6696,14 +6709,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz",
|
||||
"integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==",
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.4.tgz",
|
||||
"integrity": "sha512-SFtuYmnhwYCtuCDTKPoK+CEzCnEgKTU2qTLwoCxvrC0MFBTIXo1i6hDYOI4cwHaE5GZtlWmTN3YfucYi7KJwPw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.0",
|
||||
"synckit": "^0.9.1"
|
||||
"synckit": "^0.10.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
|
@ -7390,13 +7403,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/flydrive": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/flydrive/-/flydrive-1.1.0.tgz",
|
||||
"integrity": "sha512-acV6Pl2T+jjOURyvE57c79HP2KZmeI6sgPO6n5fZnExre4y8SCcLz5Fzttz79Snrpp6HbsA1q255OdVDf5Vrfg==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flydrive/-/flydrive-1.1.1.tgz",
|
||||
"integrity": "sha512-bcMD0eOoveOlPTvnPtjaOjq+7FidhiqldP6gSg9SQUqQc9pKSEQ/D3Xq0BDEElOLddaFKoaTUSgV2aX6kF+Ihw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@humanwhocodes/retry": "^0.3.0",
|
||||
"@poppinss/utils": "^6.7.3",
|
||||
"@humanwhocodes/retry": "^0.4.2",
|
||||
"@poppinss/utils": "^6.9.2",
|
||||
"etag": "^1.8.1",
|
||||
"mime-types": "^2.1.35"
|
||||
},
|
||||
|
@ -8152,9 +8165,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/html-entities": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
|
||||
"integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==",
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.3.tgz",
|
||||
"integrity": "sha512-D3AfvN7SjhTgBSA8L1BN4FpPzuEd06uy4lHwSoRWr0lndi9BKaNzPLKGOWZ2ocSGguozr08TTb2jhCLHaemruw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
@ -8438,9 +8451,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/index-to-position": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-0.1.2.tgz",
|
||||
"integrity": "sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.0.0.tgz",
|
||||
"integrity": "sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
@ -11230,15 +11243,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/read-pkg/node_modules/parse-json": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz",
|
||||
"integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.2.0.tgz",
|
||||
"integrity": "sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"index-to-position": "^0.1.2",
|
||||
"type-fest": "^4.7.1"
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"index-to-position": "^1.0.0",
|
||||
"type-fest": "^4.37.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
@ -11495,9 +11508,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.36.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.36.0.tgz",
|
||||
"integrity": "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==",
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz",
|
||||
"integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.6"
|
||||
|
@ -11510,25 +11523,26 @@
|
|||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.36.0",
|
||||
"@rollup/rollup-android-arm64": "4.36.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.36.0",
|
||||
"@rollup/rollup-darwin-x64": "4.36.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.36.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.36.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.36.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.36.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.36.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.36.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.36.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.36.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.36.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.36.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.36.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.36.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.36.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.36.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.36.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.37.0",
|
||||
"@rollup/rollup-android-arm64": "4.37.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.37.0",
|
||||
"@rollup/rollup-darwin-x64": "4.37.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.37.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.37.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.37.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.37.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.37.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.37.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.37.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.37.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.37.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.37.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.37.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.37.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.37.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.37.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.37.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.37.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
|
@ -12606,14 +12620,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
|
||||
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.10.2.tgz",
|
||||
"integrity": "sha512-cSGiaCPhFzeFIQY8KKEacv46LclENY4d60jgkwCrKomvRkIjtMyss1dPkHLp/62c1leuOjEedB1+lWcwqTJSvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.1.0",
|
||||
"tslib": "^2.6.2"
|
||||
"@pkgr/core": "^0.2.0",
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
|
@ -14352,9 +14366,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.0.tgz",
|
||||
"integrity": "sha512-KHBC7z61OJeaMGnF3wqNZj+GGNXOyypZviiKpQeiHirG5Ib1ImwcLBH70rbMSkKfSmUNBsdf2PwaEJtKvgmkNw==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz",
|
||||
"integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@adonisjs/auth": "^9.2.4",
|
||||
"@adonisjs/bodyparser": "^10.0.3",
|
||||
"@adonisjs/bodyparser": "^10.0.1",
|
||||
"@adonisjs/core": "^6.17.0",
|
||||
"@adonisjs/cors": "^2.2.1",
|
||||
"@adonisjs/drive": "^3.2.0",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<script setup>
|
||||
<script lang="ts" setup>
|
||||
import { mdiCog } from '@mdi/js';
|
||||
import CardBox from '@/Components/CardBox.vue';
|
||||
import NumberDynamic from '@/Components/NumberDynamic.vue';
|
||||
|
@ -49,6 +49,9 @@ defineProps({
|
|||
<PillTagTrend :trend="trend" :trend-type="trendType" small />
|
||||
<BaseButton :icon="mdiCog" icon-w="w-4" icon-h="h-4" color="white" small />
|
||||
</BaseLevel>
|
||||
<BaseLevel v-else class="mb-3" mobile>
|
||||
<BaseIcon v-if="icon" :path="icon" size="48" w="w-4" h="h-4" :class="color" />
|
||||
</BaseLevel>
|
||||
<BaseLevel mobile>
|
||||
<div>
|
||||
<h3 class="text-lg leading-tight text-gray-500 dark:text-slate-400">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { Head, usePage } from '@inertiajs/vue3';
|
||||
import { computed } from 'vue';
|
||||
import { MainService } from '@/Stores/main';
|
||||
import {
|
||||
mdiAccountMultiple,
|
||||
|
@ -9,7 +9,6 @@ import {
|
|||
mdiFinance,
|
||||
mdiMonitorCellphone,
|
||||
mdiReload,
|
||||
mdiGithub,
|
||||
mdiChartPie,
|
||||
} from '@mdi/js';
|
||||
import LineChart from '@/Components/Charts/LineChart.vue';
|
||||
|
@ -23,14 +22,15 @@ import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
|||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||
// import SectionBannerStarOnGitHub from '@/Components/SectionBannerStarOnGitea.vue';
|
||||
import CardBoxDataset from '@/Components/CardBoxDataset.vue';
|
||||
import type { User } from '@/Dataset';
|
||||
const mainService = MainService()
|
||||
|
||||
// const chartData = ref();
|
||||
// const fillChartData = async () => {
|
||||
// await mainService.fetchChartData("2022");
|
||||
// // chartData.value = chartConfig.sampleChartData();
|
||||
// // chartData.value = mainService.graphData;
|
||||
// };
|
||||
const fillChartData = async () => {
|
||||
await mainService.fetchChartData();
|
||||
// chartData.value = chartConfig.sampleChartData();
|
||||
// chartData.value = mainService.graphData;
|
||||
};
|
||||
const chartData = computed(() => mainService.graphData);
|
||||
// onMounted(async () => {
|
||||
// await mainService.fetchChartData("2022");
|
||||
|
@ -49,9 +49,14 @@ const authorBarItems = computed(() => mainService.authors.slice(0, 5));
|
|||
const authors = computed(() => mainService.authors);
|
||||
const datasets = computed(() => mainService.datasets);
|
||||
const datasetBarItems = computed(() => mainService.datasets.slice(0, 5));
|
||||
// let test = datasets.value;
|
||||
// console.log(test);
|
||||
const submitters = computed(() => mainService.clients);
|
||||
const user = computed(() => {
|
||||
return usePage().props.authUser as User;
|
||||
});
|
||||
|
||||
const userHasRoles = (roleNames: Array<string>): boolean => {
|
||||
return user.value.roles.some(role => roleNames.includes(role.name));
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -80,21 +85,21 @@ const datasetBarItems = computed(() => mainService.datasets.slice(0, 5));
|
|||
:number="authors.length"
|
||||
label="Authors"
|
||||
/>
|
||||
<CardBoxWidget
|
||||
trend="193"
|
||||
<!-- trend="193" -->
|
||||
<CardBoxWidget
|
||||
trend-type="info"
|
||||
color="text-blue-500"
|
||||
:icon="mdiDatabaseOutline"
|
||||
:number="datasets.length"
|
||||
label="Publications"
|
||||
/>
|
||||
<CardBoxWidget
|
||||
trend="+25%"
|
||||
<!-- trend="+25%" -->
|
||||
<CardBoxWidget
|
||||
trend-type="up"
|
||||
color="text-purple-500"
|
||||
:icon="mdiChartTimelineVariant"
|
||||
:number="52"
|
||||
label="Citations"
|
||||
:number="submitters.length"
|
||||
label="Submitters"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -128,11 +133,9 @@ const datasetBarItems = computed(() => mainService.datasets.slice(0, 5));
|
|||
</div>
|
||||
</CardBox>
|
||||
|
||||
<SectionTitleLineWithButton :icon="mdiAccountMultiple" title="Submitters" />
|
||||
|
||||
<SectionTitleLineWithButton v-if="userHasRoles(['administrator'])" :icon="mdiAccountMultiple" title="Submitters" />
|
||||
<!-- <NotificationBar color="info" :icon="mdiMonitorCellphone"> <b>Responsive table.</b> Collapses on mobile </NotificationBar> -->
|
||||
|
||||
<CardBox :icon="mdiMonitorCellphone" title="Responsive table" has-table>
|
||||
<CardBox v-if="userHasRoles(['administrator'])" :icon="mdiMonitorCellphone" title="Responsive table" has-table>
|
||||
<TableSampleClients />
|
||||
</CardBox>
|
||||
</SectionMain>
|
||||
|
|
|
@ -20,11 +20,13 @@ import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.
|
|||
import BaseButton from '@/Components/BaseButton.vue';
|
||||
import { mdiLightbulbAlert, mdiArrowLeftBoldOutline } from '@mdi/js';
|
||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||
|
||||
@Component({
|
||||
// options: {
|
||||
// layout: DefaultLayout,
|
||||
// },
|
||||
import LayoutGuest from '@/Layouts/LayoutGuest.vue';
|
||||
|
||||
|
||||
@Component({
|
||||
options: {
|
||||
layout: LayoutGuest,
|
||||
},
|
||||
name: 'AppComponent',
|
||||
|
||||
components: {
|
||||
|
|
71
resources/js/Pages/Errors/postgres_error.vue
Normal file
71
resources/js/Pages/Errors/postgres_error.vue
Normal file
|
@ -0,0 +1,71 @@
|
|||
<template>
|
||||
<div class="min-h-screen flex items-center justify-center bg-gray-100">
|
||||
<div class="max-w-md w-full p-6 bg-white rounded-md shadow-md">
|
||||
<h1 class="text-2xl font-bold text-red-500 mb-4">{{ status }}</h1>
|
||||
<p class="text-gray-700 mb-4">{{ message }}</p>
|
||||
<div class="text-sm text-gray-500 mb-4">
|
||||
<p>Error Code: {{ details.code }}</p>
|
||||
<p>Type: {{ details.type }}</p>
|
||||
<div v-for="(port, index) in details.ports" :key="index">
|
||||
<p>Connection attempt {{ index + 1 }}: {{ port.address }}:{{ port.port }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<SectionTitleLineWithButton :icon="mdiLightbulbAlert" :title="'Database Error'" :main="true">
|
||||
<BaseButton @click.prevent="handleAction" :icon="mdiArrowLeftBoldOutline" label="Dashboard"
|
||||
color="white" rounded-full small />
|
||||
</SectionTitleLineWithButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from 'vue-facing-decorator';
|
||||
import { Link, router } from '@inertiajs/vue3';
|
||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||
import BaseButton from '@/Components/BaseButton.vue';
|
||||
import { mdiLightbulbAlert, mdiArrowLeftBoldOutline } from '@mdi/js';
|
||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||
import LayoutGuest from '@/Layouts/LayoutGuest.vue';
|
||||
|
||||
@Component({
|
||||
options: {
|
||||
layout: LayoutGuest,
|
||||
},
|
||||
name: 'PostgresError',
|
||||
components: {
|
||||
Link,
|
||||
BaseButton,
|
||||
SectionTitleLineWithButton,
|
||||
},
|
||||
})
|
||||
export default class AppComponent extends Vue {
|
||||
@Prop({
|
||||
type: String,
|
||||
default: '',
|
||||
})
|
||||
status: string;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
default: '',
|
||||
})
|
||||
message: string;
|
||||
|
||||
@Prop({
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
})
|
||||
details: {
|
||||
code: string;
|
||||
type: string;
|
||||
ports: Array<{ port: number; address: string }>;
|
||||
};
|
||||
|
||||
mdiLightbulbAlert = mdiLightbulbAlert;
|
||||
mdiArrowLeftBoldOutline = mdiArrowLeftBoldOutline;
|
||||
|
||||
public async handleAction() {
|
||||
await router.get(stardust.route('dashboard'));
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -198,7 +198,8 @@ export const MainService = defineStore('main', {
|
|||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
alert(error.message);
|
||||
// alert(error.message);
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -236,17 +237,18 @@ export const MainService = defineStore('main', {
|
|||
this.totpState = state;
|
||||
},
|
||||
|
||||
fetchChartData(year: string) {
|
||||
fetchChartData() {
|
||||
// sampleDataKey= authors or datasets
|
||||
axios
|
||||
.get(`/api/statistic/${year}`)
|
||||
.get(`/api/statistic`)
|
||||
.then((r) => {
|
||||
if (r.data) {
|
||||
this.graphData = r.data;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
alert(error.message);
|
||||
// alert(error.message);
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -106,7 +106,14 @@ router
|
|||
|
||||
// Auth routes
|
||||
router
|
||||
.get('/app/login', ({ inertia }: HttpContext) => {
|
||||
.get('/app/login', async({ inertia }: HttpContext) => {
|
||||
try {
|
||||
await db.connection().rawQuery('SELECT 1');
|
||||
} catch (error) {
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return inertia.render('Auth/Login');
|
||||
})
|
||||
.as('app.login.show');
|
||||
|
@ -246,18 +253,11 @@ router.get('/settings/user/security', [UserController, 'accountInfo']).as('setti
|
|||
router.post('/settings/user/store', [UserController, 'accountInfoStore']).as('account.password.store').use(middleware.auth());
|
||||
router.get('/settings/profile/edit', [UserController, 'profile']).as('settings.profile.edit').use(middleware.auth());
|
||||
router
|
||||
.put('/settings/profile/:id/update', [UserController, 'profileUpdate'])
|
||||
.as('settings.profile.update')
|
||||
.where('id', router.matchers.number())
|
||||
.use(middleware.auth());
|
||||
router
|
||||
.put('/settings/password/update', [UserController, 'passwordUpdate'])
|
||||
.as('settings.password.update')
|
||||
.use(middleware.auth());
|
||||
|
||||
|
||||
|
||||
|
||||
.put('/settings/profile/:id/update', [UserController, 'profileUpdate'])
|
||||
.as('settings.profile.update')
|
||||
.where('id', router.matchers.number())
|
||||
.use(middleware.auth());
|
||||
router.put('/settings/password/update', [UserController, 'passwordUpdate']).as('settings.password.update').use(middleware.auth());
|
||||
|
||||
// Submitter routes
|
||||
router
|
||||
|
|
|
@ -20,7 +20,7 @@ router
|
|||
router.get('/dataset/:publish_id', [DatasetController, 'findOne']).as('dataset.findOne');
|
||||
router.get('/sitelinks/:year', [HomeController, 'findDocumentsPerYear']);
|
||||
router.get('/years', [HomeController, 'findYears']);
|
||||
router.get('/statistic/:year', [HomeController, 'findPublicationsPerMonth']);
|
||||
router.get('/statistic', [HomeController, 'findPublicationsPerMonth']);
|
||||
|
||||
router.get('/download/:id', [FileController, 'findOne']).as('file.findOne');
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue