How to retrieve Image in Jade from Meteor FS Collection - javascript

I am working on a existing Meteor project. I have a Schema as shown below,
Activities.schema = new SimpleSchema({
title: {
type: String,
label: 'Title',
index: 1,
},
export const ActivitiesImages = new FS.Collection('activitiesImages', {
stores: [
new FS.Store.GridFS('homeActivitiesImages', { transformWrite: homeActivityImage }),
new FS.Store.GridFS('origActivitiesImages', {}),
],
filter: {
maxSize: 1024 * 1024 * 5,
allow: {
contentTypes: ['image/*'],
},
},
});
.........
)}
And I found Insert code as below
const insertObj = {
title,
description,
type: [type],
divisions: [],
clubType,
createdBy,
privateType,
};
if (image) {
insertObj.image = ActivitiesImages.insert(image);
}
Meteor.call('v1/insertActivity', insertObj, (error) => {
if (error) {
sAlert.error(error.message);
} else {
sAlert.success('Activity added');
$('.activity-modal').modal('hide');
}
});
Now My requirement is, I wanted to display the above stored image in the below Jade Template. I am finding difficulties in rendering the same.
MyProfile.tpl.jade (Jade Template)
each activity in fiveStarActivities
.slider__item
.ui.segment
.ui.vertical.segment
h3.ui.header.center.aligned {{activity.title}}
.ui.list
.item
img(
src="{{HERE I WANT TO DISPLAY IMAGE}}"
alt="image description"
).ui.fluid.rounded.image
.item
.ui.vertical.segment.big-card__btn-src
button.ui.mini.grey.basic.button {{activity.title}}
.item
p {{activity.description}}
I have tried the below but did not work.
MyProfile.js
activityImage(activity) {
return ActivitiesImages.findOne({ _id: activity.image._id });
},
Can someone assist me on how to display the image on Jade Template ?

I have resolved this by changing template as shown below.
MyProfile.tpl.jade
each activity in fiveStarActivities
.slider__item
.ui.segment
.ui.vertical.segment
h3.ui.header.center.aligned {{activity.title}}
.ui.list
if activityImage activity
with activityImage activity
.item
img(
src="{{this.url store='homeActivitiesImages'}}"
alt="image description"
).ui.fluid.rounded.image.medium
MyProfile.js
ActivitiesImages.findOne({ _id: activity.image._id });

Related

Grapes Js: The css classes are removed and the autogenerated ids for each html tags gets changed ( Example : ivj5m-2) after each reload

How to reproduce the bug?
Install the grapes js in react app
Go to the editor and drag a component. ( Example : text component)
Style the component using the style manager
save it into DB and see the code in the editor
Reload the page
see the code in the editor
What is the expected behavior?
The html tag ids and css for that ids should not be changes or erased even though if reload the editor
What is the current behavior?
If we are reloading the editor after any changes , the ids in the html code change and the css for that ids getting erased off
If is necessary to execute some code in order to reproduce the bug, paste it here below:
const editor = grapesjs.init({
container: "#block",
canvas: {
styles: [
"https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css",
],
scripts: [
"https://cdn.jsdelivr.net/npm/#popperjs/core#2.9.2/dist/umd/popper.min.js",
"https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.min.js",
],
},
protectedCss: "",
commands: {
defaults: [
{
id: "my-command-id",
run() {
alert("This is my command");
},
},
],
},
plugins: ["gjs-preset-webpage"],
storageManager: {
id: "gjs_",
type: "remote",
autosave: true,
autoload: true,
urlStore: this.API_URL + "update_builder/" + this.state.id,
urlLoad: this.API_URL + this.state.id,
//method: 'patch',
params: {
draft: "1",
},
headers: {},
},
assetManager: {
storageType: "",
storeOnChange: true,
storeAfterUpload: true,
upload: "https://localhost/assets/images", //for temporary storage
assets: [],
uploadName: "file",
uploadFile: function (e) {
var files = e.dataTransfer
? e.dataTransfer.files
: e.target.files;
var formData = new FormData();
for (var i in files) {
formData.append("upload", files[i]); //containing all the selected images from local
}
PageService.contentUpload(formData)
.then((response) => {
console.log(response.data.path);
editor.AssetManager.add(response.data.path);
})
.catch((error) => {
// this.alert.show(error.response.data.message,{type:'error'});
});
},
},
pageManager: {
pages: this.pagesList,
},
layerManager: {
appendTo: ".layers-container",
},
styleManager: {
appendTo: '.style-container'
},
});
const pageManager = editor.Pages;
const pagesList = pageManager.getAll();
this.pages = pagesList;
this.editorData = editor;
editor.store((res) => (this.callBackAlert = true));
editor.on("storage:start:store", (objectToStore) => {
console.log(objectToStore);
});
Banner(editor);
// Resizing the components
editor.on("component:selected", function (args) {
args.set("resizable", true);
});

