mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-29 10:24:20 +01:00
show recapitulative of payzen settings
This commit is contained in:
parent
63c81b82c1
commit
667f6f6229
@ -22,16 +22,26 @@ export default class SettingAPI {
|
||||
return SettingAPI.toBulkMap(res?.data?.settings);
|
||||
}
|
||||
|
||||
async isPresent (name: SettingName): Promise<boolean> {
|
||||
const res: AxiosResponse = await apiClient.get(`/api/settings/is_present/${name}`);
|
||||
return res?.data?.isPresent;
|
||||
}
|
||||
|
||||
static get (name: SettingName): IWrapPromise<Setting> {
|
||||
const api = new SettingAPI();
|
||||
return wrapPromise(api.get(name));
|
||||
}
|
||||
|
||||
static query(names: Array<SettingName>): IWrapPromise<Map<SettingName, any>> {
|
||||
static query (names: Array<SettingName>): IWrapPromise<Map<SettingName, any>> {
|
||||
const api = new SettingAPI();
|
||||
return wrapPromise(api.query(names));
|
||||
}
|
||||
|
||||
static isPresent (name: SettingName): IWrapPromise<boolean> {
|
||||
const api = new SettingAPI();
|
||||
return wrapPromise(api.isPresent(name));
|
||||
}
|
||||
|
||||
private static toSettingsMap(data: Object): Map<SettingName, any> {
|
||||
const dataArray: Array<Array<string | any>> = Object.entries(data);
|
||||
const map = new Map();
|
||||
|
@ -16,16 +16,19 @@ interface FabInputProps {
|
||||
disabled?: boolean,
|
||||
required?: boolean,
|
||||
debounce?: number,
|
||||
readOnly?: boolean,
|
||||
type?: 'text' | 'date' | 'password' | 'url' | 'time' | 'tel' | 'search' | 'number' | 'month' | 'email' | 'datetime-local' | 'week',
|
||||
}
|
||||
|
||||
export const FabInput: React.FC<FabInputProps> = ({ id, onChange, defaultValue, icon, className, disabled, type, required, debounce, addOn, addOnClassName }) => {
|
||||
export const FabInput: React.FC<FabInputProps> = ({ id, onChange, defaultValue, icon, className, disabled, type, required, debounce, addOn, addOnClassName, readOnly }) => {
|
||||
const [inputValue, setInputValue] = useState<any>(defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
if (!inputValue) {
|
||||
setInputValue(defaultValue);
|
||||
onChange(defaultValue);
|
||||
if (typeof onChange === 'function') {
|
||||
onChange(defaultValue);
|
||||
}
|
||||
}
|
||||
}, [defaultValue]);
|
||||
|
||||
@ -46,7 +49,7 @@ export const FabInput: React.FC<FabInputProps> = ({ id, onChange, defaultValue,
|
||||
/**
|
||||
* Debounced (ie. temporised) version of the 'on change' callback.
|
||||
*/
|
||||
const debouncedOnChange = useCallback(_debounce(onChange, debounce), [onChange, debounce]);
|
||||
const debouncedOnChange = debounce ? useCallback(_debounce(onChange, debounce), [onChange, debounce]) : null;
|
||||
|
||||
/**
|
||||
* Handle the change of content in the input field, and trigger the parent callback, if any
|
||||
@ -66,11 +69,10 @@ export const FabInput: React.FC<FabInputProps> = ({ id, onChange, defaultValue,
|
||||
return (
|
||||
<div className={`fab-input ${className ? className : ''}`}>
|
||||
{hasIcon() && <span className="fab-input--icon">{icon}</span>}
|
||||
<input id={id} type={type} className="fab-input--input" value={inputValue} onChange={handleChange} disabled={disabled} required={required} />
|
||||
<input id={id} type={type} className="fab-input--input" value={inputValue} onChange={handleChange} disabled={disabled} required={required} readOnly={readOnly} />
|
||||
{hasAddOn() && <span className={`fab-input--addon ${addOnClassName ? addOnClassName : ''}`}>{addOn}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
FabInput.defaultProps = { type: 'text', debounce: 0 };
|
||||
|
||||
|
@ -125,7 +125,7 @@ const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys })
|
||||
<fieldset>
|
||||
<legend>{t('app.admin.invoices.payment.client_keys')}</legend>
|
||||
<div className="payzen-public-input">
|
||||
<label htmlFor="payzen_public_key">{ t('app.admin.invoices.payment.public_key') } *</label>
|
||||
<label htmlFor="payzen_public_key">{ t('app.admin.invoices.payment.payzen.payzen_public_key') } *</label>
|
||||
<FabInput id="payzen_public_key"
|
||||
icon={<i className="fas fa-info" />}
|
||||
defaultValue={settings.get(SettingName.PayZenPublicKey)}
|
||||
@ -142,7 +142,7 @@ const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys })
|
||||
{hasApiAddOn() && <span className={`fieldset-legend--addon ${restApiAddOnClassName ? restApiAddOnClassName : ''}`}>{restApiAddOn}</span>}
|
||||
</legend>
|
||||
<div className="payzen-api-user-input">
|
||||
<label htmlFor="payzen_username">{ t('app.admin.invoices.payment.username') } *</label>
|
||||
<label htmlFor="payzen_username">{ t('app.admin.invoices.payment.payzen.payzen_username') } *</label>
|
||||
<FabInput id="payzen_username"
|
||||
type="number"
|
||||
icon={<i className="fas fa-user-alt" />}
|
||||
@ -152,7 +152,7 @@ const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys })
|
||||
required />
|
||||
</div>
|
||||
<div className="payzen-api-password-input">
|
||||
<label htmlFor="payzen_password">{ t('app.admin.invoices.payment.password') } *</label>
|
||||
<label htmlFor="payzen_password">{ t('app.admin.invoices.payment.payzen.payzen_password') } *</label>
|
||||
<FabInput id="payzen_password"
|
||||
icon={<i className="fas fa-key" />}
|
||||
defaultValue={settings.get(SettingName.PayZenPassword)}
|
||||
@ -161,7 +161,7 @@ const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys })
|
||||
required />
|
||||
</div>
|
||||
<div className="payzen-api-endpoint-input">
|
||||
<label htmlFor="payzen_endpoint">{ t('app.admin.invoices.payment.endpoint') } *</label>
|
||||
<label htmlFor="payzen_endpoint">{ t('app.admin.invoices.payment.payzen.payzen_endpoint') } *</label>
|
||||
<FabInput id="payzen_endpoint"
|
||||
type="url"
|
||||
icon={<i className="fas fa-link" />}
|
||||
@ -171,7 +171,7 @@ const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys })
|
||||
required />
|
||||
</div>
|
||||
<div className="payzen-api-hmac-input">
|
||||
<label htmlFor="payzen_hmac">{ t('app.admin.invoices.payment.hmac') } *</label>
|
||||
<label htmlFor="payzen_hmac">{ t('app.admin.invoices.payment.payzen.payzen_hmac') } *</label>
|
||||
<FabInput id="payzen_hmac"
|
||||
icon={<i className="fas fa-subscript" />}
|
||||
defaultValue={settings.get(SettingName.PayZenHmacKey)}
|
||||
|
128
app/frontend/src/javascript/components/payzen-settings.tsx
Normal file
128
app/frontend/src/javascript/components/payzen-settings.tsx
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* This component displays a summary of the PayZen account keys, with a button triggering the modal to edit them
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Loader } from './loader';
|
||||
import { react2angular } from 'react2angular';
|
||||
import { IApplication } from '../models/application';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SettingAPI from '../api/setting';
|
||||
import { SettingName } from '../models/setting';
|
||||
import { useImmer } from 'use-immer';
|
||||
import { FabInput } from './fab-input';
|
||||
import { FabButton } from './fab-button';
|
||||
import { FabModal, ModalSize } from './fab-modal';
|
||||
import { PayZenKeysForm } from './payzen-keys-form';
|
||||
|
||||
declare var Application: IApplication;
|
||||
|
||||
interface PayzenSettingsProps {
|
||||
|
||||
}
|
||||
|
||||
const PAYZEN_HIDDEN = 'testpassword_HiDdEnHIddEnHIdDEnHiDdEnHIddEnHIdDEn';
|
||||
const payZenPublicSettings: Array<SettingName> = [SettingName.PayZenPublicKey, SettingName.PayZenEndpoint, SettingName.PayZenUsername];
|
||||
const payZenPrivateSettings: Array<SettingName> = [SettingName.PayZenPassword, SettingName.PayZenHmacKey];
|
||||
const payZenSettings: Array<SettingName> = payZenPublicSettings.concat(payZenPrivateSettings);
|
||||
const icons:Map<SettingName, string> = new Map([
|
||||
[SettingName.PayZenHmacKey, 'subscript'],
|
||||
[SettingName.PayZenPassword, 'key'],
|
||||
[SettingName.PayZenUsername, 'user'],
|
||||
[SettingName.PayZenEndpoint, 'link'],
|
||||
[SettingName.PayZenPublicKey, 'info']
|
||||
])
|
||||
|
||||
const payZenKeys = SettingAPI.query(payZenPublicSettings);
|
||||
const isPresent = {
|
||||
[SettingName.PayZenPassword]: SettingAPI.isPresent(SettingName.PayZenPassword),
|
||||
[SettingName.PayZenHmacKey]: SettingAPI.isPresent(SettingName.PayZenHmacKey)
|
||||
};
|
||||
|
||||
export const PayzenSettings: React.FC<PayzenSettingsProps> = ({}) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const [settings, updateSettings] = useImmer<Map<SettingName, string>>(new Map(payZenSettings.map(name => [name, ''])));
|
||||
const [openEditModal, setOpenEditModal] = useState<boolean>(false);
|
||||
const [preventConfirm, setPreventConfirm] = useState<boolean>(true);
|
||||
const [config, setConfig] = useState<Map<SettingName, string>>(new Map());
|
||||
const [errors, setErrors] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
const map = payZenKeys.read();
|
||||
for (const setting of payZenPrivateSettings) {
|
||||
map.set(setting, isPresent[setting].read() ? PAYZEN_HIDDEN : '');
|
||||
}
|
||||
updateSettings(map);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Open/closes the modal dialog to edit the payzen keys
|
||||
*/
|
||||
const toggleEditKeysModal = () => {
|
||||
setOpenEditModal(!openEditModal);
|
||||
}
|
||||
|
||||
const handleUpdateKeys = () => {
|
||||
const api = new SettingAPI();
|
||||
api.bulkUpdate(settings).then(result => {
|
||||
if (Array.from(result.values()).filter(item => !item.status).length > 0) {
|
||||
setErrors(JSON.stringify(result));
|
||||
} else {
|
||||
// TODO updateSettings(result);
|
||||
toggleEditKeysModal();
|
||||
}
|
||||
}, reason => {
|
||||
setErrors(reason);
|
||||
});
|
||||
}
|
||||
|
||||
const handleValidPayZenKeys = (payZenKeys: Map<SettingName, string>): void => {
|
||||
setConfig(payZenKeys);
|
||||
setPreventConfirm(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="payzen-settings">
|
||||
<h3 className="title">{t('app.admin.invoices.payment.payzen.payzen_keys')}</h3>
|
||||
<div className="payzen-keys">
|
||||
{payZenSettings.map(setting => {
|
||||
return (
|
||||
<div className="key-wrapper">
|
||||
<label htmlFor={setting}>{t(`app.admin.invoices.payment.payzen.${setting}`)}</label>
|
||||
<FabInput defaultValue={settings.get(setting)}
|
||||
id={setting}
|
||||
type={payZenPrivateSettings.indexOf(setting) > -1 ? 'password' : 'text'}
|
||||
icon={<i className={`fas fa-${icons.get(setting)}`} />}
|
||||
readOnly
|
||||
disabled />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<FabButton className="edit-keys-btn" onClick={toggleEditKeysModal}>{t('app.admin.invoices.payment.edit_keys')}</FabButton>
|
||||
<FabModal title={t('app.admin.invoices.payment.payzen.payzen_keys')}
|
||||
isOpen={openEditModal}
|
||||
toggleModal={toggleEditKeysModal}
|
||||
width={ModalSize.medium}
|
||||
confirmButton={t('app.admin.invoices.payment.payzen.update_button')}
|
||||
onConfirm={handleUpdateKeys}
|
||||
preventConfirm={preventConfirm}
|
||||
closeButton>
|
||||
{errors && <span>{errors}</span>}
|
||||
<PayZenKeysForm onValidKeys={handleValidPayZenKeys} />
|
||||
</FabModal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const PayzenSettingsWrapper: React.FC<PayzenSettingsProps> = ({}) => {
|
||||
return (
|
||||
<Loader>
|
||||
<PayzenSettings />
|
||||
</Loader>
|
||||
);
|
||||
}
|
||||
|
||||
Application.Components.component('payzenSettings', react2angular(PayzenSettingsWrapper));
|
@ -110,7 +110,6 @@ const SelectGatewayModal: React.FC<SelectGatewayModalModalProps> = ({ isOpen, to
|
||||
isOpen={isOpen}
|
||||
toggleModal={toggleModal}
|
||||
width={ModalSize.medium}
|
||||
closeButton={false}
|
||||
className="gateway-modal"
|
||||
confirmButton={t('app.admin.invoices.payment.gateway_modal.confirm_button')}
|
||||
onConfirm={onGatewayConfirmed}
|
||||
|
@ -689,17 +689,6 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
$scope.onlinePaymentStatus = res.status;
|
||||
});
|
||||
}
|
||||
if ($scope.allSettings.payment_gateway === 'stripe') {
|
||||
$scope.allSettings.payzen_username = updatedSettings.get('payzen_username').value;
|
||||
$scope.allSettings.payzen_endpoint = updatedSettings.get('payzen_endpoint').value;
|
||||
$scope.allSettings.payzen_public_key = updatedSettings.get('payzen_public_key').value;
|
||||
Setting.isPresent({ name: 'payzen_password' }, function (res) {
|
||||
$scope.allSettings.payzen_password = (res.isPresent ? PAYZEN_PASSWD_HIDDEN : '');
|
||||
});
|
||||
Setting.isPresent({ name: 'payzen_hmac' }, function (res) {
|
||||
$scope.allSettings.payzen_hmac = (res.isPresent ? PAYZEN_PASSWD_HIDDEN : '');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -859,7 +859,7 @@ angular.module('application.router', ['ui.router'])
|
||||
"'accounting_other_client_code', 'accounting_other_client_label', 'accounting_wallet_code', 'accounting_wallet_label', " +
|
||||
"'accounting_VAT_code', 'accounting_VAT_label', 'accounting_subscription_code', 'accounting_subscription_label', " +
|
||||
"'accounting_Machine_code', 'accounting_Machine_label', 'accounting_Training_code', 'accounting_Training_label', " +
|
||||
"'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', " +
|
||||
"'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', 'payment_gateway', " +
|
||||
"'feature_tour_display', 'online_payment_module', 'stripe_public_key', 'stripe_currency', 'invoice_prefix']"
|
||||
}).$promise;
|
||||
}],
|
||||
|
@ -37,5 +37,6 @@
|
||||
@import "modules/select-gateway-modal";
|
||||
@import "modules/stripe-keys-form";
|
||||
@import "modules/payzen-keys-form";
|
||||
@import "modules/payzen-settings";
|
||||
|
||||
@import "app.responsive";
|
||||
|
@ -38,6 +38,11 @@
|
||||
border-radius: 0;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .08);
|
||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
|
||||
&[disabled], &[readonly] {
|
||||
background-color: #eee;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&--addon {
|
||||
|
16
app/frontend/src/stylesheets/modules/payzen-settings.scss
Normal file
16
app/frontend/src/stylesheets/modules/payzen-settings.scss
Normal file
@ -0,0 +1,16 @@
|
||||
.payzen-settings {
|
||||
margin: 15px;
|
||||
.payzen-keys {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.key-wrapper {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.edit-keys-btn {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
on-success="onGatewayModalSuccess"
|
||||
on-error="onGatewayModalError" />
|
||||
</div>
|
||||
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true'">
|
||||
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true' && allSettings.payment_gateway === 'stripe'">
|
||||
<h3 class="m-l" translate>{{ 'app.admin.invoices.payment.stripe_keys' }}</h3>
|
||||
<div class="col-md-4 m-l">
|
||||
<label for="stripe_public_key" class="control-label">{{ 'app.admin.invoices.payment.public_key' | translate }}</label>
|
||||
@ -47,7 +47,7 @@
|
||||
<button class="btn btn-default m-t-lg" ng-click="requireStripeKeys(allSettings.online_payment_module)" translate>{{ 'app.admin.invoices.payment.edit_keys' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true'">
|
||||
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true' && allSettings.payment_gateway === 'stripe'">
|
||||
<h3 class="m-l" translate>{{ 'app.admin.invoices.payment.currency' }}</h3>
|
||||
<p class="alert alert-warning m-h-md" ng-bind-html="'app.admin.invoices.payment.currency_info_html' | translate"></p>
|
||||
<p class="alert alert-danger m-h-md" ng-bind-html="'app.admin.invoices.payment.currency_alert_html' | translate"></p>
|
||||
@ -64,5 +64,8 @@
|
||||
</text-setting>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t" ng-show="allSettings.online_payment_module === 'true' && allSettings.payment_gateway === 'payzen'">
|
||||
<payzen-settings />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
json.isPresent @setting.present?
|
||||
|
@ -641,16 +641,20 @@ en:
|
||||
payzen_keys_info_html: "<p>To be able to collect online payments, you must configure the <a href='https://payzen.eu' target='_blank'>PayZen</a> identifiers and keys.</p><p>Retrieve them from <a href='https://secure.payzen.eu/vads-merchant/' target='_blank'>your merchant back office</a>.</p>"
|
||||
client_keys: "Client key"
|
||||
api_keys: "API keys"
|
||||
username: "User"
|
||||
password: "Password"
|
||||
endpoint: "REST API server name"
|
||||
hmac: "HMAC-SHA-256 key"
|
||||
edit_keys: "Edit keys"
|
||||
currency: "Currency"
|
||||
currency_info_html: "Please specify below the currency used for online payment. You should provide a three-letter ISO code, from the list of <a href='https://stripe.com/docs/currencies' target='_blank'>Stripe supported currencies</a>."
|
||||
currency_alert_html: "<strong>Warning</strong>: the currency cannot be changed after the first online payment was made. Please define this setting carefully before opening Fab-manager to your members."
|
||||
stripe_currency: "Stripe currency"
|
||||
gateway_configuration_error: "An error occurred while configuring the payment gateway."
|
||||
payzen:
|
||||
payzen_keys: "PayZen keys"
|
||||
payzen_username: "Username"
|
||||
payzen_password: "Password"
|
||||
payzen_endpoint: "REST API server name"
|
||||
payzen_hmac: "HMAC-SHA-256 key"
|
||||
payzen_public_key: "Client public key"
|
||||
update_button: "Update"
|
||||
# select a payment gateway
|
||||
gateway_modal:
|
||||
select_gateway_title: "Select a payment gateway"
|
||||
|
@ -641,16 +641,20 @@ fr:
|
||||
payzen_keys_info_html: "<p>Pour pouvoir encaisser des paiements en ligne, vous devez configurer les identifiants et les clefs <a href='https://payzen.eu' target='_blank'>PayZen</a>.</p><p>Retrouvez les dans <a href='https://secure.payzen.eu/vads-merchant/' target='_blank'>votre back office marchant</a>.</p>"
|
||||
client_keys: "Clef client"
|
||||
api_keys: "Clefs d'API"
|
||||
username: "Utilisateur"
|
||||
password: "Mot de passe"
|
||||
endpoint: "Nom du serveur de l'API REST"
|
||||
hmac: "Clef HMAC-SHA-256"
|
||||
edit_keys: "Modifier les clefs"
|
||||
currency: "Devise"
|
||||
currency_info_html: "Veuillez indiquer la devise à utiliser lors des paiements en ligne. Vous devez fournir un code ISO à trois lettres, issu de la liste des <a href='https://stripe.com/docs/currencies' target='_blank'>devises supportées par Stripe</a>."
|
||||
currency_alert_html: "<strong>Attention</strong> : la devise ne peut pas être modifiée après que le premier paiement en ligne ait été effectué. Veuillez définir attentivement ce paramètre avant d'ouvrir Fab-manager à vos membres."
|
||||
stripe_currency: "Devise Stripe"
|
||||
gateway_configuration_error: "Une erreur est survenue lors de la configuration de la passerelle de paiement."
|
||||
payzen:
|
||||
payzen_keys: "Clefs PayZen"
|
||||
payzen_username: "Utilisateur"
|
||||
payzen_password: "Mot de passe"
|
||||
payzen_endpoint: "Nom du serveur de l'API REST"
|
||||
payzen_hmac: "Clef HMAC-SHA-256"
|
||||
payzen_public_key: "Clef publique client"
|
||||
update_button: "Mettre à jour"
|
||||
# select a payment gateway
|
||||
gateway_modal:
|
||||
select_gateway_title: "Sélectionnez une passerelle de paiement"
|
||||
|
Loading…
Reference in New Issue
Block a user