When using LOAD CSV function with session.run() to execute cypher statements into Neo4J it doesn't return anything. Have tried removing LOAD CSV and it works perfectly fine in creating nodes.
This is the code:
import { neo4jgraphql } from "neo4j-graphql-js";
import fs from "fs";
import path from "path";
const {createWriteStream} = require("fs");
const {GraphQLUpload} = require("apollo-server");
import {session} from "./index.js"
/*
* Check for GRAPHQL_SCHEMA environment variable to specify schema file
* fallback to schema.graphql if GRAPHQL_SCHEMA environment variable is not set
*/
const files = [];
export const typeDefs = fs
.readFileSync(
process.env.GRAPHQL_SCHEMA || path.join(__dirname, "schema.graphql")
)
.toString("utf-8");
export const resolvers = {
// Upload: GraphQLUpload,
Query: {
files: () => files
},
Mutation: {
uploadFile: async (_, {file}) => {
const {createReadStream, filename } = await file;
await new Promise(res =>
createReadStream()
.pipe(createWriteStream(path.join(__dirname, "./uploads", filename)))
.on("close", res)
);
session.run("LOAD CSV WITH HEADERS FROM 'file:///Connections.csv' AS csvLine CREATE(n)"); // This does not work with the LOAD CSV (Works with only CREATE(n))
return true;
}
}
};
That LOAD CSV command will just invoke CREATE (n) once per line which will create a node with no label or properties. Try changing it to something like CREATE (n:CsvNode) SET n.prop_1 = csvLine.header1 (where header1 is one of the headers from your CSV) and see if nodes labelled :CsvNode get created.
Related
Just starting with Deno, I am trying to figure out how to calculate a binary file checksum. It seems to me that the problem is not with the methods provided by the hash module of the standard library, but with the file streaming method and/or the type of the chunks feeding the hash.update method.
I have been trying a few alternatives, related to file opening and chunk types,with no success. A simple example is in the following:
import {createHash} from "https://deno.land/std#0.80.0/hash/mod.ts";
const file= new File(["my_big_folder.tar.gz"], "./my_big_folder.tar.gz");
const iterator = file.stream() .getIterator();
const hash = createHash("md5");
for await( let chunk of iterator){
hash.update(chunk);
}
console.log(hash.toString()); //b35edd0be7acc21cae8490a17c545928
This code compiles and runs with no errors, pity that the result is different from what I get running the functions of the crypto module provided by node and the md5sum provided by linux coreutils. Any suggestion ?
nodejs code:
const crypto = require('crypto');
const fs = require('fs');
const hash = crypto.createHash('md5');
const file = './my_big_folder.tar.gz';
const stream = fs.ReadStream(file);
stream.on('data', data=> { hash.update(data); });
stream.on('end', ()=> {
console.log(hash.digest('hex')); //c18f5eac67656328f7c4ec5d0ef5b96f
});
The same result in bash:
$ md5sum ./my_big_folder.tar.gz
$ c18f5eac67656328f7c4ec5d0ef5b96f ./my_big_folder.tar.gz
on Windows 10 this can be used:
CertUtil -hashfile ./my_big_folder.tar.gz md5
The File API isn't used to read a File in Deno, to do that you need to use the Deno.open API and then turn it into an iterable like this
import {createHash} from "https://deno.land/std#0.80.0/hash/mod.ts";
const hash = createHash("md5");
const file = await Deno.open(new URL(
"./BigFile.tar.gz",
import.meta.url, //This is needed cause JavaScript paths are relative to main script not current file
));
for await (const chunk of Deno.iter(file)) {
hash.update(chunk);
}
console.log(hash.toString());
Deno.close(file.rid);
import { crypto, toHashString } from 'https://deno.land/std#0.176.0/crypto/mod.ts';
const getFileBuffer = (filePath: string) => {
const file = Deno.openSync(filePath);
const buf = new Uint8Array(file.statSync().size);
file.readSync(buf);
file.close();
return buf;
};
const getMd5OfBuffer = (data: BufferSource) => toHashString(crypto.subtle.digestSync('MD5', data));
export const getFileMd5 = (filePath: string) => getMd5OfBuffer(getFileBuffer(filePath));
I have a table that contains a collection of files.
My use case is that when a user clicks on a row in that table, an event will be fired that will make a call to the service and get the JSON data. the JSON data is going to change whenever user clicks on a different row in a table. So I am not going to have specific properties or let's say keys (in key value pair). I am just gonna get JSON data in the form of a 2D string array.
Now my task is to grab this data and export it into excel document.
I was able to find a solution to this problem and I am posting it here. Here are the links I had referred to in order to make this work.
https://stackblitz.com/edit/angular6-export-xlsx
https://medium.com/#madhavmahesh/exporting-an-excel-file-in-angular-927756ac9857
The first thing to do is
npm install xlsx
Then create a service -->
import { Injectable } from '#angular/core';
import * as FileSaver from 'file-saver';
import * as XLSX from 'xlsx';
const EXCEL_TYPE =
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
const EXCEL_EXTENSION = '.xlsx';
#Injectable()
export class ExcelService {
constructor() {}
public exportAsExcelFile(json: any[], excelFileName: string): void {
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
console.log('worksheet', worksheet);
const workbook: XLSX.WorkBook = { Sheets: { data: worksheet }, SheetNames: ['data'] };
const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' });
this.saveAsExcelFile(excelBuffer, excelFileName);
}
private saveAsExcelFile(buffer: any, fileName: string): void {
const data: Blob = new Blob([buffer], {
type: EXCEL_TYPE
});
FileSaver.saveAs(data, fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION);
}
}
Import this service in your main component (app.module.ts or whatever your component is). Make sure you add that service in the 'providers' array.
Then in your TS file, add this function -->
exportAsXLSX(): void {
this.someService.getFileData(this.clientFile).subscribe(
(res: any) => {
if (res.data) {
this.fileData = res.data;
}
},
err => {
let someMsg = 'Error exporting file';
if (err.status === 409) {
someMsg =
err.error.error.errorMessage.length > 0
? err.error.error.errorMessage
: someMsg;
}
this.toastService.error(someMsg);
}
);
this.excelService.exportAsExcelFile(this.fileData, 'sample');
}
Here, this.fileData is an array of type any, defined as fileData: any [] in my component. It's totally up to you how to get data in this array. The main thing is to pass it to the function that will convert this to excel.
Now that you have your service written and your component has a function for it, it's time to wire this up to the HTML file.
<div class="ui-helper-clearfix">
<button
type="button"
pButton
icon="fa fa-file-excel-o"
iconPos="left"
label="Export To Excel"
(click)="exportAsXLSX()"
style="float:left"
></button>
</div>
On click of the button, you will be able to get data in an excel document.
This is the function I am using to upload file but is is giving me the error : Length is undefined. what I have to change in this code. where to give path of file to upload.
fileChange(event) {
let fileList: FileList = event.target.files;
if(fileList) {
let file: File = fileList[0];
let formData:FormData = new FormData();
formData.append('uploadFile', file, file.name);
let headers = new Headers();
/** No need to include Content-Type in Angular 4 */
headers.append('Content-Type', 'multipart/form-data');
headers.append('Accept', 'application/json');
let options = new RequestOptions({ headers: headers });
this.http.post(`assets/Files/info.txt`, formData, options)
.map(res => res.json())
.catch(error => Observable.throw(error))
.subscribe(
data => console.log(fileList),
error => console.log(error)
)
}
}
you need to use xhr request to transfer files
fileChange(event: EventTarget) {
let eventObj: MSInputMethodContext = <MSInputMethodContext> event;
let target: HTMLInputElement = <HTMLInputElement> eventObj.target;
let files: FileList = target.files;
if(files) {
let file: File = files[0];
this.upload(file)
}
}
public upload(filedata: File) {
let url = 'your url'
if (typeof filedata != 'undefined') {
return new Promise((resolve, reject) => {
let formData: any = new FormData();
let xhr = new XMLHttpRequest();
formData.append('icondata', filedata, filedata.name);
xhr.open('POST', url, true);
xhr.setRequestHeader('Authorization', 'JWT ' + localStorage.getItem('id_token'));
xhr.send(formData);
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
resolve(JSON.parse(xhr.responseText));
}
}
});
}
}
I understand that this is not the functionality you want to have but with no backend you can not upload files to be persistent, they should be stored somewhere. If you just wanna manipulate file names for instance, skip the express part in my answer. I personally used this code which I altered to upload multiple files.
In your Component :
import {FormArray, FormBuilder, FormControl, FormGroup} from "#angular/forms";
declare FormBuilder in the constructor:
constructor (private http: Http, private fb: FormBuilder) {}
in ngOnInit() set a variable as follows :
this.myForm = this.fb.group({chosenfiles: this.fb.array([])});
this is the code for the upload method :
// invoke the upload to server method
// TODO
// Should be in a service (injectable)
upload() {
const formData: any = new FormData();
const files: Array<File> = this.filesToUpload;
//console.log(files);
const chosenf = <FormArray> this.myForm.controls["chosenfiles"];
// iterate over the number of files
for(let i =0; i < files.length; i++){
formData.append("uploads[]", files[i], files[i]['name']);
// store file name in an array
chosenf.push(new FormControl(files[i]['name']));
}
this.http.post('http://localhost:3003/api/upload', formData)
.map(files => files.json())
.subscribe(files => console.log('upload completed, files are : ', files));
}
the method responsible for the file change :
fileChangeEvent(fileInput: any) {
this.filesToUpload = <Array<File>>fileInput.target.files;
const formData: any = new FormData();
const files: Array<File> = this.filesToUpload;
console.log(files);
const chosenf = <FormArray> this.myForm.controls["chosenfiles"];
// iterate over the number of files
for(let i =0; i < files.length; i++){
formData.append("uploads[]", files[i], files[i]['name']);
// store file name in an array
chosenf.push(new FormControl(files[i]['name']));
}
}
Template is something like this
<input id="cin" name="cin" type="file" (change)="fileChangeEvent($event)" placeholder="Upload ..." multiple/>
Notice multiple responsible for allowing multiple selections
The express API which will handle the request uses multer after an npm install
var multer = require('multer');
var path = require('path');
specify a static directory which will hold the files
// specify the folder
app.use(express.static(path.join(__dirname, 'uploads')));
As specified by multer
PS: I did not investigate multer, as soon as i got it working, i moved to another task but feel free to remove unnecessary code.
var storage = multer.diskStorage({
// destination
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname);
}
});
var upload = multer({ storage: storage });
And finally the endpoint
app.post("/api/upload", upload.array("uploads[]", 12), function (req, res) {
console.log('files', req.files);
res.send(req.files);
});
I am using ng-file-upload and multer to store files in an uploads folder and I also save the filename to database but of course not at the same instant. So if I want to save the original filename, multer will do this like:
filename: function (req, file, cb) {
cb(null, file.originalname);
I can use
cb(null, file.originalname + '-' + Date.now());
to make the name unique but then the filename in the database (taken from the ng-file-upload service) is different.
I want to use Upload.rename(file, newName) as on the github/danialfarid/ng-file-upload page but all my attempts to use it have failed.
This is the ng-file-upload code (first part)
$scope.uploadPic = function(files) {
for(var i = 0; i < $scope.files.length; i++) {
var $file = $scope.files[i];
(function(index) {
$scope.upload[index] = Upload.upload({
url: '/',
method: 'POST',
file: $file,
}).progress(function (evt) {
$scope.files[index].progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
}).then(function (response) {
$timeout(function () {
$file.result = response.data;
I have tried var newName = $file.name + '-' + Date.now()
but then I am unsure of how to apply Upload.rename(file, newName)
I thought if I set the new name before multer gets hold of it then the uploads folder and the database will have the same name.
At least that's the idea. Can anyone help?
in the upload options, set the file key as the name of the file and use the same key for the multer options e.g:
if you have this for your ng-file-upload options:
$scope.upload[index] = Upload.upload({
url: '/',
method: 'POST',
nameOfImage: $file,
})
for multer, you should also have
upload.single('nameOfImage')
I tried this using multer v1.2.0 and ng-file-upload 12.2.12
I was using an older version of ng-file-upload (7.X.X) which didn't have this in ng-file-upload.js
this.rename = function (file, name) {
file.ngfName = name;
return file;
};
I updated to version 10.0.2
So now I can use Upload.rename($file, 'preview1.jpg');
and the file is saved with the new name.
I'm trying test custom angular components. I want check the components class state. For this a have two options:
Get the component in the scope
Use web components xtag
The problems:
My scope is always empty - I debug in the console I'm using karma to run the tests in the browser.
xtag returns an HtmlElement class so I can't access my properties(cast in dart?)
The codes:
library vader.panel_spec;
import '../_specs.dart';
import "package:vader/components/vader_component.dart";
main(){
describe('Tests for Panel UI',(){
TestBed _;
Scope _scope;
Element ngAppElement;
beforeEach(async(inject((TestBed tb, Scope scope, VmTurnZone zone, TemplateCache cache) {
_ = tb;
_scope = scope;
addToTemplateCache(cache, 'packages/vader/components/panel.html');
addToTemplateCache(cache, 'packages/vader/components/window/window.html');
})));
beforeEachModule((Module module) {
ngAppElement = new DivElement()..attributes['ng-app'] = '';
module
..install(new VaderComponentModule());
module..bind(Node, toValue: ngAppElement);
document.body.append(ngAppElement);
});
afterEach(() {
ngAppElement.remove();
ngAppElement = null;
});
compile(html) {
ngAppElement.setInnerHtml(html, treeSanitizer: new NullTreeSanitizer());
_.compile(ngAppElement);
return ngAppElement.firstChild;
}
it("should collapse when clicked", async((){
Element panel = compile("<v-panel>CollapsedItem</v-panel>");
microLeap();
_.rootScope.apply();
Element contentPanel = panel.querySelector('.content-panel');
expect(contentPanel.classes.contains('collapse'), isFalse);
_.triggerEvent(panel.querySelector('#collapse-icon'), 'click');
_.rootScope.apply();
window.console.debug(_.rootScope.context);
var comp = panel.xtag;
expect(comp.doCollapse, isTrue);
}));
});
}
library ng_specs;
import 'dart:html' hide Animation;
import 'package:angular/angular.dart';
import 'package:angular/mock/module.dart';
import 'package:guinness/guinness_html.dart' as gns;
export 'dart:html' hide Animation;
export 'package:unittest/unittest.dart' hide expect;
export 'package:guinness/guinness_html.dart';
export 'package:mock/mock.dart';
export 'package:di/di.dart';
export 'package:di/dynamic_injector.dart';
export 'package:angular/angular.dart';
export 'package:angular/application.dart';
export 'package:angular/introspection.dart';
export 'package:angular/core/annotation.dart';
export 'package:angular/core/registry.dart';
export 'package:angular/core/module_internal.dart';
export 'package:angular/core_dom/module_internal.dart';
export 'package:angular/core/parser/parser.dart';
export 'package:angular/core/parser/lexer.dart';
export 'package:angular/directive/module.dart';
export 'package:angular/formatter/module.dart';
export 'package:angular/routing/module.dart';
export 'package:angular/animate/module.dart';
export 'package:angular/mock/module.dart';
export 'package:perf_api/perf_api.dart';
es(String html) {
var div = new DivElement();
div.setInnerHtml(html, treeSanitizer: new NullTreeSanitizer());
return new List.from(div.nodes);
}
e(String html) => es(html).first;
Expect expect(actual, [matcher]) {
final expect = new Expect(actual);
if (matcher != null) {
expect.to(matcher);
}
return expect;
}
class Expect extends gns.Expect {
Expect(actual) : super(actual);
NotExpect get not => new NotExpect(actual);
toBeValid() => _expect(actual.valid && !actual.invalid, true,
reason: 'Form is not valid');
toBePristine() => _expect(actual.pristine && !actual.dirty, true,
reason: 'Form is dirty');
get _expect => gns.guinness.matchers.expect;
}
class NotExpect extends gns.NotExpect {
NotExpect(actual) : super(actual);
toBeValid() => _expect(actual.valid && !actual.invalid, false,
reason: 'Form is valid');
toBePristine() => _expect(actual.pristine && !actual.dirty, false,
reason: 'Form is pristine');
get _expect => gns.guinness.matchers.expect;
}
_injectify(fn) {
// The function does two things:
// First: if the it() passed a function, we wrap it in
// the "sync" FunctionComposition.
// Second: when we are calling the FunctionComposition,
// we inject "inject" into the middle of the
// composition.
if (fn is! FunctionComposition) fn = sync(fn);
return fn.outer(inject(fn.inner));
}
// Replace guinness syntax elements to inject dependencies.
beforeEachModule(fn) => gns.beforeEach(module(fn), priority:1);
beforeEach(fn) => gns.beforeEach(_injectify(fn));
afterEach(fn) => gns.afterEach(_injectify(fn));
it(name, fn) => gns.it(name, _injectify(fn));
iit(name, fn) => gns.iit(name, _injectify(fn));
_removeNgBinding(node) {
if (node is Element) {
node = node.clone(true) as Element;
node.classes.remove('ng-binding');
node.querySelectorAll(".ng-binding").forEach((Element e) {
e.classes.remove('ng-binding');
});
return node;
}
return node;
}
/**
* It adds an html template into the TemplateCache.
*/
void addToTemplateCache(TemplateCache cache, String path) {
HttpRequest request = new HttpRequest();
request.open("GET", path, async : false);
request.send();
cache.put(path, new HttpResponse(200, request.responseText));
}
main() {
gns.beforeEach(setUpInjector, priority:3);
gns.afterEach(tearDownInjector);
gns.guinnessEnableHtmlMatchers();
gns.guinness.matchers.config.preprocessHtml = _removeNgBinding;
}
Use ngInjector(panel).get(PanelComponent) or ngDirectives(panel)[0]. See the documentation here.