How to access JSON file in NativeScript? - nativescript

hello I am trying to access a JSON file to my nativescrpt project. i tried this
let fs = require("tns-core-modules/file-system");
let documents = fs.knownFolders.currentApp();
function GetJsonData(callback) {
let filePath = documents.getFile("./shared/message.json");
let array;
let jsonData;
jsonFile.readText().then(function (content) {
try {
jsonData = JSON.parse(content);
array = new observableArrayModule.ObservableArray(jsonData);
} catch (err) {
throw new Error('Could not parse JSON file');
}
}, function (error) {
throw new Error('Could not read JSON file');
});
function showJsonData() {
GetJsonData((array) => {
console.log(array);
});
}
but it is failed to get data from JSON file

First you have to check that file is included in your webpack.config.js file in your project. Like #dashman said.
Find this in your webpack
new CopyWebpackPlugin([
{ from: { glob: "fonts/**" } },
{ from: { glob: "**/*.jpg" } },
{ from: { glob: "**/*.png" } },
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
and change to like this
new CopyWebpackPlugin([
{ from: { glob: "fonts/**" } },
{ from: { glob: "**/*.jpg" } },
{ from: { glob: "**/shared/*.json" } },
{ from: { glob: "**/*.png" } },
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
After that your code also lots of mistakes.
Change like this
let fs = require("tns-core-modules/file-system");
let documents = fs.knownFolders.currentApp();
function GetJsonData(callback) {
let jsonFile = documents.getFile("./shared/message.json");
jsonFile.readText().then(function (content) {
try {
var jsonData = JSON.parse(content);
callback(jsonData);
} catch (err) {
callback(err);
throw new Error('Could not parse JSON file');
}
}, function (error) {
callback(error);
throw new Error('Could not read JSON file');
});
}
function showJsonData() {
GetJsonData((array) => {
console.log(array);
});
}

You should fetch the folder first, and you should do so using the knownFolders starting point.
import { knownFolders } from 'tns-core-modules/file-system';
knownFolders.currentApp().getFolder('shared').getFile('message.json').readText ...;

If this file is in your source project - you have to make sure it gets saved by webpack.
In your webpack.config.js file
new CopyWebpackPlugin([
{ from: { glob: "**/*.jpg" } },
{ from: { glob: "**/shared/*.json" } },
{ from: { glob: "**/*.png" } }

Related

How to create a list of wix media folder images with url and name

Is there a way in wix to get a list of all media files (images) urls and names?
I would need this to upload it in a field of the content manager to link data records and images.
You can use the new mediaManager API:
From Wix enable the developper mode
Go to the code files (icon {} to the left), and create a new backend JS file named 'http-functions.js'
Edit this file and add the following code:
import { ok, badRequest } from 'wix-http-functions';
import { mediaManager } from 'wix-media-backend';
export function get_filesList(request) {
const response = {
"headers": {
"Content-Type": "application/json"
}
};
var filters = {};
var paging = {};
if (request.query) {
if ('folder' in request.query ) { //
filters.parentFolderId = request.query["folder"];
}
if ('limit' in request.query) {
paging.limit = request.query['limit'];
}
if ('skip' in request.query) {
paging.skip = request.query['skip'];
}
}
return mediaManager.listFiles(filters, null, paging)
.then((myFiles) => {
response.body = {
"filesList": myFiles
};
return ok(response);
})
.catch((err) => {
response.body = {
"error": err
};
return badRequest(response);
});
}
export function get_listFolders(request) {
const response = {
"headers": {
"Content-Type": "application/json"
}
};
var filters = {};
var paging = {};
if (request.query) {
if ('folder' in request.query ) { //
filters.parentFolderId = request.query["folder"];
}
if ('limit' in request.query) {
paging.limit = request.query['limit'];
}
if ('skip' in request.query) {
paging.skip = request.query['skip'];
}
}
return mediaManager.listFolders(filters, null, paging)
.then((myFolders) => {
response.body = {
"foldersList": myFolders
};
return ok(response);
})
.catch((err) => {
response.body = {
"error": err
};
return badRequest(response);
});
}
Publish the files
You can query your custom API from: https://www.your_website.com/_functions/filesList and https://www.your_website.com/_functions/foldersList and query parameters folderId, skip and limit for pagination.
Wix documentation:
https://support.wix.com/en/article/velo-exposing-a-site-api-with-http-functions
https://www.wix.com/velo/reference/wix-media-backend/mediamanager-obj/listfiles

How to query multiple images in Gatsby from Strapi using Graphql

I have set up a multiple media(images) field called pictures on my project content type on Strapi and I have added 2 projects with pictures containing 4 images each.
I want to query these images in Gatsby using Graphql.
This is my plugins array in gatsby-config.js
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`,
},
},
{
resolve: `gatsby-source-strapi`,
options: {
apiURL: `http://localhost:1337`,
queryLimit: 1000,
contentTypes: [`project`],
},
}]
This is my graphql query on localhost:8000/___graphql
query MyQuery {
allStrapiProject {
nodes {
pictures {
formats {
thumbnail {
childImageSharp {
fluid {
src
}
}
}
}
}
}
}
}
This is the result I am getting
{
"data": {
"allStrapiProject": {
"nodes": [
{
"pictures": [
{
"formats": {
"thumbnail": null
}
},
{
"formats": {
"thumbnail": {
"childImageSharp": {
"fluid": {
"src": "/static/eb8a7ee6108ecc0e6185aced82c3316b/b4216/167f320a448c2d6ff65acf179ee627e2.jpg"
}
}
}
}
},
{
"formats": {
"thumbnail": null
}
},
{
"formats": {
"thumbnail": null
}
}
]
},
{
"pictures": [
{
"formats": {
"thumbnail": null
}
},
{
"formats": {
"thumbnail": null
}
},
{
"formats": {
"thumbnail": null
}
},
{
"formats": {
"thumbnail": null
}
}
]
}
]
}
}
}
All of the thumbnails contain null except for one.
I have tried running 'gatsby clean' and sometimes get the query output to have same image urls in multiple places even though i don't have repeating images on Strapi.
As of now, there is no "official" way to make it happen. But there is a workaround which creates a custom node in the build process. For a graphql query like below
query MyQuery {
allStrapiPortfolio {
edges {
node {
category {
images {
localFile {
childImageSharp {
fluid {
base64
tracedSVG
srcWebp
srcSetWebp
originalImg
originalName
}
}
}
}
}
}
}
}
}
The code given below creates the localFile node after images. The code should go in gatsby-node.js.
const { createRemoteFileNode } = require(`gatsby-source-filesystem`);
exports.onCreateNode = async ({ node, actions, store, cache }) => {
const { createNode, createNodeField } = actions;
if (node.internal.type !== null && node.internal.type === "StrapiPortfolio") {
for (const category of node.category) {
for (const image of category.images) {
console.log(image);
const fileNode = await createRemoteFileNode({
url: "http://localhost:1337" + image.url,
store,
cache,
createNode,
createNodeId: (id) => image.id.toString(),
});
if (fileNode) {
image.localFile___NODE = fileNode.id;
}
}
}
}
};
Please note that you will have to customize the code depending on your needs. In my solution, I used two for loops because of my data structure. If you're unsure or just want to check if your custom code works, you can simply add a console.log(node) before the first if statement and a console.log(image) after the second for loop(in my case). That should give you an indication about your data structure and in which way you should proceed.
You need to create a localFile___NODE.
First, you need to edit gatsby-node.js file.
const { createRemoteFileNode } = require(`gatsby-source-filesystem`)
exports.onCreateNode = async ({
node,
actions,
store,
cache,
createNodeId,
}) => {
const { createNode } = actions
// replace ".sliderHome" for the name of multiple media in Strapi CMS
let sliderImages = node.sliderHome
// replace “StrapiHome” for your node type
if (node.internal.type === "StrapiHome") {
if (sliderImages.length > 0) {
// sliderImages.forEach(el => console.log(el))
const images = await Promise.all(
sliderImages.map(el =>
createRemoteFileNode({
url: `http://localhost:1337${el.url}`,
parentNodeId: node.id,
store,
cache,
createNode,
createNodeId,
})
)
)
sliderImages.forEach((image, i) => {
image.localFile___NODE = images[i].id
})
}
}
}
later restart Gatsby and now this is your query
query MyQuery {
allStrapiProject {
nodes {
pictures {
localFile{
childImageSharp{
fluid(maxWidth: 1200){
// or for gatsby use ...GatsbyImageSharpFluid_withWebp
src
}
}
}
}
}
}
}
this has worked for me to bring multiple images with a good quality I hope it works for you
Try below, replace the value you need to display:
Here I am the example for the user avatar
query MyQuery {
allStrapiUser {
edges {
node {
id
avatar {
publicURL
childImageSharp {
fluid {
src
aspectRatio
}
}
}
}
}
}
}
and:
const poster = data.allStrapiUser.edges[0].node
<Img fluid={{aspectRatio: 1.6, src: poster.avatar.publicURL}}/>

Unable to fetch data from API (Resource blocked by client) in Vuex

I'm trying to fetch some data from my API using vuex + axios, but the action give me a "Network Error" (ERR_BLOCKED_BY_CLIENT).
when i was using json-server it works fine, but it doesn't work with my API even with 'Allow-Access-Control-Origin': '*'
actions
const actions = {
async fetchSearch({ commit, state }) {
let res
try {
res = await axios(`http://localhost:8000/api/advertisements/search?column=title&per_page=${state.params.per_page}&search_input=${state.params.query.toLowerCase()}&page=${state.params.page}`, {
method: 'GET',
mode: 'no-cors',
headers: {
'Content-Type': 'application/json'
}
})
} catch(err) {
console.log(err)
}
commit('clearProducts')
commit('setProducts', res.data)
},
setGlobalParams({ commit }, obj) {
commit('clearParams')
commit('setParams', obj)
}
}
component
<script>
/* Vuex import */
import { mapActions } from 'vuex'
export default {
name: 'base-search-component',
data() {
return {
query_obj: {
page: 1,
per_page: 8,
query: ''
}
}
},
methods: {
...mapActions([
'fetchSearch',
'setGlobalParams'
]),
fetchData() {
if (this.query_obj.query === '') {
return
} else {
this.setGlobalParams(this.query_obj)
this.fetchSearch()
this.$router.push({ name: 'search', params: { query_obj: this.query_obj } })
}
}
}
}
</script>
Assuming your cors issue was properly resolved the reason you cannot access the data is that it is being set before the axios promise is being resolved.
Change:
async fetchSearch({ commit, state }) {
let res
try {
res = await axios(`http://localhost:8000/api/advertisements/search?column=title&per_page=${state.params.per_page}&search_input=${state.params.query.toLowerCase()}&page=${state.params.page}`, {
method: 'GET',
mode: 'no-cors',
headers: {
'Content-Type': 'application/json'
}
})
} catch(err) {
console.log(err)
}
commit('clearProducts')
commit('setProducts', res.data)
}
to:
async fetchSearch({ commit, state }) {
await axios(`http://localhost:8000/api/advertisements/search?column=title&per_page=${state.params.per_page}&search_input=${state.params.query.toLowerCase()}&page=${state.params.page}`, {
method: 'GET',
mode: 'no-cors',
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
commit('clearProducts')
commit('setProducts', response.data)
}).catch(err) {
console.log(err)
}
}
Further you should use mapState. Assuming setProducts is setting a state object like products this would look like:
<script>
/* Vuex import */
import { mapState, mapActions } from 'vuex'
export default {
name: 'base-search-component',
data() {
return {
query_obj: {
page: 1,
per_page: 8,
query: ''
}
}
},
computed: {
mapState([
'products'
])
},
methods: {
...mapActions([
'fetchSearch',
'setGlobalParams'
]),
fetchData() {
if (this.query_obj.query === '') {
return
} else {
this.setGlobalParams(this.query_obj)
this.fetchSearch()
this.$router.push({ name: 'search', params: { query_obj: this.query_obj } })
}
}
}
}
</script>
Now you can refrence this.products in JS or products in your template.

How to concat array of observables into one. throw error Property 'pipe' does not exist on type 'Observable<Message>[]'

angular v 6.1.10
typescript v 2.9.2
rxjs v 6.3.3
ng2-stmompjs v 7.0.0
I am using ng2-stomp library for web sockets which create observable of will initiate a subscription which is observable. In my requirements, I am creating multiple channel subscriptions based on application id and now want to subscribe all these channels all in once or we can say higher order observable so tried to use the various rxjs operator merge, mergeAll, concat but nothing works so far. Here is what I have done so far.
Right now this one is working
appList = [{appID: '123'}, {appID: '345'}];
const appList$ = appList.map((appID: string, idx: number) => {
const headers = Object.assign({}, this.headers, { id: `app_${idx}` });
const watcher = this.rxStompService.watch(`/topic/${appID}`, headers);
console.log({ watcher }); // This is observable
return watcher;
});
appList$.forEach((app$) => {
app$.subscribe((message: Message) => {
const notification: Notification = JSON.parse(message.body);
this.totalNotificationCount++;
if (Object.keys(notification).length) {
this.notificationMessages.push(notification);
}
});
});
{
"watcher": { "_isScalar": false, "source": { "source": { "_isScalar": false } }, "operator": { "connectable": { "source": { "_isScalar": false } } } }
}
BUT I think we can concat all observables in one and can subscribe all. Note that I am unable to use ForkJoin because appList is dynamic and so the number of WebSocket. followings are my trail to convert multiple observable into once.
Trial 1: using concat and map operator
const batch = appList.map((appID, idx) => {
console.log({ appID, idx });
const headers = Object.assign({}, this.headers, { id: `app_${idx}` });
const watcher = this.rxStompService.watch(`/topic/${appID}`, headers);
return watcher;
});
concat(...batch).pipe( map (i => i)).subscribe({ });
this gives error:
Property 'pipe' does not exist on type 'MonoTypeOperatorFunction'.
trial 2: use subscribe all after concat
concat(...batch).subscribe({
next: (v: any) => console.log(v),
complete: () => console.log('Complete')
});
Error: Property 'subscribe' does not exist on type 'MonoTypeOperatorFunction'.
Trail 3: using pipe
const appList$ = appList.map((appID: string, idx: number) => {
const headers = Object.assign({}, this.headers, { id: `app_${idx}` });
const watcher = this.rxStompService.watch(`/topic/${appID}`, headers);
return watcher;
});
console.log({ appList$ });
appList$.pipe(
takeUntil(this.ngUnsubscribe),
tap((i) => {
console.log('tapping', i);
})
);
console.log({appList$}) return this
{
"appList$": [
{
"_isScalar": false,
"source": {
"source": {
"_isScalar": false
}
},
"operator": {
"connectable": {
"source": {
"_isScalar": false
}
}
}
},
{
"_isScalar": false,
"source": {
"source": {
"_isScalar": false
}
},
"operator": {
"connectable": {
"source": {
"_isScalar": false
}
}
}
},
{
"_isScalar": false,
"source": {
"source": {
"_isScalar": false
}
},
"operator": {
"connectable": {
"source": {
"_isScalar": false
}
}
}
},
{
"_isScalar": false,
"source": {
"source": {
"_isScalar": false
}
},
"operator": {
"connectable": {
"source": {
"_isScalar": false
}
}
}
},
{
"_isScalar": false,
"source": {
"source": {
"_isScalar": false
}
},
"operator": {
"connectable": {
"source": {
"_isScalar": false
}
}
}
},
{
"_isScalar": false,
"source": {
"source": {
"_isScalar": false
}
},
"operator": {
"connectable": {
"source": {
"_isScalar": false
}
}
}
}
]
}
Error: Property 'pipe' does not exist on type 'Observable[]'
So my question is how to merge all observable into once and subscribe in once
This is amazing; whenever I write the question here and try again and I found the solution myself.
I have solved this way using from and mergeMap and thanks to this angular in depth article
private watchApplications(appList: string[]) {
const appList$ = from(appList).pipe(
mergeMap((appID, idx) => {
const headers = Object.assign({}, this.headers, { id: `app_${idx}` });
const watcher = this.rxStompService.watch(`/topic/${appID}`, headers);
return watcher;
})
);
appList$
.pipe(
takeUntil(this.ngUnsubscribe),
tap((f: Frame) => {
console.log('tapping Frame', f);
})
)
.subscribe((message: Message) => {
const notification: Notification = JSON.parse(message.body);
console.log({ notification });
this.totalNotificationCount++;
if (Object.keys(notification).length) {
this.notificationMessages.push(notification);
}
});
}

How to call the function inside other function both defined in same export default?

My code are:-
function showData(data) {
return {
type: 'SHOWDATA',
data,
};
}
export default {
fetchData() {
return function (dispatch) {
getDataApi.getData().then((response)=>dispatch(showData(response)).catch()
};},
updateData{
return function (dispatch) {
getDataApi.getData().then((response)=>if(response.isSucess)
{dispatch(fetchData())}).catch()
};}
}
After update call of the action I want to refresh the list thats why I
called dispatch(fetchData()); but it is showing that fetchData not
defined.How can I call the method defined in same export default function.
Can this help you? Not really exported as default but its named.
export const Actions = {
getAll,
add,
update,
view,
search
}
function getAll(){
return dispatch => {
dispatch(request());
Service.getAll()
.then(
response => {
// todo...
},
error => {
// catch error
}
);
}
function request() { return { type: Constants.LIST_REQUEST } }
function success(data) { return { type: Constants.LIST_SUCCESS, data } }
function failure(error) { return { type: Constants.LIST_FAILURE, error } }
}
function add(data){
return dispatch => {
dispatch(request());
Service.add(data)
.then(
response => {
if(response.status === 'fail'){
// do something
}else{
dispatch(success(response));
dispatch(getAll());
}
},
error => {
// do something
}
);
}
function request() { return { type: Constants.ADD_REQUEST } }
function success(data) { return { type: Constants.ADD_SUCCESS, data } }
function failure(error) { return { type: Constants.ADD_FAILURE, error } }
}

Resources