Extending ER Destinations: Integration with OneDrive (II)

To implement the logic, we will create four classes:

  1. TST2_OneDriveERDest_Settings: This class packs and unpacks the form’s data and implements the ERIFormatFileDestinationSettings interface.
  2. TST2_OneDriveERDest_OneDrive: This class retrieves the file and sends it to the TST2_OneDriveAPI. It implements the ERIFileDestination interface.
  3. TST2_OneDriveERDest_EventHandlers: This class enables and disables controls in the form and creates the lookup.
  4. TST2_OneDriveAPI: This class contains the logic for connecting to OneDrive. It is designed to be reusable for other parts of the ERP, such as ER origins.
using Microsoft.Dynamics365.LocalizationFramework;

// We implement the ERIFormatFileDestinationSettings interface. 
public class TST2_OneDriveERDest_Settings 
        implements ERIFormatFileDestinationSettings
{
    // The key and the version are used to identify the stored field values 
	// with a destination. If any point we modify the fields in the code, 
	// we should increase the version to avoid an error when unpacking.
    internal const str SettingsKey = classStr(TST2_OneDriveERDest_Settings);
    public const int CurrentVersion = 2;

    // Let's declare all the form fields in the class scope. 
	// A boolean to indicate if the destination is enabled is mandatory.
    private boolean isEnabled;
    private str connectionTableId;
    private str folderId;

    // Get and set the value of the field isEnabled. 
    [Hookable(false)]
    public boolean parmIsEnabled(boolean _value = isEnabled)
    {
        isEnabled = _value;
        return isEnabled;
    }

    // Get and set the value of the field connectionTableId. 
    [Hookable(false)]
    public str parmConnectionTableId(str _value = connectionTableId)
    {
        connectionTableId = _value;
        return connectionTableId;
    }

    // Get and set the value of folderId. 
    [Hookable(false)]
    public str parmFolderId(str _value = folderId)
    {
        folderId = _value;
        return folderId;
    }

    [Hookable(false)]
    public void setEnabled(boolean _value)
    {
        isEnabled = _value;
    }

     
    [Hookable(false)]
    public boolean isEnabled()
    {
        return isEnabled;
    }

    // Descriptive name (we should be using labels instead). 
    [Hookable(false)]
    public str getName()
    {
        return 'OneDrive';
    }

    // This is a mandatory method. In some implementations, MS uses it 
	// to throw errors based on conditions.
    [Hookable(false)]
    public void validate()
    {
    }

    // Creates an instance of the class responsible for sending the files.
    // Sets the parameters.
	// Setting isEnabled is not a necessary parameter.
    [Hookable(false)]
    public ERIFileDestination createDestination(
                ERDestinationExecutionContext _destinationContext, 
                boolean _isGrouped)
    {
        TST2_OneDriveERDest_OneDrive ret = new TST2_OneDriveERDest_OneDrive();
        ret.parmConnectionTableId(this.parmConnectionTableId());
        ret.parmFolderId(this.parmFolderId());
        return ret;
    }

    [Hookable(false)]
    public str getKey()
    {
        return SettingsKey;
    }

    // Serialize the fields into a container
    [Hookable(false)]
    public container pack()
    {
        return [CurrentVersion, isEnabled, folderId, connectionTableId];
    }

    // Deserialize the fields from a container
    [Hookable(false)]
    public boolean unpack(container packedClass)
    {
        int version = RunBase::getVersion(packedClass);
        switch (version)
        {
            case CurrentVersion:
                [version, isEnabled, folderId, connectionTableId] 
                    = packedClass;
                return true;
            default:
                return false;
        }
    }
    
    // Creates a new instance of the settings object from a container.    
    public static TST2_OneDriveERDest_Settings create(
                                            container _packedClass)
    {
        var ret = new TST2_OneDriveERDest_Settings();
        ret.unpack(_packedClass);
        return ret;
    }
}
using Microsoft.Dynamics365.LocalizationFramework;
 
internal final class TST2_OneDriveERDest_OneDrive implements ERIFileDestination
{    
    // The fields needed for the connection
    private str connectionTableId;
    private str folderId;
 
 
    //Get and set the parameter connectionTableId
    public str parmConnectionTableId(str _value = connectionTableId)
    {
        connectionTableId = _value;
        return connectionTableId;
    }
 
    //Get and set the parameter folderId
    public str parmFolderId(str _value = folderId)
    {
        folderId = _value;
        return folderId;
    }
 
    // All the OneDrive API logic is in another class. Here, we instantiate it
	// and pass the stream and folder ID. We set the stream position to 0.
    [Hookable(false)]
    public System.IO.Stream saveFile(System.IO.Stream _stream, str _fileName)
    {
        TST2_OneDriveAPI OneDriveAPI;

        OneDriveAPI = new TST2_OneDriveAPI(connectionTableId);
        _stream.Position = 0;


        OneDriveAPI.sendFile(_stream, folderId, _fileName);

        return _stream;
    }
 
    // Mandatory interface method
    [Hookable(false)]
    public System.IO.Stream newFileStream(str _filePath)
    {
        return new System.IO.MemoryStream();
    } 
}
// Event handlers for enabling and disabling fields in the destination 
// form and creating a lookup
public class TST2_OneDriveERDest_EventHandlers
{
    [PostHandlerFor(formStr(ERFormatDestinationSettings), 
		formMethodStr(ERFormatDestinationSettings, init))]

