Skip to content

Commit 3d38d9f

Browse files
committed
License checked and pre-deployment tested
1 parent a1abe54 commit 3d38d9f

6 files changed

Lines changed: 103 additions & 64 deletions

File tree

src/components/LicenseModal.tsx

Lines changed: 96 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export function LicenseModal({ open, onClose, showToast }: LicenseModalProps) {
2020
const [licenseKey, setLicenseKey] = React.useState('');
2121
const [type, setType] = React.useState('');
2222
const [isLicenseValid, setIsLicenseValid] = React.useState(false);
23+
const [licenseChecked, setLicenseChecked] = React.useState(false);
2324
const [agent, setAgent] = React.useState('Ollama');
2425
const [host, setHost] = React.useState('http://localhost:11434');
2526
const [model, setModel] = React.useState('ministral-3:3b');
@@ -77,16 +78,20 @@ export function LicenseModal({ open, onClose, showToast }: LicenseModalProps) {
7778
};
7879
loadApiConfig();
7980

80-
// Check initial license state
81+
// Check initial license state (restore from cache synchronously first)
82+
LicenseManager.restoreFromCache();
8183
if (LicenseManager.hasActiveLicense()) {
8284
setIsLicenseValid(true);
85+
setType(LicenseManager.getType());
86+
setLicenseChecked(true);
8387
}
8488

8589
// Subscribe to license changes to update type
8690
const unsubscribe = LicenseManager.subscribe(() => {
8791
setIsLicenseValid(LicenseManager.hasActiveLicense());
8892
const updatedType = LicenseManager.getType();
8993
setType(updatedType);
94+
setLicenseChecked(true);
9095
});
9196

9297
return () => unsubscribe();
@@ -140,6 +145,18 @@ export function LicenseModal({ open, onClose, showToast }: LicenseModalProps) {
140145
}
141146
}, [isLicenseValid, licenseKey]);
142147