Loading a custom skin onpage/window load by default [duplicate]

What i want to load a custom .wsz skin on page-load on my website.
I still don't understand how to do it to make it work.
Here a snippet with my code:
https://codepen.io/cat999/pen/rNOOjJP
js
const webamp = new Webamp({
initialTracks: [{
metaData: {
artist: "DJ Mike Llama",
title: "Llama Whippin' Intro",
},
url: "https://cdn.rawgit.com/captbaritone/webamp/43434d82/mp3/llama-2.91.mp3",
duration: 5.322286,
}],
})
webamp.onMinimize(() => {
const webampEl = document.getElementById('webamp')
webampEl.style.display = 'none'
})
webamp.renderWhenReady(document.getElementById('app')).then(() => {
document.getElementById('close').addEventListener('click', (e) => {
e.stopPropagation()
const webampEl = document.getElementById('webamp')
webampEl.style.display = 'none'
})
document.getElementById('open').addEventListener('click', () => {
const webampEl = document.getElementById('webamp')
webampEl.style.display = 'block'
})
})
Here below the skins I would like to see on my page-load
https://srv-file6.gofile.io/download/KwUySB/Aphex_Twin_-_Windowlicker.wsz
Anyone could help on How I should improve my js code to make It work?
Have you seen the Initialization portion of the docs?
https://github.com/captbaritone/webamp/blob/master/docs/usage.md#initialize-the-javascript
Try constructing Webamp by adding an initialSkin option:
const webamp = new Webamp({
initialTracks: [{
metaData: {
artist: "DJ Mike Llama",
title: "Llama Whippin' Intro",
},
url: "https://cdn.rawgit.com/captbaritone/webamp/43434d82/mp3/llama-2.91.mp3",
duration: 5.322286,
}],
initialSkin: {
url: "https://s3.amazonaws.com/webamp-uploaded-skins/skins/dbaead7a819b238d48ca726abd0617bb.wsz"
},
})

editorjs image plugin return image url is not picked up

I configured editorjs into my application. I installed image plugin on it so that I can upload an image to the server. Now my server uploads the image and returns JSON with specified format i.e.,
{
"success": 1,
"file": {
"url": "https://www.tesla.com/tesla_theme/assets/img/_vehicle_redesign/roadster_and_semi/roadster/hero.jpg",
// ... and any additional fields you want to store, such as width, height, color, extension, etc
}
}
The response has file->url but still error uploading message
Here is my config code:
const editor = new EditorJS({
/**
* Id of Element that should contain Editor instance
*/
holder: 'heditor',
/**
* Available Tools list.
* Pass Tool's class or Settings object for each Tool you want to use
*/
tools: {
header: {
class: Header,
inlineToolbar: ['link'],
config: {
placeholder: 'Title...'
}
},
paragraph: {
class: Paragraph,
inlineToolbar: true,
},
image: {
class: ImageTool,
config: {
endpoints: {
accept: 'image/*',
byFile: $('#heditor').data('url'), // Your backend file uploader endpoint
byUrl: $('#heditor').data('url'), // Your endpoint that provides uploading by Url
},
additionalRequestHeaders: {
'x-auth-token': $('#heditor').data('token'),
}
}
},
linkTool: {
class: LinkTool,
config: {
endpoint: 'http://localhost:8008/fetchUrl', // Your backend endpoint for url data fetching
}
},
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+M',
},
Marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M',
},
embed: Embed,
list: {
class: List,
inlineToolbar: true
}
},
/**
* This Tool will be used as default
*/
// initialBlock: 'paragraph',
/**
* Initial Editor data
*/
data: {
blocks: [
{
type: "header",
data: {
text: "Title of your story",
level: 2
}
},
{
type: 'paragraph',
data: {
text: 'Hey. Meet the new Story Editor. On this page you can start writing your story — try to edit this text...'
}
}
]
},
onReady: function () {
saveButton.click();
},
onChange: function () {
console.log('something changed');
}
});
/**
* Saving example
*/
saveButton.addEventListener('click', function () {
editor.save().then((savedData) => {
$("#output").html(savedData);
});
});
What I am doing wrong can anyone help?

How to reference another collection on insert?

