Smart collection pagination

I’ve created a smart collection :

const { collection } = require('forest-express-sequelize');

collection('sageProviders', {
  fields: [{
    field: 'id',
    type: 'String',
    get: record => record.matricule
  }, {
    field: 'matricule',
    type: 'String',
  }, {
    field: 'siret',
    type: 'String'
  }, {
    field: 'raison_sociale',
    type: 'String'
  }, {
    field: 'site_adresse',
    type: 'String'
  }, {
    field: 'site_ville',
    type: 'String'
  }, {
    field: 'site_codepostal',
    type: 'String'
  }, {
    field: 'telephone',
    type: 'String'
  }, {
    field: 'email',
    type: 'String'
  }, {
    field: 'bic',
    type: 'String'
  }, {
    field: 'iban',
    type: 'String'
  }, {
    field: 'street_number',
    type: 'String'
  }, {
    field: 'street',
    type: 'String'
  }, {
    field: 'domiciliation',
    type: 'String'
  }]
});

and its GET route :

// Get a list of sageProviders
router.get('/sageProviders', permissionMiddlewareCreator.list(), (request, response, next) => {
  const recordSerializer = new RecordSerializer({ name: 'sageProviders' });
  const params = {
    provider_name: '',
    siret: '',
    matricule: ''
  };

  axios.get(
    `${API_URL}/forest_admin/sage_providers`, {
    headers: {
      'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
      'X-CURRENT-USER-EMAIL': request.user.email
    },
    params
  }).then(async res => {
    response.send(await recordSerializer.serialize(res.data));
  }).catch(err => {
    response.status(400).send({ error: err.response.data.error.message });
  });
});

The API returns literally thousands of result, so I need to fix the pagination because the table view makes my browser to crash. So far I haven’t found an explicit FA doc about how the table pagination works.

Hi @JeremyV :wave:

Indeed, we do not have any documentation around the smart collection pagination.
However, all the required parameters you may need to paginate your results are actually sent within the GET request, as you can see on the screenshot below - even for smart collections.

.

These parameters should be sent for each list/table view request, so you should be able to handle pagination easily.

Let me know if that helps :pray:

1 Like

Indeed I managed to deal with it, for future reference :

// Get a list of sageProviders
router.get('/sageProviders', permissionMiddlewareCreator.list(), (request, response, next) => {
  const recordSerializer = new RecordSerializer({ name: 'sageProviders' });
  const params = {
    provider_name: '',
    siret: '',
    matricule: ''
  };

  const number = request.query.page.number;
  const size = request.query.page.size;

  axios.get(
    `${API_URL}/forest_admin/sage_providers`, {
    headers: {
      'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
      'X-CURRENT-USER-EMAIL': request.user.email
    },
    params
  }).then(async res => {
    response.send({
      ...(
        await recordSerializer.serialize(
          res.data.slice(
            (number * size) - (size - 1),
            number * size
          )
        )
      ),
      meta: {
        count: res.data.length
      }
    });
  }).catch(err => {
    response.status(400).send({ error: err.response.data.error.message });
  });
});
1 Like

I made a bit cleaner:

// Get a list of sageProviders
router.get('/sageProviders', permissionMiddlewareCreator.list(), (request, response, next) => {
  const recordSerializer = new RecordSerializer({ name: 'sageProviders' });
  const params = {
    provider_name: '',
    siret: '',
    matricule: ''
  };

  const number = request.query.page.number;
  const size = request.query.page.size;
  const end = number * size;
  const begin = end - (size - 1);

  axios.get(
    `${API_URL}/forest_admin/sage_providers`, {
    headers: {
      'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
      'X-CURRENT-USER-EMAIL': request.user.email
    },
    params
  }).then(async res => {
    response.send({
      ...(
        await recordSerializer.serialize(
          res.data.slice(begin, end)
        )
      ),
      meta: {
        count: res.data.length
      }
    });
  }).catch(err => {
    response.status(400).send({ error: err.response.data.error.message });
  });
});

Hello @JeremyV :wave:

I may have a more comprehensive example. (@JeremyV I think you miss one record per page with your implementation → look at your begin value)

// Get query parameters information
const pageSize = Number(request?.query?.page?.size) || 20;
const page = Number(request?.query?.page?.number) || 1;

const from = (page - 1) * pageSize;
const to = from + pageSize;
// equivalent to const to = page * pageSize;

...

const dataToReturn = data.slice(from, to);

...

This way imagine 10 records per page.

  • Page 1 → data.slice(0, 10) gives records 0 to 9 from the array.
  • Page 2 → data.slice(10, 20) gives records 10 to 19 from the array.

Cheers,
Morgan

1 Like

Good thing that my client hasn’t noticed yet !

Thanks @morganperre

Although my plain JS doesn’t tolerate this notation :
request?.query?.page?.size

Hello @JeremyV,

Sorry it’s optional chaining syntaxe available in Node v14. And to be honest it’s not required to use this here. :handshake:

Morgan