148+
// Derive license tier: Free, Premium, or PremiumPlus
149+
const licenseTier: 'Free' | 'Premium' | 'PremiumPlus' = isLicenseValid
150+
? (type === 'PremiumPlus' ? 'PremiumPlus' : 'Premium')
151+
: 'Free';
152+
153+
// When license tier is Free, force agent to Ollama (only after initial license check)
154+
React.useEffect(() => {
155+
if (licenseChecked && licenseTier === 'Free' && agent !== 'Ollama') {
156+
setAgent('Ollama');
157+
}
158+
}, [licenseChecked, licenseTier, agent]);
159+
143160
const handleSaveLicense = async () => {
144161
localStorage.setItem('easyeditor-user-name', name);
145162
await LicenseManager.setLicenseData(email, licenseKey);
@@ -326,8 +343,8 @@ export function LicenseModal({ open, onClose, showToast }: LicenseModalProps) {
326343
<div className="about-card">
327344
<h3>{t('about.easyai_credits')}</h3>
328345
<div style={{ marginTop: '10px' }}>
329-
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_agent')}</strong> {isLicenseValid ? (import.meta.env.VITE_PREMIUM_AGENT || 'Ollama') : agent}</p>
330-
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_model')}</strong> {isLicenseValid ? (import.meta.env.VITE_PREMIUM_MODEL || 'ministral-3:3b') : model}</p>
346+
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_agent')}</strong> {t('about.query_built')}</p>
347+
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_model')}</strong> {t('about.query_built')}</p>
331348
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_monthly')}</strong> {monthlyCredits !== null ? monthlyCredits : t('about.query_built')}</p>
332349
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_topup')}</strong> {topUpCredits !== null ? topUpCredits : t('about.query_built')}</p>
333350
<p style={{ fontSize: '0.9em', margin: '4px 0' }}><strong>{t('about.credits_used')}</strong> {usedCredits !== null ? usedCredits : t('about.query_built')}</p>
@@ -345,76 +362,98 @@ export function LicenseModal({ open, onClose, showToast }: LicenseModalProps) {
345362
</div>
346363

347364
<div className="about-card" style={{ flex: 1 }}>
348-
<h3>{t('about.api_hosting')}</h3>
365+
<h3>{t('about.api_hosting')} ({licenseTier === 'PremiumPlus' ? 'PremiumPlus' : licenseTier === 'Premium' ? 'Premium' : 'Free'})</h3>
349366
<div style={{ display: 'flex', flexDirection: 'column', gap: '3px', marginTop: '10px' }}>
350367
<div>
351368
<label style={{ display: 'block', fontSize: '0.9em', marginBottom: '4px' }}>{t('about.api_agent')}</label>
352369
<select
353370
className="license-name-input"
354371
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)' }}
355372
value={agent}
356-
onChange={(e) => {
357-
const selected = e.target.value;
358-
if (selected === 'Premium' || selected === 'PremiumPlus') {
359-
if (showToast) {
360-
showToast(t('about.premium_not_implemented'), 'warning');
361-
}
362-
// Revert the select back to current agent
363-
e.target.value = agent;
364-
return;
365-
}
366-
setAgent(selected);
367-
}}
373+
disabled={licenseTier === 'Free'}
374+
onChange={(e) => setAgent(e.target.value)}
368375
>
369376
<option value="Ollama">Ollama</option>
370-
<option value="Gemini">Gemini</option>
371-
<option value="Bedrock">Bedrock</option>
372-
<option value="Claude">Claude</option>
373-
<option value="Premium">Premium</option>
374-
<option value="PremiumPlus">PremiumPlus</option>
377+
{licenseTier !== 'Free' && (
378+
<>
379+
<option value="Gemini">Gemini</option>
380+
<option value="Bedrock">Bedrock</option>
381+
<option value="Claude">Claude</option>
382+
</>
383+
)}
384+
{licenseTier === 'PremiumPlus' && (
385+
<option value="PremiumPlus">PremiumPlus</option>
386+
)}
375387
</select>
376388
</div>
377-
<div>
378-
<label style={{ display: 'block', fontSize: '0.9em', marginBottom: '4px' }}>{t('about.api_host')}</label>
379-
<input
380-
type="text"
381-
className="license-name-input"
382-
style={{
383-
width: '95%',
384-
boxSizing: 'border-box',
385-
padding: '4px',
386-
borderRadius: '4px',
387-
border: '1px solid var(--border-color, #ccc)',
388-
opacity: agent === 'Gemini' ? 0.6 : 1,
389-
cursor: agent === 'Gemini' ? 'not-allowed' : 'text'
390-
}}
391-
placeholder={t('about.api_host_placeholder')}
392-
readOnly={agent === 'Gemini'}
393-
value={host}
394-
onChange={(e) => setHost(e.target.value)}
395-
/>
396-
</div>
389+
{agent === 'Ollama' && (
390+
<div>
391+
<label style={{ display: 'block', fontSize: '0.9em', marginBottom: '4px' }}>{t('about.api_host')}</label>
392+
<input
393+
type="text"
394+
className="license-name-input"
395+
style={{
396+
width: '95%',
397+
boxSizing: 'border-box',
398+
padding: '4px',
399+
borderRadius: '4px',
400+
border: '1px solid var(--border-color, #ccc)',
401+
}}
402+
placeholder={t('about.api_host_placeholder')}
403+
value={host}
404+
onChange={(e) => setHost(e.target.value)}
405+
/>
406+
</div>
407+
)}
397408
<div>
398409
<label style={{ display: 'block', fontSize: '0.9em', marginBottom: '4px' }}>{t('about.api_model')}</label>
399-
<input
400-
type="text"
401-
className="license-name-input"
402-
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)' }}
403-
placeholder={t('about.api_model_placeholder')}
404-
value={model}
405-
onChange={(e) => setModel(e.target.value)}
406-
/>
410+
{agent === 'PremiumPlus' ? (
411+
<input
412+
type="text"
413+
className="license-name-input"
414+
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)', opacity: 0.6, cursor: 'not-allowed' }}
415+
readOnly
416+
value="Coming soon"
417+
/>
418+
) : (
419+
<input
420+
type="text"
421+
className="license-name-input"
422+
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)' }}
423+
placeholder={t('about.api_model_placeholder')}
424+
value={model}
425+
onChange={(e) => setModel(e.target.value)}
426+
/>
427+
)}
407428
</div>
408429
<div>
409430
<label style={{ display: 'block', fontSize: '0.9em', marginBottom: '4px' }}>{t('about.api_key')}</label>
410-
<input
411-
type="password"
412-
className="license-name-input"
413-
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)' }}
414-
placeholder={t('about.api_key_placeholder')}
415-
value={apiKey}
416-
onChange={(e) => setApiKey(e.target.value)}
417-
/>
431+
{licenseTier === 'Free' ? (
432+
<input
433+
type="text"
434+
className="license-name-input"
435+
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)', opacity: 0.6, cursor: 'not-allowed', fontStyle: 'italic' }}
436+
readOnly
437+
value="Available with Premium subscription"
438+
/>
439+
) : agent === 'PremiumPlus' ? (
440+
<input
441+
type="text"
442+
className="license-name-input"
443+
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)', opacity: 0.6, cursor: 'not-allowed' }}
444+
readOnly
445+
value="Coming soon"
446+
/>
447+
) : (
448+
<input
449+
type="password"
450+
className="license-name-input"
451+
style={{ width: '95%', boxSizing: 'border-box', padding: '4px', borderRadius: '4px', border: '1px solid var(--border-color, #ccc)' }}
452+
placeholder={t('about.api_key_placeholder')}
453+
value={apiKey}
454+
onChange={(e) => setApiKey(e.target.value)}
455+
/>
456+
)}
418457
</div>
419458
<button
420459
onClick={handleSaveApiConfig}

