Compare commits
2 Commits
main
...
ostrio-fil
| Author | SHA1 | Date | |
|---|---|---|---|
| 023f73355d | |||
| 56a0b76c6d |
@ -22,3 +22,4 @@ react-meteor-data # React higher-order component for reactively tracking M
|
|||||||
roles@1.0.1
|
roles@1.0.1
|
||||||
accounts-password@3.0.3
|
accounts-password@3.0.3
|
||||||
react-meteor-accounts
|
react-meteor-accounts
|
||||||
|
ostrio:files
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
METEOR@3.1.1
|
METEOR@3.1.2
|
||||||
|
|||||||
@ -23,7 +23,7 @@ ecmascript-runtime@0.8.3
|
|||||||
ecmascript-runtime-client@0.12.2
|
ecmascript-runtime-client@0.12.2
|
||||||
ecmascript-runtime-server@0.11.1
|
ecmascript-runtime-server@0.11.1
|
||||||
ejson@1.1.4
|
ejson@1.1.4
|
||||||
email@3.1.1
|
email@3.1.2
|
||||||
es5-shim@4.8.1
|
es5-shim@4.8.1
|
||||||
facts-base@1.0.2
|
facts-base@1.0.2
|
||||||
fetch@0.1.5
|
fetch@0.1.5
|
||||||
@ -42,7 +42,7 @@ minifier-js@3.0.1
|
|||||||
minimongo@2.0.2
|
minimongo@2.0.2
|
||||||
mobile-experience@1.1.2
|
mobile-experience@1.1.2
|
||||||
mobile-status-bar@1.1.1
|
mobile-status-bar@1.1.1
|
||||||
modern-browsers@0.1.11
|
modern-browsers@0.2.0
|
||||||
modules@0.20.3
|
modules@0.20.3
|
||||||
modules-runtime@0.13.2
|
modules-runtime@0.13.2
|
||||||
modules-runtime-hot@0.14.3
|
modules-runtime-hot@0.14.3
|
||||||
@ -52,6 +52,8 @@ mongo-dev-server@1.1.1
|
|||||||
mongo-id@1.0.9
|
mongo-id@1.0.9
|
||||||
npm-mongo@6.10.2
|
npm-mongo@6.10.2
|
||||||
ordered-dict@1.2.0
|
ordered-dict@1.2.0
|
||||||
|
ostrio:cookies@2.8.1
|
||||||
|
ostrio:files@3.0.0-beta.6
|
||||||
promise@1.0.0
|
promise@1.0.0
|
||||||
random@1.2.2
|
random@1.2.2
|
||||||
rate-limit@1.1.2
|
rate-limit@1.1.2
|
||||||
@ -73,5 +75,5 @@ static-html-tools@1.0.0
|
|||||||
tracker@1.3.4
|
tracker@1.3.4
|
||||||
typescript@5.6.3
|
typescript@5.6.3
|
||||||
url@1.3.5
|
url@1.3.5
|
||||||
webapp@2.0.4
|
webapp@2.0.5
|
||||||
webapp-hashing@1.1.2
|
webapp-hashing@1.1.2
|
||||||
|
|||||||
289
imports/api/files.js
Normal file
289
imports/api/files.js
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { FilesCollection } from 'meteor/ostrio:files';
|
||||||
|
import { createBucket } from '/imports/api/lib/grid/createBucket.js';
|
||||||
|
import { createObjectId } from '/imports/api/lib/grid/createObjectId.js';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
// import { Mongo } from 'meteor/mongo';
|
||||||
|
|
||||||
|
let filesBucket;
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
filesBucket = createBucket('allFiles');
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilesCol = new FilesCollection({
|
||||||
|
collectionName: 'Files',
|
||||||
|
allowClientCode: true,
|
||||||
|
debug: Meteor.isServer && process.env.NODE_ENV === 'development',
|
||||||
|
onBeforeUpload (file) {
|
||||||
|
// if (file.size <= 10485760 && /png|jpg|jpeg/i.test(file.extension)) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return 'Please upload image, with size equal or less than 10MB';
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
onAfterUpload(file) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
// here you could manipulate your file
|
||||||
|
// and create a new version, for example a scaled 'thumbnail'
|
||||||
|
// ...
|
||||||
|
|
||||||
|
console.log("file_versions: ", file.versions);
|
||||||
|
|
||||||
|
// then we read all versions we have got so far
|
||||||
|
Object.keys(file.versions).forEach(versionName => {
|
||||||
|
const metadata = { ...file.meta, versionName, fileId: file._id };
|
||||||
|
fs.createReadStream(file.versions[ versionName ].path)
|
||||||
|
|
||||||
|
// this is where we upload the binary to the bucket
|
||||||
|
.pipe(filesBucket.openUploadStream(
|
||||||
|
file.name,
|
||||||
|
{
|
||||||
|
contentType: file.type || 'binary/octet-stream',
|
||||||
|
metadata
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
|
// and we unlink the file from the fs on any error
|
||||||
|
// that occurred during the upload to prevent zombie files
|
||||||
|
.on('error', async err => {
|
||||||
|
console.error(err);
|
||||||
|
self.unlink(await this.collection.findOneAsync(file._id), versionName); // Unlink files from FS
|
||||||
|
})
|
||||||
|
|
||||||
|
// once we are finished, we attach the gridFS Object id on the
|
||||||
|
// FilesCollection document's meta section and finally unlink the
|
||||||
|
// upload file from the filesystem
|
||||||
|
.on('finish', Meteor.bindEnvironment(async ver => {
|
||||||
|
const property = `versions.${versionName}.meta.gridFsFileId`;
|
||||||
|
await self.collection.updateAsync(file._id, {
|
||||||
|
$set: {
|
||||||
|
[ property ]: ver._id.toHexString()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.unlink(await this.collection.findOneAsync(file._id), versionName); // Unlink files from FS
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
interceptDownload (http, file, versionName) {
|
||||||
|
const { gridFsFileId } = file.versions[ versionName ].meta || {};
|
||||||
|
if (gridFsFileId) {
|
||||||
|
const gfsId = createObjectId({ gridFsFileId });
|
||||||
|
const readStream = filesBucket.openDownloadStream(gfsId);
|
||||||
|
readStream.on('data', (data) => {
|
||||||
|
http.response.write(data);
|
||||||
|
})
|
||||||
|
|
||||||
|
readStream.on('end', () => {
|
||||||
|
http.response.end('end');
|
||||||
|
})
|
||||||
|
|
||||||
|
readStream.on('error', () => {
|
||||||
|
// not found probably
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
http.response.statusCode = 404;
|
||||||
|
http.response.end('not found');
|
||||||
|
})
|
||||||
|
|
||||||
|
http.response.setHeader('Cache-Control', this.cacheControl);
|
||||||
|
http.response.setHeader('Content-Disposition', `inline; filename="${file.name}"`);
|
||||||
|
}
|
||||||
|
return Boolean(gridFsFileId) // Serve file from either GridFS or FS if it wasn't uploaded yet
|
||||||
|
},
|
||||||
|
|
||||||
|
onAfterRemove (files) {
|
||||||
|
files.forEach(file => {
|
||||||
|
Object.keys(file.versions).forEach(versionName => {
|
||||||
|
const gridFsFileId = (file.versions[ versionName ].meta || {}).gridFsFileId;
|
||||||
|
if (gridFsFileId) {
|
||||||
|
const gfsId = createObjectId({ gridFsFileId });
|
||||||
|
filesBucket.deleteAsync(gfsId, err => { if (err) console.error(err); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// if (Meteor.isClient) {
|
||||||
|
// Meteor.subscribe('files.all');
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
|
||||||
|
Meteor.publish('files.all', () => {
|
||||||
|
return FilesCol.collection.find({userId: Meteor.userId()});
|
||||||
|
});
|
||||||
|
|
||||||
|
Meteor.publish('avatars.all', () => {
|
||||||
|
return Avatars.collection.find();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Meteor.publish('avatarsregistre.all', () => {
|
||||||
|
return AvatarsRegistre.collection.find();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Meteor.publish('files.avatar', () => {
|
||||||
|
// return FilesCol.collection.find({
|
||||||
|
// userId: Meteor.userId(),
|
||||||
|
// 'meta.type': 'avatar'
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Meteor.publish('files.avatarRegister', (avatarId) => {
|
||||||
|
// if (avatarId) {
|
||||||
|
// if (!Meteor.userId()) {
|
||||||
|
// return FilesCol.collection.find({_id: avatarId});
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Meteor.publish('files.folderTree', () => {
|
||||||
|
// //if (upId) {
|
||||||
|
// if (Meteor.userId()) {
|
||||||
|
// return FilesCol.collection.find({
|
||||||
|
// userId: Meteor.userId(),
|
||||||
|
// "meta.type": "folderTree"
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // files.cartellEventUpload
|
||||||
|
// Meteor.publish('files.cartellEventUpload', (cartellId) => {
|
||||||
|
// if (cartellId) {
|
||||||
|
// //if (!Meteor.userId()) {
|
||||||
|
// return FilesCol.collection.find({_id: cartellId});
|
||||||
|
// } else {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
|
||||||
|
'RenameFile'(data){
|
||||||
|
// if (!Meteor.userId()){
|
||||||
|
// throw new Meteor.Error('not-authorized');
|
||||||
|
// }
|
||||||
|
FilesCol.insertAsync({
|
||||||
|
...data,
|
||||||
|
createdAt: new Date(),
|
||||||
|
user: Meteor.userId()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'ReassignaUserIdFile'(userIdProvisional, uid){
|
||||||
|
// if (!Meteor.userId()){
|
||||||
|
// throw new Meteor.Error('not-authorized');
|
||||||
|
// }
|
||||||
|
|
||||||
|
FilesCol.collection.updateAsync({_id: userIdProvisional}, {
|
||||||
|
$set: {
|
||||||
|
meta: {
|
||||||
|
userId: uid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'RemoveFile'(fileToRemoveId) {
|
||||||
|
FilesCol.collection.removeAsync(fileToRemoveId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// getFolderTreeFiles() {
|
||||||
|
// return FilesCol.find({
|
||||||
|
// // userId: Meteor.userId(),
|
||||||
|
// // 'meta.type': 'folderTree'
|
||||||
|
// }).fetch();
|
||||||
|
// }
|
||||||
|
// 'dates.update'(data){
|
||||||
|
// // if (Meteor.userId() !== allcod.user){
|
||||||
|
// // throw new Meteor.Error('not-authorized');
|
||||||
|
// // }
|
||||||
|
// DatesCollection.update(data._id, {
|
||||||
|
// $set: {
|
||||||
|
// ...data
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
|
||||||
|
// 'dates.delete'(data){
|
||||||
|
// // if (Meteor.userId() !== allcod.user){
|
||||||
|
// // throw new Meteor.Error('not-authorized');
|
||||||
|
// // }
|
||||||
|
// DatesCollection.remove(data._id);
|
||||||
|
// },
|
||||||
|
|
||||||
|
// 'dates.remove'(id, context) {
|
||||||
|
// DatesCollection.remove(id);
|
||||||
|
// }
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new instance of the FilesCollection
|
||||||
|
const AvatarsRegistre = new FilesCollection({
|
||||||
|
collectionName: 'AvatarsRegistre',
|
||||||
|
storagePath: 'assets/avatarRegistreStorage',
|
||||||
|
downloadRoute: '/avatar-registre',
|
||||||
|
permissions: 0o755,
|
||||||
|
cacheControl: 'public, max-age=31536000',
|
||||||
|
allowClientCode: false, // Disallow remove files from Client
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new instance of the FilesCollection
|
||||||
|
const Avatars = new FilesCollection({
|
||||||
|
collectionName: 'Avatars',
|
||||||
|
storagePath: 'assets/avatarStorage',
|
||||||
|
downloadRoute: '/avatar',
|
||||||
|
permissions: 0o755,
|
||||||
|
cacheControl: 'public, max-age=31536000',
|
||||||
|
allowClientCode: false, // Disallow remove files from Client
|
||||||
|
});
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
|
||||||
|
'registraUsuariAmbAvatar'(username, email, password, avatar) {
|
||||||
|
// Check if the username and email are valid
|
||||||
|
if (!username || !email || !password) {
|
||||||
|
throw new Meteor.Error('invalid-input', 'Please fill in all fields');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the avatar is a valid file
|
||||||
|
if (!avatar || !avatar.file) {
|
||||||
|
throw new Meteor.Error('invalid-avatar', 'Please select a valid avatar image');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload the avatar to GridFS
|
||||||
|
const avatarId = Avatars.insert(avatar.file, (err, fileObj) => {
|
||||||
|
if (err) {
|
||||||
|
throw new Meteor.Error('avatar-upload-failed', 'Failed to upload avatar');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create the new user
|
||||||
|
const userId = Accounts.createUser({
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
profile: {
|
||||||
|
avatar: avatarId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the new user's ID
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export { FilesCol, AvatarsRegistre, Avatars };
|
||||||
6
imports/api/lib/grid/createBucket.js
Normal file
6
imports/api/lib/grid/createBucket.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { MongoInternals } from 'meteor/mongo';
|
||||||
|
|
||||||
|
export const createBucket = bucketName => {
|
||||||
|
const options = bucketName ? {bucketName} : (void 0);
|
||||||
|
return new MongoInternals.NpmModule.GridFSBucket(MongoInternals.defaultRemoteCollectionDriver().mongo.db, options);
|
||||||
|
}
|
||||||
3
imports/api/lib/grid/createObjectId.js
Normal file
3
imports/api/lib/grid/createObjectId.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { MongoInternals } from 'meteor/mongo'
|
||||||
|
|
||||||
|
export const createObjectId = ({gridFsFileId}) => new MongoInternals.NpmModule.ObjectID(gridFsFileId);
|
||||||
110
imports/api/lib/images.js
Normal file
110
imports/api/lib/images.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { FilesCollection } from 'meteor/ostrio:files';
|
||||||
|
import { createBucket } from '/imports/api/lib/grid/createBucket.js';
|
||||||
|
import { createObjectId } from '/imports/api/lib/grid/createObjectId.js';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
let imagesBucket;
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
imagesBucket = createBucket('allImages');
|
||||||
|
}
|
||||||
|
|
||||||
|
const Images = new FilesCollection({
|
||||||
|
collectionName: 'Images',
|
||||||
|
allowClientCode: true,
|
||||||
|
debug: Meteor.isServer && process.env.NODE_ENV === 'development',
|
||||||
|
onBeforeUpload (file) {
|
||||||
|
if (file.size <= 10485760 && /png|jpg|jpeg/i.test(file.extension)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return 'Please upload image, with size equal or less than 10MB';
|
||||||
|
},
|
||||||
|
onAfterUpload (file) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
// here you could manipulate your file
|
||||||
|
// and create a new version, for example a scaled 'thumbnail'
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// then we read all versions we have got so far
|
||||||
|
Object.keys(file.versions).forEach(versionName => {
|
||||||
|
const metadata = { ...file.meta, versionName, fileId: file._id };
|
||||||
|
fs.createReadStream(file.versions[ versionName ].path)
|
||||||
|
|
||||||
|
// this is where we upload the binary to the bucket
|
||||||
|
.pipe(imagesBucket.openUploadStream(
|
||||||
|
file.name,
|
||||||
|
{
|
||||||
|
contentType: file.type || 'binary/octet-stream',
|
||||||
|
metadata
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
|
// and we unlink the file from the fs on any error
|
||||||
|
// that occurred during the upload to prevent zombie files
|
||||||
|
.on('error', err => {
|
||||||
|
console.error(err);
|
||||||
|
self.unlink(this.collection.findOne(file._id), versionName); // Unlink files from FS
|
||||||
|
})
|
||||||
|
|
||||||
|
// once we are finished, we attach the gridFS Object id on the
|
||||||
|
// FilesCollection document's meta section and finally unlink the
|
||||||
|
// upload file from the filesystem
|
||||||
|
.on('finish', Meteor.bindEnvironment(ver => {
|
||||||
|
const property = `versions.${versionName}.meta.gridFsFileId`;
|
||||||
|
self.collection.update(file._id, {
|
||||||
|
$set: {
|
||||||
|
[ property ]: ver._id.toHexString()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.unlink(this.collection.findOne(file._id), versionName); // Unlink files from FS
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
interceptDownload (http, file, versionName) {
|
||||||
|
const { gridFsFileId } = file.versions[ versionName ].meta || {};
|
||||||
|
if (gridFsFileId) {
|
||||||
|
const gfsId = createObjectId({ gridFsFileId });
|
||||||
|
const readStream = imagesBucket.openDownloadStream(gfsId);
|
||||||
|
readStream.on('data', (data) => {
|
||||||
|
http.response.write(data);
|
||||||
|
})
|
||||||
|
|
||||||
|
readStream.on('end', () => {
|
||||||
|
http.response.end('end');
|
||||||
|
})
|
||||||
|
|
||||||
|
readStream.on('error', () => {
|
||||||
|
// not found probably
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
http.response.statusCode = 404;
|
||||||
|
http.response.end('not found');
|
||||||
|
})
|
||||||
|
|
||||||
|
http.response.setHeader('Cache-Control', this.cacheControl);
|
||||||
|
http.response.setHeader('Content-Disposition', `inline; filename="${file.name}"`);
|
||||||
|
}
|
||||||
|
return Boolean(gridFsFileId) // Serve file from either GridFS or FS if it wasn't uploaded yet
|
||||||
|
},
|
||||||
|
onAfterRemove (files) {
|
||||||
|
files.forEach(file => {
|
||||||
|
Object.keys(file.versions).forEach(versionName => {
|
||||||
|
const gridFsFileId = (file.versions[ versionName ].meta || {}).gridFsFileId;
|
||||||
|
if (gridFsFileId) {
|
||||||
|
const gfsId = createObjectId({ gridFsFileId });
|
||||||
|
imagesBucket.delete(gfsId, err => { if (err) console.error(err); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
Meteor.subscribe('files.images.all');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Meteor.isServer) {
|
||||||
|
Meteor.publish('files.images.all', () => Images.collection.find({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Images };
|
||||||
62
imports/api/lib/persons.js
Normal file
62
imports/api/lib/persons.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { Mongo } from 'meteor/mongo';
|
||||||
|
import { Images } from './images.js';
|
||||||
|
// import SimpleSchema from 'simpl-schema';
|
||||||
|
|
||||||
|
// SimpleSchema.extendOptions(['autoform']);
|
||||||
|
// SimpleSchema.setDefaultMessages({
|
||||||
|
// initialLanguage: 'en',
|
||||||
|
// messages: {
|
||||||
|
// en: {
|
||||||
|
// uploadError: '{{{value}}}'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
const Persons = new Mongo.Collection('persons');
|
||||||
|
|
||||||
|
Persons.helpers({
|
||||||
|
profilePic() {
|
||||||
|
return Images.find({_id: this.profilePicId});
|
||||||
|
},
|
||||||
|
backgroundPic() {
|
||||||
|
return Images.find({_id: this.backgroundPicId});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Persons.attachSchema({
|
||||||
|
// name: {
|
||||||
|
// type: String,
|
||||||
|
// label: 'Name'
|
||||||
|
// },
|
||||||
|
// profilePicId: {
|
||||||
|
// type: String,
|
||||||
|
// label: 'Profile Pic Id',
|
||||||
|
// autoform: {
|
||||||
|
// afFieldInput: {
|
||||||
|
// type: 'fileUpload',
|
||||||
|
// collection: 'Images',
|
||||||
|
// insertConfig: {
|
||||||
|
// transport: 'http'
|
||||||
|
// },
|
||||||
|
// uploadTemplate: 'uploadField', // <- Optional
|
||||||
|
// previewTemplate: 'uploadPreview', // <- Optional,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// backgroundPicId: {
|
||||||
|
// type: String,
|
||||||
|
// label: 'Background Pic Id',
|
||||||
|
// autoform: {
|
||||||
|
// afFieldInput: {
|
||||||
|
// type: 'fileUpload',
|
||||||
|
// collection: 'Images',
|
||||||
|
// accept: '.png,.jpg,.jpeg', // use built-in accept config
|
||||||
|
// insertConfig: {
|
||||||
|
// transport: 'http'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
export { Persons };
|
||||||
@ -47,7 +47,7 @@ const useLongPress = (mostraMenu, setMostraMenu) => {
|
|||||||
if (isPressed) {
|
if (isPressed) {
|
||||||
setIsPressed(false);
|
setIsPressed(false);
|
||||||
// Clear any pending timeout
|
// Clear any pending timeout
|
||||||
clearTimeout(timeoutId?.current);
|
// clearTimeout(timeoutId?.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,6 +69,7 @@ const useLongPress = (mostraMenu, setMostraMenu) => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
// return () => clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => clearTimeout(timeoutId);
|
return () => clearTimeout(timeoutId);
|
||||||
@ -248,7 +249,7 @@ const UserStat = ({esAdministrador, setEsAdministrador}) => {
|
|||||||
left: 0,
|
left: 0,
|
||||||
top: `5em`,
|
top: `5em`,
|
||||||
padding: `.4em .5em`,
|
padding: `.4em .5em`,
|
||||||
border: `1px #aaa`,
|
border: `1px solid #aaa`,
|
||||||
cursor: `pointer`,
|
cursor: `pointer`,
|
||||||
zIndex: `200`
|
zIndex: `200`
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,14 +1,45 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { Accounts } from 'meteor/accounts-base';
|
import { Accounts } from 'meteor/accounts-base';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
// import { useTracker, useSubscribe, useFind } from 'meteor/react-meteor-data/suspense';
|
||||||
|
import { useSubscribe, useFind } from 'meteor/react-meteor-data';
|
||||||
import { Roles } from 'meteor/roles';
|
import { Roles } from 'meteor/roles';
|
||||||
import { ROLS_GLOBALS } from '../roles';
|
import { ROLS_GLOBALS } from '../roles';
|
||||||
|
import { AvatarsRegistre } from '/imports/api/files.js';
|
||||||
|
import AvatarFileUpload from '/imports/ui/files/AvatarFileUpload';
|
||||||
|
|
||||||
|
|
||||||
export const Login = () => {
|
export const Login = () => {
|
||||||
const [isLogin, setIsLogin] = useState( { initialState: true } );
|
const [isLogin, setIsLogin] = useState( { initialState: true } );
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// const avatarinput = useRef();
|
||||||
|
|
||||||
|
// const [avatarId, setAvatarId] = useState();
|
||||||
|
// const [avatarLink, setAvatarLink] = useState();
|
||||||
|
|
||||||
|
// const [novaImg, setNovaImg] = useState(false);
|
||||||
|
|
||||||
|
// const [avatar, setAvatar] = useState(null);
|
||||||
|
|
||||||
|
// let files;
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
|
||||||
|
// useSubscribe('avatarsregistre.all');
|
||||||
|
const isLoading = useSubscribe('avatarsregistre.all');
|
||||||
|
|
||||||
|
const files = useFind(() => AvatarsRegistre.find(), []);
|
||||||
|
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// const files = useTracker("avatars", () => {
|
||||||
|
// return Avatars.find({}).fetchAsync();
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleLogin = (e) => {
|
const handleLogin = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// console.dir(e);
|
// console.dir(e);
|
||||||
@ -44,6 +75,7 @@ export const Login = () => {
|
|||||||
email,
|
email,
|
||||||
password
|
password
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("userId deL NOU USUARI: ", userId);
|
console.log("userId deL NOU USUARI: ", userId);
|
||||||
userId && await Roles.addUsersToRolesAsync(userId, [ROLS_GLOBALS.USUARI]);
|
userId && await Roles.addUsersToRolesAsync(userId, [ROLS_GLOBALS.USUARI]);
|
||||||
navigate('/');
|
navigate('/');
|
||||||
@ -74,6 +106,8 @@ export const Login = () => {
|
|||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
action={async d => {
|
action={async d => {
|
||||||
@ -109,7 +143,11 @@ export const Login = () => {
|
|||||||
password2
|
password2
|
||||||
};
|
};
|
||||||
|
|
||||||
Meteor.callAsync('creaUsuariAmbCodi', uObj, codi);
|
// Meteor.callAsync('creaUsuariAmbCodi', uObj, codi);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Meteor.callAsync('registraUsuariAmbAvatarICodi', uObj, codi, avatarinput.current);
|
||||||
|
|
||||||
// userId = await Accounts.createUser({
|
// userId = await Accounts.createUser({
|
||||||
// username,
|
// username,
|
||||||
@ -163,7 +201,8 @@ export const Login = () => {
|
|||||||
backgroundColor: `#eeed`
|
backgroundColor: `#eeed`
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Avatar: <img
|
{/* Avatar:
|
||||||
|
<img
|
||||||
style={{
|
style={{
|
||||||
width: `3em`,
|
width: `3em`,
|
||||||
height: `3em`,
|
height: `3em`,
|
||||||
@ -179,6 +218,41 @@ export const Login = () => {
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<label
|
||||||
|
htmlFor="avatarinput"
|
||||||
|
style={{
|
||||||
|
minWidth: `3em`,
|
||||||
|
minHeight: `3em`,
|
||||||
|
borderRadius: `50%`,
|
||||||
|
border: `.6vh solid white`,
|
||||||
|
display: `block`,
|
||||||
|
// backgroundImage: `url(${link}), linear-gradient(to bottom right, transparent, #fffd)`,
|
||||||
|
backgroundSize: `cover`,
|
||||||
|
backgroundRepeat: `no-repeat`,
|
||||||
|
margin: `0 auto -1.5em auto`,
|
||||||
|
aspectRatio: `1/1`
|
||||||
|
}}
|
||||||
|
></label> */}
|
||||||
|
|
||||||
|
|
||||||
|
{/* <input type="file"
|
||||||
|
name="avatarinput"
|
||||||
|
id="avatarinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={avatarinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
style={{
|
||||||
|
position: `relative`,
|
||||||
|
zIndex: `-1`,
|
||||||
|
opacity: '0'
|
||||||
|
}}
|
||||||
|
accept="image/gif, image/jpeg, image/png"
|
||||||
|
/> */}
|
||||||
|
<hr />
|
||||||
|
<AvatarFileUpload />
|
||||||
|
<hr />
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<label htmlFor="username">Nom d'usuari: </label>
|
<label htmlFor="username">Nom d'usuari: </label>
|
||||||
<input id="username" name="username" type="text" required />
|
<input id="username" name="username" type="text" required />
|
||||||
|
|||||||
226
imports/ui/files/AvatarFileUpload.jsx
Normal file
226
imports/ui/files/AvatarFileUpload.jsx
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
import { useTracker, useSubscribe, useFind } from 'meteor/react-meteor-data/suspense';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef, Suspense } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { AvatarsRegistre } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFileStart from '/imports/ui/files/IndividualFile.jsx'; // <-------------------------
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
//const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const AvatarFileUpload = (props) => {
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const [preview, setPreview] = useState("");
|
||||||
|
|
||||||
|
// const reseter = useState(0);
|
||||||
|
|
||||||
|
// const refForm = useRef();
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
useSubscribe('avatarsregistre.all');
|
||||||
|
|
||||||
|
const files = useFind(AvatarsRegistre, [
|
||||||
|
{},
|
||||||
|
{ sort: { createdAt: -1 } },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// const files = useTracker("avatars", async () => {
|
||||||
|
// // const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = await AvatarsRegistre?.find({meta:{userId: props.uidProvisional || Meteor.userId(), entId: props.entId}}, {sort: {name: 1}})//.fetchAsync(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return files;
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = (event) => {
|
||||||
|
console.log("eventTarget: ", event.target);
|
||||||
|
setPreview(event.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
|
||||||
|
// setPreview(file);
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = AvatarsRegistre.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
entId: props.entId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
// props.setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function UploadingFile({preview}) {
|
||||||
|
|
||||||
|
// console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
// console.log("uploading: ", uploading);
|
||||||
|
// console.log("preview: ", preview);
|
||||||
|
return <div>
|
||||||
|
<img
|
||||||
|
src={preview}
|
||||||
|
alt=""
|
||||||
|
style={{
|
||||||
|
border: `solid 3px #6666`,
|
||||||
|
borderRadius: `50%`,
|
||||||
|
width: `5rem`,
|
||||||
|
margin: `0 auto`,
|
||||||
|
display: `block`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{/* {uploading.file.name} */}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%', backgroundColor: `lime`, borderRadius: `1rem`, textAlign: `center`, boxShadow: `inset 0 0 .5rem .5rem #4447`}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar"
|
||||||
|
>
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
{/* <span>{progress}%</span> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Display = async () => await files?.map(async (aFile, key) => {
|
||||||
|
|
||||||
|
let link = await AvatarsRegistre.findOneAsync({_id: aFile._id}); //The "view/download" link
|
||||||
|
let linkOriginalURL = `${window.location.origin}${link._fileRef._downloadRoute}/${link._fileRef._collectionName}/${link._fileRef._id}/original/${link._fileRef._id}.${link._fileRef.extension}`;
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
|
||||||
|
return <Suspense fallback="<>Loading...</>">
|
||||||
|
<div key={'file' + key}>
|
||||||
|
<IndividualFileStart
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={linkOriginalURL}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Suspense>
|
||||||
|
}).reverse();
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
// let display =
|
||||||
|
|
||||||
|
return <Suspense fallback="Loading...">
|
||||||
|
|
||||||
|
<button
|
||||||
|
className='btArxiu'
|
||||||
|
onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
// refForm.current.reset();
|
||||||
|
fileinput.current.click();
|
||||||
|
//reseter[1](reseter[0] + 1);
|
||||||
|
//refForm.current.reset();
|
||||||
|
ev.target.value = null;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="fa-solid fa-paperclip" >Add file</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
style={{display: `none`}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UploadingFile {...{preview}} />
|
||||||
|
<Display />
|
||||||
|
|
||||||
|
</Suspense>
|
||||||
|
// else return <div>Carregant llista d'arxius...</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = AvatarsRegistre.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default AvatarFileUpload;
|
||||||
82
imports/ui/files/AvatarIndividualFile.jsx
Normal file
82
imports/ui/files/AvatarIndividualFile.jsx
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import React from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const AvatarIndividualFile = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile(){
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.call('RemoveFile', props.fileId, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameFile(){
|
||||||
|
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
Meteor.call('RenameFile', props.fileId, prompt, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<img
|
||||||
|
src={props.fileUrl}
|
||||||
|
alt={props.fileName}
|
||||||
|
style={{maxWidth: `200px`, maxHeight: `200px`}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm"
|
||||||
|
target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export default AvatarIndividualFile;
|
||||||
204
imports/ui/files/FileUpload.jsx
Normal file
204
imports/ui/files/FileUpload.jsx
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
import { useSubscribe, useFind, useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFile from '/imports/ui/files/IndividualFile.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
// const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const FileUploadComponent = (props) => {
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const isLoading = useSubscribe('files.all');
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
//const files = FilesCol?.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
console.dir("files from FU: ", files.cursor);
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}, [isLoading()]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
console.dir("fufiles: ", files);
|
||||||
|
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insertAsync({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId() // Optional, used to check on server for file tampering
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true);// Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
// console.dir("uploaded: this ", this.config.fileId);
|
||||||
|
// console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
// console.log("upError: ", error);
|
||||||
|
props?.setUpId(fileObj?.config.fileId);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar"
|
||||||
|
>
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
// if(!isLoading() && files)
|
||||||
|
//if (files /* && docsReadyYet*/) {
|
||||||
|
{
|
||||||
|
console.dir("FUfiles: ", files);
|
||||||
|
//let fileCursors = files;
|
||||||
|
|
||||||
|
// console.dir("fileCursors: ", fileCursors);
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = files?.map(async (aFile, key) => {
|
||||||
|
console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = await FilesCol.findOneAsync({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
console.log("link: ", link);
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<p>Upload New File:</p>
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
// else return <div>Loading file list</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default FileUploadComponent;
|
||||||
208
imports/ui/files/FileUploadAdmin.jsx
Normal file
208
imports/ui/files/FileUploadAdmin.jsx
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
import IndividualFile from '/imports/ui/files/IndividualFile.jsx';
|
||||||
|
import _ from 'lodash';
|
||||||
|
// import { useUser } from 'meteor/react-meteor-accounts';
|
||||||
|
// import { Roles } from 'meteor/alanning:roles';
|
||||||
|
// import { GLOBAL_ROLES } from '../roles';
|
||||||
|
// import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
|
||||||
|
//const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const FileUploadAdmin = (props) => {
|
||||||
|
|
||||||
|
// const user = useUser();
|
||||||
|
// const isAdmin = useTracker(() => Roles.userIsInRole(user?._id, GLOBAL_ROLES.ADMIN));
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const reseter = useState(0);
|
||||||
|
|
||||||
|
const refForm = useRef();
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find({meta:{userId: props.uidProvisional || Meteor.userId(), entId: props.entId}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
entId: props.entId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
// props.setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar">
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
if (files /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = fileCursors.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <>
|
||||||
|
|
||||||
|
|
||||||
|
<button
|
||||||
|
className='btArxiu'
|
||||||
|
onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
// refForm.current.reset();
|
||||||
|
fileinput.current.click();
|
||||||
|
//reseter[1](reseter[0] + 1);
|
||||||
|
//refForm.current.reset();
|
||||||
|
ev.target.value = null;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="fas fa-paperclip" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
style={{display: `none`}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{/* <div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
{/* {display} */}
|
||||||
|
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
else return <div>Carregant llista d'arxius...</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default FileUploadAdmin;
|
||||||
203
imports/ui/files/FileUploadEnt.jsx
Normal file
203
imports/ui/files/FileUploadEnt.jsx
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFile from '/imports/ui/files/IndividualFile.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
//const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const FileUploadEnt = (props) => {
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const reseter = useState(0);
|
||||||
|
|
||||||
|
const refForm = useRef();
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find({meta:{userId: props.uidProvisional || Meteor.userId(), entId: props.entId}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
entId: props.entId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
// props.setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar">
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
if (files /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = fileCursors.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <>
|
||||||
|
|
||||||
|
|
||||||
|
<button
|
||||||
|
className='btArxiu'
|
||||||
|
onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
// refForm.current.reset();
|
||||||
|
fileinput.current.click();
|
||||||
|
//reseter[1](reseter[0] + 1);
|
||||||
|
//refForm.current.reset();
|
||||||
|
ev.target.value = null;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="fas fa-paperclip" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
style={{display: `none`}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{/* <div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
{/* {display} */}
|
||||||
|
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
else return <div>Carregant llista d'arxius...</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default FileUploadEnt;
|
||||||
235
imports/ui/files/FileUploadPOI.jsx
Normal file
235
imports/ui/files/FileUploadPOI.jsx
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
import { useTracker, useSubscribe, useFind } from 'meteor/react-meteor-data/suspense';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef, Suspense } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFilePOI from '/imports/ui/files/IndividualFilePOI.jsx'; // <-------------------------
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
//const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const useFiles = () => {
|
||||||
|
useSubscribe('files.all');
|
||||||
|
|
||||||
|
const files = useTracker("files", () => FilesCol.find({}).fetchAsync(), []);
|
||||||
|
|
||||||
|
return files;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const ShowUploads = ({uploading, progress, filePreviewURI, inProgress}) => {
|
||||||
|
// console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
// console.log("uploading: ", uploading);
|
||||||
|
return inProgress && <div style={{
|
||||||
|
border: `1px solid`,
|
||||||
|
borderRadius: `5px`,
|
||||||
|
color: `#cccc`,
|
||||||
|
padding: `1rem`,
|
||||||
|
marginBottom: `1em`
|
||||||
|
}}>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<img src={filePreviewURI} />
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar"
|
||||||
|
>
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const DisplayUploadFile = ({files}) => files?.map(async (aFile, key) => {
|
||||||
|
|
||||||
|
let link = await FilesCol.findOneAsync({_id: aFile._id}); //The "view/download" link
|
||||||
|
let linkOriginalURL = `${window.location.origin}${link._fileRef._downloadRoute}/${link._fileRef._collectionName}/${link._fileRef._id}/original/${link._fileRef._id}.${link._fileRef.extension}`;
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFilePOI
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={linkOriginalURL}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>;
|
||||||
|
}).reverse();
|
||||||
|
|
||||||
|
|
||||||
|
const FileUploadPOI = (props) => {
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const [filePreviewURI, setFilePreviewURI] = useState(null);
|
||||||
|
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const files = useFiles();
|
||||||
|
|
||||||
|
console.log("files: ", files);
|
||||||
|
// console.log("fileinput: ", fileinput);
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
console.log("UPLOADING IT");
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
console.log("E: ", e);
|
||||||
|
console.log("FILE: ", file);
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
|
||||||
|
let reader = new FileReader();
|
||||||
|
|
||||||
|
console.log("READER: ", reader);
|
||||||
|
|
||||||
|
// reader.onload = (evt) => {
|
||||||
|
// console.log("ONLOAD: ", evt.target.result);
|
||||||
|
// };
|
||||||
|
reader.readAsDataURL(e.currentTarget.files[0]);
|
||||||
|
|
||||||
|
reader.onload = function(ev){
|
||||||
|
|
||||||
|
|
||||||
|
console.log("ev.target.result: ", ev.target.result);
|
||||||
|
|
||||||
|
setFilePreviewURI(ev.target.result);
|
||||||
|
|
||||||
|
console.log("filePreviewURI: ", filePreviewURI);
|
||||||
|
|
||||||
|
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
entId: props.entId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
console.log("setInProgress: true");
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
console.log("file: ", file);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('End', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
setProgress(0);
|
||||||
|
console.log("setInProgress: false");
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
// props.setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
console.log("setInProgress: false");
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
console.log("setInProgress: false");
|
||||||
|
setInProgress(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
if (progress === 100) {
|
||||||
|
console.log("setInProgress: false");
|
||||||
|
setInProgress(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return <>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className='btArxiu'
|
||||||
|
onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
// refForm.current.reset();
|
||||||
|
fileinput.current.click();
|
||||||
|
//reseter[1](reseter[0] + 1);
|
||||||
|
//refForm.current.reset();
|
||||||
|
// ev.target.value = null;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="fa-solid fa-image" >Add file</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={() => {
|
||||||
|
setInProgress(true);
|
||||||
|
}}
|
||||||
|
style={{display: `none`}}
|
||||||
|
name="fileinput"
|
||||||
|
onClick={(ev) => {
|
||||||
|
// ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
<ShowUploads progress={progress} filePreviewURI={filePreviewURI} uploading={uploading} inProgress={inProgress} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DisplayUploadFile files={files} />
|
||||||
|
|
||||||
|
</>;
|
||||||
|
// else return <div>Carregant llista d'arxius...</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FileUploadPOI;
|
||||||
196
imports/ui/files/FileUploadStart.jsx
Normal file
196
imports/ui/files/FileUploadStart.jsx
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
import { useTracker, useSubscribe, useFind } from 'meteor/react-meteor-data/suspense';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef, Suspense } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFileStart from '/imports/ui/files/IndividualFile.jsx'; // <-------------------------
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
//const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const FileUploadStart = (props) => {
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const reseter = useState(0);
|
||||||
|
|
||||||
|
const refForm = useRef();
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
useSubscribe('files.all');
|
||||||
|
|
||||||
|
const files = useTracker("files", async () => {
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = await FilesCol?.find({meta:{userId: props.uidProvisional || Meteor.userId(), entId: props.entId}}, {sort: {name: 1}})//.fetchAsync(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
entId: props.entId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
// props.setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
// console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar"
|
||||||
|
>
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Display = async () => await files?.map(async (aFile, key) => {
|
||||||
|
|
||||||
|
let link = await FilesCol.findOneAsync({_id: aFile._id}); //The "view/download" link
|
||||||
|
let linkOriginalURL = `${window.location.origin}${link._fileRef._downloadRoute}/${link._fileRef._collectionName}/${link._fileRef._id}/original/${link._fileRef._id}.${link._fileRef.extension}`;
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
|
||||||
|
return <Suspense fallback="<>Loading...</>">
|
||||||
|
<div key={'file' + key}>
|
||||||
|
<IndividualFileStart
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={linkOriginalURL}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Suspense>
|
||||||
|
}).reverse();
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
// let display =
|
||||||
|
|
||||||
|
return <Suspense fallback="Loading...">
|
||||||
|
<button
|
||||||
|
className='btArxiu'
|
||||||
|
onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
// refForm.current.reset();
|
||||||
|
fileinput.current.click();
|
||||||
|
//reseter[1](reseter[0] + 1);
|
||||||
|
//refForm.current.reset();
|
||||||
|
ev.target.value = null;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="fa-solid fa-paperclip" >Add file</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
style={{display: `none`}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Display />
|
||||||
|
</Suspense>
|
||||||
|
// else return <div>Carregant llista d'arxius...</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default FileUploadStart;
|
||||||
188
imports/ui/files/FileUpload_abans.jsx
Normal file
188
imports/ui/files/FileUpload_abans.jsx
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFile from '/imports/ui/files/IndividualFile.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const FileUploadComponent = (props) => {
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find({meta:{userId: props?.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
locator: props.fileLocator,
|
||||||
|
userId: props.uidProvisional || Meteor.userId() // Optional, used to check on server for file tampering
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true);// Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
props.setUpId(fileObj?._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar">
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
if (files /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = fileCursors.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<p>Upload New File:</p>
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else return <div>Loading file list</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default FileUploadComponent;
|
||||||
186
imports/ui/files/FileUpload_ori.jsx
Normal file
186
imports/ui/files/FileUpload_ori.jsx
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import { withTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFile from '/imports/ui/files/IndividualFile.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
class FileUploadComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
uploading: [],
|
||||||
|
progress: 0,
|
||||||
|
inProgress: false
|
||||||
|
};
|
||||||
|
|
||||||
|
this.uploadIt = this.uploadIt.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file: file,
|
||||||
|
meta: {
|
||||||
|
locator: self.props.fileLocator,
|
||||||
|
userId: this.props.uidProvisional || Meteor.userId() // Optional, used to check on server for file tampering
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
self.setState({
|
||||||
|
uploading: uploadInstance, // Keep track of this instance to use below
|
||||||
|
inProgress: true // Show the progress bar now
|
||||||
|
});
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
//this.props?.setAvatarId(fileObj._id);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
//console.log(`setAvatarId: ${this.props?.setAvatarId}`);
|
||||||
|
|
||||||
|
// this.props.setUpId(fileObj._id);
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
self.refs['fileinput'].value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
self.setState({
|
||||||
|
uploading: [],
|
||||||
|
progress: 0,
|
||||||
|
inProgress: false
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
self.setState({
|
||||||
|
progress: progress
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
showUploads() {
|
||||||
|
console.log('**********************************', this.state.uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(this.state.uploading)) {
|
||||||
|
return <div>
|
||||||
|
{this.state.uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: this.state.progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={this.state.progress || 0} role="progressbar"
|
||||||
|
className="progress-bar">
|
||||||
|
<span className="sr-only">{this.state.progress}% Complete (success)</span>
|
||||||
|
<span>{this.state.progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
debug("Rendering FileUpload",this.props.docsReadyYet);
|
||||||
|
if (this.props.files && this.props.docsReadyYet) {
|
||||||
|
|
||||||
|
let fileCursors = this.props.files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = fileCursors.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<p>Upload New File:</p>
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={this.state.inProgress}
|
||||||
|
ref="fileinput"
|
||||||
|
onChange={this.uploadIt}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{this.showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else return <div>Loading file list</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
export default withTracker( ( props ) => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
// const setAvatarId = props.setAvatarId;
|
||||||
|
|
||||||
|
return {
|
||||||
|
docsReadyYet,
|
||||||
|
files,
|
||||||
|
// setAvatarId
|
||||||
|
};
|
||||||
|
})(FileUploadComponent);
|
||||||
34
imports/ui/files/Files.jsx
Normal file
34
imports/ui/files/Files.jsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// import { Meteor } from 'meteor/meteor';
|
||||||
|
import React from 'react';
|
||||||
|
import { useSubscribe, useFind, useTracker } from 'meteor/react-meteor-data/suspense';
|
||||||
|
|
||||||
|
// import { FilesCollection } from '/imports/api/files.js';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
import FileUploadStart from '/imports/ui/files/FileUploadStart.jsx';
|
||||||
|
|
||||||
|
|
||||||
|
const Files = () => {
|
||||||
|
|
||||||
|
useSubscribe('files.all');
|
||||||
|
|
||||||
|
const files = useTracker("files", () => {
|
||||||
|
const files = FilesCol.find({}).fetchAsync();
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<h1 style={{
|
||||||
|
fontFamily: `cyber`,
|
||||||
|
padding: `.7rem`,
|
||||||
|
color: `#ff0c`,
|
||||||
|
textShadow: `.02em .02em .1em black`
|
||||||
|
}}>Files</h1>
|
||||||
|
{
|
||||||
|
|
||||||
|
<FileUploadStart />
|
||||||
|
|
||||||
|
}
|
||||||
|
</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Files };
|
||||||
217
imports/ui/files/FilesCartellEvent/FileUploadCartellEvent.jsx
Normal file
217
imports/ui/files/FilesCartellEvent/FileUploadCartellEvent.jsx
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import { IndividualFileCartellEvent } from '/imports/ui/files/FilesCartellEvent/IndividualFileCartellEvent.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
//const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
const FileUploadCartellEvent = (props) => {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const cartellId = new Mongo.ObjectID();
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
const [upId, setUpId] = useState(null);
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.cartellEventUpload', upId);
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find(upId).fetch(); // Meteor.userId() ?? "nop" //"meta.avatarId": avatarId
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
// locator: props.fileLocator,
|
||||||
|
// userId: props.uidProvisional || Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
// eventId: props.eventId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false)
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
|
||||||
|
props.setCartellId(fileObj._id);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
|
||||||
|
props.setNovaImg(true);
|
||||||
|
})
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%', background: "white"}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar">
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
// if (files /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
// let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = files?.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: upId})?.link(); //The "view/download" link
|
||||||
|
|
||||||
|
props.setCartellLink(link);
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
<IndividualFileCartellEvent
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
{/* <button onClick={ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
Meteor.call('userAvatarUpdate', avatarId, avatarLink, () => {
|
||||||
|
setNovaImg(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// alert(`
|
||||||
|
// avatarId: ${avatarId}
|
||||||
|
// avatarLink: ${avatarLink}`);
|
||||||
|
|
||||||
|
}}>Estableix</button>*/}
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<p>Upload New File:</p>
|
||||||
|
<label htmlFor="fileinput">Tria la imatge de l'event: </label>
|
||||||
|
<br />
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
// }
|
||||||
|
// else return <div>Loading file list</div>;
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export { FileUploadCartellEvent };
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
import React from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const IndividualFileCartellEvent = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile(){
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.call('RemoveFile', props.fileId, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameFile(){
|
||||||
|
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
Meteor.call('RenameFile', props.fileId, prompt, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<a href={props.fileUrl} target="_blank" >
|
||||||
|
<img
|
||||||
|
src={props.fileUrl}
|
||||||
|
alt={props.fileName}
|
||||||
|
style={{maxWidth: `200px`, maxHeight: `200px`}}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* <div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm"
|
||||||
|
target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export { IndividualFileCartellEvent };
|
||||||
210
imports/ui/files/FolderTreeFileUpload.jsx
Normal file
210
imports/ui/files/FolderTreeFileUpload.jsx
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { Mongo } from 'meteor/mongo';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import FolderTreeIndividualFile from '/imports/ui/files/FolderTreeIndividualFile.jsx';
|
||||||
|
|
||||||
|
import _, { upperCase } from 'lodash';
|
||||||
|
|
||||||
|
const debug = require('debug')('demo:file');
|
||||||
|
|
||||||
|
|
||||||
|
const FolderTreeFileUpload = (props) => {
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const treeFileId = new Mongo.ObjectID();
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const [upId, setUpId] = useState(null);
|
||||||
|
|
||||||
|
const [uploading, setUploading] = useState([]);
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [inProgress, setInProgress] = useState(false);
|
||||||
|
|
||||||
|
const fileinput = useRef();
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.folderTree', upId);
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find(upId).fetch(); // Meteor.userId() ?? "nop" //"meta.avatarId": avatarId
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
function uploadIt(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
//let self = this;
|
||||||
|
|
||||||
|
if (e.currentTarget.files && e.currentTarget.files[0]) {
|
||||||
|
// We upload only one file, in case
|
||||||
|
// there was multiple files selected
|
||||||
|
var file = e.currentTarget.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
console.log("IfFile: ", file);
|
||||||
|
let uploadInstance = FilesCol.insert({
|
||||||
|
file,
|
||||||
|
meta: {
|
||||||
|
//locator: file.link(),
|
||||||
|
userId: Meteor.userId(), // Optional, used to check on server for file tampering
|
||||||
|
type: "folderTree"
|
||||||
|
//avatarId
|
||||||
|
},
|
||||||
|
chunkSize: 'dynamic',
|
||||||
|
allowWebWorkers: true // If you see issues with uploads, change this to false
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
setUploading(uploadInstance); // Keep track of this instance to use below
|
||||||
|
setInProgress(true); // Show the progress bar now
|
||||||
|
|
||||||
|
// These are the event functions, don't need most of them, it shows where we are in the process
|
||||||
|
uploadInstance.on('start', function () {
|
||||||
|
console.log('Starting');
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('end', function (error, fileObj) {
|
||||||
|
console.log('On end File Object: ', fileObj);
|
||||||
|
|
||||||
|
props.setFolderTreeId(fileObj._id);
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('uploaded', function (error, fileObj) {
|
||||||
|
console.log('uploaded: ', fileObj);
|
||||||
|
|
||||||
|
setUpId(fileObj._id);
|
||||||
|
|
||||||
|
// Remove the filename from the upload box
|
||||||
|
fileinput.current.value = '';
|
||||||
|
|
||||||
|
// Reset our state for the next file
|
||||||
|
setUploading([]);
|
||||||
|
setProgress(0);
|
||||||
|
setInProgress(false);
|
||||||
|
|
||||||
|
props.setNouFolderTree(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('error', function (error, fileObj) {
|
||||||
|
console.log('Error during upload: ' + error)
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.on('progress', function (progress, fileObj) {
|
||||||
|
console.log('Upload Percentage: ' + progress)
|
||||||
|
// Update our progress bar
|
||||||
|
setProgress(progress);
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadInstance.start(); // Must manually start the upload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
function showUploads() {
|
||||||
|
console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
if (!_.isEmpty(uploading)) {
|
||||||
|
return <div>
|
||||||
|
{uploading.file.name}
|
||||||
|
|
||||||
|
<div className="progress progress-bar-default">
|
||||||
|
<div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
className="progress-bar">
|
||||||
|
<span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
<span>{progress}%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
//if (files.length /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
//let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = files?.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol?.findOne({_id: upId})?.link(); //The "view/download" link
|
||||||
|
|
||||||
|
alert(`Enllaç a l'arxiu: ${link}`);
|
||||||
|
|
||||||
|
props.setFolderTreeLink(link);
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div key={'file' + key}>
|
||||||
|
{props.nouFolderTree && <FolderTreeIndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>}
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<p>Adjunta un arxiu FolderTree*:</p>
|
||||||
|
<input type="file"
|
||||||
|
id="fileinput"
|
||||||
|
disabled={inProgress}
|
||||||
|
ref={fileinput}
|
||||||
|
onChange={uploadIt}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row m-t-sm m-b-sm">
|
||||||
|
<div className="col-md-6">
|
||||||
|
|
||||||
|
{showUploads()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
<p>* Un FolderTree és un arxiu en format JSON generat per un commandament 'treedump'** o 'treedumpl'*** </p>
|
||||||
|
<p>{`** treedump () {
|
||||||
|
tree -J -s -f \${@[$#]}
|
||||||
|
}`}</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the HOC - included in this file just for convenience, but usually kept
|
||||||
|
// in a separate file to provide separation of concerns.
|
||||||
|
//
|
||||||
|
// export default withTracker( ( props ) => {
|
||||||
|
|
||||||
|
// const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
// const files = FilesCol.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// docsReadyYet,
|
||||||
|
// files,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// })(FileUploadComponent);
|
||||||
|
|
||||||
|
export default FolderTreeFileUpload;
|
||||||
78
imports/ui/files/FolderTreeIndividualFile.jsx
Normal file
78
imports/ui/files/FolderTreeIndividualFile.jsx
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import React from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const FolderTreeIndividualFile = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile(){
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.call('RemoveFile', props.fileId, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameFile(){
|
||||||
|
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
Meteor.call('RenameFile', props.fileId, prompt, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<a href={props.fileUrl} ><img src={props.fileUrl} alt={props.fileName} style={{maxWidth: `200px`, maxHeight: `200px`}}/></a>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm"
|
||||||
|
target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export default FolderTreeIndividualFile;
|
||||||
79
imports/ui/files/IndividualFile.jsx
Normal file
79
imports/ui/files/IndividualFile.jsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const IndividualFile = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile(){
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.call('RemoveFile', props.fileId, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameFile(){
|
||||||
|
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
Meteor.call('RenameFile', props.fileId, prompt, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<img src={props.fileUrl} alt={props.fileName} style={{maxWidth: `200px`, maxHeight: `200px`}}/>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm"
|
||||||
|
target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export default IndividualFile;
|
||||||
85
imports/ui/files/IndividualFileEnt.jsx
Normal file
85
imports/ui/files/IndividualFileEnt.jsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import React from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const IndividualFileEnt = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile(){
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.call('RemoveFile', props.fileId, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameFile(){
|
||||||
|
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
Meteor.call('RenameFile', props.fileId, prompt, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<a href={props.fileUrl} target="_blank" >
|
||||||
|
<img
|
||||||
|
className='imgEnt'
|
||||||
|
src={props.fileUrl}
|
||||||
|
alt={props.fileName}
|
||||||
|
style={{maxWidth: `200px`, maxHeight: `200px`, transform: `rotate(${((Math.random() * 4) - 2)}deg`}}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* <div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm"
|
||||||
|
target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export default IndividualFileEnt;
|
||||||
81
imports/ui/files/IndividualFilePOI.jsx
Normal file
81
imports/ui/files/IndividualFilePOI.jsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const IndividualFile = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile(ev) {
|
||||||
|
// ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.callAsync('RemoveFile', props.fileId)
|
||||||
|
.catch (err => {
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renameFile() {
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
await Meteor.callAsync('RenameFile', props.fileId, prompt)
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<img src={props.fileUrl} alt={props.fileName} style={{maxWidth: `200px`, maxHeight: `200px`}}/>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm"
|
||||||
|
target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export default IndividualFile;
|
||||||
86
imports/ui/files/IndividualFileStart.jsx
Normal file
86
imports/ui/files/IndividualFileStart.jsx
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const IndividualFileStart = props => {
|
||||||
|
|
||||||
|
// propTypes: {
|
||||||
|
// fileName: PropTypes.string.isRequired,
|
||||||
|
// fileSize: PropTypes.number.isRequired,
|
||||||
|
// fileUrl: PropTypes.string,
|
||||||
|
// fileId: PropTypes.string.isRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
function removeFile() {
|
||||||
|
let conf = confirm('Are you sure you want to delete the file?') || false;
|
||||||
|
if (conf == true) {
|
||||||
|
Meteor.callAsync('RemoveFile', props.fileId, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameFile() {
|
||||||
|
|
||||||
|
let validName = /[^a-zA-Z0-9 \.:\+()\-_%!&]/gi;
|
||||||
|
let prompt = window.prompt('New file name?', props.fileName);
|
||||||
|
|
||||||
|
// Replace any non valid characters, also do this on the server
|
||||||
|
if (prompt) {
|
||||||
|
prompt = prompt.replace(validName, '-');
|
||||||
|
prompt.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_.isEmpty(prompt)) {
|
||||||
|
Meteor.callAsync('RenameFile', props.fileId, prompt, function (err, res) {
|
||||||
|
if (err)
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="m-t-sm">
|
||||||
|
<a href={props.fileUrl} target="_blank" >
|
||||||
|
<img
|
||||||
|
className='imgEnt'
|
||||||
|
src={props.fileUrl}
|
||||||
|
alt={props.fileName}
|
||||||
|
style={{maxWidth: `200px`, maxHeight: `200px`, transform: `rotate(${((Math.random() * 4) - 2)}deg`}}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* <div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<strong>{props.fileName}</strong>
|
||||||
|
<div className="m-b-sm">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<button onClick={renameFile} className="btn btn-outline btn-primary btn-sm">
|
||||||
|
Rename
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-3">
|
||||||
|
<a href={props.fileUrl} className="btn btn-outline btn-primary btn-sm" target="_blank">View</a>
|
||||||
|
</div>
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<div className="col-md-2">
|
||||||
|
<button onClick={removeFile} className="btn btn-outline btn-danger btn-sm">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-4">
|
||||||
|
Size: {props.fileSize}
|
||||||
|
</div>
|
||||||
|
{/* </div> */}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
export default IndividualFileStart;
|
||||||
26
imports/ui/files/ListPersons.jsx
Normal file
26
imports/ui/files/ListPersons.jsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
|
||||||
|
const ListPersons = () => {
|
||||||
|
|
||||||
|
return <ul class="list-group">
|
||||||
|
{
|
||||||
|
persons.map((person, i) => {
|
||||||
|
return <li class="list-group-item">
|
||||||
|
{{#if update _id}}
|
||||||
|
{{> quickForm type="update" collection="Persons" doc=this id=getFormId}}
|
||||||
|
<button data-button-update class="btn btn-danger">Cancel</button>
|
||||||
|
{{else}}
|
||||||
|
<div class="jumbotron" style='background-image: url("{{#each backgroundPic.each}}{{link}}{{/each}}");'>
|
||||||
|
<h2>{{name}}</h2>
|
||||||
|
{{#each profilePic.each}}
|
||||||
|
<img style="max-width:150px;max-height:150px" src="{{link}}"/>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
<button data-button-update class="btn btn-default">Update</button>
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
87
imports/ui/files/LlistaArxiusEnt.jsx
Normal file
87
imports/ui/files/LlistaArxiusEnt.jsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import IndividualFileEnt from '/imports/ui/files/IndividualFileEnt.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const LlistaArxiusEnt = (props) => {
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.all');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find({meta:{userId: props.uidProvisional || Meteor.userId(), entId: props.entId}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
// function showUploads() {
|
||||||
|
// //console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
// if (!_.isEmpty(uploading)) {
|
||||||
|
// return <div>
|
||||||
|
// {uploading.file.name}
|
||||||
|
|
||||||
|
// <div className="progress progress-bar-default">
|
||||||
|
// <div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
// aria-valuemin="0"
|
||||||
|
// aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
// className="progress-bar">
|
||||||
|
// <span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
// <span>{progress}%</span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
if (files /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = fileCursors.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <div
|
||||||
|
key={'file' + key}
|
||||||
|
>
|
||||||
|
<IndividualFileEnt
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div
|
||||||
|
style={{
|
||||||
|
display: `flex`,
|
||||||
|
justifyContent: `space-evenly`,
|
||||||
|
alignItems: `center`,
|
||||||
|
flexWrap: `wrap`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else return <div>Loading file list</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LlistaArxiusEnt;
|
||||||
187
imports/ui/files/LlistaArxiusFolderTM.jsx
Normal file
187
imports/ui/files/LlistaArxiusFolderTM.jsx
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
import { useTracker } from 'meteor/react-meteor-data';
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
// import PropTypes from 'prop-types';
|
||||||
|
import { FilesCol } from '/imports/api/files.js';
|
||||||
|
|
||||||
|
import FolderTreeIndividualFile from '/imports/ui/files/FolderTreeIndividualFile.jsx';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import * as d3 from 'd3';
|
||||||
|
|
||||||
|
|
||||||
|
const TreeMap = ({data, link}) => {
|
||||||
|
|
||||||
|
console.table(data);
|
||||||
|
console.log("Link: ", link);
|
||||||
|
|
||||||
|
fetch(link)
|
||||||
|
.then(x => x.text())
|
||||||
|
.then(x => {
|
||||||
|
if(x.lastIndexOf("\n")>0) {
|
||||||
|
return x.substring(0, x.lastIndexOf("\n"));
|
||||||
|
} else {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
//console.log(x);
|
||||||
|
})
|
||||||
|
// .then(x => x.json())
|
||||||
|
.then(x => JSON.parse(x))
|
||||||
|
|
||||||
|
.then(x => {
|
||||||
|
const dataset = x[0];
|
||||||
|
|
||||||
|
// Necessitem canviar el format de l'arbre i substituir "contents" per "children". De moment.
|
||||||
|
function tmFormat(arbre) {
|
||||||
|
|
||||||
|
if (arbre.hasOwnProperty("contents")) {
|
||||||
|
|
||||||
|
arbre.contents.forEach(node => {
|
||||||
|
|
||||||
|
let nodeMod;
|
||||||
|
|
||||||
|
if (node.hasOwnProperty("children")) {
|
||||||
|
nodeMod = {
|
||||||
|
...node,
|
||||||
|
children: node.contents,
|
||||||
|
value: node.size
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
nodeMod = {
|
||||||
|
...node,
|
||||||
|
value: node.size
|
||||||
|
}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmFormat(nodeMod);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const nouArbre = {
|
||||||
|
...arbre,
|
||||||
|
value: arbre.size
|
||||||
|
};
|
||||||
|
|
||||||
|
return nouArbre;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tmData = tmFormat(dataset);
|
||||||
|
|
||||||
|
const hierarchyTree = d3.hierarchy(tmData)
|
||||||
|
.sum(d => d.value) //sum every child's values
|
||||||
|
.sort((a, b) => b.value - a.value)
|
||||||
|
;
|
||||||
|
|
||||||
|
//const hierarchyTree = d3.hierarchy(tmData);
|
||||||
|
|
||||||
|
console.log("Dataset: ", dataset);
|
||||||
|
console.log("TMData: ", tmData);
|
||||||
|
console.log("Hierarchy: ", hierarchyTree);
|
||||||
|
})
|
||||||
|
// .then(x => x.json())
|
||||||
|
// .then(x => console.log(x))
|
||||||
|
//.then(x => console.table(x))
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const LlistaArxiusFolderTM = (props) => {
|
||||||
|
|
||||||
|
const files = useTracker(() => {
|
||||||
|
const filesHandle = Meteor.subscribe('files.folderTree');
|
||||||
|
// const docsReadyYet = filesHandle.ready();
|
||||||
|
const files = FilesCol?.find({'meta.type': 'folderTree'}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
|
||||||
|
|
||||||
|
return files;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// const methodCall = (methodName, ...args) =>
|
||||||
|
// new Promise((resolve, reject) => {
|
||||||
|
// Meteor.call(methodName, ...args, (error, result) => {
|
||||||
|
// if (error) reject(error);
|
||||||
|
// else resolve(result);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// ;
|
||||||
|
|
||||||
|
// const files = await methodCall('getFolderTreeFiles');
|
||||||
|
|
||||||
|
// This is our progress bar, bootstrap styled
|
||||||
|
// Remove this function if not needed
|
||||||
|
// function showUploads() {
|
||||||
|
// //console.log('**********************************', uploading);
|
||||||
|
|
||||||
|
// if (!_.isEmpty(uploading)) {
|
||||||
|
// return <div>
|
||||||
|
// {uploading.file.name}
|
||||||
|
|
||||||
|
// <div className="progress progress-bar-default">
|
||||||
|
// <div style={{width: progress + '%'}} aria-valuemax="100"
|
||||||
|
// aria-valuemin="0"
|
||||||
|
// aria-valuenow={progress || 0} role="progressbar"
|
||||||
|
// className="progress-bar">
|
||||||
|
// <span className="sr-only">{progress}% Complete (success)</span>
|
||||||
|
// <span>{progress}%</span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
{
|
||||||
|
// debug("Rendering FileUpload",docsReadyYet);
|
||||||
|
if (files /* && docsReadyYet*/) {
|
||||||
|
|
||||||
|
let fileCursors = files;
|
||||||
|
|
||||||
|
// Run through each file that the user has stored
|
||||||
|
// (make sure the subscription only sends files owned by this user)
|
||||||
|
let display = fileCursors.map((aFile, key) => {
|
||||||
|
// console.log('A file: ', aFile.link(), aFile.get('name'))
|
||||||
|
let link = FilesCol.findOne({_id: aFile._id}).link(); //The "view/download" link
|
||||||
|
|
||||||
|
// Send out components that show details of each file
|
||||||
|
return <>
|
||||||
|
<div
|
||||||
|
key={'file' + key}
|
||||||
|
>
|
||||||
|
<FolderTreeIndividualFile
|
||||||
|
fileName={aFile.name}
|
||||||
|
fileUrl={link}
|
||||||
|
fileId={aFile._id}
|
||||||
|
fileSize={aFile.size}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TreeMap data={aFile} link={link} />
|
||||||
|
</>
|
||||||
|
})
|
||||||
|
|
||||||
|
return <div
|
||||||
|
style={{
|
||||||
|
display: `flex`,
|
||||||
|
justifyContent: `space-evenly`,
|
||||||
|
alignItems: `center`,
|
||||||
|
flexWrap: `wrap`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
{display}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else return <div>Loading file list</div>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LlistaArxiusFolderTM;
|
||||||
191
server/main.js
191
server/main.js
@ -1,12 +1,13 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { PoblesCollection } from '/imports/api/pobles.js';
|
import { PoblesCollection } from '/imports/api/pobles.js';
|
||||||
import { check } from "meteor/check";
|
// import { check } from "meteor/check";
|
||||||
|
|
||||||
import { Roles } from 'meteor/roles';
|
import { Roles } from 'meteor/roles';
|
||||||
import { ROLS_GLOBALS, ROLS_DE_POBLE } from '../imports/roles';
|
import { ROLS_GLOBALS, ROLS_DE_POBLE } from '../imports/roles';
|
||||||
import { NecessitatsCollection } from '../imports/api/necessitats';
|
import { NecessitatsCollection } from '../imports/api/necessitats';
|
||||||
import { TipusCollection } from '../imports/api/tipus';
|
import { TipusCollection } from '../imports/api/tipus';
|
||||||
import { CodisCollection } from '../imports/api/codis';
|
import { CodisCollection } from '../imports/api/codis';
|
||||||
|
import { Avatars } from '../imports/api/files';
|
||||||
// import { Codis } from '../imports/ui/Codis';
|
// import { Codis } from '../imports/ui/Codis';
|
||||||
|
|
||||||
async function insertPoble({ nomPoble, cp, comarca }) {
|
async function insertPoble({ nomPoble, cp, comarca }) {
|
||||||
@ -439,11 +440,11 @@ Meteor.methods({
|
|||||||
const ara = new Date();
|
const ara = new Date();
|
||||||
let dataIni, dataFi;
|
let dataIni, dataFi;
|
||||||
|
|
||||||
console.log("codiObj.periode_validesa_ini: ", await codiObj.periode_validesa_ini);
|
console.log("codiObj.condIni: ", await codiObj.condIni);
|
||||||
|
|
||||||
if (codiObj.act_cond === "on") {
|
if (codiObj.absCond === "cond") {
|
||||||
dataIni = new Date(await codiObj.periode_validesa_ini);
|
dataIni = new Date(await codiObj.condIni);
|
||||||
dataFi = new Date(await codiObj.periode_validesa_fi);
|
dataFi = new Date(await codiObj.condFi);
|
||||||
}
|
}
|
||||||
// const dataIni = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_ini) : null;
|
// const dataIni = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_ini) : null;
|
||||||
// const dataFi = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_fi) : null;
|
// const dataFi = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_fi) : null;
|
||||||
@ -452,12 +453,12 @@ Meteor.methods({
|
|||||||
console.log("ara: ", ara);
|
console.log("ara: ", ara);
|
||||||
console.log("dataIni: ", dataIni);
|
console.log("dataIni: ", dataIni);
|
||||||
console.log("dataFi: ", dataFi);
|
console.log("dataFi: ", dataFi);
|
||||||
console.log(`codiObj.act_cond === "on"`, codiObj.act_cond === "on");
|
console.log(`codiObj.absCond`, codiObj.absCond);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(`APLICANT CODI "${codi}" sobre "${userId}".`); // Comprovant si ${Meteor.userId()} és Admin: `, esAdmin);
|
console.log(`APLICANT CODI "${codi}" sobre "${userId}".`); // Comprovant si ${Meteor.userId()} és Admin: `, esAdmin);
|
||||||
|
|
||||||
if ((codiObj.act_cond==="on" && (ara >= dataIni && ara <= dataFi)) || codiObj.act_abs) {
|
if ((codiObj.absCond==="cond" && (ara >= dataIni && ara <= dataFi)) || codiObj.actAbs ) {
|
||||||
Roles.addUsersToRolesAsync(userId, codiObj.rol, codiObj.ambit);
|
Roles.addUsersToRolesAsync(userId, codiObj.rol, codiObj.ambit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +468,182 @@ Meteor.methods({
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async 'registraUsuariAmbAvatarICodi'(uObj, codi, avatar) {
|
||||||
|
|
||||||
|
if (codi) {
|
||||||
|
|
||||||
|
console.log("+codi");
|
||||||
|
|
||||||
|
if (avatar) {
|
||||||
|
|
||||||
|
console.log("+avatar");
|
||||||
|
|
||||||
|
// Upload the avatar to GridFS
|
||||||
|
const avatarId = Avatars.insert(avatar.file, (err, fileObj) => {
|
||||||
|
if (err) {
|
||||||
|
throw new Meteor.Error('avatar-upload-failed', 'Failed to upload avatar');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const codiObj = await CodisCollection.findOneAsync({codi});
|
||||||
|
|
||||||
|
// Create the new user
|
||||||
|
const userId = Accounts.createUserAsync({
|
||||||
|
...uObj,
|
||||||
|
profile: {
|
||||||
|
avatar: avatarId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the new user's ID
|
||||||
|
// return userId;
|
||||||
|
|
||||||
|
// const userId = await Accounts.createUserAsync(uObj);
|
||||||
|
|
||||||
|
const ara = new Date();
|
||||||
|
let dataIni, dataFi;
|
||||||
|
|
||||||
|
console.log("codiObj.condIni: ", await codiObj.condIni);
|
||||||
|
|
||||||
|
if (codiObj.absCond === "cond") {
|
||||||
|
dataIni = new Date(await codiObj.condIni);
|
||||||
|
dataFi = new Date(await codiObj.condFi);
|
||||||
|
}
|
||||||
|
// const dataIni = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_ini) : null;
|
||||||
|
// const dataFi = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_fi) : null;
|
||||||
|
|
||||||
|
console.log("codiObj: ", codiObj);
|
||||||
|
console.log("ara: ", ara);
|
||||||
|
console.log("dataIni: ", dataIni);
|
||||||
|
console.log("dataFi: ", dataFi);
|
||||||
|
console.log(`codiObj.absCond`, codiObj.absCond);
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`APLICANT CODI "${codi}" sobre "${userId}".`); // Comprovant si ${Meteor.userId()} és Admin: `, esAdmin);
|
||||||
|
|
||||||
|
if ((codiObj.absCond === "cond" && (ara >= dataIni && ara <= dataFi)) || codiObj.absActiu) {
|
||||||
|
Roles.addUsersToRolesAsync(userId, codiObj.rol, codiObj.ambit);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
console.log("-avatar");
|
||||||
|
|
||||||
|
const codiObj = await CodisCollection.findOneAsync({codi});
|
||||||
|
|
||||||
|
const userId = await Accounts.createUserAsync({
|
||||||
|
...uObj,
|
||||||
|
profile: {
|
||||||
|
avatar: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const ara = new Date();
|
||||||
|
let dataIni, dataFi;
|
||||||
|
|
||||||
|
console.log("codiObj.condIni: ", await codiObj.condIni);
|
||||||
|
|
||||||
|
if (codiObj.absCond === "cond") {
|
||||||
|
dataIni = new Date(await codiObj.condIni);
|
||||||
|
dataFi = new Date(await codiObj.condFi);
|
||||||
|
}
|
||||||
|
// const dataIni = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_ini) : null;
|
||||||
|
// const dataFi = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_fi) : null;
|
||||||
|
|
||||||
|
console.log("codiObj: ", codiObj);
|
||||||
|
console.log("ara: ", ara);
|
||||||
|
console.log("dataIni: ", dataIni);
|
||||||
|
console.log("dataFi: ", dataFi);
|
||||||
|
console.log(`codiObj.absCond`, codiObj.absCond);
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`APLICANT CODI "${codi}" sobre "${userId}".`); // Comprovant si ${Meteor.userId()} és Admin: `, esAdmin);
|
||||||
|
|
||||||
|
if ((codiObj.absCond === "cond" && (ara >= dataIni && ara <= dataFi)) || codiObj.absActiu) {
|
||||||
|
Roles.addUsersToRolesAsync(userId, codiObj.rol, codiObj.ambit);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// const codiObj = await CodisCollection.findOneAsync({codi});
|
||||||
|
|
||||||
|
console.log("-codi");
|
||||||
|
|
||||||
|
const userId = await Accounts.createUserAsync(uObj);
|
||||||
|
|
||||||
|
// const ara = new Date();
|
||||||
|
// let dataIni, dataFi;
|
||||||
|
|
||||||
|
// console.log("codiObj.periode_validesa_ini: ", await codiObj.periode_validesa_ini);
|
||||||
|
|
||||||
|
// if (codiObj.act_cond === "on") {
|
||||||
|
// dataIni = new Date(await codiObj.periode_validesa_ini);
|
||||||
|
// dataFi = new Date(await codiObj.periode_validesa_fi);
|
||||||
|
// }
|
||||||
|
// const dataIni = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_ini) : null;
|
||||||
|
// const dataFi = codiObj.act_cond === "on" ? new Date(codiObj.periode_validesa_fi) : null;
|
||||||
|
|
||||||
|
// console.log("codiObj: ", codiObj);
|
||||||
|
// console.log("ara: ", ara);
|
||||||
|
// console.log("dataIni: ", dataIni);
|
||||||
|
// console.log("dataFi: ", dataFi);
|
||||||
|
// console.log(`codiObj.act_cond === "on"`, codiObj.act_cond === "on");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// console.log(`APLICANT CODI "${codi}" sobre "${userId}".`); // Comprovant si ${Meteor.userId()} és Admin: `, esAdmin);
|
||||||
|
|
||||||
|
// if ((codiObj.act_cond==="on" && (ara >= dataIni && ara <= dataFi)) || codiObj.act_abs) {
|
||||||
|
Roles.addUsersToRolesAsync(userId, 'usuari', 'GENERAL');
|
||||||
|
// }
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Check if the username and email are valid
|
||||||
|
// if (!username || !email || !password) {
|
||||||
|
// throw new Meteor.Error('invalid-input', 'Please fill in all fields');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Check if the avatar is a valid file
|
||||||
|
// if (!avatar || !avatar.file) {
|
||||||
|
// throw new Meteor.Error('invalid-avatar', 'Please select a valid avatar image');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Upload the avatar to GridFS
|
||||||
|
// const avatarId = Avatars.insert(avatar.file, (err, fileObj) => {
|
||||||
|
// if (err) {
|
||||||
|
// throw new Meteor.Error('avatar-upload-failed', 'Failed to upload avatar');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
console.log("-avatar-codi");
|
||||||
|
|
||||||
|
// Create the new user
|
||||||
|
const userId = Accounts.createUserAsync({
|
||||||
|
...uObj,
|
||||||
|
profile: {
|
||||||
|
avatar: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the new user's ID
|
||||||
|
return userId;
|
||||||
|
},
|
||||||
|
|
||||||
'usaCodiAmbUsuari': async function (userId, codi) {
|
'usaCodiAmbUsuari': async function (userId, codi) {
|
||||||
// const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin");
|
// const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin");
|
||||||
const codiObj = await CodisCollection.find({codi}).fetchAsync();
|
const codiObj = await CodisCollection.find({codi}).fetchAsync();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user