🏖🔭 Telescope Nova package extending nova:forms to upload images to Cloudinary from a drop zone.
Want to add this to your Nova instance? Read below:
I would recommend that you clone this repo in your Nova's /packages folder.
In .meteor/packages file, add at the end of the Optional packages section:
xavcz:nova-forms-upload
Note: You can also add it via the classic meteor add xavcz:nova-forms-upload, however you may encounter load order issue.
This package depends on the awesome react-dropzone (repo), you need to install the dependency:
npm install react-dropzone
Create a Cloudinary account if you don't have one.
The upload to Cloudinary relies on unsigned upload:
Unsigned upload is an option for performing upload directly from a browser or mobile application with no authentication signature, and without going through your servers at all. However, for security reasons, not all upload parameters can be specified directly when performing unsigned upload calls.
Unsigned upload options are controlled by an upload preset, so in order to use this feature you first need to enable unsigned uploading for your Cloudinary account from the Upload Settings page.
When creating your preset, you can define image transformations. I recommend to set something like 200px width & height, fill mode and auto quality. Once created, you will get a preset id.
It may look like this:
Edit your settings.json and add inside the public: { ... } block the following entries with your own credentials:
public: {
"cloudinaryCloudName": "YOUR_APP_NAME",
"cloudinaryPresets": {
"avatar": "YOUR_PRESET_ID",
"posts": "ANOTHER_PRESET_ID" // or maybe the same
}
}Picture upload in Nova is now enabled! Easy-peasy, right? 👯
You can now use the Upload component as a classic form extension with custom fields like nova:forms-tags or nova:embedly.
Let's say you want to enhance your posts with a custom image. In your custom package, your new custom field could look like this:
// ... your imports
import Telescope from 'meteor/nova:lib';
import Users from 'meteor/nova:users';
import Upload from 'meteor/xavcz:nova-forms-upload'
// ... your permissions
const canInsert = user => Users.canDo(user, "posts.new");
const canEdit = Users.canEdit;
// extends Posts schema with a new field: 'image' 🏖
Posts.addField({
fieldName: 'image',
fieldSchema: {
type: String,
optional: true,
publish: true,
control: Upload,
insertableIf: canInsert,
editableIf: canEdit,
form: {
options: {
preset: Telescope.settings.get('cloudinaryPresets').posts // this setting refers to the transformation you want to apply to the image
},
}
}
});
PublicationUtils.addToFields(Posts.publishedFields.list, ["image"]);Let's say you want to enable your users to upload their own avatar. In your custom package, your new custom field could look like this:
// ... your imports
import Telescope from 'meteor/nova:lib';
import Users from 'meteor/nova:users';
import Upload from 'meteor/xavcz:nova-forms-upload'
// ... your permissions
const canInsert = user => Users.canDo(user, "users.new");
const canEdit = Users.canEdit;
// extends Users schema with a new field: 'telescope.avatar' 👁
Users.addField({
fieldName: 'telescope.avatar',
fieldSchema: {
type: String,
optional: true,
publish: true,
control: Upload,
insertableIf: canInsert,
editableIf: canEdit,
form: {
options: {
preset: Telescope.settings.get('cloudinaryPresets').avatar // this setting refers to the transformation you want to apply to the image
},
}
}
});
// publish this new field
PublicationUtils.addToFields(Users.publishedFields.list, ['telescope.avatar']);Adding the opportunity to upload an avatar comes with a trade-off: you also need to extend the behavior of the Users.avatar methods. You can do this by using this snippet:
const originalAvatarConstructor = Users.avatar;
// extends the Users.avatar function
Users.avatar = {
...originalAvatarConstructor,
getUrl(user) {
url = originalAvatarConstructor.getUrl(user);
return !!user && user.telescope && user.telescope.avatar ? user.telescope.avatar : url;
}
} Feel free to contribute to add new features and flexibility to this package :)
You are welcome to come chat about it on the Telescope Slack chatroom
This package and nova:cloudinary share a settings in common: cloudinaryCloudName. They are fully compatible.
Happy hacking! 🚀