    // Populate the fields on opening, enabling and disabling them 
    // depending on whether the destination is enabled.
    public static void ERFormatDestinationSettings_Post_init(
										XppPrePostArgs args)
    {
        FormRun formRun = args.getThis();
        ERIFormatFileDestinationSettingsStorage settingsStorage = 
			args.getThis();
        var settings = 
			TST2_OneDriveERDest_EventHandlers::getSaveOneDriveSettings(
				settingsStorage);

        FormCheckBoxControl enabledControl = formRun.design().controlName(
            formControlStr(ERFormatDestinationSettings, TST2_OneDrive_Enable));
        enabledControl.checked(settings.isEnabled());

        FormStringControl connectionTableId = formRun.design().controlName(
            formControlStr(ERFormatDestinationSettings, TST2_OneDrive_Connection));
        connectionTableId.text(settings.parmConnectionTableId());
        connectionTableId.enabled(settings.isEnabled());

        FormStringControl folderId = formRun.design().controlName(
            formControlStr(ERFormatDestinationSettings, TST2_OneDrive_FolderId));
        folderId.text(settings.parmFolderId());
        folderId.enabled(settings.isEnabled());
    }

    // Clicking the enable checkbox enables or disables the other fields.
    [FormControlEventHandler(formControlStr(
		ERFormatDestinationSettings, TST2_OneDrive_Enable), 
        FormControlEventType::Clicked)]
    public static void TST2_OneDrive_Enable(
		FormControl sender, FormControlEventArgs e)
    {
        FormRun element  = sender.formRun();
        FormCheckBoxControl control = element.design().controlName(
			formControlStr(ERFormatDestinationSettings, TST2_OneDrive_Enable));
        Boolean checked = control.checked();

        FormStringControl connectionTableId = element.design().controlName(
			formControlStr(ERFormatDestinationSettings, 
				TST2_OneDrive_Connection));
        connectionTableId.Enabled(checked);

        FormStringControl folderId = element.design().controlName(
			formControlStr(ERFormatDestinationSettings, TST2_OneDrive_FolderId));
        folderId.Enabled(checked);
    }

    // On closing the form saves the new values
    [PreHandlerFor(formStr(ERFormatDestinationSettings), formMethodStr(
		ERFormatDestinationSettings, closeOk))]
    public static void ERFormatDestinationSettings_Pre_closeOk(XppPrePostArgs args)
    {
        FormRun formRun = args.getThis();
        ERIFormatFileDestinationSettingsStorage settingsStorage = 
			args.getThis();
        var settings = 
			TST2_OneDriveERDest_EventHandlers::getSaveOneDriveSettings(settingsStorage);

        FormCheckBoxControl enabledControl = formRun.design().controlName(
												formControlStr(
													ERFormatDestinationSettings, 
													TST2_OneDrive_Enable));
        settings.parmIsEnabled(enabledControl.checked());

        FormStringControl connectionTableId = formRun.design().controlName(
												formControlStr(
													ERFormatDestinationSettings, 
													TST2_OneDrive_Connection));
        settings.parmConnectionTableId(connectionTableId.text());

        FormStringControl folderId = formRun.design().controlName(formControlStr(
														ERFormatDestinationSettings, 
														TST2_OneDrive_FolderId));
        settings.parmFolderId(folderId.text());
    }

    // Transform the text field TST2_OneDrive_Connection into a lookup 
    // to the table containing connection information and passwords.
    [FormControlEventHandler(formControlStr(ERFormatDestinationSettings, 
                TST2_OneDrive_Connection), FormControlEventType::Lookup)]
    public static void TST2_OneDrive_Connection_OnLookup(
                                        FormControl sender, 
                                        FormControlEventArgs e)
    {   
        Query query = new Query();
        QueryBuildDataSource dataSource = query.addDataSource(
											tableNum(TST2_OneDriveCon));
        dataSource.fields().addField(fieldNum(TST2_OneDriveCon, Id));                
                        
        var lookup = SysTableLookup::newParameters(
			tableNum(TST2_OneDriveCon), sender);
        lookup.parmQuery(query);
        lookup.addLookupfield(fieldNum(TST2_OneDriveCon, Id), true);        
        lookup.performFormLookup();
    }

    // Creates a settings instance used by 
    // ERFormatDestinationSettings_Pre_closeOk and 
    // ERFormatDestinationSettings_Post_init for interaction.
    private static TST2_OneDriveERDest_Settings getSaveOneDriveSettings(
		ERIFormatFileDestinationSettingsStorage _settingsStorage)
    {
        TST2_OneDriveERDest_Settings ret = _settingsStorage.getSettingsByKey(
                                            TST2_OneDriveERDest_Settings::SettingsKey);
        if (ret == null)
        {
            ret = new TST2_OneDriveERDest_Settings();
            _settingsStorage.addSettings(ret);
        }
        return ret;
    }
}

We won’t write the final class now. I’ll explain it in the next and last post of this series. For now, we will show an info message to verify it’s working.

class TST2_OneDriveAPI
{
    public void new(str _conTable)
    {
        Info(strFmt("new method not implemented %1",_conTable));
    }

    public void sendFile(System.IO.Stream _stream  ,str _filename)
    {
        Info(strFmt("sendFiles method not implemented", _filename));
    }

}

After compiling, we should see the destinations with a lookup for the connection. The enabled button should make the fields editable or non-editable. When closing and reopening the form, the entered information should remain.

On executing it, we should see the info messages of TST2_OneDriveAPI.


Posted

in

, , , ,

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *