mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-03 12:03:41 +00:00
feat: add non-expiring license support to backoffice and portal UI with updated i18n and selective form patching
This commit is contained in:
@@ -84,9 +84,11 @@ export function DesignerToolbar({
|
||||
<Text size="sm" fw={600}>
|
||||
{validityDays != null
|
||||
? t('designer.validityDays', '{{count}} days', { count: validityDays })
|
||||
: t('designer.validityMonths', '{{count}} months', {
|
||||
count: validityMonths,
|
||||
})}
|
||||
: validityMonths
|
||||
? t('designer.validityMonths', '{{count}} months', {
|
||||
count: validityMonths,
|
||||
})
|
||||
: t('designer.validityNone', 'Does not expire')}
|
||||
</Text>
|
||||
<Text size="xs" c="dimmed">
|
||||
{t('designer.validityEditedOn', '— set on Certificate Requirements → Behaviour')}
|
||||
|
||||
@@ -72,9 +72,13 @@ function toDraft(licenseType: LicenseType): Draft {
|
||||
licenseType.capitalThreshold == null
|
||||
? null
|
||||
: Number(licenseType.capitalThreshold),
|
||||
// Zero is a real stored state for `validityMonths` (a type that issues
|
||||
// nothing with an expiry) and is kept. Zero in the other two is not a
|
||||
// policy anyone set — it is an unfilled column — and seeding a box with a
|
||||
// value below its own floor only produces a save the server rejects.
|
||||
validityMonths: licenseType.validityMonths ?? 12,
|
||||
validityDays: licenseType.validityDays ?? null,
|
||||
renewalWindowDays: licenseType.renewalWindowDays ?? 60,
|
||||
validityDays: licenseType.validityDays || null,
|
||||
renewalWindowDays: licenseType.renewalWindowDays || 60,
|
||||
expiryReminderDays: licenseType.expiryReminderDays ?? [60, 30, 7],
|
||||
requiresOperatorMode: licenseType.requiresOperatorMode ?? true,
|
||||
allowMultipleOpenDrafts: licenseType.allowMultipleOpenDrafts ?? false,
|
||||
@@ -128,9 +132,38 @@ export function BehaviorTab({ licenseType }: { licenseType: LicenseType }) {
|
||||
// against an expiry that never arrives, so none of them are asked for.
|
||||
const expires = draft.validityDays !== null || draft.validityMonths > 0;
|
||||
|
||||
// The server's floor for a stated term is 6 months, so no-expiry is a state
|
||||
// this form can hold and edit around but cannot switch a type into. Offered
|
||||
// only where it is already what the type is, rather than as an option whose
|
||||
// save would be refused.
|
||||
const noExpiryAvailable =
|
||||
(licenseType.validityMonths ?? 12) === 0 && !licenseType.validityDays;
|
||||
|
||||
async function onSave() {
|
||||
// Only the settings this form actually asked for. The endpoint patches, so
|
||||
// an omitted field keeps its stored value — and the fields hidden above are
|
||||
// hidden precisely because the type has no such policy, which the server
|
||||
// stores as a zero its own validators then refuse (`validityMonths` has a
|
||||
// floor of 6, `renewalWindowDays` of 1). Echoing those back is what made
|
||||
// saving an ownership transfer fail outright.
|
||||
const {
|
||||
validityMonths,
|
||||
validityDays,
|
||||
renewalWindowDays,
|
||||
expiryReminderDays,
|
||||
...rest
|
||||
} = draft;
|
||||
|
||||
const ok = await run(
|
||||
() => save({ id: licenseType.id, ...draft }).unwrap(),
|
||||
() =>
|
||||
save({
|
||||
id: licenseType.id,
|
||||
...rest,
|
||||
...(expires ? { validityMonths, validityDays } : {}),
|
||||
...(expires && draft.renewalEnabled
|
||||
? { renewalWindowDays, expiryReminderDays }
|
||||
: {}),
|
||||
}).unwrap(),
|
||||
t('certReq.behavior.saved', 'Configuration saved.'),
|
||||
);
|
||||
if (ok) setDirty(false);
|
||||
@@ -334,7 +367,14 @@ export function BehaviorTab({ licenseType }: { licenseType: LicenseType }) {
|
||||
data={[
|
||||
{ value: 'MONTHS', label: t('certReq.behavior.unitMonths', 'Months') },
|
||||
{ value: 'DAYS', label: t('certReq.behavior.unitDays', 'Days') },
|
||||
{ value: 'NONE', label: t('certReq.behavior.unitNone', 'Does not expire') },
|
||||
...(noExpiryAvailable
|
||||
? [
|
||||
{
|
||||
value: 'NONE',
|
||||
label: t('certReq.behavior.unitNone', 'Does not expire'),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]}
|
||||
value={
|
||||
draft.validityDays !== null
|
||||
|
||||
@@ -1253,6 +1253,7 @@ export const am: Translations = {
|
||||
validityMonths_other: "{{count}} ወራት",
|
||||
validityDays_one: "{{count}} ቀን",
|
||||
validityDays_other: "{{count}} ቀናት",
|
||||
validityNone: "ጊዜው አያልፍም",
|
||||
validityEditedOn: "— በምስክር ወረቀት መስፈርቶች → ባህሪ ውስጥ ይዘጋጃል",
|
||||
newVersion: "አዲስ ስሪት",
|
||||
versions: "ስሪቶች",
|
||||
|
||||
@@ -1260,6 +1260,7 @@ export const en = {
|
||||
validityMonths_other: '{{count}} months',
|
||||
validityDays_one: '{{count}} day',
|
||||
validityDays_other: '{{count}} days',
|
||||
validityNone: 'Does not expire',
|
||||
validityEditedOn: '— set on Certificate Requirements → Behaviour',
|
||||
newVersion: 'New version',
|
||||
versions: 'Versions',
|
||||
|
||||
@@ -322,8 +322,16 @@ function LicenseTypeCard({
|
||||
</Tooltip>
|
||||
)}
|
||||
{type.issuesCertificate ? (
|
||||
// A term in days wins over the months column, and a type with
|
||||
// neither issues something that simply does not expire — a
|
||||
// transfer, or any one-off record. Reading `validityMonths`
|
||||
// alone badged those "0 months".
|
||||
<Badge size="sm" variant="light" color="teal">
|
||||
{t('licensing.catalogue.validityBadge', { months: type.validityMonths })}
|
||||
{type.validityDays
|
||||
? t('licensing.catalogue.validityDaysBadge', { count: type.validityDays })
|
||||
: type.validityMonths
|
||||
? t('licensing.catalogue.validityBadge', { months: type.validityMonths })
|
||||
: t('licensing.catalogue.noExpiryBadge')}
|
||||
</Badge>
|
||||
) : (
|
||||
<Tooltip label={t('licensing.catalogue.evaluationTooltip')}>
|
||||
|
||||
@@ -884,6 +884,9 @@ export const am: Translations = {
|
||||
capitalTooltip: 'በባንክ ደብዳቤ መረጋገጥ ያለበት ዝቅተኛ ካፒታል',
|
||||
capitalBadge: 'ካፒታል {{amount}}',
|
||||
validityBadge: '{{months}} ወራት',
|
||||
validityDaysBadge_one: '{{count}} ቀን',
|
||||
validityDaysBadge_other: '{{count}} ቀናት',
|
||||
noExpiryBadge: 'ጊዜው አያልፍም',
|
||||
evaluationTooltip: 'በምስክር ወረቀት ፈንታ በባለሥልጣኑ ውሳኔ የሚጠናቀቅ',
|
||||
evaluationOnly: 'ግምገማ ብቻ',
|
||||
startApplication: 'ማመልከቻ ጀምር',
|
||||
|
||||
@@ -886,6 +886,9 @@ export const en = {
|
||||
capitalTooltip: 'Minimum capital that must be evidenced by a bank letter',
|
||||
capitalBadge: 'Capital {{amount}}',
|
||||
validityBadge: '{{months}} months',
|
||||
validityDaysBadge_one: '{{count}} day',
|
||||
validityDaysBadge_other: '{{count}} days',
|
||||
noExpiryBadge: 'No expiry',
|
||||
evaluationTooltip: 'Concludes with an EMA decision rather than a certificate',
|
||||
evaluationOnly: 'Evaluation only',
|
||||
startApplication: 'Start application',
|
||||
|
||||
Reference in New Issue
Block a user