Abans de la col·lecció AvatarsRegistre

This commit is contained in:
Pasq G 2025-02-18 19:00:27 +01:00
parent 1cefb0b28e
commit 56a0b76c6d
32 changed files with 3709 additions and 16 deletions

View File

@ -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

View File

@ -1 +1 @@
METEOR@3.1.1 METEOR@3.1.2

View File

@ -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

275
imports/api/files.js Normal file
View File

@ -0,0 +1,275 @@
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('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 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, Avatars };

View 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);
}

View 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
View 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 };

View 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 };

View File

@ -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`
}} }}

View File

@ -1,14 +1,46 @@
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 { Roles } from 'meteor/roles'; import { Roles } from 'meteor/roles';
import { ROLS_GLOBALS } from '../roles'; import { ROLS_GLOBALS } from '../roles';
import { Avatars } 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('avatars.all');
// files = useFind(Avatars, [
// {},
// { sort: { createdAt: -1 } },
// ]);
// }, []);
// const files = useTracker("avatars", () => {
// return Avatars.find({}).fetchAsync();
// });
const handleLogin = (e) => { const handleLogin = (e) => {
e.preventDefault(); e.preventDefault();
// console.dir(e); // console.dir(e);
@ -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 />

View 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 { Avatars } 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('avatars.all');
const files = useFind(Avatars, [
{},
{ sort: { createdAt: -1 } },
]);
// const files = useTracker("avatars", async () => {
// // const docsReadyYet = filesHandle.ready();
// const files = await Avatars?.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 = Avatars.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 Avatars.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 = Avatars.find({meta:{userId: props.uidProvisional || Meteor.userId()}}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop"
// return {
// docsReadyYet,
// files,
// };
// })(FileUploadComponent);
export default AvatarFileUpload;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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);

View 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 };

View 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 };

View File

@ -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 };

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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>
}

View 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;

View 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;

View File

@ -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();