cozy / cozy-client

Document store and React components for the Cozy platform
MIT License
13 stars 13 forks source link

Create method not working with relationship #798

Open Merkur39 opened 4 years ago

Merkur39 commented 4 years ago

I want to report a problem with the create method of CozyClient When you want pass relationships, contactDataFormatted => Contact model client.create(CONTACTS_DOCTYPE, contactDataFormatted, { _id: groupID, _type: GROUPS_DOCTYPE })

i have the following error alt text here: https://github.com/cozy/cozy-client/blob/828be3c1d2eeea43701c60256dee0d794d7ccc5c/packages/cozy-client/src/CozyClient.js#L523

For the moment, I do this: contactDataFormatted => Contact model with relationship ex:

relationships: {
  groups: {
    data: groupID ? [{ _id: groupID, _type: GROUPS_DOCTYPE }] : [],
  },
},

client.create(CONTACTS_DOCTYPE, contactDataFormatted)

Crash-- commented 4 years ago

You should add a key to your relationship object.

https://github.com/cozy/cozy-client/blob/fa9b08e71426281b9a7961af6831940a8fd03f84/packages/cozy-client/src/CozyClient.js#L492

So something like :

client.create(CONTACTS_DOCTYPE, contactDataFormatted, { group: {_id: groupID, _type: GROUPS_DOCTYPE }})

should work?

Merkur39 commented 4 years ago

Thanks but not working, document[name] => undefined https://github.com/cozy/cozy-client/blob/828be3c1d2eeea43701c60256dee0d794d7ccc5c/packages/cozy-client/src/CozyClient.js#L523

Crash-- commented 4 years ago

Can you share me your schema?

Merkur39 commented 4 years ago

I use this function (mine):

export const formatContact = (data: IDataProps, oldContact?: IContact | null) => {
  const { firstName, lastName, phone, email, address, company, notes, groupID } = data

  const fullName = `${firstName} ${lastName}`
  const oldContactMetadata = oldContact ? oldContact.metadata : {}

  const contact = {
    email: email ? [{ address: email }] : [],
    fullname: fullName,
    address: address ? [{ formattedAddress: address }] : [],
    phone: phone ? [{ number: phone }] : [],
    company: company,
    birthday: '',
    note: notes,
    name: {
      givenName: firstName,
      familyName: lastName,
    },
    relationships: {
      groups: {
        data: groupID ? [{ _id: groupID, _type: GROUPS_DOCTYPE }] : [],
      },
    },
    metadata: {
      ...oldContactMetadata,
      version: 1,
      cozy: true,
    },
  }
  return contact
}
Merkur39 commented 4 years ago

Je viens de mettre à jour le schema passé au CozyClient

// the documents schema, necessary for CozyClient
const doctypes = {
  contacts: {
    doctype: CONTACTS_DOCTYPE,
    attributes: {},
    relationships: {
      groups: {
        doctype: GROUPS_DOCTYPE,
        type: 'has-many',
      },
    },
  },
  groups: {
    doctype: GROUPS_DOCTYPE,
    attributes: {},
    relationships: {},
  },
...

Toujours l'erreur CozyClient.js?fdbd:822 Uncaught (in promise) TypeError: document[name].setDocument is not a function

Mais il y a du mieux je pense, voila ce que donne de document[name]: error

ptbrowne commented 4 years ago

Bonjour @Merkur39, désolé que tu rencontres ce soucis. Pour nous aider à le résoudre, est ce que tu pourrais partager un fichier/pastebin/jsbin qui permette de reproduire le problème ?

Merkur39 commented 4 years ago

Je ne suis pas sûr que ce soit possible simplement ou de savoir ce qu'il vous faudrait exactement, mais je peux vous partager les fonctions utilisées si vous voulez ?

ptbrowne commented 4 years ago

Sans test reproducible, on va avoir du mal à débugguer, il nous suffit d'avoir un fichier node simple qui reproduise le problème, quelque chose du type:

const { createClientInteractive } = require('cozy-client/dist/cli')

const schema = {}
const CONTACT_DOCTYPE = 'io.cozy.contacts'

const main = async () => {
  const client = await createClientInteractive({
    uri: 'http://cozy.tools:8080',
    schema: schema,
    scope: [CONTACT_DOCTYPE],
    oauth: {
      softwareID: 'test'
    }
  })
  const contactDataFormatted = {}
  const relationships = {}
  await client.create(CONTACT_DOCTYPE, contactDataFormatted, relationships) 
}

if (require.main === module) {
  main().catch(e => {
    console.error(e)
    process.exit(1)
  })
}
Merkur39 commented 4 years ago

Merci beaucoup, le voici rempli http://pastebin.fr/66945

Crash-- commented 4 years ago

La dernière version de CozyClient (15.3.0) , va t'interdire de créer les relationship directement en les passants en 3e argument du create.

On va plutôt préférer faire ceci :

const group = {
      _id: 'groupID',
     _type: GROUPS_DOCTYPE
    }
    const group2 = {
      _id: 'group2',
      _type: GROUPS_DOCTYPE
    }

  const contactDataFormatted = {
    _type: CONTACT_DOCTYPE,
    email: [],
    fullname: 'givenName familyName',
    address: [],
    phone: [],
    company: 'company',
    birthday: '',
    note: '',
    name: {
      givenName: 'givenName',
      familyName: 'familyName',
    },
    metadata: {
      version: 1,
      cozy: true,
    },
  }

  const contactWithRelationShip = HasMany.setHasManyItem(contactDataFormatted, 'groups', group._id, group )
  const contact = await client.save(contactWithRelationShip)

Et donc utiliser les helpers de HasMany comme setHasManyItem pour ajouter la relation. Ils sont dispos ici : https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/associations/HasMany.js#L227

Ensuite, si tu veux pouvoir faire :

const {
    data: [lastContact],
    included,
  } = await client.query(
    client
      .find(CONTACT_DOCTYPE, {})
      .sortBy([{ 'cozyMetadata.createdAt': 'desc' }])
      .limitBy(1)

et à partir de là, vouloir faire un addById pour un groupe, tu vas devoir hydrater le document :

const {
    data: [lastContact],
    included,
  } = await client.query(
    client
      .find(CONTACT_DOCTYPE, {})
      .sortBy([{ 'cozyMetadata.createdAt': 'desc' }])
      .limitBy(1)
  )
  // On hydrate le document en fonction 
  const hydratedDoc = client.hydrateDocuments('io.cozy.contacts', [lastContact]) // ou tu peux utiliser hydrateDocument() au singulier si t'es sur d'avoir qu'un seul doc 
// Add group5 to my doc 
hydratedDoc[0].groups.addById('group5')

Cette question d'hydration automatique sur le client.query on en discute ici https://github.com/cozy/cozy-client/pull/809 mais en attendant (si jamais on l'implémente...) tu as la possibilité de le faire manuellement comme ce qui est montré juste au dessus.

J'attends d'avancer un peu plus sur l'issue #809 avant de mettre à jour la doc sur les relationships

Merkur39 commented 4 years ago

Bonjour, merci pour cette solution, je vais utiliser les helpers en attendant 👍

Il serait également bien de pouvoir récupérer des données qui n'ont que tel ou tel ID d'une même relation Voir: #811