+62
-10
@@ -307,29 +307,81 @@ img {
|
|||||||
font-weight: 700
|
font-weight: 700
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-panel input, .ai-panel textarea, .contact-form input, .contact-form textarea {
|
.ai-panel input:not([type="checkbox"]):not([type="file"]),
|
||||||
|
.ai-panel textarea,
|
||||||
|
.contact-form input:not([type="checkbox"]):not([type="file"]),
|
||||||
|
.contact-form textarea,
|
||||||
|
.subscribe-form input[type="email"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid rgba(255,255,255,.12);
|
border: 1px solid #d9e1f0;
|
||||||
border-radius: 18px;
|
border-radius: 6px;
|
||||||
background: rgba(0,0,0,.25);
|
background: #fff;
|
||||||
color: #fff;
|
color: #0e1e3a;
|
||||||
padding: 15px 16px;
|
padding: 12px 14px;
|
||||||
outline: none
|
outline: none;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
transition: border-color .15s ease, box-shadow .15s ease
|
||||||
}
|
}
|
||||||
|
|
||||||
.ai-panel input:focus, .ai-panel textarea:focus, .contact-form input:focus, .contact-form textarea:focus {
|
.ai-panel input:not([type="checkbox"]):not([type="file"])::placeholder,
|
||||||
border-color: rgba(95,160,255,.65)
|
.ai-panel textarea::placeholder,
|
||||||
|
.contact-form input:not([type="checkbox"]):not([type="file"])::placeholder,
|
||||||
|
.contact-form textarea::placeholder,
|
||||||
|
.subscribe-form input[type="email"]::placeholder {
|
||||||
|
color: #97a4b8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ai-panel input:not([type="checkbox"]):not([type="file"]):focus,
|
||||||
|
.ai-panel textarea:focus,
|
||||||
|
.contact-form input:not([type="checkbox"]):not([type="file"]):focus,
|
||||||
|
.contact-form textarea:focus,
|
||||||
|
.subscribe-form input[type="email"]:focus {
|
||||||
|
border-color: #5fa0ff;
|
||||||
|
box-shadow: 0 0 0 3px rgba(95,160,255,.18)
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-panel label.is-invalid input:not([type="checkbox"]):not([type="file"]),
|
||||||
|
.ai-panel label.is-invalid textarea,
|
||||||
|
.contact-form label.is-invalid input:not([type="checkbox"]):not([type="file"]),
|
||||||
|
.contact-form label.is-invalid textarea,
|
||||||
|
.subscribe-form .subscribe-row.is-invalid input[type="email"] {
|
||||||
|
border-color: #ff8a8a;
|
||||||
|
box-shadow: 0 0 0 3px rgba(255,138,138,.18)
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-error {
|
||||||
|
display: block;
|
||||||
|
margin-top: 6px;
|
||||||
|
color: #ff8a8a;
|
||||||
|
font-size: .85rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.35
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-error:empty {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.consent-inline.is-invalid label {
|
||||||
|
color: #ff8a8a
|
||||||
|
}
|
||||||
|
|
||||||
.file-drop {
|
.file-drop {
|
||||||
display: block;
|
display: block;
|
||||||
border: 1px dashed rgba(143,184,255,.45);
|
border: 1px dashed rgba(143,184,255,.45);
|
||||||
border-radius: 22px;
|
border-radius: 6px;
|
||||||
background: rgba(95,160,255,.07);
|
background: rgba(95,160,255,.07);
|
||||||
padding: 22px;
|
padding: 22px;
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-drop.is-invalid {
|
||||||
|
border-color: #ff8a8a;
|
||||||
|
background: rgba(255,138,138,.06)
|
||||||
|
}
|
||||||
|
|
||||||
.file-drop input {
|
.file-drop input {
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<section class="section" id="matcher">
|
<section class="section" id="matcher">
|
||||||
<div class="container matcher-grid">
|
<div class="container matcher-grid">
|
||||||
<form class="ai-panel" id="cvMatcherForm">
|
<form class="ai-panel" id="cvMatcherForm" novalidate>
|
||||||
<span class="eyebrow" data-i18n="cv.input">Input</span>
|
<span class="eyebrow" data-i18n="cv.input">Input</span>
|
||||||
<h2 data-i18n="cv.details">CV and job details</h2>
|
<h2 data-i18n="cv.details">CV and job details</h2>
|
||||||
<label class="file-drop" for="cvFile">
|
<label class="file-drop" for="cvFile">
|
||||||
@@ -97,6 +97,7 @@
|
|||||||
<span id="cvFileName" data-i18n="cv.fileHint">PDF only, max size handled by backend</span>
|
<span id="cvFileName" data-i18n="cv.fileHint">PDF only, max size handled by backend</span>
|
||||||
<input type="file" id="cvFile" accept="application/pdf" required />
|
<input type="file" id="cvFile" accept="application/pdf" required />
|
||||||
</label>
|
</label>
|
||||||
|
<small class="field-error" id="cvFileError"></small>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="cv.jobLink">Job link</span>
|
<span data-i18n="cv.jobLink">Job link</span>
|
||||||
<input type="url" id="jobUrl" placeholder="https://company.com/careers/job" />
|
<input type="url" id="jobUrl" placeholder="https://company.com/careers/job" />
|
||||||
@@ -104,6 +105,7 @@
|
|||||||
<label>
|
<label>
|
||||||
<span data-i18n="cv.jobDescription">Or paste job description</span>
|
<span data-i18n="cv.jobDescription">Or paste job description</span>
|
||||||
<textarea id="jobDescription" rows="8" data-i18n-placeholder="cv.jobPlaceholder" placeholder="Paste the job description if the page cannot be crawled."></textarea>
|
<textarea id="jobDescription" rows="8" data-i18n-placeholder="cv.jobPlaceholder" placeholder="Paste the job description if the page cannot be crawled."></textarea>
|
||||||
|
<small class="field-error" id="cvJobError"></small>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.email">Email</span>
|
<span data-i18n="form.email">Email</span>
|
||||||
@@ -113,6 +115,7 @@
|
|||||||
<input type="checkbox" id="gdprConsent" required />
|
<input type="checkbox" id="gdprConsent" required />
|
||||||
<label for="gdprConsent" data-i18n="cv.gdpr">I agree that my CV is processed and stored.</label>
|
<label for="gdprConsent" data-i18n="cv.gdpr">I agree that my CV is processed and stored.</label>
|
||||||
</div>
|
</div>
|
||||||
|
<small class="field-error" id="cvConsentError"></small>
|
||||||
<button id="matchSubmit" type="submit" class="btn btn-primary" data-i18n="cv.submit">Extract CV and match job</button>
|
<button id="matchSubmit" type="submit" class="btn btn-primary" data-i18n="cv.submit">Extract CV and match job</button>
|
||||||
<strong id="matcherMsg" class="form-message" role="status" aria-live="polite"></strong>
|
<strong id="matcherMsg" class="form-message" role="status" aria-live="polite"></strong>
|
||||||
</form>
|
</form>
|
||||||
@@ -149,18 +152,21 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form class="contact-form" id="contactForm">
|
<form class="contact-form" id="contactForm" novalidate>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.name">Name</span>
|
<span data-i18n="form.name">Name</span>
|
||||||
<input type="text" id="name" data-i18n-placeholder="form.namePlaceholder" placeholder="Your name" required />
|
<input type="text" id="name" data-i18n-placeholder="form.namePlaceholder" placeholder="Your name" required />
|
||||||
|
<small class="field-error" id="nameError"></small>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.email">Email</span>
|
<span data-i18n="form.email">Email</span>
|
||||||
<input type="email" id="email" data-i18n-placeholder="form.emailPlaceholder" placeholder="name@company.com" required />
|
<input type="email" id="email" data-i18n-placeholder="form.emailPlaceholder" placeholder="name@company.com" required />
|
||||||
|
<small class="field-error" id="emailError"></small>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.message">Message</span>
|
<span data-i18n="form.message">Message</span>
|
||||||
<textarea id="message" rows="6" data-i18n-placeholder="form.messagePlaceholder" placeholder="Tell me what you want to build." required></textarea>
|
<textarea id="message" rows="6" data-i18n-placeholder="form.messagePlaceholder" placeholder="Tell me what you want to build." required></textarea>
|
||||||
|
<small class="field-error" id="messageError"></small>
|
||||||
</label>
|
</label>
|
||||||
<button id="submit" type="submit" class="btn btn-primary" data-i18n="form.send">Send message</button>
|
<button id="submit" type="submit" class="btn btn-primary" data-i18n="form.send">Send message</button>
|
||||||
<strong id="msgSubmit" class="form-message" role="status" aria-live="polite"></strong>
|
<strong id="msgSubmit" class="form-message" role="status" aria-live="polite"></strong>
|
||||||
|
|||||||
@@ -139,18 +139,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<form class="contact-form" id="contactForm">
|
<form class="contact-form" id="contactForm" novalidate>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.name">Name</span>
|
<span data-i18n="form.name">Name</span>
|
||||||
<input type="text" id="name" data-i18n-placeholder="form.namePlaceholder" placeholder="Your name" required />
|
<input type="text" id="name" data-i18n-placeholder="form.namePlaceholder" placeholder="Your name" required />
|
||||||
|
<small class="field-error" id="nameError"></small>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.email">Email</span>
|
<span data-i18n="form.email">Email</span>
|
||||||
<input type="email" id="email" data-i18n-placeholder="form.emailPlaceholder" placeholder="name@company.com" required />
|
<input type="email" id="email" data-i18n-placeholder="form.emailPlaceholder" placeholder="name@company.com" required />
|
||||||
|
<small class="field-error" id="emailError"></small>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<span data-i18n="form.message">Message</span>
|
<span data-i18n="form.message">Message</span>
|
||||||
<textarea id="message" rows="6" data-i18n-placeholder="form.messagePlaceholder" placeholder="Tell me what you want to build." required></textarea>
|
<textarea id="message" rows="6" data-i18n-placeholder="form.messagePlaceholder" placeholder="Tell me what you want to build." required></textarea>
|
||||||
|
<small class="field-error" id="messageError"></small>
|
||||||
</label>
|
</label>
|
||||||
<button id="submit" type="submit" class="btn btn-primary" data-i18n="form.send">Send message</button>
|
<button id="submit" type="submit" class="btn btn-primary" data-i18n="form.send">Send message</button>
|
||||||
<strong id="msgSubmit" class="form-message" role="status" aria-live="polite"></strong>
|
<strong id="msgSubmit" class="form-message" role="status" aria-live="polite"></strong>
|
||||||
@@ -162,10 +165,12 @@
|
|||||||
<input type="email" id="subscribeEmail" data-i18n-placeholder="subscribe.emailPlaceholder" placeholder="name@company.com" required />
|
<input type="email" id="subscribeEmail" data-i18n-placeholder="subscribe.emailPlaceholder" placeholder="name@company.com" required />
|
||||||
<button id="subscribeSubmit" type="submit" class="btn btn-primary" data-i18n="subscribe.submit">Subscribe</button>
|
<button id="subscribeSubmit" type="submit" class="btn btn-primary" data-i18n="subscribe.submit">Subscribe</button>
|
||||||
</div>
|
</div>
|
||||||
|
<small class="field-error" id="subscribeEmailError"></small>
|
||||||
<div class="consent-inline">
|
<div class="consent-inline">
|
||||||
<input type="checkbox" id="subscribeConsent" required />
|
<input type="checkbox" id="subscribeConsent" required />
|
||||||
<label for="subscribeConsent" data-i18n="subscribe.gdpr">I agree to receive occasional emails about new demos.</label>
|
<label for="subscribeConsent" data-i18n="subscribe.gdpr">I agree to receive occasional emails about new demos.</label>
|
||||||
</div>
|
</div>
|
||||||
|
<small class="field-error" id="subscribeConsentError"></small>
|
||||||
<strong id="subscribeMsg" class="form-message" role="status" aria-live="polite"></strong>
|
<strong id="subscribeMsg" class="form-message" role="status" aria-live="polite"></strong>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+72
-26
@@ -48,6 +48,10 @@
|
|||||||
"form.captchaFailed": "Captcha verification failed.",
|
"form.captchaFailed": "Captcha verification failed.",
|
||||||
"form.failed": "Failed to send the message.",
|
"form.failed": "Failed to send the message.",
|
||||||
"form.rateLimited": "Too many requests from your network. Please wait a moment and try again.",
|
"form.rateLimited": "Too many requests from your network. Please wait a moment and try again.",
|
||||||
|
"form.required.name": "Please enter your name.",
|
||||||
|
"form.required.email": "Please enter your email address.",
|
||||||
|
"form.required.emailInvalid": "Please enter a valid email address.",
|
||||||
|
"form.required.message": "Please write a message.",
|
||||||
"subscribe.title": "Stay in the loop",
|
"subscribe.title": "Stay in the loop",
|
||||||
"subscribe.text": "Get a short note when a new AI demo is published. One email at most every few weeks.",
|
"subscribe.text": "Get a short note when a new AI demo is published. One email at most every few weeks.",
|
||||||
"subscribe.emailPlaceholder": "name@company.com",
|
"subscribe.emailPlaceholder": "name@company.com",
|
||||||
@@ -153,6 +157,10 @@
|
|||||||
"form.captchaFailed": "Verificarea Captcha a eșuat.",
|
"form.captchaFailed": "Verificarea Captcha a eșuat.",
|
||||||
"form.failed": "Mesajul nu a putut fi trimis.",
|
"form.failed": "Mesajul nu a putut fi trimis.",
|
||||||
"form.rateLimited": "Prea multe cereri din rețeaua ta. Te rugăm să aștepți câteva momente și să încerci din nou.",
|
"form.rateLimited": "Prea multe cereri din rețeaua ta. Te rugăm să aștepți câteva momente și să încerci din nou.",
|
||||||
|
"form.required.name": "Te rugăm să introduci numele.",
|
||||||
|
"form.required.email": "Te rugăm să introduci adresa de email.",
|
||||||
|
"form.required.emailInvalid": "Te rugăm să introduci o adresă de email validă.",
|
||||||
|
"form.required.message": "Te rugăm să scrii un mesaj.",
|
||||||
"subscribe.title": "Rămâi la curent",
|
"subscribe.title": "Rămâi la curent",
|
||||||
"subscribe.text": "Primești o notă scurtă când publicăm un nou demo AI. Cel mult un email la câteva săptămâni.",
|
"subscribe.text": "Primești o notă scurtă când publicăm un nou demo AI. Cel mult un email la câteva săptămâni.",
|
||||||
"subscribe.emailPlaceholder": "nume@companie.ro",
|
"subscribe.emailPlaceholder": "nume@companie.ro",
|
||||||
@@ -393,6 +401,27 @@
|
|||||||
$('#msgSubmit').removeClass().addClass('form-message ' + tone).text(msg);
|
$('#msgSubmit').removeClass().addClass('form-message ' + tone).text(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showFieldError(errorId, msg) {
|
||||||
|
var $el = $('#' + errorId);
|
||||||
|
$el.text(msg || '');
|
||||||
|
// Look first at the parent (for errors nested inside a label),
|
||||||
|
// then at the previous sibling block (for errors after consent/file-drop/subscribe-row).
|
||||||
|
var $parent = $el.parent();
|
||||||
|
var $container = $parent.is('label, .consent-inline') ? $parent : $el.prev();
|
||||||
|
if (!$container.length || !$container.is('label, .consent-inline, .file-drop, .subscribe-row')) {
|
||||||
|
$container = $el.closest('form');
|
||||||
|
}
|
||||||
|
$container.toggleClass('is-invalid', !!msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearFieldErrors(errorIds) {
|
||||||
|
for (var i = 0; i < errorIds.length; i++) showFieldError(errorIds[i], '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isValidEmail(value) {
|
||||||
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value || '').trim());
|
||||||
|
}
|
||||||
|
|
||||||
function formSuccess() {
|
function formSuccess() {
|
||||||
$('#contactForm')[0].reset();
|
$('#contactForm')[0].reset();
|
||||||
submitMSG(true, t('form.thanks'));
|
submitMSG(true, t('form.thanks'));
|
||||||
@@ -408,22 +437,35 @@
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var loader = $('#contactLoader'),
|
var loader = $('#contactLoader'),
|
||||||
button = $('#submit');
|
button = $('#submit');
|
||||||
|
|
||||||
|
var name = $('#name').val().trim();
|
||||||
|
var email = $('#email').val().trim();
|
||||||
|
var message = $('#message').val().trim();
|
||||||
|
clearFieldErrors(['nameError', 'emailError', 'messageError']);
|
||||||
|
$('#msgSubmit').removeClass().addClass('form-message').text('');
|
||||||
|
|
||||||
|
var hasError = false;
|
||||||
|
if (!name) { showFieldError('nameError', t('form.required.name')); hasError = true; }
|
||||||
|
if (!email) { showFieldError('emailError', t('form.required.email')); hasError = true; }
|
||||||
|
else if (!isValidEmail(email)) { showFieldError('emailError', t('form.required.emailInvalid')); hasError = true; }
|
||||||
|
if (!message) { showFieldError('messageError', t('form.required.message')); hasError = true; }
|
||||||
|
if (hasError) return;
|
||||||
|
|
||||||
loader.css('display', 'flex');
|
loader.css('display', 'flex');
|
||||||
button.prop('disabled', true);
|
button.prop('disabled', true);
|
||||||
$('#msgSubmit').text('');
|
|
||||||
|
|
||||||
function postContact(token) {
|
function postContact(token) {
|
||||||
var message = {
|
var payload = {
|
||||||
Name: $('#name').val(),
|
Name: name,
|
||||||
Email: $('#email').val(),
|
Email: email,
|
||||||
Subject: '[MyAi.ro contact request]',
|
Subject: '[MyAi.ro contact request]',
|
||||||
Message: $('#message').val(),
|
Message: message,
|
||||||
CaptchaToken: token || ''
|
CaptchaToken: token || ''
|
||||||
};
|
};
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/api/contact',
|
url: '/api/contact',
|
||||||
data: JSON.stringify(message),
|
data: JSON.stringify(payload),
|
||||||
contentType: 'application/json; charset=utf-8',
|
contentType: 'application/json; charset=utf-8',
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function (resp) {
|
}).done(function (resp) {
|
||||||
@@ -468,18 +510,15 @@
|
|||||||
var $msg = $('#matcherMsg'),
|
var $msg = $('#matcherMsg'),
|
||||||
$button = $('#matchSubmit'),
|
$button = $('#matchSubmit'),
|
||||||
$result = $('#matchResult');
|
$result = $('#matchResult');
|
||||||
if (!file) {
|
|
||||||
$msg.removeClass().addClass('form-message text-danger').text(t('cv.noFile'));
|
clearFieldErrors(['cvFileError', 'cvJobError', 'cvConsentError']);
|
||||||
return;
|
$msg.removeClass().addClass('form-message').text('');
|
||||||
}
|
|
||||||
if (!jobUrl && !jobDescription) {
|
var hasError = false;
|
||||||
$msg.removeClass().addClass('form-message text-danger').text(t('cv.noJob'));
|
if (!file) { showFieldError('cvFileError', t('cv.noFile')); hasError = true; }
|
||||||
return;
|
if (!jobUrl && !jobDescription) { showFieldError('cvJobError', t('cv.noJob')); hasError = true; }
|
||||||
}
|
if (!consent) { showFieldError('cvConsentError', t('cv.noConsent')); hasError = true; }
|
||||||
if (!consent) {
|
if (hasError) return;
|
||||||
$msg.removeClass().addClass('form-message text-danger').text(t('cv.noConsent'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var $cvLoader = $('#cvLoader');
|
var $cvLoader = $('#cvLoader');
|
||||||
$button.prop('disabled', true).text(t('cv.processing'));
|
$button.prop('disabled', true).text(t('cv.processing'));
|
||||||
$msg.removeClass().addClass('form-message').text(t('cv.extracting'));
|
$msg.removeClass().addClass('form-message').text(t('cv.extracting'));
|
||||||
@@ -563,25 +602,32 @@
|
|||||||
var $msg = $('#subscribeMsg');
|
var $msg = $('#subscribeMsg');
|
||||||
var $button = $('#subscribeSubmit');
|
var $button = $('#subscribeSubmit');
|
||||||
var $loader = $('#contactLoader');
|
var $loader = $('#contactLoader');
|
||||||
var email = $('#subscribeEmail').val();
|
var email = $('#subscribeEmail').val().trim();
|
||||||
var consent = $('#subscribeConsent').is(':checked');
|
var consent = $('#subscribeConsent').is(':checked');
|
||||||
|
|
||||||
function setMsg(severity, key) {
|
function setMsg(severity, key) {
|
||||||
$msg.removeClass().addClass('form-message text-' + severity).text(t(key));
|
$msg.removeClass().addClass('form-message text-' + severity).text(t(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!consent) {
|
clearFieldErrors(['subscribeEmailError', 'subscribeConsentError']);
|
||||||
setMsg('danger', 'subscribe.noConsent');
|
$msg.removeClass().addClass('form-message').text('');
|
||||||
return;
|
|
||||||
}
|
var hasError = false;
|
||||||
if (!email) {
|
if (!email) {
|
||||||
setMsg('danger', 'form.failed');
|
showFieldError('subscribeEmailError', t('form.required.email'));
|
||||||
return;
|
hasError = true;
|
||||||
|
} else if (!isValidEmail(email)) {
|
||||||
|
showFieldError('subscribeEmailError', t('form.required.emailInvalid'));
|
||||||
|
hasError = true;
|
||||||
}
|
}
|
||||||
|
if (!consent) {
|
||||||
|
showFieldError('subscribeConsentError', t('subscribe.noConsent'));
|
||||||
|
hasError = true;
|
||||||
|
}
|
||||||
|
if (hasError) return;
|
||||||
|
|
||||||
$loader.css('display', 'flex');
|
$loader.css('display', 'flex');
|
||||||
$button.prop('disabled', true);
|
$button.prop('disabled', true);
|
||||||
$msg.removeClass().addClass('form-message').text('');
|
|
||||||
|
|
||||||
function postSubscribe(token) {
|
function postSubscribe(token) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|||||||
Reference in New Issue
Block a user