forked from geolba/tethys.backend
- second commit
This commit is contained in:
parent
4fc3bb0a01
commit
59a99ff3c8
|
@ -8,7 +8,7 @@ README.md
|
||||||
# Docker stuff
|
# Docker stuff
|
||||||
.dockerignore
|
.dockerignore
|
||||||
Dockerfile*
|
Dockerfile*
|
||||||
|
docker-compose.yml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
11
.prettierrc
Normal file
11
.prettierrc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"trailingComma": "all",
|
||||||
|
"tabWidth": 4,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"useTabs": false,
|
||||||
|
"quoteProps": "consistent",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "always",
|
||||||
|
"printWidth": 140
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ FROM base AS production
|
||||||
|
|
||||||
# Copy package.* to the working directory with active user
|
# Copy package.* to the working directory with active user
|
||||||
COPY --chown=node:node ./package*.json ./
|
COPY --chown=node:node ./package*.json ./
|
||||||
# We run NPM CI to install the exact versions of dependencies
|
# We run NPM CI to install the exact versions of production dependencies
|
||||||
RUN npm ci --omit=dev
|
RUN npm ci --omit=dev
|
||||||
# Copy files to the working directory from the build folder the user
|
# Copy files to the working directory from the build folder the user
|
||||||
COPY --chown=node:node --from=build /home/node/app/build .
|
COPY --chown=node:node --from=build /home/node/app/build .
|
||||||
|
|
|
@ -117,7 +117,7 @@ export default class UsersController {
|
||||||
const roles = await Role.query().pluck('name', 'id');
|
const roles = await Role.query().pluck('name', 'id');
|
||||||
// const userHasRoles = user.roles;
|
// const userHasRoles = user.roles;
|
||||||
const userHasRoles = await user.related('roles').query().orderBy('name').pluck('id');
|
const userHasRoles = await user.related('roles').query().orderBy('name').pluck('id');
|
||||||
|
// let test = Object.keys(userHasRoles).map((key) => userHasRoles[key]);
|
||||||
return inertia.render('Admin/User/Edit', {
|
return inertia.render('Admin/User/Edit', {
|
||||||
roles: roles,
|
roles: roles,
|
||||||
user: user,
|
user: user,
|
||||||
|
|
|
@ -4,20 +4,34 @@ import Person from 'App/Models/Person';
|
||||||
|
|
||||||
// node ace make:controller Author
|
// node ace make:controller Author
|
||||||
export default class AuthorsController {
|
export default class AuthorsController {
|
||||||
|
|
||||||
public async index({}: HttpContextContract) {
|
public async index({}: HttpContextContract) {
|
||||||
// select * from gba.persons
|
// select * from gba.persons
|
||||||
// where exists (select * from gba.documents inner join gba.link_documents_persons on "documents"."id" = "link_documents_persons"."document_id"
|
// where exists (select * from gba.documents inner join gba.link_documents_persons on "documents"."id" = "link_documents_persons"."document_id"
|
||||||
// where ("link_documents_persons"."role" = 'author') and ("persons"."id" = "link_documents_persons"."person_id"));
|
// where ("link_documents_persons"."role" = 'author') and ("persons"."id" = "link_documents_persons"."person_id"));
|
||||||
const authors = await Person.query()
|
const authors = await Person.query()
|
||||||
.whereHas('datasets', (dQuery) => {
|
.whereHas('datasets', (dQuery) => {
|
||||||
dQuery.wherePivot('role', 'author')
|
dQuery.wherePivot('role', 'author');
|
||||||
})
|
})
|
||||||
.withCount('datasets', (query) => {
|
.withCount('datasets', (query) => {
|
||||||
query.as('datasets_count')
|
query.as('datasets_count');
|
||||||
});
|
});
|
||||||
|
|
||||||
return authors;
|
return authors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async persons({ request }: HttpContextContract) {
|
||||||
|
const authors = Person.query().where('status', true);
|
||||||
|
|
||||||
|
if (request.input('filter')) {
|
||||||
|
// users = users.whereRaw('name like %?%', [request.input('search')])
|
||||||
|
const searchTerm = request.input('filter');
|
||||||
|
authors
|
||||||
|
.where('first_name', 'ilike', `%${searchTerm}%`)
|
||||||
|
.orWhere('last_name', 'like', `%${searchTerm}%`)
|
||||||
|
.orWhere('email', 'like', `%${searchTerm}%`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let persons = await authors;
|
||||||
|
return persons;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
162
app/Controllers/Http/Submitter/DatasetController.ts
Normal file
162
app/Controllers/Http/Submitter/DatasetController.ts
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
// import User from 'App/Models/User';
|
||||||
|
// import Role from 'App/Models/Role';
|
||||||
|
// import Database from '@ioc:Adonis/Lucid/Database';
|
||||||
|
import License from 'App/Models/License';
|
||||||
|
// import type { ModelQueryBuilderContract } from '@ioc:Adonis/Lucid/Orm';
|
||||||
|
// import CreateUserValidator from 'App/Validators/CreateUserValidator';
|
||||||
|
// import UpdateUserValidator from 'App/Validators/UpdateUserValidator';
|
||||||
|
// import { RenderResponse } from '@ioc:EidelLev/Inertia';
|
||||||
|
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator';
|
||||||
|
|
||||||
|
enum TitleTypes {
|
||||||
|
Main = 'Main',
|
||||||
|
Sub = 'Sub',
|
||||||
|
Alternative = 'Alternative',
|
||||||
|
Translated = 'Translated',
|
||||||
|
Other = 'Other',
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DescriptionTypes {
|
||||||
|
Abstract = 'Abstract',
|
||||||
|
Methods = 'Methods',
|
||||||
|
Series_information = 'Series_information',
|
||||||
|
Technical_info = 'Technical_info',
|
||||||
|
Translated = 'Translated',
|
||||||
|
Other = 'Other',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DatasetController {
|
||||||
|
public async create({ inertia }: HttpContextContract) {
|
||||||
|
const licenses = await License.query().select('id', 'name_long').pluck('name_long', 'id');
|
||||||
|
|
||||||
|
const doctypes = {
|
||||||
|
analysisdata: { label: 'Analysis', value: 'analysisdata' },
|
||||||
|
measurementdata: { label: 'Measurements', value: 'measurementdata' },
|
||||||
|
monitoring: 'Monitoring',
|
||||||
|
remotesensing: 'Remote Sensing',
|
||||||
|
gis: 'GIS',
|
||||||
|
models: 'Models',
|
||||||
|
mixedtype: 'Mixed Type',
|
||||||
|
};
|
||||||
|
|
||||||
|
// const titletypes = {
|
||||||
|
// Sub: 'Sub',
|
||||||
|
// Alternative: 'Alternative',
|
||||||
|
// Translated: 'Translated',
|
||||||
|
// Other: 'Other',
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const languages = await Database.from('languages').select('*').where('active', true);
|
||||||
|
return inertia.render('Submitter/Dataset/Create', {
|
||||||
|
licenses: licenses,
|
||||||
|
doctypes: doctypes,
|
||||||
|
titletypes: Object.values(TitleTypes).filter((x) => x.valueOf() !== 'Main'),
|
||||||
|
descriptiontypes: Object.values(DescriptionTypes).filter((x) => x.valueOf() !== 'Abstract'),
|
||||||
|
// descriptiontypes: DescriptionTypes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async firstStep({ request, response }: HttpContextContract) {
|
||||||
|
const newDatasetSchema = schema.create({
|
||||||
|
language: schema.string({ trim: true }, [
|
||||||
|
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||||
|
]),
|
||||||
|
licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
|
||||||
|
rights: schema.string([rules.equalTo('true')]),
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Step 2 - Validate request body against the schema
|
||||||
|
|
||||||
|
await request.validate({ schema: newDatasetSchema, messages: this.messages });
|
||||||
|
// console.log({ payload });
|
||||||
|
} catch (error) {
|
||||||
|
// Step 3 - Handle errors
|
||||||
|
// return response.badRequest(error.messages);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return response.redirect().back();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async secondStep({ request, response }: HttpContextContract) {
|
||||||
|
const newDatasetSchema = schema.create({
|
||||||
|
language: schema.string({ trim: true }, [
|
||||||
|
rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores
|
||||||
|
]),
|
||||||
|
licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset
|
||||||
|
type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||||
|
creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||||
|
titles: schema.array([rules.minLength(1)]).members(
|
||||||
|
schema.object().members({
|
||||||
|
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||||
|
type: schema.enum(Object.values(TitleTypes)),
|
||||||
|
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
descriptions: schema.array([rules.minLength(1)]).members(
|
||||||
|
schema.object().members({
|
||||||
|
value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]),
|
||||||
|
type: schema.enum(Object.values(DescriptionTypes)),
|
||||||
|
language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Step 2 - Validate request body against the schema
|
||||||
|
await request.validate({ schema: newDatasetSchema, messages: this.messages });
|
||||||
|
// console.log({ payload });
|
||||||
|
} catch (error) {
|
||||||
|
// Step 3 - Handle errors
|
||||||
|
// return response.badRequest(error.messages);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return response.redirect().back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// public async store({ request, response, session }: HttpContextContract) {
|
||||||
|
// // node ace make:validator CreateUser
|
||||||
|
// try {
|
||||||
|
// // Step 2 - Validate request body against the schema
|
||||||
|
// await request.validate(CreateUserValidator);
|
||||||
|
// // console.log({ payload });
|
||||||
|
// } catch (error) {
|
||||||
|
// // Step 3 - Handle errors
|
||||||
|
// // return response.badRequest(error.messages);
|
||||||
|
// throw error;
|
||||||
|
// }
|
||||||
|
// const input = request.only(['login', 'email', 'password']);
|
||||||
|
// const user = await User.create(input);
|
||||||
|
// if (request.input('roles')) {
|
||||||
|
// const roles: Array<number> = request.input('roles');
|
||||||
|
// await user.related('roles').attach(roles);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// session.flash('message', 'User has been created successfully');
|
||||||
|
// return response.redirect().toRoute('user.index');
|
||||||
|
// }
|
||||||
|
|
||||||
|
public messages: CustomMessages = {
|
||||||
|
'minLength': '{{ field }} must be at least {{ options.minLength }} characters long',
|
||||||
|
'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long',
|
||||||
|
'required': '{{ field }} is required',
|
||||||
|
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||||
|
// 'confirmed': '{{ field }} is not correct',
|
||||||
|
'licences.minLength': 'at least {{ options.minLength }} permission must be defined',
|
||||||
|
'licences.*.number': 'Define roles as valid numbers',
|
||||||
|
'rights.equalTo': 'you must agree to continue',
|
||||||
|
|
||||||
|
'titles.0.value.minLength': 'Main Title must be at least {{ options.minLength }} characters long',
|
||||||
|
'titles.0.value.required': 'Main Title is required',
|
||||||
|
'titles.*.value.required': 'Additional title is required, if defined',
|
||||||
|
'titles.*.type.required': 'Additional title type is required',
|
||||||
|
'titles.*.language.required': 'Additional title language is required',
|
||||||
|
|
||||||
|
'descriptions.0.value.minLength': 'Main Abstract must be at least {{ options.minLength }} characters long',
|
||||||
|
'descriptions.0.value.required': 'Main Abstract is required',
|
||||||
|
'descriptions.*.value.required': 'Additional description is required, if defined',
|
||||||
|
'descriptions.*.type.required': 'Additional description type is required',
|
||||||
|
'descriptions.*.language.required': 'Additional description language is required',
|
||||||
|
};
|
||||||
|
}
|
37
app/Models/License.ts
Normal file
37
app/Models/License.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { column, BaseModel, SnakeCaseNamingStrategy } from '@ioc:Adonis/Lucid/Orm';
|
||||||
|
|
||||||
|
export default class License extends BaseModel {
|
||||||
|
public static namingStrategy = new SnakeCaseNamingStrategy();
|
||||||
|
public static primaryKey = 'id';
|
||||||
|
public static table = 'document_licences';
|
||||||
|
public static selfAssignPrimaryKey = false;
|
||||||
|
|
||||||
|
@column({
|
||||||
|
isPrimary: true,
|
||||||
|
})
|
||||||
|
public id: number;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public active: boolean;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public langauge: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public link_licence: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public link_logo: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public display_name: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public name_long: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
@column({})
|
||||||
|
public sortOrder: number;
|
||||||
|
}
|
|
@ -54,7 +54,7 @@ export default class Person extends BaseModel {
|
||||||
serializeAs: 'name'
|
serializeAs: 'name'
|
||||||
})
|
})
|
||||||
public get fullName() {
|
public get fullName() {
|
||||||
return this.firstName + ' ' + this.lastName;
|
return `${this.firstName} ${this.lastName} (${this.email})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed()
|
@computed()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { BaseCommand } from '@adonisjs/core/build/standalone';
|
import { BaseCommand } from '@adonisjs/core/build/standalone';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
// import Config from '@ioc:Adonis/Core/Config';
|
||||||
|
import Logger from '@ioc:Adonis/Core/Logger'
|
||||||
|
|
||||||
export default class ValidateChecksum extends BaseCommand {
|
export default class ValidateChecksum extends BaseCommand {
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +39,9 @@ export default class ValidateChecksum extends BaseCommand {
|
||||||
// query all files from database:
|
// query all files from database:
|
||||||
const files = await File.query().preload('hashvalues');
|
const files = await File.query().preload('hashvalues');
|
||||||
|
|
||||||
|
// const logLevel = Config.get('app.logger.level', 'info');
|
||||||
|
// console.log(this.logger.)
|
||||||
|
|
||||||
for (var file of files) {
|
for (var file of files) {
|
||||||
let hashValue = await file.related('hashvalues').query().pluck('value', 'type');
|
let hashValue = await file.related('hashvalues').query().pluck('value', 'type');
|
||||||
|
|
||||||
|
@ -45,16 +50,17 @@ export default class ValidateChecksum extends BaseCommand {
|
||||||
try {
|
try {
|
||||||
calculatedMd5FileHash = await this.checksumFile(filePath, 'md5');
|
calculatedMd5FileHash = await this.checksumFile(filePath, 'md5');
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
this.logger.error(exception.message);
|
// this.logger.error(exception.message);
|
||||||
|
Logger.error(exception.message);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashValue['md5'] == calculatedMd5FileHash) {
|
if (hashValue['md5'] == calculatedMd5FileHash) {
|
||||||
this.logger.info(
|
Logger.info(
|
||||||
`File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`,
|
`File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.logger.logError(
|
Logger.error(
|
||||||
`File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`,
|
`File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,10 @@ export const logger: LoggerConfig = {
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
level: Env.get('LOG_LEVEL', 'info'),
|
level: Env.get('LOG_LEVEL', 'info'),
|
||||||
|
redact: {
|
||||||
|
paths: ['password', '*.password'],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
|
import BaseSchema from '@ioc:Adonis/Lucid/Schema';
|
||||||
import Config from '@ioc:Adonis/Core/Config'
|
import Config from '@ioc:Adonis/Core/Config';
|
||||||
|
|
||||||
export default class Roles extends BaseSchema {
|
export default class Roles extends BaseSchema {
|
||||||
protected tableName = Config.get('rolePermission.role_table', 'roles')
|
protected tableName = Config.get('rolePermission.role_table', 'roles');
|
||||||
|
|
||||||
public async up() {
|
public async up() {
|
||||||
this.schema.createTable(this.tableName, (table) => {
|
this.schema.createTable(this.tableName, (table) => {
|
||||||
table.increments('id')
|
table.increments('id');
|
||||||
table.string('name', 191).unique()
|
table.string('name', 191).unique();
|
||||||
table.string('slug', 191).nullable().unique()
|
table.string('slug', 191).nullable().unique();
|
||||||
table.string('description', 191).nullable()
|
table.string('description', 191).nullable();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses timestamptz for PostgreSQL and DATETIME2 for MSSQL
|
* Uses timestamptz for PostgreSQL and DATETIME2 for MSSQL
|
||||||
*/
|
*/
|
||||||
table.timestamp('created_at', { useTz: true }).nullable()
|
table.timestamp('created_at', { useTz: true }).nullable();
|
||||||
table.timestamp('updated_at', { useTz: true }).nullable()
|
table.timestamp('updated_at', { useTz: true }).nullable();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down() {
|
public async down() {
|
||||||
this.schema.dropTable(this.tableName)
|
this.schema.dropTable(this.tableName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
env.ts
4
env.ts
|
@ -12,7 +12,7 @@
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Env from '@ioc:Adonis/Core/Env'
|
import Env from '@ioc:Adonis/Core/Env';
|
||||||
|
|
||||||
export default Env.rules({
|
export default Env.rules({
|
||||||
HOST: Env.schema.string({ format: 'host' }),
|
HOST: Env.schema.string({ format: 'host' }),
|
||||||
|
@ -29,4 +29,4 @@ export default Env.rules({
|
||||||
PG_USER: Env.schema.string(),
|
PG_USER: Env.schema.string(),
|
||||||
PG_PASSWORD: Env.schema.string.optional(),
|
PG_PASSWORD: Env.schema.string.optional(),
|
||||||
PG_DB_NAME: Env.schema.string(),
|
PG_DB_NAME: Env.schema.string(),
|
||||||
})
|
});
|
||||||
|
|
625
package-lock.json
generated
625
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
|
@ -28,17 +28,6 @@
|
||||||
"eslintIgnore": [
|
"eslintIgnore": [
|
||||||
"build"
|
"build"
|
||||||
],
|
],
|
||||||
"prettier": {
|
|
||||||
"trailingComma": "all",
|
|
||||||
"tabWidth": 4,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"useTabs": false,
|
|
||||||
"quoteProps": "consistent",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"arrowParens": "always",
|
|
||||||
"printWidth": 120
|
|
||||||
},
|
|
||||||
"alias": {
|
"alias": {
|
||||||
"vue": "./node_modules/vue/dist/vue.esm-bundler.js"
|
"vue": "./node_modules/vue/dist/vue.esm-bundler.js"
|
||||||
},
|
},
|
||||||
|
@ -71,7 +60,7 @@
|
||||||
"naive-ui": "^2.34.3",
|
"naive-ui": "^2.34.3",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"pino-pretty": "^9.1.1",
|
"pino-pretty": "^10.0.0",
|
||||||
"postcss-loader": "^7.0.2",
|
"postcss-loader": "^7.0.2",
|
||||||
"prettier": "^2.8.3",
|
"prettier": "^2.8.3",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
|
@ -91,7 +80,9 @@
|
||||||
"@adonisjs/shield": "^7.1.0",
|
"@adonisjs/shield": "^7.1.0",
|
||||||
"@adonisjs/view": "^6.1.5",
|
"@adonisjs/view": "^6.1.5",
|
||||||
"@eidellev/adonis-stardust": "^3.0.0",
|
"@eidellev/adonis-stardust": "^3.0.0",
|
||||||
"@eidellev/inertia-adonisjs": "^7.4.0",
|
"@eidellev/inertia-adonisjs": "^8.0.0",
|
||||||
|
"@fontsource/archivo-black": "^4.5.9",
|
||||||
|
"@fontsource/inter": "^4.5.15",
|
||||||
"@inertiajs/inertia": "^0.11.1",
|
"@inertiajs/inertia": "^0.11.1",
|
||||||
"@inertiajs/vue3": "^1.0.0",
|
"@inertiajs/vue3": "^1.0.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
{
|
{
|
||||||
"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/fonts/inter-all-400-normal.woff": "http://localhost:8080/assets/fonts/inter-all-400-normal.8c804432.woff",
|
||||||
|
"assets/fonts/archivo-black-all-400-normal.woff": "http://localhost:8080/assets/fonts/archivo-black-all-400-normal.da68e413.woff",
|
||||||
|
"assets/fonts/inter-latin-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.3a7a7652.woff2",
|
||||||
|
"assets/fonts/archivo-black-latin-400-normal.woff2": "http://localhost:8080/assets/fonts/archivo-black-latin-400-normal.fc847a1f.woff2",
|
||||||
|
"assets/fonts/inter-latin-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-latin-400-normal.be7cb18d.woff2",
|
||||||
|
"assets/fonts/archivo-black-latin-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/archivo-black-latin-ext-400-normal.21761451.woff2",
|
||||||
|
"assets/fonts/inter-cyrillic-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-cyrillic-ext-400-normal.fcc125c4.woff2",
|
||||||
|
"assets/fonts/inter-greek-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-greek-400-normal.0278a49f.woff2",
|
||||||
|
"assets/fonts/inter-cyrillic-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-cyrillic-400-normal.8684fef6.woff2",
|
||||||
|
"assets/fonts/inter-greek-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-greek-ext-400-normal.3f642a92.woff2",
|
||||||
|
"assets/fonts/inter-vietnamese-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-vietnamese-400-normal.789afb71.woff2"
|
||||||
}
|
}
|
|
@ -1,23 +1,37 @@
|
||||||
/* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500&display=swap'); */
|
/* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500&display=swap'); */
|
||||||
@import url('https://fonts.googleapis.com/css?family=Roboto:400,400i,600,700');
|
/* @import url('https://fonts.googleapis.com/css?family=Roboto:400,400i,600,700'); */
|
||||||
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@import "_checkbox-radio-switch.css";
|
@import '_checkbox-radio-switch.css';
|
||||||
@import "_progress.css";
|
@import '_progress.css';
|
||||||
@import "_scrollbars.css";
|
@import '_scrollbars.css';
|
||||||
@import "_table.css";
|
@import '_table.css';
|
||||||
|
|
||||||
|
@import '@fontsource/inter/index.css';
|
||||||
|
@import '@fontsource/archivo-black/index.css';
|
||||||
|
|
||||||
html, body {
|
/* @layer base {
|
||||||
background-color: #F7F8FA;
|
html,
|
||||||
font-family: 'Roboto', sans-serif;
|
body {
|
||||||
/* height: 100vh; */
|
background-color: #f7f8fa;
|
||||||
|
font-family: Inter, system-ui, sans-serif;
|
||||||
|
height: 100vh;
|
||||||
color: #46444c;
|
color: #46444c;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* html,
|
||||||
|
body {
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
height: 100vh;
|
||||||
|
color: #46444c;
|
||||||
|
position: relative;
|
||||||
|
} */
|
||||||
.px-6 {
|
.px-6 {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
/* padding-right: 1.5rem; */
|
/* padding-right: 1.5rem; */
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
// import { reactive, computed } from 'vue';
|
// import { reactive, computed } from 'vue';
|
||||||
// import { usePage } from '@inertiajs/vue3'
|
// import { usePage } from '@inertiajs/vue3'
|
||||||
// import { usePage } from '@inertiajs/inertia-vue3';
|
// import { usePage } from '@inertiajs/inertia-vue3';
|
||||||
import { LayoutService } from '@/Stores/layout.js';
|
import { LayoutService } from '@/Stores/layout';
|
||||||
import menu from '@/menu.js'
|
import menu from '@/menu'
|
||||||
import AsideMenuLayer from '@/Components/AsideMenuLayer.vue';
|
import AsideMenuLayer from '@/Components/AsideMenuLayer.vue';
|
||||||
import OverlayLayer from '@/Components/OverlayLayer.vue';
|
import OverlayLayer from '@/Components/OverlayLayer.vue';
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ref, computed } from 'vue';
|
||||||
import { Link } from '@inertiajs/vue3';
|
import { Link } from '@inertiajs/vue3';
|
||||||
// import { Link } from '@inertiajs/inertia-vue3';
|
// import { Link } from '@inertiajs/inertia-vue3';
|
||||||
|
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
import { mdiMinus, mdiPlus } from '@mdi/js';
|
import { mdiMinus, mdiPlus } from '@mdi/js';
|
||||||
import { getButtonColor } from '@/colors.js';
|
import { getButtonColor } from '@/colors.js';
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { router } from '@inertiajs/vue3'
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
import { mdiLogout, mdiClose } from '@mdi/js';
|
import { mdiLogout, mdiClose } from '@mdi/js';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { LayoutService } from '@/Stores/layout.js';
|
import { LayoutService } from '@/Stores/layout';
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
import AsideMenuList from '@/Components/AsideMenuList.vue';
|
import AsideMenuList from '@/Components/AsideMenuList.vue';
|
||||||
import AsideMenuItem from '@/Components/AsideMenuItem.vue';
|
import AsideMenuItem from '@/Components/AsideMenuItem.vue';
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
|
|
|
@ -5,15 +5,15 @@ defineProps({
|
||||||
isDropdownList: Boolean,
|
isDropdownList: Boolean,
|
||||||
menu: {
|
menu: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['menu-click'])
|
const emit = defineEmits(['menu-click']);
|
||||||
|
|
||||||
const menuClick = (event, item) => {
|
const menuClick = (event, item) => {
|
||||||
emit('menu-click', event, item)
|
emit('menu-click', event, item);
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,110 +1,80 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { mdiCog } from '@mdi/js'
|
import { mdiCog } from '@mdi/js';
|
||||||
import { computed, useSlots } from 'vue'
|
import { computed, useSlots } from 'vue';
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue'
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
headerIcon: {
|
headerIcon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
rounded: {
|
rounded: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'rounded-xl'
|
default: 'rounded-xl',
|
||||||
},
|
},
|
||||||
hasTable: Boolean,
|
hasFormData: Boolean,
|
||||||
empty: Boolean,
|
empty: Boolean,
|
||||||
form: Boolean,
|
form: Boolean,
|
||||||
hoverable: Boolean,
|
hoverable: Boolean,
|
||||||
modal: Boolean
|
modal: Boolean,
|
||||||
})
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['header-icon-click', 'submit'])
|
const emit = defineEmits(['header-icon-click', 'submit']);
|
||||||
|
|
||||||
const is = computed(() => props.form ? 'form' : 'div')
|
const is = computed(() => (props.form ? 'form' : 'div'));
|
||||||
|
|
||||||
const slots = useSlots()
|
const slots = useSlots();
|
||||||
|
|
||||||
const footer = computed(() => slots.footer && !!slots.footer())
|
const footer = computed(() => slots.footer && !!slots.footer());
|
||||||
|
|
||||||
const componentClass = computed(() => {
|
const componentClass = computed(() => {
|
||||||
const base = [
|
const base = [props.rounded, props.modal ? 'dark:bg-slate-900' : 'dark:bg-slate-900/70'];
|
||||||
props.rounded,
|
|
||||||
props.modal ? 'dark:bg-slate-900' : 'dark:bg-slate-900/70'
|
|
||||||
]
|
|
||||||
|
|
||||||
if (props.hoverable) {
|
if (props.hoverable) {
|
||||||
base.push('hover:shadow-lg transition-shadow duration-500')
|
base.push('hover:shadow-lg transition-shadow duration-500');
|
||||||
}
|
}
|
||||||
|
|
||||||
return base
|
return base;
|
||||||
})
|
});
|
||||||
|
|
||||||
const computedHeaderIcon = computed(() => props.headerIcon ?? mdiCog)
|
const computedHeaderIcon = computed(() => props.headerIcon ?? mdiCog);
|
||||||
|
|
||||||
const headerIconClick = () => {
|
const headerIconClick = () => {
|
||||||
emit('header-icon-click')
|
emit('header-icon-click');
|
||||||
}
|
};
|
||||||
|
|
||||||
const submit = e => {
|
const submit = (e) => {
|
||||||
emit('submit', e)
|
emit('submit', e);
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<component
|
<component :is="is" :class="componentClass" class="bg-white flex flex-col" @submit="submit">
|
||||||
:is="is"
|
<header v-if="title" class="flex items-stretch border-b border-gray-100 dark:border-slate-800">
|
||||||
:class="componentClass"
|
<div class="flex items-center py-3 grow font-bold" :class="[icon ? 'px-4' : 'px-6']">
|
||||||
class="bg-white flex flex-col"
|
<BaseIcon v-if="icon" :path="icon" class="mr-3" />
|
||||||
@submit="submit"
|
|
||||||
>
|
|
||||||
<header
|
|
||||||
v-if="title"
|
|
||||||
class="flex items-stretch border-b border-gray-100 dark:border-slate-800"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex items-center py-3 grow font-bold"
|
|
||||||
:class="[ icon ? 'px-4' : 'px-6' ]"
|
|
||||||
>
|
|
||||||
<BaseIcon
|
|
||||||
v-if="icon"
|
|
||||||
:path="icon"
|
|
||||||
class="mr-3"
|
|
||||||
/>
|
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button class="flex items-center py-3 px-4 justify-center ring-blue-700 focus:ring" @click="headerIconClick">
|
||||||
class="flex items-center py-3 px-4 justify-center ring-blue-700 focus:ring"
|
|
||||||
@click="headerIconClick"
|
|
||||||
>
|
|
||||||
<BaseIcon :path="computedHeaderIcon" />
|
<BaseIcon :path="computedHeaderIcon" />
|
||||||
</button>
|
</button>
|
||||||
</header>
|
</header>
|
||||||
<div
|
<div v-if="empty" class="text-center py-24 text-gray-500 dark:text-slate-400">
|
||||||
v-if="empty"
|
|
||||||
class="text-center py-24 text-gray-500 dark:text-slate-400"
|
|
||||||
>
|
|
||||||
<p>Nothing's here…</p>
|
<p>Nothing's here…</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<!-- <div v-else class="flex-1" :class="{'p-6':!hasTable}"> -->
|
||||||
v-else
|
<div v-else class="flex-1" :class="[!hasFormData && 'p-6']">
|
||||||
class="flex-1"
|
|
||||||
:class="{'p-6':!hasTable}"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="footer" class="p-6 border-t border-gray-100 dark:border-slate-800">
|
||||||
v-if="footer"
|
|
||||||
class="p-6 border-t border-gray-100 dark:border-slate-800"
|
|
||||||
>
|
|
||||||
<slot name="footer" />
|
<slot name="footer" />
|
||||||
</div>
|
</div>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -1,56 +1,62 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue';
|
||||||
import { mdiClose } from '@mdi/js'
|
import { mdiClose } from '@mdi/js';
|
||||||
import BaseButton from '@/Components/BaseButton.vue'
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
import BaseButtons from '@/Components/BaseButtons.vue'
|
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
import CardBox from '@/Components/CardBox.vue'
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
import OverlayLayer from '@/Components/OverlayLayer.vue'
|
import OverlayLayer from '@/Components/OverlayLayer.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
largeTitle: {
|
largeTitle: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'info'
|
default: 'info',
|
||||||
},
|
},
|
||||||
buttonLabel: {
|
buttonLabel: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'Done'
|
default: 'Done',
|
||||||
},
|
},
|
||||||
hasCancel: Boolean,
|
hasCancel: Boolean,
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [String, Number, Boolean],
|
type: [String, Number, Boolean],
|
||||||
default: null
|
default: null,
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'cancel', 'confirm'])
|
const emit = defineEmits(['update:modelValue', 'cancel', 'confirm']);
|
||||||
|
|
||||||
const value = computed({
|
const value = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
set: value => emit('update:modelValue', value)
|
set: (value) => emit('update:modelValue', value),
|
||||||
})
|
});
|
||||||
|
|
||||||
const confirmCancel = (mode) => {
|
const confirmCancel = (mode) => {
|
||||||
value.value = false;
|
value.value = false;
|
||||||
emit(mode);
|
emit(mode);
|
||||||
}
|
};
|
||||||
|
|
||||||
const confirm = () => confirmCancel('confirm')
|
const confirm = () => confirmCancel('confirm');
|
||||||
|
|
||||||
const cancel = () => confirmCancel('cancel')
|
const cancel = () => confirmCancel('cancel');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<OverlayLayer v-show="value" @overlay-click="cancel">
|
<OverlayLayer v-show="value" @overlay-click="cancel">
|
||||||
<CardBox v-show="value" :title="title" class="shadow-lg max-h-modal w-11/12 md:w-3/5 lg:w-2/5 xl:w-4/12 z-50"
|
<CardBox
|
||||||
:header-icon="mdiClose" modal @header-icon-click="cancel">
|
v-show="value"
|
||||||
|
:title="title"
|
||||||
|
class="shadow-lg max-h-modal w-11/12 md:w-3/5 lg:w-2/5 xl:w-4/12 z-50"
|
||||||
|
:header-icon="mdiClose"
|
||||||
|
modal
|
||||||
|
@header-icon-click="cancel"
|
||||||
|
>
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
<h1 v-if="largeTitle" class="text-2xl">
|
<h1 v-if="largeTitle" class="text-2xl">
|
||||||
{{ largeTitle }}
|
{{ largeTitle }}
|
||||||
|
|
|
@ -28,13 +28,17 @@ const props = defineProps({
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Array,
|
type: [Array, Object],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'text',
|
default: 'text',
|
||||||
},
|
},
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [String, Number, Boolean, Array, Object],
|
type: [String, Number, Boolean, Array, Object],
|
||||||
default: '',
|
default: '',
|
||||||
|
@ -57,7 +61,8 @@ const inputElClass = computed(() => {
|
||||||
'dark:placeholder-gray-400',
|
'dark:placeholder-gray-400',
|
||||||
computedType.value === 'textarea' ? 'h-24' : 'h-12',
|
computedType.value === 'textarea' ? 'h-24' : 'h-12',
|
||||||
props.borderless ? 'border-0' : 'border',
|
props.borderless ? 'border-0' : 'border',
|
||||||
props.transparent ? 'bg-transparent' : 'bg-white dark:bg-slate-800',
|
// props.transparent && !props.isReadOnly ? 'bg-transparent' : 'bg-white dark:bg-slate-800',
|
||||||
|
props.isReadOnly ? 'bg-gray-50 dark:bg-slate-600' : 'bg-white dark:bg-slate-800',
|
||||||
];
|
];
|
||||||
if (props.icon) {
|
if (props.icon) {
|
||||||
base.push('pl-10');
|
base.push('pl-10');
|
||||||
|
@ -105,14 +110,9 @@ if (props.ctrlKFocus) {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<select
|
<select v-if="computedType === 'select'" :id="id" v-model="computedValue" :name="name" :class="inputElClass">
|
||||||
v-if="computedType === 'select'"
|
<option v-if="placeholder" class="text-opacity-25" value="" disabled selected>{{ placeholder }}</option>
|
||||||
:id="id"
|
<option v-for="option in options" :key="option.id ?? option" :value="option.value ?? option">
|
||||||
v-model="computedValue"
|
|
||||||
:name="name"
|
|
||||||
:class="inputElClass"
|
|
||||||
>
|
|
||||||
<option v-for="option in options" :key="option.id ?? option" :value="option">
|
|
||||||
{{ option.label ?? option }}
|
{{ option.label ?? option }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -137,6 +137,7 @@ if (props.ctrlKFocus) {
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:type="computedType"
|
:type="computedType"
|
||||||
:class="inputElClass"
|
:class="inputElClass"
|
||||||
|
:readonly="isReadOnly"
|
||||||
/>
|
/>
|
||||||
<FormControlIcon v-if="icon" :icon="icon" :h="controlIconH" />
|
<FormControlIcon v-if="icon" :icon="icon" :h="controlIconH" />
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
@ -36,7 +36,8 @@ const wrapperClass = computed(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="mb-6 last:mb-0">
|
<div class="mb-6 last:mb-0">
|
||||||
<label v-if="label" :for="labelFor" class="block font-bold mb-2">{{ label }}</label>
|
<!-- <label v-if="label" :for="labelFor" class="block font-bold mb-2">{{ label }}</label> -->
|
||||||
|
<label v-if="label" :for="labelFor" class="font-bold h-6 mt-3 text-xs leading-8 uppercase">{{ label }}</label>
|
||||||
<div v-bind:class="wrapperClass">
|
<div v-bind:class="wrapperClass">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
44
resources/js/Components/Icons/Confirm.vue
Normal file
44
resources/js/Components/Icons/Confirm.vue
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="my-svg-component"
|
||||||
|
>
|
||||||
|
<ellipse cx="12" cy="5" rx="9" ry="3"></ellipse>
|
||||||
|
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path>
|
||||||
|
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'Icon_Mandatory',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.my-svg-component {
|
||||||
|
/* Scoped CSS here */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
fill: none;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 1;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* path,
|
||||||
|
circle {
|
||||||
|
stroke: #ffffff;
|
||||||
|
stroke-width: 6px;
|
||||||
|
fill: none;
|
||||||
|
} */
|
||||||
|
</style>
|
35
resources/js/Components/Icons/Language.vue
Normal file
35
resources/js/Components/Icons/Language.vue
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="my-svg-component">
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M9 2.25a.75.75 0 01.75.75v1.506a49.38 49.38 0 015.343.371.75.75 0 11-.186 1.489c-.66-.083-1.323-.151-1.99-.206a18.67 18.67 0 01-2.969 6.323c.317.384.65.753.998 1.107a.75.75 0 11-1.07 1.052A18.902 18.902 0 019 13.687a18.823 18.823 0 01-5.656 4.482.75.75 0 11-.688-1.333 17.323 17.323 0 005.396-4.353A18.72 18.72 0 015.89 8.598a.75.75 0 011.388-.568A17.21 17.21 0 009 11.224a17.17 17.17 0 002.391-5.165 48.038 48.038 0 00-8.298.307.75.75 0 01-.186-1.489 49.159 49.159 0 015.343-.371V3A.75.75 0 019 2.25zM15.75 9a.75.75 0 01.68.433l5.25 11.25a.75.75 0 01-1.36.634l-1.198-2.567h-6.744l-1.198 2.567a.75.75 0 01-1.36-.634l5.25-11.25A.75.75 0 0115.75 9zm-2.672 8.25h5.344l-2.672-5.726-2.672 5.726z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Icon_Mandatory',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.my-svg-component {
|
||||||
|
/* Scoped CSS here */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
fill: none;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 1;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* path,
|
||||||
|
circle {
|
||||||
|
stroke: #ffffff;
|
||||||
|
stroke-width: 6px;
|
||||||
|
fill: none;
|
||||||
|
} */
|
||||||
|
</style>
|
35
resources/js/Components/Icons/Mandatory.vue
Normal file
35
resources/js/Components/Icons/Mandatory.vue
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<svg class="my-svg-component" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 11-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 004.486-6.336l-3.276 3.277a3.004 3.004 0 01-2.25-2.25l3.276-3.276a4.5 4.5 0 00-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437l1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Icon_Mandatory',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.my-svg-component {
|
||||||
|
/* Scoped CSS here */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
fill: none;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* path,
|
||||||
|
circle {
|
||||||
|
stroke: #ffffff;
|
||||||
|
stroke-width: 6px;
|
||||||
|
fill: none;
|
||||||
|
} */
|
||||||
|
</style>
|
33
resources/js/Components/Icons/Recommendet.vue
Normal file
33
resources/js/Components/Icons/Recommendet.vue
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<template>
|
||||||
|
<svg class="my-svg-component" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M6 3a3 3 0 00-3 3v2.25a3 3 0 003 3h2.25a3 3 0 003-3V6a3 3 0 00-3-3H6zM15.75 3a3 3 0 00-3 3v2.25a3 3 0 003 3H18a3 3 0 003-3V6a3 3 0 00-3-3h-2.25zM6 12.75a3 3 0 00-3 3V18a3 3 0 003 3h2.25a3 3 0 003-3v-2.25a3 3 0 00-3-3H6zM17.625 13.5a.75.75 0 00-1.5 0v2.625H13.5a.75.75 0 000 1.5h2.625v2.625a.75.75 0 001.5 0v-2.625h2.625a.75.75 0 000-1.5h-2.625V13.5z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Icon_Mandatory',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.my-svg-component {
|
||||||
|
/* Scoped CSS here */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
fill: none;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* path,
|
||||||
|
circle {
|
||||||
|
stroke: #ffffff;
|
||||||
|
stroke-width: 6px;
|
||||||
|
fill: none;
|
||||||
|
} */
|
||||||
|
</style>
|
49
resources/js/Components/Icons/Wizard.vue
Normal file
49
resources/js/Components/Icons/Wizard.vue
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center relative">
|
||||||
|
<!-- v-bind:class="{ 'text-white bg-teal-600 border-teal-600': isCurrent, 'border-teal-600': isChecked }" -->
|
||||||
|
<div
|
||||||
|
class="text-gray-500 rounded-full transition duration-500 ease-in-out h-12 w-12 py-3 border-2"
|
||||||
|
:class="[
|
||||||
|
isCurrent ? 'text-white bg-teal-600 border-teal-600' : 'border-gray-300',
|
||||||
|
isChecked && 'text-teal-600 border-teal-600',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<!-- <svg class="my-svg-component" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 11-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 004.486-6.336l-3.276 3.277a3.004 3.004 0 01-2.25-2.25l3.276-3.276a4.5 4.5 0 00-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437l1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008z"
|
||||||
|
/>
|
||||||
|
</svg> -->
|
||||||
|
<slot></slot>
|
||||||
|
<div class="absolute top-0 -ml-10 text-center mt-16 w-32 text-xs font-medium uppercase invisible sm:visible">
|
||||||
|
{{ label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!isLastStep"
|
||||||
|
class="flex-auto border-t-2 transition duration-500 ease-in-out invisible sm:visible"
|
||||||
|
:class="[isChecked ? 'border-teal-600' : 'border-gray-300']"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Icon_Multistep',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
isCurrent: Boolean,
|
||||||
|
isChecked: Boolean,
|
||||||
|
isLastStep: Boolean,
|
||||||
|
label: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mode: 'light',
|
||||||
|
checkedClass: 'border-teal-600',
|
||||||
|
uncheckedClass: 'border-gray-300',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -7,8 +7,8 @@ import {ComputedRef} from "vue";
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { containerMaxW } from '@/config.js';
|
import { containerMaxW } from '@/config.js';
|
||||||
// import { MainService } from '@/Stores/main.js';
|
// import { MainService } from '@/Stores/main.js';
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
import { LayoutService } from '@/Stores/layout.js';
|
import { LayoutService } from '@/Stores/layout';
|
||||||
import {
|
import {
|
||||||
mdiForwardburger,
|
mdiForwardburger,
|
||||||
mdiBackburger,
|
mdiBackburger,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { StyleService } from '@/Stores/style.js'
|
import { StyleService } from '@/Stores/style'
|
||||||
// import { Link } from '@inertiajs/vue3'
|
// import { Link } from '@inertiajs/vue3'
|
||||||
import { Link } from '@inertiajs/vue3'
|
import { Link } from '@inertiajs/vue3'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { StyleService } from '@/Stores/style.js'
|
import { StyleService } from '@/Stores/style'
|
||||||
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
|
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
|
||||||
import { mdiChevronUp, mdiChevronDown } from '@mdi/js'
|
import { mdiChevronUp, mdiChevronDown } from '@mdi/js'
|
||||||
import NavBarItem from '@/Components/NavBarItem.vue'
|
import NavBarItem from '@/Components/NavBarItem.vue'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
zIndex: {
|
zIndex: {
|
||||||
|
|
281
resources/js/Components/SearchAutocomplete.vue
Normal file
281
resources/js/Components/SearchAutocomplete.vue
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
<template>
|
||||||
|
<!-- <input
|
||||||
|
v-model="data.search"
|
||||||
|
@change="onChange"
|
||||||
|
type="text"
|
||||||
|
class="text-base font-medium block w-full rounded-md border transition ease-in-out focus:ring-1 border-gray-300 border-solid py-2 px-3 text-gray-700 placeholder-gray-400 focus:border-blue-200 focus:ring-blue-500 focus:outline-none"
|
||||||
|
v-bind:name="props.name"
|
||||||
|
/>
|
||||||
|
<ul v-if="data.isOpen" class="mt-1 border-2 border-slate-50 overflow-auto shadow-lg rounded list-none">
|
||||||
|
<li
|
||||||
|
:class="['hover:bg-blue-100 hover:text-blue-800', 'w-full list-none text-left py-2 px-3 cursor-pointer']"
|
||||||
|
v-for="(result, i) in data.results"
|
||||||
|
:key="i"
|
||||||
|
>
|
||||||
|
{{ result.name }}
|
||||||
|
</li>
|
||||||
|
</ul> -->
|
||||||
|
|
||||||
|
<!-- <div class="flex-col justify-center relative"> -->
|
||||||
|
<div class="relative">
|
||||||
|
<input
|
||||||
|
v-model="data.search"
|
||||||
|
type="text"
|
||||||
|
:class="inputElClass"
|
||||||
|
:name="props.name"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
autocomplete="off"
|
||||||
|
@keydown.down="onArrowDown"
|
||||||
|
@keydown.up="onArrowUp"
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
class="w-4 h-4 absolute left-2.5 top-3.5"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<!-- <ul v-if="data.isOpen" class="bg-white border border-gray-100 w-full mt-2 max-h-28 overflow-y-auto"> -->
|
||||||
|
<!-- :ref="(el) => { ul[i] = el }" -->
|
||||||
|
<ul v-if="data.isOpen" class="bg-white dark:bg-slate-800 w-full mt-2 max-h-28 overflow-y-auto scroll-smooth">
|
||||||
|
<li
|
||||||
|
class="pl-8 pr-2 py-1 border-b-2 border-gray-100 relative cursor-pointer hover:bg-yellow-50 hover:text-gray-900"
|
||||||
|
:class="{
|
||||||
|
'bg-yellow-50 text-gray-900': i == selectedIndex,
|
||||||
|
}"
|
||||||
|
v-for="(result, i) in data.results"
|
||||||
|
:key="i"
|
||||||
|
:ref="
|
||||||
|
(el: HTMLLIElement | null) => {
|
||||||
|
ul[i] = el;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<svg class="absolute w-4 h-4 left-2 top-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<!-- <b>Gar</b>{{ result.name }} -->
|
||||||
|
|
||||||
|
<!-- <span>
|
||||||
|
{{ makeBold(result.name) }}
|
||||||
|
</span> -->
|
||||||
|
<span
|
||||||
|
v-for="(item, index) in makeBold(result.name)"
|
||||||
|
:key="index"
|
||||||
|
:class="{
|
||||||
|
'font-bold': data.search.toLowerCase().includes(item.toLowerCase()),
|
||||||
|
'is-active': index == selectedIndex,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ item }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- </div> -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, computed, Ref, watch } from 'vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
let props = defineProps({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: 'autocomplete',
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
type: [String, Array, Function],
|
||||||
|
required: true,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: 'name',
|
||||||
|
},
|
||||||
|
responseProperty: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: 'name',
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
required: Boolean,
|
||||||
|
borderless: Boolean,
|
||||||
|
transparent: Boolean,
|
||||||
|
ctrlKFocus: Boolean,
|
||||||
|
});
|
||||||
|
|
||||||
|
const inputElClass = computed(() => {
|
||||||
|
const base = [
|
||||||
|
'px-3 py-2 max-w-full focus:ring focus:outline-none border-gray-700 rounded w-full',
|
||||||
|
'dark:placeholder-gray-400',
|
||||||
|
'h-12',
|
||||||
|
props.borderless ? 'border-0' : 'border',
|
||||||
|
props.transparent ? 'bg-transparent' : 'bg-white dark:bg-slate-800',
|
||||||
|
// props.isReadOnly ? 'bg-gray-50 dark:bg-slate-600' : 'bg-white dark:bg-slate-800',
|
||||||
|
];
|
||||||
|
// if (props.icon) {
|
||||||
|
base.push('pl-10');
|
||||||
|
// }
|
||||||
|
return base;
|
||||||
|
});
|
||||||
|
|
||||||
|
let search = ref('');
|
||||||
|
let data = reactive({
|
||||||
|
search: search,
|
||||||
|
isOpen: false,
|
||||||
|
results: [],
|
||||||
|
});
|
||||||
|
let error = ref('');
|
||||||
|
let selectedIndex: Ref<number> = ref(0);
|
||||||
|
// const listItem = ref(null);
|
||||||
|
const ul: Ref<Array<HTMLLIElement | null>> = ref([]);
|
||||||
|
|
||||||
|
watch(selectedIndex, (selectedIndex) => {
|
||||||
|
if (selectedIndex != null && ul.value != null) {
|
||||||
|
const currentElement: HTMLLIElement | null = ul.value[selectedIndex];
|
||||||
|
currentElement &&
|
||||||
|
currentElement.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'nearest',
|
||||||
|
inline: 'start',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(search, async () => {
|
||||||
|
await onChange();
|
||||||
|
});
|
||||||
|
|
||||||
|
// function clear() {
|
||||||
|
// data.search = "";
|
||||||
|
// data.isOpen = false;
|
||||||
|
// data.results = [];
|
||||||
|
// error.value = "";
|
||||||
|
// // this.$emit("clear");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function onChange() {
|
||||||
|
// if (!props.source || !data.search) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// data.isOpen = true;
|
||||||
|
// arrayLikeSearch(props.source);
|
||||||
|
// }
|
||||||
|
async function onChange() {
|
||||||
|
if (!props.source || !data.search) return false;
|
||||||
|
|
||||||
|
selectedIndex.value = 0;
|
||||||
|
|
||||||
|
if (data.search.length >= 2) {
|
||||||
|
data.isOpen = true;
|
||||||
|
switch (true) {
|
||||||
|
case typeof props.source === 'string':
|
||||||
|
return await request(props.source, data.search);
|
||||||
|
// case typeof props.source === 'function':
|
||||||
|
// return props.source(data.search).then((response) => {
|
||||||
|
// data.results = getResults(response);
|
||||||
|
// });
|
||||||
|
case Array.isArray(props.source):
|
||||||
|
return arrayLikeSearch(props.source);
|
||||||
|
default:
|
||||||
|
throw new Error('typeof source is ' + typeof props.source);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data.results = [];
|
||||||
|
data.isOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getResults(response) {
|
||||||
|
// if (props.responseProperty) {
|
||||||
|
// let foundObj;
|
||||||
|
// JSON.stringify(response, (_, nestedValue) => {
|
||||||
|
// if (nestedValue && nestedValue[props.responseProperty]) foundObj = nestedValue[props.responseProperty];
|
||||||
|
|
||||||
|
// return nestedValue;
|
||||||
|
// });
|
||||||
|
// return foundObj;
|
||||||
|
// }
|
||||||
|
if (Array.isArray(response)) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// function setResult(result) {
|
||||||
|
// data.search = result[props.label];
|
||||||
|
// data.isOpen = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function request(url) {
|
||||||
|
// return axios.get(url).then((response) => {
|
||||||
|
// data.results = getResults(response);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
async function request(url, param) {
|
||||||
|
try {
|
||||||
|
let response = await searchTerm(url, param);
|
||||||
|
error.value = '';
|
||||||
|
data.results = getResults(response);
|
||||||
|
// this.results = res.data;
|
||||||
|
// this.loading = false;
|
||||||
|
} catch (error) {
|
||||||
|
error.value = error.message;
|
||||||
|
// this.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchTerm(term: string, param): Promise<any> {
|
||||||
|
let res = await axios.get(term, { params: { filter: param } });
|
||||||
|
// console.log(res.data);
|
||||||
|
return res.data; //.response;//.docs;
|
||||||
|
}
|
||||||
|
// async function request(term: string): Promise<any> {
|
||||||
|
// let res = await axios.get('/api/persons', { params: { filter: term } });
|
||||||
|
// return res.data; //.response;//.docs;
|
||||||
|
// }
|
||||||
|
|
||||||
|
function arrayLikeSearch(items) {
|
||||||
|
data.results = items.filter((item) => {
|
||||||
|
return item.toLowerCase().indexOf(data.search.toLowerCase()) > -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeBold(suggestion) {
|
||||||
|
const query = data.search.valueOf();
|
||||||
|
const regex = new RegExp(query.split('').join('-?'), 'i');
|
||||||
|
const test = suggestion.replace(regex, (match) => '<split>' + match + '<split>');
|
||||||
|
// return suggestion.match(regex);
|
||||||
|
// const splitWord = suggestion.match(regex);
|
||||||
|
return test.split('<split>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onArrowDown() {
|
||||||
|
if (data.results.length > 0) {
|
||||||
|
selectedIndex.value = selectedIndex.value === data.results.length - 1 ? 0 : selectedIndex.value + 1;
|
||||||
|
// const currentElement: HTMLLIElement = ul.value[selectedIndex.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onArrowUp() {
|
||||||
|
if (data.results.length > 0) {
|
||||||
|
selectedIndex.value = selectedIndex.value == 0 || selectedIndex.value == -1 ? data.results.length - 1 : selectedIndex.value - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { containerMaxW } from '@/config.js'
|
import { containerMaxW } from '@/config.js';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
30
resources/js/Dataset.ts
Normal file
30
resources/js/Dataset.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { Ref } from 'vue';
|
||||||
|
|
||||||
|
export interface Dataset {
|
||||||
|
[key: string]: string | Ref<string>| boolean | Array<Title> | (IErrorMessage | undefined);
|
||||||
|
language: Ref<string>;
|
||||||
|
// licenses: Array<number>;
|
||||||
|
rights: boolean;
|
||||||
|
type: string;
|
||||||
|
creating_corporation: string;
|
||||||
|
titles: Array<Title>;
|
||||||
|
descriptions: Array<Description>;
|
||||||
|
errors?: IErrorMessage;
|
||||||
|
// async (user): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Title {
|
||||||
|
value: string;
|
||||||
|
type: string;
|
||||||
|
language: string | Ref<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Description {
|
||||||
|
value: string;
|
||||||
|
type: string;
|
||||||
|
language: string | Ref<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IErrorMessage {
|
||||||
|
[key: string]: Array<string>;
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { LayoutService } from '@/Stores/layout.js'
|
import { LayoutService } from '@/Stores/layout';
|
||||||
import { StyleService } from '@/Stores/style'
|
import { StyleService } from '@/Stores/style';
|
||||||
import NavBar from '@/Components/NavBar.vue'
|
import NavBar from '@/Components/NavBar.vue';
|
||||||
import AsideMenu from '@/Components/AsideMenu.vue'
|
import AsideMenu from '@/Components/AsideMenu.vue';
|
||||||
import FooterBar from '@/Components/FooterBar.vue'
|
import FooterBar from '@/Components/FooterBar.vue';
|
||||||
|
|
||||||
const styleService = StyleService()
|
const styleService = StyleService();
|
||||||
|
|
||||||
const layoutService = LayoutService()
|
const layoutService = LayoutService();
|
||||||
|
|
||||||
// defineProps({
|
// defineProps({
|
||||||
// user: {
|
// user: {
|
||||||
|
@ -15,11 +15,15 @@ const layoutService = LayoutService()
|
||||||
// default: () => ({}),
|
// default: () => ({}),
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="{ 'dark': styleService.darkMode, 'overflow-hidden lg:overflow-visible': layoutService.isAsideMobileExpanded }">
|
<div
|
||||||
|
:class="{
|
||||||
|
'dark': styleService.darkMode,
|
||||||
|
'overflow-hidden lg:overflow-visible': layoutService.isAsideMobileExpanded,
|
||||||
|
}"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
:class="{ 'ml-60 lg:ml-0': layoutService.isAsideMobileExpanded }"
|
:class="{ 'ml-60 lg:ml-0': layoutService.isAsideMobileExpanded }"
|
||||||
class="pt-14 xl:pl-60 min-h-screen w-screen transition-position lg:w-auto bg-gray-50 dark:bg-slate-800 dark:text-slate-100"
|
class="pt-14 xl:pl-60 min-h-screen w-screen transition-position lg:w-auto bg-gray-50 dark:bg-slate-800 dark:text-slate-100"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
const styleService = StyleService();
|
const styleService = StyleService();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
mdiContrastCircle,
|
mdiContrastCircle,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
// import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
|
// import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
|
||||||
import { Head, Link, useForm, router } from '@inertiajs/vue3';
|
import { useForm } from '@inertiajs/vue3';
|
||||||
|
// import { reactive } from 'vue';
|
||||||
import {
|
import {
|
||||||
mdiAccount,
|
mdiAccount,
|
||||||
mdiAccountCircle,
|
mdiAccountCircle,
|
||||||
|
@ -9,7 +10,7 @@ import {
|
||||||
mdiAsterisk,
|
mdiAsterisk,
|
||||||
mdiFormTextboxPassword,
|
mdiFormTextboxPassword,
|
||||||
mdiArrowLeftBoldOutline,
|
mdiArrowLeftBoldOutline,
|
||||||
mdiAlertBoxOutline,
|
// mdiAlertBoxOutline,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import SectionMain from '@/Components/SectionMain.vue';
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
import CardBox from '@/Components/CardBox.vue';
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
|
@ -18,7 +19,7 @@ import FormField from '@/Components/FormField.vue';
|
||||||
import FormControl from '@/Components/FormControl.vue';
|
import FormControl from '@/Components/FormControl.vue';
|
||||||
import BaseButton from '@/Components/BaseButton.vue';
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
import BaseButtons from '@/Components/BaseButtons.vue';
|
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
import NotificationBar from '@/Components/NotificationBar.vue';
|
// import NotificationBar from '@/Components/NotificationBar.vue';
|
||||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
@ -41,16 +42,16 @@ const profileForm = useForm({
|
||||||
email: props.user.email,
|
email: props.user.email,
|
||||||
});
|
});
|
||||||
const profileSubmit = async () => {
|
const profileSubmit = async () => {
|
||||||
await router.post(stardust.route('admin.account.info.store', [props.user.id]), profileForm);
|
await profileForm.post(stardust.route('admin.account.info.store', [props.user.id]));
|
||||||
};
|
};
|
||||||
|
|
||||||
const passwordForm = useForm({
|
const passwordForm = useForm({
|
||||||
old_password: null,
|
old_password: "",
|
||||||
new_password: null,
|
new_password: "",
|
||||||
confirm_password: null,
|
confirm_password: "",
|
||||||
});
|
});
|
||||||
const passwordSubmit = async () => {
|
const passwordSubmit = async () => {
|
||||||
await router.post(stardust.route('admin.account.info.store'), passwordForm, {
|
await passwordForm.post(stardust.route('admin.account.info.store'), {
|
||||||
preserveScroll: true,
|
preserveScroll: true,
|
||||||
onSuccess: (resp) => {
|
onSuccess: (resp) => {
|
||||||
console.log(resp);
|
console.log(resp);
|
||||||
|
@ -68,9 +69,9 @@ const passwordSubmit = async () => {
|
||||||
rounded-full small />
|
rounded-full small />
|
||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
|
|
||||||
<NotificationBar v-if="$page.props.flash.message" color="success" :icon="mdiAlertBoxOutline">
|
<!-- <NotificationBar v-if="$page.props.flash.message" color="success" :icon="mdiAlertBoxOutline">
|
||||||
{{ $page.props.flash.message }}
|
{{ $page.props.flash.message }}
|
||||||
</NotificationBar>
|
</NotificationBar> -->
|
||||||
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { Head, Link, useForm, router } from '@inertiajs/vue3';
|
import { Head, useForm, router } from '@inertiajs/vue3';
|
||||||
import { mdiAccountKey, mdiArrowLeftBoldOutline } from '@mdi/js';
|
import { mdiAccountKey, mdiArrowLeftBoldOutline } from '@mdi/js';
|
||||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import SectionMain from '@/Components/SectionMain.vue';
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
@ -45,11 +45,11 @@ const submit = async () => {
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Add user" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Add user" main>
|
||||||
<BaseButton :route-name="stardust.route('user.index')" :icon="mdiArrowLeftBoldOutline" label="Back"
|
<BaseButton :route-name="stardust.route('user.index')" :icon="mdiArrowLeftBoldOutline" label="Back"
|
||||||
color="white" rounded-full small />
|
color="modern" rounded-full small />
|
||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
<!-- @submit.prevent="form.post(stardust.route('user.store'))" -->
|
<!-- @submit.prevent="form.post(stardust.route('user.store'))" -->
|
||||||
<CardBox form @submit.prevent="submit()">
|
<CardBox form @submit.prevent="submit()">
|
||||||
<FormField label="Login" :class="{ 'text-red-400': errors.name }">
|
<FormField label="Login" :class="{ 'text-red-400': errors.login }">
|
||||||
<FormControl v-model="form.login" type="text" placeholder="Enter Login" :errors="errors.login">
|
<FormControl v-model="form.login" type="text" placeholder="Enter Login" :errors="errors.login">
|
||||||
<div class="text-red-400 text-sm" v-if="errors.login && Array.isArray(errors.login)">
|
<div class="text-red-400 text-sm" v-if="errors.login && Array.isArray(errors.login)">
|
||||||
<!-- {{ errors.login }} -->
|
<!-- {{ errors.login }} -->
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { Head, Link, useForm, router } from "@inertiajs/vue3"
|
import { Head, useForm, router } from "@inertiajs/vue3"
|
||||||
import {
|
import {
|
||||||
mdiAccountKey,
|
mdiAccountKey,
|
||||||
mdiArrowLeftBoldOutline
|
mdiArrowLeftBoldOutline
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
// import { Head, Link, useForm, usePage } from '@inertiajs/inertia-vue3';
|
// import { Head, Link, useForm, usePage } from '@inertiajs/inertia-vue3';
|
||||||
import { Head, Link, useForm, usePage } from '@inertiajs/vue3';
|
import { Head, Link, useForm, usePage } from '@inertiajs/vue3';
|
||||||
|
import { ComputedRef } from 'vue';
|
||||||
import {
|
import {
|
||||||
mdiAccountKey,
|
mdiAccountKey,
|
||||||
mdiPlus,
|
mdiPlus,
|
||||||
|
@ -8,7 +9,7 @@ import {
|
||||||
mdiTrashCan,
|
mdiTrashCan,
|
||||||
mdiAlertBoxOutline,
|
mdiAlertBoxOutline,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import { watch, computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import SectionMain from '@/Components/SectionMain.vue';
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
|
@ -44,7 +45,7 @@ const props = defineProps({
|
||||||
// return props.filters.search;
|
// return props.filters.search;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
const flash = computed(() => {
|
const flash: ComputedRef<any> = computed(() => {
|
||||||
// let test = usePage();
|
// let test = usePage();
|
||||||
// console.log(test);
|
// console.log(test);
|
||||||
return usePage().props.flash;
|
return usePage().props.flash;
|
||||||
|
@ -73,7 +74,7 @@ const destroy = async (id) => {
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Tethys Users" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Tethys Users" main>
|
||||||
<BaseButton v-if="can.create" :route-name="stardust.route('user.create')" :icon="mdiPlus" label="Add"
|
<BaseButton v-if="can.create" :route-name="stardust.route('user.create')" :icon="mdiPlus" label="Add"
|
||||||
color="info" rounded-full small />
|
color="modern" rounded-full small />
|
||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
<!-- <label>{{ form.search }}</label> -->
|
<!-- <label>{{ form.search }}</label> -->
|
||||||
<NotificationBar v-if="flash.message" color="success" :icon="mdiAlertBoxOutline">
|
<NotificationBar v-if="flash.message" color="success" :icon="mdiAlertBoxOutline">
|
||||||
|
@ -87,7 +88,7 @@ const destroy = async (id) => {
|
||||||
<input type="search" v-model="form.search"
|
<input type="search" v-model="form.search"
|
||||||
class="rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
|
class="rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
|
||||||
placeholder="Search" />
|
placeholder="Search" />
|
||||||
<BaseButton label="Search" type="submit" color="info"
|
<BaseButton label="Search" type="submit" color="modern"
|
||||||
class="ml-4 inline-flex items-center px-4 py-2" />
|
class="ml-4 inline-flex items-center px-4 py-2" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { Head, Link, useForm } from "@inertiajs/vue3"
|
import { Head } from '@inertiajs/vue3';
|
||||||
import {
|
import { mdiAccountKey, mdiArrowLeftBoldOutline } from '@mdi/js';
|
||||||
mdiAccountKey,
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
mdiArrowLeftBoldOutline,
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
} from "@mdi/js"
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
import LayoutAuthenticated from "@/Layouts/LayoutAuthenticated.vue"
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
import SectionMain from "@/Components/SectionMain.vue"
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
import SectionTitleLineWithButton from "@/Components/SectionTitleLineWithButton.vue"
|
|
||||||
import CardBox from "@/Components/CardBox.vue"
|
|
||||||
import BaseButton from "@/Components/BaseButton.vue"
|
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
|
||||||
const props = defineProps({
|
defineProps({
|
||||||
user: {
|
user: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
|
@ -23,63 +20,41 @@ const props = defineProps({
|
||||||
userHasRoles: {
|
userHasRoles: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LayoutAuthenticated :user="user">
|
<LayoutAuthenticated :user="user">
|
||||||
|
|
||||||
<Head title="View user" />
|
<Head title="View user" />
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="View user" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="View user" main>
|
||||||
<BaseButton :route-name="stardust.route('user.index')" :icon="mdiArrowLeftBoldOutline" label="Back" color="white"
|
<BaseButton
|
||||||
rounded-full small />
|
:route-name="stardust.route('user.index')"
|
||||||
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
|
label="Back"
|
||||||
|
color="white"
|
||||||
|
rounded-full
|
||||||
|
small
|
||||||
|
/>
|
||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
<CardBox class="mb-6">
|
<CardBox class="mb-6">
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="
|
<td class="p-4 pl-8 text-slate-500 dark:text-slate-400 hidden lg:block">Login</td>
|
||||||
p-4
|
|
||||||
pl-8
|
|
||||||
text-slate-500
|
|
||||||
dark:text-slate-400
|
|
||||||
hidden
|
|
||||||
lg:block
|
|
||||||
">
|
|
||||||
Login
|
|
||||||
</td>
|
|
||||||
<td data-label="Login">
|
<td data-label="Login">
|
||||||
{{ user.login }}
|
{{ user.login }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="
|
<td class="p-4 pl-8 text-slate-500 dark:text-slate-400 hidden lg:block">Email</td>
|
||||||
p-4
|
|
||||||
pl-8
|
|
||||||
text-slate-500
|
|
||||||
dark:text-slate-400
|
|
||||||
hidden
|
|
||||||
lg:block
|
|
||||||
">
|
|
||||||
Email
|
|
||||||
</td>
|
|
||||||
<td data-label="Email">
|
<td data-label="Email">
|
||||||
{{ user.email }}
|
{{ user.email }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="
|
<td class="p-4 pl-8 text-slate-500 dark:text-slate-400 hidden lg:block">Created</td>
|
||||||
p-4
|
|
||||||
pl-8
|
|
||||||
text-slate-500
|
|
||||||
dark:text-slate-400
|
|
||||||
hidden
|
|
||||||
lg:block
|
|
||||||
">
|
|
||||||
Created
|
|
||||||
</td>
|
|
||||||
<td data-label="Created">
|
<td data-label="Created">
|
||||||
{{ new Date(user.created_at).toLocaleString() }}
|
{{ new Date(user.created_at).toLocaleString() }}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -32,7 +32,6 @@ import FormControl from '@/Components/FormControl.vue';
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LayoutGuest>
|
<LayoutGuest>
|
||||||
|
|
||||||
<Head title="Login" />
|
<Head title="Login" />
|
||||||
|
|
||||||
<SectionFullScreen v-slot="{ cardClass }" :bg="'greenBlue'">
|
<SectionFullScreen v-slot="{ cardClass }" :bg="'greenBlue'">
|
||||||
|
@ -44,13 +43,18 @@ import FormControl from '@/Components/FormControl.vue';
|
||||||
</NotificationBarInCard>
|
</NotificationBarInCard>
|
||||||
|
|
||||||
<FormField label="Email" label-for="email" help="Please enter your email">
|
<FormField label="Email" label-for="email" help="Please enter your email">
|
||||||
<FormControl v-model="form.email" :icon="mdiAccount" id="email" autocomplete="email" type="email"
|
<FormControl v-model="form.email" :icon="mdiAccount" id="email" autocomplete="email" type="email" required />
|
||||||
required />
|
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField label="Password" label-for="password" help="Please enter your password">
|
<FormField label="Password" label-for="password" help="Please enter your password">
|
||||||
<FormControl v-model="form.password" :icon="mdiAsterisk" type="password" id="password"
|
<FormControl
|
||||||
autocomplete="current-password" required />
|
v-model="form.password"
|
||||||
|
:icon="mdiAsterisk"
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
autocomplete="current-password"
|
||||||
|
required
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormCheckRadioGroup v-model="form.remember" name="remember" :options="{ remember: 'Remember' }" />
|
<FormCheckRadioGroup v-model="form.remember" name="remember" :options="{ remember: 'Remember' }" />
|
||||||
|
@ -71,20 +75,26 @@ import FormControl from '@/Components/FormControl.vue';
|
||||||
<!-- buttons -->
|
<!-- buttons -->
|
||||||
<BaseLevel>
|
<BaseLevel>
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type="submit" color="info" label="Login" :class="{ 'opacity-25': form.processing }"
|
<BaseButton
|
||||||
v-bind:disabled="form.processing" />
|
type="submit"
|
||||||
|
color="info"
|
||||||
|
label="Login"
|
||||||
|
:class="{ 'opacity-25': form.processing }"
|
||||||
|
v-bind:disabled="form.processing"
|
||||||
|
/>
|
||||||
<!-- <BaseButton v-if="canResetPassword" :route-name="route('password.request')" color="info" outline
|
<!-- <BaseButton v-if="canResetPassword" :route-name="route('password.request')" color="info" outline
|
||||||
label="Remind" /> -->
|
label="Remind" /> -->
|
||||||
</BaseButtons>
|
</BaseButtons>
|
||||||
<Link :href="stardust.route('app.register.show')"> Register </Link>
|
<!-- <Link :href="stardust.route('app.register.show')"> Register </Link> -->
|
||||||
</BaseLevel>
|
</BaseLevel>
|
||||||
</CardBox>
|
</CardBox>
|
||||||
</SectionFullScreen>
|
</SectionFullScreen>
|
||||||
</LayoutGuest>
|
</LayoutGuest>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { useForm, Head, Link } from '@inertiajs/vue3';
|
import { useForm, Head } from '@inertiajs/vue3';
|
||||||
|
import { Ref } from 'vue';
|
||||||
// import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
|
// import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
|
||||||
import { mdiAccount, mdiAsterisk } from '@mdi/js';
|
import { mdiAccount, mdiAsterisk } from '@mdi/js';
|
||||||
import LayoutGuest from '@/Layouts/LayoutGuest.vue';
|
import LayoutGuest from '@/Layouts/LayoutGuest.vue';
|
||||||
|
@ -101,18 +111,18 @@ import NotificationBarInCard from '@/Components/NotificationBarInCard.vue';
|
||||||
import BaseLevel from '@/Components/BaseLevel.vue';
|
import BaseLevel from '@/Components/BaseLevel.vue';
|
||||||
|
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
import NotificationBar from '@/Components/NotificationBar.vue';
|
// import NotificationBar from '@/Components/NotificationBar.vue';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { usePage } from '@inertiajs/vue3';
|
import { usePage } from '@inertiajs/vue3';
|
||||||
|
|
||||||
// interface IErrorMessage {
|
// interface IErrorMessage {
|
||||||
// [key: string]: Array<string>;
|
// [key: string]: Array<string>;
|
||||||
// }
|
// }
|
||||||
const flash = computed(() => {
|
const flash: Ref<any> = computed(() => {
|
||||||
return usePage().props.flash;
|
return usePage().props.flash;
|
||||||
});
|
});
|
||||||
|
|
||||||
const props = defineProps({
|
defineProps({
|
||||||
canResetPassword: Boolean,
|
canResetPassword: Boolean,
|
||||||
status: {
|
status: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -137,9 +147,9 @@ const submit = async() => {
|
||||||
remember: form.remember && form.remember.length ? 'on' : '',
|
remember: form.remember && form.remember.length ? 'on' : '',
|
||||||
}))
|
}))
|
||||||
.post(stardust.route('login.store'), {
|
.post(stardust.route('login.store'), {
|
||||||
// onFinish: () => {
|
onFinish: () => {
|
||||||
// form.reset('password');
|
form.reset('password');
|
||||||
// }
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { computed, ref, onMounted } from 'vue';
|
import { computed, ref, onMounted } from 'vue';
|
||||||
import { MainService } from '@/Stores/main';
|
import { MainService } from '@/Stores/main';
|
||||||
|
// import { Inertia } from '@inertiajs/inertia';
|
||||||
import {
|
import {
|
||||||
mdiAccountMultiple,
|
mdiAccountMultiple,
|
||||||
mdiCartOutline,
|
|
||||||
mdiDatabaseOutline,
|
mdiDatabaseOutline,
|
||||||
mdiChartTimelineVariant,
|
mdiChartTimelineVariant,
|
||||||
mdiFinance,
|
mdiFinance,
|
||||||
|
@ -13,7 +13,7 @@ import {
|
||||||
mdiGithub,
|
mdiGithub,
|
||||||
mdiChartPie,
|
mdiChartPie,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import { containerMaxW } from '@/config.js'; // "xl:max-w-6xl xl:mx-auto"
|
// import { containerMaxW } from '@/config.js'; // "xl:max-w-6xl xl:mx-auto"
|
||||||
import * as chartConfig from '@/Components/Charts/chart.config.js';
|
import * as chartConfig from '@/Components/Charts/chart.config.js';
|
||||||
import LineChart from '@/Components/Charts/LineChart.vue';
|
import LineChart from '@/Components/Charts/LineChart.vue';
|
||||||
import SectionMain from '@/Components/SectionMain.vue';
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
@ -27,7 +27,7 @@ import CardBoxClient from '@/Components/CardBoxClient.vue';
|
||||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
import SectionBannerStarOnGitHub from '@/Components/SectionBannerStarOnGitea.vue';
|
import SectionBannerStarOnGitHub from '@/Components/SectionBannerStarOnGitea.vue';
|
||||||
const chartData = ref(null);
|
const chartData = ref();
|
||||||
const fillChartData = () => {
|
const fillChartData = () => {
|
||||||
chartData.value = chartConfig.sampleChartData();
|
chartData.value = chartConfig.sampleChartData();
|
||||||
};
|
};
|
||||||
|
@ -42,7 +42,7 @@ mainService.fetch('history');
|
||||||
mainService.fetchApi('authors');
|
mainService.fetchApi('authors');
|
||||||
mainService.fetchApi('datasets');
|
mainService.fetchApi('datasets');
|
||||||
|
|
||||||
const clientBarItems = computed(() => mainService.clients.slice(0, 4));
|
// const clientBarItems = computed(() => mainService.clients.slice(0, 4));
|
||||||
const transactionBarItems = computed(() => mainService.history);
|
const transactionBarItems = computed(() => mainService.history);
|
||||||
|
|
||||||
const authorBarItems = computed(() => mainService.authors.slice(0, 4));
|
const authorBarItems = computed(() => mainService.authors.slice(0, 4));
|
||||||
|
@ -109,9 +109,9 @@ const datasets = computed(() => mainService.datasets);
|
||||||
|
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountMultiple" title="Submitters (to do)" />
|
<SectionTitleLineWithButton :icon="mdiAccountMultiple" title="Submitters (to do)" />
|
||||||
|
|
||||||
<!-- <NotificationBar color="info" :icon="mdiMonitorCellphone">
|
<NotificationBar color="info" :icon="mdiMonitorCellphone">
|
||||||
<b>Responsive table.</b> Collapses on mobile
|
<b>Responsive table.</b> Collapses on mobile
|
||||||
</NotificationBar> -->
|
</NotificationBar>
|
||||||
|
|
||||||
<CardBox :icon="mdiMonitorCellphone" title="Responsive table" has-table>
|
<CardBox :icon="mdiMonitorCellphone" title="Responsive table" has-table>
|
||||||
<TableSampleClients />
|
<TableSampleClients />
|
||||||
|
|
604
resources/js/Pages/Submitter/Dataset/Create.vue
Normal file
604
resources/js/Pages/Submitter/Dataset/Create.vue
Normal file
|
@ -0,0 +1,604 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Head, useForm } from '@inertiajs/vue3';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Dataset, Title } from '@/Dataset';
|
||||||
|
import { mdiDatabasePlus, mdiMinusCircle, mdiPlusCircle, mdiFinance, mdiInformationOutline, mdiBookOpenPageVariant } from '@mdi/js';
|
||||||
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
|
import CardBox from '@/Components/CardBox.vue';
|
||||||
|
import FormField from '@/Components/FormField.vue';
|
||||||
|
import FormControl from '@/Components/FormControl.vue';
|
||||||
|
import FormCheckRadioGroup from '@/Components/FormCheckRadioGroup.vue';
|
||||||
|
// import BaseDivider from '@/Components/BaseDivider.vue';
|
||||||
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
|
// import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
// import { Inertia } from '@inertiajs/inertia';
|
||||||
|
import CardBoxModal from '@/Components/CardBoxModal.vue';
|
||||||
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
|
|
||||||
|
import IconWizard from '@/Components/Icons/Wizard.vue';
|
||||||
|
import IconMandatory from '@/Components/Icons/Mandatory.vue';
|
||||||
|
import IconLanguage from '@/Components/Icons/Language.vue';
|
||||||
|
import IconRecommendet from '@/Components/Icons/Recommendet.vue';
|
||||||
|
import IconConfirm from '@/Components/Icons/Confirm.vue';
|
||||||
|
import SearchAutocomplete from '@/Components/SearchAutocomplete.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
licenses: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
doctypes: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
titletypes: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
descriptiontypes: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
errors: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// const form = useForm({
|
||||||
|
// language: '',
|
||||||
|
// licenses: [],
|
||||||
|
// type: '',
|
||||||
|
// titles: [{ value: '', type: 'Main', language: Dataset.language }],
|
||||||
|
// });
|
||||||
|
// let language: (string | Ref<string>) = ref('');
|
||||||
|
let language = ref('');
|
||||||
|
let dataset = {
|
||||||
|
language: language,
|
||||||
|
licenses: [],
|
||||||
|
rights: false,
|
||||||
|
type: '',
|
||||||
|
creating_corporation: 'Tethys RDR',
|
||||||
|
titles: [{ value: '', type: 'Main', language: language }],
|
||||||
|
descriptions: [{ value: '', type: 'Abstract', language: language }],
|
||||||
|
// errors: undefined,
|
||||||
|
};
|
||||||
|
// const form = useForm({
|
||||||
|
// language: language,
|
||||||
|
// licenses: [],
|
||||||
|
// rights: false,
|
||||||
|
// type: '',
|
||||||
|
// creating_corporation: 'Tethys RDR',
|
||||||
|
// titles: [{ value: '', type: 'Main', language: language }],
|
||||||
|
// descriptions: [{ value: '', type: 'Abstract', language: language }],
|
||||||
|
// });
|
||||||
|
const form = useForm<Dataset>(dataset);
|
||||||
|
// dataset.language.value = 'de';
|
||||||
|
|
||||||
|
// const emit = defineEmits(['update:modelValue', 'setRef']);
|
||||||
|
// computed({
|
||||||
|
// get: () => form.rights,
|
||||||
|
// set: (value) => {
|
||||||
|
// emit('update:modelValue', value);
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
const isModalActive = ref(false);
|
||||||
|
const formStep = ref(1);
|
||||||
|
|
||||||
|
// const submit = async () => {
|
||||||
|
// await router.post(stardust.route('user.store'), form, {
|
||||||
|
// onSuccess: () => {
|
||||||
|
// form.reset(), (formStep.value = 1);
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
const nextStep = async () => {
|
||||||
|
let route = stardust.route('dataset.first.step');
|
||||||
|
if (formStep.value == 2) {
|
||||||
|
route = stardust.route('dataset.second.step');
|
||||||
|
}
|
||||||
|
// formStep.value++;
|
||||||
|
await form
|
||||||
|
.transform((data) => ({
|
||||||
|
...data,
|
||||||
|
rights: form.rights && form.rights == true ? 'true' : 'false',
|
||||||
|
}))
|
||||||
|
.post(route, {
|
||||||
|
form,
|
||||||
|
onSuccess: () => {
|
||||||
|
formStep.value++;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const prevStep = () => {
|
||||||
|
formStep.value--;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addTitle = () => {
|
||||||
|
let newTitle: Title = { value: '', language: '', type: '' };
|
||||||
|
//this.dataset.files.push(uploadedFiles[i]);
|
||||||
|
form.titles.push(newTitle);
|
||||||
|
};
|
||||||
|
const removeTitle = (key) => {
|
||||||
|
form.titles.splice(key, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addDescription = () => {
|
||||||
|
let newDescription = { value: '', language: '', type: '' };
|
||||||
|
//this.dataset.files.push(uploadedFiles[i]);
|
||||||
|
form.descriptions.push(newDescription);
|
||||||
|
};
|
||||||
|
const removeDescription = (key) => {
|
||||||
|
form.descriptions.splice(key, 1);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CardBoxModal v-model="isModalActive" title="Einverständniserklärung *">
|
||||||
|
Mit dem Setzen des Hakens bestätige ich hiermit
|
||||||
|
<ul class="list-decimal">
|
||||||
|
<li>
|
||||||
|
die Data Policy von Tethys RDR sowie die Terms & Conditions von Tethys gelesen und verstanden zu haben (<a
|
||||||
|
href="/docs/HandbuchTethys.pdf"
|
||||||
|
target="_blank"
|
||||||
|
>siehe hier</a
|
||||||
|
>)
|
||||||
|
</li>
|
||||||
|
<li>das Einverständnis aller Co-Autoren über die bevorstehende Datenpublikation schriftlich eingeholt zu haben</li>
|
||||||
|
<li>sowohl mit der Data Policy als auch mit den Terms & Conditions einverstanden zu sein</li>
|
||||||
|
</ul>
|
||||||
|
</CardBoxModal>
|
||||||
|
|
||||||
|
<LayoutAuthenticated>
|
||||||
|
<Head title="Submit Dataset" />
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton :icon="mdiDatabasePlus" title="Submit dataset" main>
|
||||||
|
<!-- <BaseButton :route-name="stardust.route('user.index')" :icon="mdiArrowLeftBoldOutline" label="Back"
|
||||||
|
color="white" rounded-full small /> -->
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
|
||||||
|
<CardBox>
|
||||||
|
<div class="mx-4 p-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<!-- <label>{{ form.titles[0].language }}</label>
|
||||||
|
<label>{{ form.language }}</label> -->
|
||||||
|
<icon-wizard :is-current="formStep == 1" :is-checked="formStep > 1" :label="'Language'">
|
||||||
|
<icon-language></icon-language>
|
||||||
|
</icon-wizard>
|
||||||
|
|
||||||
|
<icon-wizard :is-current="formStep == 2" :is-checked="formStep > 2" :label="'Mandatory'">
|
||||||
|
<icon-mandatory></icon-mandatory>
|
||||||
|
</icon-wizard>
|
||||||
|
|
||||||
|
<icon-wizard :is-current="formStep == 3" :is-checked="formStep > 3" :label="'Recommendet'">
|
||||||
|
<icon-recommendet></icon-recommendet>
|
||||||
|
</icon-wizard>
|
||||||
|
|
||||||
|
<icon-wizard :is-current="formStep == 4" :is-checked="false" :label="'Confirm'" :is-last-step="true">
|
||||||
|
<icon-confirm></icon-confirm>
|
||||||
|
</icon-wizard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- mt-8: margin-top: 2rem; /* 32px */ 4 p-4: spacing 1rem 16px-->
|
||||||
|
<div class="mt-8 p-4">
|
||||||
|
<div v-if="formStep == 1">
|
||||||
|
<div class="flex flex-col md:flex-row">
|
||||||
|
<FormField
|
||||||
|
label="Language *"
|
||||||
|
help="required: select dataset main language"
|
||||||
|
:class="{ 'text-red-400': errors.language }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.language"
|
||||||
|
:type="'select'"
|
||||||
|
placeholder="[Enter Language]"
|
||||||
|
:errors="form.errors.language"
|
||||||
|
:options="['de', 'en']"
|
||||||
|
>
|
||||||
|
<div class="text-red-400 text-sm" v-if="form.errors.language">
|
||||||
|
{{ form.errors.language.join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
label="Licenses"
|
||||||
|
wrap-body
|
||||||
|
:class="{ 'text-red-400': form.errors.licenses }"
|
||||||
|
class="mt-8 w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormCheckRadioGroup v-model="form.licenses" name="roles" is-column :options="props.licenses" />
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<!-- <label for="rights">
|
||||||
|
<input class="form-checkbox" name="rights" id="rights" type="checkbox" v-model="dataset.rights" />
|
||||||
|
terms and conditions
|
||||||
|
</label> -->
|
||||||
|
<FormField
|
||||||
|
label="Rights"
|
||||||
|
help="You must agree to continue"
|
||||||
|
wrap-body
|
||||||
|
:class="{ 'text-red-400': form.errors.rights }"
|
||||||
|
class="mt-8 w-full mx-2 flex-1 flex-col"
|
||||||
|
>
|
||||||
|
<label for="rights" class="checkbox mr-6 mb-3 last:mr-0">
|
||||||
|
<input type="checkbox" id="rights" required v-model="form.rights" />
|
||||||
|
<span class="check" />
|
||||||
|
<a class="pl-2" target="_blank">terms and conditions </a>
|
||||||
|
<!-- <BaseButton color="modern" :icon="mdiInformationOutline" small @click="isModalActive = true" /> -->
|
||||||
|
<BaseIcon
|
||||||
|
v-if="mdiInformationOutline"
|
||||||
|
:path="mdiInformationOutline"
|
||||||
|
@click.prevent="isModalActive = true"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</FormField>
|
||||||
|
<div class="text-red-400 text-sm" v-if="errors.rights && Array.isArray(errors.rights)">
|
||||||
|
<!-- {{ errors.password_confirmation }} -->
|
||||||
|
{{ errors.rights.join(', ') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="formStep == 2">
|
||||||
|
<!-- <CardBox title="Performance" :icon="mdiFinance" :header-icon="mdiReload" class="mb-6"> -->
|
||||||
|
<div class="flex flex-col md:flex-row">
|
||||||
|
<FormField
|
||||||
|
label="Dataset Type *"
|
||||||
|
help="required: dataset type"
|
||||||
|
: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 --"
|
||||||
|
:errors="errors.type"
|
||||||
|
:options="doctypes"
|
||||||
|
>
|
||||||
|
<div class="text-red-400 text-sm" v-if="form.errors.type && Array.isArray(form.errors.type)">
|
||||||
|
{{ form.errors.type.join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<!-- <div class="w-full mx-2 flex-1 svelte-1l8159u"></div> -->
|
||||||
|
<!-- Creating Corporation -->
|
||||||
|
<FormField
|
||||||
|
label="Creating Corporation *"
|
||||||
|
:class="{ 'text-red-400': form.errors.creating_corporation }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.creating_corporation"
|
||||||
|
type="text"
|
||||||
|
placeholder="[enter creating corporation]"
|
||||||
|
:is-read-only="true"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="form.errors.creating_corporation && Array.isArray(form.errors.creating_corporation)"
|
||||||
|
>
|
||||||
|
{{ form.errors.creating_corporation.join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
<!-- <BaseDivider /> -->
|
||||||
|
|
||||||
|
<!-- titles -->
|
||||||
|
<CardBox
|
||||||
|
class="mb-6"
|
||||||
|
:has-form-data="true"
|
||||||
|
title="Titles"
|
||||||
|
:icon="mdiFinance"
|
||||||
|
:header-icon="mdiPlusCircle"
|
||||||
|
v-on:header-icon-click="addTitle()"
|
||||||
|
>
|
||||||
|
<!-- <div class="py-6 border-t border-gray-100 dark:border-slate-800"> -->
|
||||||
|
<div class="flex flex-col md:flex-row">
|
||||||
|
<FormField
|
||||||
|
label="Main Title *"
|
||||||
|
help="required: main title"
|
||||||
|
: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" placeholder="[enter main title]">
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="form.errors['titles.0.value'] && Array.isArray(form.errors['titles.0.value'])"
|
||||||
|
>
|
||||||
|
{{ form.errors['titles.0.value'].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Main Title Language*"
|
||||||
|
help="required: main title language"
|
||||||
|
:class="{ 'text-red-400': form.errors['titles.0.language'] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl required v-model="form.titles[0].language" type="text" :is-read-only="true">
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="form.errors['titles.0.language'] && Array.isArray(form.errors['titles.0.language'])"
|
||||||
|
>
|
||||||
|
{{ form.errors['titles.0.language'].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
<label v-if="form.titles.length > 1">additional titles </label>
|
||||||
|
<!-- <BaseButton :icon="mdiPlusCircle" @click.prevent="addTitle()" color="modern" rounded-full small /> -->
|
||||||
|
<div v-if="form.titles.length > 1">
|
||||||
|
<div v-for="(item, index) in form.titles">
|
||||||
|
<div class="flex flex-col md:flex-row" v-if="item.type != 'Main'">
|
||||||
|
<FormField v-if="item.type != 'Main'" label="Remove">
|
||||||
|
<BaseButton
|
||||||
|
:icon="mdiMinusCircle"
|
||||||
|
class="mt-1"
|
||||||
|
@click.prevent="removeTitle(index)"
|
||||||
|
color="modern"
|
||||||
|
small
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Title Value *"
|
||||||
|
:class="{ 'text-red-400': form.errors[`titles.${index}.value`] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.titles[index].value"
|
||||||
|
type="text"
|
||||||
|
placeholder="[enter main title]"
|
||||||
|
>
|
||||||
|
<div class="text-red-400 text-sm" v-if="form.errors[`titles.${index}.value`]">
|
||||||
|
{{ form.errors[`titles.${index}.value`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Title Type*"
|
||||||
|
:class="{ 'text-red-400': form.errors[`titles.${index}.type`] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.titles[index].type"
|
||||||
|
type="select"
|
||||||
|
:options="titletypes"
|
||||||
|
placeholder="[select title type]"
|
||||||
|
>
|
||||||
|
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors[`titles.${index}.type`])">
|
||||||
|
{{ form.errors[`titles.${index}.type`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Title Language*"
|
||||||
|
:class="{ 'text-red-400': form.errors[`titles.${index}.language`] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.titles[index].language"
|
||||||
|
type="select"
|
||||||
|
:options="['de', 'en']"
|
||||||
|
placeholder="[select title language]"
|
||||||
|
>
|
||||||
|
<div class="text-red-400 text-sm" v-if="form.errors[`titles.${index}.language`]">
|
||||||
|
{{ form.errors[`titles.${index}.language`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- </div> -->
|
||||||
|
</CardBox>
|
||||||
|
|
||||||
|
<!-- Descriptions -->
|
||||||
|
<CardBox
|
||||||
|
class="mb-6"
|
||||||
|
:has-form-data="true"
|
||||||
|
title="Descriptions"
|
||||||
|
:header-icon="mdiPlusCircle"
|
||||||
|
v-on:header-icon-click="addDescription()"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col md:flex-row">
|
||||||
|
<FormField
|
||||||
|
label="Main Abstract *"
|
||||||
|
help="required: main abstract"
|
||||||
|
:class="{ 'text-red-400': form.errors['descriptions.0.value'] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.descriptions[0].value"
|
||||||
|
type="textarea"
|
||||||
|
placeholder="[enter main abstract]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="form.errors['descriptions.0.value'] && Array.isArray(form.errors['descriptions.0.value'])"
|
||||||
|
>
|
||||||
|
{{ form.errors['descriptions.0.value'].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Main Title Language*"
|
||||||
|
help="required: main abstract language"
|
||||||
|
:class="{ 'text-red-400': form.errors['descriptions.0.language'] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl required v-model="form.descriptions[0].language" type="text" :is-read-only="true">
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="
|
||||||
|
form.errors['descriptions.0.value'] && Array.isArray(form.errors['descriptions.0.language'])
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ form.errors['descriptions.0.language'].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
<label v-if="form.descriptions.length > 1">additional descriptions: </label>
|
||||||
|
<!-- <BaseButton :icon="mdiPlusCircle" @click.prevent="addTitle()" color="modern" rounded-full small /> -->
|
||||||
|
<div v-if="form.descriptions.length > 1">
|
||||||
|
<div v-for="(item, index) in form.descriptions">
|
||||||
|
<div class="flex flex-col md:flex-row" v-if="item.type != 'Abstract'">
|
||||||
|
<FormField v-if="item.type != 'Abstract'" label="Remove">
|
||||||
|
<BaseButton
|
||||||
|
:icon="mdiMinusCircle"
|
||||||
|
class="mt-1"
|
||||||
|
@click.prevent="removeDescription(index)"
|
||||||
|
color="modern"
|
||||||
|
small
|
||||||
|
/>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Description Value *"
|
||||||
|
:class="{ 'text-red-400': form.errors[`descriptions.${index}.value`] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.descriptions[index].value"
|
||||||
|
type="text"
|
||||||
|
placeholder="[enter additional description]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="
|
||||||
|
form.errors[`descriptions.${index}.value`] &&
|
||||||
|
Array.isArray(form.errors[`descriptions.${index}.value`])
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ form.errors[`descriptions.${index}.value`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Description Type *"
|
||||||
|
:class="{ 'text-red-400': form.errors[`descriptions.${index}.type`] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.descriptions[index].type"
|
||||||
|
type="select"
|
||||||
|
:options="descriptiontypes"
|
||||||
|
placeholder="[select description type]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="
|
||||||
|
form.errors[`descriptions.${index}.type`] &&
|
||||||
|
Array.isArray(form.errors[`descriptions.${index}.type`])
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ form.errors[`descriptions.${index}.type`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
<FormField
|
||||||
|
label="Description Language*"
|
||||||
|
:class="{ 'text-red-400': form.errors[`titdescriptionsles.${index}.language`] }"
|
||||||
|
class="w-full mx-2 flex-1"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
required
|
||||||
|
v-model="form.descriptions[index].language"
|
||||||
|
type="select"
|
||||||
|
:options="['de', 'en']"
|
||||||
|
placeholder="[select title language]"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="text-red-400 text-sm"
|
||||||
|
v-if="form.errors && Array.isArray(form.errors[`descriptions.${index}.language`])"
|
||||||
|
>
|
||||||
|
{{ form.errors[`descriptions.${index}.language`].join(', ') }}
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardBox>
|
||||||
|
|
||||||
|
<CardBox class="mb-6" :has-form-data="true" title="Authors" :icon="mdiBookOpenPageVariant" >
|
||||||
|
<SearchAutocomplete
|
||||||
|
source="/api/persons"
|
||||||
|
:response-property="'first_name'"
|
||||||
|
placeholder="search in person table...."
|
||||||
|
></SearchAutocomplete>
|
||||||
|
</CardBox>
|
||||||
|
<!-- <SectionTitleLineWithButton :icon="mdiChartPie" title="Trends overview (to do publications per year)" class="flex flex-col md:flex-row" >
|
||||||
|
</SectionTitleLineWithButton> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="formStep == 3">
|
||||||
|
<label>To Do: Recommendet</label>
|
||||||
|
<!-- <div class="w-full mx-2 flex-1 svelte-1l8159u">
|
||||||
|
<div class="font-bold h-6 mt-3 text-gray-600 text-xs leading-8 uppercase">Username</div>
|
||||||
|
<div class="bg-white my-2 p-1 flex border border-gray-200 rounded svelte-1l8159u">
|
||||||
|
<input placeholder="Just a hint.." class="p-1 px-2 appearance-none outline-none w-full text-gray-800" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full mx-2 flex-1 svelte-1l8159u">
|
||||||
|
<div class="font-bold h-6 mt-3 text-gray-600 text-xs leading-8 uppercase">Your Email</div>
|
||||||
|
<div class="bg-white my-2 p-1 flex border border-gray-200 rounded svelte-1l8159u">
|
||||||
|
<input placeholder="jhon@doe.com" class="p-1 px-2 appearance-none outline-none w-full text-gray-800" />
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="formStep == 4">
|
||||||
|
<label>To Do: File Upload</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="flex p-2 mt-4">
|
||||||
|
<button
|
||||||
|
v-if="formStep > 1"
|
||||||
|
@click="prevStep"
|
||||||
|
class="text-base hover:scale-110 focus:outline-none flex justify-center px-4 py-2 rounded font-bold cursor-pointer hover:bg-gray-200 bg-gray-100 text-gray-700 border duration-200 ease-in-out border-gray-600 transition"
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="flex-auto flex flex-row-reverse">
|
||||||
|
<button
|
||||||
|
v-if="formStep < 4"
|
||||||
|
@click="nextStep"
|
||||||
|
class="text-base ml-2 hover:scale-110 focus:outline-none flex justify-center px-4 py-2 rounded font-bold cursor-pointer hover:bg-teal-600 bg-teal-600 text-teal-100 border duration-200 ease-in-out border-teal-600 transition"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- <button
|
||||||
|
class="text-base hover:scale-110 focus:outline-none flex justify-center px-4 py-2 rounded font-bold cursor-pointer hover:bg-teal-200 bg-teal-100 text-teal-700 border duration-200 ease-in-out border-teal-600 transition"
|
||||||
|
>
|
||||||
|
Skip
|
||||||
|
</button> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</LayoutAuthenticated>
|
||||||
|
</template>
|
|
@ -1,62 +0,0 @@
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export const MainService = defineStore('main', {
|
|
||||||
state: () => ({
|
|
||||||
/* User */
|
|
||||||
userName: '',
|
|
||||||
userEmail: null,
|
|
||||||
userAvatar: null,
|
|
||||||
|
|
||||||
/* Field focus with ctrl+k (to register only once) */
|
|
||||||
isFieldFocusRegistered: false,
|
|
||||||
|
|
||||||
/* Sample data for starting dashboard(commonly used) */
|
|
||||||
clients: [],
|
|
||||||
history: [],
|
|
||||||
authors: [],
|
|
||||||
datasets: []
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
// payload = authenticated user
|
|
||||||
setUser(payload) {
|
|
||||||
if (payload.name) {
|
|
||||||
this.userName = payload.name;
|
|
||||||
}
|
|
||||||
if (payload.email) {
|
|
||||||
this.userEmail = payload.email;
|
|
||||||
}
|
|
||||||
if (payload.avatar) {
|
|
||||||
this.userAvatar = payload.avatar;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
fetch(sampleDataKey) {
|
|
||||||
// sampleDataKey= clients or history
|
|
||||||
axios
|
|
||||||
.get(`data-sources/${sampleDataKey}.json`)
|
|
||||||
.then((r) => {
|
|
||||||
if (r.data && r.data.data) {
|
|
||||||
this[sampleDataKey] = r.data.data;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
alert(error.message);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
fetchApi(sampleDataKey) {
|
|
||||||
// sampleDataKey= clients or history
|
|
||||||
axios
|
|
||||||
.get(`api/${sampleDataKey}`)
|
|
||||||
.then((r) => {
|
|
||||||
if (r.data) {
|
|
||||||
this[sampleDataKey] = r.data;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
alert(error.message);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
79
resources/js/Stores/main.ts
Normal file
79
resources/js/Stores/main.ts
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
interface Person {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
datasetCount: string;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TransactionItem {
|
||||||
|
amount: number;
|
||||||
|
account: string;
|
||||||
|
name: string;
|
||||||
|
date: string;
|
||||||
|
type: string;
|
||||||
|
business: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MainService = defineStore('main', {
|
||||||
|
state: () => ({
|
||||||
|
/* User */
|
||||||
|
userName: '',
|
||||||
|
userEmail: null,
|
||||||
|
userAvatar: null,
|
||||||
|
|
||||||
|
/* Field focus with ctrl+k (to register only once) */
|
||||||
|
isFieldFocusRegistered: false,
|
||||||
|
|
||||||
|
/* Sample data for starting dashboard(commonly used) */
|
||||||
|
clients: [],
|
||||||
|
history: [] as Array<TransactionItem>,
|
||||||
|
authors: [] as Array<Person>,
|
||||||
|
datasets: [],
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
// payload = authenticated user
|
||||||
|
setUser(payload) {
|
||||||
|
if (payload.name) {
|
||||||
|
this.userName = payload.name;
|
||||||
|
}
|
||||||
|
if (payload.email) {
|
||||||
|
this.userEmail = payload.email;
|
||||||
|
}
|
||||||
|
if (payload.avatar) {
|
||||||
|
this.userAvatar = payload.avatar;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch(sampleDataKey) {
|
||||||
|
// sampleDataKey= clients or history
|
||||||
|
axios
|
||||||
|
.get(`data-sources/${sampleDataKey}.json`)
|
||||||
|
.then((r) => {
|
||||||
|
if (r.data && r.data.data) {
|
||||||
|
this[sampleDataKey] = r.data.data;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert(error.message);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchApi(sampleDataKey) {
|
||||||
|
// sampleDataKey= authors or datasets
|
||||||
|
axios
|
||||||
|
.get(`api/${sampleDataKey}`)
|
||||||
|
.then((r) => {
|
||||||
|
if (r.data) {
|
||||||
|
this[sampleDataKey] = r.data;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert(error.message);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -3,11 +3,11 @@ import { createApp, h } from 'vue';
|
||||||
import { Inertia } from '@inertiajs/inertia';
|
import { Inertia } from '@inertiajs/inertia';
|
||||||
|
|
||||||
import { createInertiaApp, Link, usePage } from '@inertiajs/vue3';
|
import { createInertiaApp, Link, usePage } from '@inertiajs/vue3';
|
||||||
import DefaultLayout from '@/Layouts/Default.vue';
|
// import DefaultLayout from '@/Layouts/Default.vue';
|
||||||
|
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
import { StyleService } from '@/Stores/style.js';
|
import { StyleService } from '@/Stores/style';
|
||||||
import { LayoutService } from '@/Stores/layout.js';
|
import { LayoutService } from '@/Stores/layout';
|
||||||
import { MainService } from '@/Stores/main';
|
import { MainService } from '@/Stores/main';
|
||||||
import { darkModeKey, styleKey } from '@/config';
|
import { darkModeKey, styleKey } from '@/config';
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
@ -15,18 +15,13 @@ const pinia = createPinia();
|
||||||
import { initRoutes } from '@eidellev/adonis-stardust/client';
|
import { initRoutes } from '@eidellev/adonis-stardust/client';
|
||||||
initRoutes();
|
initRoutes();
|
||||||
|
|
||||||
// import { defineProps } from 'vue';
|
// import '@fontsource/archivo-black/index.css';
|
||||||
|
// import '@fontsource/inter/index.css';
|
||||||
// const props = defineProps({
|
|
||||||
// user: {
|
|
||||||
// type: Object,
|
|
||||||
// default: () => ({}),
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
createInertiaApp({
|
createInertiaApp({
|
||||||
progress: {
|
progress: {
|
||||||
color: '#4B5563',
|
// color: '#4B5563',
|
||||||
|
color: '#22C55E',
|
||||||
},
|
},
|
||||||
// resolve: (name) => {
|
// resolve: (name) => {
|
||||||
// const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
|
// const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
|
||||||
|
|
|
@ -22,6 +22,7 @@ export const colorsText = {
|
||||||
danger: 'text-red-500',
|
danger: 'text-red-500',
|
||||||
warning: 'text-yellow-500',
|
warning: 'text-yellow-500',
|
||||||
info: 'text-blue-500',
|
info: 'text-blue-500',
|
||||||
|
modern: 'text-teal-500',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const colorsOutline = {
|
export const colorsOutline = {
|
||||||
|
@ -44,6 +45,7 @@ export const getButtonColor = (color, isOutlined, hasHover) => {
|
||||||
danger: 'bg-red-600 dark:bg-red-500 text-white',
|
danger: 'bg-red-600 dark:bg-red-500 text-white',
|
||||||
warning: 'bg-yellow-600 dark:bg-yellow-500 text-white',
|
warning: 'bg-yellow-600 dark:bg-yellow-500 text-white',
|
||||||
info: 'bg-blue-600 dark:bg-blue-500 text-white',
|
info: 'bg-blue-600 dark:bg-blue-500 text-white',
|
||||||
|
modern: 'bg-teal-600 dark:bg-teal-500 text-white',
|
||||||
},
|
},
|
||||||
bgHover: {
|
bgHover: {
|
||||||
white: 'hover:bg-gray-50',
|
white: 'hover:bg-gray-50',
|
||||||
|
@ -56,6 +58,7 @@ export const getButtonColor = (color, isOutlined, hasHover) => {
|
||||||
warning:
|
warning:
|
||||||
'hover:bg-yellow-700 hover:border-yellow-700 hover:dark:bg-yellow-600 hover:dark:border-yellow-600',
|
'hover:bg-yellow-700 hover:border-yellow-700 hover:dark:bg-yellow-600 hover:dark:border-yellow-600',
|
||||||
info: 'hover:bg-blue-700 hover:border-blue-700 hover:dark:bg-blue-600 hover:dark:border-blue-600',
|
info: 'hover:bg-blue-700 hover:border-blue-700 hover:dark:bg-blue-600 hover:dark:border-blue-600',
|
||||||
|
modern: 'hover:bg-emerald-700 hover:border-emerald-700 hover:dark:bg-emerald-600 hover:dark:border-emerald-600',
|
||||||
},
|
},
|
||||||
borders: {
|
borders: {
|
||||||
white: 'border-gray-100',
|
white: 'border-gray-100',
|
||||||
|
@ -65,6 +68,7 @@ export const getButtonColor = (color, isOutlined, hasHover) => {
|
||||||
danger: 'border-red-600 dark:border-red-500',
|
danger: 'border-red-600 dark:border-red-500',
|
||||||
warning: 'border-yellow-600 dark:border-yellow-500',
|
warning: 'border-yellow-600 dark:border-yellow-500',
|
||||||
info: 'border-blue-600 dark:border-blue-500',
|
info: 'border-blue-600 dark:border-blue-500',
|
||||||
|
modern: 'border-teal-600 dark:border-teal-500',
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
white: 'text-black dark:text-slate-100',
|
white: 'text-black dark:text-slate-100',
|
||||||
|
@ -74,6 +78,7 @@ export const getButtonColor = (color, isOutlined, hasHover) => {
|
||||||
danger: 'text-red-600 dark:text-red-500',
|
danger: 'text-red-600 dark:text-red-500',
|
||||||
warning: 'text-yellow-600 dark:text-yellow-500',
|
warning: 'text-yellow-600 dark:text-yellow-500',
|
||||||
info: 'text-blue-600 dark:text-blue-500',
|
info: 'text-blue-600 dark:text-blue-500',
|
||||||
|
modern: 'text-teal-600 dark:text-teal-500',
|
||||||
},
|
},
|
||||||
outlineHover: {
|
outlineHover: {
|
||||||
white: 'hover:bg-gray-100 hover:text-gray-900 dark:hover:text-slate-900',
|
white: 'hover:bg-gray-100 hover:text-gray-900 dark:hover:text-slate-900',
|
||||||
|
@ -87,6 +92,7 @@ export const getButtonColor = (color, isOutlined, hasHover) => {
|
||||||
warning:
|
warning:
|
||||||
'hover:bg-yellow-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-yellow-600',
|
'hover:bg-yellow-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-yellow-600',
|
||||||
info: 'hover:bg-blue-600 hover:text-white hover:dark:text-white hover:dark:border-blue-600',
|
info: 'hover:bg-blue-600 hover:text-white hover:dark:text-white hover:dark:border-blue-600',
|
||||||
|
modern: 'hover:bg-teal-600 hover:text-teal hover:dark:bg-teal-100 hover:dark:text-black',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
import {
|
|
||||||
mdiAccountCircle,
|
|
||||||
mdiMonitor,
|
|
||||||
mdiGithub,
|
|
||||||
mdiAccountKey,
|
|
||||||
mdiAccountEye,
|
|
||||||
mdiAccountGroup,
|
|
||||||
mdiPalette,
|
|
||||||
} from '@mdi/js'
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
route: 'dashboard',
|
|
||||||
icon: mdiMonitor,
|
|
||||||
label: 'Dashboard'
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// route: 'permission.index',
|
|
||||||
// icon: mdiAccountKey,
|
|
||||||
// label: 'Permissions'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// route: 'role.index',
|
|
||||||
// icon: mdiAccountEye,
|
|
||||||
// label: 'Roles'
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
route: 'user.index',
|
|
||||||
icon: mdiAccountGroup,
|
|
||||||
label: 'Users'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
route: 'role.index',
|
|
||||||
icon: mdiAccountEye,
|
|
||||||
label: 'Roles'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: 'https://gitea.geologie.ac.at/geolba/tethys',
|
|
||||||
icon: mdiGithub,
|
|
||||||
label: 'Gitea',
|
|
||||||
target: '_blank'
|
|
||||||
}
|
|
||||||
]
|
|
46
resources/js/menu.ts
Normal file
46
resources/js/menu.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import {
|
||||||
|
mdiMonitor,
|
||||||
|
mdiGithub,
|
||||||
|
mdiAccountEye,
|
||||||
|
mdiAccountGroup,
|
||||||
|
mdiDatabasePlus,
|
||||||
|
} from '@mdi/js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
route: 'dashboard',
|
||||||
|
icon: mdiMonitor,
|
||||||
|
label: 'Dashboard',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// route: 'permission.index',
|
||||||
|
// icon: mdiAccountKey,
|
||||||
|
// label: 'Permissions'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// route: 'role.index',
|
||||||
|
// icon: mdiAccountEye,
|
||||||
|
// label: 'Roles'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
route: 'user.index',
|
||||||
|
icon: mdiAccountGroup,
|
||||||
|
label: 'Users',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
route: 'role.index',
|
||||||
|
icon: mdiAccountEye,
|
||||||
|
label: 'Roles',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
route: 'dataset.create',
|
||||||
|
icon: mdiDatabasePlus,
|
||||||
|
label: 'Create Dataset',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: 'https://gitea.geologie.ac.at/geolba/tethys',
|
||||||
|
icon: mdiGithub,
|
||||||
|
label: 'Gitea',
|
||||||
|
target: '_blank',
|
||||||
|
},
|
||||||
|
];
|
10
server.ts
10
server.ts
|
@ -10,10 +10,10 @@
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'reflect-metadata'
|
import 'reflect-metadata';
|
||||||
import sourceMapSupport from 'source-map-support'
|
import sourceMapSupport from 'source-map-support';
|
||||||
import { Ignitor } from '@adonisjs/core/build/standalone'
|
import { Ignitor } from '@adonisjs/core/build/standalone';
|
||||||
|
|
||||||
sourceMapSupport.install({ handleUncaughtExceptions: false })
|
sourceMapSupport.install({ handleUncaughtExceptions: false });
|
||||||
|
|
||||||
new Ignitor(__dirname).httpServer().start()
|
new Ignitor(__dirname).httpServer().start();
|
||||||
|
|
|
@ -123,3 +123,23 @@ Route.post('/edit-account-info/store/:id', 'UsersController.accountInfoStore')
|
||||||
.namespace('App/Controllers/Http/Admin')
|
.namespace('App/Controllers/Http/Admin')
|
||||||
.middleware(['auth']);
|
.middleware(['auth']);
|
||||||
// Route::post('change-password', 'UserController@changePasswordStore')->name('admin.account.password.store');
|
// Route::post('change-password', 'UserController@changePasswordStore')->name('admin.account.password.store');
|
||||||
|
|
||||||
|
Route.group(() => {
|
||||||
|
// Route.get('/user', 'UsersController.index').as('user.index');
|
||||||
|
Route.get('/dataset/create', 'DatasetController.create').as('dataset.create').middleware(['auth', 'can:dataset-submit']);
|
||||||
|
Route.post('/dataset/first/first-step', 'DatasetController.firstStep')
|
||||||
|
.as('dataset.first.step')
|
||||||
|
.middleware(['auth', 'can:dataset-submit']);
|
||||||
|
Route.post('/dataset/second/second-step', 'DatasetController.secondStep')
|
||||||
|
.as('dataset.second.step')
|
||||||
|
.middleware(['auth', 'can:dataset-submit']);
|
||||||
|
// Route.get('/user/:id', 'UsersController.show').as('user.show').where('id', Route.matchers.number());
|
||||||
|
// Route.get('/user/:id/edit', 'UsersController.edit').as('user.edit').where('id', Route.matchers.number());
|
||||||
|
// Route.put('/user/:id/update', 'UsersController.update').as('user.update').where('id', Route.matchers.number());
|
||||||
|
// Route.delete('/user/:id', 'UsersController.destroy').as('user.destroy').where('id', Route.matchers.number());
|
||||||
|
// Route.resource('user', 'DatasetController');
|
||||||
|
})
|
||||||
|
.namespace('App/Controllers/Http/Submitter')
|
||||||
|
.prefix('submitter');
|
||||||
|
// .middleware(['auth', 'can:dataset-list,dataset-publish']);
|
||||||
|
// .middleware(['auth', 'is:submitter']);
|
||||||
|
|
|
@ -8,6 +8,7 @@ Route.group(() => {
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
Route.get('authors', 'AuthorsController.index').as('author.index');
|
Route.get('authors', 'AuthorsController.index').as('author.index');
|
||||||
Route.get('datasets', 'DatasetController.index').as('dataset.index');
|
Route.get('datasets', 'DatasetController.index').as('dataset.index');
|
||||||
|
Route.get('persons', 'AuthorsController.persons').as('author.persons');
|
||||||
// Route.get("author/:id", "TodosController.show");
|
// Route.get("author/:id", "TodosController.show");
|
||||||
// Route.put("author/update", "TodosController.update");
|
// Route.put("author/update", "TodosController.update");
|
||||||
// Route.post("author", "TodosController.store");
|
// Route.post("author", "TodosController.store");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
const plugin = require("tailwindcss/plugin");
|
const plugin = require('tailwindcss/plugin');
|
||||||
|
const defaultTheme = require('tailwindcss/defaultTheme');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ['./resources/**/*.{edge,js,ts,jsx,tsx,vue}'],
|
content: ['./resources/**/*.{edge,js,ts,jsx,tsx,vue}'],
|
||||||
|
@ -10,6 +11,14 @@ module.exports = {
|
||||||
gray: 'gray',
|
gray: 'gray',
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
colors: {
|
||||||
|
'primary': '#22C55E',
|
||||||
|
'primary-dark': '#DCFCE7',
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['Inter', ...defaultTheme.fontFamily.sans],
|
||||||
|
logo: ['Archivo Black', ...defaultTheme.fontFamily.sans],
|
||||||
|
},
|
||||||
zIndex: {
|
zIndex: {
|
||||||
'-1': '-1',
|
'-1': '-1',
|
||||||
},
|
},
|
||||||
|
@ -41,37 +50,37 @@ module.exports = {
|
||||||
}, //extend
|
}, //extend
|
||||||
}, // theme
|
}, // theme
|
||||||
plugins: [
|
plugins: [
|
||||||
require("@tailwindcss/forms"),
|
require('@tailwindcss/forms'),
|
||||||
plugin(function ({ matchUtilities, theme }) {
|
plugin(function ({ matchUtilities, theme }) {
|
||||||
matchUtilities(
|
matchUtilities(
|
||||||
{
|
{
|
||||||
"aside-scrollbars": (value) => {
|
'aside-scrollbars': (value) => {
|
||||||
const track = value === "light" ? "100" : "900";
|
const track = value === 'light' ? '100' : '900';
|
||||||
const thumb = value === "light" ? "300" : "600";
|
const thumb = value === 'light' ? '300' : '600';
|
||||||
const color = value === "light" ? "gray" : value;
|
const color = value === 'light' ? 'gray' : value;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scrollbarWidth: "thin",
|
'scrollbarWidth': 'thin',
|
||||||
scrollbarColor: `${theme(`colors.${color}.${thumb}`)} ${theme(
|
'scrollbarColor': `${theme(`colors.${color}.${thumb}`)} ${theme(
|
||||||
`colors.${color}.${track}`
|
`colors.${color}.${track}`,
|
||||||
)}`,
|
)}`,
|
||||||
"&::-webkit-scrollbar": {
|
'&::-webkit-scrollbar': {
|
||||||
width: "8px",
|
width: '8px',
|
||||||
height: "8px",
|
height: '8px',
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-track": {
|
'&::-webkit-scrollbar-track': {
|
||||||
backgroundColor: theme(`colors.${color}.${track}`),
|
backgroundColor: theme(`colors.${color}.${track}`),
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb": {
|
'&::-webkit-scrollbar-thumb': {
|
||||||
borderRadius: "0.25rem",
|
borderRadius: '0.25rem',
|
||||||
backgroundColor: theme(`colors.${color}.${thumb}`),
|
backgroundColor: theme(`colors.${color}.${thumb}`),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ values: theme("asideScrollbars") }
|
{ values: theme('asideScrollbars') },
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
require("@tailwindcss/line-clamp"),
|
require('@tailwindcss/line-clamp'),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
{
|
{
|
||||||
"extends": "adonis-preset-ts/tsconfig.json",
|
"extends": "adonis-preset-ts/tsconfig.json",
|
||||||
"include": [
|
"include": [
|
||||||
"**/*"
|
// "**/*",
|
||||||
|
"**/*",
|
||||||
// "./resources/js/**/*"
|
// "./resources/js/**/*"
|
||||||
// "./resources/js/**/*.vue",
|
// "./resources/js/**/*.vue",
|
||||||
|
// "./resources/js/**/*.ts",
|
||||||
|
// "./resources/js/**/*.vue",
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user