I'm trying to figure how to take an Image (a file using CollectionFS) and insert the Image's Id into my Items imageId field:
lib/collections/items.js
Items = new Mongo.Collection("items");
Items.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Name",
},
userId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoform: {
type: "hidden",
label: false
},
autoValue: function () { return Meteor.userId() },
},
image: {
type: String,
optional: true,
autoform: {
label: false,
afFieldInput: {
type: "fileUpload",
collection: "Images",
label: 'Select Photo',
}
}
},
imageId: {
type: String
}
}));
lib/collections/images.js
if (Meteor.isServer) {
var imageStore = new FS.Store.S3("images", {
accessKeyId: Meteor.settings.AWSAccessKeyId,
secretAccessKey: Meteor.settings.AWSSecretAccessKey,
bucket: Meteor.settings.AWSBucket,
});
Images = new FS.Collection("Images", {
stores: [imageStore],
filter: {
allow: {
contentTypes: ['image/*']
}
}
});
}
// On the client just create a generic FS Store as don't have
// access (or want access) to S3 settings on client
if (Meteor.isClient) {
var imageStore = new FS.Store.S3("images");
Images = new FS.Collection("Images", {
stores: [imageStore],
filter: {
allow: {
contentTypes: ['image/*']
},
}
});
}
Right now my allow rules are:
server/allows.js
Items.allow({
insert: function(userId, doc){return doc && doc.userId === userId;},
update: function(userId, doc){ return doc && doc.userId === userId;},
remove: function(userId, doc) { return doc && doc.userId === userId;},
})
Images.allow({
insert: function(userId, doc) { return true; },
update: function(userId,doc) { return true; },
remove: function(userId,doc) { return true; },
download: function(userId, doc) {return true;},
});
I'm using Autoform so my form looks like this:
client/item_form.html
<template name="insertItemForm">
{{#autoForm collection="Items" id="insertItemForm" type="insert"}}
{{> afQuickField name="name" autocomplete="off"}}
{{> afQuickField name="image" id="imageFile"}}
<button type="submit">Continue</button>
{{/autoForm}}
</template>
Right now when I select browse and select an image it will be in the database and I want to take that _id it has and place it in the Item that is created afterwards, but how do I fetch that particular image? I figured this is a good way to reference an image.
UPDATE 1
Find out the ID is actually located hidden after a file is selected:
<input type="hidden" class="js-value" data-schema-key="image" value="ma633fFpKHYewCRm8">
So I'm trying to get ma633fFpKHYewCRm8 to be placed as a String in the ImageId.
UPDATE 2
Maybe one way is to use FS.File Reference?
I have solved the same problem rather simpler, after file is inserted, I just call a method that does the related collection update:
client.html
<template name="hello">
<p>upload file for first texture: <input id="myFileInput1" type="file"> </p>
</template>
lib.js
var textureStore = new FS.Store.GridFS("textures");
TextureFiles = new FS.Collection("textures", {
stores: [textureStore]
});
Textures = new Mongo.Collection("textures");
client.js
Template.hello.events({
'change #myFileInput1': function(event, template) {
uploadTextureToDb('first',event);
}
});
function uploadTextureToDb(name, event) {
FS.Utility.eachFile(event, function(file) {
TextureFiles.insert(file, function (err, fileObj) {
// Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
console.log('inserted');
console.log(fileObj);
//after file itself is inserted, we also update Texture object with reference to this file
Meteor.call('updateTexture',name,fileObj._id);
});
});
}
server.js
Meteor.methods({
updateTexture: function(textureName, fileId) {
Textures.upsert(
{
name:textureName
},
{
$set: {
file: fileId,
updatedAt: Date.now()
}
});
}
});
as you are using autoForm and simpleSchema, it might not be so easy, but I suggest to you to forget about autoForm and simpleSchema at first and try to make it work with simple html and default collections.
After everything works, you can go back to setting up those, but beware that there might be more issues when it comes to CollectionFS, especially when it comes to styling generated by autoForm.

Accessing parent functions in QML

I'm currently creating a Twitter client as a way of learning to develop for Blackberry 10. I'm currently trying to create a context menu for a custom ListView item, which on selection will show a dialog in the main layout. However, I cannot get the selected list item to call any functions from the parent Page.
Here is the QML from my custom list item:
import bb.cascades 1.0
Container {
property alias avatar: tracker.imageSource
property alias username: txtTweetUser.text
property alias tweetText: txtTweetContent.text
property alias tweetTime: txtTweetTime.text
signal sendReply(string username)
function cout(text) {
console.debug("[DEBUG] " + text);
}
id: itemTweet
preferredWidth: 768;
preferredHeight: 200
// Actions
contextActions: [
ActionSet {
title: "Action Set"
subtitle: "This is an action set."
actions: [
ActionItem {
title: "Reply"
imageSource: "asset:///reply.png"
onTriggered: {
itemTweet.sendReply(txtTweetUser.text);
}
},
ActionItem {
title: "Retweet"
imageSource: "asset:///retweet.png"
},
ActionItem {
title: "Favourite"
imageSource: "asset:///fav.png"
}
]
} // end of ActionSet
] // end of contextActions list
<Layout for the List Item>...
}
}
And for the main QML file:
import bb.cascades 1.0
TabbedPane {
id: tabbedPane
showTabsOnActionBar: true
Tab {
id: tabTimeline
title: "Timeline"
imageSource: "asset:///twitter-white.png"
Page {
id: pageTimeline
signal openReply
signal showNewTweet
function cout(text) {
console.debug("[DEBUG] " + text);
}
function showTweetWindow(username) {
pageTimeline.dialogNewTweet.text = username;
pageTimeline.dialogNewTweet.visible = true;
}
// Title bar
titleBar: TitleBar {
visibility: Overlay
title: "Twitter"
acceptAction: ActionItem {
id: btnNewTweet
title: "+"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
pageTimeline.cout("action selected");
dialogNewTweet.visible = true;
}
}
}
// Main content
content: Container {
layout: AbsoluteLayout {}
Container {
// Listview for the tweets
ListView {
id: lstTweets
objectName: "lstTweets"
// Components to display the rows
listItemComponents: [
ListItemComponent {
id: listItem
type: "listItem"
TweetItem {
tweetText: ListItemData.content
tweetTime: ListItemData.time
avatar: ListItemData.avatar
username: ListItemData.username
onSendReply: {
cout("Reply selected in parent to " + username);
pageTimeline.showTweetWindow(username);
}
}
}
]
onSelectionChanged: {
}
function itemType(data, indexPath) {
if (indexPath.length == 1) {
return "header";
} else {
return "listItem";
}
}
}
}
DialogNewTweet {
id: dialogNewTweet
visible: false
onShowNewTweet: {
dialogNewTweet.visible = true;
}
}
}
// End container
}
}
... <Other tabs> ...
}
So when the main QML file receives the SendReply signal, it's suppposed to call showTweetWindow(username) which then makes dialogNewTweet visible, but instead I get the error ReferenceError: Can't find variable: pageTimeline. It's definitely a scope issue, but I can't figure out what I'm doing wrong, or if I need to restructure this.
Answer here:
https://community.blackberry.com/message/182467#182467
What I need to achieve is to operate on a list of data, e.g. delete an item using ContextAction in ListItem in QML, then call a C++ method of an object in QmlDocument's contextProperty. here is how I did it:
C++ code:
QmlDocument *qml = QmlDocument::create("accounts.qml");
root = qml->createRootNode<AbstractPane>();
//Here set the context property, accountsManager was already created
qml->setContextProperty("accountsManager", accountsManager);
//Set the model for the list view
ListView* accountsListView = root->findChild<ListView*>("accountsListView");
accountsListView->setDataModel(accountsManager->getDataModel());
QML code:
Page {
content: Container {
ListView {
id: listView
objectName: "accountsListView"
listItemComponents: [
ListItemComponent {
type: "listItem"
StandardListItem{
id: accountItem
title: ListItemData.username
contextActions: [
ActionSet {
deleteAction: DeleteActionItem {
title: "Delete"
onTriggered: {
//it does not work here, "ReferenceError: Can't find variable: accountsManager"
accountsManager.doSometing();
}
}
}
]
}
}
]
function itemType(data, indexPath) {
return "listItem";
}
} // end of ListView
} // end of Container
actions: [
ActionItem {
title: "Add account"
ActionBar.placement: ActionBarPlacement.OnBar
onTriggered: {
//It works fine here
accountsManager.doSomething();
}
}
]
} // end of Page
And another method:
https://community.blackberry.com/message/453794#453794
At the top Page level add the following line to make the label accessible.
Page {
id: topPage
onCreationCompleted: { Qt.topLabel = topLabel; }
Then in the button definition you can reference the Qt.topLabel from within the list.
listItemComponents: [
ListItemComponent {
type: "item"
Button {
text: "Change To Three"
onClicked: {
Qt.topLabel.text = "Three";
}
}
}
]

Categories