mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-06-26 04:00:34 +02:00
Merge commit 'c3fc1347ec850d0b2f94b4e12db94f6dc1d4b808' into weekly
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
"autoprefixer": "^6.2.3",
|
||||
"bcryptjs": "~2.3.0",
|
||||
"body-parser": "^1.9.0",
|
||||
"chart.js": "^1.0.2",
|
||||
"chart.js": "^2.1.0",
|
||||
"colors": "^1.1.0",
|
||||
"compression": "^1.1.0",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
@@ -57,7 +57,7 @@
|
||||
"nodebb-plugin-spam-be-gone": "0.4.9",
|
||||
"nodebb-rewards-essentials": "0.0.9",
|
||||
"nodebb-theme-lavender": "3.0.13",
|
||||
"nodebb-theme-persona": "4.1.11",
|
||||
"nodebb-theme-persona": "4.1.12",
|
||||
"nodebb-theme-vanilla": "5.1.3",
|
||||
"nodebb-widget-essentials": "2.0.10",
|
||||
"nodemailer": "2.0.0",
|
||||
@@ -117,4 +117,4 @@
|
||||
"url": "https://github.com/barisusakli"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
"share_this_category": "انشر هذه الفئة",
|
||||
"watch": "تابع",
|
||||
"ignore": "تجاهل",
|
||||
"watching": "Watching",
|
||||
"ignoring": "Ignoring",
|
||||
"watching.description": "Show topics in unread",
|
||||
"ignoring.description": "Do not show topics in unread",
|
||||
"watch.message": "أنت اﻷن متابع لتحديثات هذه الفئة",
|
||||
"watching": "متابع",
|
||||
"ignoring": "متجاهل",
|
||||
"watching.description": "أظهر المواضيع في غير مقروء",
|
||||
"ignoring.description": "لا تظهر المواضيع في غير مقروء",
|
||||
"watch.message": "أنت اﻷن تتابع تحديثات هذه الفئة",
|
||||
"ignore.message": "أنت اﻷن تتجاهل تحديثات هذه الفئة",
|
||||
"watched-categories": "الفئات المراقبه"
|
||||
"watched-categories": "الفئات المتابعة"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Потребителят не е в стаята",
|
||||
"no-users-in-room": "Няма потребители в тази стая",
|
||||
"cant-kick-self": "Не можете да изритате себе си от групата",
|
||||
"no-users-selected": "Няма избран(и) потребител(и)"
|
||||
"no-users-selected": "Няма избран(и) потребител(и)",
|
||||
"invalid-home-page-route": "Грешен път към началната страница"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "Nemůžete vyhodit sami sebe ze kupiny",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Bruger er ikke i rummet",
|
||||
"no-users-in-room": "Ingen brugere i rummet",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Benutzer nicht im Raum",
|
||||
"no-users-in-room": "In diesem Raum befinden sich keine Benutzer.",
|
||||
"cant-kick-self": "Du kannst dich nicht selber aus der Gruppe entfernen.",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
"email-taken": "Email taken",
|
||||
"email-not-confirmed": "Your email has not been confirmed yet, please click here to confirm your email.",
|
||||
"email-not-confirmed-chat": "You are unable to chat until your email is confirmed, please click here to confirm your email.",
|
||||
"email-not-confirmed-email-sent": "Your email has not been confirmed yet, please check your inbox for the confirmation email.",
|
||||
"no-email-to-confirm": "This forum requires email confirmation, please click here to enter an email",
|
||||
"email-confirm-failed": "We could not confirm your email, please try again later.",
|
||||
"confirm-email-already-sent": "Confirmation email already sent, please wait %1 minute(s) to send another one.",
|
||||
|
||||
@@ -116,5 +116,7 @@
|
||||
"enter_page_number": "Enter page number",
|
||||
"upload_file": "Upload file",
|
||||
"upload": "Upload",
|
||||
"allowed-file-types": "Allowed file types are %1"
|
||||
"allowed-file-types": "Allowed file types are %1",
|
||||
|
||||
"unsaved-changes": "You have unsaved changes. Are you sure you wish to navigate away?"
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
"alternative_logins": "Alternative Logins",
|
||||
"failed_login_attempt": "Login Unsuccessful",
|
||||
"login_successful": "You have successfully logged in!",
|
||||
"dont_have_account": "Don't have an account?"
|
||||
"dont_have_account": "Don't have an account?",
|
||||
"logged-out-due-to-inactivity": "You have been logged out due to inactivity"
|
||||
}
|
||||
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "El usuario no está en la sala",
|
||||
"no-users-in-room": "No hay usuarios en esta sala",
|
||||
"cant-kick-self": "No te puedes expulsar a ti mismo del grupo",
|
||||
"no-users-selected": "Ningun usuario(s) seleccionado"
|
||||
"no-users-selected": "Ningun usuario(s) seleccionado",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Kasutaja pole ruumis",
|
||||
"no-users-in-room": "Ühtegi kasutajat ei leidu siit ruumist",
|
||||
"cant-kick-self": "Sa ei saa ennast ära visata gruppist",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "هیچ کاربری در این گفتگو نیست",
|
||||
"no-users-in-room": "هیچ کاربری در این گفتگو نیست",
|
||||
"cant-kick-self": "شما نمی توانید خودتان را از گروه کیک کنید",
|
||||
"no-users-selected": "هیچ کاربر(های) انتخاب نشده"
|
||||
"no-users-selected": "هیچ کاربر(های) انتخاب نشده",
|
||||
"invalid-home-page-route": "مسیر صفحه اصلی نامعتبر است"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Käyttäjä ei ole huoneessa",
|
||||
"no-users-in-room": "Ei käyttäjiä tässä huoneessa",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "L'utilisateur n'est pas dans cette salle",
|
||||
"no-users-in-room": "Aucun utilisateur dans cette salle",
|
||||
"cant-kick-self": "Vous ne pouvez pas vous exclure vous-même du groupe",
|
||||
"no-users-selected": "Aucun utilisateur sélectionné"
|
||||
"no-users-selected": "Aucun utilisateur sélectionné",
|
||||
"invalid-home-page-route": "Route de page d'accueil invalide"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "O usuario non se encontra nesta sala",
|
||||
"no-users-in-room": "Non hai usuarios nesta sala",
|
||||
"cant-kick-self": "Non te podes expulsar a ti mesmo do grupo",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "משתמש זה לא בצ'אט",
|
||||
"no-users-in-room": "אין משתמש בחדר הזה",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "없는 사용자입니다.",
|
||||
"no-users-in-room": "사용자가 없습니다.",
|
||||
"cant-kick-self": "스스로 이 그룹을 탈퇴할 수 없습니다.",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Pengguna tiada dalam bilik",
|
||||
"no-users-in-room": "Tiada pengguna dalam bilik ini",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -10,10 +10,10 @@
|
||||
"share_this_category": "Deel deze categorie",
|
||||
"watch": "Volgen",
|
||||
"ignore": "Negeren",
|
||||
"watching": "Watching",
|
||||
"ignoring": "Ignoring",
|
||||
"watching.description": "Show topics in unread",
|
||||
"ignoring.description": "Do not show topics in unread",
|
||||
"watching": "Volgend",
|
||||
"ignoring": "Negerend",
|
||||
"watching.description": "Toon ongelezen onderwerpen",
|
||||
"ignoring.description": "Toon geen onderwerpen onder onder ongelezen onderwerpen",
|
||||
"watch.message": "Van deze categorie worden nu meldingen ontvangen",
|
||||
"ignore.message": "Er worden geen meldingen van deze categorie ontvangen",
|
||||
"watched-categories": "Categorieën die bekeken zijn."
|
||||
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Gebruiker niet in de chat",
|
||||
"no-users-in-room": "Er zijn geen gebruikers in deze chat",
|
||||
"cant-kick-self": "Je kunt jezelf niet uit een groep schoppen",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -31,8 +31,8 @@
|
||||
"flag_success": "Dit bericht is gerapporteerd aan de beheerder.",
|
||||
"deleted_message": "Dit onderwerp is verwijderd. Alleen gebruikers met beheerrechten op onderwerpniveau kunnen dit inzien.",
|
||||
"following_topic.message": "Vanaf nu worden meldingen ontvangen zodra iemand een reactie op dit onderwerp geeft.",
|
||||
"not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.",
|
||||
"ignoring_topic.message": "You will no longer see this topic in the unread topics list. You will be notified when you are mentioned or your post is up voted.",
|
||||
"not_following_topic.message": "Dit onderwerp zal verschijnen in de lijst van ongelezen onderwerpen, maar er zullen geen meldingen ontvangen zodra iemand een reactie op dit onderwerp geeft.",
|
||||
"ignoring_topic.message": "Dit onderwerp zal niet meer verschijnen in de lijst van ongelezen berichten. U zult enkel een melding ontvangen wanneer u wordt genoemd, of wanneer er een positieve stem op uw reactie wordt gegeven.",
|
||||
"login_to_subscribe": "Log in or registreer om dit onderwerp te volgen.",
|
||||
"markAsUnreadForAll.success": "Onderwerp is voor iedereen als ongelezen gemarkeerd.",
|
||||
"mark_unread": "Ongelezen markeren",
|
||||
@@ -45,9 +45,9 @@
|
||||
"watching": "Gevolgd",
|
||||
"not-watching": "Niet gevolgd",
|
||||
"ignoring": "Genegeerd",
|
||||
"watching.description": "Notify me of new replies.<br/>Show topic in unread.",
|
||||
"not-watching.description": "Do not notify me of new replies.<br/>Show topic in unread if category is not ignored.",
|
||||
"ignoring.description": "Do not notify me of new replies.<br/>Do not show topic in unread.",
|
||||
"watching.description": "Stuur me een melding bij nieuwe reacties.<br/>Toon onderwerp bij de ongelezen onderwerpen.",
|
||||
"not-watching.description": "Stuur me geen melding van nieuwe reacties.<br/>Toon onderwerp in ongelezen mits de categorie niet genegeerd wordt.",
|
||||
"ignoring.description": "Stuur me geen melding van nieuwe reacties.<br/>Toon dit onderwerp niet onder de ongelezen onderwerpen.",
|
||||
"thread_tools.title": "Acties",
|
||||
"thread_tools.markAsUnreadForAll": "Ongelezen markeren",
|
||||
"thread_tools.pin": "Onderwerp vastpinnen",
|
||||
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Użytkownik nie jest w pokoju",
|
||||
"no-users-in-room": "Brak użytkowników w pokoju",
|
||||
"cant-kick-self": "Nie możesz wyrzucić samego siebie z grupy",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -10,10 +10,10 @@
|
||||
"share_this_category": "Compartilhar esta categoria",
|
||||
"watch": "Acompanhar",
|
||||
"ignore": "Ignorar",
|
||||
"watching": "Watching",
|
||||
"ignoring": "Ignoring",
|
||||
"watching.description": "Show topics in unread",
|
||||
"ignoring.description": "Do not show topics in unread",
|
||||
"watching": "Assistindo",
|
||||
"ignoring": "Ignorando",
|
||||
"watching.description": "Mostrar tópicos em não-lido",
|
||||
"ignoring.description": "Não mostrar tópicos em não-lido",
|
||||
"watch.message": "Agora você está acompanhando as atualizações desta categoria",
|
||||
"ignore.message": "Agora você está ignorando as atualizações desta categoria",
|
||||
"watched-categories": "Categorias acompanhadas"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"user-banned": "Usuário banido",
|
||||
"user-too-new": "Desculpe, é necessário que você aguarde %1 segundo(s) antes de fazer o seu primeiro post.",
|
||||
"blacklisted-ip": "Desculpe, o seu endereço IP foi banido desta comunidade. Se você acha que isso é um engano, por favor contate um administrador.",
|
||||
"ban-expiry-missing": "Please provide an end date for this ban",
|
||||
"ban-expiry-missing": "Por favor forneça uma data para o fim deste banimento",
|
||||
"no-category": "A categoria não existe",
|
||||
"no-topic": "O tópico não existe",
|
||||
"no-post": "O post não existe",
|
||||
@@ -47,13 +47,13 @@
|
||||
"post-edit-duration-expired-hours-minutes": "Você pode apenas editar posts por %1 hora(s) e %2 minuto(s) após postar",
|
||||
"post-edit-duration-expired-days": "Você pode apenas editar posts por %1 dia(s) após postar",
|
||||
"post-edit-duration-expired-days-hours": "Você pode apenas editar posts por %1 dia(s) e %2 hora(s) após postar",
|
||||
"post-delete-duration-expired": "You are only allowed to delete posts for %1 second(s) after posting",
|
||||
"post-delete-duration-expired-minutes": "You are only allowed to delete posts for %1 minute(s) after posting",
|
||||
"post-delete-duration-expired-minutes-seconds": "You are only allowed to delete posts for %1 minute(s) %2 second(s) after posting",
|
||||
"post-delete-duration-expired-hours": "You are only allowed to delete posts for %1 hour(s) after posting",
|
||||
"post-delete-duration-expired-hours-minutes": "You are only allowed to delete posts for %1 hour(s) %2 minute(s) after posting",
|
||||
"post-delete-duration-expired-days": "You are only allowed to delete posts for %1 day(s) after posting",
|
||||
"post-delete-duration-expired-days-hours": "You are only allowed to delete posts for %1 day(s) %2 hour(s) after posting",
|
||||
"post-delete-duration-expired": "Você só pode deletar posts por %1 segundo(s) depois de postar",
|
||||
"post-delete-duration-expired-minutes": "Você só pode deletar posts por %1 minuto(s) depois de postar",
|
||||
"post-delete-duration-expired-minutes-seconds": "Você só pode deletar posts por %1 minuto(s) e %2 segundo(s) depois de postar",
|
||||
"post-delete-duration-expired-hours": "Você só pode deletar posts por %1 hora(s) depois de postar",
|
||||
"post-delete-duration-expired-hours-minutes": "Você só pode deletar posts por %1 hora(s) e %2 minutos(s) depois de postar",
|
||||
"post-delete-duration-expired-days": "Você só pode deletar posts por %1 dia(s) depois de postar",
|
||||
"post-delete-duration-expired-days-hours": "Você só pode deletar posts por %1 dia(s) e %2 hora(s) depois de postar",
|
||||
"content-too-short": "Por favor digite um post maior. Posts precisam conter ao menos %1 caractere(s).",
|
||||
"content-too-long": "Por favor digite um post mais curto. Posts não podem ser maiores que %1 caractere(s)",
|
||||
"title-too-short": "Por favor digite um título maior. Títulos devem conter no mínimo %1 caractere(s)",
|
||||
@@ -71,12 +71,12 @@
|
||||
"already-unfavourited": "Você já removeu este post dos favoritos",
|
||||
"cant-ban-other-admins": "Você não pode banir outros administradores!",
|
||||
"cant-remove-last-admin": "Você é o único administrador. Adicione outro usuário como administrador antes de remover a si mesmo como admin",
|
||||
"cant-delete-admin": "Remove administrator privileges from this account before attempting to delete it.",
|
||||
"cant-delete-admin": "Remova o privilégio de administrador desta conta antes de tentar deletá-la.",
|
||||
"invalid-image-type": "Tipo inválido de imagem. Os tipos permitidos são: %1",
|
||||
"invalid-image-extension": "Extensão de imagem inválida",
|
||||
"invalid-file-type": "Tipo de arquivo inválido. Os tipos permitidos são: %1",
|
||||
"group-name-too-short": "Nome do grupo é muito curto",
|
||||
"group-name-too-long": "Group name too long",
|
||||
"group-name-too-long": "O nome do grupo é muito extenso",
|
||||
"group-already-exists": "O grupo já existe",
|
||||
"group-name-change-not-allowed": "Sem permissão para alterar nome do grupo",
|
||||
"group-already-member": "Já faz parte deste grupo",
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "O usuário não está na sala",
|
||||
"no-users-in-room": "Nenhum usuário nesta sala",
|
||||
"cant-kick-self": "Você não pode kickar a si mesmo do grupo",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "Nenhuma escolha de usuário(s) foi feita",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -50,9 +50,9 @@
|
||||
"topics": "Tópicos",
|
||||
"posts": "Posts",
|
||||
"best": "Melhor",
|
||||
"upvoters": "Upvoters",
|
||||
"upvoters": "Cimavotadores",
|
||||
"upvoted": "Votado positivamente",
|
||||
"downvoters": "Downvoters",
|
||||
"downvoters": "Baixovotadores",
|
||||
"downvoted": "Votado negativamente",
|
||||
"views": "Visualizações",
|
||||
"reputation": "Reputação",
|
||||
@@ -80,7 +80,7 @@
|
||||
"language": "Idioma",
|
||||
"guest": "Visitante",
|
||||
"guests": "Visitantes",
|
||||
"updated.title": "Forum Updated",
|
||||
"updated.title": "Fórum Atualizado",
|
||||
"updated.message": "Este fórum foi atualizado para sua última versão. Clique aqui para atualizar a página.",
|
||||
"privacy": "Privacidade",
|
||||
"follow": "Seguir",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"users/sort-posts": "Usuários com mais posts",
|
||||
"users/sort-reputation": "Usuários com maior reputação",
|
||||
"users/banned": "Usuários Banidos",
|
||||
"users/most-flags": "Most flagged users",
|
||||
"users/most-flags": "Usuários mais sinalizados",
|
||||
"users/search": "Pesquisa de Usuários",
|
||||
"notifications": "Notificações",
|
||||
"tags": "Tags",
|
||||
@@ -29,7 +29,7 @@
|
||||
"account/edit/password": "Editando senha de \"%1\"",
|
||||
"account/edit/username": "Editando nome de usuário de \"%1\"",
|
||||
"account/edit/email": "Editando email de \"%1\"",
|
||||
"account/info": "Account Info",
|
||||
"account/info": "Informação da Conta",
|
||||
"account/following": "Pessoas que %1 segue",
|
||||
"account/followers": "Pessoas que seguem %1",
|
||||
"account/posts": "Posts feitos por %1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"register": "Cadastrar",
|
||||
"cancel_registration": "Cancel Registration",
|
||||
"cancel_registration": "Cancelar Cadastro",
|
||||
"help.email": "Por padrão seu email ficará invisível para o publico.",
|
||||
"help.username_restrictions": "Um nome de usuário único entre %1 e %2 caracteres. Os outros poderão te mencionar digitando @<span id='yourUsername'>usuário</span>.",
|
||||
"help.minimum_password_length": "Sua senha tem que ter no mínimo %1 caracteres.",
|
||||
@@ -16,8 +16,8 @@
|
||||
"alternative_registration": "Cadastro Alternativo",
|
||||
"terms_of_use": "Termos de Uso",
|
||||
"agree_to_terms_of_use": "Eu concordo com os Termos de Uso",
|
||||
"terms_of_use_error": "You must agree to the Terms of Use",
|
||||
"terms_of_use_error": "Você deve concordar com os Termos de Uso",
|
||||
"registration-added-to-queue": "O seu cadastro foi adicionado à fila de aprovação. Você receberá um email quando ele for aceito por um administrador.",
|
||||
"interstitial.intro": "We require some additional information before we can create your account.",
|
||||
"interstitial.errors-found": "We could not complete your registration:"
|
||||
"interstitial.intro": "Nós pedimos alguma informação adicional antes que você possa criar a sua conta.",
|
||||
"interstitial.errors-found": "Nós não pudemos completar o seu cadastro:"
|
||||
}
|
||||
@@ -31,7 +31,7 @@
|
||||
"flag_success": "Este post foi sinalizado para ser moderado.",
|
||||
"deleted_message": "Este tópico foi deletado. Apenas usuários com privilégios de moderação de tópico podem vê-lo.",
|
||||
"following_topic.message": "Agora você receberá notificações quando alguém responder este tópico.",
|
||||
"not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.",
|
||||
"not_following_topic.message": "Você verá este tópico na lista de tópicos não-lidos, mas você não receberá notificações quendo alguém posta no tópico.",
|
||||
"ignoring_topic.message": "Você não verá mais este tópico na lista de tópicos não lidos. Você será notificado quando você for mencionado ou sua postagem for votada positivamente.",
|
||||
"login_to_subscribe": "Por favor se cadastre ou entre para assinar à este tópico.",
|
||||
"markAsUnreadForAll.success": "Tópico marcado como não lido para todos.",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"postcount": "Número de Posts",
|
||||
"email": "Email",
|
||||
"confirm_email": "Confirmar Email",
|
||||
"account_info": "Account Info",
|
||||
"account_info": "Informação da Conta",
|
||||
"ban_account": "Banir Conta",
|
||||
"ban_account_confirm": "Você realmente quer banir esse usuario?",
|
||||
"unban_account": "Desbanir Conta",
|
||||
@@ -96,8 +96,8 @@
|
||||
"delay_image_loading": "Aguardar para Carregar Imagens",
|
||||
"image_load_delay_help": "Se habilitado, imagens em tópicos não serão carregadas até que eles sejam rolados à visão",
|
||||
"scroll_to_my_post": "Após postar uma réplica, mostre o novo post",
|
||||
"follow_topics_you_reply_to": "Watch topics that you reply to",
|
||||
"follow_topics_you_create": "Watch topics you create",
|
||||
"follow_topics_you_reply_to": "Assistir os tópicos que você responde",
|
||||
"follow_topics_you_create": "Assistir aos tópicos que você cria",
|
||||
"grouptitle": "Título do Grupo",
|
||||
"no-group-title": "Sem título de grupo",
|
||||
"select-skin": "Escolha uma Skin",
|
||||
@@ -109,10 +109,10 @@
|
||||
"sso.title": "Logar por outros Serviços",
|
||||
"sso.associated": "Associado com",
|
||||
"sso.not-associated": "Clique aqui para associar com",
|
||||
"info.latest-flags": "Latest Flags",
|
||||
"info.no-flags": "No Flagged Posts Found",
|
||||
"info.ban-history": "Recent Ban History",
|
||||
"info.no-ban-history": "This user has never been banned",
|
||||
"info.banned-until": "Banned until %1",
|
||||
"info.banned-permanently": "Banned permanently"
|
||||
"info.latest-flags": "Últimas Sinalizações",
|
||||
"info.no-flags": "Nenhum Post Sinalizado Encontrado",
|
||||
"info.ban-history": "Histórico de Banimentos Recentes",
|
||||
"info.no-ban-history": "Este usuário nunca foi banido",
|
||||
"info.banned-until": "Banido até %1",
|
||||
"info.banned-permanently": "Banido permanentemente"
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"latest_users": "Últimos Usuários",
|
||||
"top_posters": "Principais Participantes",
|
||||
"most_reputation": "Maior Reputação",
|
||||
"most_flags": "Most Flags",
|
||||
"most_flags": "Mais Sinalizações",
|
||||
"search": "Pesquisar",
|
||||
"enter_username": "Digite um nome de usuário para pesquisar",
|
||||
"load_more": "Carregar Mais",
|
||||
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Пользователь не в комнате",
|
||||
"no-users-in-room": "В этой комнате нет пользователей",
|
||||
"cant-kick-self": "Вы не можете удалить себя сами из группы.",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "Nta muntu uri muri iki gikari",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Användaren finns inte i rummet",
|
||||
"no-users-in-room": "Inga användare i det här rummet",
|
||||
"cant-kick-self": "Du kan inte sparka ut dig själv från gruppen",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "User not in room",
|
||||
"no-users-in-room": "No users in this room",
|
||||
"cant-kick-self": "You can't kick yourself from the group",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -10,10 +10,10 @@
|
||||
"share_this_category": "Bu kategoriyi paylaş",
|
||||
"watch": "İzle",
|
||||
"ignore": "Yoksay",
|
||||
"watching": "Watching",
|
||||
"ignoring": "Ignoring",
|
||||
"watching.description": "Show topics in unread",
|
||||
"ignoring.description": "Do not show topics in unread",
|
||||
"watching": "İzleniyor",
|
||||
"ignoring": "Yoksayılıyor",
|
||||
"watching.description": "Okunmamış başlıkları göster",
|
||||
"ignoring.description": "Okunmamış başlıkları gösterme",
|
||||
"watch.message": "Şuan bu kategorideki güncellemeleri izliyorsunuz",
|
||||
"ignore.message": "Şuan bu kategoriden güncellemeleri gizliyorsunuz",
|
||||
"watched-categories": "Takip edilen kategoriler"
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
"already-unfavourited": "Bu iletiyi zaten yer imlerinizden çıkardınız",
|
||||
"cant-ban-other-admins": "Başka yöneticileri yasaklayamazsınız!",
|
||||
"cant-remove-last-admin": "Tek yönetici sizsiniz. Kendinizi adminlikten çıkarmadan önce başka bir kullanıcıyı admin olarak ekleyiniz",
|
||||
"cant-delete-admin": "Remove administrator privileges from this account before attempting to delete it.",
|
||||
"cant-delete-admin": "Öncelikle yönetici izinlerini kaldırman gerekiyor.",
|
||||
"invalid-image-type": "Geçersiz resim uzantısı. Izin verilen uzantılar: %1",
|
||||
"invalid-image-extension": "Geçersiz resim uzantısı",
|
||||
"invalid-file-type": "Geçersiz dosya türü. İzin verilenler şunlar : %1",
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Odada kullanıcı yok",
|
||||
"no-users-in-room": "Bu odada kullanıcı yok",
|
||||
"cant-kick-self": "Kendinizi gruptan atamazsınız.",
|
||||
"no-users-selected": "Seçili kullanıcı(s) bulunamadı"
|
||||
"no-users-selected": "Seçili kullanıcı(s) bulunamadı",
|
||||
"invalid-home-page-route": "Geçersiz anasayfa yolu"
|
||||
}
|
||||
@@ -50,9 +50,9 @@
|
||||
"topics": "Başlık",
|
||||
"posts": "İleti",
|
||||
"best": "En İyi",
|
||||
"upvoters": "Upvoters",
|
||||
"upvoters": "Artı",
|
||||
"upvoted": "Artı",
|
||||
"downvoters": "Downvoters",
|
||||
"downvoters": "Eksi",
|
||||
"downvoted": "Eksi",
|
||||
"views": "Görünüm",
|
||||
"reputation": "Saygınlık",
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"account/edit/password": "\"%1\" parolayı düzenliyor",
|
||||
"account/edit/username": "\"%1\" kullanıcı adını düzenliyor",
|
||||
"account/edit/email": "\"%1\" email adresini düzenliyor",
|
||||
"account/info": "Account Info",
|
||||
"account/info": "Hesap Hakkında",
|
||||
"account/following": "%1 tarafından takip edilenler",
|
||||
"account/followers": "%1 takip edenler",
|
||||
"account/posts": "%1 tarafından gönderilen iletiler",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"register": "Kayıt Ol",
|
||||
"cancel_registration": "Cancel Registration",
|
||||
"cancel_registration": "Kaydı İptal Et",
|
||||
"help.email": "E-posta adresiniz varsayılan olarak topluluktan gizlidir.",
|
||||
"help.username_restrictions": "%1 ve %2 karakter arası bir kullanıcı ismi. Başkaları sizden @<span id='yourUsername'>isim</span> kullanarak bahsedebilir.",
|
||||
"help.minimum_password_length": "Şifreniz en az %1 karakter olmalı",
|
||||
@@ -16,8 +16,8 @@
|
||||
"alternative_registration": "Alternatif Kayıt",
|
||||
"terms_of_use": "Kullanım Şartları",
|
||||
"agree_to_terms_of_use": "Kullanım Şartlarını kabul ediyorum",
|
||||
"terms_of_use_error": "You must agree to the Terms of Use",
|
||||
"terms_of_use_error": "Kullanım şartlarını kabul etmen gerekiyor",
|
||||
"registration-added-to-queue": "Kayıt olma isteğiniz kabul listesine eklenmiştir. Yönetici tarafından kabul edildiğinizde mail alacaksınız.",
|
||||
"interstitial.intro": "We require some additional information before we can create your account.",
|
||||
"interstitial.errors-found": "We could not complete your registration:"
|
||||
"interstitial.intro": "Hesabınızı yaratmadan önce bazı ekstra bilgiler gerekiyor.",
|
||||
"interstitial.errors-found": "Kaydınınız tamamlanmadı:"
|
||||
}
|
||||
@@ -31,7 +31,7 @@
|
||||
"flag_success": "Bu ileti yöneticilere bildirildi.",
|
||||
"deleted_message": "Bu başlık silindi. Sadece başlık düzenleme yetkisi olan kullanıcılar görebilir.",
|
||||
"following_topic.message": "Artık bir kullanıcı bu başlığa ileti gönderdiğinde bildirim alacaksınız.",
|
||||
"not_following_topic.message": "You will see this topic in the unread topics list, but you will not receive notifications when somebody posts to this topic.",
|
||||
"not_following_topic.message": "Bu başlığı okunmamışlarda göreceksiniz ama biri bir şey yazdığında bildirim gelmeyecek.",
|
||||
"ignoring_topic.message": "Bu başlığı okunmamış başlıklar alanında görmeyeceksin. Eğer bir iletide bahsedilirsen veya iletin oylanırsa bildiri alacaksın.",
|
||||
"login_to_subscribe": "Lütfen bu iletiyi başlığa üye olmak için giriş yapın.",
|
||||
"markAsUnreadForAll.success": "Başlık herkes için okunmadı olarak işaretlendi.",
|
||||
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "Thành viên không có trong phòng",
|
||||
"no-users-in-room": "Không có ai trong phòng này",
|
||||
"cant-kick-self": "Bạn không thể kick chính bạn ra khỏi nhóm",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "用户已不在聊天室中",
|
||||
"no-users-in-room": "这个聊天室中没有用户",
|
||||
"cant-kick-self": "你不能把自己踢出群组",
|
||||
"no-users-selected": "尚未选择用户"
|
||||
"no-users-selected": "尚未选择用户",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -119,5 +119,6 @@
|
||||
"not-in-room": "使用者沒有在聊天室中",
|
||||
"no-users-in-room": "沒有使用者在聊天室中",
|
||||
"cant-kick-self": "你不能把自己從群組中踢出",
|
||||
"no-users-selected": "No user(s) selected"
|
||||
"no-users-selected": "No user(s) selected",
|
||||
"invalid-home-page-route": "Invalid home page route"
|
||||
}
|
||||
@@ -29,6 +29,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.fa-home {
|
||||
margin-top: 12px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
#user_dropdown {
|
||||
font-size: 25px;
|
||||
color: #eee;
|
||||
|
||||
@@ -2,9 +2,23 @@
|
||||
/*global config, translator, componentHandler, define, socket, app, ajaxify, utils, bootbox, Slideout, NProgress, RELATIVE_PATH*/
|
||||
|
||||
(function() {
|
||||
var logoutTimer = 0;
|
||||
function startLogoutTimer() {
|
||||
if (logoutTimer) {
|
||||
clearTimeout(logoutTimer);
|
||||
}
|
||||
|
||||
logoutTimer = setTimeout(function() {
|
||||
app.alert({
|
||||
message: '[[login:logged-out-due-to-inactivity]]'
|
||||
});
|
||||
setTimeout(app.logout, 5000);
|
||||
}, 3600000);
|
||||
}
|
||||
|
||||
$(window).on('action:ajaxify.end', function() {
|
||||
showCorrectNavTab();
|
||||
startLogoutTimer();
|
||||
});
|
||||
|
||||
function showCorrectNavTab() {
|
||||
|
||||
@@ -16,6 +16,8 @@ define('admin/appearance/customise', ['admin/settings'], function(Settings) {
|
||||
customCSS.getSession().setMode("ace/mode/css");
|
||||
|
||||
customCSS.on('change', function(e) {
|
||||
app.flags = app.flags || {};
|
||||
app.flags._unsaved = true;
|
||||
$('#customCSS-holder').val(customCSS.getValue());
|
||||
});
|
||||
|
||||
@@ -23,6 +25,8 @@ define('admin/appearance/customise', ['admin/settings'], function(Settings) {
|
||||
customHTML.getSession().setMode("ace/mode/html");
|
||||
|
||||
customHTML.on('change', function(e) {
|
||||
app.flags = app.flags || {};
|
||||
app.flags._unsaved = true;
|
||||
$('#customHTML-holder').val(customHTML.getValue());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
/*global define, ajaxify, app, socket, utils, bootbox, RELATIVE_PATH*/
|
||||
|
||||
define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
var Admin = {},
|
||||
intervals = {
|
||||
var Admin = {};
|
||||
var intervals = {
|
||||
rooms: false,
|
||||
graphs: false
|
||||
},
|
||||
isMobile = false,
|
||||
isPrerelease = /^v?\d+\.\d+\.\d+-.+$/,
|
||||
graphData = {
|
||||
};
|
||||
var isMobile = false;
|
||||
var isPrerelease = /^v?\d+\.\d+\.\d+-.+$/;
|
||||
var graphData = {
|
||||
rooms: {},
|
||||
traffic: {}
|
||||
},
|
||||
currentGraph = {
|
||||
};
|
||||
var currentGraph = {
|
||||
units: 'hours',
|
||||
until: undefined
|
||||
};
|
||||
@@ -121,8 +121,8 @@ define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
topics: null
|
||||
};
|
||||
|
||||
var topicColors = ["#bf616a","#5B90BF","#d08770","#ebcb8b","#a3be8c","#96b5b4","#8fa1b3","#b48ead","#ab7967","#46BFBD"],
|
||||
usedTopicColors = [];
|
||||
var topicColors = ["#bf616a","#5B90BF","#d08770","#ebcb8b","#a3be8c","#96b5b4","#8fa1b3","#b48ead","#ab7967","#46BFBD"];
|
||||
var usedTopicColors = [];
|
||||
|
||||
// from chartjs.org
|
||||
function lighten(col, amt) {
|
||||
@@ -170,92 +170,103 @@ define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
}
|
||||
|
||||
var data = {
|
||||
labels: trafficLabels,
|
||||
datasets: [
|
||||
{
|
||||
label: "Page Views",
|
||||
fillColor: "rgba(220,220,220,0.2)",
|
||||
strokeColor: "rgba(220,220,220,1)",
|
||||
pointColor: "rgba(220,220,220,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(220,220,220,1)",
|
||||
data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
},
|
||||
{
|
||||
label: "Unique Visitors",
|
||||
fillColor: "rgba(151,187,205,0.2)",
|
||||
strokeColor: "rgba(151,187,205,1)",
|
||||
pointColor: "rgba(151,187,205,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
}
|
||||
]
|
||||
};
|
||||
labels: trafficLabels,
|
||||
datasets: [
|
||||
{
|
||||
label: "Page Views",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
},
|
||||
{
|
||||
label: "Unique Visitors",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
borderColor: "rgba(151,187,205,1)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(151,187,205,1)",
|
||||
data: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
trafficCanvas.width = $(trafficCanvas).parent().width();
|
||||
graphs.traffic = new Chart(trafficCtx).Line(data, {
|
||||
responsive: true
|
||||
graphs.traffic = new Chart(trafficCtx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
graphs.registered = new Chart(registeredCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ["Registered Users", "Anonymous Users"],
|
||||
datasets: [{
|
||||
data: [1, 1],
|
||||
backgroundColor: ["#F7464A", "#46BFBD"],
|
||||
hoverBackgroundColor: ["#FF5A5E", "#5AD3D1"]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
graphs.registered = new Chart(registeredCtx).Doughnut([{
|
||||
value: 1,
|
||||
color:"#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "Registered Users"
|
||||
graphs.presence = new Chart(presenceCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ["On categories list", "Reading posts", "Browsing topics", "Recent", "Unread"],
|
||||
datasets: [{
|
||||
data: [1, 1, 1, 1, 1],
|
||||
backgroundColor: ["#F7464A", "#46BFBD", "#FDB45C", "#949FB1", "#9FB194"],
|
||||
hoverBackgroundColor: ["#FF5A5E", "#5AD3D1", "#FFC870", "#A8B3C5", "#A8B3C5"]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
graphs.topics = new Chart(topicsCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
data: [],
|
||||
backgroundColor: [],
|
||||
hoverBackgroundColor: []
|
||||
}]
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Anonymous Users"
|
||||
}], {
|
||||
responsive: true
|
||||
});
|
||||
|
||||
graphs.presence = new Chart(presenceCtx).Doughnut([{
|
||||
value: 1,
|
||||
color:"#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "On categories list"
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Reading posts"
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "Browsing topics"
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
color: "#949FB1",
|
||||
highlight: "#A8B3C5",
|
||||
label: "Recent"
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
color: "#9FB194",
|
||||
highlight: "#A8B3C5",
|
||||
label: "Unread"
|
||||
}
|
||||
], {
|
||||
responsive: true
|
||||
});
|
||||
|
||||
graphs.topics = new Chart(topicsCtx).Doughnut([], {responsive: true});
|
||||
topicsCanvas.onclick = function(evt){
|
||||
var obj = graphs.topics.getSegmentsAtEvent(evt);
|
||||
if (obj && obj[0]) {
|
||||
window.open(RELATIVE_PATH + '/topic/' + obj[0].tid);
|
||||
}
|
||||
};
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateTrafficGraph();
|
||||
|
||||
@@ -302,15 +313,10 @@ define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
|
||||
graphData.traffic = data;
|
||||
|
||||
// If new data set contains fewer points than currently shown, truncate
|
||||
while(graphs.traffic.datasets[0].points.length > data.pageviews.length) {
|
||||
graphs.traffic.removeData();
|
||||
}
|
||||
|
||||
if (units === 'days') {
|
||||
graphs.traffic.scale.xLabels = utils.getDaysArray(until);
|
||||
graphs.traffic.data.xLabels = utils.getDaysArray(until);
|
||||
} else {
|
||||
graphs.traffic.scale.xLabels = utils.getHoursArray();
|
||||
graphs.traffic.data.xLabels = utils.getHoursArray();
|
||||
|
||||
$('#pageViewsThisMonth').html(data.monthlyPageViews.thisMonth);
|
||||
$('#pageViewsLastMonth').html(data.monthlyPageViews.lastMonth);
|
||||
@@ -320,17 +326,9 @@ define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
utils.addCommasToNumbers($('#pageViewsPastDay'));
|
||||
}
|
||||
|
||||
for (var i = 0, ii = data.pageviews.length; i < ii; i++) {
|
||||
if (graphs.traffic.datasets[0].points[i]) {
|
||||
graphs.traffic.datasets[0].points[i].value = data.pageviews[i];
|
||||
graphs.traffic.datasets[0].points[i].label = graphs.traffic.scale.xLabels[i];
|
||||
graphs.traffic.datasets[1].points[i].value = data.uniqueVisitors[i];
|
||||
graphs.traffic.datasets[1].points[i].label = graphs.traffic.scale.xLabels[i];
|
||||
} else {
|
||||
// No points to replace? Add data.
|
||||
graphs.traffic.addData([data.pageviews[i], data.uniqueVisitors[i]], graphs.traffic.scale.xLabels[i]);
|
||||
}
|
||||
}
|
||||
graphs.traffic.data.datasets[0].data = data.pageviews;
|
||||
graphs.traffic.data.datasets[1].data = data.uniqueVisitors;
|
||||
graphs.traffic.data.labels = graphs.traffic.data.xLabels;
|
||||
|
||||
graphs.traffic.update();
|
||||
currentGraph.units = units;
|
||||
@@ -339,22 +337,21 @@ define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
}
|
||||
|
||||
function updateRegisteredGraph(registered, anonymous) {
|
||||
graphs.registered.segments[0].value = registered;
|
||||
graphs.registered.segments[1].value = anonymous;
|
||||
graphs.registered.data.datasets[0].data[0] = registered;
|
||||
graphs.registered.data.datasets[0].data[1] = anonymous;
|
||||
graphs.registered.update();
|
||||
}
|
||||
|
||||
function updatePresenceGraph(users) {
|
||||
graphs.presence.segments[0].value = users.categories;
|
||||
graphs.presence.segments[1].value = users.topics;
|
||||
graphs.presence.segments[2].value = users.category;
|
||||
graphs.presence.segments[3].value = users.recent;
|
||||
graphs.presence.segments[4].value = users.unread;
|
||||
|
||||
graphs.presence.data.datasets[0].data[0] = users.categories;
|
||||
graphs.presence.data.datasets[0].data[1] = users.topics;
|
||||
graphs.presence.data.datasets[0].data[2] = users.category;
|
||||
graphs.presence.data.datasets[0].data[3] = users.recent;
|
||||
graphs.presence.data.datasets[0].data[4] = users.unread;
|
||||
|
||||
graphs.presence.update();
|
||||
}
|
||||
|
||||
|
||||
function updateTopicsGraph(topics) {
|
||||
if (!Object.keys(topics).length) {
|
||||
topics = {"0": {
|
||||
@@ -363,88 +360,36 @@ define('admin/general/dashboard', ['semver', 'Chart'], function(semver, Chart) {
|
||||
}};
|
||||
}
|
||||
|
||||
var tids = Object.keys(topics),
|
||||
segments = graphs.topics.segments;
|
||||
|
||||
function reassignExistingTopics() {
|
||||
for (var i = segments.length - 1; i >= 0; i--) {
|
||||
if (!segments[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var tid = segments[i].tid;
|
||||
|
||||
if ($.inArray(tid, tids) === -1) {
|
||||
usedTopicColors.splice($.inArray(segments[i].fillColor, usedTopicColors), 1);
|
||||
graphs.topics.removeData(i);
|
||||
} else {
|
||||
graphs.topics.segments[i].value = topics[tid].value;
|
||||
delete topics[tid];
|
||||
}
|
||||
}
|
||||
var tids = Object.keys(topics);
|
||||
|
||||
graphs.topics.data.labels = [];
|
||||
graphs.topics.data.datasets[0].data = [];
|
||||
graphs.topics.data.datasets[0].backgroundColor = [];
|
||||
graphs.topics.data.datasets[0].hoverBackgroundColor = [];
|
||||
|
||||
for (var i = 0, ii = tids.length; i < ii; i++) {
|
||||
graphs.topics.data.labels.push(topics[tids[i]].title);
|
||||
graphs.topics.data.datasets[0].data.push(topics[tids[i]].value);
|
||||
graphs.topics.data.datasets[0].backgroundColor.push(topicColors[i]);
|
||||
graphs.topics.data.datasets[0].hoverBackgroundColor.push(lighten(topicColors[i], 10));
|
||||
}
|
||||
|
||||
function assignNewTopics() {
|
||||
while (segments.length < 10 && tids.length > 0) {
|
||||
var tid = tids.pop(),
|
||||
data = topics[tid],
|
||||
color = null;
|
||||
|
||||
if (!data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tid === '0') {
|
||||
color = '#4D5360';
|
||||
} else {
|
||||
do {
|
||||
for (var i = 0, ii = topicColors.length; i < ii; i++) {
|
||||
var chosenColor = topicColors[i];
|
||||
|
||||
if ($.inArray(chosenColor, usedTopicColors) === -1) {
|
||||
color = chosenColor;
|
||||
usedTopicColors.push(color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (color === null && usedTopicColors.length < topicColors.length);
|
||||
}
|
||||
|
||||
if (color) {
|
||||
graphs.topics.addData({
|
||||
value: data.value,
|
||||
color: color,
|
||||
highlight: lighten(color, 10),
|
||||
label: data.title
|
||||
});
|
||||
|
||||
segments[segments.length - 1].tid = tid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function buildTopicsLegend() {
|
||||
var legend = $('#topics-legend').html('');
|
||||
|
||||
segments.sort(function(a, b) {
|
||||
return b.value - a.value;
|
||||
});
|
||||
for (var i = 0, ii = segments.length; i < ii; i++) {
|
||||
var topic = segments[i],
|
||||
label = topic.tid === '0' ? topic.label : '<a title="' + topic.label + '"href="' + RELATIVE_PATH + '/topic/' + topic.tid + '" target="_blank"> ' + topic.label + '</a>';
|
||||
|
||||
for (var i = 0, ii = tids.length; i < ii; i++) {
|
||||
var topic = topics[tids[i]];
|
||||
var label = topic.value === '0' ? topic.title : '<a title="' + topic.title + '"href="' + RELATIVE_PATH + '/topic/' + tids[i] + '" target="_blank"> ' + topic.title + '</a>';
|
||||
|
||||
legend.append(
|
||||
'<li>' +
|
||||
'<div style="background-color: ' + topic.highlightColor + '; border-color: ' + topic.strokeColor + '"></div>' +
|
||||
'<span>' + label + '</span>' +
|
||||
'<div style="background-color: ' + topicColors[i] + ';"></div>' +
|
||||
'<span>' + label + '</span>' +
|
||||
'</li>');
|
||||
}
|
||||
}
|
||||
|
||||
reassignExistingTopics();
|
||||
assignNewTopics();
|
||||
buildTopicsLegend();
|
||||
|
||||
graphs.topics.update();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
"use strict";
|
||||
/*global config, define, app, socket, ajaxify, bootbox, templates, utils */
|
||||
/*global define, ajaxify, utils */
|
||||
|
||||
define('admin/manage/category-analytics', ['Chart'], function(Chart) {
|
||||
var CategoryAnalytics = {};
|
||||
|
||||
CategoryAnalytics.init = function() {
|
||||
var hourlyCanvas = document.getElementById('pageviews:hourly'),
|
||||
dailyCanvas = document.getElementById('pageviews:daily'),
|
||||
topicsCanvas = document.getElementById('topics:daily'),
|
||||
postsCanvas = document.getElementById('posts:daily'),
|
||||
hourlyLabels = utils.getHoursArray().map(function(text, idx) {
|
||||
var hourlyCanvas = document.getElementById('pageviews:hourly');
|
||||
var dailyCanvas = document.getElementById('pageviews:daily');
|
||||
var topicsCanvas = document.getElementById('topics:daily');
|
||||
var postsCanvas = document.getElementById('posts:daily');
|
||||
var hourlyLabels = utils.getHoursArray().map(function(text, idx) {
|
||||
return idx % 3 ? '' : text;
|
||||
}),
|
||||
dailyLabels = utils.getDaysArray().map(function(text, idx) {
|
||||
});
|
||||
var dailyLabels = utils.getDaysArray().map(function(text, idx) {
|
||||
return idx % 3 ? '' : text;
|
||||
});
|
||||
|
||||
if (utils.isMobile()) {
|
||||
Chart.defaults.global.showTooltips = false;
|
||||
Chart.defaults.global.tooltips.enabled = false;
|
||||
}
|
||||
|
||||
var data = {
|
||||
@@ -26,12 +26,12 @@ define('admin/manage/category-analytics', ['Chart'], function(Chart) {
|
||||
datasets: [
|
||||
{
|
||||
label: "",
|
||||
fillColor: "rgba(186,139,175,0.2)",
|
||||
strokeColor: "rgba(186,139,175,1)",
|
||||
pointColor: "rgba(186,139,175,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(186,139,175,1)",
|
||||
backgroundColor: "rgba(186,139,175,0.2)",
|
||||
borderColor: "rgba(186,139,175,1)",
|
||||
pointBackgroundColor: "rgba(186,139,175,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(186,139,175,1)",
|
||||
data: ajaxify.data.analytics['pageviews:hourly']
|
||||
}
|
||||
]
|
||||
@@ -41,12 +41,12 @@ define('admin/manage/category-analytics', ['Chart'], function(Chart) {
|
||||
datasets: [
|
||||
{
|
||||
label: "",
|
||||
fillColor: "rgba(151,187,205,0.2)",
|
||||
strokeColor: "rgba(151,187,205,1)",
|
||||
pointColor: "rgba(151,187,205,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
borderColor: "rgba(151,187,205,1)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(151,187,205,1)",
|
||||
data: ajaxify.data.analytics['pageviews:daily']
|
||||
}
|
||||
]
|
||||
@@ -56,12 +56,12 @@ define('admin/manage/category-analytics', ['Chart'], function(Chart) {
|
||||
datasets: [
|
||||
{
|
||||
label: "",
|
||||
fillColor: "rgba(171,70,66,0.2)",
|
||||
strokeColor: "rgba(171,70,66,1)",
|
||||
pointColor: "rgba(171,70,66,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(171,70,66,1)",
|
||||
backgroundColor: "rgba(171,70,66,0.2)",
|
||||
borderColor: "rgba(171,70,66,1)",
|
||||
pointBackgroundColor: "rgba(171,70,66,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(171,70,66,1)",
|
||||
data: ajaxify.data.analytics['topics:daily']
|
||||
}
|
||||
]
|
||||
@@ -71,12 +71,12 @@ define('admin/manage/category-analytics', ['Chart'], function(Chart) {
|
||||
datasets: [
|
||||
{
|
||||
label: "",
|
||||
fillColor: "rgba(161,181,108,0.2)",
|
||||
strokeColor: "rgba(161,181,108,1)",
|
||||
pointColor: "rgba(161,181,108,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(161,181,108,1)",
|
||||
backgroundColor: "rgba(161,181,108,0.2)",
|
||||
borderColor: "rgba(161,181,108,1)",
|
||||
pointBackgroundColor: "rgba(161,181,108,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(161,181,108,1)",
|
||||
data: ajaxify.data.analytics['posts:daily']
|
||||
}
|
||||
]
|
||||
@@ -87,21 +87,81 @@ define('admin/manage/category-analytics', ['Chart'], function(Chart) {
|
||||
dailyCanvas.width = $(dailyCanvas).parent().width();
|
||||
topicsCanvas.width = $(topicsCanvas).parent().width();
|
||||
postsCanvas.width = $(postsCanvas).parent().width();
|
||||
new Chart(hourlyCanvas.getContext('2d')).Line(data['pageviews:hourly'], {
|
||||
responsive: true,
|
||||
animation: false
|
||||
|
||||
new Chart(hourlyCanvas.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: data['pageviews:hourly'],
|
||||
options: {
|
||||
responsive: true,
|
||||
animation: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
new Chart(dailyCanvas.getContext('2d')).Line(data['pageviews:daily'], {
|
||||
responsive: true,
|
||||
animation: false
|
||||
|
||||
new Chart(dailyCanvas.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: data['pageviews:daily'],
|
||||
options: {
|
||||
responsive: true,
|
||||
animation: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
new Chart(topicsCanvas.getContext('2d')).Line(data['topics:daily'], {
|
||||
responsive: true,
|
||||
animation: false
|
||||
|
||||
new Chart(topicsCanvas.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: data['topics:daily'],
|
||||
options: {
|
||||
responsive: true,
|
||||
animation: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
new Chart(postsCanvas.getContext('2d')).Line(data['posts:daily'], {
|
||||
responsive: true,
|
||||
animation: false
|
||||
|
||||
new Chart(postsCanvas.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: data['posts:daily'],
|
||||
options: {
|
||||
responsive: true,
|
||||
animation: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ define('admin/manage/category', [
|
||||
if (cid) {
|
||||
modified_categories[cid] = modified_categories[cid] || {};
|
||||
modified_categories[cid][$(el).attr('data-name')] = $(el).val();
|
||||
|
||||
app.flags = app.flags || {};
|
||||
app.flags._unsaved = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +34,7 @@ define('admin/manage/category', [
|
||||
}
|
||||
|
||||
if (result && result.length) {
|
||||
app.flags._unsaved = false;
|
||||
app.alert({
|
||||
title: 'Updated Categories',
|
||||
message: 'Category IDs ' + result.join(', ') + ' was successfully updated.',
|
||||
|
||||
@@ -110,7 +110,7 @@ define('admin/manage/flags', [
|
||||
});
|
||||
|
||||
if (utils.isMobile()) {
|
||||
Chart.defaults.global.showTooltips = false;
|
||||
Chart.defaults.global.tooltips.enabled = false;
|
||||
}
|
||||
var data = {
|
||||
'flags:daily': {
|
||||
@@ -118,26 +118,37 @@ define('admin/manage/flags', [
|
||||
datasets: [
|
||||
{
|
||||
label: "",
|
||||
fillColor: "rgba(151,187,205,0.2)",
|
||||
strokeColor: "rgba(151,187,205,1)",
|
||||
pointColor: "rgba(151,187,205,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
borderColor: "rgba(151,187,205,1)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(151,187,205,1)",
|
||||
data: ajaxify.data.analytics
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
dailyCanvas.width = $(dailyCanvas).parent().width();
|
||||
new Chart(dailyCanvas.getContext('2d')).Line(data['flags:daily'], {
|
||||
responsive: true,
|
||||
animation: false
|
||||
new Chart(dailyCanvas.getContext('2d'), {
|
||||
type: 'line',
|
||||
data: data['flags:daily'],
|
||||
options: {
|
||||
responsive: true,
|
||||
animation: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return Flags;
|
||||
|
||||
@@ -27,6 +27,12 @@ define('admin/settings', ['uploader'], function(uploader) {
|
||||
revertBtn = $('#revert'),
|
||||
x, key, inputType, field;
|
||||
|
||||
// Handle unsaved changes
|
||||
$(fields).on('change', function() {
|
||||
app.flags = app.flags || {};
|
||||
app.flags._unsaved = true;
|
||||
});
|
||||
|
||||
for (x = 0; x < numFields; x++) {
|
||||
field = fields.eq(x);
|
||||
key = field.attr('data-field');
|
||||
@@ -77,6 +83,9 @@ define('admin/settings', ['uploader'], function(uploader) {
|
||||
type: 'danger'
|
||||
});
|
||||
}
|
||||
|
||||
app.flags._unsaved = false;
|
||||
|
||||
app.alert({
|
||||
alert_id: 'config_status',
|
||||
timeout: 2500,
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"use strict";
|
||||
/*global app, bootbox, templates, socket, config, RELATIVE_PATH*/
|
||||
|
||||
var ajaxify = ajaxify || {};
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
/*global app, templates, socket, config, RELATIVE_PATH*/
|
||||
|
||||
var location = document.location || window.location;
|
||||
var rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : '');
|
||||
var apiXHR = null;
|
||||
@@ -295,6 +293,32 @@ $(document).ready(function() {
|
||||
|
||||
// Enhancing all anchors to ajaxify...
|
||||
$(document.body).on('click', 'a', function (e) {
|
||||
var _self = this;
|
||||
var process = function() {
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.metaKey && e.which === 1) {
|
||||
if (internalLink) {
|
||||
var pathname = this.href.replace(rootUrl + RELATIVE_PATH + '/', '');
|
||||
|
||||
// Special handling for urls with hashes
|
||||
if (window.location.pathname === this.pathname && this.hash.length) {
|
||||
window.location.hash = this.hash;
|
||||
} else {
|
||||
if (ajaxify.go(pathname)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
} else if (window.location.pathname !== '/outgoing') {
|
||||
if (config.openOutgoingLinksInNewTab) {
|
||||
window.open(this.href, '_blank');
|
||||
e.preventDefault();
|
||||
} else if (config.useOutgoingLinksPage) {
|
||||
ajaxify.go('outgoing?url=' + encodeURIComponent(this.href));
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.target !== '' || (this.protocol !== 'http:' && this.protocol !== 'https:')) {
|
||||
return;
|
||||
}
|
||||
@@ -311,6 +335,7 @@ $(document).ready(function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Default behaviour for rss feeds
|
||||
if (internalLink && $(this).attr('href').endsWith('.rss')) {
|
||||
return;
|
||||
}
|
||||
@@ -319,28 +344,19 @@ $(document).ready(function() {
|
||||
return e.preventDefault();
|
||||
}
|
||||
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.metaKey && e.which === 1) {
|
||||
if (internalLink) {
|
||||
var pathname = this.href.replace(rootUrl + RELATIVE_PATH + '/', '');
|
||||
|
||||
// Special handling for urls with hashes
|
||||
if (window.location.pathname === this.pathname && this.hash.length) {
|
||||
window.location.hash = this.hash;
|
||||
} else {
|
||||
if (ajaxify.go(pathname)) {
|
||||
e.preventDefault();
|
||||
if (app.flags && app.flags.hasOwnProperty('_unsaved') && app.flags._unsaved === true) {
|
||||
translator.translate('[[global:unsaved-changes]]', function(text) {
|
||||
bootbox.confirm(text, function(navigate) {
|
||||
if (navigate) {
|
||||
app.flags._unsaved = false;
|
||||
process.call(_self);
|
||||
}
|
||||
}
|
||||
} else if (window.location.pathname !== '/outgoing') {
|
||||
if (config.openOutgoingLinksInNewTab) {
|
||||
window.open(this.href, '_blank');
|
||||
e.preventDefault();
|
||||
} else if (config.useOutgoingLinksPage) {
|
||||
ajaxify.go('outgoing?url=' + encodeURIComponent(this.href));
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return e.preventDefault();
|
||||
}
|
||||
|
||||
process.call(_self);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -473,33 +473,35 @@ app.cacheBuster = null;
|
||||
if (!config.requireEmailConfirmation || !app.user.uid) {
|
||||
return;
|
||||
}
|
||||
var msg = {
|
||||
alert_id: 'email_confirm',
|
||||
type: 'warning',
|
||||
timeout: 0
|
||||
};
|
||||
|
||||
if (!app.user.email) {
|
||||
app.alert({
|
||||
alert_id: 'email_confirm',
|
||||
message: '[[error:no-email-to-confirm]]',
|
||||
type: 'warning',
|
||||
timeout: 0,
|
||||
clickfn: function() {
|
||||
app.removeAlert('email_confirm');
|
||||
ajaxify.go('user/' + app.user.userslug + '/edit');
|
||||
}
|
||||
});
|
||||
} else if (!app.user['email:confirmed']) {
|
||||
app.alert({
|
||||
alert_id: 'email_confirm',
|
||||
message: err ? err.message : '[[error:email-not-confirmed]]',
|
||||
type: 'warning',
|
||||
timeout: 0,
|
||||
clickfn: function() {
|
||||
app.removeAlert('email_confirm');
|
||||
socket.emit('user.emailConfirm', {}, function(err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
app.alertSuccess('[[notifications:email-confirm-sent]]');
|
||||
});
|
||||
}
|
||||
});
|
||||
msg.message = '[[error:no-email-to-confirm]]';
|
||||
msg.clickfn = function() {
|
||||
app.removeAlert('email_confirm');
|
||||
ajaxify.go('user/' + app.user.userslug + '/edit');
|
||||
};
|
||||
app.alert(msg);
|
||||
} else if (!app.user['email:confirmed'] && !app.user.isEmailConfirmSent) {
|
||||
msg.message = err ? err.message : '[[error:email-not-confirmed]]';
|
||||
msg.clickfn = function() {
|
||||
app.removeAlert('email_confirm');
|
||||
socket.emit('user.emailConfirm', {}, function(err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
app.alertSuccess('[[notifications:email-confirm-sent]]');
|
||||
});
|
||||
};
|
||||
|
||||
app.alert(msg);
|
||||
} else if (!app.user['email:confirmed'] && app.user.isEmailConfirmSent) {
|
||||
msg.message = '[[error:email-not-confirmed-email-sent]]';
|
||||
app.alert(msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -196,7 +196,8 @@ define('forum/category', [
|
||||
templates.parse('category', 'topics', {
|
||||
privileges: {editable: editable},
|
||||
showSelect: editable,
|
||||
topics: [topic]
|
||||
topics: [topic],
|
||||
template: {category: true}
|
||||
}, function(html) {
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var topic = $(translatedHTML),
|
||||
@@ -347,4 +348,4 @@ define('forum/category', [
|
||||
};
|
||||
|
||||
return Category;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -473,6 +473,12 @@ define('settings', function () {
|
||||
});
|
||||
$(window).trigger('action:admin.settingsLoaded');
|
||||
|
||||
// Handle unsaved changes
|
||||
$(formEl).on('change', 'input, select, textarea', function() {
|
||||
app.flags = app.flags || {};
|
||||
app.flags._unsaved = true;
|
||||
});
|
||||
|
||||
callback(null, values);
|
||||
});
|
||||
},
|
||||
@@ -498,6 +504,9 @@ define('settings', function () {
|
||||
hash: hash,
|
||||
values: values
|
||||
}, function (err) {
|
||||
// Remove unsaved flag to re-enable ajaxify
|
||||
app.flags._unsaved = false;
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
} else {
|
||||
|
||||
254
public/vendor/autosize.js
vendored
254
public/vendor/autosize.js
vendored
@@ -1,254 +0,0 @@
|
||||
/*!
|
||||
Autosize 3.0.15
|
||||
license: MIT
|
||||
http://www.jacklmoore.com/autosize
|
||||
*/
|
||||
(function (global, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define('autosize', ['exports', 'module'], factory);
|
||||
} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
|
||||
factory(exports, module);
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports, mod);
|
||||
global.autosize = mod.exports;
|
||||
}
|
||||
})(this, function (exports, module) {
|
||||
'use strict';
|
||||
|
||||
var set = typeof Set === 'function' ? new Set() : (function () {
|
||||
var list = [];
|
||||
|
||||
return {
|
||||
has: function has(key) {
|
||||
return Boolean(list.indexOf(key) > -1);
|
||||
},
|
||||
add: function add(key) {
|
||||
list.push(key);
|
||||
},
|
||||
'delete': function _delete(key) {
|
||||
list.splice(list.indexOf(key), 1);
|
||||
} };
|
||||
})();
|
||||
|
||||
var createEvent = function createEvent(name) {
|
||||
return new Event(name);
|
||||
};
|
||||
try {
|
||||
new Event('test');
|
||||
} catch (e) {
|
||||
// IE does not support `new Event()`
|
||||
createEvent = function (name) {
|
||||
var evt = document.createEvent('Event');
|
||||
evt.initEvent(name, true, false);
|
||||
return evt;
|
||||
};
|
||||
}
|
||||
|
||||
function assign(ta) {
|
||||
var _ref = arguments[1] === undefined ? {} : arguments[1];
|
||||
|
||||
var _ref$setOverflowX = _ref.setOverflowX;
|
||||
var setOverflowX = _ref$setOverflowX === undefined ? true : _ref$setOverflowX;
|
||||
var _ref$setOverflowY = _ref.setOverflowY;
|
||||
var setOverflowY = _ref$setOverflowY === undefined ? true : _ref$setOverflowY;
|
||||
|
||||
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || set.has(ta)) return;
|
||||
|
||||
var heightOffset = null;
|
||||
var overflowY = null;
|
||||
var clientWidth = ta.clientWidth;
|
||||
|
||||
function init() {
|
||||
var style = window.getComputedStyle(ta, null);
|
||||
|
||||
overflowY = style.overflowY;
|
||||
|
||||
if (style.resize === 'vertical') {
|
||||
ta.style.resize = 'none';
|
||||
} else if (style.resize === 'both') {
|
||||
ta.style.resize = 'horizontal';
|
||||
}
|
||||
|
||||
if (style.boxSizing === 'content-box') {
|
||||
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
|
||||
} else {
|
||||
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
|
||||
}
|
||||
// Fix when a textarea is not on document body and heightOffset is Not a Number
|
||||
if (isNaN(heightOffset)) {
|
||||
heightOffset = 0;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
function changeOverflow(value) {
|
||||
{
|
||||
// Chrome/Safari-specific fix:
|
||||
// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
|
||||
// made available by removing the scrollbar. The following forces the necessary text reflow.
|
||||
var width = ta.style.width;
|
||||
ta.style.width = '0px';
|
||||
// Force reflow:
|
||||
/* jshint ignore:start */
|
||||
ta.offsetWidth;
|
||||
/* jshint ignore:end */
|
||||
ta.style.width = width;
|
||||
}
|
||||
|
||||
overflowY = value;
|
||||
|
||||
if (setOverflowY) {
|
||||
ta.style.overflowY = value;
|
||||
}
|
||||
|
||||
resize();
|
||||
}
|
||||
|
||||
function resize() {
|
||||
var htmlTop = window.pageYOffset;
|
||||
var bodyTop = document.body.scrollTop;
|
||||
var originalHeight = ta.style.height;
|
||||
|
||||
ta.style.height = 'auto';
|
||||
|
||||
var endHeight = ta.scrollHeight + heightOffset;
|
||||
|
||||
if (ta.scrollHeight === 0) {
|
||||
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
|
||||
ta.style.height = originalHeight;
|
||||
return;
|
||||
}
|
||||
|
||||
ta.style.height = endHeight + 'px';
|
||||
|
||||
// used to check if an update is actually necessary on window.resize
|
||||
clientWidth = ta.clientWidth;
|
||||
|
||||
// prevents scroll-position jumping
|
||||
document.documentElement.scrollTop = htmlTop;
|
||||
document.body.scrollTop = bodyTop;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var startHeight = ta.style.height;
|
||||
|
||||
resize();
|
||||
|
||||
var style = window.getComputedStyle(ta, null);
|
||||
|
||||
if (style.height !== ta.style.height) {
|
||||
if (overflowY !== 'visible') {
|
||||
changeOverflow('visible');
|
||||
}
|
||||
} else {
|
||||
if (overflowY !== 'hidden') {
|
||||
changeOverflow('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
if (startHeight !== ta.style.height) {
|
||||
var evt = createEvent('autosize:resized');
|
||||
ta.dispatchEvent(evt);
|
||||
}
|
||||
}
|
||||
|
||||
var pageResize = function pageResize() {
|
||||
if (ta.clientWidth !== clientWidth) {
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
var destroy = (function (style) {
|
||||
window.removeEventListener('resize', pageResize, false);
|
||||
ta.removeEventListener('input', update, false);
|
||||
ta.removeEventListener('keyup', update, false);
|
||||
ta.removeEventListener('autosize:destroy', destroy, false);
|
||||
ta.removeEventListener('autosize:update', update, false);
|
||||
set['delete'](ta);
|
||||
|
||||
Object.keys(style).forEach(function (key) {
|
||||
ta.style[key] = style[key];
|
||||
});
|
||||
}).bind(ta, {
|
||||
height: ta.style.height,
|
||||
resize: ta.style.resize,
|
||||
overflowY: ta.style.overflowY,
|
||||
overflowX: ta.style.overflowX,
|
||||
wordWrap: ta.style.wordWrap });
|
||||
|
||||
ta.addEventListener('autosize:destroy', destroy, false);
|
||||
|
||||
// IE9 does not fire onpropertychange or oninput for deletions,
|
||||
// so binding to onkeyup to catch most of those events.
|
||||
// There is no way that I know of to detect something like 'cut' in IE9.
|
||||
if ('onpropertychange' in ta && 'oninput' in ta) {
|
||||
ta.addEventListener('keyup', update, false);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', pageResize, false);
|
||||
ta.addEventListener('input', update, false);
|
||||
ta.addEventListener('autosize:update', update, false);
|
||||
set.add(ta);
|
||||
|
||||
if (setOverflowX) {
|
||||
ta.style.overflowX = 'hidden';
|
||||
ta.style.wordWrap = 'break-word';
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
function destroy(ta) {
|
||||
if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
|
||||
var evt = createEvent('autosize:destroy');
|
||||
ta.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
function update(ta) {
|
||||
if (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;
|
||||
var evt = createEvent('autosize:update');
|
||||
ta.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
var autosize = null;
|
||||
|
||||
// Do nothing in Node.js environment and IE8 (or lower)
|
||||
if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
|
||||
autosize = function (el) {
|
||||
return el;
|
||||
};
|
||||
autosize.destroy = function (el) {
|
||||
return el;
|
||||
};
|
||||
autosize.update = function (el) {
|
||||
return el;
|
||||
};
|
||||
} else {
|
||||
autosize = function (el, options) {
|
||||
if (el) {
|
||||
Array.prototype.forEach.call(el.length ? el : [el], function (x) {
|
||||
return assign(x, options);
|
||||
});
|
||||
}
|
||||
return el;
|
||||
};
|
||||
autosize.destroy = function (el) {
|
||||
if (el) {
|
||||
Array.prototype.forEach.call(el.length ? el : [el], destroy);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
autosize.update = function (el) {
|
||||
if (el) {
|
||||
Array.prototype.forEach.call(el.length ? el : [el], update);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = autosize;
|
||||
});
|
||||
@@ -91,7 +91,7 @@ module.exports = function(Messaging) {
|
||||
userData: function(next) {
|
||||
user.getUsersFields(uids, ['uid', 'username', 'userslug'], next);
|
||||
},
|
||||
settings: function(next) {
|
||||
userSettings: function(next) {
|
||||
user.getMultipleUserSettings(uids, next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
|
||||
@@ -30,7 +30,6 @@ module.exports = function(Meta) {
|
||||
'public/vendor/tinycon/tinycon.js',
|
||||
'public/vendor/xregexp/xregexp.js',
|
||||
'public/vendor/xregexp/unicode/unicode-base.js',
|
||||
'public/vendor/autosize.js',
|
||||
'./node_modules/templates.js/lib/templates.js',
|
||||
'public/src/utils.js',
|
||||
'public/src/sockets.js',
|
||||
@@ -79,7 +78,7 @@ module.exports = function(Meta) {
|
||||
|
||||
// modules listed below are routed through express (/src/modules) so they can be defined anonymously
|
||||
modules: {
|
||||
"Chart.js": './node_modules/chart.js/Chart.js',
|
||||
"Chart.js": './node_modules/chart.js/dist/Chart.min.js',
|
||||
"mousetrap.js": './node_modules/mousetrap/mousetrap.js',
|
||||
|
||||
"buzz.js": 'public/vendor/buzz/buzz.js'
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
var async = require('async');
|
||||
var nconf = require('nconf');
|
||||
|
||||
var db = require('../database');
|
||||
var user = require('../user');
|
||||
var meta = require('../meta');
|
||||
var plugins = require('../plugins');
|
||||
@@ -94,6 +95,12 @@ module.exports = function(app, middleware) {
|
||||
next(null, userData);
|
||||
}
|
||||
},
|
||||
isEmailConfirmSent: function(next) {
|
||||
if (!meta.config.requireEmailConfirmation || !req.uid) {
|
||||
return next(null, false);
|
||||
}
|
||||
db.get('uid:' + req.uid + ':confirm:email:sent', next);
|
||||
},
|
||||
navigation: async.apply(navigation.get),
|
||||
tags: async.apply(meta.tags.parse, res.locals.metaTags, res.locals.linkTags)
|
||||
}, function(err, results) {
|
||||
@@ -110,6 +117,7 @@ module.exports = function(app, middleware) {
|
||||
results.user.isGlobalMod = results.isGlobalMod;
|
||||
results.user.uid = parseInt(results.user.uid, 10);
|
||||
results.user['email:confirmed'] = parseInt(results.user['email:confirmed'], 10) === 1;
|
||||
results.user.isEmailConfirmSent = !!results.isEmailConfirmSent;
|
||||
|
||||
if (parseInt(meta.config.disableCustomUserSkins, 10) !== 1 && res.locals.config.bootswatchSkin !== 'default') {
|
||||
templateValues.bootswatchCSS = '//maxcdn.bootstrapcdn.com/bootswatch/latest/' + res.locals.config.bootswatchSkin + '/bootstrap.min.css';
|
||||
|
||||
@@ -206,6 +206,7 @@ middleware.isAdmin = function(req, res, next) {
|
||||
|
||||
var loginTime = req.session.meta ? req.session.meta.datetime : 0;
|
||||
if (loginTime && parseInt(loginTime, 10) > Date.now() - 3600000) {
|
||||
req.session.meta.datetime += 300000;
|
||||
return next();
|
||||
}
|
||||
|
||||
|
||||
@@ -425,28 +425,4 @@ var middleware;
|
||||
], next);
|
||||
};
|
||||
|
||||
// function addLanguages(params, callback) {
|
||||
// Plugins.customLanguages.forEach(function(lang) {
|
||||
// console.log('route for', '/language/' + lang.route);
|
||||
// params.router.get('/language' + lang.route, function(req, res, next) {
|
||||
// res.json(lang.file);
|
||||
// });
|
||||
|
||||
// var components = lang.route.split('/'),
|
||||
// language = components[1],
|
||||
// filename = components[2].replace('.json', '');
|
||||
|
||||
// translator.addTranslation(language, filename, lang.file);
|
||||
// });
|
||||
|
||||
// for(var resource in Plugins.customLanguageFallbacks) {
|
||||
// params.router.get('/language/:lang/' + resource + '.json', function(req, res, next) {
|
||||
// winston.verbose('[translator] No resource file found for ' + req.params.lang + '/' + path.basename(req.path, '.json') + ', using provided fallback language file');
|
||||
// res.sendFile(Plugins.customLanguageFallbacks[path.basename(req.path, '.json')]);
|
||||
// });
|
||||
// }
|
||||
|
||||
// callback(null);
|
||||
// }
|
||||
|
||||
}(exports));
|
||||
|
||||
@@ -14,13 +14,17 @@ module.exports = function(Plugins) {
|
||||
`data.priority`, the relative priority of the method when it is eventually called (default: 10)
|
||||
*/
|
||||
Plugins.registerHook = function(id, data, callback) {
|
||||
callback = callback || function() {};
|
||||
function register() {
|
||||
Plugins.loadedHooks[data.hook] = Plugins.loadedHooks[data.hook] || [];
|
||||
Plugins.loadedHooks[data.hook].push(data);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
if (!data.hook) {
|
||||
winston.warn('[plugins/' + id + '] registerHook called with invalid data.hook', data);
|
||||
return callback();
|
||||
}
|
||||
|
||||
var method;
|
||||
@@ -65,6 +69,7 @@ module.exports = function(Plugins) {
|
||||
register();
|
||||
} else {
|
||||
winston.warn('[plugins/' + id + '] Hook method mismatch: ' + data.hook + ' => ' + data.method);
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
var SocketIO = require('socket.io');
|
||||
var SocketIO = require('socket.io');
|
||||
var socketioWildcard = require('socketio-wildcard')();
|
||||
var async = require('async');
|
||||
var nconf = require('nconf');
|
||||
|
||||
@@ -28,8 +28,8 @@ var emailer = require('../emailer');
|
||||
|
||||
UserEmail.sendValidationEmail = function(uid, email, callback) {
|
||||
callback = callback || function() {};
|
||||
var confirm_code = utils.generateUUID(),
|
||||
confirm_link = nconf.get('url') + '/confirm/' + confirm_code;
|
||||
var confirm_code = utils.generateUUID();
|
||||
var confirm_link = nconf.get('url') + '/confirm/' + confirm_code;
|
||||
|
||||
var emailInterval = meta.config.hasOwnProperty('emailConfirmInterval') ? parseInt(meta.config.emailConfirmInterval, 10) : 10;
|
||||
|
||||
@@ -97,6 +97,7 @@ var emailer = require('../emailer');
|
||||
async.series([
|
||||
async.apply(user.setUserField, confirmObj.uid, 'email:confirmed', 1),
|
||||
async.apply(db.delete, 'confirm:' + code),
|
||||
async.apply(db.delete, 'uid:' + confirmObj.uid + ':confirm:email:sent'),
|
||||
function(next) {
|
||||
db.sortedSetRemove('users:notvalidated', confirmObj.uid, next);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ module.exports = function(User) {
|
||||
var updateUid = uid;
|
||||
var imageDimension = parseInt(meta.config.profileImageDimension, 10) || 128;
|
||||
var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10) === 1;
|
||||
var keepAllVersions = parseInt(meta.config['profile:keepAllUserImages'], 10) === 1;
|
||||
var uploadedImage;
|
||||
|
||||
async.waterfall([
|
||||
@@ -42,7 +43,7 @@ module.exports = function(User) {
|
||||
return plugins.fireHook('filter:uploadImage', {image: picture, uid: updateUid}, next);
|
||||
}
|
||||
|
||||
var filename = updateUid + '-profileimg' + (convertToPNG ? '.png' : extension);
|
||||
var filename = updateUid + '-profileimg' + (keepAllVersions ? '-' + Date.now() : '') + (convertToPNG ? '.png' : extension);
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
@@ -68,21 +69,7 @@ module.exports = function(User) {
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
User.getUserField(updateUid, 'uploadedpicture', next);
|
||||
},
|
||||
function(oldpicture, next) {
|
||||
if (!oldpicture) {
|
||||
return file.saveFileToLocal(filename, 'profile', picture.path, next);
|
||||
}
|
||||
var oldpicturePath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), 'profile', path.basename(oldpicture));
|
||||
|
||||
fs.unlink(oldpicturePath, function (err) {
|
||||
if (err) {
|
||||
winston.error(err);
|
||||
}
|
||||
|
||||
file.saveFileToLocal(filename, 'profile', picture.path, next);
|
||||
});
|
||||
file.saveFileToLocal(filename, 'profile', picture.path, next);
|
||||
},
|
||||
], next);
|
||||
},
|
||||
@@ -134,6 +121,7 @@ module.exports = function(User) {
|
||||
};
|
||||
|
||||
User.updateCoverPicture = function(data, callback) {
|
||||
var keepAllVersions = parseInt(meta.config['profile:keepAllUserImages'], 10) === 1;
|
||||
var url, md5sum;
|
||||
|
||||
if (!data.imageData && data.position) {
|
||||
@@ -181,7 +169,7 @@ module.exports = function(User) {
|
||||
return plugins.fireHook('filter:uploadImage', {image: image, uid: data.uid}, next);
|
||||
}
|
||||
|
||||
var filename = data.uid + '-profilecover';
|
||||
var filename = data.uid + '-profilecover' + (keepAllVersions ? '-' + Date.now() : '');
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
file.isFileTypeAllowed(data.file.path, next);
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
var app = {
|
||||
template: "{template.name}",
|
||||
user: JSON.parse('{{userJSON}}'),
|
||||
config: JSON.parse(decodeURIComponent("{{adminConfigJSON}}"))
|
||||
config: JSON.parse(decodeURIComponent("{{adminConfigJSON}}")),
|
||||
flags: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -118,15 +118,9 @@
|
||||
<ul id="user_label" class="pull-right">
|
||||
<li class="dropdown pull-right">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="user_dropdown">
|
||||
<i class="fa fa-ellipsis-v"></i>
|
||||
<i class="fa fa-fw fa-ellipsis-v"></i>
|
||||
</a>
|
||||
<ul id="user-control-list" class="dropdown-menu" aria-labelledby="user_dropdown">
|
||||
<li>
|
||||
<a href="{relative_path}/" target="_top" title="View Forum">
|
||||
View Forum
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li>
|
||||
<a href="#" class="reload" title="Reload Forum">
|
||||
Reload Forum
|
||||
@@ -143,6 +137,13 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="pull-right">
|
||||
<a href="{config.relative_path}/">
|
||||
<i class="fa fa-fw fa-home" title="View Forum"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<form class="pull-right hidden-sm hidden-xs" role="search">
|
||||
<div class="" id="acp-search" >
|
||||
<div class="dropdown">
|
||||
|
||||
@@ -115,6 +115,13 @@
|
||||
(in kilobytes, default: 2,048 KiB)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="checkbox">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input class="mdl-switch__input" type="checkbox" data-field="profile:keepAllUserImages">
|
||||
<span class="mdl-switch__label"><strong>Keep old versions of avatars and profile covers on the server</strong></span>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,4 +139,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/settings/footer.tpl -->
|
||||
<!-- IMPORT admin/settings/footer.tpl -->
|
||||
|
||||
@@ -85,6 +85,7 @@ function initializeNodeBB(callback) {
|
||||
function(next) {
|
||||
plugins.init(app, middleware, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, 'static:assets.prepare', {}),
|
||||
async.apply(meta.js.bridgeModules, app),
|
||||
function(next) {
|
||||
async.series([
|
||||
|
||||
@@ -44,7 +44,7 @@ widgets.render = function(uid, area, req, res, callback) {
|
||||
req: req,
|
||||
res: res
|
||||
}, function(err, html) {
|
||||
if (err) {
|
||||
if (err || html === null) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user