Difference between revisions of "CSV Exporting"

From SocialStack
 
Line 13: Line 13:
= CSV endpoint usage =
= CSV endpoint usage =


Any /list endpoint is now available as /list.csv as well. For example, navigating to http://yoursite.com/v1/user/list.csv will provide a CSV of users, provided you have access to the endpoint through the user_list [[Permissions|permission grant]].
Any /list endpoint is now available as /list.csv as well. For example, navigating to https://yoursite.com/v1/user/list.csv will provide a CSV of users, provided you have access to the endpoint through the user_list [[Permissions|permission grant]].


From the frontend this can then be done in a few ways:
From the frontend this can then be done in a few ways:

Latest revision as of 13:24, 4 October 2022

Sometimes it is useful to have your site data exportable as a CSV. Due to the generic way SocialStack handles database content, exporting a CSV requires little to get it going.

Installing CSV Exporter

Install the API module:

socialstack install Api/CsvExport

And that's it! You can now use the .csv endpoints

CSV endpoint usage

Any /list endpoint is now available as /list.csv as well. For example, navigating to https://yoursite.com/v1/user/list.csv will provide a CSV of users, provided you have access to the endpoint through the user_list permission grant.

From the frontend this can then be done in a few ways:

  • As a simple link, often from a custom admin panel component:
<a href='/v1/user/list.csv' target='_blank'>Download user data</a>
  • Via webRequest (or fetch):
import webRequest from 'UI/Functions/WebRequest';

// As text:
webRequest('user/list.csv', null, {rawText: true}).then(response => {
     // response.text
});

// As a blob (binary):
webRequest('user/list.csv', null, {blob: true}).then(response => {
     // response.blob
});

// It supports {where: {}} as well as query/ args just like regular list endpoints too.
webRequest('user/list.csv', {query: 'AvatarRef!=?', args: ['']}, {rawText: true}).then(response => {
     // response.text
});

Omitting or renaming fields

By default the CSV will include all the fields which would otherwise be present in the JSON. This is because it is based on the same field visibility mechanics as the regular JSON endpoints and does watch out for [JsonIgnore] attributes as well as [CsvIgnore] attributes. When the CSV schema is loaded, it will pass each field through the BeforeCsvGettable event, similar to the BeforeGettable field event, which you can use to modify fields in a wide range of ways:


using Api.Startup;
using Api.Contexts;
using Api.CsvExport;
using Api.Eventing;
using System.Threading.Tasks;
using Api.Users;


namespace Api.MyCsvEvents
{
    /// <summary>
    /// EventListeners are instanced automatically during startup.
    /// The class and namespace can be anything - it just needs to have the attribute.
    /// </summary>
    [EventListener]
    public partial class CsvEventSetup
    {
        /// <summary>
        /// EventListeners are instanced automatically during startup.
        /// </summary>
        public CsvEventSetup()
        {
            Events.User.BeforeCsvGettable.AddEventListener((Context context, CsvFieldMap<User> csvField) => {
                if(csvField == null)
                {
                    // something else already filtered it out. Do nothing.
                    return new ValueTask<CsvFieldMap<User>>(csvField);
                }

                if(csvField.Name == "RevisionId")
                {
                    // returning a null will effectively remove this field from the CSV.
                    csvField = null;
                }
                else if(csvField.Name == "Id")
                {
                    // Changing the name of the field will rename it in the CSV.
                    csvField.Name = "Socialstack Site Id";
                }
                
                // can also set csvField.AdvancedHandler to specify a value rewrite function (see below)
                
                return new ValueTask<CsvFieldMap<User>>(csvField);
            });
        }
    }
}

Field value rewriting

If you would like to rewrite the value that actually appears in the CSV, use the above technique to obtain the field you want to rewrite the value for and then set an AdvancedHandler on it, like so:

// Non-async:
csvField.AdvancedHandler = (User user, CsvWriter writer) => {
    writer.WriteField("#" + user.Id);
    return new ValueTask();
};

// Async:
csvField.AdvancedHandler = async (User user, CsvWriter writer) => {
    // ..do something slow..

    writer.WriteField("#" + user.Id);
};