How to use realm with async fetch request? - react-native

I have meet this situation for my requirements:
step 1. save data to local db which in the mobile phone (realm)
step 2. upload the local data to the server, and the server will return the data ids if success
step 3. delete the records in local db by the returned ids which get by step2
Realm.open({schema:[MySchame],encryptionKey:getRealmKey()})
.then(realm =>{
realm.write(() => {
// 1. get all step data from db
let objetcs = realm.objects('MySchema');
// 2. upload obtained data to server
if(objetcs.length > 0){
let recordArr = [];
for (let o of steps){
recordArr.push(o.get());
}
uploadDataToServer(recordArr,(res)=>{
//3. filter the uploaded steps and delete them
let uploadedSteps = realm.objects('MySchema').filtered('id=$0',res.id);
if(uploadedSteps.length > 0){
realm.delete(uploadedSteps);
}
});
}
});
realm.close();
})
.catch(error =>{
console.log(error);
});
but this is not works as expected, it seems DB is closed too early than networks success callback.
Thanks for any ideas.

Finally ,I use realm like this:
let realm = new Realm({schema:[JOB_SCHEMA.jobTrack],encryptionKey:getRealmKey()});
let objects = realm.objects('JobTrack');
realm.beginTransaction();
realm.delete(objects);
realm.commitTransaction();
realm.close();