src/i18n/locales/de.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"api_host_placeholder": "http://localhost:11434",
265265
"api_model_placeholder": "ministral-3:3b",
266266
"api_key_placeholder": "Ihr API-Schlüssel",
267-
"license_info": "Lizenzinformationen",
267+
"license_info": "EasyEditor Lizenz",
268268
"license_name": "Name",
269269
"license_name_placeholder": "Ihr Name",
270270
"license_email": "E-Mail",

src/i18n/locales/en.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@
247247
"persona_li6": "Document Repo",
248248
"persona_li7": "Fix / Rewrite Doc",
249249
"persona_li8": "Markdown Tables",
250-
"easyai_credits": "EasyAI Credits (Premium)",
250+
"easyai_credits": "EasyAI Credits (PremiumPlus)",
251251
"credits_agent": "Agent:",
252252
"credits_model": "Model:",
253253
"credits_monthly": "MonthlyCredits:",
@@ -256,15 +256,15 @@
256256
"credits_balance": "BalanceCredits:",
257257
"query_built": "(coming soon)",
258258
"go_premiumplus": "Go PremiumPlus",
259-
"api_hosting": "EasyAI API Hosting (Free)",
259+
"api_hosting": "EasyAI API Hosting",
260260
"api_agent": "Agent",
261261
"api_host": "Host",
262262
"api_model": "Model",
263263
"api_key": "API Key",
264264
"api_host_placeholder": "http://localhost:11434",
265265
"api_model_placeholder": "ministral-3:3b",
266266
"api_key_placeholder": "Your API Key",
267-
"license_info": "License Information",
267+
"license_info": "EasyEditor License",
268268
"license_name": "Name",
269269
"license_name_placeholder": "Your Name",
270270
"license_email": "Email",

src/i18n/locales/nl.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"api_host_placeholder": "http://localhost:11434",
265265
"api_model_placeholder": "ministral-3:3b",
266266
"api_key_placeholder": "Uw API-sleutel",
267-
"license_info": "Licentie-informatie",
267+
"license_info": "EasyEditor Licentie",
268268
"license_name": "Naam",
269269
"license_name_placeholder": "Uw naam",
270270
"license_email": "E-mail",

src/i18n/locales/pl.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"api_host_placeholder": "http://localhost:11434",
265265
"api_model_placeholder": "ministral-3:3b",
266266
"api_key_placeholder": "Twój klucz API",
267-
"license_info": "Informacje o licencji",
267+
"license_info": "EasyEditor Licencja",
268268
"license_name": "Imię",
269269
"license_name_placeholder": "Twoje imię",
270270
"license_email": "Email",

src/i18n/locales/pt-br.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@
264264
"api_host_placeholder": "http://localhost:11434",
265265
"api_model_placeholder": "ministral-3:3b",
266266
"api_key_placeholder": "Sua Chave API",
267-
"license_info": "Informação de Licença",
267+
"license_info": "EasyEditor Licença",
268268
"license_name": "Nome",
269269
"license_name_placeholder": "Seu Nome",
270270
"license_email": "Email",

0 commit comments

Comments
 (0)