1
0
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:
Sylvain 2021-04-06 17:47:47 +02:00
parent 63c81b82c1
commit 667f6f6229
14 changed files with 197 additions and 34 deletions

View File

@ -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();

View File

@ -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 };

View File

@ -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)}

View 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));

View File

@ -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}

View File

@ -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 : '');
});
}
};
/**

View File

@ -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;
}],

View File

@ -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";

View File

@ -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 {

View 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;
}
}

View File

@ -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>

View File

@ -1 +1,3 @@
# frozen_string_literal: true
json.isPresent @setting.present?

View File

@ -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"

View File

@ -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"