From 33eb000ee33e5aa513083450f0a00abd7240efb0 Mon Sep 17 00:00:00 2001 From: ppelegrin Date: Tue, 15 Oct 2019 23:33:50 +0200 Subject: [PATCH 001/176] Start adding missing portuguese translation --- webapp/locales/pt.json | 946 ++++++++++++++++++++++++++++++++++------- 1 file changed, 791 insertions(+), 155 deletions(-) diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index 6eccc2fc0..903be2d5d 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -1,8 +1,85 @@ { + "components": { + "password-reset": { + "request": { + "title": "Redefinir sua senha", + "form": { + "description": "Um e-mail de redefinição de senha será enviado ao endereço de e-mail fornecido.", + "submit": "Solicitar e-mail", + "submitted": "Um e-mail com mais instruções foi enviado para {email}" + } + }, + "change-password": { + "success": "Changing your password was successful!", + "error": "Changing your password failed. Maybe the security code was not correct?", + "help": "In case of problems, feel free to ask for help by sending us a mail to:" + } + }, + "enter-nonce": { + "form": { + "nonce": "Enter your code", + "description": "Open your inbox and enter the code that we've sent to you.", + "next": "Continue", + "validations": { + "length": "must be 6 characters long" + } + } + }, + "registration": { + "signup": { + "unavailable": "Unfortunately, public registration of user accounts is not available right now on this server.", + "title": "Join Human Connection!", + "form": { + "description": "To get started, enter your email address:", + "invitation-code": "Your invitation code is: {code}", + "errors": { + "email-exists": "There is already a user account with this email address!", + "invalid-invitation-token": "It looks like as if the invitation has been used already. Invitation links can only be used once." + }, + "submit": "Create an account", + "success": "A mail with a link to complete your registration has been sent to {email}" + } + }, + "create-user-account": { + "title": "Create user account", + "success": "Your account has been created!", + "error": "No user account could be created!", + "help": " Maybe the confirmation was invalid? In case of problems, feel free to ask for help by sending us a mail to:" + } + } + }, + "maintenance": { + "title": "Human Connection is under maintenance", + "explanation": "At the moment we are doing some scheduled maintenance, please try again later.", + "questions": "Any Questions or concerns, send an email to" + }, + "index": { + "no-results": "No contributions found.", + "change-filter-settings": "Change your filter settings to get more results." + }, + "filter-menu": { + "title": "Your filter bubble", + "hashtag-search": "Searching for #{hashtag}", + "clearSearch": "Clear search" + }, + "filter-posts": { + "categories": { + "header": "Categories of Content", + "all": "All" + }, + "general": { + "header": "Filter by …" + }, + "followers": { + "label": "Users I follow" + } + }, "site": { + "thanks": "Obrigado(a)!", + "error-occurred": "Ocorreu um erro.", "made": "Feito com ❤", "imprint": "Impressão", - "termsAc": "Termos e Condições", + "termsAndConditions": "Termos e Condições", "data-privacy": "Proteção de Dados", "changelog": "Mudanças e Histórico", "contact": "Contato", @@ -14,7 +91,11 @@ "bank": "conta bancária", "germany": "Alemanha", "code-of-conduct": "Codigo de Conduto", - "login": "Voltar para o Login" + "back-to-login": "Voltar para o Login" + }, + "sorting": { + "newest": "Newest", + "oldest": "Oldest" }, "login": { "copy": "Se você já tem uma conta no Human Connection, por favor faça o login.", @@ -22,211 +103,766 @@ "logout": "Sair", "email": "Seu email", "password": "Sua senha", + "forgotPassword": "Esqueceu a sua senha?", + "no-account": "Ainda não tem uma conta?", + "register": "Cadastrar-se", "moreInfo": "O que é o Human Connection?", + "moreInfoURL": "https://human-connection.org/en/", "hello": "Olá", - "forgotPassword": "Esqueceu a sua senha?" + "success": "Você está conectado!" }, - "password-reset": { - "form": { - "description": "Um e-mail de redefinição de senha será enviado para o endereço de e-mail fornecido.", - "submit": "Solicitar email", - "submitted": "Um e-mail com mais instruções foi enviado para {email}" + "editor": { + "placeholder": "Leave your inspirational thoughts …", + "mention": { + "noUsersFound": "No users found" + }, + "hashtag": { + "noHashtagsFound": "No hashtags found", + "addHashtag": "New hashtag", + "addLetter": "Type a letter" + }, + "embed": { + "data_privacy_warning": "Data Privacy Warning!", + "data_privacy_info": "Your data has not yet been shared with any third party providers. If you proceed to watch this video the following provider will likely collect user data:", + "play_now": "Watch now", + "always_allow": "Always allow embedded content by third party providers (this setting can be changed any time)" } }, "profile": { - "name": "Meu perfil", - "memberSince": "Membro desde", - "follow": "Seguir", - "followers": "Seguidores", - "following": "Seguindo", - "shouted": "Aclamou", - "commented": "Comentou", - "userAnonym": "Anonymous" - }, - "settings": { - "name": "Configurações", - "data": { - "name": "Seus dados", - "labelName": "Seu nome", - "namePlaceholder": "Anonymous", - "labelCity": "Sua cidade ou estado", - "labelBio": "Sobre você" - }, - "security": { - "name": "Segurança" + "name": "My Profile", + "memberSince": "Member since", + "follow": "Follow", + "followers": "Followers", + "following": "Following", + "shouted": "Shouted", + "commented": "Commented", + "userAnonym": "Anonymous", + "socialMedia": "Where else can I find", + "network": { + "title": "Network", + "following": "is following:", + "followingNobody": "follows nobody.", + "followedBy": "is followed by:", + "followedByNobody": "is not followed by anyone.", + "andMore": "and {number} more …" }, "invites": { - "name": "Convites" + "title": "Invite somebody to Human Connection!", + "description": "Enter thier email address for invitation.", + "emailPlaceholder": "Email to invite" + } + }, + "notifications": { + "reason": { + "mentioned_in_post": "Mentioned you in a post …", + "mentioned_in_comment": "Mentioned you in a comment …", + "commented_on_post": "Commented on your post …" + }, + "comment": "Comment" + }, + "search": { + "placeholder": "Search", + "hint": "What are you searching for?", + "failed": "Nothing found" + }, + "settings": { + "name": "Settings", + "data": { + "name": "Your data", + "labelName": "Your Name", + "labelSlug": "Your unique user name", + "namePlaceholder": "Femanon Funny", + "labelCity": "Your City or Region", + "labelBio": "About You", + "success": "Your data was successfully updated!" + }, + "email": { + "validation": { + "same-email": "This is your current email address" + }, + "name": "Your email", + "labelEmail": "Change your email address", + "labelNewEmail": "New email Address", + "labelNonce": "Enter your code", + "success": "A new email address has been registered.", + "submitted": "An email to verify your address has been sent to {email}.", + "change-successful": "Your email address has been changed successfully.", + "verification-error": { + "message": "Your email could not be changed.", + "explanation": "This can have different causes:", + "reason": { + "invalid-nonce": "Is the confirmation code invalid?", + "no-email-request": "Are you certain that you requested a change of your email address?" + }, + "support": "If the problem persists, please contact us by email at" + } + }, + "validation": { + "slug": { + "regex": "Allowed characters are only lowercase letters, numbers, underscores and hyphens.", + "alreadyTaken": "This user name is already taken." + } + }, + "security": { + "name": "Security", + "change-password": { + "button": "Change password", + "success": "Password successfully changed!", + "label-old-password": "Your old password", + "label-new-password": "Your new password", + "label-new-password-confirm": "Confirm new password", + "message-old-password-required": "Enter your old password", + "message-new-password-required": "Enter a new password", + "message-new-password-confirm-required": "Confirm your new password", + "message-new-password-missmatch": "Type the same password again", + "passwordSecurity": "Password security", + "passwordStrength0": "Very insecure password", + "passwordStrength1": "Insecure password", + "passwordStrength2": "Mediocre password", + "passwordStrength3": "Strong password", + "passwordStrength4": "Very strong password" + } + }, + "invites": { + "name": "Invites" }, "download": { - "name": "Baixar dados" + "name": "Download Data" }, - "delete": { - "name": "Apagar conta" + "deleteUserAccount": { + "name": "Delete data", + "contributionsCount": "Delete my {count} posts", + "commentedCount": "Delete my {count} comments", + "accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.", + "accountWarning": "You CAN'T MANAGE and CAN'T RECOVER your Account, Posts, or Comments after deleting your account!", + "success": "Account successfully deleted!", + "pleaseConfirm": "Destructive action! Type {confirm} to confirm" + }, + "embeds": { + "name": "Third party providers", + "info-description": "Here is the list of third-party providers whose content can be displayed as third-party code, e.g. in the form of embedded videos.", + "status": { + "description": "As a default for you, embedded code of third-party providers is", + "disabled": { + "off": "initially not displayed", + "on": "displayed immediately" + }, + "change": { + "question": "Should embedded source code from third parties always be displayed to you?", + "allow": "Sure", + "deny": "No thanks" + } + } }, "organizations": { - "name": "Minhas Organizações" + "name": "My Organizations" }, "languages": { - "name": "Linguagens" + "name": "Languages" + }, + "social-media": { + "name": "Social media", + "placeholder": "Your social media url", + "requireUnique": "You added this url already", + "submit": "Add link", + "successAdd": "Added social media. Updated user profile!", + "successDelete": "Deleted social media. Updated user profile!" + }, + "blocked-users": { + "name": "Blocked users", + "explanation": { + "intro": "If another user has been blocked by you, this is what happens:", + "your-perspective": "The blocked person's posts will no longer appear in your news feed.", + "their-perspective": "Vice versa: The blocked person will also no longer see your posts in their news feed.", + "search": "Posts of blocked people disappear from your search results.", + "notifications": "Blocked users will no longer receive notifications if they are mentioned in your posts.", + "closing": "This should be sufficient for now so that blocked users can no longer bother you." + }, + "columns": { + "name": "Name", + "slug": "Slug" + }, + "empty": "So far, you have not blocked anybody.", + "how-to": "You can block other users on their profile page via the content menu.", + "block": "Block user", + "unblock": "Unblock user" } }, "admin": { - "name": "Administração", + "name": "Admin", "dashboard": { - "name": "Painel de controle", - "users": "Usuários", - "posts": "Postagens", - "comments": "Comentários", - "notifications": "Notificações", - "organizations": "Organizações", - "projects": "Projetos", - "invites": "Convites", - "follows": "Segue", - "shouts": "Aclamações" + "name": "Dashboard", + "users": "Users", + "posts": "Posts", + "comments": "Comments", + "notifications": "Notifications", + "organizations": "Organizations", + "projects": "Projects", + "invites": "Invites", + "follows": "Follows", + "shouts": "Shouts" }, "organizations": { - "name": "Organizações" + "name": "Organizations" }, "users": { - "name": "Usuários" + "name": "Users", + "form": { + "placeholder": "email, name or description" + }, + "table": { + "columns": { + "number": "No.", + "name": "Name", + "email": "E-mail", + "slug": "Slug", + "role": "Role", + "createdAt": "Created at" + } + }, + "empty": "No users found" }, "pages": { - "name": "Páginas" + "name": "Pages" }, "notifications": { - "name": "Notificações" + "name": "Notifications" }, "categories": { - "name": "Categorias", - "categoryName": "Nome", - "postCount": "Postagens" + "name": "Categories", + "categoryName": "Name", + "postCount": "Posts" }, - "tags": { - "name": "Etiquetas", - "tagCountUnique": "Usuários", - "tagCount": "Postagens" + "hashtags": { + "name": "Hashtags", + "number": "No.", + "nameOfHashtag": "Name", + "tagCountUnique": "Users", + "tagCount": "Posts" }, "settings": { - "name": "Configurações" + "name": "Settings" + }, + "invites": { + "name": "Invite users", + "title": "Invite people", + "description": "Invitations are a wonderful way to have your friends in your network …" } }, "post": { - "name": "Postar", + "name": "Post", "moreInfo": { - "name": "Mais informações" + "name": "More info", + "title": "More information", + "description": "Here you can find more information about this topic.", + "titleOfCategoriesSection": "Categories", + "titleOfHashtagsSection": "Hashtags", + "titleOfRelatedContributionsSection": "Related posts" }, "takeAction": { - "name": "Tomar uma ação" + "name": "Take action" + }, + "menu": { + "edit": "Edit Post", + "delete": "Delete Post" }, "comment": { - "submit": "Commentar" + "submit": "Comment", + "submitted": "Comment Submitted", + "updated": "Changes Saved" }, - "edited": "editado" - }, - "quotes": { - "african": { - "quote": "Muitas pessoas pequenas, em muitos lugares pequenos, fazem muitas coisas pequenas, que podem mudar a face do mundo.", - "author": "Provérbio africano" - } - }, - "common": { - "post": "Postagem ::: Postagens", - "comment": "Comentário ::: Comentários", - "letsTalk": "Vamos Conversar", - "versus": "Contra", - "moreInfo": "Mais informações", - "takeAction": "Tomar uma ação", - "shout": "Aclamação ::: Aclamações", - "user": "Usuário ::: Usuários", - "category": "Categoria ::: Categorias", - "organization": "Organização ::: Organizações", - "project": "Projeto ::: Projetos", - "tag": "Etiqueta ::: Etiquetas", - "name": "Nome", - "loadMore": "Carregar mais", - "loading": "Carregando", - "reportContent": "Denunciar" - }, - "actions": { - "loading": "Carregando", - "loadMore": "Carregar mais", - "create": "Criar", - "save": "Salvar", - "edit": "Editar", - "delete": "Apagar", - "cancel": "Cancelar" - }, - "moderation": { - "name": "Moderação", - "reports": { - "empty": "Parabéns, nada a moderar.", - "name": "Denúncias", - "reporter": "Denunciado por" - } - }, - "disable": { - "user": { - "title": "Desativar usuário", - "type": "Usuário", - "message": "Você realmente deseja desativar o usuário \" {name} \"?" - }, - "contribution": { - "title": "Desativar Contribuição", - "type": "Contribuição", - "message": "Você realmente deseja desativar a contribuição \" {name} \"?" - }, - "comment": { - "title": "Desativar comentário", - "type": "Comentário", - "message": "Você realmente deseja desativar o comentário de \" {name} \"?" - } - }, - "report": { - "submit": "Enviar denúncia", - "cancel": "Cancelar", - "user": { - "title": "Denunciar usuário", - "type": "Usuário", - "message": "Você realmente deseja denunciar o usuário \" {name} \"?" - }, - "contribution": { - "title": "Denunciar Contribuição", - "type": "Contribuição", - "message": "Você realmente deseja denunciar a contribuição \" {name} \"?" - }, - "comment": { - "title": "Denunciar Comentário", - "type": "Comentário", - "message": "Você realmente deseja denunciar o comentário de \"{name}\"?" - } - }, - "contribution": { - "edit": "Editar Contribuição", - "delete": "Apagar Contribuição", - "teaserImage": { - "cropperConfirm": "Confirmar" - } + "edited": "edited" }, "comment": { "content": { - "unavailable-placeholder": "… este commenttário não está disponível" + "unavailable-placeholder": "… this comment is not available anymore" }, "menu": { - "edit": "Editar Comentário", - "delete": "Apagar Comentário" + "edit": "Edit Comment", + "delete": "Delete Comment" }, "show": { - "more": "mostrar mais", - "less": "mostrar menos" + "more": "show more", + "less": "show less" }, - "edited": "editado" + "edited": "edited" + }, + "quotes": { + "african": { + "quote": "Many small people in many small places do many small things, that can alter the face of the world.", + "author": "African proverb" + } + }, + "common": { + "post": "Post ::: Posts", + "comment": "Comment ::: Comments", + "letsTalk": "Let`s Talk", + "versus": "Versus", + "moreInfo": "More Info", + "takeAction": "Take Action", + "shout": "Shout ::: Shouts", + "user": "User ::: Users", + "category": "Category ::: Categories", + "organization": "Organization ::: Organizations", + "project": "Project ::: Projects", + "tag": "Tag ::: Tags", + "name": "Name", + "loadMore": "load more", + "loading": "loading", + "reportContent": "Report", + "validations": { + "email": "must be a valid email address", + "url": "must be a valid URL" + } + }, + "actions": { + "loading": "loading", + "loadMore": "load more", + "create": "Create", + "save": "Save", + "edit": "Edit", + "delete": "Delete", + "cancel": "Cancel" + }, + "moderation": { + "name": "Moderation", + "reports": { + "empty": "Congratulations, nothing to moderate.", + "name": "Reports", + "submitter": "reported by", + "disabledBy": "disabled by" + } + }, + "disable": { + "submit": "Disable", + "cancel": "Cancel", + "success": "Disabled successfully!", + "user": { + "title": "Disable User", + "type": "User", + "message": "Do you really want to disable the user \"{name}\"?" + }, + "contribution": { + "title": "Disable Contribution", + "type": "Contribution", + "message": "Do you really want to disable the contribution \"{name}\"?" + }, + "comment": { + "title": "Disable Comment", + "type": "Comment", + "message": "Do you really want to disable the comment from \"{name}\"?" + } + }, + "delete": { + "submit": "Delete", + "cancel": "Cancel", + "contribution": { + "title": "Delete Post", + "type": "Contribution", + "message": "Do you really want to delete the post \"{name}\"?", + "success": "Post successfully deleted!" + }, + "comment": { + "title": "Delete Comment", + "type": "Comment", + "message": "Do you really want to delete the comment \"{name}\"?", + "success": "Comment successfully deleted!" + } + }, + "report": { + "submit": "Report", + "cancel": "Cancel", + "success": "Thanks for reporting!", + "user": { + "title": "Report User", + "type": "User", + "message": "Do you really want to report the user \"{name}\"?", + "error": "You already reported the user!" + }, + "contribution": { + "title": "Report Post", + "type": "Contribution", + "message": "Do you really want to report the contribution \"{name}\"?", + "error": "You have already reported the contribution!" + }, + "comment": { + "title": "Report Comment", + "type": "Comment", + "message": "Do you really want to report the comment from \"{name}\"?", + "error": "You have already reported the comment!" + } }, "followButton": { - "follow": "Seguir", - "following": "Seguindo" + "follow": "Follow", + "following": "Following" }, "shoutButton": { - "shouted": "Aclamou" + "shouted": "shouted" + }, + "release": { + "submit": "Release", + "cancel": "Cancel", + "success": "Released successfully!", + "user": { + "title": "Release User", + "type": "User", + "message": "Do you really want to release the user \"{name}\"?", + "error": "You already reported the user!" + }, + "contribution": { + "title": "Release Contribution", + "type": "Contribution", + "message": "Do you really want to release the contribution \"{name}\"?", + "error": "You have already reported the contribution!!" + }, + "comment": { + "title": "Release Comment", + "type": "Comment", + "message": "Do you really want to release the comment from \"{name}\"?", + "error": "You have already reported the comment!" + } + }, + "user": { + "avatar": { + "submitted": "Upload successful!" + } + }, + "contribution": { + "newPost": "Create a new Post", + "filterFollow": "Filter contributions from users I follow", + "filterALL": "View all contributions", + "success": "Saved!", + "languageSelectLabel": "Language", + "categories": { + "infoSelectedNoOfMaxCategories": "{chosen} of {max} categories selected" + }, + "emotions-label": { + "funny": "Funny", + "happy": "Happy", + "surprised": "Surprised", + "cry": "Cry", + "angry": "Angry" + }, + "category": { + "name": { + "freedom-of-speech": "Freedom of Speech", + "consumption-sustainability": "Consumption & Sustainability", + "global-peace-nonviolence": "Global Peace & Nonviolence", + "just-for-fun": "Just for Fun", + "happiness-values": "Happiness & Values", + "health-wellbeing": "Health & Wellbeing", + "environment-nature": "Environment & Nature", + "animal-protection": "Animal Protection", + "human-rights-justice": "Human Rights & Justice", + "education-sciences": "Education & Sciences", + "cooperation-development": "Cooperation & Development", + "democracy-politics": "Democracy & Politics", + "economy-finances": "Economy & Finances", + "energy-technology": "Energy & Technology", + "it-internet-data-privacy": "IT, Internet & Data Privacy", + "art-culture-sport": "Art, Culture, & Sport" + } + }, + "teaserImage": { + "cropperConfirm": "Confirm" + } + }, + "code-of-conduct": { + "subheader": "for the social network of the Human Connection gGmbH", + "preamble": { + "title": "Preamble", + "description": "Human Connection is a non-profit social knowledge and action network of the next generation. By people - for people. Open Source, fair and transparent. For positive local and global change in all areas of life. We completely redesign the public exchange of knowledge, ideas and projects. The functions of Human Connection bring people together - offline and online - so that we can make the world a better place." + }, + "purpose": { + "title": "Purpose", + "description": "With these code of conduct we regulate the essential principles for behavior in our social network. The United Nations Charter of Human Rights is our orientation and forms the heart of our understanding of values. The code of conduct serves as guiding principles for our personal appearance and interaction with one another. Anyone who is active as a user in the Human Connection Network, writes articles, comments or contacts other users, including those outside the network,acknowledges these rules of conduct as binding." + }, + "expected-behaviour": { + "title": "Expected Behaviour", + "description": "The following behaviors are expected and requested of all community members:", + "list": { + "0": "Exercise consideration and respect in your speech and actions.", + "1": "Attempt collaboration before conflict.", + "2": "Refrain from demeaning, discriminatory, or harassing behavior and speech.", + "3": "Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential." + } + }, + "unacceptable-behaviour": { + "title": "Unacceptable Behavior", + "description": "The following behaviors are unacceptable within our community:", + "list": { + "0": "Discriminatory posts, comments, utterances or insults, particularly those relating to gender, sexual orientation, race, religion, political or philosophical orientation or disability.", + "1": "Posting or linking of clearly pornographic material.", + "2": "Glorification or trivialization of cruel or inhuman acts of violence.", + "3": "The disclosure of others' personal information without their consent or threat there of (\"doxing\").", + "4": "Intentional intimidation, stalking or persecution.", + "5": "Advertising products and services with commercial intent.", + "6": "Criminal behavior or violation of German law.", + "7": "Endorse or encourage such conduct." + } + }, + "consequences": { + "title": "Consequences of Unacceptable Behavior", + "description": "If a community member exhibits unacceptable behaviour, the responsible operators, moderators and administrators of the network may take appropriate measures, including but not limited to:", + "list": { + "0": "Request for immediate cessation of unacceptable conduct", + "1": "Locking or deleting comments", + "2": "Temporary exclusion from the respective post or contribution", + "3": "Blocking or deleting of content", + "4": "Temporary withdrawal of write permissions", + "5": "Temporary exclusion from the network", + "6": "Final exclusion from the network", + "7": "Violations of German law can be reported.", + "8": "Advocacy or encouragement to these behaviors." + } + }, + "get-help": "If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible and link or refer to the corresponding content:" + }, + "termsAndConditions": { + "newTermsAndConditions": "New Terms and Conditions", + "termsAndConditionsConfirmed": "I have read and confirmed the Terms and Conditions.", + "termsAndConditionsNewConfirmText": "Please read the new terms of use now!", + "termsAndConditionsNewConfirm": "I have read and agree to the new terms of conditions.", + "agree": "I agree!", + "risk": { + "title": "Risk of accident", + "description": "This is a test version! All data, your profile and the server can be completely destroyed, wiped out, lost, burnt and eventually synchronised near Alpha Centauri at any time. Use on your own risk. Commercial effects are not likely though." + }, + "data-privacy": { + "title": "You and your data", + "description": "Please note that the content of the alpha version will be used for public web presentations etc. but we are sure, this is in your interest. Avoid real names and use anonymous profile pictures without your face. You can find more information in our data privacy policy" + }, + "work-in-progress": { + "title": "Work in progress", + "description": "This is still a test version. Please excuse if some applications are not working, blocking, irritating, displayed falsely or not able to be clicked on. Please report faults and bugs! mailto:support@human-connection.org" + }, + "code-of-conduct": { + "title": "Code of conduct", + "description": "The code of conduct serves as guiding principles for our personal appearance and interaction with one another. Anyone who is active as a user in the Human Connection Network, writes articles, comments or contacts other users, including those outside the network, acknowledges these rules of conduct as binding." + }, + "moderation": { + "title": "Moderation", + "description": "As long as there is no community moderation-system in operation, a rainbow colored unicorn decides, if you are physically and mentally stable enough to operate our test version. The unicorn can delete you from the alpha version at any time. So be so kind and leave rainbow food!" + }, + "fairness": { + "title": "Fairness", + "description": "If, against all expectations, our alpha version is not to your liking, we return your monthly payment within the first two months. Please send a mail to: info@human-connection.org Note that more features are added on a regular basis." + }, + "questions": { + "title": "Questions", + "description": "You can find the dates and links to our zoom-rooms here: https://human-connection.org/en/events/ " + }, + "human-connection": { + "title": "By humans for humans", + "description": "Please help us to get new donators for Human Connection, so the network can take off as soon as possible. https://human-connection.org " + }, + "have-fun": "Now have fun with the alpha version of Human Connection! For the first universal peace. ♥︎", + "closing": "Thank you very much

your Human Connection Team" } } + +// { +// "password-reset": { +// "form": { +// "description": "Um e-mail de redefinição de senha será enviado para o endereço de e-mail fornecido.", +// "submit": "Solicitar email", +// "submitted": "Um e-mail com mais instruções foi enviado para {email}" +// } +// }, +// "profile": { +// "name": "Meu perfil", +// "memberSince": "Membro desde", +// "follow": "Seguir", +// "followers": "Seguidores", +// "following": "Seguindo", +// "shouted": "Aclamou", +// "commented": "Comentou", +// "userAnonym": "Anonymous" +// }, +// "settings": { +// "name": "Configurações", +// "data": { +// "name": "Seus dados", +// "labelName": "Seu nome", +// "namePlaceholder": "Anonymous", +// "labelCity": "Sua cidade ou estado", +// "labelBio": "Sobre você" +// }, +// "security": { +// "name": "Segurança" +// }, +// "invites": { +// "name": "Convites" +// }, +// "download": { +// "name": "Baixar dados" +// }, +// "delete": { +// "name": "Apagar conta" +// }, +// "organizations": { +// "name": "Minhas Organizações" +// }, +// "languages": { +// "name": "Linguagens" +// } +// }, +// "admin": { +// "name": "Administração", +// "dashboard": { +// "name": "Painel de controle", +// "users": "Usuários", +// "posts": "Postagens", +// "comments": "Comentários", +// "notifications": "Notificações", +// "organizations": "Organizações", +// "projects": "Projetos", +// "invites": "Convites", +// "follows": "Segue", +// "shouts": "Aclamações" +// }, +// "organizations": { +// "name": "Organizações" +// }, +// "users": { +// "name": "Usuários" +// }, +// "pages": { +// "name": "Páginas" +// }, +// "notifications": { +// "name": "Notificações" +// }, +// "categories": { +// "name": "Categorias", +// "categoryName": "Nome", +// "postCount": "Postagens" +// }, +// "tags": { +// "name": "Etiquetas", +// "tagCountUnique": "Usuários", +// "tagCount": "Postagens" +// }, +// "settings": { +// "name": "Configurações" +// } +// }, +// "post": { +// "name": "Postar", +// "moreInfo": { +// "name": "Mais informações" +// }, +// "takeAction": { +// "name": "Tomar uma ação" +// }, +// "comment": { +// "submit": "Commentar" +// }, +// "edited": "editado" +// }, +// "quotes": { +// "african": { +// "quote": "Muitas pessoas pequenas, em muitos lugares pequenos, fazem muitas coisas pequenas, que podem mudar a face do mundo.", +// "author": "Provérbio africano" +// } +// }, +// "common": { +// "post": "Postagem ::: Postagens", +// "comment": "Comentário ::: Comentários", +// "letsTalk": "Vamos Conversar", +// "versus": "Contra", +// "moreInfo": "Mais informações", +// "takeAction": "Tomar uma ação", +// "shout": "Aclamação ::: Aclamações", +// "user": "Usuário ::: Usuários", +// "category": "Categoria ::: Categorias", +// "organization": "Organização ::: Organizações", +// "project": "Projeto ::: Projetos", +// "tag": "Etiqueta ::: Etiquetas", +// "name": "Nome", +// "loadMore": "Carregar mais", +// "loading": "Carregando", +// "reportContent": "Denunciar" +// }, +// "actions": { +// "loading": "Carregando", +// "loadMore": "Carregar mais", +// "create": "Criar", +// "save": "Salvar", +// "edit": "Editar", +// "delete": "Apagar", +// "cancel": "Cancelar" +// }, +// "moderation": { +// "name": "Moderação", +// "reports": { +// "empty": "Parabéns, nada a moderar.", +// "name": "Denúncias", +// "reporter": "Denunciado por" +// } +// }, +// "disable": { +// "user": { +// "title": "Desativar usuário", +// "type": "Usuário", +// "message": "Você realmente deseja desativar o usuário \" {name} \"?" +// }, +// "contribution": { +// "title": "Desativar Contribuição", +// "type": "Contribuição", +// "message": "Você realmente deseja desativar a contribuição \" {name} \"?" +// }, +// "comment": { +// "title": "Desativar comentário", +// "type": "Comentário", +// "message": "Você realmente deseja desativar o comentário de \" {name} \"?" +// } +// }, +// "report": { +// "submit": "Enviar denúncia", +// "cancel": "Cancelar", +// "user": { +// "title": "Denunciar usuário", +// "type": "Usuário", +// "message": "Você realmente deseja denunciar o usuário \" {name} \"?" +// }, +// "contribution": { +// "title": "Denunciar Contribuição", +// "type": "Contribuição", +// "message": "Você realmente deseja denunciar a contribuição \" {name} \"?" +// }, +// "comment": { +// "title": "Denunciar Comentário", +// "type": "Comentário", +// "message": "Você realmente deseja denunciar o comentário de \"{name}\"?" +// } +// }, +// "contribution": { +// "edit": "Editar Contribuição", +// "delete": "Apagar Contribuição", +// "teaserImage": { +// "cropperConfirm": "Confirmar" +// } +// }, +// "comment": { +// "content": { +// "unavailable-placeholder": "… este commenttário não está disponível" +// }, +// "menu": { +// "edit": "Editar Comentário", +// "delete": "Apagar Comentário" +// }, +// "show": { +// "more": "mostrar mais", +// "less": "mostrar menos" +// }, +// "edited": "editado" +// }, +// "followButton": { +// "follow": "Seguir", +// "following": "Seguindo" +// }, +// "shoutButton": { +// "shouted": "Aclamou" +// } +// } From 7d2801a636dcbf4713a2e46349c64577517218aa Mon Sep 17 00:00:00 2001 From: ogerly Date: Tue, 29 Oct 2019 11:05:49 +0100 Subject: [PATCH 002/176] after successful login the saved language of the user is set --- webapp/pages/login.vue | 11 +++++++++++ webapp/store/auth.js | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/webapp/pages/login.vue b/webapp/pages/login.vue index e969fe46f..4db3a7c3d 100644 --- a/webapp/pages/login.vue +++ b/webapp/pages/login.vue @@ -7,12 +7,18 @@ From 5fbe0da2ae9c43c82861036f6526507206a88c32 Mon Sep 17 00:00:00 2001 From: Ewald Arnold Date: Sun, 3 Nov 2019 17:31:10 +0100 Subject: [PATCH 012/176] add empty russian template --- webapp/locales/ru.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 webapp/locales/ru.json diff --git a/webapp/locales/ru.json b/webapp/locales/ru.json new file mode 100644 index 000000000..e69de29bb From 97bd1b4816cb0eb61c733aa451af9140a73efe55 Mon Sep 17 00:00:00 2001 From: Alexander Friedland Date: Sun, 3 Nov 2019 19:12:20 +0100 Subject: [PATCH 013/176] in ru.json i started this once in ru.json i started this once. as a template you can use german or english. both languages are complete. you can copy and paste the ru.json. what is not translated. default will be shown in english. --- webapp/locales/ru.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/webapp/locales/ru.json b/webapp/locales/ru.json index e69de29bb..6f97cdf10 100644 --- a/webapp/locales/ru.json +++ b/webapp/locales/ru.json @@ -0,0 +1,28 @@ +{ + "components": { + "password-reset": { + "request": { + "title": "Сбросить пароль", + "form": { + "description": "На указанный адрес электронной почты будет отправлено письмо для сброса пароля.", + "submit": "Запросить электронную почту", + "submitted": "На {email} отправлено письмо с дополнительными инструкциями." + } + }, + "change-password": { + "success": "Смена пароля прошла успешно!", + "error": "Смена пароля не удалась. Может быть, код безопасности был неверным?", + "help": "В случае возникновения проблем, не стесняйтесь обратиться за помощью, отправив нам письмо по адресу:" + } + }, + "enter-nonce": { + "form": { + "nonce": "Введите ваш код", + "description": "Откройте свой почтовый ящик и введите код, который мы вам отправили.", + "next": "Продолжить", + "validations": { + "length": "должно быть длиной 6 символов" + } + } + } + } From 60c2bba2718cda5507024ea1224f5f025657ef0e Mon Sep 17 00:00:00 2001 From: Alexander Friedland Date: Sun, 3 Nov 2019 19:14:44 +0100 Subject: [PATCH 014/176] fix missing bracket fix missing bracket --- webapp/locales/ru.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/locales/ru.json b/webapp/locales/ru.json index 6f97cdf10..a103ef7a9 100644 --- a/webapp/locales/ru.json +++ b/webapp/locales/ru.json @@ -25,4 +25,5 @@ } } } - } + } +} From a704709ba3ec9e8013f9af4f8141a712a52e5aa6 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Mon, 4 Nov 2019 18:52:34 +0100 Subject: [PATCH 015/176] fix: resolver returned undefined for `nameRU` This registers the language Russian in the backend. Unfortunately, the locations seem to be implemented with a hard coded attribute for each language. :disappointed: We should refactor this. --- backend/src/middleware/nodes/locations.js | 4 +++- backend/src/models/Location.js | 1 + backend/src/schema/types/Location.gql | 1 + backend/src/seed/seed-db.js | 5 +++++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/src/middleware/nodes/locations.js b/backend/src/middleware/nodes/locations.js index a90d8c0d7..e72869cb6 100644 --- a/backend/src/middleware/nodes/locations.js +++ b/backend/src/middleware/nodes/locations.js @@ -19,7 +19,7 @@ const fetch = url => { }) } -const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl'] +const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl', 'ru'] const createLocation = async (session, mapboxData) => { const data = { @@ -32,6 +32,7 @@ const createLocation = async (session, mapboxData) => { nameES: mapboxData.text_es, namePT: mapboxData.text_pt, namePL: mapboxData.text_pl, + nameRU: mapboxData.text_ru, type: mapboxData.id.split('.')[0].toLowerCase(), lat: mapboxData.center && mapboxData.center.length ? mapboxData.center[0] : null, lng: mapboxData.center && mapboxData.center.length ? mapboxData.center[1] : null, @@ -48,6 +49,7 @@ const createLocation = async (session, mapboxData) => { 'l.nameES = $nameES, ' + 'l.namePT = $namePT, ' + 'l.namePL = $namePL, ' + + 'l.nameRU = $nameRU, ' + 'l.type = $type' if (data.lat && data.lng) { diff --git a/backend/src/models/Location.js b/backend/src/models/Location.js index bd6e0b5d9..2c62877f7 100644 --- a/backend/src/models/Location.js +++ b/backend/src/models/Location.js @@ -12,6 +12,7 @@ module.exports = { nameDE: { type: 'string' }, nameNL: { type: 'string' }, namePL: { type: 'string' }, + nameRU: { type: 'string' }, isIn: { type: 'relationship', relationship: 'IS_IN', diff --git a/backend/src/schema/types/Location.gql b/backend/src/schema/types/Location.gql index e7053e345..78bc07656 100644 --- a/backend/src/schema/types/Location.gql +++ b/backend/src/schema/types/Location.gql @@ -9,6 +9,7 @@ type Location { nameES: String namePT: String namePL: String + nameRU: String type: String! lat: Float lng: Float diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js index 76fbb4875..1fc5af85a 100644 --- a/backend/src/seed/seed-db.js +++ b/backend/src/seed/seed-db.js @@ -39,6 +39,7 @@ import { gql } from '../jest/helpers' nameDE: 'Hamburg', nameNL: 'Hamburg', namePL: 'Hamburg', + nameRU: 'Гамбург', }), factory.create('Location', { id: 'region.14880313158564380', @@ -54,6 +55,7 @@ import { gql } from '../jest/helpers' nameDE: 'Berlin', nameNL: 'Berlijn', namePL: 'Berlin', + nameRU: 'Берлин', }), factory.create('Location', { id: 'country.10743216036480410', @@ -67,6 +69,7 @@ import { gql } from '../jest/helpers' nameFR: 'Allemagne', nameIT: 'Germania', nameEN: 'Germany', + nameRU: 'Германия', }), factory.create('Location', { id: 'region.9397217726497330', @@ -82,6 +85,7 @@ import { gql } from '../jest/helpers' nameDE: 'Paris', nameNL: 'Parijs', namePL: 'Paryż', + nameRU: 'Париж', }), factory.create('Location', { id: 'country.9759535382641660', @@ -95,6 +99,7 @@ import { gql } from '../jest/helpers' nameFR: 'France', nameIT: 'Francia', nameEN: 'France', + nameRU: 'Франция', }), ]) await Promise.all([ From 7e070208e0d3abd8510881066db2ed28de4d6bb0 Mon Sep 17 00:00:00 2001 From: ppelegrin Date: Mon, 4 Nov 2019 20:49:50 +0100 Subject: [PATCH 016/176] Continue portuguese translations --- webapp/locales/pt.json | 290 ++++++++++++++++++++--------------------- 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index 8877fe6a7..0b0b235f8 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -134,263 +134,263 @@ "follow": "Seguir", "followers": "Seguidores", "following": "Seguindo", - "shouted": "Aclamou", + "shouted": "Anunciou", "commented": "Comentou", - "userAnonym": "Anonymous", - "socialMedia": "Where else can I find", + "userAnonym": "Anônimo", + "socialMedia": "Onde mais posso encontrar", "network": { - "title": "Network", - "following": "is following:", - "followingNobody": "follows nobody.", - "followedBy": "is followed by:", - "followedByNobody": "is not followed by anyone.", - "andMore": "and {number} more …" + "title": "Rede", + "following": "está seguindo:", + "followingNobody": "não segue ninguém.", + "followedBy": "é seguido por:", + "followedByNobody": "não é seguido por ninguém.", + "andMore": "e {number} mais …" }, "invites": { - "title": "Invite somebody to Human Connection!", - "description": "Enter thier email address for invitation.", - "emailPlaceholder": "Email to invite" + "title": "Convidar alguém para Human Connection!", + "description": "Digite o endereço de e-mail para o convite.", + "emailPlaceholder": "E-mail para convidar" } }, "notifications": { "reason": { - "mentioned_in_post": "Mentioned you in a post …", - "mentioned_in_comment": "Mentioned you in a comment …", - "commented_on_post": "Commented on your post …" + "mentioned_in_post": "Mencionou você em um post …", + "mentioned_in_comment": "Mencionou você em um comentário …", + "commented_on_post": "Comentou no seu post …" }, - "comment": "Comment" + "comment": "Comentário" }, "search": { - "placeholder": "Search", - "hint": "What are you searching for?", - "failed": "Nothing found" + "placeholder": "Pesquisar", + "hint": "O que você está pesquisando??", + "failed": "Nada foi encontrado" }, "settings": { - "name": "Settings", + "name": "Configurações", "data": { - "name": "Your data", - "labelName": "Your Name", - "labelSlug": "Your unique user name", + "name": "Seus dados", + "labelName": "Seu Nome", + "labelSlug": "Seu nome de usuário exclusivo", "namePlaceholder": "Femanon Funny", - "labelCity": "Your City or Region", - "labelBio": "About You", - "success": "Your data was successfully updated!" + "labelCity": "Sua cidade ou região", + "labelBio": "Sobre você", + "success": "Seus dados foram atualizados com sucesso!" }, "email": { "validation": { - "same-email": "This is your current email address" + "same-email": "Este é o seu endereço de e-mail atual" }, - "name": "Your email", - "labelEmail": "Change your email address", - "labelNewEmail": "New email Address", - "labelNonce": "Enter your code", - "success": "A new email address has been registered.", - "submitted": "An email to verify your address has been sent to {email}.", - "change-successful": "Your email address has been changed successfully.", + "name": "Seu email", + "labelEmail": "Alterar o seu endereço de e-mail", + "labelNewEmail": "Novo endereço de e-mail", + "labelNonce": "Digite o seu código", + "success": "Um novo endereço de e-mail foi registrado.", + "submitted": "Um e-mail para verificar o seu endereço foi enviado para {email}.", + "change-successful": "O seu endereço de e-mail foi alterado com sucesso.", "verification-error": { - "message": "Your email could not be changed.", - "explanation": "This can have different causes:", + "message": "O seu e-mail não pode ser alterado.", + "explanation": "Isto pode ter diferentes causas:", "reason": { - "invalid-nonce": "Is the confirmation code invalid?", - "no-email-request": "Are you certain that you requested a change of your email address?" + "invalid-nonce": "O código de confirmação esta inválido?", + "no-email-request": "Você tem certeza de que solicitou uma alteração no seu endereço de e-mail?" }, - "support": "If the problem persists, please contact us by email at" + "support": "Se o problema persistir, por favor contacte-nos por e-mail" } }, "validation": { "slug": { - "regex": "Allowed characters are only lowercase letters, numbers, underscores and hyphens.", - "alreadyTaken": "This user name is already taken." + "regex": "Os caracteres permitidos são apenas letras minúsculas, números, sublinhados e hífens.", + "alreadyTaken": "Este nome de usuário já está registrado." } }, "security": { - "name": "Security", + "name": "Segurança", "change-password": { - "button": "Change password", - "success": "Password successfully changed!", - "label-old-password": "Your old password", - "label-new-password": "Your new password", - "label-new-password-confirm": "Confirm new password", - "message-old-password-required": "Enter your old password", - "message-new-password-required": "Enter a new password", - "message-new-password-confirm-required": "Confirm your new password", - "message-new-password-missmatch": "Type the same password again", - "passwordSecurity": "Password security", - "passwordStrength0": "Very insecure password", - "passwordStrength1": "Insecure password", - "passwordStrength2": "Mediocre password", - "passwordStrength3": "Strong password", - "passwordStrength4": "Very strong password" + "button": "Alterar senha", + "success": "Senha alterada com sucesso!", + "label-old-password": "Sua senha antiga", + "label-new-password": "Sua nova senha", + "label-new-password-confirm": "Confirme sua nova senha", + "message-old-password-required": "Digite sua senha antiga", + "message-new-password-required": "Digite uma nova senha", + "message-new-password-confirm-required": "Confirme sua nova senha", + "message-new-password-missmatch": "Digite a mesma senha novamente", + "passwordSecurity": "Segurança da senha", + "passwordStrength0": "Senha muito insegura", + "passwordStrength1": "Senha insegura", + "passwordStrength2": "Senha medíocre", + "passwordStrength3": "Senha forte", + "passwordStrength4": "Senha muito forte" } }, "invites": { - "name": "Invites" + "name": "Convites" }, "download": { - "name": "Download Data" + "name": "Baixar Dados" }, "deleteUserAccount": { - "name": "Delete data", - "contributionsCount": "Delete my {count} posts", - "commentedCount": "Delete my {count} comments", - "accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.", - "accountWarning": "You CAN'T MANAGE and CAN'T RECOVER your Account, Posts, or Comments after deleting your account!", - "success": "Account successfully deleted!", - "pleaseConfirm": "Destructive action! Type {confirm} to confirm" + "name": "Deletar dados", + "contributionsCount": "Deletar meus {count} posts", + "commentedCount": "Deletar meus {count} comentários", + "accountDescription": "Esteja ciente de que o seus Posts e Comentários são importantes para a nossa comunidade. Se você ainda optar por excluí-los, você tem que marcá-los abaixo.", + "accountWarning": "Você NÃO PODE GERENCIAR e NÃO PODE RECUPERAR sua conta, Posts, ou Comentários após excluir sua conta!", + "success": "Conta eliminada com sucesso!", + "pleaseConfirm": "Ação destrutiva! Digitar {confirm} para confirmar" }, "embeds": { - "name": "Third party providers", - "info-description": "Here is the list of third-party providers whose content can be displayed as third-party code, e.g. in the form of embedded videos.", + "name": "Fornecedores de terceiros", + "info-description": "Aqui está a lista de fornecedores terceiros, cujo conteúdo pode ser exibido como código de terceiros, por exemplo, sob a forma de vídeos incorporados.", "status": { - "description": "As a default for you, embedded code of third-party providers is", + "description": "Como padrão para você, o código incorporado de provedores de terceiros é", "disabled": { - "off": "initially not displayed", - "on": "displayed immediately" + "off": "não exibido inicialmente", + "on": "exibido inicialmente" }, "change": { - "question": "Should embedded source code from third parties always be displayed to you?", - "allow": "Sure", - "deny": "No thanks" + "question": "O código-fonte incorporado de terceiros deve sempre ser exibido para você?", + "allow": "Sim", + "deny": "Não, obrigado" } } }, "organizations": { - "name": "My Organizations" + "name": "Minhas Organizações" }, "languages": { - "name": "Languages" + "name": "Linguagens" }, "social-media": { - "name": "Social media", - "placeholder": "Your social media url", - "requireUnique": "You added this url already", - "submit": "Add link", - "successAdd": "Added social media. Updated user profile!", - "successDelete": "Deleted social media. Updated user profile!" + "name": "Mídias sociais", + "placeholder": "Sua url de mídia social", + "requireUnique": "Você já adicionou esta url", + "submit": "Adicionar link", + "successAdd": "Mídias sociais adicionadas. Perfil de usuário atualizado!", + "successDelete": "Mídias sociais removidas. Perfil de usuário atualizado!" }, "blocked-users": { - "name": "Blocked users", + "name": "Usuários bloqueados", "explanation": { - "intro": "If another user has been blocked by you, this is what happens:", - "your-perspective": "The blocked person's posts will no longer appear in your news feed.", - "their-perspective": "Vice versa: The blocked person will also no longer see your posts in their news feed.", - "search": "Posts of blocked people disappear from your search results.", - "notifications": "Blocked users will no longer receive notifications if they are mentioned in your posts.", - "closing": "This should be sufficient for now so that blocked users can no longer bother you." + "intro": "Se outro usuário foi bloqueado por você, isto é o que acontece:", + "your-perspective": "As mensagens da pessoa bloqueada não aparecerão mais no seu feed de notícias.", + "their-perspective": "Vice versa: A pessoa bloqueada também não verá mais suas mensagens em seu feed de notícias.", + "search": "Posts de pessoas bloqueadas desaparecem dos resultados da sua pesquisa.", + "notifications": "Usuários bloqueados não receberão mais notificações se forem mencionados em suas mensagens.", + "closing": "Isso deve ser suficiente por enquanto para que os usuários bloqueados não possam mais incomodá-lo." }, "columns": { - "name": "Name", + "name": "Nome", "slug": "Slug" }, - "empty": "So far, you have not blocked anybody.", - "how-to": "You can block other users on their profile page via the content menu.", - "block": "Block user", - "unblock": "Unblock user" + "empty": "Até agora, você não bloqueou ninguém.", + "how-to": "Você pode bloquear outros usuários em suas páginas de perfil através do menu de conteúdo.", + "block": "Bloquear usuário", + "unblock": "Desbloquear usuário" } }, "admin": { - "name": "Admin", + "name": "Administração", "dashboard": { - "name": "Dashboard", - "users": "Users", - "posts": "Posts", - "comments": "Comments", - "notifications": "Notifications", - "organizations": "Organizations", - "projects": "Projects", - "invites": "Invites", - "follows": "Follows", - "shouts": "Shouts" + "name": "Painel de controle", + "users": "Usuários", + "posts": "Postagens", + "comments": "Comentários", + "notifications": "Notificações", + "organizations": "Organizações", + "projects": "Projetos", + "invites": "Convites", + "follows": "Segue", + "shouts": "Recomendar" }, "organizations": { - "name": "Organizations" + "name": "Organizações" }, "users": { - "name": "Users", + "name": "Usuários", "form": { - "placeholder": "email, name or description" + "placeholder": "e-mail, nome ou descrição" }, "table": { "columns": { - "number": "No.", - "name": "Name", + "number": "N.º", + "name": "Nome", "email": "E-mail", "slug": "Slug", - "role": "Role", - "createdAt": "Created at" + "role": "Função", + "createdAt": "Criado em" } }, - "empty": "No users found" + "empty": "Nenhum usuário encontrado" }, "pages": { - "name": "Pages" + "name": "Páginas" }, "notifications": { - "name": "Notifications" + "name": "Notificações" }, "categories": { - "name": "Categories", - "categoryName": "Name", + "name": "Categorias", + "categoryName": "Nome", "postCount": "Posts" }, "hashtags": { "name": "Hashtags", - "number": "No.", - "nameOfHashtag": "Name", - "tagCountUnique": "Users", + "number": "Não.", + "nameOfHashtag": "Nome", + "tagCountUnique": "Usuários", "tagCount": "Posts" }, "settings": { - "name": "Settings" + "name": "Configurações" }, "invites": { - "name": "Invite users", - "title": "Invite people", - "description": "Invitations are a wonderful way to have your friends in your network …" + "name": "Convidar usuários", + "title": "Convidar pessoas", + "description": "Convites são uma maneira maravilhosa de ter seus amigos em sua rede …" } }, "post": { - "name": "Post", + "name": "Publicação", "moreInfo": { - "name": "More info", - "title": "More information", - "description": "Here you can find more information about this topic.", - "titleOfCategoriesSection": "Categories", + "name": "Mais informações", + "title": "Mais informações", + "description": "Aqui você pode encontrar mais informações sobre este tópico.", + "titleOfCategoriesSection": "Categorias", "titleOfHashtagsSection": "Hashtags", - "titleOfRelatedContributionsSection": "Related posts" + "titleOfRelatedContributionsSection": "Publicações relacionadas" }, "takeAction": { - "name": "Take action" + "name": "Tomar providências" }, "menu": { - "edit": "Edit Post", - "delete": "Delete Post" + "edit": "Editar publicação", + "delete": "Excluir publicação" }, "comment": { - "submit": "Comment", - "submitted": "Comment Submitted", - "updated": "Changes Saved" + "submit": "Comentário", + "submitted": "Comentário Enviado", + "updated": "Alterações salvas" }, - "edited": "edited" + "edited": "editado" }, "comment": { "content": { - "unavailable-placeholder": "… this comment is not available anymore" + "unavailable-placeholder": "… este comentário não está mais disponível" }, "menu": { - "edit": "Edit Comment", - "delete": "Delete Comment" + "edit": "Editar Comentário", + "delete": "Apagar Comentário" }, "show": { - "more": "show more", - "less": "show less" + "more": "mostrar mais", + "less": "mostrar menos" }, - "edited": "edited" + "edited": "editado" }, "quotes": { "african": { - "quote": "Many small people in many small places do many small things, that can alter the face of the world.", - "author": "African proverb" + "quote": "Muitas pessoas pequenas em muitos lugares pequenos fazem muitas coisas pequenas, que podem alterar a face do mundo.", + "author": "Provérbio africano" } }, "common": { From fea0b60c2d2fc75bed952b68919094d7dae14742 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Mon, 4 Nov 2019 20:55:08 +0100 Subject: [PATCH 017/176] Fix lint errors --- webapp/pages/login.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/pages/login.vue b/webapp/pages/login.vue index b9228cde5..25480a0df 100644 --- a/webapp/pages/login.vue +++ b/webapp/pages/login.vue @@ -25,8 +25,8 @@ export default { } }, methods: { - handleSuccess() { - this.$i18n.set(this.user.locale) + handleSuccess() { + this.$i18n.set(this.user.locale) this.$router.replace(this.$route.query.path || '/') }, }, From 3f7a7913c0fd170bb084128379f10ef0934a04cc Mon Sep 17 00:00:00 2001 From: Stephen Hogsten Date: Wed, 30 Oct 2019 10:53:39 -0700 Subject: [PATCH 018/176] convert email to lowercase before submitting --- webapp/components/PasswordReset/Request.vue | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/webapp/components/PasswordReset/Request.vue b/webapp/components/PasswordReset/Request.vue index bcececcca..6f0176f12 100644 --- a/webapp/components/PasswordReset/Request.vue +++ b/webapp/components/PasswordReset/Request.vue @@ -68,9 +68,12 @@ export default { } }, computed: { - submitMessage() { + lowercaseEmail() { const { email } = this.formData - return this.$t('components.password-reset.request.form.submitted', { email }) + return email.toLowerCase() + }, + submitMessage() { + return this.$t('components.password-reset.request.form.submitted', { email: this.lowercaseEmail }) }, }, methods: { @@ -86,7 +89,7 @@ export default { requestPasswordReset(email: $email) } ` - const { email } = this.formData + const email = this.lowercaseEmail try { await this.$apollo.mutate({ mutation, variables: { email } }) From 1d1517650066cc91ea227085c0827dc74ce04973 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Mon, 4 Nov 2019 22:07:05 +0100 Subject: [PATCH 019/176] Write a test for #2057 --- webapp/components/PasswordReset/Request.spec.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/webapp/components/PasswordReset/Request.spec.js b/webapp/components/PasswordReset/Request.spec.js index 594d6628d..4a6dbde9f 100644 --- a/webapp/components/PasswordReset/Request.spec.js +++ b/webapp/components/PasswordReset/Request.spec.js @@ -84,5 +84,18 @@ describe('Request', () => { }) }) }) + + describe('capital letters in a gmail address', () => { + beforeEach(async () => { + wrapper = Wrapper() + wrapper.find('input#email').setValue('mAiL@gmail.com') + await wrapper.find('form').trigger('submit') + }) + + it('normalizes email to lower case letters', () => { + const expected = expect.objectContaining({ variables: { email: 'mail@gmail.com' } }) + expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected) + }) + }) }) }) From bcf06dff25eec69786a98f5a30aacfc1835c2e21 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Mon, 4 Nov 2019 23:09:49 +0100 Subject: [PATCH 020/176] Implement backend lookup with `normalizeEmail` --- backend/package.json | 1 + backend/src/schema/resolvers/passwordReset.js | 29 +---------------- .../schema/resolvers/passwordReset.spec.js | 5 +-- .../passwordReset/createPasswordReset.js | 31 +++++++++++++++++++ .../passwordReset/createPasswordReset.spec.js | 31 +++++++++++++++++++ backend/yarn.lock | 5 +++ 6 files changed, 70 insertions(+), 32 deletions(-) create mode 100644 backend/src/schema/resolvers/passwordReset/createPasswordReset.js create mode 100644 backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js diff --git a/backend/package.json b/backend/package.json index 622a8313d..78dd26bc0 100644 --- a/backend/package.json +++ b/backend/package.json @@ -101,6 +101,7 @@ "slug": "~1.1.0", "trunc-html": "~1.1.2", "uuid": "~3.3.3", + "validator": "^12.0.0", "wait-on": "~3.3.0", "xregexp": "^4.2.4" }, diff --git a/backend/src/schema/resolvers/passwordReset.js b/backend/src/schema/resolvers/passwordReset.js index 3c5f4636c..e03378ec1 100644 --- a/backend/src/schema/resolvers/passwordReset.js +++ b/backend/src/schema/resolvers/passwordReset.js @@ -1,34 +1,7 @@ import uuid from 'uuid/v4' import bcrypt from 'bcryptjs' +import createPasswordReset from './passwordReset/createPasswordReset' -export async function createPasswordReset(options) { - const { driver, nonce, email, issuedAt = new Date() } = options - const session = driver.session() - let response = {} - try { - const cypher = ` - MATCH (u:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email:$email}) - CREATE(pr:PasswordReset {nonce: $nonce, issuedAt: datetime($issuedAt), usedAt: NULL}) - MERGE (u)-[:REQUESTED]->(pr) - RETURN e, pr, u - ` - const transactionRes = await session.run(cypher, { - issuedAt: issuedAt.toISOString(), - nonce, - email, - }) - const records = transactionRes.records.map(record => { - const { email } = record.get('e').properties - const { nonce } = record.get('pr').properties - const { name } = record.get('u').properties - return { email, nonce, name } - }) - response = records[0] || {} - } finally { - session.close() - } - return response -} export default { Mutation: { diff --git a/backend/src/schema/resolvers/passwordReset.spec.js b/backend/src/schema/resolvers/passwordReset.spec.js index fabee1c7e..03de77493 100644 --- a/backend/src/schema/resolvers/passwordReset.spec.js +++ b/backend/src/schema/resolvers/passwordReset.spec.js @@ -1,7 +1,7 @@ import Factory from '../../seed/factories' import { gql } from '../../jest/helpers' import { neode as getNeode, getDriver } from '../../bootstrap/neo4j' -import { createPasswordReset } from './passwordReset' +import { createPasswordReset } from './passwordReset/createPasswordReset' import createServer from '../../server' import { createTestClient } from 'apollo-server-testing' @@ -109,10 +109,7 @@ describe('passwordReset', () => { describe('resetPassword', () => { const setup = async (options = {}) => { const { email = 'user@example.org', issuedAt = new Date(), nonce = 'abcdef' } = options - - const session = driver.session() await createPasswordReset({ driver, email, issuedAt, nonce }) - session.close() } const mutation = gql` diff --git a/backend/src/schema/resolvers/passwordReset/createPasswordReset.js b/backend/src/schema/resolvers/passwordReset/createPasswordReset.js new file mode 100644 index 000000000..8d575abfc --- /dev/null +++ b/backend/src/schema/resolvers/passwordReset/createPasswordReset.js @@ -0,0 +1,31 @@ +import { normalizeEmail } from 'validator' + +export default async function createPasswordReset(options) { + const { driver, nonce, email, issuedAt = new Date() } = options + const normalizedEmail = normalizeEmail(email) + const session = driver.session() + let response = {} + try { + const cypher = ` + MATCH (u:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email:$email}) + CREATE(pr:PasswordReset {nonce: $nonce, issuedAt: datetime($issuedAt), usedAt: NULL}) + MERGE (u)-[:REQUESTED]->(pr) + RETURN e, pr, u + ` + const transactionRes = await session.run(cypher, { + issuedAt: issuedAt.toISOString(), + nonce, + email: normalizedEmail, + }) + const records = transactionRes.records.map(record => { + const { email } = record.get('e').properties + const { nonce } = record.get('pr').properties + const { name } = record.get('u').properties + return { email, nonce, name } + }) + response = records[0] || {} + } finally { + session.close() + } + return response +} diff --git a/backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js b/backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js new file mode 100644 index 000000000..a5c4d75a5 --- /dev/null +++ b/backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js @@ -0,0 +1,31 @@ +import createPasswordReset from './createPasswordReset' + +describe('createPasswordReset', () => { + const issuedAt = new Date() + const nonce = 'abcdef' + + describe('email lookup', () => { + let driver + let mockSession + beforeEach(() => { + mockSession = { + close() {}, + run: jest.fn().mockReturnValue({ + records: { + map: jest.fn(() => []) + } + }) + } + driver = { session: () => mockSession } + }) + + it('lowercases email address', async () => { + const email = 'stRaNGeCaSiNG@ExAmplE.ORG' + await createPasswordReset({ driver, email, issuedAt, nonce }) + expect(mockSession.run.mock.calls) + .toEqual([[expect.any(String), expect.objectContaining({ + email: 'strangecasing@example.org' + })]]) + }) + }) +}) diff --git a/backend/yarn.lock b/backend/yarn.lock index e6c662229..59254dfc7 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -8418,6 +8418,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validator@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-12.0.0.tgz#fb33221f5320abe2422cda2f517dc3838064e813" + integrity sha512-r5zA1cQBEOgYlesRmSEwc9LkbfNLTtji+vWyaHzRZUxCTHdsX3bd+sdHfs5tGZ2W6ILGGsxWxCNwT/h3IY/3ng== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" From 61a89149892c2c225824b789325363e681dd8a18 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Mon, 4 Nov 2019 23:41:46 +0100 Subject: [PATCH 021/176] Always normalize email in backend --- backend/src/schema/resolvers/emails.js | 9 ++++++--- .../createPasswordReset.js | 0 .../createPasswordReset.spec.js | 18 +++++++++++------- .../resolvers/helpers/existingEmailAddress.js | 7 +++---- backend/src/schema/resolvers/passwordReset.js | 3 +-- .../src/schema/resolvers/passwordReset.spec.js | 2 +- backend/src/schema/resolvers/registration.js | 13 +++++++------ 7 files changed, 29 insertions(+), 23 deletions(-) rename backend/src/schema/resolvers/{passwordReset => helpers}/createPasswordReset.js (100%) rename backend/src/schema/resolvers/{passwordReset => helpers}/createPasswordReset.spec.js (68%) diff --git a/backend/src/schema/resolvers/emails.js b/backend/src/schema/resolvers/emails.js index ce93a28e9..06c0dbd1a 100644 --- a/backend/src/schema/resolvers/emails.js +++ b/backend/src/schema/resolvers/emails.js @@ -3,11 +3,14 @@ import Resolver from './helpers/Resolver' import existingEmailAddress from './helpers/existingEmailAddress' import { UserInputError } from 'apollo-server' import Validator from 'neode/build/Services/Validator.js' +import { normalizeEmail } from 'validator' export default { Mutation: { AddEmailAddress: async (_parent, args, context, _resolveInfo) => { let response + args.email = normalizeEmail(args.email) + try { const { neode } = context await new Validator(neode, neode.model('UnverifiedEmailAddress'), args) @@ -16,13 +19,13 @@ export default { } // check email does not belong to anybody - await existingEmailAddress(_parent, args, context) + await existingEmailAddress({ args, context }) const nonce = generateNonce() const { user: { id: userId }, } = context - const { email } = args + const session = context.driver.session() const writeTxResultPromise = session.writeTransaction(async txc => { const result = await txc.run( @@ -32,7 +35,7 @@ export default { SET email.createdAt = toString(datetime()) RETURN email, user `, - { userId, email, nonce }, + { userId, email: args.email, nonce }, ) return result.records.map(record => ({ name: record.get('user').properties.name, diff --git a/backend/src/schema/resolvers/passwordReset/createPasswordReset.js b/backend/src/schema/resolvers/helpers/createPasswordReset.js similarity index 100% rename from backend/src/schema/resolvers/passwordReset/createPasswordReset.js rename to backend/src/schema/resolvers/helpers/createPasswordReset.js diff --git a/backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js b/backend/src/schema/resolvers/helpers/createPasswordReset.spec.js similarity index 68% rename from backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js rename to backend/src/schema/resolvers/helpers/createPasswordReset.spec.js index a5c4d75a5..a566e225a 100644 --- a/backend/src/schema/resolvers/passwordReset/createPasswordReset.spec.js +++ b/backend/src/schema/resolvers/helpers/createPasswordReset.spec.js @@ -12,9 +12,9 @@ describe('createPasswordReset', () => { close() {}, run: jest.fn().mockReturnValue({ records: { - map: jest.fn(() => []) - } - }) + map: jest.fn(() => []), + }, + }), } driver = { session: () => mockSession } }) @@ -22,10 +22,14 @@ describe('createPasswordReset', () => { it('lowercases email address', async () => { const email = 'stRaNGeCaSiNG@ExAmplE.ORG' await createPasswordReset({ driver, email, issuedAt, nonce }) - expect(mockSession.run.mock.calls) - .toEqual([[expect.any(String), expect.objectContaining({ - email: 'strangecasing@example.org' - })]]) + expect(mockSession.run.mock.calls).toEqual([ + [ + expect.any(String), + expect.objectContaining({ + email: 'strangecasing@example.org', + }), + ], + ]) }) }) }) diff --git a/backend/src/schema/resolvers/helpers/existingEmailAddress.js b/backend/src/schema/resolvers/helpers/existingEmailAddress.js index 007d2de6b..ee1a6af82 100644 --- a/backend/src/schema/resolvers/helpers/existingEmailAddress.js +++ b/backend/src/schema/resolvers/helpers/existingEmailAddress.js @@ -1,7 +1,6 @@ import { UserInputError } from 'apollo-server' -export default async function alreadyExistingMail(_parent, args, context) { - let { email } = args - email = email.toLowerCase() + +export default async function alreadyExistingMail({ args, context }) { const cypher = ` MATCH (email:EmailAddress {email: $email}) OPTIONAL MATCH (email)-[:BELONGS_TO]-(user) @@ -10,7 +9,7 @@ export default async function alreadyExistingMail(_parent, args, context) { let transactionRes const session = context.driver.session() try { - transactionRes = await session.run(cypher, { email }) + transactionRes = await session.run(cypher, { email: args.email }) } finally { session.close() } diff --git a/backend/src/schema/resolvers/passwordReset.js b/backend/src/schema/resolvers/passwordReset.js index e03378ec1..7c0d9e747 100644 --- a/backend/src/schema/resolvers/passwordReset.js +++ b/backend/src/schema/resolvers/passwordReset.js @@ -1,7 +1,6 @@ import uuid from 'uuid/v4' import bcrypt from 'bcryptjs' -import createPasswordReset from './passwordReset/createPasswordReset' - +import createPasswordReset from './helpers/createPasswordReset' export default { Mutation: { diff --git a/backend/src/schema/resolvers/passwordReset.spec.js b/backend/src/schema/resolvers/passwordReset.spec.js index 03de77493..e9f986acd 100644 --- a/backend/src/schema/resolvers/passwordReset.spec.js +++ b/backend/src/schema/resolvers/passwordReset.spec.js @@ -1,7 +1,7 @@ import Factory from '../../seed/factories' import { gql } from '../../jest/helpers' import { neode as getNeode, getDriver } from '../../bootstrap/neo4j' -import { createPasswordReset } from './passwordReset/createPasswordReset' +import { createPasswordReset } from './helpers/createPasswordReset' import createServer from '../../server' import { createTestClient } from 'apollo-server-testing' diff --git a/backend/src/schema/resolvers/registration.js b/backend/src/schema/resolvers/registration.js index bd62b32c3..bdcb6f04f 100644 --- a/backend/src/schema/resolvers/registration.js +++ b/backend/src/schema/resolvers/registration.js @@ -4,6 +4,7 @@ import fileUpload from './fileUpload' import encryptPassword from '../../helpers/encryptPassword' import generateNonce from './helpers/generateNonce' import existingEmailAddress from './helpers/existingEmailAddress' +import { normalizeEmail } from 'validator' const instance = neode() @@ -29,9 +30,9 @@ export default { return response }, Signup: async (_parent, args, context) => { - const nonce = generateNonce() - args.nonce = nonce - let emailAddress = await existingEmailAddress(_parent, args, context) + args.nonce = generateNonce() + args.email = normalizeEmail(args.email) + let emailAddress = await existingEmailAddress({ args, context }) if (emailAddress) return emailAddress try { emailAddress = await instance.create('EmailAddress', args) @@ -42,8 +43,8 @@ export default { }, SignupByInvitation: async (_parent, args, context) => { const { token } = args - const nonce = generateNonce() - args.nonce = nonce + args.nonce = generateNonce() + args.email = normalizeEmail(args.email) let emailAddress = await existingEmailAddress(_parent, args, context) if (emailAddress) return emailAddress try { @@ -78,7 +79,7 @@ export default { args.termsAndConditionsAgreedAt = new Date().toISOString() let { nonce, email } = args - email = email.toLowerCase() + email = normalizeEmail(email) const result = await instance.cypher( ` MATCH(email:EmailAddress {nonce: {nonce}, email: {email}}) From 0cf59743ab57532a9d2e770d5fd93c38d98898a7 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Mon, 4 Nov 2019 23:45:01 +0100 Subject: [PATCH 022/176] refactor: replace 'isemail' with 'validator' ..and use `normalizeEmail` everywhere in the webapp. --- webapp/components/PasswordReset/Request.vue | 12 +- webapp/components/Registration/Signup.vue | 9 +- webapp/package.json | 2 +- webapp/pages/admin/users.vue | 6 +- .../pages/settings/my-email-address/index.vue | 14 +- webapp/yarn.lock | 235 ++---------------- 6 files changed, 47 insertions(+), 231 deletions(-) diff --git a/webapp/components/PasswordReset/Request.vue b/webapp/components/PasswordReset/Request.vue index 6f0176f12..1cf575574 100644 --- a/webapp/components/PasswordReset/Request.vue +++ b/webapp/components/PasswordReset/Request.vue @@ -46,6 +46,7 @@ - From b79770469fd7773d5c9816ab5a4325cd6010ebfa Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Tue, 22 Oct 2019 14:40:10 +0200 Subject: [PATCH 061/176] Update notifications page - display more notifications by simplifying the table - get sorting working --- .../Notification/Notification.spec.js | 0 .../Notification/Notification.vue | 0 .../NotificationList/NotificationList.spec.js | 0 .../NotificationList/NotificationList.vue | 0 .../NotificationMenu/NotificationMenu.spec.js | 0 .../NotificationMenu/NotificationMenu.vue | 20 ++- webapp/graphql/User.js | 4 +- webapp/locales/en.json | 2 +- webapp/pages/notifications/index.vue | 135 +++++++----------- 9 files changed, 71 insertions(+), 90 deletions(-) rename webapp/components/{notifications => }/Notification/Notification.spec.js (100%) rename webapp/components/{notifications => }/Notification/Notification.vue (100%) rename webapp/components/{notifications => }/NotificationList/NotificationList.spec.js (100%) rename webapp/components/{notifications => }/NotificationList/NotificationList.vue (100%) rename webapp/components/{notifications => }/NotificationMenu/NotificationMenu.spec.js (100%) rename webapp/components/{notifications => }/NotificationMenu/NotificationMenu.vue (87%) diff --git a/webapp/components/notifications/Notification/Notification.spec.js b/webapp/components/Notification/Notification.spec.js similarity index 100% rename from webapp/components/notifications/Notification/Notification.spec.js rename to webapp/components/Notification/Notification.spec.js diff --git a/webapp/components/notifications/Notification/Notification.vue b/webapp/components/Notification/Notification.vue similarity index 100% rename from webapp/components/notifications/Notification/Notification.vue rename to webapp/components/Notification/Notification.vue diff --git a/webapp/components/notifications/NotificationList/NotificationList.spec.js b/webapp/components/NotificationList/NotificationList.spec.js similarity index 100% rename from webapp/components/notifications/NotificationList/NotificationList.spec.js rename to webapp/components/NotificationList/NotificationList.spec.js diff --git a/webapp/components/notifications/NotificationList/NotificationList.vue b/webapp/components/NotificationList/NotificationList.vue similarity index 100% rename from webapp/components/notifications/NotificationList/NotificationList.vue rename to webapp/components/NotificationList/NotificationList.vue diff --git a/webapp/components/notifications/NotificationMenu/NotificationMenu.spec.js b/webapp/components/NotificationMenu/NotificationMenu.spec.js similarity index 100% rename from webapp/components/notifications/NotificationMenu/NotificationMenu.spec.js rename to webapp/components/NotificationMenu/NotificationMenu.spec.js diff --git a/webapp/components/notifications/NotificationMenu/NotificationMenu.vue b/webapp/components/NotificationMenu/NotificationMenu.vue similarity index 87% rename from webapp/components/notifications/NotificationMenu/NotificationMenu.vue rename to webapp/components/NotificationMenu/NotificationMenu.vue index 255101139..4ab3dedca 100644 --- a/webapp/components/notifications/NotificationMenu/NotificationMenu.vue +++ b/webapp/components/NotificationMenu/NotificationMenu.vue @@ -13,7 +13,9 @@ - {{ $t('notifications.page') }} + + {{ $t('notifications.page') }} + @@ -35,6 +37,7 @@ export default { return { displayedNotifications: [], notifications: [], + nofiticationRead: null, } }, props: { @@ -75,15 +78,24 @@ export default { } return countUnread }, + updateNotifications() { + return this.notificationRead + }, }, apollo: { notifications: { query() { return notificationQuery(this.$i18n) }, + variables() { + return { + read: false, + orderBy: 'updatedAt_desc', + } + }, pollInterval: NOTIFICATIONS_POLL_INTERVAL, - update(data) { - const newNotifications = data.notifications.filter(newN => { + update({ notifications }) { + const newNotifications = notifications.filter(newN => { return !this.displayedNotifications.find(oldN => this.equalNotification(newN, oldN)) }) this.displayedNotifications = newNotifications @@ -91,7 +103,7 @@ export default { .sort((a, b) => { return new Date(b.createdAt) - new Date(a.createdAt) }) - return data.notifications + return notifications }, error(error) { this.$toast.error(error.message) diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index 54d5889e2..5a4b18b6a 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -51,8 +51,8 @@ export const notificationQuery = i18n => { ${commentFragment(lang)} ${postFragment(lang)} - query { - notifications(orderBy: updatedAt_desc) { + query($read: Boolean, $orderBy: NotificationOrdering) { + notifications(read: $read, orderBy: $orderBy) { read reason createdAt diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 59b8a9390..c978a35a7 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -182,7 +182,7 @@ "createdAt": "Notification created at", "type": "Type", "user": "User", - "action": "Action" + "content": "Content" }, "search": { "placeholder": "Search", diff --git a/webapp/pages/notifications/index.vue b/webapp/pages/notifications/index.vue index fcbebd1c2..118ca0d45 100644 --- a/webapp/pages/notifications/index.vue +++ b/webapp/pages/notifications/index.vue @@ -14,7 +14,7 @@ @click.prevent="toggleMenu()" > - {{ 'All' }} + {{ selected }} - {{ item.route.option }} + {{ item.route.label }} @@ -39,51 +39,12 @@ - - + + @@ -136,23 +98,29 @@ export default { }, data() { return { - notifications: [], - sortingOptions: ['All', 'Read', 'Unread'], + selectedNotifications: [], + selected: 'All', + sortingOptions: [ + { label: 'All', value: null }, + { label: 'Read', value: true }, + { label: 'Unread', value: false }, + ], nofiticationRead: null, } }, computed: { fields() { return { - notifications: null, - // user: this.$t('notifications.user'), - // type: this.$t('notifications.type'), + user: this.$t('notifications.user'), + post: this.$t('notifications.type'), + content: this.$t('notifications.content'), } }, routes() { let routes = this.sortingOptions.map(option => { return { - option, + label: option.label, + value: option.value, } }) return routes @@ -160,24 +128,25 @@ export default { }, methods: { sortNotifications(option, toggleMenu) { - if (option === 'Read') { - this.notificationRead = true - } else if (option === 'Unread') { - this.notificationRead = false - } else { - this.notificationRead = null - } - this.$apollo.queries.notificationsPage.refetch() + this.notificationRead = option.value + this.selected = option.label + this.$apollo.queries.notifications.refresh() toggleMenu() }, }, apollo: { - notificationsPage: { + notifications: { query() { return notificationQuery(this.$i18n) }, + variables() { + return { + read: this.notificationRead, + orderBy: 'updatedAt_desc', + } + }, update({ notifications }) { - this.notifications = notifications + this.selectedNotifications = notifications }, fetchPolicy: 'cache-and-network', error(error) { @@ -191,7 +160,7 @@ export default { .sorting-dropdown { float: right; } -#notifications-table thead { - display: none; +.notifications-table td { + width: 500px; } From cf8124fb2d96c04c44c35f3542d1a6eaac10fe47 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Thu, 24 Oct 2019 09:11:49 +0200 Subject: [PATCH 062/176] Clean up/add german translations --- .../components/Notification/Notification.vue | 68 +++++++++---------- webapp/locales/de.json | 11 ++- webapp/locales/en.json | 11 +-- webapp/pages/notifications/index.vue | 10 +-- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/webapp/components/Notification/Notification.vue b/webapp/components/Notification/Notification.vue index 9649b0d7e..321d1df39 100644 --- a/webapp/components/Notification/Notification.vue +++ b/webapp/components/Notification/Notification.vue @@ -1,39 +1,37 @@ - diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 25ce3742f..534ef819f 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -185,7 +185,8 @@ "all": "Alle", "read": "Lesen ", "unread": "Ungelesen" - } + }, + "empty": "Sorry, du hast im Moment keine Benachrichtigungen." }, "search": { "placeholder": "Suchen", @@ -684,7 +685,7 @@ "terms-of-service": { "title": "Nutzungsbedingungen", "description": "Die folgenden Nutzungsbedingungen sind Basis für die Nutzung unseres Netzwerkes. Beim Registrieren musst Du sie anerkennen und wir werden Dich auch später über ggf. stattfindende Änderungen informieren. Das Human Connection Netzwerk wird in Deutschland betrieben und unterliegt daher deutschem Recht. Gerichtsstand ist Kirchheim / Teck. Zu Details schau in unser Impressum: https://human-connection.org/impressum " - }, + }, "use-and-license" : { "title": "Nutzung und Lizenz", "description": "Sind Inhalte, die Du bei uns einstellst, durch Rechte am geistigen Eigentum geschützt, erteilst Du uns eine nicht-exklusive, übertragbare, unterlizenzierbare und weltweite Lizenz für die Nutzung dieser Inhalte für die Bereitstellung in unserem Netzwerk. Diese Lizenz endet, sobald Du Deine Inhalte oder Deinen ganzen Account löscht. Bedenke, dass andere Deine Inhalte weiter teilen können und wir diese nicht löschen können." @@ -712,6 +713,6 @@ "addition" : { "title": "Zusätzliche machen wir regelmäßig Veranstaltungen, wo Du auch Eindrücke wiedergeben und Fragen stellen kannst. Du findest eine aktuelle Übersicht hier:", "description": " https://human-connection.org/veranstaltungen/ " - } + } } } diff --git a/webapp/locales/en.json b/webapp/locales/en.json index b77922b74..775132eab 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -186,7 +186,8 @@ "all": "All", "read": "Read", "unread": "Unread" - } + }, + "empty": "Sorry, you don't have any notifications at the moment." }, "search": { "placeholder": "Search", @@ -685,7 +686,7 @@ "terms-of-service": { "title": "Terms of Service", "description": "The following terms of use form the basis for the use of our network. When you register, you must accept them and we will inform you later about any changes that may take place. The Human Connection Network is operated in Germany and is therefore subject to German law. Place of jurisdiction is Kirchheim / Teck. For details see our imprint: https://human-connection.org/imprint " - }, + }, "use-and-license" : { "title": "Use and License", "description": "If any content you post to us is protected by intellectual property rights, you grant us a non-exclusive, transferable, sublicensable, worldwide license to use such content for posting to our network. This license expires when you delete your content or your entire account. Remember that others may share your content and we cannot delete it." @@ -713,10 +714,10 @@ "addition" : { "title": "In addition, we regularly hold events where you can also share your impressions and ask questions. You can find a current overview here:", "description": " https://human-connection.org/events/ " - } + } } } - - - + + + diff --git a/webapp/pages/notifications/index.vue b/webapp/pages/notifications/index.vue index 0ed768dfc..2ff6fe2d5 100644 --- a/webapp/pages/notifications/index.vue +++ b/webapp/pages/notifications/index.vue @@ -44,19 +44,35 @@ :fields="fields" class="notifications-table" > + - + @@ -88,7 +106,7 @@ import HcUser from '~/components/User/User' import HcEmpty from '~/components/Empty.vue' import Dropdown from '~/components/Dropdown' -import { notificationQuery } from '~/graphql/User' +import { notificationQuery, markAsReadMutation } from '~/graphql/User' export default { components: { @@ -111,7 +129,14 @@ export default { computed: { fields() { return { - user: this.$t('notifications.user'), + icon: { + label: ' ', + width: '60px', + }, + user: { + label: this.$t('notifications.user'), + width: '350px', + }, post: this.$t('notifications.post'), content: this.$t('notifications.content'), } @@ -133,6 +158,16 @@ export default { this.$apollo.queries.notifications.refresh() toggleMenu() }, + async markNotificationAsRead(notificationSourceId) { + try { + await this.$apollo.mutate({ + mutation: markAsReadMutation(this.$i18n), + variables: { id: notificationSourceId }, + }) + } catch (error) { + this.$toast.error(error.message) + } + }, }, apollo: { notifications: { @@ -160,7 +195,8 @@ export default { .sorting-dropdown { float: right; } -.notifications-table td { - width: 500px; +.notification-status { + opacity: 0.6; /* Real browsers */ + filter: alpha(opacity = 60); /* MSIE */ } From 994a0b049d1803784d9c06383872f1c9e33095a0 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Fri, 25 Oct 2019 13:12:55 +0200 Subject: [PATCH 065/176] Extract AvatarMenu into its own component --- webapp/components/AvatarMenu/AvatarMenu.vue | 162 ++++++++++++++++++++ webapp/layouts/default.vue | 138 +---------------- 2 files changed, 165 insertions(+), 135 deletions(-) create mode 100644 webapp/components/AvatarMenu/AvatarMenu.vue diff --git a/webapp/components/AvatarMenu/AvatarMenu.vue b/webapp/components/AvatarMenu/AvatarMenu.vue new file mode 100644 index 000000000..96d26f210 --- /dev/null +++ b/webapp/components/AvatarMenu/AvatarMenu.vue @@ -0,0 +1,162 @@ + + + diff --git a/webapp/layouts/default.vue b/webapp/layouts/default.vue index 35af4d25f..091bfb7c8 100644 --- a/webapp/layouts/default.vue +++ b/webapp/layouts/default.vue @@ -71,52 +71,7 @@ - - - - + @@ -144,21 +99,19 @@ import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch' import SearchInput from '~/components/SearchInput.vue' import Modal from '~/components/Modal' import NotificationMenu from '~/components/notifications/NotificationMenu/NotificationMenu' -import Dropdown from '~/components/Dropdown' -import HcAvatar from '~/components/Avatar/Avatar.vue' import seo from '~/mixins/seo' import FilterPosts from '~/components/FilterPosts/FilterPosts.vue' import CategoryQuery from '~/graphql/CategoryQuery.js' import PageFooter from '~/components/PageFooter/PageFooter' +import AvatarMenu from '~/components/AvatarMenu/AvatarMenu' export default { components: { - Dropdown, LocaleSwitch, SearchInput, Modal, NotificationMenu, - HcAvatar, + AvatarMenu, FilterPosts, PageFooter, }, @@ -172,49 +125,10 @@ export default { }, computed: { ...mapGetters({ - user: 'auth/user', isLoggedIn: 'auth/isLoggedIn', - isModerator: 'auth/isModerator', - isAdmin: 'auth/isAdmin', quickSearchResults: 'search/quickResults', quickSearchPending: 'search/quickPending', }), - userName() { - const { name } = this.user || {} - return name || this.$t('profile.userAnonym') - }, - routes() { - if (!this.user.slug) { - return [] - } - let routes = [ - { - name: this.$t('profile.name'), - path: `/profile/${this.user.slug}`, - icon: 'user', - }, - { - name: this.$t('settings.name'), - path: `/settings`, - icon: 'cogs', - }, - ] - if (this.isModerator) { - routes.push({ - name: this.$t('moderation.name'), - path: `/moderation`, - icon: 'balance-scale', - }) - } - if (this.isAdmin) { - routes.push({ - name: this.$t('admin.name'), - path: `/admin`, - icon: 'shield', - }) - } - return routes - }, showFilterPostsDropdown() { const [firstRoute] = this.$route.matched return firstRoute && firstRoute.name === 'index' @@ -239,13 +153,6 @@ export default { }) }) }, - matcher(url, route) { - if (url.indexOf('/profile') === 0) { - // do only match own profile - return this.$route.path === url - } - return this.$route.path.indexOf(url) === 0 - }, toggleMobileMenuView() { this.toggleMobileMenu = !this.toggleMobileMenu }, @@ -289,45 +196,6 @@ export default { .main-navigation-right .desktop-view { float: right; } -.avatar-menu { - margin: 2px 0px 0px 5px; -} -.avatar-menu-trigger { - user-select: none; - display: flex; - align-items: center; - padding-left: $space-xx-small; -} -.avatar-menu-popover { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - hr { - color: $color-neutral-90; - background-color: $color-neutral-90; - } - .logout-link { - margin-left: -$space-small; - margin-right: -$space-small; - margin-top: -$space-xxx-small; - margin-bottom: -$space-x-small; - padding: $space-x-small $space-small; - // subtract menu border with from padding - padding-left: $space-small - 2; - color: $text-color-base; - &:hover { - color: $text-color-link-active; - } - } - nav { - margin-left: -$space-small; - margin-right: -$space-small; - margin-top: -$space-xx-small; - margin-bottom: -$space-xx-small; - a { - padding-left: 12px; - } - } -} @media only screen and (min-width: 960px) { .mobile-hamburger-menu { display: none; From d83a42451318cdc1fe85c58dfea0d6b21fa56b77 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Mon, 28 Oct 2019 17:29:01 +0100 Subject: [PATCH 066/176] Add styling - to link in NotificationMenu - make table more mobile responsive - remove unneccessary props Co-authored-by: Alina Beck --- webapp/components/AvatarMenu/AvatarMenu.vue | 5 ++-- .../NotificationMenu/NotificationMenu.vue | 28 ++++++++++--------- webapp/layouts/default.vue | 2 +- webapp/pages/notifications/index.vue | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/webapp/components/AvatarMenu/AvatarMenu.vue b/webapp/components/AvatarMenu/AvatarMenu.vue index 96d26f210..18865f457 100644 --- a/webapp/components/AvatarMenu/AvatarMenu.vue +++ b/webapp/components/AvatarMenu/AvatarMenu.vue @@ -1,5 +1,5 @@ diff --git a/webapp/pages/notifications/index.vue b/webapp/pages/notifications/index.vue index 2ff6fe2d5..95d30df1a 100644 --- a/webapp/pages/notifications/index.vue +++ b/webapp/pages/notifications/index.vue @@ -135,7 +135,7 @@ export default { }, user: { label: this.$t('notifications.user'), - width: '350px', + width: '33.333%', }, post: this.$t('notifications.post'), content: this.$t('notifications.content'), From 4448c12f2e153d2eec04e7734c39992e7b04f408 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Mon, 28 Oct 2019 17:30:28 +0100 Subject: [PATCH 067/176] Add componenet test for AvatarMenu Co-authored-by: mindcodemediator Co-authored-by: Mike Aono --- .../components/AvatarMenu/AvatarMenu.spec.js | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 webapp/components/AvatarMenu/AvatarMenu.spec.js diff --git a/webapp/components/AvatarMenu/AvatarMenu.spec.js b/webapp/components/AvatarMenu/AvatarMenu.spec.js new file mode 100644 index 000000000..17237d37e --- /dev/null +++ b/webapp/components/AvatarMenu/AvatarMenu.spec.js @@ -0,0 +1,148 @@ +import { config, mount, createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import VTooltip from 'v-tooltip' +import Styleguide from '@human-connection/styleguide' +import AvatarMenu from './AvatarMenu.vue' +import Filters from '~/plugins/vue-filters' + +const localVue = createLocalVue() +localVue.use(Styleguide) +localVue.use(Vuex) +localVue.use(Filters) +localVue.use(VTooltip) + +config.stubs['nuxt-link'] = '' +config.stubs['router-link'] = '' + +describe('AvatarMenu.vue', () => { + let propsData, getters, wrapper, mocks + + beforeEach(() => { + propsData = {} + mocks = { + $route: { + path: '', + }, + $router: { + resolve: jest.fn(() => { + return { href: '/profile/u343/matt' } + }), + }, + $t: jest.fn(a => a), + } + getters = { + 'auth/user': () => { + return { id: 'u343', name: 'Matt' } + }, + } + }) + + const Wrapper = () => { + const store = new Vuex.Store({ + getters, + }) + return mount(AvatarMenu, { propsData, localVue, store, mocks }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders the HcAvatar component', () => { + wrapper.find('.avatar-menu-trigger').trigger('click') + expect(wrapper.find('.ds-avatar').exists()).toBe(true) + }) + + describe('given a userName', () => { + it('displays the userName', () => { + expect(wrapper.find('b').text()).toEqual('Matt') + }) + }) + + describe('no userName', () => { + beforeEach(() => { + getters = { + 'auth/user': () => { + return { id: 'u343' } + }, + } + wrapper = Wrapper() + wrapper.find('.avatar-menu-trigger').trigger('click') + }) + + it('displays anonymous user', () => { + expect(wrapper.find('b').text()).toEqual('profile.userAnonym') + }) + }) + + describe('routes', () => { + beforeEach(() => { + getters = { + 'auth/user': () => { + return { id: 'u343', slug: 'matt' } + }, + 'auth/isModerator': () => false, + 'auth/isAdmin': () => false, + } + wrapper = Wrapper() + wrapper.find('.avatar-menu-trigger').trigger('click') + }) + + describe('role user', () => { + it('displays a link to user profile', () => { + const profileLink = wrapper.findAll('.ds-menu-item span').at(0) + expect(profileLink.attributes().to).toEqual('/profile/u343/matt') + }) + + it('displays a link to the notifications page', () => { + const notificationsLink = wrapper.findAll('.ds-menu-item span').at(2) + expect(notificationsLink.attributes().to).toEqual('/notifications') + }) + + it('displays a link to the settings page', () => { + const settingsLink = wrapper.findAll('.ds-menu-item span').at(4) + expect(settingsLink.attributes().to).toEqual('/settings') + }) + }) + + describe('role moderator', () => { + beforeEach(() => { + getters = { + 'auth/user': () => { + return { id: 'u343', slug: 'matt' } + }, + 'auth/isModerator': () => true, + 'auth/isAdmin': () => false, + } + wrapper = Wrapper() + wrapper.find('.avatar-menu-trigger').trigger('click') + }) + + it('displays a link to moderation page', () => { + const moderationLink = wrapper.findAll('.ds-menu-item span').at(6) + expect(moderationLink.attributes().to).toEqual('/moderation') + }) + }) + + describe('role admin', () => { + beforeEach(() => { + getters = { + 'auth/user': () => { + return { id: 'u343', slug: 'matt' } + }, + 'auth/isModerator': () => true, + 'auth/isAdmin': () => true, + } + wrapper = Wrapper() + wrapper.find('.avatar-menu-trigger').trigger('click') + }) + + it('displays a link to admin page', () => { + const adminLink = wrapper.findAll('.ds-menu-item span').at(8) + expect(adminLink.attributes().to).toEqual('/admin') + }) + }) + }) + }) +}) From f34c8f44e0b5fa816fd79a11dfc310c443a7aefe Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Tue, 29 Oct 2019 18:02:49 +0100 Subject: [PATCH 068/176] Update resolver for paginated notifications --- backend/src/schema/resolvers/notifications.js | 9 +++++---- backend/src/schema/types/type/NOTIFIED.gql | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/backend/src/schema/resolvers/notifications.js b/backend/src/schema/resolvers/notifications.js index 4cab1ffc4..8fe45bde3 100644 --- a/backend/src/schema/resolvers/notifications.js +++ b/backend/src/schema/resolvers/notifications.js @@ -18,9 +18,8 @@ export default { notifications: async (_parent, args, context, _resolveInfo) => { const { user: currentUser } = context const session = context.driver.session() - let notifications - let whereClause - let orderByClause + let notifications, whereClause, orderByClause + switch (args.read) { case true: whereClause = 'WHERE notification.read = TRUE' @@ -41,13 +40,15 @@ export default { default: orderByClause = '' } - + const offset = args.offset ? `SKIP ${args.offset}` : '' + const limit = args.first ? `LIMIT ${args.first}` : '' try { const cypher = ` MATCH (resource {deleted: false, disabled: false})-[notification:NOTIFIED]->(user:User {id:$id}) ${whereClause} RETURN resource, notification, user ${orderByClause} + ${offset} ${limit} ` const result = await session.run(cypher, { id: currentUser.id }) notifications = await result.records.map(transformReturnType) diff --git a/backend/src/schema/types/type/NOTIFIED.gql b/backend/src/schema/types/type/NOTIFIED.gql index 5082b5f7f..42da6a39b 100644 --- a/backend/src/schema/types/type/NOTIFIED.gql +++ b/backend/src/schema/types/type/NOTIFIED.gql @@ -23,7 +23,7 @@ enum NotificationReason { } type Query { - notifications(read: Boolean, orderBy: NotificationOrdering): [NOTIFIED] + notifications(read: Boolean, orderBy: NotificationOrdering, first: Int, offset: Int): [NOTIFIED] } type Mutation { From 084388a21ec669607bdb6245963dc011c523e142 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Tue, 29 Oct 2019 18:04:51 +0100 Subject: [PATCH 069/176] Follow new file structure - avoid nested directories --- webapp/components/{ => Empty}/Empty.vue | 0 webapp/layouts/default.vue | 2 +- webapp/pages/admin/notifications.vue | 2 +- webapp/pages/admin/organizations.vue | 2 +- webapp/pages/admin/pages.vue | 2 +- webapp/pages/admin/settings.vue | 2 +- webapp/pages/index.vue | 2 +- webapp/pages/moderation/index.vue | 2 +- webapp/pages/post/_id/_slug/more-info.vue | 2 +- webapp/pages/post/_id/_slug/take-action.vue | 2 +- webapp/pages/profile/_id/_slug.vue | 2 +- webapp/pages/registration/signup.vue | 2 +- webapp/pages/settings/data-download.vue | 2 +- webapp/pages/settings/invites.vue | 2 +- webapp/pages/settings/languages.vue | 2 +- webapp/pages/settings/my-organizations.vue | 2 +- 16 files changed, 15 insertions(+), 15 deletions(-) rename webapp/components/{ => Empty}/Empty.vue (100%) diff --git a/webapp/components/Empty.vue b/webapp/components/Empty/Empty.vue similarity index 100% rename from webapp/components/Empty.vue rename to webapp/components/Empty/Empty.vue diff --git a/webapp/layouts/default.vue b/webapp/layouts/default.vue index 7a95ada76..a39e0a148 100644 --- a/webapp/layouts/default.vue +++ b/webapp/layouts/default.vue @@ -98,7 +98,7 @@ import { mapGetters, mapActions } from 'vuex' import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch' import SearchInput from '~/components/SearchInput.vue' import Modal from '~/components/Modal' -import NotificationMenu from '~/components/notifications/NotificationMenu/NotificationMenu' +import NotificationMenu from '~/components/NotificationMenu/NotificationMenu' import seo from '~/mixins/seo' import FilterPosts from '~/components/FilterPosts/FilterPosts.vue' import CategoryQuery from '~/graphql/CategoryQuery.js' diff --git a/webapp/pages/admin/notifications.vue b/webapp/pages/admin/notifications.vue index 0d348633f..faad87a46 100644 --- a/webapp/pages/admin/notifications.vue +++ b/webapp/pages/admin/notifications.vue @@ -5,7 +5,7 @@ diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index 5a4b18b6a..7b2a012a4 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -51,8 +51,8 @@ export const notificationQuery = i18n => { ${commentFragment(lang)} ${postFragment(lang)} - query($read: Boolean, $orderBy: NotificationOrdering) { - notifications(read: $read, orderBy: $orderBy) { + query($read: Boolean, $orderBy: NotificationOrdering, $first: Int, $offset: Int) { + notifications(read: $read, orderBy: $orderBy, first: $first, offset: $offset) { read reason createdAt diff --git a/webapp/pages/notifications/index.vue b/webapp/pages/notifications/index.vue index 95d30df1a..5d22aa0b4 100644 --- a/webapp/pages/notifications/index.vue +++ b/webapp/pages/notifications/index.vue @@ -5,158 +5,52 @@ {{ $t('notifications.title') }} - - - - {{ selected }} - - - - - {{ item.route.label }} - - - + + + - - - - - - - + + diff --git a/webapp/components/NotificationsTable/NotificationsTable.vue b/webapp/components/NotificationsTable/NotificationsTable.vue new file mode 100644 index 000000000..8366ea5c5 --- /dev/null +++ b/webapp/components/NotificationsTable/NotificationsTable.vue @@ -0,0 +1,105 @@ + + + diff --git a/webapp/pages/notifications/index.vue b/webapp/pages/notifications/index.vue index 5d22aa0b4..9e2346061 100644 --- a/webapp/pages/notifications/index.vue +++ b/webapp/pages/notifications/index.vue @@ -103,8 +103,4 @@ export default { .sorting-dropdown { float: right; } -.notification-status { - opacity: 0.6; /* Real browsers */ - filter: alpha(opacity = 60); /* MSIE */ -} From b916c9fe8308d58b0998993e13bd47008a6c024d Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Wed, 30 Oct 2019 12:26:05 +0100 Subject: [PATCH 072/176] Add portuguese translations Co-authored-by: ppelegrin <56610168+ppelegrin@users.noreply.github.com> --- webapp/locales/pt.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index 0765ff465..8ff168b72 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -182,6 +182,25 @@ "hint": "O que você está pesquisando??", "failed": "Nada foi encontrado" }, + "notifications": { + "reason": { + "mentioned_in_post": "Mencinou você em um post …", + "mentioned_in_comment": "Mentionou você em um comentário …", + "commented_on_post": "Comentou no seu post …" + }, + "comment": "Comentário", + "title": "Notificações", + "pageLink": "Todas as notificações", + "post": "Post", + "user": "Usuário", + "content": "Conteúdo", + "sortingLabel": { + "all": "Todos", + "read": "Lido", + "unread": "Não lido" + }, + "empty": "Desculpe, não tem nenhuma notificação neste momento." + }, "settings": { "name": "Configurações", "data": { From aabaa2e637db5eb815c1476f0ae2ddb94c13368b Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Wed, 30 Oct 2019 13:37:30 +0100 Subject: [PATCH 073/176] Fix typo Co-authored-by: Alina Beck --- webapp/components/Paginate/Paginate.spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/components/Paginate/Paginate.spec.js b/webapp/components/Paginate/Paginate.spec.js index 36e22d1b4..034d33301 100644 --- a/webapp/components/Paginate/Paginate.spec.js +++ b/webapp/components/Paginate/Paginate.spec.js @@ -20,6 +20,7 @@ describe('Paginate.vue', () => { beforeEach(() => { wrapper = Wrapper() }) + describe('next button', () => { beforeEach(() => { propsData.hasNext = true @@ -38,7 +39,7 @@ describe('Paginate.vue', () => { expect(nextButton.attributes().disabled).toBeUndefined() }) - it('emits back when clicked', async () => { + it('emits next when clicked', async () => { await nextButton.trigger('click') expect(wrapper.emitted().next).toHaveLength(1) }) From a1af4f5037f0d5445328385946a4f59d1e73a39f Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Wed, 30 Oct 2019 13:38:17 +0100 Subject: [PATCH 074/176] Add storybook notes Co-authored-by: @alina-beck --- webapp/package.json | 1 + webapp/storybook/addons.js | 1 + webapp/yarn.lock | 140 +++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) diff --git a/webapp/package.json b/webapp/package.json index 4e63bb3d6..649788ac7 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -97,6 +97,7 @@ "@babel/preset-env": "~7.7.1", "@storybook/addon-a11y": "^5.2.5", "@storybook/addon-actions": "^5.2.5", + "@storybook/addon-notes": "^5.2.5", "@storybook/vue": "~5.2.5", "@vue/cli-shared-utils": "~4.0.5", "@vue/eslint-config-prettier": "~5.0.0", diff --git a/webapp/storybook/addons.js b/webapp/storybook/addons.js index 44a5acb23..47c4cbd22 100644 --- a/webapp/storybook/addons.js +++ b/webapp/storybook/addons.js @@ -1,4 +1,5 @@ import '@storybook/addon-actions/register' import '@storybook/addon-a11y/register' import 'storybook-design-token/register' +import '@storybook/addon-notes/register-panel' // import '@storybook/addon-links/register' diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 712696431..ef0decedc 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -2113,6 +2113,25 @@ react-inspector "^3.0.2" uuid "^3.3.2" +"@storybook/addon-notes@^5.2.5": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/addon-notes/-/addon-notes-5.2.6.tgz#bf74ff4f8018e315a4c07c3d5e90cd9154ce6e8e" + integrity sha512-CfWOkoPFI1ZAWQYnwFVqGmeCeXnVQGoFyDSVc3NcIFF1lsk2aagGV+ifJMJuDTXIKu0FClKpvMcENWt+bBpA+w== + dependencies: + "@storybook/addons" "5.2.6" + "@storybook/api" "5.2.6" + "@storybook/client-logger" "5.2.6" + "@storybook/components" "5.2.6" + "@storybook/core-events" "5.2.6" + "@storybook/router" "5.2.6" + "@storybook/theming" "5.2.6" + core-js "^3.0.1" + global "^4.3.2" + markdown-to-jsx "^6.10.3" + memoizerific "^1.11.3" + prop-types "^15.7.2" + util-deprecate "^1.0.2" + "@storybook/addons@5.1.9": version "5.1.9" resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.1.9.tgz#ecf218d08508b97ca5e6e0f1ed361081385bd3ff" @@ -2138,6 +2157,19 @@ global "^4.3.2" util-deprecate "^1.0.2" +"@storybook/addons@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.2.6.tgz#c1278137acb3502e068b0b0d07a8371c607e9c02" + integrity sha512-5MF64lsAhIEMxTbVpYROz5Wez595iwSw45yXyP8gWt12d+EmFO5tdy7cYJCxcMuVhDfaCI78tFqS9orr1atVyA== + dependencies: + "@storybook/api" "5.2.6" + "@storybook/channels" "5.2.6" + "@storybook/client-logger" "5.2.6" + "@storybook/core-events" "5.2.6" + core-js "^3.0.1" + global "^4.3.2" + util-deprecate "^1.0.2" + "@storybook/api@5.1.9": version "5.1.9" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.1.9.tgz#eec5b2f775392ce0803930104c6ce14fa4931e8b" @@ -2184,6 +2216,29 @@ telejson "^3.0.2" util-deprecate "^1.0.2" +"@storybook/api@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-5.2.6.tgz#43d3c20b90e585e6c94b36e29845d39704ae2135" + integrity sha512-X/di44/SAL68mD6RHTX2qdWwhjRW6BgcfPtu0dMd38ErB3AfsfP4BITXs6kFOeSM8kWiaQoyuw0pOBzA8vlYug== + dependencies: + "@storybook/channels" "5.2.6" + "@storybook/client-logger" "5.2.6" + "@storybook/core-events" "5.2.6" + "@storybook/router" "5.2.6" + "@storybook/theming" "5.2.6" + core-js "^3.0.1" + fast-deep-equal "^2.0.1" + global "^4.3.2" + lodash "^4.17.15" + memoizerific "^1.11.3" + prop-types "^15.6.2" + react "^16.8.3" + semver "^6.0.0" + shallow-equal "^1.1.0" + store2 "^2.7.1" + telejson "^3.0.2" + util-deprecate "^1.0.2" + "@storybook/channel-postmessage@5.2.5": version "5.2.5" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.2.5.tgz#47397e543a87ea525cbe93f7d85bd8533edc9127" @@ -2209,6 +2264,13 @@ dependencies: core-js "^3.0.1" +"@storybook/channels@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.2.6.tgz#e2837508864dc4d5b5e03f078886f0ce113762ea" + integrity sha512-/UsktYsXuvb1efjVPCEivhh5ywRhm7hl73pQnpJLJHRqyLMM2I5nGPFELTTNuU9yWy7sP9QL5gRqBBPe1sqjZQ== + dependencies: + core-js "^3.0.1" + "@storybook/client-api@5.2.5": version "5.2.5" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.2.5.tgz#53151a236b6ffc2088acc4535a08e010013e3278" @@ -2244,6 +2306,13 @@ dependencies: core-js "^3.0.1" +"@storybook/client-logger@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.2.6.tgz#cfc4536e9b724b086f7509c2bb34c221016713c9" + integrity sha512-hJvPD267cCwLIRMOISjDH8h9wbwOcXIJip29UlJbU9iMtZtgE+YelmlpmZJvqcDfUiXWWrOh7tP76mj8EAfwIQ== + dependencies: + core-js "^3.0.1" + "@storybook/components@5.1.9": version "5.1.9" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.1.9.tgz#2a5258780fff07172d103287759946dbb4b13e2d" @@ -2293,6 +2362,31 @@ react-textarea-autosize "^7.1.0" simplebar-react "^1.0.0-alpha.6" +"@storybook/components@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.2.6.tgz#cddb60227720aea7cae34fe782d0370bcdbd4005" + integrity sha512-C7OS90bZ1ZvxlWUZ3B2MPFFggqAtUo7X8DqqS3IwsuDUiK9dD/KS0MwPgOuFDnOTW1R5XqmQd/ylt53w3s/U5g== + dependencies: + "@storybook/client-logger" "5.2.6" + "@storybook/theming" "5.2.6" + "@types/react-syntax-highlighter" "10.1.0" + "@types/react-textarea-autosize" "^4.3.3" + core-js "^3.0.1" + global "^4.3.2" + markdown-to-jsx "^6.9.1" + memoizerific "^1.11.3" + polished "^3.3.1" + popper.js "^1.14.7" + prop-types "^15.7.2" + react "^16.8.3" + react-dom "^16.8.3" + react-focus-lock "^1.18.3" + react-helmet-async "^1.0.2" + react-popper-tooltip "^2.8.3" + react-syntax-highlighter "^8.0.1" + react-textarea-autosize "^7.1.0" + simplebar-react "^1.0.0-alpha.6" + "@storybook/core-events@5.1.9": version "5.1.9" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.1.9.tgz#441a6297e2ccfa743e15d1db1f4ac445b91f40d8" @@ -2307,6 +2401,13 @@ dependencies: core-js "^3.0.1" +"@storybook/core-events@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.2.6.tgz#34c9aae256e7e5f4a565b81f1e77dda8bccc6752" + integrity sha512-W8kLJ7tc0aAxs11CPUxUOCReocKL4MYGyjTg8qwk0USLzPUb/FUQWmhcm2ilFz6Nz8dXLcKrXdRVYTmiMsgAeg== + dependencies: + core-js "^3.0.1" + "@storybook/core@5.2.5": version "5.2.5" resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.2.5.tgz#cc04313480a1847aa6881420c675517cc400dc2e" @@ -2416,6 +2517,19 @@ memoizerific "^1.11.3" qs "^6.6.0" +"@storybook/router@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.2.6.tgz#5180d3785501699283c6c3717986c877f84fead5" + integrity sha512-/FZd3fYg5s2QzOqSIP8UMOSnCIFFIlli/jKlOxvm3WpcpxgwQOY4lfHsLO+r9ThCLs2UvVg2R/HqGrOHqDFU7A== + dependencies: + "@reach/router" "^1.2.1" + "@types/reach__router" "^1.2.3" + core-js "^3.0.1" + global "^4.3.2" + lodash "^4.17.15" + memoizerific "^1.11.3" + qs "^6.6.0" + "@storybook/theming@5.1.9": version "5.1.9" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.1.9.tgz#c425f5867fae0db79e01112853b1808332a5f1a2" @@ -2452,6 +2566,24 @@ prop-types "^15.7.2" resolve-from "^5.0.0" +"@storybook/theming@5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.2.6.tgz#e04170b3e53dcfc791b2381c8a39192ae88cd291" + integrity sha512-Xa9R/H8DDgmvxsCHloJUJ2d9ZQl80AeqHrL+c/AKNpx05s9lV74DcinusCf0kz72YGUO/Xt1bAjuOvLnAaS8Gw== + dependencies: + "@emotion/core" "^10.0.14" + "@emotion/styled" "^10.0.14" + "@storybook/client-logger" "5.2.6" + common-tags "^1.8.0" + core-js "^3.0.1" + deep-object-diff "^1.1.0" + emotion-theming "^10.0.14" + global "^4.3.2" + memoizerific "^1.11.3" + polished "^3.3.1" + prop-types "^15.7.2" + resolve-from "^5.0.0" + "@storybook/ui@5.2.5": version "5.2.5" resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.2.5.tgz#0c2c67216e4c808e39cdb48301cafde81b77d074" @@ -10713,6 +10845,14 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-to-jsx@^6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.3.tgz#7f0946684acd321125ff2de7fd258a9b9c7c40b7" + integrity sha512-PSoUyLnW/xoW6RsxZrquSSz5eGEOTwa15H5eqp3enmrp8esmgDJmhzd6zmQ9tgAA9TxJzx1Hmf3incYU/IamoQ== + dependencies: + prop-types "^15.6.2" + unquote "^1.1.0" + markdown-to-jsx@^6.9.1, markdown-to-jsx@^6.9.3: version "6.10.2" resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.2.tgz#644f602b81d088f10aef1c3674874876146cf38b" From 3ae71544d6cd6912bf35ea692e0ff65d0ef251a8 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Wed, 30 Oct 2019 13:39:02 +0100 Subject: [PATCH 075/176] Add story for Empty component Co-authored-by: @alina-beck --- webapp/components/Empty/Empty.story.js | 24 ++++++++++++++++++++++++ webapp/components/Empty/Empty.vue | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 webapp/components/Empty/Empty.story.js diff --git a/webapp/components/Empty/Empty.story.js b/webapp/components/Empty/Empty.story.js new file mode 100644 index 000000000..44d241df7 --- /dev/null +++ b/webapp/components/Empty/Empty.story.js @@ -0,0 +1,24 @@ +import { storiesOf } from '@storybook/vue' +import { withA11y } from '@storybook/addon-a11y' +import HcEmpty from '~/components/Empty/Empty' +import helpers from '~/storybook/helpers' + +helpers.init() + +storiesOf('Empty', module) + .addDecorator(withA11y) + .addDecorator(helpers.layout) + .add( + 'tasks icon with message', + () => ({ + components: { HcEmpty }, + template: '', + }), + { + notes: "Possible icons include 'messages', 'events', 'alert', 'tasks', 'docs', and 'file'", + }, + ) + .add('default icon, no message', () => ({ + components: { HcEmpty }, + template: '', + })) diff --git a/webapp/components/Empty/Empty.vue b/webapp/components/Empty/Empty.vue index 8760a6e6f..ea99702b5 100644 --- a/webapp/components/Empty/Empty.vue +++ b/webapp/components/Empty/Empty.vue @@ -26,7 +26,7 @@ export default { */ icon: { type: String, - required: true, + default: 'alert', validator: value => { return value.match(/(messages|events|alert|tasks|docs|file)/) }, From 542647f4186780595a0d831158f20144526a8727 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Wed, 30 Oct 2019 14:40:02 +0100 Subject: [PATCH 076/176] Add NotificationsDropdownFilter story, refactor - rename incorrectly named varaibles - use filterOptions to remove unneccessary computed routes Co-authored-by: @alina-beck --- .../NotificationsDropdownFilter.story.js | 18 ++++++++++ .../NotificationsDropdownFilter.vue | 33 +++++++------------ webapp/locales/de.json | 2 +- webapp/locales/en.json | 2 +- webapp/locales/pt.json | 2 +- webapp/pages/notifications/index.vue | 6 ++-- 6 files changed, 35 insertions(+), 28 deletions(-) create mode 100644 webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.story.js diff --git a/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.story.js b/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.story.js new file mode 100644 index 000000000..35724fe7e --- /dev/null +++ b/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.story.js @@ -0,0 +1,18 @@ +import { storiesOf } from '@storybook/vue' +import { withA11y } from '@storybook/addon-a11y' +import { action } from '@storybook/addon-actions' +import NotificationsDropdownFilter from '~/components/NotificationsDropdownFilter/NotificationsDropdownFilter' +import helpers from '~/storybook/helpers' + +helpers.init() + +storiesOf('NotificationsDropdownFilter', module) + .addDecorator(withA11y) + .addDecorator(helpers.layout) + .add('filter dropdown', () => ({ + components: { NotificationsDropdownFilter }, + methods: { + filterNotifications: action('filterNotifications'), + }, + template: '', + })) diff --git a/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.vue b/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.vue index b0d1deb7d..7c5e0a42a 100644 --- a/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.vue +++ b/webapp/components/NotificationsDropdownFilter/NotificationsDropdownFilter.vue @@ -1,5 +1,5 @@ From a215093bc3d55f3d0b8b762e70fd64664c89b0f6 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Tue, 12 Nov 2019 13:26:30 +0100 Subject: [PATCH 134/176] Make Donations reactive Co-authored-by: @alina-beck --- backend/src/schema/resolvers/donations.js | 4 ---- backend/src/schema/resolvers/donations.spec.js | 2 ++ webapp/graphql/Donations.js | 1 + webapp/pages/admin/donations.vue | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/src/schema/resolvers/donations.js b/backend/src/schema/resolvers/donations.js index 4057748e0..88149077d 100644 --- a/backend/src/schema/resolvers/donations.js +++ b/backend/src/schema/resolvers/donations.js @@ -1,13 +1,9 @@ -import uuid from 'uuid/v4' - export default { Mutation: { UpdateDonations: async (_parent, params, context, _resolveInfo) => { const { driver } = context const session = driver.session() let donations - params.id = params.id || uuid() - const writeTxResultPromise = session.writeTransaction(async txc => { const updateDonationsTransactionResponse = await txc.run( ` diff --git a/backend/src/schema/resolvers/donations.spec.js b/backend/src/schema/resolvers/donations.spec.js index 9c62a7dda..327688d3a 100644 --- a/backend/src/schema/resolvers/donations.spec.js +++ b/backend/src/schema/resolvers/donations.spec.js @@ -12,6 +12,7 @@ const driver = getDriver() const updateDonationsMutation = gql` mutation($goal: Int, $progress: Int) { UpdateDonations(goal: $goal, progress: $progress) { + id goal progress createdAt @@ -22,6 +23,7 @@ const updateDonationsMutation = gql` const donationsQuery = gql` query { Donations { + id goal progress } diff --git a/webapp/graphql/Donations.js b/webapp/graphql/Donations.js index 41d7cb87e..cc2a6a783 100644 --- a/webapp/graphql/Donations.js +++ b/webapp/graphql/Donations.js @@ -3,6 +3,7 @@ import gql from 'graphql-tag' export const DonationsQuery = () => gql` query { Donations { + id goal progress } diff --git a/webapp/pages/admin/donations.vue b/webapp/pages/admin/donations.vue index 22bd43e81..9ce2eb76f 100644 --- a/webapp/pages/admin/donations.vue +++ b/webapp/pages/admin/donations.vue @@ -49,7 +49,7 @@ export default { query() { return DonationsQuery() }, - result({ data: { Donations } }) { + update({ Donations }) { const { goal, progress } = Donations[0] this.formData = { goal, From e19990a58b3ca87b984db1ef2982834db5072231 Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Tue, 12 Nov 2019 13:43:51 +0100 Subject: [PATCH 135/176] Fix lint --- webapp/pages/index.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/pages/index.spec.js b/webapp/pages/index.spec.js index aeb033cb9..d8587aaf4 100644 --- a/webapp/pages/index.spec.js +++ b/webapp/pages/index.spec.js @@ -54,7 +54,7 @@ describe('PostIndex', () => { 'auth/user': () => { return { id: 'u23' } }, - 'posts/currentPosts': () => [], + 'posts/currentPosts': () => [], }, mutations, }) From 2b2aaa04e1dd1c436ef79bf128ba5f869b2bad8d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2019 13:06:14 +0000 Subject: [PATCH 136/176] build(deps-dev): bump eslint from 5.16.0 to 6.6.0 in /webapp Bumps [eslint](https://github.com/eslint/eslint) from 5.16.0 to 6.6.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v5.16.0...v6.6.0) Signed-off-by: dependabot-preview[bot] --- webapp/package.json | 2 +- webapp/yarn.lock | 150 ++++++++++++++++++++++++++------------------ 2 files changed, 91 insertions(+), 61 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index a75d80095..517d03fb5 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -111,7 +111,7 @@ "babel-preset-vue": "~2.0.2", "core-js": "~2.6.10", "css-loader": "~3.2.0", - "eslint": "~5.16.0", + "eslint": "~6.6.0", "eslint-config-prettier": "~6.5.0", "eslint-config-standard": "~12.0.0", "eslint-loader": "~3.0.2", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 72a6dd55b..3aaccce46 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -3255,6 +3255,11 @@ acorn-jsx@^5.0.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== + acorn-walk@^6.0.1, acorn-walk@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" @@ -3275,6 +3280,11 @@ acorn@^6.2.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== +acorn@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + address@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -3338,17 +3348,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@^6.1.0, ajv@^6.5.5, ajv@^6.9.1: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.10.2: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== @@ -5465,6 +5465,13 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-spinners@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.1.0.tgz#22c34b4d51f573240885b201efda4e4ec9fff3c7" @@ -7168,66 +7175,67 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.3.1, eslint-utils@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" - integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== +eslint-utils@^1.4.2, eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== dependencies: - eslint-visitor-keys "^1.0.0" + eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@~5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== +eslint@~6.6.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.6.0.tgz#4a01a2fb48d32aacef5530ee9c5a78f11a8afd04" + integrity sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" + ajv "^6.10.0" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" - glob "^7.1.2" + glob-parent "^5.0.0" globals "^11.7.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.11" + lodash "^4.17.14" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" - path-is-inside "^1.0.2" progress "^2.0.0" regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" table "^5.2.3" text-table "^0.2.0" + v8-compile-cache "^2.0.3" esm@^3.2.25: version "3.2.25" resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^5.0.0, espree@^5.0.1: +espree@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== @@ -7236,6 +7244,15 @@ espree@^5.0.0, espree@^5.0.1: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" +espree@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== + dependencies: + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" + esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -8121,7 +8138,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== @@ -8981,7 +8998,7 @@ inquirer@6.2.2: strip-ansi "^5.0.0" through "^2.3.6" -inquirer@^6.2.0: +inquirer@^6.2.0, inquirer@^6.2.2: version "6.5.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== @@ -9000,22 +9017,22 @@ inquirer@^6.2.0: strip-ansi "^5.1.0" through "^2.3.6" -inquirer@^6.2.2: - version "6.3.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" - integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== +inquirer@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" + integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== dependencies: - ansi-escapes "^3.2.0" + ansi-escapes "^4.2.1" chalk "^2.4.2" - cli-cursor "^2.1.0" + cli-cursor "^3.1.0" cli-width "^2.0.0" external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.11" - mute-stream "0.0.7" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" run-async "^2.2.0" rxjs "^6.4.0" - string-width "^2.1.0" + string-width "^4.1.0" strip-ansi "^5.1.0" through "^2.3.6" @@ -11088,6 +11105,11 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nan@^2.12.1, nan@^2.13.2: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" @@ -12016,7 +12038,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -13970,6 +13992,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -15154,11 +15184,16 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" -strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + style-loader@^0.23.1, style-loader@~0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" @@ -15300,7 +15335,7 @@ symbol.prototype.description@^1.0.0: dependencies: has-symbols "^1.0.0" -table@5.4.6: +table@5.4.6, table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== @@ -15310,16 +15345,6 @@ table@5.4.6: slice-ansi "^2.1.0" string-width "^3.0.0" -table@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" - integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== - dependencies: - ajv "^6.9.1" - lodash "^4.17.11" - slice-ansi "^2.1.0" - string-width "^3.0.0" - tapable@^1.0.0, tapable@^1.0.0-beta.5, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" @@ -16159,6 +16184,11 @@ v-tooltip@~2.0.2: popper.js "^1.15.0" vue-resize "^0.4.5" +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" From 8b5cd48d3c3e9093f089ae85000e32fbbe6f620a Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Tue, 12 Nov 2019 15:33:21 +0100 Subject: [PATCH 137/176] Translate success message, guard clause for no Donations --- webapp/components/DonationInfo/DonationInfo.vue | 5 +++-- webapp/locales/de.json | 3 ++- webapp/locales/en.json | 3 ++- webapp/locales/pt.json | 6 ++++++ webapp/pages/admin/donations.vue | 3 ++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/webapp/components/DonationInfo/DonationInfo.vue b/webapp/components/DonationInfo/DonationInfo.vue index 947f4bdbc..c7d42252b 100644 --- a/webapp/components/DonationInfo/DonationInfo.vue +++ b/webapp/components/DonationInfo/DonationInfo.vue @@ -17,7 +17,7 @@ export default { }, data() { return { - goal: 0, + goal: 15000, progress: 0, } }, @@ -39,7 +39,8 @@ export default { query() { return DonationsQuery() }, - result({ data: { Donations } }) { + update({ Donations }) { + if (!Donations[0]) return const { goal, progress } = Donations[0] this.goal = goal this.progress = progress diff --git a/webapp/locales/de.json b/webapp/locales/de.json index e70fd025a..a9cf7ce2c 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -384,7 +384,8 @@ "donations": { "name": "Spendeninfo", "goal": "Monatlich benötigte Spenden", - "progress": "Bereits gesammelte Spenden" + "progress": "Bereits gesammelte Spenden", + "successfulUpdate": "Spenden-Info erfolgreich aktualisiert!" } }, "post": { diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 958025370..15ef63a95 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -385,7 +385,8 @@ "donations": { "name": "Donations info", "goal": "Monthly donations needed", - "progress": "Donations collected so far" + "progress": "Donations collected so far", + "successfulUpdate": "Donations info updated successfully!" } }, "post": { diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json index 900b65f67..76560aba9 100644 --- a/webapp/locales/pt.json +++ b/webapp/locales/pt.json @@ -380,6 +380,12 @@ "name": "Convidar usuários", "title": "Convidar pessoas", "description": "Convites são uma maneira maravilhosa de ter seus amigos em sua rede …" + }, + "donations": { + "name": "Informações sobre Doações", + "goal": "Doações mensais necessárias", + "progress": "Doações arrecadadas até o momento", + "successfulUpdate": "Informações sobre doações atualizadas com sucesso!" } }, "post": { diff --git a/webapp/pages/admin/donations.vue b/webapp/pages/admin/donations.vue index 9ce2eb76f..7f0205be5 100644 --- a/webapp/pages/admin/donations.vue +++ b/webapp/pages/admin/donations.vue @@ -39,7 +39,7 @@ export default { }, }) .then(() => { - this.$toast.success('yay!!') + this.$toast.success(this.$t('admin.donations.successfulUpdate')) }) .catch(error => this.$toast.error(error.message)) }, @@ -50,6 +50,7 @@ export default { return DonationsQuery() }, update({ Donations }) { + if (!Donations[0]) return const { goal, progress } = Donations[0] this.formData = { goal, From f8b16b35aa3cf26d6144e0ed087dd83948efd78c Mon Sep 17 00:00:00 2001 From: Alina Beck Date: Tue, 12 Nov 2019 18:12:25 +0300 Subject: [PATCH 138/176] change times to german time --- CONTRIBUTING.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 148b74d8c..0b2e66b9f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,38 +49,40 @@ You can see the core team behind Human Connection [on our website](https://human ## Meetings and Pair Programming Sessions +Times below refer to **German Time** – that's CET (GMT+1) in winter and CEST (GMT+2) in summer – because most Human Connection core team members are living in Germany. + Daily standup -* every Monday–Friday 10:45 UTC +* every Monday–Friday 11:45 * in the discord `Conference Room` * all contributors welcome! * everybody shares what they are working on and asks for help if they are blocked Regular pair programming sessions -* every Monday, Wednesday and Thursday 14:00 UTC +* every Monday, Wednesday and Thursday 15:00 * the link will be posted in the [discord chat](https://discord.gg/6ub73U3) and on the [Agile Ventures website](https://www.agileventures.org/events?utf8=%E2%9C%93&project_id=220&commit=Filter+by+Project) * all contributors welcome! * we team up and work on an issue together (often using Visual Studio live sharing sessions) Open-Source Community Meeting -* every Thursday 12:00 UTC +* every Thursday 13:00 * the link will be posted in the [discord chat](https://discord.gg/6ub73U3) and on the [Agile Ventures website](https://www.agileventures.org/events?utf8=%E2%9C%93&project_id=220&commit=Filter+by+Project) * all contributors welcome! Meet the team -* every Monday 20:00 UTC (at the moment only in German) +* every Monday 21:00 (at the moment only in German) * details here https://human-connection.org/veranstaltungen/ * via this [zoom link](https://zoom.us/j/936943532) * all contributors and users of the network welcome! * users of the network chat with the Human Connection team and discuss current questions and issues Sprint planning -* bi-weekly on Tuesday 12:00 UTC +* bi-weekly on Tuesday 13:00 * via this [zoom link](https://zoom.us/j/7743582385) * all contributors welcome (recommended for those who want to work on an issue in this sprint) * we select and prioritise the issues we will work on in the following two weeks Sprint retrospective -* bi-weekly on Monday 12:00 UTC +* bi-weekly on Monday 13:00 * via this [zoom link](https://zoom.us/j/7743582385) * all contributors welcome (most interesting for those who participated in the sprint) * we review the past sprint and talk about what went well and what we could improve From 63d223e368273156ae9e173b29a54eb4f75605b0 Mon Sep 17 00:00:00 2001 From: Alina Beck Date: Tue, 12 Nov 2019 18:52:38 +0300 Subject: [PATCH 139/176] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Robert Schäfer --- webapp/components/DonationInfo/DonationInfo.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/components/DonationInfo/DonationInfo.vue b/webapp/components/DonationInfo/DonationInfo.vue index c7d42252b..10f42e880 100644 --- a/webapp/components/DonationInfo/DonationInfo.vue +++ b/webapp/components/DonationInfo/DonationInfo.vue @@ -1,7 +1,7 @@