forked from geolba/tethys.backend
- addes @adonisjs/redis fo saving session into redis with redis.ts contract and config
- npm updated - added createHashValues and dlete inside File.ts - added dataset_count property inside Subject.ts - corrected rotes.ts with correct permissions
This commit is contained in:
parent
d8bdce1369
commit
b6fdfbff41
|
@ -19,11 +19,15 @@
|
||||||
"./start/kernel",
|
"./start/kernel",
|
||||||
{
|
{
|
||||||
"file": "./start/inertia",
|
"file": "./start/inertia",
|
||||||
"environment": ["web"]
|
"environment": [
|
||||||
|
"web"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "./start/validator",
|
"file": "./start/validator",
|
||||||
"environment": ["web"]
|
"environment": [
|
||||||
|
"web"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"providers": [
|
"providers": [
|
||||||
|
@ -37,7 +41,8 @@
|
||||||
"@adonisjs/auth",
|
"@adonisjs/auth",
|
||||||
"@eidellev/adonis-stardust",
|
"@eidellev/adonis-stardust",
|
||||||
"./providers/QueryBuilderProvider",
|
"./providers/QueryBuilderProvider",
|
||||||
"./providers/TokenWorkerProvider"
|
"./providers/TokenWorkerProvider",
|
||||||
|
"@adonisjs/redis"
|
||||||
],
|
],
|
||||||
"metaFiles": [
|
"metaFiles": [
|
||||||
{
|
{
|
||||||
|
@ -49,15 +54,21 @@
|
||||||
"reloadServer": false
|
"reloadServer": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aceProviders": ["@adonisjs/repl"],
|
"aceProviders": [
|
||||||
|
"@adonisjs/repl"
|
||||||
|
],
|
||||||
"tests": {
|
"tests": {
|
||||||
"suites": [
|
"suites": [
|
||||||
{
|
{
|
||||||
"name": "functional",
|
"name": "functional",
|
||||||
"files": ["tests/functional/**/*.spec(.ts|.js)"],
|
"files": [
|
||||||
|
"tests/functional/**/*.spec(.ts|.js)"
|
||||||
|
],
|
||||||
"timeout": 60000
|
"timeout": 60000
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"testProviders": ["@japa/preset-adonis/TestsProvider"]
|
"testProviders": [
|
||||||
|
"@japa/preset-adonis/TestsProvider"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,3 +11,7 @@ PG_PORT=5432
|
||||||
PG_USER=lucid
|
PG_USER=lucid
|
||||||
PG_PASSWORD=
|
PG_PASSWORD=
|
||||||
PG_DB_NAME=lucid
|
PG_DB_NAME=lucid
|
||||||
|
REDIS_CONNECTION=local
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
|
|
@ -34,6 +34,7 @@ import ClamScan from 'clamscan';
|
||||||
import { ValidationException } from '@ioc:Adonis/Core/Validator';
|
import { ValidationException } from '@ioc:Adonis/Core/Validator';
|
||||||
import Drive from '@ioc:Adonis/Core/Drive';
|
import Drive from '@ioc:Adonis/Core/Drive';
|
||||||
import { Exception } from '@adonisjs/core/build/standalone';
|
import { Exception } from '@adonisjs/core/build/standalone';
|
||||||
|
import { MultipartFileContract } from '@ioc:Adonis/Core/BodyParser';
|
||||||
|
|
||||||
export default class DatasetController {
|
export default class DatasetController {
|
||||||
public async index({ auth, request, inertia }: HttpContextContract) {
|
public async index({ auth, request, inertia }: HttpContextContract) {
|
||||||
|
@ -335,8 +336,8 @@ export default class DatasetController {
|
||||||
}
|
}
|
||||||
|
|
||||||
session.flash('message', 'Dataset has been created successfully');
|
session.flash('message', 'Dataset has been created successfully');
|
||||||
// return response.redirect().toRoute('user.index');
|
return response.redirect().toRoute('user.index');
|
||||||
return response.redirect().back();
|
// return response.redirect().back();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createDatasetAndAssociations(user: User, request: HttpContextContract['request'], trx: TransactionClientContract) {
|
private async createDatasetAndAssociations(user: User, request: HttpContextContract['request'], trx: TransactionClientContract) {
|
||||||
|
@ -691,7 +692,10 @@ export default class DatasetController {
|
||||||
.preload('licenses')
|
.preload('licenses')
|
||||||
.preload('authors')
|
.preload('authors')
|
||||||
.preload('contributors')
|
.preload('contributors')
|
||||||
.preload('subjects')
|
// .preload('subjects')
|
||||||
|
.preload('subjects', (builder) => {
|
||||||
|
builder.orderBy('id', 'asc').withCount('datasets');
|
||||||
|
})
|
||||||
.preload('references')
|
.preload('references')
|
||||||
.preload('files');
|
.preload('files');
|
||||||
|
|
||||||
|
@ -779,6 +783,7 @@ export default class DatasetController {
|
||||||
throw error;
|
throw error;
|
||||||
// return response.badRequest(error.messages);
|
// return response.badRequest(error.messages);
|
||||||
}
|
}
|
||||||
|
// await request.validate(UpdateDatasetValidator);
|
||||||
const id = request.param('id');
|
const id = request.param('id');
|
||||||
|
|
||||||
let trx: TransactionClientContract | null = null;
|
let trx: TransactionClientContract | null = null;
|
||||||
|
@ -843,6 +848,25 @@ export default class DatasetController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// await dataset.useTransaction(trx).related('subjects').sync([]);
|
||||||
|
const keywords = request.input('subjects');
|
||||||
|
for (const keywordData of keywords) {
|
||||||
|
if (keywordData.id) {
|
||||||
|
const subject = await Subject.findOrFail(keywordData.id);
|
||||||
|
// await dataset.useTransaction(trx).related('subjects').attach([keywordData.id]);
|
||||||
|
subject.value = keywordData.value;
|
||||||
|
subject.type = keywordData.type;
|
||||||
|
subject.external_key = keywordData.external_key;
|
||||||
|
if (subject.$isDirty) {
|
||||||
|
await subject.save();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const keyword = new Subject();
|
||||||
|
keyword.fill(keywordData);
|
||||||
|
await dataset.useTransaction(trx).related('subjects').save(keyword, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Save already existing files
|
// Save already existing files
|
||||||
const files = request.input('fileInputs', []);
|
const files = request.input('fileInputs', []);
|
||||||
for (const fileData of files) {
|
for (const fileData of files) {
|
||||||
|
@ -857,43 +881,57 @@ export default class DatasetController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle new uploaded files:
|
// handle new uploaded files:
|
||||||
const uploadedFiles = request.files('files');
|
const uploadedFiles: MultipartFileContract[] = request.files('files');
|
||||||
if (Array.isArray(uploadedFiles) && uploadedFiles.length > 0) {
|
if (Array.isArray(uploadedFiles) && uploadedFiles.length > 0) {
|
||||||
// let index = 1;
|
|
||||||
// for (const key in files) {
|
|
||||||
// const formFile = files[key]
|
|
||||||
// for (const fileData of files) {
|
|
||||||
for (const [index, fileData] of uploadedFiles.entries()) {
|
for (const [index, fileData] of uploadedFiles.entries()) {
|
||||||
// const uploads = request.file('uploads');
|
|
||||||
// const fileIndex = formFile.file;
|
|
||||||
// const file = uploads[fileIndex];
|
|
||||||
|
|
||||||
const fileName = `file-${cuid()}.${fileData.extname}`;
|
const fileName = `file-${cuid()}.${fileData.extname}`;
|
||||||
const mimeType = fileData.headers['content-type'] || 'application/octet-stream'; // Fallback to a default MIME type
|
|
||||||
const datasetFolder = `files/${dataset.id}`;
|
const datasetFolder = `files/${dataset.id}`;
|
||||||
await fileData.moveToDisk(
|
|
||||||
datasetFolder,
|
await fileData.moveToDisk(datasetFolder, { name: fileName, overwrite: true }, 'local');
|
||||||
{
|
|
||||||
name: fileName,
|
|
||||||
overwrite: true, // overwrite in case of conflict
|
|
||||||
},
|
|
||||||
'local',
|
|
||||||
);
|
|
||||||
// save file metadata into db
|
|
||||||
const newFile = new File();
|
|
||||||
newFile.pathName = `${datasetFolder}/${fileName}`;
|
|
||||||
newFile.fileSize = fileData.size;
|
|
||||||
newFile.mimeType = mimeType;
|
|
||||||
newFile.label = fileData.clientName;
|
|
||||||
newFile.sortOrder = index;
|
|
||||||
newFile.visibleInFrontdoor = true;
|
|
||||||
newFile.visibleInOai = true;
|
|
||||||
// let path = coverImage.filePath;
|
// let path = coverImage.filePath;
|
||||||
await dataset.useTransaction(trx).related('files').save(newFile);
|
|
||||||
await newFile.createHashValues();
|
const { clientFileName, sortOrder } = this.extractVariableNameAndSortOrder(fileData.clientName);
|
||||||
|
const mimeType = fileData.headers['content-type'] || 'application/octet-stream'; // Fallback to a default MIME type
|
||||||
|
// save file metadata into db
|
||||||
|
// const newFile = new File();
|
||||||
|
// newFile.pathName = `${datasetFolder}/${fileName}`;
|
||||||
|
// newFile.fileSize = fileData.size;
|
||||||
|
// newFile.mimeType = mimeType;
|
||||||
|
// newFile.label = clientFileName;
|
||||||
|
// newFile.sortOrder = sortOrder ? sortOrder : index;
|
||||||
|
// newFile.visibleInFrontdoor = true;
|
||||||
|
// newFile.visibleInOai = true;
|
||||||
|
|
||||||
|
const newFile = await dataset
|
||||||
|
.useTransaction(trx)
|
||||||
|
.related('files')
|
||||||
|
.create({
|
||||||
|
pathName: `${datasetFolder}/${fileName}`,
|
||||||
|
fileSize: fileData.size,
|
||||||
|
mimeType,
|
||||||
|
label: clientFileName,
|
||||||
|
sortOrder: sortOrder || index,
|
||||||
|
visibleInFrontdoor: true,
|
||||||
|
visibleInOai: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// save many related HashValue Instances to the file:
|
||||||
|
await newFile.createHashValues(trx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save collection
|
||||||
|
// const collection: Collection | null = await Collection.query().where('id', 21).first();
|
||||||
|
// collection && (await dataset.useTransaction(trx).related('collections').attach([collection.id]));
|
||||||
|
|
||||||
|
// // Save coverage
|
||||||
|
// if (data.coverage && !this.containsOnlyNull(data.coverage)) {
|
||||||
|
// const formCoverage = request.input('coverage');
|
||||||
|
// const coverage = await dataset.related('coverage').updateOrCreate({ dataset_id: dataset.id }, formCoverage);
|
||||||
|
// } else if (data.coverage && this.containsOnlyNull(data.coverage) && !dataset.coverage) {
|
||||||
|
// await dataset.coverage().delete();
|
||||||
|
// }
|
||||||
|
|
||||||
const input = request.only(['project_id', 'embargo_date', 'language', 'type', 'creating_corporation']);
|
const input = request.only(['project_id', 'embargo_date', 'language', 'type', 'creating_corporation']);
|
||||||
// dataset.type = request.input('type');
|
// dataset.type = request.input('type');
|
||||||
dataset.merge(input);
|
dataset.merge(input);
|
||||||
|
@ -911,11 +949,30 @@ export default class DatasetController {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
session.flash('message', 'Dataset has been created successfully');
|
session.flash('message', 'Dataset has been updated successfully');
|
||||||
// return response.redirect().toRoute('user.index');
|
// return response.redirect().toRoute('user.index');
|
||||||
return response.redirect().back();
|
return response.redirect().back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extractVariableNameAndSortOrder(inputString: string): { clientFileName: string; sortOrder?: number } {
|
||||||
|
const regex = /^([^?]+)(?:\?([^=]+)=([^&]+))?/;
|
||||||
|
const match = inputString.match(regex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const clientFileName = match[1];
|
||||||
|
|
||||||
|
const param = match[2];
|
||||||
|
let sortOrder;
|
||||||
|
if (param && param.toLowerCase() === 'sortorder') {
|
||||||
|
sortOrder = parseInt(match[3], 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { clientFileName, sortOrder };
|
||||||
|
} else {
|
||||||
|
return { clientFileName: '', sortOrder: undefined }; // Or handle as needed for no match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async delete({ request, inertia, response, session }) {
|
public async delete({ request, inertia, response, session }) {
|
||||||
const id = request.param('id');
|
const id = request.param('id');
|
||||||
try {
|
try {
|
||||||
|
@ -923,8 +980,8 @@ export default class DatasetController {
|
||||||
.preload('user', (builder) => {
|
.preload('user', (builder) => {
|
||||||
builder.select('id', 'login');
|
builder.select('id', 'login');
|
||||||
})
|
})
|
||||||
.preload('files')
|
|
||||||
.where('id', id)
|
.where('id', id)
|
||||||
|
.preload('files')
|
||||||
.firstOrFail();
|
.firstOrFail();
|
||||||
const validStates = ['inprogress', 'rejected_editor'];
|
const validStates = ['inprogress', 'rejected_editor'];
|
||||||
if (!validStates.includes(dataset.server_state)) {
|
if (!validStates.includes(dataset.server_state)) {
|
||||||
|
@ -958,21 +1015,27 @@ export default class DatasetController {
|
||||||
if (validStates.includes(dataset.server_state)) {
|
if (validStates.includes(dataset.server_state)) {
|
||||||
if (dataset.files && dataset.files.length > 0) {
|
if (dataset.files && dataset.files.length > 0) {
|
||||||
for (const file of dataset.files) {
|
for (const file of dataset.files) {
|
||||||
if (file.pathName) {
|
// overwriten delete method also delets file on filespace
|
||||||
// delete file from filesystem
|
await file.delete();
|
||||||
await Drive.delete(file.pathName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// delete dataset wirh relation from db
|
const datasetFolder = `files/${params.id}`;
|
||||||
await dataset.delete();
|
const folderExists = await Drive.exists(datasetFolder);
|
||||||
session.flash({ message: 'You have deleted 1 dataset!' });
|
if (folderExists) {
|
||||||
return response.redirect().toRoute('dataset.list');
|
const folderContents = await Drive.list(datasetFolder).toArray();
|
||||||
} else {
|
if (folderContents.length === 0) {
|
||||||
session.flash({
|
await Drive.delete(datasetFolder);
|
||||||
warning: `You cannot delete this dataset! The status of this dataset is "${dataset.server_state}"!`,
|
}
|
||||||
});
|
// delete dataset wirh relation from db
|
||||||
return response.redirect().back();
|
await dataset.delete();
|
||||||
|
session.flash({ message: 'You have deleted 1 dataset!' });
|
||||||
|
return response.redirect().toRoute('dataset.list');
|
||||||
|
} else {
|
||||||
|
session.flash({
|
||||||
|
warning: `You cannot delete this dataset! Invalid server_state: "${dataset.server_state}"!`,
|
||||||
|
});
|
||||||
|
return response.status(400).redirect().back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof ValidationException) {
|
if (error instanceof ValidationException) {
|
||||||
|
|
|
@ -203,7 +203,7 @@ export default class Dataset extends DatasetExtension {
|
||||||
pivotForeignKey: 'document_id',
|
pivotForeignKey: 'document_id',
|
||||||
pivotRelatedForeignKey: 'person_id',
|
pivotRelatedForeignKey: 'person_id',
|
||||||
pivotTable: 'link_documents_persons',
|
pivotTable: 'link_documents_persons',
|
||||||
pivotColumns: ['role', 'sort_order', 'allow_email_contact'],
|
pivotColumns: ['role', 'sort_order', 'allow_email_contact', 'contributor_type'],
|
||||||
onQuery(query) {
|
onQuery(query) {
|
||||||
query.wherePivot('role', 'contributor');
|
query.wherePivot('role', 'contributor');
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@ import BaseModel from './BaseModel';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
|
import { TransactionClientContract } from '@ioc:Adonis/Lucid/Database';
|
||||||
|
import Drive from '@ioc:Adonis/Core/Drive';
|
||||||
|
|
||||||
export default class File extends BaseModel {
|
export default class File extends BaseModel {
|
||||||
// private readonly _data: Uint8Array;
|
// private readonly _data: Uint8Array;
|
||||||
|
@ -116,21 +117,20 @@ export default class File extends BaseModel {
|
||||||
serializeAs: 'fileData',
|
serializeAs: 'fileData',
|
||||||
})
|
})
|
||||||
public get fileData(): string {
|
public get fileData(): string {
|
||||||
// return this.fileData;
|
try {
|
||||||
// const fileData = fs.readFileSync(path.resolve(__dirname, this.filePath));
|
const fileContent: Buffer = fs.readFileSync(this.filePath);
|
||||||
// const fileData = fs.readFileSync(this.filePath);
|
// Create a Blob from the file content
|
||||||
const fileContent: Buffer = fs.readFileSync(this.filePath);
|
// const blob = new Blob([fileContent], { type: this.type }); // Adjust
|
||||||
// Create a Blob from the file content
|
// let fileSrc = URL.createObjectURL(blob);
|
||||||
// const blob = new Blob([fileContent], { type: this.type }); // Adjust
|
// return fileSrc;
|
||||||
// let fileSrc = URL.createObjectURL(blob);
|
|
||||||
// return fileSrc;
|
|
||||||
|
|
||||||
// return Buffer.from(fileContent);
|
// create a JSON string that contains the data in the property "blob"
|
||||||
// get the buffer from somewhere
|
const json = JSON.stringify({ blob: fileContent.toString('base64') });
|
||||||
// const buff = fs.readFileSync('./test.bin');
|
return json;
|
||||||
// create a JSON string that contains the data in the property "blob"
|
} catch (err) {
|
||||||
const json = JSON.stringify({ blob: fileContent.toString('base64') });
|
// console.error(`Error reading file: ${err}`);
|
||||||
return json;
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createHashValues(trx?: TransactionClientContract) {
|
public async createHashValues(trx?: TransactionClientContract) {
|
||||||
|
@ -139,7 +139,7 @@ export default class File extends BaseModel {
|
||||||
for (const type of hashtypes) {
|
for (const type of hashtypes) {
|
||||||
const hash = new HashValue();
|
const hash = new HashValue();
|
||||||
hash.type = type;
|
hash.type = type;
|
||||||
const hashString = await this.checksumFile(this.filePath, type); // Assuming getRealHash is a method in the same model
|
const hashString = await this._checksumFile(this.filePath, type); // Assuming getRealHash is a method in the same model
|
||||||
hash.value = hashString;
|
hash.value = hashString;
|
||||||
|
|
||||||
// https://github.com/adonisjs/core/discussions/1872#discussioncomment-132289
|
// https://github.com/adonisjs/core/discussions/1872#discussioncomment-132289
|
||||||
|
@ -152,7 +152,17 @@ export default class File extends BaseModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checksumFile(path, hashName = 'md5'): Promise<string> {
|
public async delete() {
|
||||||
|
if (this.pathName) {
|
||||||
|
// Delete file from additional storage
|
||||||
|
await Drive.delete(this.pathName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the original delete method of the BaseModel to remove the record from the database
|
||||||
|
await super.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _checksumFile(path, hashName = 'md5'): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const hash = crypto.createHash(hashName);
|
const hash = crypto.createHash(hashName);
|
||||||
const stream = fs.createReadStream(path);
|
const stream = fs.createReadStream(path);
|
||||||
|
|
|
@ -69,6 +69,12 @@ export default class Person extends BaseModel {
|
||||||
return stock;
|
return stock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed()
|
||||||
|
public get pivot_contributor_type() {
|
||||||
|
const contributor_type = this.$extras.pivot_contributor_type; //my pivot column name was "stock"
|
||||||
|
return contributor_type;
|
||||||
|
}
|
||||||
|
|
||||||
@manyToMany(() => Dataset, {
|
@manyToMany(() => Dataset, {
|
||||||
pivotForeignKey: 'person_id',
|
pivotForeignKey: 'person_id',
|
||||||
pivotRelatedForeignKey: 'document_id',
|
pivotRelatedForeignKey: 'document_id',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { column, SnakeCaseNamingStrategy, manyToMany, ManyToMany, beforeCreate, beforeUpdate } from '@ioc:Adonis/Lucid/Orm';
|
import { column, SnakeCaseNamingStrategy, manyToMany, ManyToMany, computed} from '@ioc:Adonis/Lucid/Orm';
|
||||||
import BaseModel from './BaseModel';
|
import BaseModel from './BaseModel';
|
||||||
|
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
@ -44,28 +44,33 @@ export default class Subject extends BaseModel {
|
||||||
})
|
})
|
||||||
public updated_at: DateTime;
|
public updated_at: DateTime;
|
||||||
|
|
||||||
@beforeCreate()
|
// @beforeCreate()
|
||||||
@beforeUpdate()
|
// @beforeUpdate()
|
||||||
public static async resetDate(role) {
|
// public static async resetDate(role) {
|
||||||
role.created_at = this.formatDateTime(role.created_at);
|
// role.created_at = this.formatDateTime(role.created_at);
|
||||||
role.updated_at = this.formatDateTime(role.updated_at);
|
// role.updated_at = this.formatDateTime(role.updated_at);
|
||||||
}
|
// }
|
||||||
|
|
||||||
private static formatDateTime(datetime) {
|
// private static formatDateTime(datetime) {
|
||||||
let value = new Date(datetime);
|
// let value = new Date(datetime);
|
||||||
return datetime
|
// return datetime
|
||||||
? value.getFullYear() +
|
// ? value.getFullYear() +
|
||||||
'-' +
|
// '-' +
|
||||||
(value.getMonth() + 1) +
|
// (value.getMonth() + 1) +
|
||||||
'-' +
|
// '-' +
|
||||||
value.getDate() +
|
// value.getDate() +
|
||||||
' ' +
|
// ' ' +
|
||||||
value.getHours() +
|
// value.getHours() +
|
||||||
':' +
|
// ':' +
|
||||||
value.getMinutes() +
|
// value.getMinutes() +
|
||||||
':' +
|
// ':' +
|
||||||
value.getSeconds()
|
// value.getSeconds()
|
||||||
: datetime;
|
// : datetime;
|
||||||
|
// }
|
||||||
|
@computed()
|
||||||
|
public get dataset_count() : number{
|
||||||
|
const count = this.$extras.datasets_count; //my pivot column name was "stock"
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@manyToMany(() => Dataset, {
|
@manyToMany(() => Dataset, {
|
||||||
|
|
|
@ -135,7 +135,7 @@ export default class CreateDatasetValidator {
|
||||||
'required': '{{ field }} is required',
|
'required': '{{ field }} is required',
|
||||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||||
// 'confirmed': '{{ field }} is not correct',
|
// 'confirmed': '{{ field }} is not correct',
|
||||||
'licenses.minLength': 'at least {{ options.minLength }} permission must be defined',
|
'licenses.minLength': 'at least {{ options.minLength }} licenses must be defined',
|
||||||
'licenses.*.number': 'Define licences as valid numbers',
|
'licenses.*.number': 'Define licences as valid numbers',
|
||||||
'rights.equalTo': 'you must agree to continue',
|
'rights.equalTo': 'you must agree to continue',
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ export default class UpdateDatasetValidator {
|
||||||
'required': '{{ field }} is required',
|
'required': '{{ field }} is required',
|
||||||
'unique': '{{ field }} must be unique, and this value is already taken',
|
'unique': '{{ field }} must be unique, and this value is already taken',
|
||||||
// 'confirmed': '{{ field }} is not correct',
|
// 'confirmed': '{{ field }} is not correct',
|
||||||
'licenses.minLength': 'at least {{ options.minLength }} permission must be defined',
|
'licenses.minLength': 'at least {{ options.minLength }} licenses must be defined',
|
||||||
'licenses.*.number': 'Define licences as valid numbers',
|
'licenses.*.number': 'Define licences as valid numbers',
|
||||||
'rights.equalTo': 'you must agree to continue',
|
'rights.equalTo': 'you must agree to continue',
|
||||||
|
|
||||||
|
|
46
config/redis.ts
Normal file
46
config/redis.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* Config source: https://git.io/JemcF
|
||||||
|
*
|
||||||
|
* Feel free to let us know via PR, if you find something broken in this config
|
||||||
|
* file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Env from '@ioc:Adonis/Core/Env'
|
||||||
|
import { redisConfig } from '@adonisjs/redis/build/config'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Redis configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Following is the configuration used by the Redis provider to connect to
|
||||||
|
| the redis server and execute redis commands.
|
||||||
|
|
|
||||||
|
| Do make sure to pre-define the connections type inside `contracts/redis.ts`
|
||||||
|
| file for AdonisJs to recognize connections.
|
||||||
|
|
|
||||||
|
| Make sure to check `contracts/redis.ts` file for defining extra connections
|
||||||
|
*/
|
||||||
|
export default redisConfig({
|
||||||
|
connection: Env.get('REDIS_CONNECTION'),
|
||||||
|
|
||||||
|
connections: {
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| The default connection
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The main connection you want to use to execute redis commands. The same
|
||||||
|
| connection will be used by the session provider, if you rely on the
|
||||||
|
| redis driver.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
local: {
|
||||||
|
host: Env.get('REDIS_HOST'),
|
||||||
|
port: Env.get('REDIS_PORT'),
|
||||||
|
password: Env.get('REDIS_PASSWORD', ''),
|
||||||
|
db: 0,
|
||||||
|
keyPrefix: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
13
contracts/redis.ts
Normal file
13
contracts/redis.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* Contract source: https://git.io/JemcN
|
||||||
|
*
|
||||||
|
* Feel free to let us know via PR, if you find something broken in this config
|
||||||
|
* file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { InferConnectionsFromConfig } from '@adonisjs/redis/build/config'
|
||||||
|
import redisConfig from '../config/redis'
|
||||||
|
|
||||||
|
declare module '@ioc:Adonis/Addons/Redis' {
|
||||||
|
interface RedisConnectionsList extends InferConnectionsFromConfig<typeof redisConfig> {}
|
||||||
|
}
|
92
package-lock.json
generated
92
package-lock.json
generated
|
@ -11,6 +11,7 @@
|
||||||
"@adonisjs/auth": "^8.2.3",
|
"@adonisjs/auth": "^8.2.3",
|
||||||
"@adonisjs/core": "^5.9.0",
|
"@adonisjs/core": "^5.9.0",
|
||||||
"@adonisjs/lucid": "^18.3.0",
|
"@adonisjs/lucid": "^18.3.0",
|
||||||
|
"@adonisjs/redis": "^7.3.4",
|
||||||
"@adonisjs/repl": "^3.1.11",
|
"@adonisjs/repl": "^3.1.11",
|
||||||
"@adonisjs/session": "^6.4.0",
|
"@adonisjs/session": "^6.4.0",
|
||||||
"@adonisjs/shield": "^7.1.0",
|
"@adonisjs/shield": "^7.1.0",
|
||||||
|
@ -529,6 +530,19 @@
|
||||||
"truncatise": "0.0.8"
|
"truncatise": "0.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@adonisjs/redis": {
|
||||||
|
"version": "7.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@adonisjs/redis/-/redis-7.3.4.tgz",
|
||||||
|
"integrity": "sha512-74SApmgimjwU8QflnhANeo7CpQeP9aoObM217LJ51AtKwTvnb0yXaqdj2v60G9uCqcqZAIFWJmeUdXGgUwGcXw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@poppinss/utils": "^5.0.0",
|
||||||
|
"@types/ioredis": "^4.28.10",
|
||||||
|
"ioredis": "^5.2.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@adonisjs/core": "^5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@adonisjs/repl": {
|
"node_modules/@adonisjs/repl": {
|
||||||
"version": "3.1.11",
|
"version": "3.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@adonisjs/repl/-/repl-3.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@adonisjs/repl/-/repl-3.1.11.tgz",
|
||||||
|
@ -2886,6 +2900,11 @@
|
||||||
"vue": "^3.0.0"
|
"vue": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@ioredis/commands": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
|
||||||
|
},
|
||||||
"node_modules/@japa/api-client": {
|
"node_modules/@japa/api-client": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/@japa/api-client/-/api-client-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@japa/api-client/-/api-client-1.4.4.tgz",
|
||||||
|
@ -4055,6 +4074,14 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ioredis": {
|
||||||
|
"version": "4.28.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz",
|
||||||
|
"integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||||
|
@ -7794,6 +7821,14 @@
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
@ -10365,6 +10400,29 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ioredis": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@ioredis/commands": "^1.1.1",
|
||||||
|
"cluster-key-slot": "^1.1.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"denque": "^2.1.0",
|
||||||
|
"lodash.defaults": "^4.2.0",
|
||||||
|
"lodash.isarguments": "^3.1.0",
|
||||||
|
"redis-errors": "^1.2.0",
|
||||||
|
"redis-parser": "^3.0.0",
|
||||||
|
"standard-as-callback": "^2.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.22.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/ioredis"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ipaddr.js": {
|
"node_modules/ipaddr.js": {
|
||||||
"version": "1.9.1",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
|
@ -11493,6 +11551,11 @@
|
||||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.defaults": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
|
||||||
|
},
|
||||||
"node_modules/lodash.flatten": {
|
"node_modules/lodash.flatten": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||||
|
@ -11505,6 +11568,11 @@
|
||||||
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.isarguments": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
||||||
|
},
|
||||||
"node_modules/lodash.isequal": {
|
"node_modules/lodash.isequal": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
|
@ -14363,6 +14431,25 @@
|
||||||
"@redis/time-series": "1.0.5"
|
"@redis/time-series": "1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redis-errors": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/redis-parser": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||||
|
"dependencies": {
|
||||||
|
"redis-errors": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/reflect-metadata": {
|
"node_modules/reflect-metadata": {
|
||||||
"version": "0.1.13",
|
"version": "0.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||||
|
@ -15514,6 +15601,11 @@
|
||||||
"get-source": "^2.0.12"
|
"get-source": "^2.0.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/standard-as-callback": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
|
||||||
|
},
|
||||||
"node_modules/static-extend": {
|
"node_modules/static-extend": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
"@adonisjs/auth": "^8.2.3",
|
"@adonisjs/auth": "^8.2.3",
|
||||||
"@adonisjs/core": "^5.9.0",
|
"@adonisjs/core": "^5.9.0",
|
||||||
"@adonisjs/lucid": "^18.3.0",
|
"@adonisjs/lucid": "^18.3.0",
|
||||||
|
"@adonisjs/redis": "^7.3.4",
|
||||||
"@adonisjs/repl": "^3.1.11",
|
"@adonisjs/repl": "^3.1.11",
|
||||||
"@adonisjs/session": "^6.4.0",
|
"@adonisjs/session": "^6.4.0",
|
||||||
"@adonisjs/shield": "^7.1.0",
|
"@adonisjs/shield": "^7.1.0",
|
||||||
|
|
|
@ -10,6 +10,7 @@ import OverlayLayer from '@/Components/OverlayLayer.vue';
|
||||||
// let menu = reactive({});
|
// let menu = reactive({});
|
||||||
// menu = computed(() => usePage().props.navigation?.menu);
|
// menu = computed(() => usePage().props.navigation?.menu);
|
||||||
|
|
||||||
|
|
||||||
const layoutService = LayoutService();
|
const layoutService = LayoutService();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, ComputedRef } from 'vue';
|
||||||
import { Link } from '@inertiajs/vue3';
|
import { Link, usePage } from '@inertiajs/vue3';
|
||||||
// import { Link } from '@inertiajs/inertia-vue3';
|
// import { Link } from '@inertiajs/inertia-vue3';
|
||||||
|
|
||||||
import { StyleService } from '@/Stores/style';
|
import { StyleService } from '@/Stores/style';
|
||||||
|
@ -9,6 +9,7 @@ import { getButtonColor } from '@/colors.js';
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
import AsideMenuList from '@/Components/AsideMenuList.vue';
|
import AsideMenuList from '@/Components/AsideMenuList.vue';
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
import type { User } from '@/Dataset';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
|
@ -18,6 +19,10 @@ const props = defineProps({
|
||||||
isDropdownList: Boolean,
|
isDropdownList: Boolean,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const user: ComputedRef<User> = computed(() => {
|
||||||
|
return usePage().props.authUser as User;
|
||||||
|
});
|
||||||
|
|
||||||
const itemRoute = computed(() => (props.item && props.item.route ? stardust.route(props.item.route) : ''));
|
const itemRoute = computed(() => (props.item && props.item.route ? stardust.route(props.item.route) : ''));
|
||||||
// const isCurrentRoute = computed(() => (props.item && props.item.route ? stardust.isCurrent(props.item.route): false));
|
// const isCurrentRoute = computed(() => (props.item && props.item.route ? stardust.isCurrent(props.item.route): false));
|
||||||
const itemHref = computed(() => (props.item && props.item.href ? props.item.href : ''));
|
const itemHref = computed(() => (props.item && props.item.href ? props.item.href : ''));
|
||||||
|
@ -65,12 +70,20 @@ const is = computed(() => {
|
||||||
return 'div';
|
return 'div';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hasRoles = computed(() => {
|
||||||
|
if (props.item.roles) {
|
||||||
|
return user.value.roles.some(role => props.item.roles.includes(role.name));
|
||||||
|
// return test;
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
});
|
||||||
|
|
||||||
// props.routeName && stardust.isCurrent(props.routeName) ? props.activeColor : null
|
// props.routeName && stardust.isCurrent(props.routeName) ? props.activeColor : null
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- :target="props.item.target ?? null" -->
|
<!-- :target="props.item.target ?? null" -->
|
||||||
<template>
|
<template>
|
||||||
<li>
|
<li v-if="hasRoles">
|
||||||
<!-- <component :is="itemHref ? 'div' : Link" :href="itemHref ? itemHref : itemRoute" -->
|
<!-- <component :is="itemHref ? 'div' : Link" :href="itemHref ? itemHref : itemRoute" -->
|
||||||
<component
|
<component
|
||||||
:is="is"
|
:is="is"
|
||||||
|
|
|
@ -19,10 +19,10 @@ const menuClick = (event, item) => {
|
||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<AsideMenuItem
|
<AsideMenuItem
|
||||||
v-for="(item, index) in menu"
|
v-for="(menuItem, index) in menu"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-bind:item="item"
|
v-bind:item="menuItem"
|
||||||
:is-dropdown-list="item.children?.length > 0"
|
:is-dropdown-list="menuItem.children?.length > 0"
|
||||||
@menu-click="menuClick"
|
@menu-click="menuClick"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -250,7 +250,7 @@ class FileUploadComponent extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch("files", {
|
@Watch("files", {
|
||||||
deep: true
|
deep: true //also in case of pushing
|
||||||
})
|
})
|
||||||
public propertyWatcher(newItems: Array<TethysFile>) {
|
public propertyWatcher(newItems: Array<TethysFile>) {
|
||||||
// Update sort_order based on the new index when the list is changed
|
// Update sort_order based on the new index when the list is changed
|
||||||
|
@ -361,10 +361,11 @@ class FileUploadComponent extends Vue {
|
||||||
let localUrl: string = "";
|
let localUrl: string = "";
|
||||||
if (file instanceof File) {
|
if (file instanceof File) {
|
||||||
localUrl = URL.createObjectURL(file as Blob);
|
localUrl = URL.createObjectURL(file as Blob);
|
||||||
} else if (file.filePath) {
|
} else if (file.fileData) {
|
||||||
// const blob = new Blob([file.fileData]);
|
// const blob = new Blob([file.fileData]);
|
||||||
// localUrl = URL.createObjectURL(blob);
|
// localUrl = URL.createObjectURL(blob);
|
||||||
const parsed = JSON.parse(file.fileData);
|
const parsed = JSON.parse(file.fileData);
|
||||||
|
file.fileData = "";
|
||||||
// retrieve the original buffer of data
|
// retrieve the original buffer of data
|
||||||
const buff = Buffer.from(parsed.blob, "base64");
|
const buff = Buffer.from(parsed.blob, "base64");
|
||||||
const blob = new Blob([buff], { type: 'application/octet-stream' });
|
const blob = new Blob([buff], { type: 'application/octet-stream' });
|
||||||
|
|
|
@ -34,7 +34,7 @@ import UserAvatarCurrentUser from '@/Components/UserAvatarCurrentUser.vue';
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
import NavBarSearch from '@/Components/NavBarSearch.vue';
|
import NavBarSearch from '@/Components/NavBarSearch.vue';
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
import type User from 'App/Models/User';
|
import type { User } from '@/Dataset';
|
||||||
|
|
||||||
// const mainStore = MainService();
|
// const mainStore = MainService();
|
||||||
// const userName = computed(() =>mainStore.userName);
|
// const userName = computed(() =>mainStore.userName);
|
||||||
|
@ -68,6 +68,9 @@ const menuNavBarToggle = () => {
|
||||||
const menuOpenLg = () => {
|
const menuOpenLg = () => {
|
||||||
layoutStore.isAsideLgActive = true;
|
layoutStore.isAsideLgActive = true;
|
||||||
};
|
};
|
||||||
|
const userHasRoles = (roleNames): boolean => {
|
||||||
|
return user.value.roles.some(role => roleNames.includes(role.name));
|
||||||
|
};
|
||||||
|
|
||||||
// const logout = () => {
|
// const logout = () => {
|
||||||
// // router.post(route('logout'))
|
// // router.post(route('logout'))
|
||||||
|
@ -133,7 +136,7 @@ const logout = async () => {
|
||||||
<NavBarItem :route-name="'admin.account.info'">
|
<NavBarItem :route-name="'admin.account.info'">
|
||||||
<NavBarItemLabel :icon="mdiAccount" label="My Profile" />
|
<NavBarItemLabel :icon="mdiAccount" label="My Profile" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
<NavBarItem :route-name="'settings'">
|
<NavBarItem v-if="userHasRoles(['moderator', 'administrator'])" :route-name="'settings'">
|
||||||
<NavBarItemLabel :icon="mdiCogOutline" label="Settings" />
|
<NavBarItemLabel :icon="mdiCogOutline" label="Settings" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
<NavBarItem>
|
<NavBarItem>
|
||||||
|
|
|
@ -3,13 +3,9 @@
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<!-- <label for="search-dropdown" class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Your Email</label> -->
|
<!-- <label for="search-dropdown" class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Your Email</label> -->
|
||||||
<div class="relative" data-te-dropdown-ref>
|
<div class="relative" data-te-dropdown-ref>
|
||||||
<button
|
<button id="states-button" data-dropdown-toggle="dropdown-states"
|
||||||
id="states-button"
|
|
||||||
data-dropdown-toggle="dropdown-states"
|
|
||||||
class="whitespace-nowrap h-12 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-500 bg-gray-100 border border-gray-300 rounded-l-lg hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600"
|
class="whitespace-nowrap h-12 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-center text-gray-500 bg-gray-100 border border-gray-300 rounded-l-lg hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:focus:ring-gray-700 dark:text-white dark:border-gray-600"
|
||||||
type="button"
|
type="button" @click.prevent="showStates">
|
||||||
@click.prevent="showStates"
|
|
||||||
>
|
|
||||||
<!-- <svg aria-hidden="true" class="h-3 mr-2" viewBox="0 0 15 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<!-- <svg aria-hidden="true" class="h-3 mr-2" viewBox="0 0 15 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect x="0.5" width="14" height="12" rx="2" fill="white" />
|
<rect x="0.5" width="14" height="12" rx="2" fill="white" />
|
||||||
<mask id="mask0_12694_49953" style="mask-type: alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="15" height="12">
|
<mask id="mask0_12694_49953" style="mask-type: alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="15" height="12">
|
||||||
|
@ -69,26 +65,20 @@
|
||||||
</svg> -->
|
</svg> -->
|
||||||
<!-- eng -->
|
<!-- eng -->
|
||||||
{{ language }}
|
{{ language }}
|
||||||
<svg aria-hidden="true" class="w-4 h-4 ml-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
<svg aria-hidden="true" class="w-4 h-4 ml-1" fill="currentColor" viewBox="0 0 20 20"
|
||||||
<path
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||||
clip-rule="evenodd"
|
clip-rule="evenodd"></path>
|
||||||
></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<!-- class="w-full overflow-visible z-10 bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700"-->
|
<!-- class="w-full overflow-visible z-10 bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700"-->
|
||||||
<div
|
<div id="dropdown-states" v-show="statesToggle"
|
||||||
id="dropdown-states"
|
class="absolute z-[1000] float-left m-0 min-w-max list-none overflow-hidden rounded-lg border-none bg-white bg-clip-padding text-left text-base shadow-lg dark:bg-neutral-700">
|
||||||
v-show="statesToggle"
|
|
||||||
class="absolute z-[1000] float-left m-0 min-w-max list-none overflow-hidden rounded-lg border-none bg-white bg-clip-padding text-left text-base shadow-lg dark:bg-neutral-700"
|
|
||||||
>
|
|
||||||
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="states-button">
|
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="states-button">
|
||||||
<li v-for="(item, index) in dropDownStates" :key="index" @click.prevent="setLanguage(item)">
|
<li v-for="(item, index) in dropDownStates" :key="index" @click.prevent="setLanguage(item)">
|
||||||
<button
|
<button type="button"
|
||||||
type="button"
|
class="inline-flex w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-white">
|
||||||
class="inline-flex w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-600 dark:hover:text-white"
|
|
||||||
>
|
|
||||||
<div class="inline-flex items-center">
|
<div class="inline-flex items-center">
|
||||||
<span v-html="item.svg"></span>
|
<span v-html="item.svg"></span>
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
|
@ -102,57 +92,30 @@
|
||||||
<div class="w-full relative">
|
<div class="w-full relative">
|
||||||
<!-- :class="inputElClass" -->
|
<!-- :class="inputElClass" -->
|
||||||
<!-- class="block p-2.5 w-full z-20 text-sm text-gray-900 bg-gray-50 rounded-r-lg border-l-gray-50 border-l-2 border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-l-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:border-blue-500" -->
|
<!-- class="block p-2.5 w-full z-20 text-sm text-gray-900 bg-gray-50 rounded-r-lg border-l-gray-50 border-l-2 border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-l-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:border-blue-500" -->
|
||||||
<input
|
<input v-model="computedValue" type="text" :name="props.name" autocomplete="off" :class="inputElClass"
|
||||||
v-model="computedValue"
|
placeholder="Search Keywords..." required @input="handleInput" />
|
||||||
type="text"
|
|
||||||
:name="props.name"
|
|
||||||
autocomplete="off"
|
|
||||||
:class="inputElClass"
|
|
||||||
placeholder="Search Keywords..."
|
|
||||||
required
|
|
||||||
@input="handleInput"
|
|
||||||
/>
|
|
||||||
<!-- v-model="data.search" -->
|
<!-- v-model="data.search" -->
|
||||||
<svg
|
<svg class="w-4 h-4 absolute left-2.5 top-3.5" v-show="computedValue.length < 2"
|
||||||
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">
|
||||||
v-show="computedValue.length < 2"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||||
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>
|
</svg>
|
||||||
|
|
||||||
<svg
|
<svg class="w-4 h-4 absolute left-2.5 top-3.5" v-show="computedValue.length >= 2"
|
||||||
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" @click="() => {
|
||||||
v-show="computedValue.length >= 2"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
computedValue = '';
|
computedValue = '';
|
||||||
data.isOpen = false;
|
data.isOpen = false;
|
||||||
}
|
}
|
||||||
"
|
">
|
||||||
>
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
<ul
|
<ul v-if="data.isOpen"
|
||||||
v-if="data.isOpen"
|
class="absolute absolute z-[1000] float-left m-0 list-none bg-white dark:bg-slate-800 m-0 max-h-32 overflow-y-auto scroll-smooth min-w-full">
|
||||||
class="absolute absolute z-[1000] float-left m-0 list-none bg-white dark:bg-slate-800 m-0 max-h-32 overflow-y-auto scroll-smooth min-w-full"
|
<li class="leading-3 pl-4 py-3 border-b-2 line border-gray-100 relative cursor-pointer hover:bg-yellow-50 hover:text-gray-900"
|
||||||
>
|
v-for="(item, index) in data.results" @click.prevent="setResult(item)" :key="index">
|
||||||
<li
|
|
||||||
class="leading-3 pl-4 py-3 border-b-2 line border-gray-100 relative cursor-pointer hover:bg-yellow-50 hover:text-gray-900"
|
|
||||||
v-for="(item, index) in data.results"
|
|
||||||
@click.prevent="setResult(item)"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<!-- <a href="${BASE}?uri=${a.s.value}&lang=${USER_LANG}"> -->
|
<!-- <a href="${BASE}?uri=${a.s.value}&lang=${USER_LANG}"> -->
|
||||||
<strong class="text-sm"> {{ item.title.value }}</strong>
|
<strong class="text-sm"> {{ item.title.value }}</strong>
|
||||||
<!-- </a> -->
|
<!-- </a> -->
|
||||||
|
@ -406,7 +369,10 @@ function setResult(item) {
|
||||||
computedValue.value = item.title.value;
|
computedValue.value = item.title.value;
|
||||||
clear();
|
clear();
|
||||||
// this.$emit('person', person);
|
// this.$emit('person', person);
|
||||||
emit('subject', language.value);
|
emit('subject', {
|
||||||
|
language: language.value,
|
||||||
|
uri: item.s.value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { mdiTrashCan } from '@mdi/js';
|
||||||
import BaseLevel from '@/Components/BaseLevel.vue';
|
import BaseLevel from '@/Components/BaseLevel.vue';
|
||||||
import BaseButtons from '@/Components/BaseButtons.vue';
|
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||||
import BaseButton from '@/Components/BaseButton.vue';
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
// import Person from 'App/Models/Person';
|
|
||||||
import { Subject } from '@/Dataset';
|
import { Subject } from '@/Dataset';
|
||||||
// import FormField from '@/Components/FormField.vue';
|
// import FormField from '@/Components/FormField.vue';
|
||||||
import FormControl from '@/Components/FormControl.vue';
|
import FormControl from '@/Components/FormControl.vue';
|
||||||
|
@ -120,7 +119,7 @@ const removeItem = (key) => {
|
||||||
<UserAvatar :username="client.value" class="w-24 h-24 mx-auto lg:w-6 lg:h-6" />
|
<UserAvatar :username="client.value" class="w-24 h-24 mx-auto lg:w-6 lg:h-6" />
|
||||||
</td> -->
|
</td> -->
|
||||||
<td data-label="Type" scope="row">
|
<td data-label="Type" scope="row">
|
||||||
<FormControl required v-model="item.type" :type="'select'" placeholder="[Enter Language]" :options="props.subjectTypes">
|
<FormControl required v-model="item.type" @update:modelValue="() => {item.external_key = undefined; item.value= '';}" :type="'select'" placeholder="[Enter Language]" :options="props.subjectTypes">
|
||||||
<div class="text-red-400 text-sm" v-if="errors[`subjects.${index}.type`]">
|
<div class="text-red-400 text-sm" v-if="errors[`subjects.${index}.type`]">
|
||||||
{{ errors[`subjects.${index}.type`].join(', ') }}
|
{{ errors[`subjects.${index}.type`].join(', ') }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -132,8 +131,9 @@ const removeItem = (key) => {
|
||||||
v-if="item.type !== 'uncontrolled'"
|
v-if="item.type !== 'uncontrolled'"
|
||||||
v-model="item.value"
|
v-model="item.value"
|
||||||
@subject="
|
@subject="
|
||||||
(language) => {
|
(result) => {
|
||||||
item.language = language;
|
item.language = result.language;
|
||||||
|
item.external_key = result.uri;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,4 +1,24 @@
|
||||||
import { Ref } from 'vue';
|
import { Ref } from 'vue';
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
id: number;
|
||||||
|
login: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
createdAt: DateTime;
|
||||||
|
updatedAt: DateTime;
|
||||||
|
roles: Array<Role>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Role {
|
||||||
|
id: number;
|
||||||
|
display_name: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
created_at: DateTime;
|
||||||
|
updated_at: DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Dataset {
|
export interface Dataset {
|
||||||
[key: string]:
|
[key: string]:
|
||||||
|
@ -75,11 +95,12 @@ export interface TethysFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Subject {
|
export interface Subject {
|
||||||
// id: number;
|
id?: number;
|
||||||
language: string;
|
language: string;
|
||||||
type: string;
|
type: string;
|
||||||
value: string;
|
value: string;
|
||||||
external_key?: string;
|
external_key?: string;
|
||||||
|
dataset_count: number;
|
||||||
}
|
}
|
||||||
export interface DatasetReference {
|
export interface DatasetReference {
|
||||||
// id: number;
|
// id: number;
|
||||||
|
|
|
@ -290,14 +290,15 @@ const submit = async () => {
|
||||||
|
|
||||||
// this.currentStatus = STATUS_SAVING;
|
// this.currentStatus = STATUS_SAVING;
|
||||||
// serrors = [];
|
// serrors = [];
|
||||||
// const files = form.files.map((obj) => {
|
const files = form.files.map((obj) => {
|
||||||
// return new File([obj.blob], obj.label, { type: obj.type, lastModified: obj.lastModified });
|
return new File([obj.blob], obj.label, { type: obj.type, lastModified: obj.lastModified });
|
||||||
// });
|
});
|
||||||
|
|
||||||
// formStep.value++;
|
// formStep.value++;
|
||||||
await form
|
await form
|
||||||
.transform((data) => ({
|
.transform((data) => ({
|
||||||
...data,
|
...data,
|
||||||
|
files: files,
|
||||||
rights: form.rights && form.rights == true ? 'true' : 'false',
|
rights: form.rights && form.rights == true ? 'true' : 'false',
|
||||||
}))
|
}))
|
||||||
.post(route, {
|
.post(route, {
|
||||||
|
@ -404,7 +405,7 @@ const onMapInitialized = (newItem) => {
|
||||||
adds a new Keyword
|
adds a new Keyword
|
||||||
*/
|
*/
|
||||||
const addKeyword = () => {
|
const addKeyword = () => {
|
||||||
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled' };
|
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled', dataset_count: 0 };
|
||||||
//this.dataset.files.push(uploadedFiles[i]);
|
//this.dataset.files.push(uploadedFiles[i]);
|
||||||
form.subjects.push(newSubject);
|
form.subjects.push(newSubject);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,11 +8,15 @@
|
||||||
color="white" rounded-full small />
|
color="white" rounded-full small />
|
||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
|
|
||||||
|
<NotificationBar v-if="flash.message" color="success" :icon="mdiAlertBoxOutline">
|
||||||
|
{{ flash.message }}
|
||||||
|
</NotificationBar>
|
||||||
|
<FormValidationErrors v-bind:errors="errors" />
|
||||||
<!-- max-w-2xl max-width: 42rem; /* 672px */ -->
|
<!-- max-w-2xl max-width: 42rem; /* 672px */ -->
|
||||||
<!-- <div class="max-w-2xl mx-auto"> -->
|
<!-- <div class="max-w-2xl mx-auto"> -->
|
||||||
|
|
||||||
<CardBox :form="true">
|
<CardBox :form="true">
|
||||||
<FormValidationErrors v-bind:errors="errors" />
|
<!-- <FormValidationErrors v-bind:errors="errors" /> -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<!-- <label for="title" class="block text-gray-700 font-bold mb-2">Title:</label>
|
<!-- <label for="title" class="block text-gray-700 font-bold mb-2">Title:</label>
|
||||||
<input
|
<input
|
||||||
|
@ -218,8 +222,8 @@
|
||||||
<td class="before:hidden lg:w-1 whitespace-nowrap">
|
<td class="before:hidden lg:w-1 whitespace-nowrap">
|
||||||
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
||||||
<!-- <BaseButton color="info" :icon="mdiEye" small @click="isModalActive = true" /> -->
|
<!-- <BaseButton color="info" :icon="mdiEye" small @click="isModalActive = true" /> -->
|
||||||
<BaseButton color="danger" :icon="mdiTrashCan" small v-if="item.id == undefined"
|
<BaseButton color="danger" :icon="mdiTrashCan" small
|
||||||
@click.prevent="removeDescription(index)" />
|
v-if="item.id == undefined" @click.prevent="removeDescription(index)" />
|
||||||
</BaseButtons>
|
</BaseButtons>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -469,7 +473,8 @@
|
||||||
// import { Component, Vue, Prop, Setup, toNative } from 'vue-facing-decorator';
|
// import { Component, Vue, Prop, Setup, toNative } from 'vue-facing-decorator';
|
||||||
// import AuthLayout from '@/Layouts/Auth.vue';
|
// import AuthLayout from '@/Layouts/Auth.vue';
|
||||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import { useForm, Head } from '@inertiajs/vue3';
|
import { useForm, Head, usePage } from '@inertiajs/vue3';
|
||||||
|
import { computed, ComputedRef } from 'vue';
|
||||||
// import { ref } from 'vue';
|
// import { ref } from 'vue';
|
||||||
// import { MainService } from '@/Stores/main';
|
// import { MainService } from '@/Stores/main';
|
||||||
// import FormInput from '@/Components/FormInput.vue'; // @/Components/FormInput.vue'
|
// import FormInput from '@/Components/FormInput.vue'; // @/Components/FormInput.vue'
|
||||||
|
@ -502,8 +507,10 @@ import {
|
||||||
mdiTrashCan,
|
mdiTrashCan,
|
||||||
mdiBookOpenPageVariant,
|
mdiBookOpenPageVariant,
|
||||||
mdiEarthPlus,
|
mdiEarthPlus,
|
||||||
|
mdiAlertBoxOutline,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import { notify } from '@/notiwind';
|
import { notify } from '@/notiwind';
|
||||||
|
import NotificationBar from '@/Components/NotificationBar.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
errors: {
|
errors: {
|
||||||
|
@ -557,6 +564,11 @@ const props = defineProps({
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
const flash: ComputedRef<any> = computed(() => {
|
||||||
|
// let test = usePage();
|
||||||
|
// console.log(test);
|
||||||
|
return usePage().props.flash;
|
||||||
});
|
});
|
||||||
|
|
||||||
// const projects = reactive([]);
|
// const projects = reactive([]);
|
||||||
|
@ -639,11 +651,17 @@ const submit = async (): Promise<void> => {
|
||||||
form.licenses = form.licenses.map((obj) => obj.id.toString());
|
form.licenses = form.licenses.map((obj) => obj.id.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const files = form.files.map((obj) => {
|
||||||
|
// return new File([obj.blob], obj.label, { type: obj.type, lastModified: obj.lastModified });
|
||||||
|
// });
|
||||||
|
|
||||||
const [fileUploads, fileInputs] = form.files?.reduce(
|
const [fileUploads, fileInputs] = form.files?.reduce(
|
||||||
([fileUploads, fileInputs], obj) => {
|
([fileUploads, fileInputs], obj) => {
|
||||||
if (!obj.id) {
|
if (!obj.id) {
|
||||||
// return MultipartFile for file upload
|
// return MultipartFile for file upload
|
||||||
fileUploads[obj.sort_order] = new File([obj.blob], obj.label, { type: obj.type, lastModified: obj.lastModified });
|
let file = new File([obj.blob], `${obj.label}?sortOrder=${obj.sort_order}`, { type: obj.type, lastModified: obj.lastModified });
|
||||||
|
// fileUploads[obj.sort_order] = file;
|
||||||
|
fileUploads.push(file);
|
||||||
} else {
|
} else {
|
||||||
// return normal request input
|
// return normal request input
|
||||||
fileInputs.push(obj);
|
fileInputs.push(obj);
|
||||||
|
@ -723,7 +741,7 @@ const onAddContributor = (person) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const addKeyword = () => {
|
const addKeyword = () => {
|
||||||
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled' };
|
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled', dataset_count: 0 };
|
||||||
//this.dataset.files.push(uploadedFiles[i]);
|
//this.dataset.files.push(uploadedFiles[i]);
|
||||||
form.subjects.push(newSubject);
|
form.subjects.push(newSubject);
|
||||||
};
|
};
|
||||||
|
@ -743,7 +761,7 @@ const onMapInitialized = (newItem) => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
.max-w-2xl {
|
.max-w-2xl {
|
||||||
max-width: 2xl;
|
max-width: 2xl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ const flash: ComputedRef<any> = computed(() => {
|
||||||
:route-name="stardust.route('dataset.release', [dataset.id])" color="info"
|
:route-name="stardust.route('dataset.release', [dataset.id])" color="info"
|
||||||
:icon="mdiLockOpen" :label="'Release'" small />
|
:icon="mdiLockOpen" :label="'Release'" small />
|
||||||
<!-- && (dataset.server_state === 'inprogress' || dataset.server_state === 'rejected_editor')" -->
|
<!-- && (dataset.server_state === 'inprogress' || dataset.server_state === 'rejected_editor')" -->
|
||||||
<BaseButton v-if="can.edit" :route-name="stardust.route('dataset.edit', [dataset.id])"
|
<BaseButton :route-name="stardust.route('dataset.edit', [dataset.id])"
|
||||||
color="info" :icon="mdiSquareEditOutline" :label="'Edit'" small />
|
color="info" :icon="mdiSquareEditOutline" :label="'Edit'" small />
|
||||||
<!-- @click="destroy(dataset.id)" -->
|
<!-- @click="destroy(dataset.id)" -->
|
||||||
<BaseButton v-if="can.delete" color="danger"
|
<BaseButton v-if="can.delete" color="danger"
|
||||||
|
|
|
@ -216,7 +216,7 @@ class EditComponent extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
public addKeyword() {
|
public addKeyword() {
|
||||||
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled' };
|
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled', dataset_count: 0 };
|
||||||
//this.dataset.files.push(uploadedFiles[i]);
|
//this.dataset.files.push(uploadedFiles[i]);
|
||||||
this.form.subjects.push(newSubject);
|
this.form.subjects.push(newSubject);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ export default [
|
||||||
// route: 'dataset.create',
|
// route: 'dataset.create',
|
||||||
icon: mdiDatabasePlus,
|
icon: mdiDatabasePlus,
|
||||||
label: 'Submitter',
|
label: 'Submitter',
|
||||||
|
permissions: ['submitter'],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
route: 'dataset.list',
|
route: 'dataset.list',
|
||||||
|
|
|
@ -24,8 +24,9 @@ Inertia.share({
|
||||||
},
|
},
|
||||||
|
|
||||||
// params: ({ params }) => params,
|
// params: ({ params }) => params,
|
||||||
authUser: ({ auth }: HttpContextContract) => {
|
authUser: async ({ auth }: HttpContextContract) => {
|
||||||
if (auth.user) {
|
if (auth.user) {
|
||||||
|
await auth.user.load('roles');
|
||||||
return auth.user;
|
return auth.user;
|
||||||
// {
|
// {
|
||||||
// 'id': auth.user.id,
|
// 'id': auth.user.id,
|
||||||
|
|
|
@ -94,6 +94,8 @@ Route.post('/app/login', 'Auth/AuthController.login').as('login.store');
|
||||||
// Route.post("/signup", "AuthController.signup");
|
// Route.post("/signup", "AuthController.signup");
|
||||||
Route.post('/signout', 'Auth/AuthController.logout').as('logout');
|
Route.post('/signout', 'Auth/AuthController.logout').as('logout');
|
||||||
|
|
||||||
|
|
||||||
|
// administrator
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
Route.get('/settings', async ({ inertia }) => {
|
Route.get('/settings', async ({ inertia }) => {
|
||||||
return inertia.render('Admin/Settings');
|
return inertia.render('Admin/Settings');
|
||||||
|
@ -133,6 +135,10 @@ Route.group(() => {
|
||||||
// .middleware(['auth', 'can:dataset-list,dataset-publish']);
|
// .middleware(['auth', 'can:dataset-list,dataset-publish']);
|
||||||
.middleware(['auth', 'is:administrator,moderator']);
|
.middleware(['auth', 'is:administrator,moderator']);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Route.get('/edit-account-info', 'UsersController.accountInfo')
|
Route.get('/edit-account-info', 'UsersController.accountInfo')
|
||||||
.as('admin.account.info')
|
.as('admin.account.info')
|
||||||
.namespace('App/Controllers/Http/Admin')
|
.namespace('App/Controllers/Http/Admin')
|
||||||
|
@ -145,9 +151,10 @@ Route.post('/edit-account-info/store/:id', 'UsersController.accountInfoStore')
|
||||||
.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');
|
||||||
|
|
||||||
|
// submitter:
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
// Route.get('/user', 'UsersController.index').as('user.index');
|
// Route.get('/user', 'UsersController.index').as('user.index');
|
||||||
Route.get('/dataset', 'DatasetController.index').as('dataset.list').middleware(['auth']); //.middleware(['can:dataset-list']);
|
Route.get('/dataset', 'DatasetController.index').as('dataset.list').middleware(['auth', 'can:dataset-list']);
|
||||||
Route.get('/dataset/create', 'DatasetController.create').as('dataset.create').middleware(['auth', 'can:dataset-submit']);
|
Route.get('/dataset/create', 'DatasetController.create').as('dataset.create').middleware(['auth', 'can:dataset-submit']);
|
||||||
Route.post('/dataset/first/first-step', 'DatasetController.firstStep')
|
Route.post('/dataset/first/first-step', 'DatasetController.firstStep')
|
||||||
.as('dataset.first.step')
|
.as('dataset.first.step')
|
||||||
|
@ -158,25 +165,23 @@ Route.group(() => {
|
||||||
Route.post('/dataset/second/third-step', 'DatasetController.thirdStep')
|
Route.post('/dataset/second/third-step', 'DatasetController.thirdStep')
|
||||||
.as('dataset.third.step')
|
.as('dataset.third.step')
|
||||||
.middleware(['auth', 'can:dataset-submit']);
|
.middleware(['auth', 'can:dataset-submit']);
|
||||||
|
|
||||||
Route.post('/dataset/submit', 'DatasetController.store').as('dataset.submit').middleware(['auth', 'can:dataset-submit']);
|
Route.post('/dataset/submit', 'DatasetController.store').as('dataset.submit').middleware(['auth', 'can:dataset-submit']);
|
||||||
|
|
||||||
Route.get('/dataset/:id/release', 'DatasetController.release')
|
Route.get('/dataset/:id/release', 'DatasetController.release')
|
||||||
.as('dataset.release')
|
.as('dataset.release')
|
||||||
.where('id', Route.matchers.number())
|
.where('id', Route.matchers.number())
|
||||||
.middleware(['auth']); //, 'can:dataset-submit']);
|
.middleware(['auth', 'can:dataset-edit']);
|
||||||
Route.put('/dataset/:id/releaseupdate', 'DatasetController.releaseUpdate')
|
Route.put('/dataset/:id/releaseupdate', 'DatasetController.releaseUpdate')
|
||||||
.as('dataset.releaseUpdate')
|
.as('dataset.releaseUpdate')
|
||||||
.middleware(['auth', 'can:dataset-submit']);
|
.middleware(['auth', 'can:dataset-edit']);
|
||||||
Route.get('/dataset/:id/edit', 'DatasetController.edit')
|
Route.get('/dataset/:id/edit', 'DatasetController.edit')
|
||||||
.as('dataset.edit')
|
.as('dataset.edit')
|
||||||
.where('id', Route.matchers.number())
|
.where('id', Route.matchers.number())
|
||||||
.middleware(['auth', 'can:dataset-submit']);
|
.middleware(['auth', 'can:dataset-edit']);
|
||||||
|
|
||||||
Route.put('/dataset/:id/update', 'DatasetController.update')
|
Route.put('/dataset/:id/update', 'DatasetController.update')
|
||||||
.as('dataset.update')
|
.as('dataset.update')
|
||||||
.where('id', Route.matchers.number())
|
.where('id', Route.matchers.number())
|
||||||
.middleware(['auth', 'can:dataset-submit']);
|
.middleware(['auth', 'can:dataset-edit']);
|
||||||
|
|
||||||
Route.get('/dataset/:id/delete', 'DatasetController.delete').as('dataset.delete').middleware(['auth', 'can:dataset-delete']);
|
Route.get('/dataset/:id/delete', 'DatasetController.delete').as('dataset.delete').middleware(['auth', 'can:dataset-delete']);
|
||||||
Route.put('/dataset/:id/deleteupdate', 'DatasetController.deleteUpdate')
|
Route.put('/dataset/:id/deleteupdate', 'DatasetController.deleteUpdate')
|
||||||
|
@ -195,7 +200,7 @@ Route.group(() => {
|
||||||
// .middleware(['auth', 'is:submitter']);
|
// .middleware(['auth', 'is:submitter']);
|
||||||
|
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
Route.put('/dataset/:id/update', 'DatasetsController.update').as('editor.dataset.update').middleware(['auth', 'can:dataset-submit']);
|
Route.put('/dataset/:id/update', 'DatasetsController.update').as('editor.dataset.update').middleware(['auth', 'can:dataset-editor-edit']);
|
||||||
})
|
})
|
||||||
.namespace('App/Controllers/Http/Editor')
|
.namespace('App/Controllers/Http/Editor')
|
||||||
.prefix('editor');
|
.prefix('editor');
|
||||||
|
|
|
@ -30,12 +30,22 @@
|
||||||
"esModuleInterop": true, //neu
|
"esModuleInterop": true, //neu
|
||||||
"allowSyntheticDefaultImports": true, //neu,
|
"allowSyntheticDefaultImports": true, //neu,
|
||||||
"paths": {
|
"paths": {
|
||||||
"App/*": ["./app/*"],
|
"App/*": [
|
||||||
"Config/*": ["./config/*"],
|
"./app/*"
|
||||||
"Contracts/*": ["./contracts/*"],
|
],
|
||||||
"Database/*": ["./database/*"],
|
"Config/*": [
|
||||||
|
"./config/*"
|
||||||
|
],
|
||||||
|
"Contracts/*": [
|
||||||
|
"./contracts/*"
|
||||||
|
],
|
||||||
|
"Database/*": [
|
||||||
|
"./database/*"
|
||||||
|
],
|
||||||
// "@/*": ["./resources/js/"],
|
// "@/*": ["./resources/js/"],
|
||||||
"@/*": ["./resources/js/*"]
|
"@/*": [
|
||||||
|
"./resources/js/*"
|
||||||
|
]
|
||||||
// "vue$": ["vue/dist/vue.runtime.esm-bundler.js"],
|
// "vue$": ["vue/dist/vue.runtime.esm-bundler.js"],
|
||||||
},
|
},
|
||||||
"types": [
|
"types": [
|
||||||
|
@ -48,8 +58,11 @@
|
||||||
"@eidellev/inertia-adonisjs",
|
"@eidellev/inertia-adonisjs",
|
||||||
"naive-ui/volar",
|
"naive-ui/volar",
|
||||||
"@adonisjs/lucid",
|
"@adonisjs/lucid",
|
||||||
"@adonisjs/auth"
|
"@adonisjs/auth",
|
||||||
|
"@adonisjs/redis"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"files": ["index.d.ts"]
|
"files": [
|
||||||
|
"index.d.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user