feat: select multiple filters on the dashboard

feat: add multi email recipients
feat: add option for also showing the original price on the dashboard
feat: open edit form after cloning subscription
fix: typo on export subscriptions to csv
chore: removed version line from docker-compose file
This commit is contained in:
Miguel Ribeiro
2024-09-01 22:19:06 +02:00
committed by GitHub
parent 0fb8fb272e
commit fed0192394
34 changed files with 364 additions and 119 deletions
@@ -42,7 +42,7 @@ while ($userToNotify = $usersToNotify->fetchArray(SQLITE3_ASSOC)) {
$email['smtpUsername'] = $row["smtp_username"];
$email['smtpPassword'] = $row["smtp_password"];
$email['fromEmail'] = $row["from_email"] ? $row["from_email"] : "wallos@wallosapp.com";
$email['otherEmail'] = $row["other_email"];
$email['otherEmails'] = $row["other_emails"];
}
// Check if Discord notifications are enabled and get the settings
@@ -217,8 +217,15 @@ while ($userToNotify = $usersToNotify->fetchArray(SQLITE3_ASSOC)) {
$mail->setFrom($email['fromEmail'], 'Wallos App');
$mail->addAddress($emailaddress, $name);
if (!empty($email['otherEmail'])) {
$list = explode(';', $email['otherEmail']);
if (!empty($email['otherEmails'])) {
$list = explode(';', $email['otherEmails']);
// Avoid duplicate emails
$list = array_unique($list);
$list = array_filter($list, function ($value) use ($emailaddress) {
return $value !== $emailaddress;
});
foreach($list as $value) {
$mail->addCC(trim($value));
}
+10 -3
View File
@@ -60,7 +60,7 @@ while ($userToNotify = $usersToNotify->fetchArray(SQLITE3_ASSOC)) {
$email['smtpUsername'] = $row["smtp_username"];
$email['smtpPassword'] = $row["smtp_password"];
$email['fromEmail'] = $row["from_email"] ? $row["from_email"] : "wallos@wallosapp.com";
$email['otherEmail'] = $row["other_email"];
$email['otherEmails'] = $row["other_emails"];
}
// Check if Discord notifications are enabled and get the settings
@@ -261,8 +261,15 @@ while ($userToNotify = $usersToNotify->fetchArray(SQLITE3_ASSOC)) {
$mail->setFrom($email['fromEmail'], 'Wallos App');
$mail->addAddress($emailaddress, $name);
if (!empty($email['otherEmail'])) {
$list = explode(';', $email['otherEmail']);
if (!empty($email['otherEmails'])) {
$list = explode(';', $email['otherEmails']);
// Avoid duplicate emails
$list = array_unique($list);
$list = array_filter($list, function ($value) use ($emailaddress) {
return $value !== $emailaddress;
});
foreach($list as $value) {
$mail->addCC(trim($value));
}
@@ -34,7 +34,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$smtpUsername = $data["smtpusername"];
$smtpPassword = $data["smtppassword"];
$fromEmail = $data["fromemail"];
$otherEmail = $data["otheremail"];
$otherEmails = $data["otheremails"];
$query = "SELECT COUNT(*) FROM email_notifications WHERE user_id = :userId";
$stmt = $db->prepare($query);
@@ -51,12 +51,12 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$row = $result->fetchArray();
$count = $row[0];
if ($count == 0) {
$query = "INSERT INTO email_notifications (enabled, smtp_address, smtp_port, smtp_username, smtp_password, from_email, other_email, encryption, user_id)
VALUES (:enabled, :smtpAddress, :smtpPort, :smtpUsername, :smtpPassword, :fromEmail, :otherEmail, :encryption, :userId)";
$query = "INSERT INTO email_notifications (enabled, smtp_address, smtp_port, smtp_username, smtp_password, from_email, other_emails, encryption, user_id)
VALUES (:enabled, :smtpAddress, :smtpPort, :smtpUsername, :smtpPassword, :fromEmail, :otherEmails, :encryption, :userId)";
} else {
$query = "UPDATE email_notifications
SET enabled = :enabled, smtp_address = :smtpAddress, smtp_port = :smtpPort,
smtp_username = :smtpUsername, smtp_password = :smtpPassword, from_email = :fromEmail, other_email = :otherEmail, encryption = :encryption WHERE user_id = :userId";
smtp_username = :smtpUsername, smtp_password = :smtpPassword, from_email = :fromEmail, other_emails = :otherEmails, encryption = :encryption WHERE user_id = :userId";
}
$stmt = $db->prepare($query);
@@ -66,7 +66,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$stmt->bindValue(':smtpUsername', $smtpUsername, SQLITE3_TEXT);
$stmt->bindValue(':smtpPassword', $smtpPassword, SQLITE3_TEXT);
$stmt->bindValue(':fromEmail', $fromEmail, SQLITE3_TEXT);
$stmt->bindValue(':otherEmail', $otherEmail, SQLITE3_TEXT);
$stmt->bindValue(':otherEmails', $otherEmails, SQLITE3_TEXT);
$stmt->bindValue(':encryption', $encryption, SQLITE3_TEXT);
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
@@ -0,0 +1,34 @@
<?php
require_once '../../includes/connect_endpoint.php';
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
die(json_encode([
"success" => false,
"message" => translate('session_expired', $i18n)
]));
}
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$postData = file_get_contents("php://input");
$data = json_decode($postData, true);
$show_original_price = $data['value'];
$stmt = $db->prepare('UPDATE settings SET show_original_price = :show_original_price WHERE user_id = :userId');
$stmt->bindParam(':show_original_price', $show_original_price, SQLITE3_INTEGER);
$stmt->bindParam(':userId', $userId, SQLITE3_INTEGER);
if ($stmt->execute()) {
die(json_encode([
"success" => true,
"message" => translate("success", $i18n)
]));
} else {
die(json_encode([
"success" => false,
"message" => translate("error", $i18n)
]));
}
}
?>
+2 -1
View File
@@ -40,7 +40,8 @@
if ($cloneStmt->execute()) {
$response = [
"success" => true,
"message" => translate('success', $i18n)
"message" => translate('success', $i18n),
"id" => $db->lastInsertRowID()
];
echo json_encode($response);
} else {
+44 -18
View File
@@ -28,28 +28,50 @@ if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
$params = array();
$sql = "SELECT * FROM subscriptions WHERE user_id = :userId";
if (isset($_GET['category']) && $_GET['category'] != "") {
$sql .= " AND category_id = :category";
$params[':category'] = $_GET['category'];
}
if (isset($_GET['categories']) && $_GET['categories'] != "") {
$allCategories = explode(',', $_GET['categories']);
$placeholders = array_map(function($idx) {
return ":categories{$idx}";
}, array_keys($allCategories));
if (isset($_GET['payments']) && $_GET['payments'] !== "") {
$sql .= " AND (";
$innerSql = [];
$idx = 0;
$allPayments = explode(',', $_GET['payments']);
foreach($allPayments as $payment) {
$innerSql[] = "payment_method_id = :payments{$idx}";
$params[':payments' . $idx] = $payment;
$idx++;
$sql .= " AND (" . implode(' OR ', array_map(function($placeholder) {
return "category_id = {$placeholder}";
}, $placeholders)) . ")";
foreach ($allCategories as $idx => $category) {
$params[":categories{$idx}"] = $category;
}
$sql .= implode(' OR ', $innerSql) . ")";
}
}
if (isset($_GET['member']) && $_GET['member'] != "") {
$sql .= " AND payer_user_id = :member";
$params[':member'] = $_GET['member'];
if (isset($_GET['payments']) && $_GET['payments'] !== "") {
$allPayments = explode(',', $_GET['payments']);
$placeholders = array_map(function($idx) {
return ":payments{$idx}";
}, array_keys($allPayments));
$sql .= " AND (" . implode(' OR ', array_map(function($placeholder) {
return "payment_method_id = {$placeholder}";
}, $placeholders)) . ")";
foreach ($allPayments as $idx => $payment) {
$params[":payments{$idx}"] = $payment;
}
}
if (isset($_GET['members']) && $_GET['members'] != "") {
$allMembers = explode(',', $_GET['members']);
$placeholders = array_map(function($idx) {
return ":members{$idx}";
}, array_keys($allMembers));
$sql .= " AND (" . implode(' OR ', array_map(function($placeholder) {
return "payer_user_id = {$placeholder}";
}, $placeholders)) . ")";
foreach ($allMembers as $idx => $member) {
$params[":members{$idx}"] = $member;
}
}
if (isset($_GET['state']) && $_GET['state'] != "") {
$sql .= " AND inactive = :inactive";
@@ -141,6 +163,10 @@ if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
if (isset($settings['showMonthlyPrice']) && $settings['showMonthlyPrice'] === 'true') {
$print[$id]['price'] = getPricePerMonth($cycle, $frequency, $print[$id]['price']);
}
if (isset($settings['showOriginalPrice']) && $settings['showOriginalPrice'] === 'true') {
$print[$id]['original_price'] = floatval($subscription['price']);
$print[$id]['original_currency_code'] = $currencies[$subscription['currency_id']]['code'];
}
}
if ($sortOrder == "alphanumeric") {
+1
View File
@@ -31,6 +31,7 @@ if ($settings) {
$settings['removeBackground'] = $settings['remove_background'] ? 'true': 'false';
$settings['hideDisabledSubscriptions'] = $settings['hide_disabled'] ? 'true': 'false';
$settings['disabledToBottom'] = $settings['disabled_to_bottom'] ? 'true': 'false';
$settings['showOriginalPrice'] = $settings['show_original_price'] ? 'true': 'false';
}
$query = "SELECT * FROM custom_colors WHERE user_id = :userId";
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP Benutzername",
"smtp_password" => "SMTP Passwort",
"from_email" => "Absender E-Mail Adresse (optional)",
"send_to_other_emails" => "Benachrichtigungen auch an die folgenden E-Mail-Adressen senden (verwende ; um sie zu trennen):",
"smtp_info" => "Das SMTP Passwort wird in Klartext übermittelt und gespeichert. Aus Sicherheitsgründen erstelle bitte einen gesonderten Account nur zu diesem Zweck.",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram Bot Token",
@@ -196,6 +197,8 @@ $i18n = [
"reset_custom_colors" => "Benutzerdefinierte Farben zurücksetzen",
"calculate_monthly_price" => "Berechne und zeige monatlichen Preis für alle Abonnements an",
"convert_prices" => "Preise immer in meine Hauptwährung umrechnen und darin anzeigen (langsamer)",
"show_original_price" => "Originalpreis anzeigen, wenn Umrechnungen oder Berechnungen durchgeführt werden",
"disabled_subscriptions" => "Deaktivierte Abonnements",
"hide_disabled_subscriptions" => "Deaktivierte Abonnements verstecken",
"show_disabled_subscriptions_at_the_bottom" => "Deaktivierte Abonnements am Ende anzeigen",
"experimental_settings" => "Experimentelle Einstellungen",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP χρήστης",
"smtp_password" => "SMTP κωδικός",
"from_email" => "Από (Προαιρετικό)",
"send_to_other_emails" => "Επίσης στείλτε ειδοποιήσεις στις ακόλουθες διευθύνσεις email (χρησιμοποιήστε ; για να τις διαχωρίσετε):",
"smtp_info" => "Ο κωδικός πρόσβασης SMTP μεταδίδεται και αποθηκεύεται σε απλό κείμενο. Για λόγους ασφαλείας, παρακαλούμε δημιούργησε έναν λογαριασμό μόνο γι' αυτό το σκοπό.",
"telegram" => "Telegram",
"telegram_bot_token" => "Τηλεγραφήματα Bot Token",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Αποθήκευση προσαρμοσμένου CSS",
"calculate_monthly_price" => "Υπολογισμός και εμφάνιση της μηνιαίας τιμής για όλες τις συνδρομές",
"convert_prices" => "Πάντα να μετατρέπει και να εμφανίζει τις τιμές στο κύριο νόμισμά μου (πιο αργό)",
"show_original_price" => "Εμφάνιση της αρχικής τιμής όταν γίνονται μετατροπές ή υπολογισμοί",
"disabled_subscriptions" => "Απενεργοποιημένες συνδρομές",
"hide_disabled_subscriptions" => "Απόκρυψη απενεργοποιημένων συνδρομών",
"show_disabled_subscriptions_at_the_bottom" => "Εμφάνιση απενεργοποιημένων συνδρομών στο τέλος",
"experimental_settings" => "Πειραματικές ρυθμίσεις",
+4 -1
View File
@@ -140,7 +140,8 @@ $i18n = [
"smtp_username" => "SMTP Username",
"smtp_password" => "SMTP Password",
"from_email" => "From email (Optional)",
"other_email" => "Other email (Use ; to separate)",
"send_to_other_emails" => "Also send notifications to the following email addresses (use ; to separate them):",
"other_emails_placeholder" => "user@domain.com;test@user.com",
"smtp_info" => "SMTP Password is transmitted and stored in plaintext. For security, please create an account just for this.",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram Bot Token",
@@ -197,6 +198,8 @@ $i18n = [
"save_custom_css" => "Save Custom CSS",
"calculate_monthly_price" => "Calculate and show monthly price for all subscriptions",
"convert_prices" => "Always convert and show prices on my main currency (slower)",
"show_original_price" => "Also show original price when conversions or calculations are made",
"disabled_subscriptions" => "Disabled Subscriptions",
"hide_disabled_subscriptions" => "Hide disabled subscriptions",
"show_disabled_subscriptions_at_the_bottom" => "Show disabled subscriptions at the bottom",
"experimental_settings" => "Experimental Settings",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Nombre de usuario SMTP",
"smtp_password" => "Contraseña SMTP",
"from_email" => "Correo electrónico de origen (Opcional)",
"send_to_other_emails" => "También enviar notificaciones a las siguientes direcciones de correo electrónico (use ; para separarlas):",
"smtp_info" => "La contraseña SMTP se transmite y almacena en texto plano. Por seguridad, crea una cuenta solo para esto.",
"telegram" => "Telegram",
"telegram_bot_token" => "Token del Bot de Telegram",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Guardar CSS Personalizado",
"calculate_monthly_price" => "Calcular y mostrar el precio mensual de todas las suscripciones",
"convert_prices" => "Convertir y mostrar siempre los precios en mi moneda principal (más lento)",
"show_original_price" => "Mostrar también el precio original cuando se realicen conversiones o cálculos",
"disabled_subscriptions" => "Suscripciones Desactivadas",
"hide_disabled_subscriptions" => "Ocultar suscripciones desactivadas",
"show_disabled_subscriptions_at_the_bottom" => "Mostrar suscripciones desactivadas al final",
"experimental_settings" => "Configuraciones Experimentales",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Nom d'utilisateur SMTP",
"smtp_password" => "Mot de passe SMTP",
"from_email" => "De l'adresse courriel (facultatif)",
"send_to_other_emails" => "Envoyer également des notifications aux adresses courriel suivantes (utilisez ; pour les séparer):",
"smtp_info" => "Le mot de passe SMTP est transmis et stocké en texte brut. Pour des raisons de sécurité, veuillez créer un compte uniquement à cette fin.",
"telegram" => "Telegram",
"telegram_bot_token" => "Jeton du bot Telegram",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Enregistrer le CSS personnalisé",
"calculate_monthly_price" => "Calculer et afficher le prix mensuel pour tous les abonnements",
"convert_prices" => "Convertir toujours et afficher les prix dans ma devise principale (plus lent)",
"show_original_price" => "Afficher également le prix original lorsque des conversions ou des calculs sont effectués",
"disabled_subscriptions" => "Abonnements désactivés",
"hide_disabled_subscriptions" => "Masquer les abonnements désactivés",
"show_disabled_subscriptions_at_the_bottom" => "Afficher les abonnements désactivés en bas",
"experimental_settings" => "Paramètres expérimentaux",
+2 -1
View File
@@ -148,7 +148,6 @@ $i18n = [
'smtp_username' => 'Nome utente SMTP',
'smtp_password' => 'Password SMTP',
'from_email' => 'Da quale e-mail (Opzionale)',
"other_email" => "Altre e-mail (Usa ; per separare)",
'smtp_info' => 'La password SMTP viene memorizzata e trasmessa in chiaro. Per motivi di sicurezza, si prega di creare un account da utilizzare solo per questo.',
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram Bot Token",
@@ -205,6 +204,8 @@ $i18n = [
"save_custom_css" => "Salva CSS personalizzato",
'calculate_monthly_price' => 'Calcola e mostra il prezzo mensile per tutti gli abbonamenti',
'convert_prices' => 'Converti sempre e mostra i prezzi nella mia valuta principale (più lento)',
"show_original_price" => "Mostra anche il prezzo originale quando vengono effettuate conversioni o calcoli",
"disabled_subscriptions" => 'Abbonamenti disattivati',
"hide_disabled_subscriptions" => 'Nascondi gli abbonamenti disattivati',
"show_disabled_subscriptions_at_the_bottom" => 'Mostra gli abbonamenti disattivati in fondo',
'experimental_settings' => 'Impostazioni sperimentali',
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTPユーザー名",
"smtp_password" => "SMTPパスワード",
"from_email" => "送信元アドレス (オプション)",
"send_to_other_emails" => "通知を以下のメールアドレスにも送信する(区切りには ; を使用):",
"smtp_info" => "SMTPパスワードは平文で送信および保存されます。セキュリティのため専用のアカウントを作成してください。",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegramボットトークン",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "カスタムCSSを保存",
"calculate_monthly_price" => "すべての定期購入の月額料金を計算して表示する",
"convert_prices" => "常にメイン通貨で価格を換算して表示する (遅い)",
"show_original_price" => "変換や計算が行われるときに元の価格も表示する",
"disabled_subscriptions" => "無効な定期購入",
"hide_disabled_subscriptions" => "無効な定期購入を非表示にする",
"show_disabled_subscriptions_at_the_bottom" => "無効な定期購入を一番下に表示する",
"experimental_settings" => "実験的な設定",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP 유저명",
"smtp_password" => "SMTP 비밀번호",
"from_email" => "발송 주소 (선택사항)",
"send_to_other_emails" => "알림을 다음 이메일 주소로도 보내기 (구분자는 ; 사용):",
"smtp_info" => "SMTP 비밀번호는 평문으로 저장되고 발송됩니다. 보안을 위해, 이 서비스를 위해서만 사용하는 계정을 생성해 주세요.",
"telegram" => "텔레그램",
"telegram_bot_token" => "텔레그램 봇 토큰",
@@ -197,6 +198,8 @@ $i18n = [
"save_custom_css" => "커스텀 CSS 저장",
"calculate_monthly_price" => "모든 구독에 대한 월별 요금을 계산하고 표시",
"convert_prices" => "항상 기본 통화로 가격을 환산하고 표시 (느림)",
"show_original_price" => "변환이나 계산이 이루어질 때 원래 가격도 표시",
"disabled_subscriptions" => "비활성화된 구독",
"hide_disabled_subscriptions" => "비활성화된 구독 숨기기",
"show_disabled_subscriptions_at_the_bottom" => "비활성화된 구독을 하단에 표시",
"experimental_settings" => "실험적 설정",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Nazwa użytkownika SMTP",
"smtp_password" => "Hasło SMTP",
"from_email" => "Z adresu e-mail (opcjonalnie)",
"send_to_other_emails" => "Wyślij powiadomienia również na następujące adresy e-mail (użyj ; aby je rozdzielić):",
"smtp_info" => "Hasło SMTP jest przesyłane i przechowywane w postaci zwykłego tekstu. Ze względów bezpieczeństwa utwórz konto tylko w tym celu.",
"telegram" => "Telegram",
"telegram_bot_token" => "Token bota",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Zapisz niestandardowy CSS",
"calculate_monthly_price" => "Oblicz i pokaż miesięczną cenę wszystkich subskrypcji",
"convert_prices" => "Zawsze przeliczaj i pokazuj ceny w mojej głównej walucie (wolniej)",
"show_original_price" => "Pokaż również oryginalną cenę, gdy dokonywane są przeliczenia lub obliczenia",
"disabled_subscriptions" => "Wyłączone subskrypcje",
"hide_disabled_subscriptions" => "Ukryj wyłączone subskrypcje",
"show_disabled_subscriptions_at_the_bottom" => "Pokaż wyłączone subskrypcje na dole",
"experimental_settings" => "Ustawienia eksperymentalne",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Utilizador SMTP",
"smtp_password" => "Password SMTP",
"from_email" => "Email de envio (Opcional)",
"send_to_other_emails" => "Também enviar notificações para os seguintes endereços de email (use ; para os separar):",
"smtp_info" => "A Password é armazenada e transmitida em texto. Por segurança, crie uma conta só para esta finalidade.",
"telegram" => "Telegram",
"telegram_bot_token" => "Token do Bot Telegram",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Guardar CSS Personalizado",
"calculate_monthly_price" => "Calcular e mostrar preço mensal para todas as subscrições",
"convert_prices" => "Converter e mostrar todas as subscrições na moeda principal (mais lento)",
"show_original_price" => "Também mostrar o preço original quando são feitas conversões ou cálculos",
"disabled_subscriptions" => "Subscrições Desactivadas",
"hide_disabled_subscriptions" => "Esconder subscrições desactivadas",
"show_disabled_subscriptions_at_the_bottom" => "Mostrar subscrições desactivadas no fundo da lista",
"experimental_settings" => "Definições Experimentais",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Usuário SMTP",
"smtp_password" => "Senha SMTP",
"from_email" => "Email de envio (Opcional)",
"send_to_other_emails" => "Também enviar notificações para os seguintes endereços de email (use ; para separá-los):",
"smtp_info" => "A senha do SMTP é transmitida em texto puro. Por segurança, crie uma conta só para esta finalidade.",
"telegram" => "Telegram",
"telegram_bot_token" => "Token do Bot",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Salvar CSS Personalizado",
"calculate_monthly_price" => "Calcular e exibir o custo mensal para todas as assinaturas",
"convert_prices" => "Sempre converter e exibir preços na moeda principal (mais lento)",
"show_original_price" => "Também mostrar o preço original quando conversões ou cálculos são feitos",
"disabled_subscriptions" => "Assinaturas desativadas",
"hide_disabled_subscriptions" => "Ocultar assinaturas desativadas",
"show_disabled_subscriptions_at_the_bottom" => "Mostre as assinaturas desativadas no final da lista",
"experimental_settings" => "Configurações experimentais",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Имя пользователя SMTP",
"smtp_password" => "Пароль SMTP",
"from_email" => "От кого E-Mail (необязательно)",
"send_to_other_emails" => "Также отправлять уведомления на следующие адреса электронной почты (используйте ; для их разделения):",
"smtp_info" => "Пароль SMTP передается и сохраняется в виде открытого текста. В целях безопасности создайте учетную запись только для Wallos.",
"telegram" => "Telegram",
"telegram_bot_token" => "Токен Telegram-бота",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Сохранить пользовательский CSS",
"calculate_monthly_price" => "Рассчитать и показать ежемесячную цену для всех подписок",
"convert_prices" => "Всегда конвертировать и показывать цены в моей основной валюте (медленнее)",
"show_original_price" => "Также показывать оригинальную цену при выполнении конверсий или расчетов",
"disabled_subscriptions" => "Отключенные подписки",
"hide_disabled_subscriptions" => "Скрыть отключенные подписки",
"show_disabled_subscriptions_at_the_bottom" => "Показать отключенные подписки внизу списка",
"experimental_settings" => "Экспериментальные настройки",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "Uporabniško ime SMTP",
"smtp_password" => "Geslo SMTP",
"from_email" => "Iz e-pošte (izbirno)",
"send_to_other_emails" => "Pošlji obvestila tudi na naslednje e-poštne naslove (uporabi ; za ločevanje):",
"smtp_info" => "Geslo SMTP se prenaša in shranjuje v navadnem besedilu. Zaradi varnosti ustvarite račun samo za to.",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram Bot žeton",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Shrani CSS po meri",
"calculate_monthly_price" => "Izračunaj in prikaži mesečno ceno za vse naročnine",
"convert_prices" => "Vedno pretvori in prikaži cene v moji glavni valuti (počasneje)",
"show_original_price" => "Prikaži tudi originalno ceno, ko se izvajajo pretvorbe ali izračuni",
"disabled_subscriptions" => "Onemogočene naročnine",
"hide_disabled_subscriptions" => "Skrij onemogočene naročnine",
"show_disabled_subscriptions_at_the_bottom" => "Prikaži onemogočene naročnine na dnu seznama",
"experimental_settings" => "Eksperimentalne nastavitve",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP корисничко име",
"smtp_password" => "SMTP лозинка",
"from_email" => "Од е-поште (Опционо)",
"send_to_other_emails" => "Такође пошаљите обавештења на следеће адресе е-поште (користите ; за њихово раздвајање):",
"smtp_info" => "SMTP лозинка се преноси и чува у обичном тексту. Из сигурносних разлога, молимо вас да направите налог само за ово.",
"telegram" => "Телеграм",
"telegram_bot_token" => "Телеграм бот токен",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Сачувај прилагођени CSS",
"calculate_monthly_price" => "Израчунајте и прикажите месечну цену за све претплате",
"convert_prices" => "Увек конвертујте и прикажите цене на мојој главној валути (спорије)",
"show_original_price" => "Прикажи и оригиналну цену када се врше конверзије или прорачуни",
"disabled_subscriptions" => "Онемогућене претплате",
"hide_disabled_subscriptions" => "Сакриј онемогућене претплате",
"show_disabled_subscriptions_at_the_bottom" => "Прикажи онемогућене претплате на дну",
"experimental_settings" => "Експериментална подешавања",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP korisničko ime",
"smtp_password" => "SMTP lozinka",
"from_email" => "Od e-pošte (Opciono)",
"send_to_other_emails" => "Takođe pošaljite obaveštenja na sledeće e-mail adrese (koristite ; za razdvajanje):",
"smtp_info" => "SMTP lozinka se prenosi i čuva u običnom tekstu. Iz sigurnosnih razloga, molimo vas da napravite nalog samo za ovo.",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram bot token",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Sačuvaj prilagođeni CSS",
"calculate_monthly_price" => "Izračunaj i prikaži mesečnu cenu za sve pretplate",
"convert_prices" => "Uvek konvertuj i prikaži cene u mojoj glavnoj valuti (sporije)",
"show_original_price" => "Prikaži i originalnu cenu kada se vrše konverzije ili proračuni",
"disabled_subscriptions" => "Onemogućene pretplate",
"hide_disabled_subscriptions" => "Sakrij onemogućene pretplate",
"show_disabled_subscriptions_at_the_bottom" => "Prikaži onemogućene pretplate na dnu",
"experimental_settings" => "Eksperimentalna podešavanja",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP Kullanıcı Adı",
"smtp_password" => "SMTP Şifresi",
"from_email" => "Gönderen e-posta (İsteğe bağlı)",
"send_to_other_emails" => "Bildirimleri aşağıdaki e-posta adreslerine de gönder (ayırmak için ; kullanın):",
"smtp_info" => "SMTP Şifresi düz metin olarak iletilir ve saklanır. Güvenlik için, lütfen bunun için özel bir hesap oluşturun.",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram Bot Token",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "Özel CSS'yi Kaydet",
"calculate_monthly_price" => "Tüm aboneliklerin aylık fiyatını hesaplayın ve gösterin",
"convert_prices" => "Fiyatları her zaman ana para birimimde dönüştürün ve gösterin (daha yavaş)",
"show_original_price" => "Dönüşümler veya hesaplamalar yapıldığında orijinal fiyatı da göster",
"disabled_subscriptions" => "Devre Dışı Bırakılan Abonelikler",
"hide_disabled_subscriptions" => "Devre dışı bırakılan abonelikleri gizle",
"show_disabled_subscriptions_at_the_bottom" => "Devre dışı bırakılan abonelikleri altta göster",
"experimental_settings" => "Deneysel Ayarlar",
+3
View File
@@ -148,6 +148,7 @@ $i18n = [
"smtp_username" => "SMTP 用户名",
"smtp_password" => "SMTP 密码",
"from_email" => "发件人邮箱(可选)",
"send_to_other_emails" => "还发送通知到以下电子邮件地址(使用 ; 分隔它们):",
"smtp_info" => "SMTP 密码以明文传输和存储。为安全起见,建议专门为 Wallos 创建一个账户。",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram 机器人令牌",
@@ -204,6 +205,8 @@ $i18n = [
"save_custom_css" => "保存自定义 CSS",
"calculate_monthly_price" => "计算并显示所有订阅的月价格",
"convert_prices" => "始终按我的主要货币转换和显示价格(较慢)",
"show_original_price" => "当进行转换或计算时,也显示原始价格",
"disabled_subscriptions" => "已停用的订阅",
"hide_disabled_subscriptions" => "隐藏已停用的订阅",
"show_disabled_subscriptions_at_the_bottom" => "在订阅列表底部显示已停用的订阅",
"experimental_settings" => "实验性设置",
+3
View File
@@ -140,6 +140,7 @@ $i18n = [
"smtp_username" => "SMTP 使用者名稱",
"smtp_password" => "SMTP 密碼",
"from_email" => "寄件人信箱(可選)",
"send_to_other_emails" => "還發送通知到以下電子郵件地址(使用 ; 分隔它們):",
"smtp_info" => "SMTP 密碼將以明文傳輸和儲存。為了安全起見,建議專門為 Wallos 建立一個帳戶。",
"telegram" => "Telegram",
"telegram_bot_token" => "Telegram 機器人令牌",
@@ -196,6 +197,8 @@ $i18n = [
"save_custom_css" => "儲存自訂 CSS",
"calculate_monthly_price" => "計算並顯示所有訂閱的每月價格",
"convert_prices" => "始終按照我的主要貨幣單位轉換和顯示價格(較慢)",
"show_original_price" => "當進行轉換或計算時,也顯示原始價格",
"disabled_subscriptions" => "停用的訂閱",
"hide_disabled_subscriptions" => "隱藏已停用的訂閱",
"show_disabled_subscriptions_at_the_bottom" => "將已停用的訂閱顯示在底部",
"experimental_settings" => "實驗性設定",
+15 -3
View File
@@ -118,9 +118,21 @@ function printSubscriptions($subscriptions, $sort, $categories, $members, $i18n,
<span class="cycle"><?= $subscription['billing_cycle'] ?></span>
<span class="next"><?= $subscription['next_payment'] ?></span>
<span class="price">
<img src="<?= $subscription['payment_method_icon'] ?>"
title="<?= translate('payment_method', $i18n) ?>: <?= $subscription['payment_method_name'] ?>" />
<?= CurrencyFormatter::format($subscription['price'], $subscription['currency_code']) ?>
<span class="payment_method">
<img src="<?= $subscription['payment_method_icon'] ?>"
title="<?= translate('payment_method', $i18n) ?>: <?= $subscription['payment_method_name'] ?>" />
</span>
<span class="value">
<?= CurrencyFormatter::format($subscription['price'], $subscription['currency_code']) ?>
<?php
if (isset($subscription['original_price']) && $subscription['original_price'] != $subscription['price']) {
?>
<span
class="original_price">(<?= CurrencyFormatter::format($subscription['original_price'], $subscription['original_currency_code']) ?>)</span>
<?php
}
?>
</span>
</span>
<button type="button" class="actions-expand" onClick="expandActions(event, <?= $subscription['id'] ?>)">
<i class="fas fa-ellipsis-v"></i>
+1 -1
View File
@@ -1,3 +1,3 @@
<?php
$version = "v2.22.1";
$version = "v2.23.0";
?>
+73 -6
View File
@@ -1,4 +1,5 @@
<?php
require_once 'includes/header.php';
require_once 'includes/getdbkeys.php';
@@ -27,8 +28,55 @@ if (isset($_COOKIE['sortOrder']) && $_COOKIE['sortOrder'] != "") {
$sort = "next_payment";
}
$params = array();
$sql = "SELECT * FROM subscriptions WHERE user_id = :userId";
if (isset($_GET['member'])) {
$memberIds = explode(',', $_GET['member']);
$placeholders = array_map(function ($key) {
return ":member{$key}";
}, array_keys($memberIds));
$sql .= " AND payer_user_id IN (" . implode(',', $placeholders) . ")";
foreach ($memberIds as $key => $memberId) {
$params[":member{$key}"] = $memberId;
}
}
if (isset($_GET['category'])) {
$categoryIds = explode(',', $_GET['category']);
$placeholders = array_map(function ($key) {
return ":category{$key}";
}, array_keys($categoryIds));
$sql .= " AND category_id IN (" . implode(',', $placeholders) . ")";
foreach ($categoryIds as $key => $categoryId) {
$params[":category{$key}"] = $categoryId;
}
}
if (isset($_GET['payment'])) {
$paymentIds = explode(',', $_GET['payment']);
$placeholders = array_map(function ($key) {
return ":payment{$key}";
}, array_keys($paymentIds));
$sql .= " AND payment_method_id IN (" . implode(',', $placeholders) . ")";
foreach ($paymentIds as $key => $paymentId) {
$params[":payment{$key}"] = $paymentId;
}
}
if (!isset($settings['hideDisabledSubscriptions']) || $settings['hideDisabledSubscriptions'] !== 'true') {
if (isset($_GET['state']) && $_GET['state'] != "") {
$sql .= " AND inactive = :inactive";
$params[':inactive'] = $_GET['state'];
}
}
$orderByClauses = [];
if ($settings['disabledToBottom'] === 'true') {
@@ -55,6 +103,12 @@ if (isset($_COOKIE['sortOrder']) && $_COOKIE['sortOrder'] != "") {
$stmt = $db->prepare($sql);
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
foreach ($params as $key => $value) {
$stmt->bindValue($key, $value, SQLITE3_INTEGER);
}
$result = $stmt->execute();
if ($result) {
$subscriptions = array();
@@ -113,8 +167,11 @@ $headerClass = count($subscriptions) > 0 ? "main-actions" : "main-actions hidden
<?php
foreach ($members as $member) {
$selectedClass = '';
if (isset($_GET['member']) && $_GET['member'] == $member['id']) {
$selectedClass = 'selected';
if (isset($_GET['member'])) {
$memberIds = explode(',', $_GET['member']);
if (in_array($member['id'], $memberIds)) {
$selectedClass = 'selected';
}
}
?>
<div class="filter-item <?= $selectedClass ?>" data-memberid="<?= $member['id'] ?>"><?= $member['name'] ?>
@@ -139,8 +196,11 @@ $headerClass = count($subscriptions) > 0 ? "main-actions" : "main-actions hidden
$category['name'] = translate("no_category", $i18n);
}
$selectedClass = '';
if (isset($_GET['category']) && $_GET['category'] == $category['id']) {
$selectedClass = 'selected';
if (isset($_GET['category'])) {
$categoryIds = explode(',', $_GET['category']);
if (in_array($category['id'], $categoryIds)) {
$selectedClass = 'selected';
}
}
?>
<div class="filter-item <?= $selectedClass ?>" data-categoryid="<?= $category['id'] ?>">
@@ -163,8 +223,11 @@ $headerClass = count($subscriptions) > 0 ? "main-actions" : "main-actions hidden
<?php
foreach ($payment_methods as $payment) {
$selectedClass = '';
if (isset($_GET['payment']) && in_array( $payment['id'], $_GET['payment'])) {
$selectedClass = 'selected';
if (isset($_GET['payment'])) {
$paymentIds = explode(',', $_GET['payment']);
if (in_array($payment['id'], $paymentIds)) {
$selectedClass = 'selected';
}
}
?>
<div class="filter-item <?= $selectedClass ?>" data-paymentid="<?= $payment['id'] ?>">
@@ -276,6 +339,10 @@ $headerClass = count($subscriptions) > 0 ? "main-actions" : "main-actions hidden
if (isset($settings['showMonthlyPrice']) && $settings['showMonthlyPrice'] === 'true') {
$print[$id]['price'] = getPricePerMonth($cycle, $frequency, $print[$id]['price']);
}
if (isset($settings['showOriginalPrice']) && $settings['showOriginalPrice'] === 'true') {
$print[$id]['original_price'] = floatval($subscription['price']);
$print[$id]['original_currency_code'] = $currencies[$subscription['currency_id']]['code'];
}
}
if ($sortOrder == "alphanumeric") {
+11 -3
View File
@@ -1,10 +1,18 @@
<?php
// This migration adds a "other_email" column to the email_notifications table.
// This migration adds a "other_emails" column to the email_notifications table.
// It also adds a "show_original_price" column to the settings table.
/** @noinspection PhpUndefinedVariableInspection */
$columnQuery = $db->query("SELECT * FROM pragma_table_info('email_notifications') where name='other_email'");
$columnQuery = $db->query("SELECT * FROM pragma_table_info('email_notifications') where name='other_emails'");
$columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false;
if ($columnRequired) {
$db->exec('ALTER TABLE email_notifications ADD COLUMN other_email TEXT DEFAULT "";');
$db->exec('ALTER TABLE email_notifications ADD COLUMN other_emails TEXT DEFAULT "";');
}
$columnQuery = $db->query("SELECT * FROM pragma_table_info('settings') where name='show_original_price'");
$columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false;
if ($columnRequired) {
$db->exec('ALTER TABLE settings ADD COLUMN show_original_price BOOLEAN DEFAULT 0');
}
+56 -60
View File
@@ -207,7 +207,8 @@ function cloneSubscription(event, id) {
})
.then(data => {
if (data.success) {
fetchSubscriptions();
const id = data.id;
fetchSubscriptions(id, event);
showSuccessMessage(decodeURI(data.message));
} else {
showErrorMessage(data.message || translate('error'));
@@ -288,15 +289,15 @@ function closeLogoSearch() {
logoResults.innerHTML = "";
}
function fetchSubscriptions() {
function fetchSubscriptions(id, event) {
const subscriptionsContainer = document.querySelector("#subscriptions");
let getSubscriptions = "endpoints/subscriptions/get.php";
if (activeFilters['category'] !== "") {
getSubscriptions += `?category=${activeFilters['category']}`;
if (activeFilters['categories'].length > 0) {
getSubscriptions += `?categories=${activeFilters['categories']}`;
}
if (activeFilters['member'] !== "") {
getSubscriptions += getSubscriptions.includes("?") ? `&member=${activeFilters['member']}` : `?member=${activeFilters['member']}`;
if (activeFilters['members'].length > 0) {
getSubscriptions += getSubscriptions.includes("?") ? `&members=${activeFilters['members']}` : `?members=${activeFilters['members']}`;
}
if (activeFilters['payments'].length > 0) {
getSubscriptions += getSubscriptions.includes("?") ? `&payments=${activeFilters['payments']}` : `?payments=${activeFilters['payments']}`;
@@ -317,6 +318,10 @@ function fetchSubscriptions() {
mainActions.classList.remove("hidden");
}
}
if (id && event) {
openEditSubscription(event, id);
}
})
.catch(error => {
console.error(translate('error_reloading_subscription'), error);
@@ -346,18 +351,18 @@ function convertSvgToPng(file, callback) {
const reader = new FileReader();
reader.onload = function (e) {
const img = new Image();
img.src = e.target.result;
img.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
const pngDataUrl = canvas.toDataURL('image/png');
const pngFile = dataURLtoFile(pngDataUrl, file.name.replace(".svg", ".png"));
callback(pngFile);
};
const img = new Image();
img.src = e.target.result;
img.onload = function () {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
const pngDataUrl = canvas.toDataURL('image/png');
const pngFile = dataURLtoFile(pngDataUrl, file.name.replace(".svg", ".png"));
callback(pngFile);
};
};
reader.readAsDataURL(file);
@@ -365,16 +370,16 @@ function convertSvgToPng(file, callback) {
function dataURLtoFile(dataurl, filename) {
let arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
return new File([u8arr], filename, { type: mime });
}
function submitFormData(formData, submitButton, endpoint) {
@@ -403,7 +408,7 @@ document.addEventListener('DOMContentLoaded', function () {
subscriptionForm.addEventListener("submit", function (e) {
e.preventDefault();
submitButton.disabled = true;
const formData = new FormData(subscriptionForm);
@@ -411,12 +416,12 @@ document.addEventListener('DOMContentLoaded', function () {
const file = fileInput.files[0];
if (file && file.type === "image/svg+xml") {
convertSvgToPng(file, function(pngFile) {
formData.set("logo", pngFile);
submitFormData(formData, submitButton, endpoint);
});
} else {
convertSvgToPng(file, function (pngFile) {
formData.set("logo", pngFile);
submitFormData(formData, submitButton, endpoint);
});
} else {
submitFormData(formData, submitButton, endpoint);
}
});
@@ -459,8 +464,8 @@ function closeSubMenus() {
}
const activeFilters = [];
activeFilters['category'] = "";
activeFilters['member'] = "";
activeFilters['categories'] = [];
activeFilters['members'] = [];
activeFilters['payments'] = [];
activeFilters['state'] = "";
@@ -502,41 +507,32 @@ document.querySelectorAll('.filter-item').forEach(function (item) {
if (this.hasAttribute('data-categoryid')) {
const categoryId = this.getAttribute('data-categoryid');
if (activeFilters['category'] === categoryId) {
activeFilters['category'] = "";
if (activeFilters['categories'].includes(categoryId)) {
const categoryIndex = activeFilters['categories'].indexOf(categoryId);
activeFilters['categories'].splice(categoryIndex, 1);
this.classList.remove('selected');
} else {
activeFilters['category'] = categoryId;
Array.from(this.parentNode.children).forEach(sibling => {
sibling.classList.remove('selected');
});
activeFilters['categories'].push(categoryId);
this.classList.add('selected');
}
} else if (this.hasAttribute('data-memberid')) {
const memberId = this.getAttribute('data-memberid');
if (activeFilters['member'] === memberId) {
activeFilters['member'] = "";
this.classList.remove('selected');
} else {
activeFilters['member'] = memberId;
Array.from(this.parentNode.children).forEach(sibling => {
sibling.classList.remove('selected');
});
this.classList.add('selected');
}
if (activeFilters['members'].includes(memberId)) {
const memberIndex = activeFilters['members'].indexOf(memberId);
activeFilters['members'].splice(memberIndex, 1);
this.classList.remove('selected');
} else {
activeFilters['members'].push(memberId);
this.classList.add('selected');
}
} else if (this.hasAttribute('data-paymentid')) {
const paymentId = this.getAttribute('data-paymentid');
if (activeFilters['payments'].includes(paymentId)) {
const index = activeFilters['payments'].indexOf(paymentId);
activeFilters['payments'].splice(index, 1);
const paymentIndex = activeFilters['payments'].indexOf(paymentId);
activeFilters['payments'].splice(paymentIndex, 1);
this.classList.remove('selected');
} else {
activeFilters['payments'].push(paymentId);
/*
Array.from(this.parentNode.children).forEach(sibling => {
sibling.classList.remove('selected');
});
*/
this.classList.add('selected');
}
} else if (this.hasAttribute('data-state')) {
@@ -553,7 +549,7 @@ document.querySelectorAll('.filter-item').forEach(function (item) {
}
}
if (activeFilters['category'] !== "" || activeFilters['member'] !== "" || activeFilters['payments'].length > 0) {
if (activeFilters['categories'].length > 0 || activeFilters['members'].length > 0 || activeFilters['payments'].length > 0) {
document.querySelector('#clear-filters').classList.remove('hide');
} else {
document.querySelector('#clear-filters').classList.add('hide');
@@ -566,8 +562,8 @@ document.querySelectorAll('.filter-item').forEach(function (item) {
function clearFilters() {
const searchInput = document.querySelector("#search");
searchInput.value = "";
activeFilters['category'] = "";
activeFilters['member'] = "";
activeFilters['categories'] = [];
activeFilters['members'] = [];
activeFilters['payments'] = [];
document.querySelectorAll('.filter-item').forEach(function (item) {
item.classList.remove('selected');
+2 -2
View File
@@ -65,7 +65,7 @@ function saveNotificationsEmailButton() {
const smtpUsername = document.getElementById("smtpusername").value;
const smtpPassword = document.getElementById("smtppassword").value;
const fromEmail = document.getElementById("fromemail").value;
const otherEmail = document.getElementById("otheremail").value;
const otherEmails = document.getElementById("otheremails").value;
const data = {
enabled: enabled,
@@ -75,7 +75,7 @@ function saveNotificationsEmailButton() {
smtpusername: smtpUsername,
smtppassword: smtpPassword,
fromemail: fromEmail,
otheremail: otherEmail
otheremails: otherEmails
};
makeFetchCall('endpoints/notifications/saveemailnotifications.php', data, button);
+7
View File
@@ -927,6 +927,13 @@ function setDisabledToBottom() {
storeSettingsOnDB('disabled_to_bottom', value);
}
function setShowOriginalPrice() {
const showOriginalPriceCheckbox = document.querySelector("#showoriginalprice");
const value = showOriginalPriceCheckbox.checked;
storeSettingsOnDB('show_original_price', value);
}
function saveCategorySorting() {
const categories = document.getElementById('categories');
const categoryIds = Array.from(categories.children).map(category => category.dataset.categoryid);
+22 -5
View File
@@ -249,7 +249,7 @@ require_once 'includes/header.php';
$notificationsEmail['smtp_username'] = $row['smtp_username'];
$notificationsEmail['smtp_password'] = $row['smtp_password'];
$notificationsEmail['from_email'] = $row['from_email'];
$notificationsEmail['other_email'] = $row['other_email'];
$notificationsEmail['other_emails'] = $row['other_emails'];
$rowCount++;
}
@@ -261,7 +261,7 @@ require_once 'includes/header.php';
$notificationsEmail['smtp_username'] = "";
$notificationsEmail['smtp_password'] = "";
$notificationsEmail['from_email'] = "";
$notificationsEmail['other_email'] = "";
$notificationsEmail['other_emails'] = "";
}
// Discord notifications
@@ -483,10 +483,11 @@ require_once 'includes/header.php';
placeholder="<?= translate('from_email', $i18n) ?>"
value="<?= $notificationsEmail['from_email'] ?>" />
</div>
<label for="otheremails" ><?= translate('send_to_other_emails', $i18n) ?></label>
<div class="form-group-inline">
<input type="text" name="otheremail" id="otheremail"
placeholder="<?= translate('other_email', $i18n) ?>"
value="<?= $notificationsEmail['other_email'] ?>" />
<input type="text" name="otheremails" id="otheremails"
placeholder="<?= translate('other_emails_placeholder', $i18n) ?>"
value="<?= $notificationsEmail['other_emails'] ?>" />
</div>
<div class="buttons">
<input type="button" class="secondary-button thin mobile-grow"
@@ -1212,6 +1213,7 @@ require_once 'includes/header.php';
<h2><?= translate('display_settings', $i18n) ?></h2>
</header>
<div class="account-settings-list">
<h3><?= translate('price', $i18n) ?></h3>
<div>
<div class="form-group-inline">
<input type="checkbox" id="monthlyprice" name="monthlyprice" onChange="setShowMonthlyPrice()" <?php if ($settings['monthly_price'])
@@ -1231,6 +1233,21 @@ require_once 'includes/header.php';
<label for="convertcurrency"><?= translate('convert_prices', $i18n) ?></label>
</div>
</div>
<div>
<div class="form-group-inline">
<input type="checkbox" id="showoriginalprice" name="showoriginalprice" onChange="setShowOriginalPrice()" <?php if ($settings['show_original_price'])
echo 'checked'; ?>>
<label for="showoriginalprice"><?= translate('show_original_price', $i18n) ?></label>
</div>
</div>
<h3><?= translate('disabled_subscriptions', $i18n) ?></h3>
<div>
<div class="form-group-inline">
<input type="checkbox" id="disabledtobottom" name="disabledtobottom" onChange="setDisabledToBottom()" <?php if ($settings['disabled_to_bottom'])
echo 'checked'; ?>>
<label for="disabledtobottom"><?= translate('show_disabled_subscriptions_at_the_bottom', $i18n) ?></label>
</div>
</div>
<div>
<div class="form-group-inline">
<input type="checkbox" id="hidedisabled" name="hidedisabled" onChange="setHideDisabled()" <?php if ($settings['hide_disabled'])
+17 -7
View File
@@ -459,12 +459,7 @@ button:hover svg .main-color {
flex-grow: 1;
}
.subscription .price {
flex-basis: 12%;
justify-content: flex-start;
}
.subscription .price img {
.subscription .payment_method img {
width: 45px;
height: 30px;
aspect-ratio: 3 / 2;
@@ -472,12 +467,23 @@ button:hover svg .main-color {
margin-right: 12px;
}
.rtl .subscription .price img {
.rtl .subscription .payment_method img {
margin-right: 0px;
margin-left: 12px;
}
.subscription .price {
flex-basis: 8%;
justify-content: flex-start;
flex-direction: row;
}
.subscription .price .original_price {
font-size: 14px;
color: #888;
}
.subscription .actions {
flex-basis: auto;
}
@@ -617,6 +623,10 @@ button:hover svg .main-color {
margin-bottom: 0px;
}
.account-section .account-settings-list h3 {
margin: 0px;
}
.account-section .account-settings-theme h3 {
margin-bottom: 24px;
}