Webiant Logo Webiant Logo
  1. No results found.

    Try your search with a different keyword or use * as a wildcard.

Configure.cshtml

@model ConfigurationModel

@{
    Layout = "_ConfigurePlugin";
    NopHtml.SetActiveMenuItemSystemName(ZettleDefaults.SystemName);

    var signUpUrl = $"https://my.zettle.com/apps/api-keys?name={ZettleDefaults.ApplicationName}&scopes=READ:FINANCE%20READ:PURCHASE%20READ:USERINFO%20READ:PRODUCT%20WRITE:PRODUCT&utm_source=local_partnership&utm_medium=ecommerce&utm_campaign=nopcommerce";
}

<form asp-controller="ZettleAdmin" asp-action="Configure" method="post" id="configuration-form">
    <div class="cards-group">
        <div class="card card-default no-margin">

            <div class="card-header">
                @T("Plugins.Misc.Zettle.Credentials")
            </div>

            <div class="card-body">
                <p>
                    To enable this plugin, you'll need to:<br />
                    <br />
                    1. Go to your <a href="@signUpUrl" target="_blank">merchant account</a>.<br />
                    2. Review the information and click <b>Create key</b>. A client ID will be created together with the API key.<br />
                    3. On the <b>Create API key page</b>, click <b>Copy key</b> and paste it into the field on this plugin configuration page, do the same for Client ID.<br />
                    <em>Note: The API key will be displayed only once, so make sure to make a copy of it.</em><br />
                </p>
                <div class="form-group row">
                    <div class="col-md-3">
                        <div class="label-wrapper">
                            <label class="col-form-label">
                                @T("Plugins.Misc.Zettle.Credentials.Status")
                            </label>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="form-text-row">@T($"Plugins.Misc.Zettle.Credentials.{(Model.Connected ? "Connected" : "Disconnected")}")</div>
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-md-9 offset-md-3">
                        @if (Model.Connected)
                        {
                            <button type="submit" name="revoke" class="btn btn-danger">@T("Plugins.Misc.Zettle.Credentials.Revoke")</button>
                        }
                        else
                        {
                            <a href="@signUpUrl" target="_blank" class="btn bg-olive">@T("Plugins.Misc.Zettle.Credentials.SignUp")</a>
                        }
                    </div>
                </div>
                @if (Model.Connected)
                {
                    @if (!Model.Account.Accepted)
                    {
                        <div class="form-group row">
                            <div class="col-md-9 offset-md-3">
                                <div class="form-text-row">@T("Plugins.Misc.Zettle.Account.Pending", Model.Account.CustomerStatus, "https://www.zettle.com/gb/help/articles/1113715-confirm-your-identity")</div>
                            </div>
                        </div>
                    }
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Account.Name" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row">@Model.Account.Name</div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Account.Currency" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row">@Model.Account.Currency</div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Account.TaxationType" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row">@Model.Account.TaxationType</div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Account.TaxationMode" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row">@Model.Account.TaxationMode</div>
                        </div>
                    </div>
                }
                <div class="form-group row">
                    <div class="col-md-3">
                        <nop-label asp-for="ClientId" />
                    </div>
                    <div class="col-md-9">
                        <nop-editor asp-for="ClientId" />
                        <span asp-validation-for="ClientId"></span>
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-md-3">
                        <nop-label asp-for="ApiKey" />
                    </div>
                    <div class="col-md-9">
                        <nop-editor asp-for="ApiKey" asp-required="@(!string.IsNullOrEmpty(Model.ClientId))" html-attributes="@(new { value = Model.ApiKey })" />
                        <span asp-validation-for="ApiKey"></span>
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-md-3">
                        <nop-label asp-for="DisconnectOnUninstall" />
                    </div>
                    <div class="col-md-9">
                        <nop-editor asp-for="DisconnectOnUninstall" />
                        <span asp-validation-for="DisconnectOnUninstall"></span>
                    </div>
                </div>
                <div class="form-group row">
                    <div class="col-md-9 offset-md-3">
                        <button type="submit" name="credentials" class="btn btn-primary">@T("Admin.Common.Save")</button>
                    </div>
                </div>
            </div>
        </div>

        @if (Model.Connected)
        {
            <div class="card card-default no-margin">
                <div class="card-header">
                    @T("Plugins.Misc.Zettle.Sync")
                </div>

                <div class="card-body">
                    <p>
                        The PayPal Zettle Go POS application will display product items that have been set up in the PayPal Zettle product library.<br />
                        Here you can define products from your nopCommerce catalog to be imported into PayPal Zettle product library and keep them synchronized across changes and updates.<br />
                        The product library consists of products and their variants (in nopCommerce they are product attribute combinations). For correct synchronization, you have to fill in SKUs for products and combinations.<br />
                        <br />
                        It's recommneded to keep the number of items in the product library below 10,000.<br />
                        <br />
                        You can only assign up to 99 variants (product attribute combinations) to a product. This means that you can specify a maximum of 3 product attributes for a product.<br />
                        If there are multiple product attributes, multiply the number of values of each attribute to get the total number of product variants.<br />
                        <em>For example, if you have 3 product attributes (Color, Size and Print) and the product attribute values for each attribute are 4 (Red, Blue, Green, Orange), 3 (9, 10, 11), and 2 (Animal, Floral) respectively, then the total number of product variants is 24 (4x3x2).</em><br />
                        <br />
                        Images are important parts of a product library. A product can have one single associated image.<br />
                        If you have enabled image synchronization, make sure that only ASCII characters are used in their names, the size must be smaller than 5 MB but bigger than 50*50 pixels.<br />
                    </p>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="AutoSyncEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="AutoSyncEnabled" />
                            <span asp-validation-for="AutoSyncEnabled"></span>
                        </div>
                    </div>
                    <nop-nested-setting asp-for="AutoSyncEnabled">
                        <div class="form-group row">
                            <div class="col-md-3">
                                <nop-label asp-for="AutoSyncPeriod" />
                            </div>
                            <div class="col-md-9">
                                <nop-editor asp-for="AutoSyncPeriod" />
                                <span asp-validation-for="AutoSyncPeriod"></span>
                            </div>
                        </div>
                    </nop-nested-setting>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="DeleteBeforeImport" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="DeleteBeforeImport" />
                            <span asp-validation-for="DeleteBeforeImport"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="SyncEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="SyncEnabled" />
                            <span asp-validation-for="SyncEnabled"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="PriceSyncEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="PriceSyncEnabled" />
                            <span asp-validation-for="PriceSyncEnabled"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="ImageSyncEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="ImageSyncEnabled" />
                            <span asp-validation-for="ImageSyncEnabled"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="InventoryTrackingEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="InventoryTrackingEnabled" />
                            <span asp-validation-for="InventoryTrackingEnabled"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="DefaultTaxEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="DefaultTaxEnabled" />
                            <span asp-validation-for="DefaultTaxEnabled"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="DiscountSyncEnabled" />
                        </div>
                        <div class="col-md-9">
                            <nop-editor asp-for="DiscountSyncEnabled" />
                            <span asp-validation-for="DiscountSyncEnabled"></span>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-9 offset-md-3">
                            <button type="submit" name="sync" class="btn btn-primary">@T("Admin.Common.Save")</button>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-12">
                            &nbsp;
                        </div>
                    </div>

                    <button type="submit" id="add-record" onclick="javascript:OpenWindow('@(Url.Action("ProductToSync", "ZettleAdmin", new { btnId = "recordsUpdate", formId = "configuration-form" }))', 800, 800, true); return false;" class="btn bg-olive ml-1">
                        <i class="fas fa-square-plus"></i>
                        @T("Plugins.Misc.Zettle.Sync.AddProduct")
                    </button>
                    <button type="submit" id="recordsUpdate" style="display: none"></button>

                    <button type="button" id="delete-selected" class="btn btn-danger ml-1">
                        <i class="far fa-trash-can"></i>
                        @T("Plugins.Misc.Zettle.Sync.DeleteSelected")
                    </button>
                    <nop-action-confirmation asp-button-id="delete-selected" />

                    @await Html.PartialAsync("Table", new DataTablesModel
                    {
                        Name = "records-grid",
                        UrlRead = new DataUrl("SyncRecordList", "ZettleAdmin", null),
                        UrlUpdate = new DataUrl("SyncRecordUpdate", "ZettleAdmin", null),
                        Length = Model.SyncRecordSearchModel.PageSize,
                        LengthMenu = Model.SyncRecordSearchModel.AvailablePageSizes,
                        ColumnCollection = new List<ColumnProperty>
                        {
                            new ColumnProperty(nameof(SyncRecordModel.Id))
                            {
                                IsMasterCheckBox = true,
                                Render = new RenderCheckBox("records-checkbox"),
                                ClassName =  NopColumnClassDefaults.CenterAll,
                                Width = "50",
                            },
                            new ColumnProperty(nameof(SyncRecordModel.ProductName))
                            {
                                Title = T("Plugins.Misc.Zettle.Sync.Fields.Product").Text,
                                Render = new RenderLink(new DataUrl("~/Admin/Product/Edit/", nameof(SyncRecordModel.ProductId)))
                            },
                            new ColumnProperty(nameof(SyncRecordModel.Active))
                            {
                                Title = T("Plugins.Misc.Zettle.Sync.Fields.Active").Text,
                                Width = "80",
                                ClassName = NopColumnClassDefaults.CenterAll,
                                Render = new RenderBoolean(),
                                Editable = true,
                                EditType = EditType.Checkbox
                            },
                            new ColumnProperty(nameof(SyncRecordModel.PriceSyncEnabled))
                            {
                                Title = T("Plugins.Misc.Zettle.Sync.Fields.PriceSyncEnabled").Text,
                                Width = "80",
                                ClassName = NopColumnClassDefaults.CenterAll,
                                Render = new RenderBoolean(),
                                Editable = true,
                                EditType = EditType.Checkbox
                            },
                            new ColumnProperty(nameof(SyncRecordModel.ImageSyncEnabled))
                            {
                                Title = T("Plugins.Misc.Zettle.Sync.Fields.ImageSyncEnabled").Text,
                                Width = "80",
                                ClassName = NopColumnClassDefaults.CenterAll,
                                Render = new RenderBoolean(),
                                Editable = true,
                                EditType = EditType.Checkbox
                            },
                            new ColumnProperty(nameof(SyncRecordModel.InventoryTrackingEnabled))
                            {
                                Title = T("Plugins.Misc.Zettle.Sync.Fields.InventoryTrackingEnabled").Text,
                                Width = "80",
                                ClassName = NopColumnClassDefaults.CenterAll,
                                Render = new RenderBoolean(),
                                Editable = true,
                                EditType = EditType.Checkbox
                            },
                            new ColumnProperty(nameof(SyncRecordModel.UpdatedDate))
                            {
                                Title = T("Plugins.Misc.Zettle.Sync.Fields.UpdatedDate").Text,
                                Width = "140",
                                Render = new RenderDate()
                            },
                            new ColumnProperty(nameof(SyncRecordModel.Id))
                            {
                                Title = T("Admin.Common.Edit").Text,
                                Width = "100",
                                ClassName =  NopColumnClassDefaults.Button + " column-edit",
                                Render = new RenderButtonsInlineEdit()
                            }
                        }
                    })

                    <script>
                        $(function() {
                            $('#recordsUpdate').click(function () {
                                updateTable('#records-grid');
                                return false;
                            });

                            $('#start-sync-action-confirmation-submit-button').on('click', function () {
                                $.ajax({
                                    cache: false,
                                    type: 'GET',
                                    url: '@(Url.Action("SyncStart", "ZettleAdmin"))',
                                    error: function (jqXHR, textStatus, errorThrown) {
                                        showAlert('sync-failed', errorThrown);
                                    },
                                    complete: function (jqXHR, textStatus) {
                                        window.location = window.location.href;
                                    }
                                });
                                $('#start-sync-action-confirmation').modal('toggle');
                                return false;
                            });

                            $('#delete-selected-action-confirmation-submit-button').on('click', function () {
                                var postData = {
                                    selectedIds: selectedIds
                                };
                                addAntiForgeryToken(postData);
                                $.ajax({
                                    cache: false,
                                    type: 'POST',
                                    url: '@(Url.Action("SyncRecordDelete", "ZettleAdmin"))',
                                    data: postData,
                                    traditional: true,
                                    error: function (jqXHR, textStatus, errorThrown) {
                                        showAlert('delete-selected-failed', errorThrown);
                                    },
                                    complete: function (jqXHR, textStatus) {
                                        if (jqXHR.status === 204)
                                        {
                                            showAlert('nothing-selected-alert', '@T("Admin.Common.Alert.NothingSelected")');
                                            return;
                                        }
                                        updateTable('#records-grid');
                                    }
                                });
                                $('#delete-selected-action-confirmation').modal('toggle');
                                return false;
                            });
                        });
                    </script>
                </div>

                <div class="card-footer">
                    <button type="button" id="start-sync" class="btn btn-primary">
                        @T("Plugins.Misc.Zettle.Sync.Start")
                    </button>
                    <nop-action-confirmation asp-button-id="start-sync" asp-additional-confirm="Plugins.Misc.Zettle.Sync.Start.Confirm" />
                </div>
            </div>
        }

        @if (!string.IsNullOrEmpty(Model.Import.State))
        {
            <div class="card card-default no-margin">
                <div class="card-header">
                    @T("Plugins.Misc.Zettle.Sync.Last")
                </div>

                <div class="card-body">
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Import.StartDate" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row" id="sync-start-date">@Model.Import.StartDate?.ToString("G")</div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Import.Items" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row" id="sync-items">@Model.Import.Items</div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Import.State" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row" id="sync-state">@Model.Import.State</div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <nop-label asp-for="Import.EndDate" />
                        </div>
                        <div class="col-md-9">
                            <div class="form-text-row" id="sync-end-date">@Model.Import.EndDate?.ToString("G")</div>
                        </div>
                    </div>
                </div>

                @if (Model.Import.Active)
                {
                    <script>
                        $(function() {
                            $('#start-sync').prop('disabled', true);
                            updateSyncState();
                        });

                        function updateSyncState() {
                            setTimeout(function () {
                                $.ajax({
                                    cache: false,
                                    type: 'GET',
                                    url: '@(Url.Action("SyncUpdate", "ZettleAdmin"))',
                                    success: function (data, textStatus, jqXHR) {
                                        if (data.Completed) {
                                            $('#start-sync').prop('disabled', false);
                                            window.location = window.location.href;
                                        }
                                        else {
                                            $('#sync-start-date').text(data.StartDate);
                                            $('#sync-items').text(data.Items);
                                            $('#sync-state').text(data.State);
                                            updateSyncState();
                                        }
                                    },
                                    error: function (jqXHR, textStatus, errorThrown) {
                                        showAlert('sync-failed', errorThrown);
                                        updateSyncState();
                                    }
                                });
                            }, 10000);
                        }
                    </script>
                }
            </div>
        }
    </div>
</form>

<nop-alert asp-alert-id="delete-selected-failed" />
<nop-alert asp-alert-id="nothing-selected-alert" />
<nop-alert asp-alert-id="sync-failed" />