Programmatically upload file on Sharepoint using ReactJs - javascript

I am new to use ReactJS, I need community help to solve my problem statement.
Problem statement :- I want to upload image file in Sharepoint using ReactJS and as response I want back image's Sharepoint URL, so that I can save in data base to display those images in my application pages.
I am developing a web app and this app is running under teams as tab.
Here is one reference link I have tried but I am unable implement successfully.
http://siddharthvaghasia.com/2019/10/16/upload-file-to-sharepoint-library-using-file-control-and-pnp-js-in-spfx-webpart/
After implementing this I am getting following error:-
TypeError: Cannot read property 'getFolderByServerRelativeUrl' of undefined
Settings.uploadFileFromControl
src/components/Settings.jsx:656
653 | //var files = this._input.files;
654 | //var file = files[0];
655 | //Upload a file to the SharePoint Library`enter code here`
> 656 | sp.web.getFolderByServerRelativeUrl(this.props.context.pageContext.web.serverRelativeUrl)
| ^ 657 | //sp.web.getFolderByServerRelativeUrl(this.props.context.pageContext.web.serverRelativeUrl + "/MyDocs")
658 | .files.add(file.name, file, true)
659 | .then((data) =>{
View compiled
FileReader.reader.onloadend
src/components/Settings.jsx:603
600 |
601 | //console.log('fileVar[i].name ' + reader.fileName);
602 |
> 603 | this.uploadFileFromControl(fileVar[i]);
| ^ 604 |
605 | logoImages.push({image: reader.result, name: reader.fileName});
606 | this.setState({eventLogoImageUrl: JSON.stringify(logoImages)});
I am not getting this weather this sp.web will work under teams app or not?
Please help
Thanks in advance.

Basically you are getting error because your getFolderByServerRelativeUrl is not getting any value or undefined
You need to use the function like this and call this function on the button click
private uploadFileFromControl() {
//Get the file from File DOM
var files = this._input.files;
var file = files[0];
//Upload a file to the SharePoint Library
var url = this.props.context.pageContext.web.serverRelativeUrl;
pnp.sp.web.getFolderByServerRelativeUrl( url+ "/FormServerTemplates")
.files.add(file.name, file, true)
.then((data) => {
alert("File uploaded sucessfully");
})
.catch((error) => {
alert("Error is uploading");
});
}
In the render use this code of html rendering
return (
<div className={ styles.maincontainer }>
<input type="file" ref={(elm) => { this._input = elm; }}></input>
<p>
<button onClick={() => this.uploadFileFromControl()} >
Upload
</button>
</p>
</div>
);
Run this command
npm install sp-pnp-js --save
Import sp-pnp-js
import * as pnp from 'sp-pnp-js';

The reason for this problem should be that pnp js is not imported correctly.
npm install sp-pnp-js --save
Run this command in your command bar.
Official example:
https://pnp.github.io/pnpjs/sp/files/#adding-files
If you need further help,please share the full code in tsx file.

Related

I keep getting a Step definiton error using Cypress/Cucumber

I am getting a "Step implementation missing for: I open ecommerce page" when I try to run my Cypress/Cucumber test.feature file.
I was referring to another post to help me but didn't manage to help clear up my own issue. The link for the post I used is below
Cypress.io and Cucumber.io testing integration, Step implementation missing for:
So here is what everything I have for this.
As a start here is my current file structure that I have adjusted
-cypress
-integration
-test
-test.feature
-test.js
Here is my test.feature file
Feature: End to end GFM validation
Scenario: Ecommerce products delivery
Given I open ecommerce page
When I add items to cart
And Validate the total prices
Then select the country submit and verify thank you
Here is the test.js file with the step definitions
/// <reference types="Cypress" />
import { Given,When,Then,And } from 'cypress-cucumber-preprocessor/steps'
import HomePage from "../../support/classes/HomePage"
import ProductPage from "../../support/classes/ProductPage"
import CheckOutPg from "../../support/classes/CheckOutPg"
const homePage = new HomePage()
const productPage = new ProductPage()
const checkOut = new CheckOutPg()
Given("I open ecommerce page",()=>{
cy.visit(Cypress.env('url')+"/angularpractice/")
})
//When using hook to load data, use non-es6 syntax for a function.....might need to check if this was updated in later releases
When('I add items to cart',function(){
homePage.getShopTab().click()
testData.productName.forEach((product)=>{
cy.selectProduct(product)
})
productPage.getCheckoutBtn().click()
})
And('Validate the total prices',()=>{
let sum = 0
let total;
checkOut.getItemPrices().each(($el,index,$list)=>{
let price = $el.text().split(' ')[1].trim()
sum = Number(sum) + Number(price);
}).then(()=>{
cy.log(sum)
})
checkOut.getTotal().then((el)=> {
total = el.text().split(' ')[1].trim()
expect(Number(total)).to.eq(sum)
})
})
Then('select the country submit and verify thank you',()=>{
cy.get(':nth-child(6) > :nth-child(5) > .btn').click()
cy.get('#country').type('United States')
cy.wait(6000)
cy.get('.suggestions > ul > li > a').click()
cy.get('input[type="checkbox"]').check({force:true})
cy.get('.ng-untouched > .btn').click()
cy.get('.alert').then((el)=>{
const text = el.text()
expect(text.includes('Success')).to.be.true
})
})
I added the stepDefinitions in my package.json, and set the nonGlobalStepDifitions attribute to true as per cucumber docs when the the path for stepDefinition is set to "cypress/integration".
"cypress-cucumber-preprocessor": {
"stepDefinitions": "cypress/integration",
"nonGlobalStepDefinitions": true,
"cucumberJson": {
"generate": true,
"outputFolder": "cypress/cucumber-json",
"filePrefix": "",
"fileSuffix": ".cucumber"
}
}
I am not sure if I presented the context well on this, so I am open to any suggestion. Other than that is anyone able to assist me to see where this might have gone wrong?
Cypress-cucumber-preprocessor recommends this folder structure when you set "nonGlobalStepDefinitions": true and "stepDefinitions": "cypress/integration" in package.json.
See doc here.
- cypress/
- integration/
- feature1.feature
- feature1/
- feature1.js
- feature2.feature
- feature2/
- feature2.js
So:
Create your .feature file in cypress/integration
Create a folder with the same name as your .feature file, also in cypress/integration
Create a .js file in the newly created folder with your step definitions

Update Salesforce Object from Marketing Cloud Automation Studio Using Script

I would like to update a record in the Sales Cloud object using Script in Automation Studio in Marketing Cloud.
I found the code: https://gist.github.com/katydorjee/818912244f95c49c0bf52c175d00cfe8. I've tried to apply it to my case, but it errors "ERROR: A runtime error occurred while the SSJS Activity executed the SSJS script. Please review the SSJS activity to ensure that errors are handled properly."
<script runat="server">
Platform.Load("core","1.1.1");
var sfUpdateString;
var targetDE = DataExtension.Init('xxx').Rows.Retrieve();
for (var i = 0; i < targetDE.length; i++)
{
var Field1 = targetDE[i].AccountID;
var Field2 = targetDE[i].Gender;
sfUpdateString = '';
sfUpdateString = '%'+'%[SET #uso = UpdateSingleSalesforceObject("Account","'+Field1+'"';
sfUpdateString += ',"Gender__c","'+Field2+'")]%'+'%';
Platform.Function.TreatAsContent(sfUpdateString);
Write(Platform.Variable.GetValue("#uso"));
}
</script>
Data Extension:
|AccountID | Gender |
| ------------------ | -------------- |
| 0015g00000FwcXXXXX | Female |
Account (Salesforce Object):
Id = 0015g00000FwcXXXXX
Name = Mr. A
Gender__c(picklist field) = ' ' (I would like to update this field to be "Female")
I change "Platform.Load("core","1.1.1");" to "Platform.Load("core","1");" and it works well now.

HUGO: was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff)

I'm currently trying to deploy a HUGO site to Netlify but I have been unable to. I get the following error:
The resource from
“https://cdn.jsdelivr.net/gh/theasteve/blog/master#0.0.1/public/assets/main.js”
was blocked due to MIME type (“text/plain”) mismatch
(X-Content-Type-Options: nosniff).
Not sure why Netlify is returning HTML instead of the JavaScript file. Both files are there when I check prism.js file and the main.js file.
The error is shown coming from the About page, even after removing the script tags I still get a page without any styles being added.
<footer class="footer">
<div class="footer__inner">
{{ if $.Site.Copyright }}
<div class="copyright copyright--user">{{ $.Site.Copyright | safeHTML }}</div>
{{else}}
{{ partial "logo.html" . }}
<div class="copyright">
<span>© {{ now.Year }} Powered by Hugo</span>
<span>Theme created by panr</span>
</div>
{{end}}
</div>
</footer>
<script src="https://cdn.rawgit.com/theasteve/blog/master/public/assets/main.js"></script>
<script src="https://cdn.rawgit.com/theasteve/blog/master/public/assets/prism.js"></script>
<!-- <script src="{{ "assets/prism.js" | absURL }}"></script> -->
Here is my config.toml
# baseurl = "https://theasteve.github.io/"
languageCode = "en-us"
theme = "hello-friend"
paginate = 5
[params]
# dir name of your blog content (default is `content/posts`)
contentTypeName = "posts"
# "light" or "dark"
defaultTheme = "light"
# if you set this to 0, only submenu trigger will be visible
showMenuItems = 2
# Show reading time in minutes for posts
showReadingTime = false
[languages]
[languages.en]
title = "theAsteve"
subtitle = "Lets get it"
keywords = ""
copyright = ""
menuMore = "Show more"
writtenBy = "Written by"
readMore = "Read more"
readOtherPosts = "Read other posts"
newerPosts = "Newer posts"
olderPosts = "Older posts"
minuteReadingTime = "min read"
dateFormatSingle = "2006-01-02"
dateFormatList = "2006-01-02"
[languages.en.params.logo]
logoText = "theAsteve"
logoHomeLink = "/"
# or
# path = "/img/your-example-logo.svg"
alt = "theAsteve"
[languages.en.menu]
[[languages.en.menu.main]]
identifier = "about"
name = "About"
url = "/about"
I commented out the baseurl because nothing was being shown when deploying to Netlify. Here, is my Netlify.toml
[build]
publish = "public"
command = "hugo --gc --minify"
[context.production.environment]
HUGO_VERSION = "0.69.2"
HUGO_ENV = "production"
HUGO_ENABLEGITINFO = "true"
[context.split1]
command = "hugo --gc --minify --enableGitInfo"
[context.split1.environment]
HUGO_VERSION = "0.69.2"
HUGO_ENV = "production"
[context.deploy-preview]
command = "hugo --gc --minify --buildFuture -b $DEPLOY_PRIME_URL"
[context.deploy-preview.environment]
HUGO_VERSION = "0.69.2"
[context.branch-deploy]
command = "hugo --gc --minify -b $DEPLOY_PRIME_URL"
[context.branch-deploy.environment]
HUGO_VERSION = "0.69.2"
[context.next.environment]
HUGO_ENABLEGITINFO = "true"
Why is HTML being returned ? Why are the assets not compiling?
Found a solution. It is because hugo trys to load the css/js files from another URL i.e. if you are on mydomain.com/en/ hugo trys to import mydomain.com/css/mycss.css but it has to be mydomain.com/en/css/mycss.css
So to perfom this you need to replace the static import in your baseof.html with:
<link rel="stylesheet" href='{{ "css/materialize.css" | absLangURL }}'>
You have to do that with all your href and src keywords.
Hope I could help :D
I experienced this issue deploying to gitlab from local windows machine.
I resolved this issue using recommended solution from Mad Mike: Commenting out the BaseURL line in config.toml and using relativeURLS in the config. See config.toml snippet below...
#baseURL = "/"
relativeURLs = true

Trigger .py file when JS page is opened on nodjs server browser

I have a nodjs server set up with several JS pages. On one of them, I want a local .py file to be opened and run one time in the background. I DON'T need to generate a response from it.
I have flask set up already, but I don't understand how to incorporate that with my current React Javascript page (the one I want my python file triggered from).
In different instances, I have tried using:
var path = require('C:/Users/myPath/python.exe');
var nwDir = path.dirname(process.execPath);
var spawn = require("child_process").spawn;
var child = spawn(nwDir + '/test.py');]
as well as:
const spawn = require("child_process").spawn;
const pythonProcess = spawn('python',["/test.py"]);
but I receive this error in both instances:
TypeError: spawn is not a function
located at:
const pythonProcess = spawn('python',["/test.py"]);
lastly I have also tried:
var express = require('express');
var app = express();
const {PythonShell} = require('python-shell');
var options = {
mode: 'text',
pythonPath:
'C:/Users/myPath/python.exe',
pythonOptions: [],
// make sure you use an absolute path for scriptPath
scriptPath:
C:/Users/myPath/test.py', args: []
};
PythonShell.run('test.py', options, function (err, results) {
if (err) throw err;
// results is an array consisting of messages collected during
execution
console.log('results: %j', results);
});
but I receive this error:
TypeError: Cannot read property 'prototype' of undefined
located at my response.js file:
var res = Object.create(http.ServerResponse.prototype);
Is there something I should be including in my server.js file?
Is there a way I can incorporate flask with my current JS page?
For reference, here is a basic version of my current JS file:
myFile.js:
import React from "react";
import Header from "../Header";
import Footer from "../Footer";
class SummaryPage extends React.Component {
render() {
return (
<div>
<Header />
<div className="container-fluid ">
<b><h1>Update and Read CSV File </h1></b>
</div>
<form enctype="multipart/form-data" action="/upload/image"
method="post">
<input type="file" id="fileUpload" />
<div id="dvCSV">
</div>
</form>
<Footer/>
</div>
);
}
}
export default SummaryPage;
To reiterate, how can I have a local .py file be opened and run in the background when my JS page is opened? I would also be happy if it had to occur with the click of a button. No response from the .py file is needed.
Thank you for the time.

Carrierwave image uploading not working

I am trying to upload a logo image to Amazon s3 bucket using carrierwave through rails application. but my file upload is not reading file as HTTP file and adds NULL to the database. I am unable to figure out what is wrong with my code.
Here is my model
class StoreLocation < ActiveRecord::Base
mount_uploader :logo_url, ImageUploader
...
end
My ImageUploader
require 'carrierwave/orm/activerecord'
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
#storage :file
storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def cache_dir
# "#{Rails.root}/tmp/uploads"
Rails.root.join 'tmp/uploads'
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png)
end
end
snippet from my store_location/new.html.erb
<div>
<input id="picholder" type="file" name = "store_location[logo_url]" style = "width: 0px;">
<img id="storeLogo" src="/assets/Picupload_bg.png" alt="storeLogo" class = "small_thumb"/>
<img src="/assets/brws.png" id="brws_logo_file" class = "brws_btn">
</div>
and my javascript store_location.js to read file.
$(document).on('ready page:load', function () {
jQuery.validator.addMethod("lettersonly", function(value, element) {
return this.optional(element) || /^[A-Za-z ]+$/i.test(value);
}, " ");
function readURLImage(filePath) {
if (filePath.files && filePath.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#storeLogo').attr('src', e.target.result);
}
reader.readAsDataURL(filePath.files[0]);
}
}
$("#picholder").change(function(){
readURLImage(this);
});
$("#brws_logo_file").click(function () {
$("#picholder").trigger('click');
});
});
when I run this, I can see thumbnail image on form on selection of any image file, but parameters in requests are like following: (From rails log)
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Q0ejEHG2uzPlSlJ2XF8eC7uVXWs76jtEGfXRNCHgyuc=", "store_location"=>{"store_name"=>"Origins", "first_address"=>"Gulberg", "second_address"=>"", "country"=>"Pakistan", "state"=>"Punjab", "city"=>"Lahore", "zip_code"=>"54000", "phone_no"=>"111674446", "logo_url"=>"b3.jpg"}, "commit"=>"Submit"}
INSERT INTO `store_locations` (`city`, `country`, `created_at`, `first_address`, `logo_url`, `phone_no`, `second_address`, `state`, `store_name`, `updated_at`, `user_id`, `zip_code`) VALUES ('Lahore', 'Pakistan', '2014-12-10 10:33:37', 'Gulberg', NULL, '111674446', '', 'Punjab', 'Origins', '2014-12-10 10:33:37', 1, '54000')
I am unable to understand why logo_url is coming just as file name, where as it should be like
"logo_url"=>#<ActionDispatch::Http::UploadedFile:0x00000009b07c88 #tempfile=#<Tempfile:/tmp/RackMultipart20141209-15502-1q6mzyf>, #original_filename="b3.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"store_location[logo_url]\"; filename=\"b3.jpg\"\r\nContent-Type: image/jpeg\r\n">
Any help in this regard would be appreciated.
Thank You.
By default Carrierwave has a method which is column_name + _url for uploading remote images in a certain column.
For example:
user.logo_url('http://www.example.com/example.png') will save this image in the logo column in the user model.
Rename your column from logo_url to logo in order to upload the image directly and not start HTTP request.

Categories