First create a service like one below
import repository from "./realmConfig";
let CatalogsService = {
findAll: function () {
return repository.objects("CatalogsModel");
},
save: function (catalogs) {
repository.write(() => {
repository.create("CatalogsModel", catalogs);
});
},
delete: function () {
repository.write(() => {
let all = repository.objects("CatalogsModel");
repository.delete(all);
});
},
update: function (catalogs, callback) {
if (!callback) return;
repository.write(() => {
callback();
catalogs.updatedAt = new Date();
});
}
};
module.exports = CatalogsService;
where my realmConfig file is as
import Realm from "realm";
class CatalogsModel extends Realm.Object { }
CatalogsModel.schema = {
name: "CatalogsModel",
primaryKey: "id",
properties: {
id: "string",
name: "string",
url: "string",
status: "int"
}
};
class OffersModel extends Realm.Object { }
OffersModel.schema = {
name: "OffersModel",
primaryKey: "id",
properties: {
id: "string",
name: "string",
url: "string",
status: "int",
machineId: "string",
machineName: "string"
}
};
export default new Realm({
schema: [CatalogsModel, OffersModel],
schemaVersion: 1,
deleteRealmIfMigrationNeeded: true
});
Now import Service.js where you are calling async server call and do your job. For reference see below code
import CatalogService from './path/to/CatalogService .js'
//get objects
var catalogs = CatalogsService.findAll();
// fire async function , I prefer axios for network calls
Axios.post("SERVER_URL", {
data: catalogs
})
.then(function (response) {
if (response.success)
CatalogsService.delete()
}
I assume you can easily modify findAll() and delete() method as per your need

Related

How Do I Insert Data Into Shopware 6 Database Via The Administration

I have created a plugin, created an admin route but inserting the data into Shopware 6 database does not work. Below is my code. After the build process, it doesn't work, what am I doing wrong?
From the code below I am trying to insert the data 'Diekedie' into the 'name' column of the 'product_manufacturer_translation' table.
const { Component, Mixin } = Shopware;
import template from './custom-module-list.html.twig'
Component.register('custom-module-list', {
template,
inject: [
'repositoryFactory'
],
metaInfo() {
return {
title: this.$createTitle()
};
},
data: function () {
return {
entity: undefined
}
},
methods: {
manufacturerRepository() {
return this.repositoryFactory.create('product_manufacturer_translation');
}
},
computed: {
},
created() {
this.manufacturerRepository();
this.entity = this.manufacturerRepository.create(Shopware.Context.api);
this.entity.name = 'Diekedie';
this.manufacturerRepository.save(this.entity, Shopware.Context.api);
}
});
To set translations you use the repository of the related entity, not the repository of the translations themselves. Also if you have a method that returns the created repository, you must use that return value to create the entity:
methods: {
manufacturerRepository() {
return this.repositoryFactory.create('product_manufacturer');
},
},
created() {
const repository = this.manufacturerRepository();
this.entity = repository.create(Shopware.Context.api);
this.entity.name = 'Diekedie';
repository.save(this.entity, Shopware.Context.api);
}

Why am I not getting updates from my subscription?

I am trying to set up GraphQL Subscriptions but it seems to get connected to the backend but it's not pushing any updates.
On frontend, I am using Nuxt 2 and that's how I am trying to get it working:
That's my test query
export const pendingInquiresSubscription = () => {
return gql`
subscription PendingInquires {
countPendingInquires {
amount
}
}`
}
My smartQuery on the page component
apollo: {
$subscribe: {
pendingInquires: {
query: pendingInquiresSubscription(),
result({ data, loading }) {
this.loading = loading;
console.log(data)
},
error(err) {
this.$notify({ message: `Что-то пошло не так пытаясь обновить количество новый запросов: ${err.message}`, type: 'error' })
},
}
}
},
Backend:
my pubsub
import { RedisPubSub } from 'graphql-redis-subscriptions';
import Redis from 'ioredis';
const REDIS_DOMAIN_NAME = '127.0.0.1'
const PORT_NUMBER = 6379
const options = {
host: REDIS_DOMAIN_NAME,
port: PORT_NUMBER,
retryStrategy: (times: any) => {
return Math.min(times * 50, 2000);
}
}
export const pubsub = new RedisPubSub({
publisher: new Redis(options),
subscriber: new Redis(options)
})
My Schema:
extend type Subscription {
countPendingInquires: PendingInquires!
}
type PendingInquires {
amount: Int!
}
My resolver
...
Subscription: {
countPendingInquires: {
subscribe: () => pubsub.asyncIterator(['countPendingInquires'])
},
},
...
That's the way I am trying to push the event:
pubsub.publish('countPendingInquires', {
PendingInquires: {
amount: await TelegramInguireModel.find({ }).countDocuments()
}
})
And I also wonder if there is any built-in way to set the initial state for subscriptions.
The issue was in the way I was trying to push the event
The correct way of pushing is like this:
pubsub.publish('countPendingInquires', {
countPendingInquires: { // <- here was the issue
amount: await TelegramInquireModel.find({ }).countDocuments()
}
)
I've just set wrong subscription name

Ant Design Pro dynamic menu not showing up

Following the instruction at https://pro.ant.design/docs/router-and-nav#fetch-menu-from-server
I changed file BasicLayout.tsx as below. Menu is not showing up.
...
const testMenu = [{name:"login", path:"/user/login"}] as any;
const [menuData, setMenuData] = useState([]);
useEffect(() => {
if (dispatch) {
dispatch({
type: 'user/fetchCurrent',
});
}
setMenuData(testMenu)
}, []);
...
menuDataRender={()=>menuData}
...
I was doing same as you and failed as you. Document is still wrong.
And I found getting menu from server has a lot of bug with ant design pro v4. (Maybe I did not know)
So my final decision is to display all menu from /config/config.ts as designed initially.
And get only authorization information from server and set only authority to show only logged in user related menu.
So my solution (not correct answer) is:
I referenced this link. https://umijs.org/docs/runtime-config#patchroutes-routes-
Created file /src/app.tsx and inserted code as follow:
interface PathAndIdsModel {
path: string;
ids: string[];
}
const setAuthority = (routes: any, pathAndIds: PathAndIdsModel[]) => {
routes.forEach((route: any) => {
const found = pathAndIds.find((item) => item.path === route.path);
if (found) {
// eslint-disable-next-line no-param-reassign
route.authority = [...new Set([...(route.authority || []), ...found.ids])];
}
if (route.routes) {
setAuthority(route.routes, pathAndIds);
}
});
};
async function patchRoutes({ routes }) {
const response = await fetch(`https://localhost:44357/authorities`);
const pathAndIds = await response.json();
setAuthority(routes, pathAndIds);
}
export { patchRoutes };
Inserted following code to ASP.Net Core Controller:
[HttpGet("/authorities")]
public IEnumerable<object> Authorities()
{
return new[]
{
new {
Path = "/dashboard/analysis",
Ids = new [] { "user", "admin", },
},
new {
Path = "/dashboard/monitor",
Ids = new [] { "user", "admin", },
},
new {
Path = "/dashboard/workplace",
Ids = new [] { "admin", },
},
new {
Path = "/form/basic-form",
Ids = new [] { "admin", },
},
};
}
/dashboard/workplace and /form/basic-form page will be hidden if logged in as user, but shows if logged in as admin.
I tried to get full routes from server, but failed because of async call, UmiJS did not wait until fetching from server and setting new routes.
So when I fetched routes from server and changed routes, UmiJS already converted icon and component of old routes and my new routes never changed.

Vue Apollo: How can I query GraphQL using an object as Input argument?

I would like to create a checkout object via the GraphQL API provided by the Saleor eCommerce platform.
According to the gql playground there is a mutation to do so that takes a CheckoutCreateInput object as it's argument.
Here is an example mutation that works fine within the playground.
Here is the current code that I have tried (I am doing this within a vuex action)
export const actions = {
addToCart({ commit, dispatch }, cartItem) {
const currentCartItems = this.state.cartItems
// Check to see if we already have a checkout object
if (this.state.checkoutId !== '') {
// Create a new checkout ID
console.log('creating new checkout object')
try {
this.app.apolloProvider.defaultClient
.mutate({
mutation: CREATE_CART_MUTATION,
variables: {
checkoutInput: {
lines: { quantity: 10, variantId: 'UHJvZHVjdFZhcmlhbnQ6NQ==' },
email: 'test#test.com'
}
}
})
.then(({ data }) => {
console.log(data)
})
} catch (e) {
console.log(e)
}
} else {
console.log('checkout id already set')
}
// TODO: Check to see if the cart already contains the current Cart Item
commit('ADD_CART_ITEM', cartItem)
}
and here is the CREATE_CART_MUTATION:
import gql from 'graphql-tag'
export const CREATE_CART_MUTATION = gql`
mutation($checkoutInput: CheckoutCreateInput!) {
checkoutCreate(input: $checkoutInput) {
checkout {
id
created
lastChange
lines {
id
variant {
id
name
}
quantity
totalPrice {
gross {
localized
}
net {
localized
}
}
}
totalPrice {
gross {
localized
}
net {
localized
}
}
}
}
}
`
On the server this comes back with the following error:
graphql.error.base.GraphQLError: Variable "$checkoutInput" got invalid value {"email": "test#test.com", "lines": {"quantity": 10, "variantId": "UHJvZHVjdFZhcmlhbnQ6NQ=="}}.
In field "lines": In element #0: Expected "CheckoutLineInput", found not an object.
Looks like I was most of the way there, I was just passing a single lines object rather than an array of them. The correct code is as follows:
try {
this.app.apolloProvider.defaultClient
.mutate({
mutation: CREATE_CART_MUTATION,
variables: {
checkoutInput: {
lines: [
{ quantity: cartItem.quantity, variantId: cartItem.variantId }
],
email: 'test#test.com'
}
}
})
.then(({ data }) => {
console.log('mutation done!')
commit('SET_CHECKOUT_OBJECT', data.checkoutCreate.checkout)
})
} catch (e) {
console.log('error:')
console.log(e)
}

Realm "observer.next create #[native code]" exception

I am trying to fetch data with apollo and then write it to realm. I have created a js file that I know works, because it has worked before. But, when I try to write to a particular model I get an error message. More details as follows:
Code (Not entire code) LocationQuery.js:
const realm = new Realm({ schema: [testBuilding1], schemaVersion: 1 });
let buildingTypeArray = [];
const temp = [];
class LocationQuery extends Component {
static get propTypes() {
return {
data: React.PropTypes.shape({
loading: React.PropTypes.bool,
error: React.PropTypes.object,
sites: React.PropTypes.array,
}).isRequired,
};
}
render() {
if (this.props.data.loading) {
return (null);
}
if (this.props.data.error) {
return (<Text>An unexpected error occurred</Text>);
}
if (this.props.data.sites) {
this.props.data.sites.map((value) => {
buildingTypeArray.push(value.locations);
});
buildingTypeArray.forEach((locationValues) => {
realm.write(() => {
realm.create('testBuilding1', {
building: '273',
});
});
});
}
return null;
}
}
const locationQueryCall = gql`
query locationQueryCall($id: String!){
sites(id: $id){
locations {
building
type
}
}
}`;
const ViewWithData = graphql(locationQueryCall, {
options: props => ({
variables: {
id: 'SCH1',
},
}),
})(LocationQuery);
export default connect(mapStateToProp)(ViewWithData);
The error I get is a big red screen that read:
console.error: "Error in observe.next.... blah blah blah"
The Model I am using:
export const testBuilding1 = {
name: 'testBuilding1',
properties: {
building: 'string',
},
};
The weird thing is that the code works when I use this model:
export const locationScene = {
name: 'locationScene',
properties: {
building: 'string',
},
};
I am calling LocationQuery.js in another piece of code passing it through at render.
Thank you in advance for the help!