- added LicenseController.ts and MimetypeController for enabling mime_types and licences
Some checks failed
CI Pipeline / japa-tests (push) Failing after 58s
Some checks failed
CI Pipeline / japa-tests (push) Failing after 58s
- add new authors and contributors only by unique email addresses - allow multiple file upload - added validation rule for validating length of uploaded files - modified Dockerfile for starting "bin/server.js" instead of *server.js" - npm updates
This commit is contained in:
parent
770e791613
commit
ac473b1e72
|
@ -89,4 +89,4 @@ COPY --chown=node:node --from=build /home/node/app/build .
|
||||||
EXPOSE 3333
|
EXPOSE 3333
|
||||||
ENTRYPOINT ["/home/node/app/docker-entrypoint.sh"]
|
ENTRYPOINT ["/home/node/app/docker-entrypoint.sh"]
|
||||||
# Run the command to start the server using "dumb-init"
|
# Run the command to start the server using "dumb-init"
|
||||||
CMD [ "dumb-init", "node", "server.js" ]
|
CMD [ "dumb-init", "node", "bin/server.js" ]
|
|
@ -27,7 +27,9 @@ export default defineConfig({
|
||||||
() => import('./start/kernel.js'),
|
() => import('./start/kernel.js'),
|
||||||
() => import('#start/validator'),
|
() => import('#start/validator'),
|
||||||
() => import('#start/rules/unique'),
|
() => import('#start/rules/unique'),
|
||||||
() => import('#start/rules/translated_language')
|
() => import('#start/rules/translated_language'),
|
||||||
|
() => import('#start/rules/unique_person'),
|
||||||
|
() => import('#start/rules/file_length')
|
||||||
],
|
],
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -64,7 +66,8 @@ export default defineConfig({
|
||||||
() => import('#providers/token_worker_provider'),
|
() => import('#providers/token_worker_provider'),
|
||||||
// () => import('#providers/validator_provider'),
|
// () => import('#providers/validator_provider'),
|
||||||
() => import('#providers/drive/provider/drive_provider'),
|
() => import('#providers/drive/provider/drive_provider'),
|
||||||
() => import('@adonisjs/core/providers/vinejs_provider')
|
// () => import('@adonisjs/core/providers/vinejs_provider'),
|
||||||
|
() => import('#providers/vinejs_provider')
|
||||||
],
|
],
|
||||||
metaFiles: [
|
metaFiles: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -134,7 +134,7 @@ export default class AdminuserController {
|
||||||
// validate update form
|
// validate update form
|
||||||
await request.validateUsing(updateUserValidator, {
|
await request.validateUsing(updateUserValidator, {
|
||||||
meta: {
|
meta: {
|
||||||
userId: user.id,
|
objId: user.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -166,8 +166,8 @@ export default class AdminuserController {
|
||||||
return response.redirect().toRoute('settings.user.index');
|
return response.redirect().toRoute('settings.user.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
// private async syncRoles(userId: number, roleIds: Array<number>) {
|
// private async syncRoles(objId: number, roleIds: Array<number>) {
|
||||||
// const user = await User.findOrFail(userId)
|
// const user = await User.findOrFail(objId)
|
||||||
// // const roles: Role[] = await Role.query().whereIn('id', roleIds);
|
// // const roles: Role[] = await Role.query().whereIn('id', roleIds);
|
||||||
|
|
||||||
// // await user.roles().sync(roles.rows.map(role => role.id))
|
// // await user.roles().sync(roles.rows.map(role => role.id))
|
||||||
|
|
51
app/Controllers/Http/Admin/LicenseController.ts
Normal file
51
app/Controllers/Http/Admin/LicenseController.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import type { HttpContext } from '@adonisjs/core/http';
|
||||||
|
import License from '#models/license';
|
||||||
|
|
||||||
|
export default class LicenseController {
|
||||||
|
public async index({ auth, inertia }: HttpContext) {
|
||||||
|
const direction = 'asc'; // or 'desc'
|
||||||
|
const licenses = await License.query().orderBy('sort_order', direction).exec();
|
||||||
|
|
||||||
|
return inertia.render('Admin/License/Index', {
|
||||||
|
licenses: licenses,
|
||||||
|
can: {
|
||||||
|
edit: await auth.user?.can(['settings']),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down({ request, response }: HttpContext) {
|
||||||
|
const id = request.param('id');
|
||||||
|
const license = await License.findOrFail(id);
|
||||||
|
license.active = false;
|
||||||
|
await license.save();
|
||||||
|
|
||||||
|
// session.flash({ message: 'person has been deactivated!' });
|
||||||
|
return response.flash('person has been deactivated!', 'message').toRoute('settings.license.index')
|
||||||
|
}
|
||||||
|
|
||||||
|
public async up({ request, response }: HttpContext) {
|
||||||
|
const id = request.param('id');
|
||||||
|
const license = await License.findOrFail(id);
|
||||||
|
license.active = true;
|
||||||
|
await license.save();
|
||||||
|
|
||||||
|
// session.flash({ message: 'person has been activated!' });
|
||||||
|
return response.flash('person has been activated!', 'message').toRoute('settings.license.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// public async edit({ request, inertia }: HttpContext) {
|
||||||
|
// const id = request.param('id');
|
||||||
|
// const license = await License.query().where('id', id).firstOrFail();
|
||||||
|
|
||||||
|
// // const permissions = await Permission.query().pluck('name', 'id');
|
||||||
|
// // // const userHasRoles = user.roles;
|
||||||
|
// // const rolerHasPermissions = await role.related('permissions').query().orderBy('name').pluck('id');
|
||||||
|
|
||||||
|
// return inertia.render('Admin/License/Edit', {
|
||||||
|
// // permissions: permissions,
|
||||||
|
// license: license,
|
||||||
|
// // roleHasPermissions: Object.keys(rolerHasPermissions).map((key) => rolerHasPermissions[key]), //convert object to array with role ids
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
51
app/Controllers/Http/Admin/MimetypeController.ts
Normal file
51
app/Controllers/Http/Admin/MimetypeController.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import type { HttpContext } from '@adonisjs/core/http';
|
||||||
|
import MimeType from '#models/mime_type';
|
||||||
|
|
||||||
|
export default class MimetypeController {
|
||||||
|
public async index({ auth, inertia }: HttpContext) {
|
||||||
|
const direction = 'asc'; // or 'desc'
|
||||||
|
const mimetypes = await MimeType.query().orderBy('name', direction).exec();
|
||||||
|
|
||||||
|
return inertia.render('Admin/Mimetype/Index', {
|
||||||
|
mimetypes: mimetypes,
|
||||||
|
can: {
|
||||||
|
edit: await auth.user?.can(['settings']),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down({ request, response }: HttpContext) {
|
||||||
|
const id = request.param('id');
|
||||||
|
const mimetype = await MimeType.findOrFail(id);
|
||||||
|
mimetype.enabled = false;
|
||||||
|
await mimetype .save();
|
||||||
|
|
||||||
|
// session.flash({ message: 'person has been deactivated!' });
|
||||||
|
return response.flash('mimetype has been deactivated!', 'message').toRoute('settings.mimetype.index')
|
||||||
|
}
|
||||||
|
|
||||||
|
public async up({ request, response }: HttpContext) {
|
||||||
|
const id = request.param('id');
|
||||||
|
const mimetype = await MimeType.findOrFail(id);
|
||||||
|
mimetype.enabled = true;
|
||||||
|
await mimetype .save();
|
||||||
|
|
||||||
|
// session.flash({ message: 'person has been activated!' });
|
||||||
|
return response.flash('mimetype has been activated!', 'message').toRoute('settings.mimetype.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// public async edit({ request, inertia }: HttpContext) {
|
||||||
|
// const id = request.param('id');
|
||||||
|
// const license = await License.query().where('id', id).firstOrFail();
|
||||||
|
|
||||||
|
// // const permissions = await Permission.query().pluck('name', 'id');
|
||||||
|
// // // const userHasRoles = user.roles;
|
||||||
|
// // const rolerHasPermissions = await role.related('permissions').query().orderBy('name').pluck('id');
|
||||||
|
|
||||||
|
// return inertia.render('Admin/License/Edit', {
|
||||||
|
// // permissions: permissions,
|
||||||
|
// license: license,
|
||||||
|
// // roleHasPermissions: Object.keys(rolerHasPermissions).map((key) => rolerHasPermissions[key]), //convert object to array with role ids
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
|
@ -216,17 +216,23 @@ export default class DatasetController {
|
||||||
authors: vine
|
authors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.minLength(1),
|
.minLength(1)
|
||||||
|
.distinct('email'),
|
||||||
contributors: vine
|
contributors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.distinct('email')
|
||||||
.optional(),
|
.optional(),
|
||||||
project_id: vine.number().optional(),
|
project_id: vine.number().optional(),
|
||||||
});
|
});
|
||||||
|
@ -287,17 +293,23 @@ export default class DatasetController {
|
||||||
authors: vine
|
authors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.minLength(1),
|
.minLength(1)
|
||||||
|
.distinct('email'),
|
||||||
contributors: vine
|
contributors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.distinct('email')
|
||||||
.optional(),
|
.optional(),
|
||||||
// third step
|
// third step
|
||||||
project_id: vine.number().optional(),
|
project_id: vine.number().optional(),
|
||||||
|
@ -631,7 +643,9 @@ export default class DatasetController {
|
||||||
'The language of the translated description must be different from the language of the dataset',
|
'The language of the translated description must be different from the language of the dataset',
|
||||||
|
|
||||||
'authors.array.minLength': 'at least {{ min }} author must be defined',
|
'authors.array.minLength': 'at least {{ min }} author must be defined',
|
||||||
|
'authors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',
|
||||||
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
||||||
|
'contributors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',
|
||||||
|
|
||||||
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
|
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
|
||||||
|
|
||||||
|
|
|
@ -55,17 +55,23 @@ export const createDatasetValidator = vine.compile(
|
||||||
authors: vine
|
authors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.minLength(1),
|
.minLength(1)
|
||||||
|
.distinct('email'),
|
||||||
contributors: vine
|
contributors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.distinct('email')
|
||||||
.optional(),
|
.optional(),
|
||||||
// third step
|
// third step
|
||||||
project_id: vine.number().optional(),
|
project_id: vine.number().optional(),
|
||||||
|
@ -114,10 +120,10 @@ export const createDatasetValidator = vine.compile(
|
||||||
// last step
|
// last step
|
||||||
files: vine
|
files: vine
|
||||||
.array(
|
.array(
|
||||||
vine.file({
|
vine.myfile({
|
||||||
size: '512mb',
|
size: '512mb',
|
||||||
extnames: extensions,
|
extnames: extensions,
|
||||||
}),
|
}).filenameLength({ clientNameSizeLimit : 100 }),
|
||||||
)
|
)
|
||||||
.minLength(1),
|
.minLength(1),
|
||||||
}),
|
}),
|
||||||
|
@ -169,17 +175,23 @@ export const updateDatasetValidator = vine.compile(
|
||||||
authors: vine
|
authors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.minLength(1),
|
.minLength(1)
|
||||||
|
.distinct('email'),
|
||||||
contributors: vine
|
contributors: vine
|
||||||
.array(
|
.array(
|
||||||
vine.object({
|
vine.object({
|
||||||
email: vine.string().trim().maxLength(255).email().normalizeEmail(),
|
email: vine.string().trim().maxLength(255).email().normalizeEmail().isUniquePerson({ table: 'persons', column: 'email', idField: 'id' }),
|
||||||
|
first_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
|
last_name: vine.string().trim().minLength(3).maxLength(255),
|
||||||
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.distinct('email')
|
||||||
.optional(),
|
.optional(),
|
||||||
// third step
|
// third step
|
||||||
project_id: vine.number().optional(),
|
project_id: vine.number().optional(),
|
||||||
|
@ -228,7 +240,7 @@ export const updateDatasetValidator = vine.compile(
|
||||||
// last step
|
// last step
|
||||||
files: vine
|
files: vine
|
||||||
.array(
|
.array(
|
||||||
vine.file({
|
vine.myfile({
|
||||||
size: '512mb',
|
size: '512mb',
|
||||||
extnames: extensions,
|
extnames: extensions,
|
||||||
}),
|
}),
|
||||||
|
@ -270,7 +282,9 @@ let messagesProvider = new SimpleMessagesProvider({
|
||||||
'The language of the translated description must be different from the language of the dataset',
|
'The language of the translated description must be different from the language of the dataset',
|
||||||
|
|
||||||
'authors.array.minLength': 'at least {{ min }} author must be defined',
|
'authors.array.minLength': 'at least {{ min }} author must be defined',
|
||||||
|
'authors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',
|
||||||
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined',
|
||||||
|
'contributors.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.',
|
||||||
|
|
||||||
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
|
'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`,
|
||||||
|
|
||||||
|
|
|
@ -23,21 +23,21 @@ export const createUserValidator = vine.compile(
|
||||||
* Validates the role's update action
|
* Validates the role's update action
|
||||||
* node ace make:validator user
|
* node ace make:validator user
|
||||||
*/
|
*/
|
||||||
export const updateUserValidator = vine.withMetaData<{ userId: number }>().compile(
|
export const updateUserValidator = vine.withMetaData<{ objId: number }>().compile(
|
||||||
vine.object({
|
vine.object({
|
||||||
login: vine
|
login: vine
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
.minLength(3)
|
.minLength(3)
|
||||||
.maxLength(20)
|
.maxLength(20)
|
||||||
.isUnique({ table: 'accounts', column: 'login', whereNot: (field) => field.meta.userId })
|
.isUnique({ table: 'accounts', column: 'login', whereNot: (field) => field.meta.objId })
|
||||||
.regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores
|
.regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores
|
||||||
email: vine
|
email: vine
|
||||||
.string()
|
.string()
|
||||||
.maxLength(255)
|
.maxLength(255)
|
||||||
.email()
|
.email()
|
||||||
.normalizeEmail()
|
.normalizeEmail()
|
||||||
.isUnique({ table: 'accounts', column: 'email', whereNot: (field) => field.meta.userId }),
|
.isUnique({ table: 'accounts', column: 'email', whereNot: (field) => field.meta.objId }),
|
||||||
password: vine.string().confirmed().trim().minLength(3).maxLength(60),
|
password: vine.string().confirmed().trim().minLength(3).maxLength(60),
|
||||||
roles: vine.array(vine.number()).minLength(1), // define at least one role for the new user
|
roles: vine.array(vine.number()).minLength(1), // define at least one role for the new user
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -13,7 +13,7 @@ import env from '#start/env';
|
||||||
// import { ServerConfig } from "@adonisjs/core/services/server";
|
// import { ServerConfig } from "@adonisjs/core/services/server";
|
||||||
// import { LoggerConfig } from "@adonisjs/core/types/logger";
|
// import { LoggerConfig } from "@adonisjs/core/types/logger";
|
||||||
// import { ValidatorConfig } from "@adonisjs/validator/types";
|
// import { ValidatorConfig } from "@adonisjs/validator/types";
|
||||||
import { defineConfig } from "@adonisjs/core/http";
|
import { defineConfig } from '@adonisjs/core/http';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -114,7 +114,6 @@ export const http = defineConfig({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Profiler
|
| Profiler
|
||||||
|
|
1670
package-lock.json
generated
1670
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
160
providers/vinejs_provider.ts
Normal file
160
providers/vinejs_provider.ts
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Provider File - node ace make:provider vinejsProvider
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|*/
|
||||||
|
import type { ApplicationService } from '@adonisjs/core/types';
|
||||||
|
import vine, { BaseLiteralType, Vine } from '@vinejs/vine';
|
||||||
|
import type { Validation, FieldContext, FieldOptions } from '@vinejs/vine/types';
|
||||||
|
// import type { MultipartFile, FileValidationOptions } from '@adonisjs/bodyparser/types';
|
||||||
|
import type { MultipartFile } from '@adonisjs/core/bodyparser';
|
||||||
|
import type { FileValidationOptions } from '@adonisjs/core/types/bodyparser';
|
||||||
|
import { Request, RequestValidator } from '@adonisjs/core/http';
|
||||||
|
/**
|
||||||
|
* Validation options accepted by the "file" rule
|
||||||
|
*/
|
||||||
|
export type FileRuleValidationOptions = Partial<FileValidationOptions> | ((field: FieldContext) => Partial<FileValidationOptions>);
|
||||||
|
/**
|
||||||
|
* Extend VineJS
|
||||||
|
*/
|
||||||
|
declare module '@vinejs/vine' {
|
||||||
|
interface Vine {
|
||||||
|
myfile(options?: FileRuleValidationOptions): VineMultipartFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Extend HTTP request class
|
||||||
|
*/
|
||||||
|
declare module '@adonisjs/core/http' {
|
||||||
|
interface Request extends RequestValidator {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is an instance of multipart file
|
||||||
|
* from bodyparser.
|
||||||
|
*/
|
||||||
|
export function isBodyParserFile(file: MultipartFile | unknown): boolean {
|
||||||
|
return !!(file && typeof file === 'object' && 'isMultipartFile' in file);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* VineJS validation rule that validates the file to be an
|
||||||
|
* instance of BodyParser MultipartFile class.
|
||||||
|
*/
|
||||||
|
const isMultipartFile = vine.createRule((file: MultipartFile | unknown, options: FileRuleValidationOptions, field: FieldContext) => {
|
||||||
|
/**
|
||||||
|
* Report error when value is not a field multipart
|
||||||
|
* file object
|
||||||
|
*/
|
||||||
|
if (!isBodyParserFile(file)) {
|
||||||
|
field.report('The {{ field }} must be a file', 'file', field);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// At this point, you can use type assertion to explicitly tell TypeScript that file is of type MultipartFile
|
||||||
|
const validatedFile = file as MultipartFile;
|
||||||
|
const validationOptions = typeof options === 'function' ? options(field) : options;
|
||||||
|
/**
|
||||||
|
* Set size when it's defined in the options and missing
|
||||||
|
* on the file instance
|
||||||
|
*/
|
||||||
|
if (validatedFile.sizeLimit === undefined && validationOptions.size) {
|
||||||
|
validatedFile.sizeLimit = validationOptions.size;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set extensions when it's defined in the options and missing
|
||||||
|
* on the file instance
|
||||||
|
*/
|
||||||
|
if (validatedFile.allowedExtensions === undefined && validationOptions.extnames) {
|
||||||
|
validatedFile.allowedExtensions = validationOptions.extnames;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* wieder löschen
|
||||||
|
* Set extensions when it's defined in the options and missing
|
||||||
|
* on the file instance
|
||||||
|
*/
|
||||||
|
// if (file.clientNameSizeLimit === undefined && validationOptions.clientNameSizeLimit) {
|
||||||
|
// file.clientNameSizeLimit = validationOptions.clientNameSizeLimit;
|
||||||
|
// }
|
||||||
|
/**
|
||||||
|
* Validate file
|
||||||
|
*/
|
||||||
|
validatedFile.validate();
|
||||||
|
/**
|
||||||
|
* Report errors
|
||||||
|
*/
|
||||||
|
validatedFile.errors.forEach((error) => {
|
||||||
|
field.report(error.message, `file.${error.type}`, field, validationOptions);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export class VineMultipartFile extends BaseLiteralType<MultipartFile, MultipartFile, MultipartFile> {
|
||||||
|
// #private;
|
||||||
|
// constructor(validationOptions?: FileRuleValidationOptions, options?: FieldOptions, validations?: Validation<any>[]);
|
||||||
|
// clone(): this;
|
||||||
|
|
||||||
|
public validationOptions;
|
||||||
|
// extnames: (18) ['gpkg', 'htm', 'html', 'csv', 'txt', 'asc', 'c', 'cc', 'h', 'srt', 'tiff', 'pdf', 'png', 'zip', 'jpg', 'jpeg', 'jpe', 'xlsx']
|
||||||
|
// size: '512mb'
|
||||||
|
|
||||||
|
public constructor(validationOptions?: FileRuleValidationOptions, options?: FieldOptions, validations?: Validation<any>[]) {
|
||||||
|
// super(options, validations);
|
||||||
|
super(options, [isMultipartFile(validationOptions || {})]);
|
||||||
|
this.validationOptions = validationOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public clone(): any {
|
||||||
|
return new VineMultipartFile(this.validationOptions, this.cloneOptions(), this.cloneValidations());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class VinejsProvider {
|
||||||
|
protected app: ApplicationService;
|
||||||
|
|
||||||
|
constructor(app: ApplicationService) {
|
||||||
|
this.app = app;
|
||||||
|
this.app.usingVineJS = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register bindings to the container
|
||||||
|
*/
|
||||||
|
register() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The container bindings have booted
|
||||||
|
*/
|
||||||
|
|
||||||
|
boot(): void {
|
||||||
|
// VineString.macro('translatedLanguage', function (this: VineString, options: Options) {
|
||||||
|
// return this.use(translatedLanguageRule(options));
|
||||||
|
// });
|
||||||
|
|
||||||
|
Vine.macro('myfile', function (this: Vine, options) {
|
||||||
|
return new VineMultipartFile(options);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The validate method can be used to validate the request
|
||||||
|
* data for the current request using VineJS validators
|
||||||
|
*/
|
||||||
|
Request.macro('validateUsing', function (...args) {
|
||||||
|
return new RequestValidator(this.ctx).validateUsing(...args);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application has been booted
|
||||||
|
*/
|
||||||
|
async start() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The process has been started
|
||||||
|
*/
|
||||||
|
async ready() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preparing to shutdown the app
|
||||||
|
*/
|
||||||
|
async shutdown() {}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
"assets/app.css": "http://localhost:8080/assets/app.css",
|
"assets/app.css": "http://localhost:8080/assets/app.css",
|
||||||
"assets/app.js": "http://localhost:8080/assets/app.js",
|
"assets/app.js": "http://localhost:8080/assets/app.js",
|
||||||
|
"assets/resources_js_Pages_Admin_License_Index_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_License_Index_vue.js",
|
||||||
|
"assets/resources_js_Pages_Admin_Mimetype_Index_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Mimetype_Index_vue.js",
|
||||||
"assets/resources_js_Pages_Admin_Permission_Create_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Permission_Create_vue.js",
|
"assets/resources_js_Pages_Admin_Permission_Create_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Permission_Create_vue.js",
|
||||||
"assets/resources_js_Pages_Admin_Permission_Edit_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Permission_Edit_vue.js",
|
"assets/resources_js_Pages_Admin_Permission_Edit_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Permission_Edit_vue.js",
|
||||||
"assets/resources_js_Pages_Admin_Permission_Index_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Permission_Index_vue.js",
|
"assets/resources_js_Pages_Admin_Permission_Index_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Permission_Index_vue.js",
|
||||||
|
@ -60,6 +62,7 @@
|
||||||
"assets/resources_js_Components_Admin_Pagination_vue-resources_js_Components_BaseButtons_vue-resource-8134e7.js": "http://localhost:8080/assets/resources_js_Components_Admin_Pagination_vue-resources_js_Components_BaseButtons_vue-resource-8134e7.js",
|
"assets/resources_js_Components_Admin_Pagination_vue-resources_js_Components_BaseButtons_vue-resource-8134e7.js": "http://localhost:8080/assets/resources_js_Components_Admin_Pagination_vue-resources_js_Components_BaseButtons_vue-resource-8134e7.js",
|
||||||
"assets/resources_js_Components_Map_draw_component_vue-resources_js_Components_Map_zoom_component_vue-196747.js": "http://localhost:8080/assets/resources_js_Components_Map_draw_component_vue-resources_js_Components_Map_zoom_component_vue-196747.js",
|
"assets/resources_js_Components_Map_draw_component_vue-resources_js_Components_Map_zoom_component_vue-196747.js": "http://localhost:8080/assets/resources_js_Components_Map_draw_component_vue-resources_js_Components_Map_zoom_component_vue-196747.js",
|
||||||
"assets/resources_js_Components_Admin_Sort_vue-resources_js_Components_SectionTitleLineWithButton_vue.js": "http://localhost:8080/assets/resources_js_Components_Admin_Sort_vue-resources_js_Components_SectionTitleLineWithButton_vue.js",
|
"assets/resources_js_Components_Admin_Sort_vue-resources_js_Components_SectionTitleLineWithButton_vue.js": "http://localhost:8080/assets/resources_js_Components_Admin_Sort_vue-resources_js_Components_SectionTitleLineWithButton_vue.js",
|
||||||
|
"assets/resources_js_Components_CardBoxModal_vue.js": "http://localhost:8080/assets/resources_js_Components_CardBoxModal_vue.js",
|
||||||
"assets/resources_js_Components_FileUpload_vue-resources_js_Components_FormCheckRadioGroup_vue-resour-d5e5fc.js": "http://localhost:8080/assets/resources_js_Components_FileUpload_vue-resources_js_Components_FormCheckRadioGroup_vue-resour-d5e5fc.js",
|
"assets/resources_js_Components_FileUpload_vue-resources_js_Components_FormCheckRadioGroup_vue-resour-d5e5fc.js": "http://localhost:8080/assets/resources_js_Components_FileUpload_vue-resources_js_Components_FormCheckRadioGroup_vue-resour-d5e5fc.js",
|
||||||
"assets/fonts/inter-latin-ext-400-normal.woff": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.40b3b0d5.woff",
|
"assets/fonts/inter-latin-ext-400-normal.woff": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.40b3b0d5.woff",
|
||||||
"assets/fonts/inter-latin-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.0f9e8d4e.woff2",
|
"assets/fonts/inter-latin-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.0f9e8d4e.woff2",
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
</p>
|
</p>
|
||||||
<!-- <p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p> -->
|
<!-- <p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p> -->
|
||||||
</div>
|
</div>
|
||||||
<input id="dropzone-file" type="file" class="hidden" @change="onChangeFile" />
|
<input id="dropzone-file" type="file" class="hidden" @change="onChangeFile" multiple="true"/>
|
||||||
</label>
|
</label>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ export default class DrawControlComponent extends Vue {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
top: 100px;
|
top: 100px;
|
||||||
z-index: 39;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group-vertical button {
|
.btn-group-vertical button {
|
||||||
|
|
|
@ -257,7 +257,7 @@ export default class MapComponent extends Vue {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-pane {
|
/* .leaflet-pane {
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
}
|
} */
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -100,7 +100,7 @@ export default class ZoomControlComponent extends Vue {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
z-index: 39;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group-vertical button {
|
.btn-group-vertical button {
|
||||||
|
|
|
@ -22,6 +22,10 @@ const props = defineProps({
|
||||||
type: Array<Person>,
|
type: Array<Person>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
relation: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
contributortypes: {
|
contributortypes: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
|
@ -82,7 +86,7 @@ const pagesList = computed(() => {
|
||||||
return pagesList;
|
return pagesList;
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeAuthor = (key) => {
|
const removeAuthor = (key: number) => {
|
||||||
items.value.splice(key, 1);
|
items.value.splice(key, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,8 +135,10 @@ const removeAuthor = (key) => {
|
||||||
<!-- <th v-if="checkable" /> -->
|
<!-- <th v-if="checkable" /> -->
|
||||||
<th />
|
<th />
|
||||||
<th scope="col">Sort</th>
|
<th scope="col">Sort</th>
|
||||||
<th class="hidden lg:table-cell"></th>
|
<th scope="col">Id</th>
|
||||||
<th>Name</th>
|
<!-- <th class="hidden lg:table-cell"></th> -->
|
||||||
|
<th>First Name</th>
|
||||||
|
<th>Last Name</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th scope="col" v-if="Object.keys(contributortypes).length">
|
<th scope="col" v-if="Object.keys(contributortypes).length">
|
||||||
<span>Type</span>
|
<span>Type</span>
|
||||||
|
@ -153,15 +159,56 @@ const removeAuthor = (key) => {
|
||||||
<BaseIcon :path="mdiDragVariant" />
|
<BaseIcon :path="mdiDragVariant" />
|
||||||
</td>
|
</td>
|
||||||
<td scope="row">{{ index + 1 }}</td>
|
<td scope="row">{{ index + 1 }}</td>
|
||||||
|
<td data-label="Id">{{ element.id }}</td>
|
||||||
<!-- <TableCheckboxCell v-if="checkable" @checked="checked($event, client)" /> -->
|
<!-- <TableCheckboxCell v-if="checkable" @checked="checked($event, client)" /> -->
|
||||||
<td class="border-b-0 lg:w-6 before:hidden hidden lg:table-cell">
|
<!-- <td v-if="element.name" class="border-b-0 lg:w-6 before:hidden hidden lg:table-cell">
|
||||||
<UserAvatar :username="element.name" class="w-24 h-24 mx-auto lg:w-6 lg:h-6" />
|
<UserAvatar :username="element.name" class="w-24 h-24 mx-auto lg:w-6 lg:h-6" />
|
||||||
|
</td> -->
|
||||||
|
<td data-label="First Name">
|
||||||
|
<!-- {{ element.first_name }} -->
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="element.first_name"
|
||||||
|
type="text" :is-read-only="element.status==true"
|
||||||
|
placeholder="[FIRST NAME]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="errors && Array.isArray(errors[`${relation}.${index}.first_name`])"
|
||||||
|
>
|
||||||
|
{{ errors[`${relation}.${index}.first_name`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
</td>
|
</td>
|
||||||
<td data-label="Name">
|
<td data-label="Last Name">
|
||||||
{{ element.name }}
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="element.last_name"
|
||||||
|
type="text" :is-read-only="element.status==true"
|
||||||
|
placeholder="[LAST NAME]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="errors && Array.isArray(errors[`${relation}.${index}.last_name`])"
|
||||||
|
>
|
||||||
|
{{ errors[`${relation}.${index}.last_name`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
</td>
|
</td>
|
||||||
<td data-label="Email">
|
<td data-label="Email">
|
||||||
{{ element.email }}
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="element.email"
|
||||||
|
type="text" :is-read-only="element.status==true"
|
||||||
|
placeholder="[EMAIL]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="errors && Array.isArray(errors[`${relation}.${index}.email`])"
|
||||||
|
>
|
||||||
|
{{ errors[`${relation}.${index}.email`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="Object.keys(contributortypes).length">
|
<td v-if="Object.keys(contributortypes).length">
|
||||||
<!-- <select type="text" v-model="element.pivot.contributor_type">
|
<!-- <select type="text" v-model="element.pivot.contributor_type">
|
||||||
|
@ -178,9 +225,9 @@ const removeAuthor = (key) => {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="text-red-400 text-sm"
|
class="text-red-400 text-sm"
|
||||||
v-if="errors && Array.isArray(errors[`contributors.${index}.pivot_contributor_type`])"
|
v-if="errors && Array.isArray(errors[`${relation}.${index}.pivot_contributor_type`])"
|
||||||
>
|
>
|
||||||
{{ errors[`contributors.${index}.pivot_contributor_type`].join(', ') }}
|
{{ errors[`${relation}.${index}.pivot_contributor_type`].join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -130,13 +130,14 @@ export interface Description {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Person {
|
export interface Person {
|
||||||
id: number;
|
id?: number;
|
||||||
name: string;
|
name?: string;
|
||||||
email: string;
|
email: string;
|
||||||
name_type: string;
|
name_type: string;
|
||||||
identifier_orcid: string;
|
identifier_orcid: string;
|
||||||
datasetCount: string;
|
datasetCount?: string;
|
||||||
created_at: string;
|
created_at?: string;
|
||||||
|
status: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IErrorMessage {
|
interface IErrorMessage {
|
||||||
|
|
116
resources/js/Pages/Admin/License/Index.vue
Normal file
116
resources/js/Pages/Admin/License/Index.vue
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Head, usePage } from '@inertiajs/vue3';
|
||||||
|
import { mdiAccountKey, mdiSquareEditOutline, mdiAlertBoxOutline } from '@mdi/js';
|
||||||
|
import { computed, ComputedRef } from 'vue';
|
||||||
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
|
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
|
import NotificationBar from '@/Components/NotificationBar.vue';
|
||||||
|
// import Pagination from '@/Components/Admin/Pagination.vue';
|
||||||
|
// import Sort from '@/Components/Admin/Sort.vue';
|
||||||
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
// import CardBoxModal from '@/Components/CardBoxModal.vue';
|
||||||
|
|
||||||
|
// const isModalDangerActive = ref(false);
|
||||||
|
// const deleteId = ref();
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
licenses: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
// filters: {
|
||||||
|
// type: Object,
|
||||||
|
// default: () => ({}),
|
||||||
|
// },
|
||||||
|
can: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const flash: ComputedRef<any> = computed(() => {
|
||||||
|
// let test = usePage();
|
||||||
|
// console.log(test);
|
||||||
|
return usePage().props.flash;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<LayoutAuthenticated>
|
||||||
|
|
||||||
|
<Head title="Licenses" />
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Licenses" main>
|
||||||
|
<!-- <BaseButton
|
||||||
|
v-if="can.create"
|
||||||
|
:route-name="stardust.route('settings.role.create')"
|
||||||
|
:icon="mdiPlus"
|
||||||
|
label="Add"
|
||||||
|
color="info"
|
||||||
|
rounded-full
|
||||||
|
small
|
||||||
|
/> -->
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
<NotificationBar v-if="flash.message" color="success" :icon="mdiAlertBoxOutline">
|
||||||
|
{{ flash.message }}
|
||||||
|
</NotificationBar>
|
||||||
|
<CardBox class="mb-6" has-table>
|
||||||
|
</CardBox>
|
||||||
|
<CardBox class="mb-6" has-form-data>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<!-- <Sort label="Name" attribute="name" /> -->
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<!-- <Sort label="Sort Order" attribute="sort_order" /> -->
|
||||||
|
Sort Order
|
||||||
|
</th>
|
||||||
|
<th v-if="can.edit">Actions</th>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="license in licenses" :key="license.id">
|
||||||
|
<td data-label="Name">
|
||||||
|
<!-- <Link
|
||||||
|
:href="stardust.route('settings.role.show', [role.id])"
|
||||||
|
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400"
|
||||||
|
>
|
||||||
|
{{ license.name }}
|
||||||
|
</Link> -->
|
||||||
|
{{ license.name }}
|
||||||
|
</td>
|
||||||
|
<td data-label="Description">
|
||||||
|
{{ license.sort_order }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td v-if="can.edit" class="before:hidden lg:w-1 whitespace-nowrap">
|
||||||
|
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
||||||
|
<BaseButton v-if="license.active"
|
||||||
|
:route-name="stardust.route('settings.license.down', [license.id])"
|
||||||
|
color="warning" :icon="mdiSquareEditOutline" label="deactivate" small />
|
||||||
|
<BaseButton v-else :route-name="stardust.route('settings.license.up', [license.id])"
|
||||||
|
color="success" :icon="mdiSquareEditOutline" label="activate" small />
|
||||||
|
</BaseButtons>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- <div class="py-4">
|
||||||
|
<Pagination v-bind:data="roles.meta" />
|
||||||
|
</div> -->
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</LayoutAuthenticated>
|
||||||
|
</template>
|
118
resources/js/Pages/Admin/Mimetype/Index.vue
Normal file
118
resources/js/Pages/Admin/Mimetype/Index.vue
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Head, usePage } from '@inertiajs/vue3';
|
||||||
|
import { mdiAccountKey, mdiSquareEditOutline, mdiAlertBoxOutline } from '@mdi/js';
|
||||||
|
import { computed, ComputedRef } from 'vue';
|
||||||
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
|
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
|
import NotificationBar from '@/Components/NotificationBar.vue';
|
||||||
|
// import Pagination from '@/Components/Admin/Pagination.vue';
|
||||||
|
// import Sort from '@/Components/Admin/Sort.vue';
|
||||||
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
// import CardBoxModal from '@/Components/CardBoxModal.vue';
|
||||||
|
|
||||||
|
// const isModalDangerActive = ref(false);
|
||||||
|
// const deleteId = ref();
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
mimetypes: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
// filters: {
|
||||||
|
// type: Object,
|
||||||
|
// default: () => ({}),
|
||||||
|
// },
|
||||||
|
can: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const flash: ComputedRef<any> = computed(() => {
|
||||||
|
// let test = usePage();
|
||||||
|
// console.log(test);
|
||||||
|
return usePage().props.flash;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<LayoutAuthenticated>
|
||||||
|
|
||||||
|
<Head title="Mime Types" />
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Mime Types" main>
|
||||||
|
<!-- <BaseButton
|
||||||
|
v-if="can.create"
|
||||||
|
:route-name="stardust.route('settings.role.create')"
|
||||||
|
:icon="mdiPlus"
|
||||||
|
label="Add"
|
||||||
|
color="info"
|
||||||
|
rounded-full
|
||||||
|
small
|
||||||
|
/> -->
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
<NotificationBar v-if="flash.message" color="success" :icon="mdiAlertBoxOutline">
|
||||||
|
{{ flash.message }}
|
||||||
|
</NotificationBar>
|
||||||
|
<CardBox class="mb-6" has-table>
|
||||||
|
</CardBox>
|
||||||
|
<CardBox class="mb-6" has-form-data>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<!-- <Sort label="Name" attribute="name" /> -->
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<!-- <Sort label="Sort Order" attribute="sort_order" /> -->
|
||||||
|
Status
|
||||||
|
</th>
|
||||||
|
<th v-if="can.edit">Actions</th>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="mimetype in mimetypes" :key="mimetype.id">
|
||||||
|
<td data-label="Name">
|
||||||
|
<!-- <Link
|
||||||
|
:href="stardust.route('settings.role.show', [role.id])"
|
||||||
|
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400"
|
||||||
|
>
|
||||||
|
{{ license.name }}
|
||||||
|
</Link> -->
|
||||||
|
{{ mimetype.name }}
|
||||||
|
</td>
|
||||||
|
<td data-label="Status">
|
||||||
|
<template v-if="mimetype.enabled">Active</template>
|
||||||
|
<template v-else>Inactive</template>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td v-if="can.edit" class="before:hidden lg:w-1 whitespace-nowrap">
|
||||||
|
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
||||||
|
<BaseButton v-if="mimetype.enabled"
|
||||||
|
:route-name="stardust.route('settings.mimetype.down', [mimetype.id])"
|
||||||
|
color="warning" :icon="mdiSquareEditOutline" label="disable" small />
|
||||||
|
<BaseButton v-else
|
||||||
|
:route-name="stardust.route('settings.mimetype.up', [mimetype.id])" color="success"
|
||||||
|
:icon="mdiSquareEditOutline" label="enable" small />
|
||||||
|
</BaseButtons>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- <div class="py-4">
|
||||||
|
<Pagination v-bind:data="roles.meta" />
|
||||||
|
</div> -->
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</LayoutAuthenticated>
|
||||||
|
</template>
|
|
@ -373,6 +373,11 @@ const submit = async () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addNewAuthor = () => {
|
||||||
|
let newAuthor = { status: false, first_name: '', last_name: '', email: '', academic_title: '', identifier_orcid: '', name_type: 'Personal' };
|
||||||
|
form.authors.push(newAuthor);
|
||||||
|
};
|
||||||
|
|
||||||
const addTitle = () => {
|
const addTitle = () => {
|
||||||
let newTitle: Title = { value: '', language: '', type: '' };
|
let newTitle: Title = { value: '', language: '', type: '' };
|
||||||
//this.dataset.files.push(uploadedFiles[i]);
|
//this.dataset.files.push(uploadedFiles[i]);
|
||||||
|
@ -463,10 +468,11 @@ Removes a selected keyword
|
||||||
Mit dem Setzen des Hakens bestätige ich hiermit
|
Mit dem Setzen des Hakens bestätige ich hiermit
|
||||||
<ul class="list-decimal">
|
<ul class="list-decimal">
|
||||||
<li>
|
<li>
|
||||||
die Data Policy von Tethys RDR sowie die Terms & Conditions von Tethys gelesen und verstanden zu haben (<a
|
die Data Policy von Tethys RDR sowie die Terms & Conditions von Tethys gelesen und verstanden zu haben
|
||||||
href="/docs/HandbuchTethys.pdf" target="_blank">siehe hier</a>)
|
(<a href="/docs/HandbuchTethys.pdf" target="_blank">siehe hier</a>)
|
||||||
</li>
|
</li>
|
||||||
<li>das Einverständnis aller Co-Autoren über die bevorstehende Datenpublikation schriftlich eingeholt zu haben
|
<li>das Einverständnis aller Co-Autoren über die bevorstehende Datenpublikation schriftlich eingeholt zu
|
||||||
|
haben
|
||||||
</li>
|
</li>
|
||||||
<li>sowohl mit der Data Policy als auch mit den Terms & Conditions einverstanden zu sein</li>
|
<li>sowohl mit der Data Policy als auch mit den Terms & Conditions einverstanden zu sein</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -516,9 +522,8 @@ Removes a selected keyword
|
||||||
<div class="flex flex-col md:flex-row">
|
<div class="flex flex-col md:flex-row">
|
||||||
<FormField label="Language *" help="required: select dataset main language"
|
<FormField label="Language *" help="required: select dataset main language"
|
||||||
:class="{ 'text-red-400': errors.language }" class="w-full mx-2 flex-1">
|
:class="{ 'text-red-400': errors.language }" class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="language" :type="'select'"
|
<FormControl required v-model="language" :type="'select'" placeholder="[Enter Language]"
|
||||||
placeholder="[Enter Language]" :errors="form.errors.language"
|
:errors="form.errors.language" :options="{ de: 'de', en: 'en' }">
|
||||||
:options="{ de: 'de', en: 'en' }">
|
|
||||||
<div class="text-red-400 text-sm" v-if="form.errors.language">
|
<div class="text-red-400 text-sm" v-if="form.errors.language">
|
||||||
{{ form.errors.language.join(', ') }}
|
{{ form.errors.language.join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -528,7 +533,8 @@ Removes a selected keyword
|
||||||
|
|
||||||
<FormField label="Licenses" wrap-body :class="{ 'text-red-400': form.errors.licenses }"
|
<FormField label="Licenses" wrap-body :class="{ 'text-red-400': form.errors.licenses }"
|
||||||
class="mt-8 w-full mx-2 flex-1">
|
class="mt-8 w-full mx-2 flex-1">
|
||||||
<FormCheckRadioGroup v-model="form.licenses" name="roles" is-column :options="props.licenses" />
|
<FormCheckRadioGroup v-model="form.licenses" name="roles" is-column
|
||||||
|
:options="props.licenses" />
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<!-- <label for="rights">
|
<!-- <label for="rights">
|
||||||
|
@ -557,8 +563,8 @@ Removes a selected keyword
|
||||||
<div class="flex flex-col md:flex-row">
|
<div class="flex flex-col md:flex-row">
|
||||||
<FormField label="Dataset Type *" help="required: dataset type"
|
<FormField label="Dataset Type *" help="required: dataset type"
|
||||||
:class="{ 'text-red-400': form.errors.type }" class="w-full mx-2 flex-1">
|
:class="{ 'text-red-400': form.errors.type }" class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.type" :type="'select'" placeholder="-- select type --"
|
<FormControl required v-model="form.type" :type="'select'"
|
||||||
:errors="errors.type" :options="doctypes">
|
placeholder="-- select type --" :errors="errors.type" :options="doctypes">
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
v-if="form.errors.type && Array.isArray(form.errors.type)">
|
v-if="form.errors.type && Array.isArray(form.errors.type)">
|
||||||
{{ form.errors.type.join(', ') }}
|
{{ form.errors.type.join(', ') }}
|
||||||
|
@ -568,7 +574,8 @@ Removes a selected keyword
|
||||||
<!-- <div class="w-full mx-2 flex-1 svelte-1l8159u"></div> -->
|
<!-- <div class="w-full mx-2 flex-1 svelte-1l8159u"></div> -->
|
||||||
<!-- Creating Corporation -->
|
<!-- Creating Corporation -->
|
||||||
<FormField label="Creating Corporation *"
|
<FormField label="Creating Corporation *"
|
||||||
:class="{ 'text-red-400': form.errors.creating_corporation }" class="w-full mx-2 flex-1">
|
:class="{ 'text-red-400': form.errors.creating_corporation }"
|
||||||
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.creating_corporation" type="text"
|
<FormControl required v-model="form.creating_corporation" type="text"
|
||||||
placeholder="[enter creating corporation]" :is-read-only="true">
|
placeholder="[enter creating corporation]" :is-read-only="true">
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
|
@ -586,7 +593,8 @@ Removes a selected keyword
|
||||||
<!-- <div class="py-6 border-t border-gray-100 dark:border-slate-800"> -->
|
<!-- <div class="py-6 border-t border-gray-100 dark:border-slate-800"> -->
|
||||||
<div class="flex flex-col md:flex-row">
|
<div class="flex flex-col md:flex-row">
|
||||||
<FormField label="Main Title *" help="required: main title"
|
<FormField label="Main Title *" help="required: main title"
|
||||||
:class="{ 'text-red-400': form.errors['titles.0.value'] }" class="w-full mx-2 flex-1">
|
:class="{ 'text-red-400': form.errors['titles.0.value'] }"
|
||||||
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.titles[0].value" type="text"
|
<FormControl required v-model="form.titles[0].value" type="text"
|
||||||
placeholder="[enter main title]">
|
placeholder="[enter main title]">
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
|
@ -718,8 +726,9 @@ Removes a selected keyword
|
||||||
<FormField label="Description Language*"
|
<FormField label="Description Language*"
|
||||||
:class="{ 'text-red-400': form.errors[`titdescriptionsles.${index}.language`] }"
|
:class="{ 'text-red-400': form.errors[`titdescriptionsles.${index}.language`] }"
|
||||||
class="w-full mx-2 flex-1">
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.descriptions[index].language" type="select"
|
<FormControl required v-model="form.descriptions[index].language"
|
||||||
:options="{ de: 'de', en: 'en' }" placeholder="[select title language]">
|
type="select" :options="{ de: 'de', en: 'en' }"
|
||||||
|
placeholder="[select title language]">
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
v-if="form.errors && Array.isArray(form.errors[`descriptions.${index}.language`])">
|
v-if="form.errors && Array.isArray(form.errors[`descriptions.${index}.language`])">
|
||||||
{{ form.errors[`descriptions.${index}.language`].join(', ') }}
|
{{ form.errors[`descriptions.${index}.language`].join(', ') }}
|
||||||
|
@ -736,10 +745,16 @@ Removes a selected keyword
|
||||||
<SearchAutocomplete source="/api/persons" :response-property="'first_name'"
|
<SearchAutocomplete source="/api/persons" :response-property="'first_name'"
|
||||||
placeholder="search in person table...." v-on:person="onAddAuthor"></SearchAutocomplete>
|
placeholder="search in person table...." v-on:person="onAddAuthor"></SearchAutocomplete>
|
||||||
|
|
||||||
<TablePersons :persons="form.authors" v-if="form.authors.length > 0" />
|
<TablePersons :errors="form.errors" :persons="form.authors" :relation="'authors'" v-if="form.authors.length > 0" />
|
||||||
<div class="text-red-400 text-sm" v-if="errors.authors && Array.isArray(errors.authors)">
|
<div class="text-red-400 text-sm" v-if="errors.authors && Array.isArray(errors.authors)">
|
||||||
{{ errors.authors.join(', ') }}
|
{{ errors.authors.join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="w-full md:w-1/2">
|
||||||
|
<label class="block" for="additionalCreators">Add additional creator(s) if creator is
|
||||||
|
not in database</label>
|
||||||
|
<button class="bg-blue-500 text-white py-2 px-4 rounded-sm"
|
||||||
|
@click.prevent="addNewAuthor()">+</button>
|
||||||
|
</div>
|
||||||
</CardBox>
|
</CardBox>
|
||||||
|
|
||||||
<!-- contributors -->
|
<!-- contributors -->
|
||||||
|
@ -748,7 +763,7 @@ Removes a selected keyword
|
||||||
placeholder="search in person table...." v-on:person="onAddContributor">
|
placeholder="search in person table...." v-on:person="onAddContributor">
|
||||||
</SearchAutocomplete>
|
</SearchAutocomplete>
|
||||||
|
|
||||||
<TablePersons :persons="form.contributors" v-if="form.contributors.length > 0"
|
<TablePersons :persons="form.contributors" :relation="'contributors'" v-if="form.contributors.length > 0"
|
||||||
:contributortypes="contributorTypes" :errors="form.errors" />
|
:contributortypes="contributorTypes" :errors="form.errors" />
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
v-if="form.errors.contributors && Array.isArray(form.errors.contributors)">
|
v-if="form.errors.contributors && Array.isArray(form.errors.contributors)">
|
||||||
|
@ -772,8 +787,8 @@ Removes a selected keyword
|
||||||
|
|
||||||
<FormField label="Embargo Date.." help="embargo date is optional"
|
<FormField label="Embargo Date.." help="embargo date is optional"
|
||||||
:class="{ 'text-red-400': errors.embargo_date }" class="w-full mx-2 flex-1">
|
:class="{ 'text-red-400': errors.embargo_date }" class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.embargo_date" :type="'date'" placeholder="date('y-m-d')"
|
<FormControl required v-model="form.embargo_date" :type="'date'"
|
||||||
:errors="form.errors.embargo_date">
|
placeholder="date('y-m-d')" :errors="form.errors.embargo_date">
|
||||||
<div class="text-red-400 text-sm" v-if="form.errors.embargo_date">
|
<div class="text-red-400 text-sm" v-if="form.errors.embargo_date">
|
||||||
{{ form.errors.embargo_date.join(', ') }}
|
{{ form.errors.embargo_date.join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -790,7 +805,8 @@ Removes a selected keyword
|
||||||
|
|
||||||
<div class="flex flex-col md:flex-row">
|
<div class="flex flex-col md:flex-row">
|
||||||
<!-- x min and max -->
|
<!-- x min and max -->
|
||||||
<FormField label="Coverage X Min" :class="{ 'text-red-400': form.errors['coverage.x_min'] }"
|
<FormField label="Coverage X Min"
|
||||||
|
:class="{ 'text-red-400': form.errors['coverage.x_min'] }"
|
||||||
class="w-full mx-2 flex-1">
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.coverage.x_min" type="text"
|
<FormControl required v-model="form.coverage.x_min" type="text"
|
||||||
placeholder="[enter x_min]">
|
placeholder="[enter x_min]">
|
||||||
|
@ -800,7 +816,8 @@ Removes a selected keyword
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Coverage X Max" :class="{ 'text-red-400': form.errors['coverage.x_max'] }"
|
<FormField label="Coverage X Max"
|
||||||
|
:class="{ 'text-red-400': form.errors['coverage.x_max'] }"
|
||||||
class="w-full mx-2 flex-1">
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.coverage.x_max" type="text"
|
<FormControl required v-model="form.coverage.x_max" type="text"
|
||||||
placeholder="[enter x_max]">
|
placeholder="[enter x_max]">
|
||||||
|
@ -811,7 +828,8 @@ Removes a selected keyword
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormField>
|
</FormField>
|
||||||
<!-- y min and max -->
|
<!-- y min and max -->
|
||||||
<FormField label="Coverage Y Min" :class="{ 'text-red-400': form.errors['coverage.y_min'] }"
|
<FormField label="Coverage Y Min"
|
||||||
|
:class="{ 'text-red-400': form.errors['coverage.y_min'] }"
|
||||||
class="w-full mx-2 flex-1">
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.coverage.y_min" type="text"
|
<FormControl required v-model="form.coverage.y_min" type="text"
|
||||||
placeholder="[enter y_min]">
|
placeholder="[enter y_min]">
|
||||||
|
@ -821,7 +839,8 @@ Removes a selected keyword
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Coverage Y Max" :class="{ 'text-red-400': form.errors['coverage.y_max'] }"
|
<FormField label="Coverage Y Max"
|
||||||
|
:class="{ 'text-red-400': form.errors['coverage.y_max'] }"
|
||||||
class="w-full mx-2 flex-1">
|
class="w-full mx-2 flex-1">
|
||||||
<FormControl required v-model="form.coverage.y_max" type="text"
|
<FormControl required v-model="form.coverage.y_max" type="text"
|
||||||
placeholder="[enter y_max]">
|
placeholder="[enter y_max]">
|
||||||
|
@ -956,8 +975,8 @@ Removes a selected keyword
|
||||||
<td data-label="Reference Value">
|
<td data-label="Reference Value">
|
||||||
<!-- <input name="Reference Value" class="form-control"
|
<!-- <input name="Reference Value" class="form-control"
|
||||||
placeholder="[VALUE]" v-model="item.value" /> -->
|
placeholder="[VALUE]" v-model="item.value" /> -->
|
||||||
<FormControl required v-model="item.value" :type="'text'" placeholder="[VALUE]"
|
<FormControl required v-model="item.value" :type="'text'"
|
||||||
:errors="form.errors.embargo_date">
|
placeholder="[VALUE]" :errors="form.errors.embargo_date">
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
v-if="form.errors[`references.${index}.value`] && Array.isArray(form.errors[`references.${index}.value`])">
|
v-if="form.errors[`references.${index}.value`] && Array.isArray(form.errors[`references.${index}.value`])">
|
||||||
{{ form.errors[`references.${index}.value`].join(', ') }}
|
{{ form.errors[`references.${index}.value`].join(', ') }}
|
||||||
|
@ -980,8 +999,8 @@ Removes a selected keyword
|
||||||
['placeholder' => '[relationType]', 'v-model' => 'item.relation',
|
['placeholder' => '[relationType]', 'v-model' => 'item.relation',
|
||||||
'data-vv-scope' => 'step-2'])
|
'data-vv-scope' => 'step-2'])
|
||||||
!!} -->
|
!!} -->
|
||||||
<FormControl required v-model="form.references[index].relation" type="select"
|
<FormControl required v-model="form.references[index].relation"
|
||||||
:options="relationTypes" placeholder="[relation type]">
|
type="select" :options="relationTypes" placeholder="[relation type]">
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
v-if="Array.isArray(form.errors[`references.${index}.relation`])">
|
v-if="Array.isArray(form.errors[`references.${index}.relation`])">
|
||||||
{{ form.errors[`references.${index}.relation`].join(', ') }}
|
{{ form.errors[`references.${index}.relation`].join(', ') }}
|
||||||
|
@ -1036,7 +1055,8 @@ Removes a selected keyword
|
||||||
|
|
||||||
<FileUploadComponent :files="form.files"></FileUploadComponent>
|
<FileUploadComponent :files="form.files"></FileUploadComponent>
|
||||||
|
|
||||||
<div class="text-red-400 text-sm" v-if="form.errors['file'] && Array.isArray(form.errors['file'])">
|
<div class="text-red-400 text-sm"
|
||||||
|
v-if="form.errors['file'] && Array.isArray(form.errors['file'])">
|
||||||
{{ form.errors['file'].join(', ') }}
|
{{ form.errors['file'].join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-red-400 text-sm"
|
<div class="text-red-400 text-sm"
|
||||||
|
@ -1068,7 +1088,8 @@ Removes a selected keyword
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<progress v-if="form.progress" :value="form.progress.percentage" max="100">{{ form.progress.percentage
|
<progress v-if="form.progress" :value="form.progress.percentage" max="100">{{
|
||||||
|
form.progress.percentage
|
||||||
}}%</progress>
|
}}%</progress>
|
||||||
</template>
|
</template>
|
||||||
</CardBox>
|
</CardBox>
|
||||||
|
|
|
@ -10,6 +10,8 @@ import {
|
||||||
mdiLock,
|
mdiLock,
|
||||||
mdiFormatListGroup,
|
mdiFormatListGroup,
|
||||||
mdiShieldCrownOutline,
|
mdiShieldCrownOutline,
|
||||||
|
mdiLicense,
|
||||||
|
mdiFileDocument,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
|
@ -72,6 +74,18 @@ export default [
|
||||||
label: 'Roles',
|
label: 'Roles',
|
||||||
roles: ['administrator'],
|
roles: ['administrator'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
route: 'settings.mimetype.index',
|
||||||
|
icon: mdiFileDocument,
|
||||||
|
label: 'Mime Types',
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
route: 'settings.license.index',
|
||||||
|
icon: mdiLicense,
|
||||||
|
label: 'Licenses',
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ import AuthController from '#controllers/Http/Auth/AuthController';
|
||||||
import UserController from '#controllers/Http/Auth/UserController';
|
import UserController from '#controllers/Http/Auth/UserController';
|
||||||
import AdminuserController from '#controllers/Http/Admin/AdminuserController';
|
import AdminuserController from '#controllers/Http/Admin/AdminuserController';
|
||||||
import RoleController from '#controllers/Http/Admin/RoleController';
|
import RoleController from '#controllers/Http/Admin/RoleController';
|
||||||
|
import LicenseController from '#controllers/Http/Admin/LicenseController';
|
||||||
|
import MimetypeController from '#controllers/Http/Admin/MimetypeController';
|
||||||
|
|
||||||
import DatasetController from '#app/Controllers/Http/Submitter/DatasetController';
|
import DatasetController from '#app/Controllers/Http/Submitter/DatasetController';
|
||||||
import PersonController from '#app/Controllers/Http/Submitter/PersonController';
|
import PersonController from '#app/Controllers/Http/Submitter/PersonController';
|
||||||
|
@ -160,6 +162,17 @@ router.group(() => {
|
||||||
// // .as('role.destroy')
|
// // .as('role.destroy')
|
||||||
// // .where('id', Route.matchers.number())
|
// // .where('id', Route.matchers.number())
|
||||||
// // .use(middleware.can(['user-delete']));
|
// // .use(middleware.can(['user-delete']));
|
||||||
|
|
||||||
|
router.get('/license', [LicenseController, 'index']).as('license.index');
|
||||||
|
// router.get('/license/:id/edit', [LicenseController, 'edit']).as('license.edit').where('id', router.matchers.number()).use(middleware.can(['settings']));
|
||||||
|
router.get('/license/:id/down', [LicenseController, 'down']).as('license.down').where('id', router.matchers.number()).use(middleware.can(['settings']));
|
||||||
|
router.get('/license/:id/up', [LicenseController, 'up']).as('license.up').where('id', router.matchers.number()).use(middleware.can(['settings']));
|
||||||
|
|
||||||
|
router.get('/mimetype', [MimetypeController, 'index']).as('mimetype.index');
|
||||||
|
// router.get('/mimetype/:id/edit', [MimetypeController, 'edit']).as('mimetype.edit').where('id', router.matchers.number()).use(middleware.can(['settings']));
|
||||||
|
router.get('/mimetype/:id/down', [MimetypeController, 'down']).as('mimetype.down').where('id', router.matchers.number()).use(middleware.can(['settings']));
|
||||||
|
router.get('/mimetype/:id/up', [MimetypeController, 'up']).as('mimetype.up').where('id', router.matchers.number()).use(middleware.can(['settings']));
|
||||||
|
|
||||||
})
|
})
|
||||||
.prefix('admin')
|
.prefix('admin')
|
||||||
.as('settings')
|
.as('settings')
|
||||||
|
|
51
start/rules/file_length.ts
Normal file
51
start/rules/file_length.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Preloaded File - node ace make:preload rules/translatedLanguage
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|*/
|
||||||
|
|
||||||
|
import { FieldContext } from '@vinejs/vine/types';
|
||||||
|
import vine from '@vinejs/vine';
|
||||||
|
// import { VineString } from '@vinejs/vine';
|
||||||
|
import { VineMultipartFile, isBodyParserFile } from '#providers/vinejs_provider';
|
||||||
|
import type { MultipartFile } from '@adonisjs/core/bodyparser';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options accepted by the unique rule
|
||||||
|
*/
|
||||||
|
// type Options = {
|
||||||
|
// mainLanguageField: string;
|
||||||
|
// typeField: string;
|
||||||
|
// };
|
||||||
|
type Options = {
|
||||||
|
// size: string | number;
|
||||||
|
// extnames: string[];
|
||||||
|
clientNameSizeLimit: number
|
||||||
|
};
|
||||||
|
|
||||||
|
async function filenameLength(file: VineMultipartFile | unknown, options: Options, field: FieldContext) {
|
||||||
|
// if (typeof value !== 'string' && typeof value != 'number') {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
if (!isBodyParserFile(file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const validatedFile = file as MultipartFile;
|
||||||
|
|
||||||
|
if (validatedFile.clientName.length > options.clientNameSizeLimit) {
|
||||||
|
|
||||||
|
field.report(`Filename length should be less or equal than ${options.clientNameSizeLimit} characters`, 'filenameLength', field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const filenameLengthRule = vine.createRule(filenameLength);
|
||||||
|
|
||||||
|
declare module '#providers/vinejs_provider' {
|
||||||
|
interface VineMultipartFile {
|
||||||
|
filenameLength(options: Options): this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VineMultipartFile.macro('filenameLength', function (this: VineMultipartFile, options: Options) {
|
||||||
|
return this.use(filenameLengthRule(options));
|
||||||
|
});
|
|
@ -30,7 +30,7 @@ async function translatedLanguage(value: unknown, options: Options, field: Field
|
||||||
if (typeValue === 'Translated') {
|
if (typeValue === 'Translated') {
|
||||||
if (value === mainLanguage) {
|
if (value === mainLanguage) {
|
||||||
// report thattranlated language field is same as main language field of dataset
|
// report thattranlated language field is same as main language field of dataset
|
||||||
field.report('The tranlated {{ field }} hast the same language seted as dataset language', 'translatedLanguage', field);
|
field.report('The tranlated {{ field }} hast the same language as dataset language', 'translatedLanguage', field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
64
start/rules/unique_person.ts
Normal file
64
start/rules/unique_person.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Preloaded File - node ace make:preload rules/uniquePerson
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|*/
|
||||||
|
|
||||||
|
import { FieldContext } from '@vinejs/vine/types';
|
||||||
|
import db from '@adonisjs/lucid/services/db';
|
||||||
|
import vine from '@vinejs/vine';
|
||||||
|
import { VineString, VineNumber } from '@vinejs/vine';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options accepted by the unique rule
|
||||||
|
*/
|
||||||
|
type Options = {
|
||||||
|
table: string;
|
||||||
|
column: string;
|
||||||
|
// whereNot?: ((field: FieldContext) => string);
|
||||||
|
idField: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
async function isUniquePerson(value: unknown, options: Options, field: FieldContext) {
|
||||||
|
if (typeof value !== 'string' && typeof value != 'number') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let ignoreId: string | undefined;
|
||||||
|
// if (options.whereNot) {
|
||||||
|
// ignoreId = options.whereNot(field);
|
||||||
|
// }
|
||||||
|
const idValue = vine.helpers.getNestedValue(options.idField, field); //'Main' or 'Translated'
|
||||||
|
|
||||||
|
const builder = db.from(options.table).select(options.column).where(options.column, value);
|
||||||
|
// if existent id, exclide it from validating
|
||||||
|
if (idValue) {
|
||||||
|
builder.whereNot('id', '=', idValue);
|
||||||
|
}
|
||||||
|
const result = await builder.first();
|
||||||
|
if (result) {
|
||||||
|
// report that value is NOT unique
|
||||||
|
field.report('The {{ field }} field is not unique', 'isUnique', field);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isUniquePersonRule = vine.createRule(isUniquePerson);
|
||||||
|
|
||||||
|
|
||||||
|
declare module '@vinejs/vine' {
|
||||||
|
interface VineString {
|
||||||
|
isUniquePerson(options: Options): this;
|
||||||
|
}
|
||||||
|
interface VineNumber {
|
||||||
|
isUniquePerson(options: Options): this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VineString.macro('isUniquePerson', function (this: VineString, options: Options) {
|
||||||
|
return this.use(isUniquePersonRule(options));
|
||||||
|
});
|
||||||
|
VineNumber.macro('isUniquePerson', function (this: VineNumber, options: Options) {
|
||||||
|
return this.use(isUniquePersonRule(options));
|
||||||
|
});
|
|
@ -302,18 +302,18 @@ Encore.addLoader({
|
||||||
// vue$: 'vue/dist/vue.runtime.esm-bundler.js',
|
// vue$: 'vue/dist/vue.runtime.esm-bundler.js',
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// Encore.addLoader(babelLoader)
|
Encore.addLoader(babelLoader)
|
||||||
Encore.enableTypeScriptLoader(config => {
|
// Encore.enableTypeScriptLoader(config => {
|
||||||
// Loader-specific options
|
// // Loader-specific options
|
||||||
config.configFile = 'resources/js/tsconfig.json';
|
// config.configFile = 'resources/js/tsconfig.json';
|
||||||
config.appendTsSuffixTo = [/\.vue$/];
|
// config.appendTsSuffixTo = [/\.vue$/];
|
||||||
config.transpileOnly = true;
|
// config.transpileOnly = true;
|
||||||
config.happyPackMode = false;
|
// config.happyPackMode = false;
|
||||||
}, {
|
// }, {
|
||||||
// Directly change the exclude rule
|
// // Directly change the exclude rule
|
||||||
exclude: /node_modules/,
|
// exclude: /node_modules/,
|
||||||
|
|
||||||
})
|
// })
|
||||||
.addAliases({
|
.addAliases({
|
||||||
'@': join(__dirname, 'resources/js'),
|
'@': join(__dirname, 'resources/js'),
|
||||||
'vue$': 'vue/dist/vue.runtime.esm-bundler.js',
|
'vue$': 'vue/dist/vue.runtime.esm-bundler.js',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user