From 5773876cbc29b8d3c8698f6df33be18bcf6974d2 Mon Sep 17 00:00:00 2001 From: Transifex-Openfoodnetwork Date: Fri, 12 Aug 2016 17:26:28 +1000 Subject: [PATCH 01/25] Updating translations for config/locales/fr.yml [skip ci] --- config/locales/fr.yml | 472 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 425 insertions(+), 47 deletions(-) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c4d0939e18..90d9bce3ad 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1,4 +1,9 @@ fr: + activerecord: + attributes: + spree/order: + payment_state: Statut du paiement + shipment_state: Statut livraison devise: failure: invalid: | @@ -10,11 +15,16 @@ fr: not_confirmed: Votre adresse email n'a pas pu être confirmée. Peut-être l'aviez-vous déjà confirmée? confirmation_sent: "Un mail de confirmation a été envoyé!" confirmation_not_sent: "Impossible d'envoyer le mail de confirmation." - home: "OFN" - title: Open Food France + enterprise_mailer: + confirmation_instructions: + subject: "Confirmez l'adresse email pour %{enterprise}" + welcome: + subject: "%{enterprise} est maintenant sur %{sitename}" + title: Open Food Network France welcome_to: 'Bienvenue sur ' - search_by_name: Recherche pas nom ou région... - producers: Producteurs et hubs + site_meta_description: "Tout commence dans le sol. Avec ces paysans, agriculteurs, producteurs, engagés pour une agriculture durable et régénératrice, et désireux de partager leur histoire et leur passion avec fierté. Avec ces distributeurs souhaitant reconnecter les individus à leurs aliments et aux gens qui les produisent, soutenir les prises de conscience, dans une démarche de transparence, d'honnêteté, en assurant une juste rémunération des producteurs. Avec ces acheteurs qui croient que de meilleures décisions d'achats peuvent ..." + search_by_name: Recherche par nom ou département... + producers: 'Producteurs Français' producers_join: Les producteurs et autres hubs basés en France sont invités à rejoindre Open Food France. charges_sales_tax: Soumis à la TVA? print_invoice: "Imprimer la facture" @@ -30,13 +40,140 @@ fr: invoice: "Facture" percentage_of_sales: "%{percentage} des ventes" percentage_of_turnover: "Pourcentage du chiffre d'affaire" - monthly_cap_excl_tax: "Cumul mensuel (sans TVA)" + monthly_cap_excl_tax: "plafond mensuel (sans TVA)" capped_at_cap: "plafonné à %{cap}" per_month: "par mois" free: "gratuit" + free_trial: "Utilisation contre contribution libre" plus_tax: "plus TVA" total_monthly_bill_incl_tax: "Facture mensuelle totale (taxes incluses)" + min_bill_turnover_desc: "Quand le chiffre d'affaire dépasse %{mbt_amount}" + business_model_configuration: "Configuration du modèle économique" + say_no: "Non" + say_yes: "Oui" + then: puis sort_order_cycles_on_shopfront_by: "Trier les cycles de vente par" + admin: + date: Date + email: Email + name: Nom + on_hand: En stock + on_demand: A volonté + on_demand?: A volonté? + order_cycle: Cycle de vente + phone: N° tel + price: Prix + producer: Producteur + product: Produit + quantity: Quantité + shop: Boutique + sku: Référence produit + tags: Tags + variant: Variante + quick_search: Recherche rapide + clear_all: Vider + start_date: "Date de début" + end_date: "Date de fin" + columns: Colonnes + actions: Actions + viewing: "Vous regardez: %{current_view_name}" + whats_this: Qu'est-ce que c'est? + tag_has_rules: "Règles existantes pour ce tag: %{num}" + has_one_rule: "a une règle" + has_n_rules: "a %{num} règles" + customers: + index: + add_customer: "Ajouter un acheteur" + new_customer: "Nouvel acheteur" + customer_placeholder: "acheteur@exemple.org" + valid_email_error: Veuillez entrer un email valide + add_a_new_customer_for: Ajouter un nouvel acheteur pour %{shop_name} + code: Code + duplicate_code: "Ce code est déjà utilisé." + products: + bulk_edit: + unit: Unité + display_as: Affiché + category: Catégorie + tax_category: TVA appliquée + inherits_properties?: Hériter des propriétés producteur? + available_on: Disponible sur + av_on: "Disp. sur" + variant_overrides: + index: + title: Stock + description: Utilisez cette page pour gérer le catalogue de votre entreprise. Les détails produits saisis ici remplaceront ceux de la page "Produit" pour votre entreprise uniquement. + enable_reset?: Autoriser réinitialisation du stock (retour configurations par défaut)? + inherit?: Hériter? + add: Ajouter + hide: Masquer + select_a_shop: Choisir une boutique + review_now: Vérifier maintenant + new_products_alert_message: Il y a %{new_product_count} nouveaux produits disponibles pouvant être ajoutés à votre catalogue. + currently_empty: Votre catalogue est actuellement vide + no_matching_products: Pas de produits correspondants dans votre catalogue + no_hidden_products: Aucun produit masqué dans ce catalogue + no_matching_hidden_products: Aucune produit masqué ne répond à la recherche + no_new_products: Pas de nouveaux produits à ajouter à ce catalogue + no_matching_new_products: Pas de nouveaux produits répondant à la recherche + inventory_powertip: Ceci est votre catalogue produits. Pour ajouter des produits à votre catalogue, sélectionnez "Nouveaux Produits" dans le menu déroulant. + hidden_powertip: Ces produits ont été masqués de votre catalogue, vous ne pourrez pas les proposer dans votre boutique. Vous pouvez cliquer sur "Ajouter" pour ajouter un produit à votre catalogue. + new_powertip: Ces produits peuvent être ajoutés à votre catalogue. Cliquez sur "Ajouter" pour ajouter un produit à votre catalogue, ou 'Masquer" pour ne plus l'afficher. Vous pourrez changer d'avis plus tard! + orders: + bulk_management: + tip: "Utilisez cette page pour changer les quantités d'un produit sur plusieurs commandes. Les produits peuvent aussi être supprimés de toutes les commandes, si nécessaire." + shared: "Ressource partagée?" + order_no: "N° commande" + order_date: "Date commande" + max: "Max" + product_unit: "Produit: Unité" + weight_volume: "Poids/Volume" + ask: "Demander?" + page_title: "Gestion des commandes" + actions_delete: "Supprimer la sélection" + loading: "Commandes en cours de chargement" + no_results: "Aucune commande trouvée." + group_buy_unit_size: "Quantité totale du lot" + total_qtt_ordered: "Quantité totale commandée" + max_qtt_ordered: "Quantité max commandée" + current_fulfilled_units: "Nombre de lots commandés" + max_fulfilled_units: "Nombre max de lots commandés" + order_error: "Des erreurs doivent être résolues avant de pouvoir mettre à jour les commandes.\nLes champs entourés en rouge contiennent des erreurs." + variants_without_unit_value: "ATTENTION: certaines variantes n'ont pas de valeur unitaire" + order_cycles: + edit: + choose_products_from: "Cycle de vente:" + enterprise: + select_outgoing_oc_products_from: Sélectionner les produits sortants pour le cycle de vente parmi + enterprises: + index: + producer?: Producteur? + package: Pack + status: Statut + manage: Gérer + form: + primary_details: + shopfront_requires_login: "Cette boutique exige un login?" + shopfront_requires_login_tip: "Les acheteurs doivent-ils se connecter pour accéder à la boutique?" + shopfront_requires_login_false: "Public" + shopfront_requires_login_true: "Demander aux acheteurs de se connecter" + home: + hubs: + show_closed_shops: "Aficher les boutiques fermées" + hide_closed_shops: "Masquer les boutiques fermées" + show_on_map: "Tout afficher sur la carte" + shared: + register_call: + selling_on_ofn: "Vous souhaitez proposer vos produits sur Open Food France?" + register: "Démarrez ici" + shop: + messages: + login: "login" + register: "s'inscrire" + contact: "contact" + require_customer_login: "La boutique est réservée aux membres." + require_login_html: "Déjà inscrit? %{Connectez-vous}. Sinon, %{inscrivez-vous} pour pouvoir faire vos achats." + require_customer_html: "Veuillez %{contacter} %{l'entreprise} pour devenir membre." invoice_column_item: "Produit" invoice_column_qty: "Qté" invoice_column_tax: "TVA" @@ -66,20 +203,20 @@ fr: address: Adresse address2: Adresse (suite) city: Ville - state: Région + state: Département postcode: Code postal country: Pays unauthorized: Non authorisé terms_of_service: "Conditions d'utilisation" on_demand: A volonté none: Aucun - alert_selling_on_ofn: "Vous souhaitez proposer vos produits sur Open Food France?" - alert_start_here: "Démarrez ici" label_shops: "Boutiques" label_map: "Carte" label_producers: "Producteurs" label_groups: "Groupes" label_about: "A propos" + label_connect: "Se connecter" + label_learn: "Apprendre" label_shopping: "Achats" label_login: "Login" label_logout: "Logout" @@ -87,8 +224,9 @@ fr: label_administration: "Administration" label_admin: "Admin" label_account: "Compte" - label_more: "Afficher" + label_more: "Afficher plus" label_less: "Masquer" + label_notices: "Informations" items: "produits" cart_headline: "Votre panier" total: "Total" @@ -128,10 +266,8 @@ fr: footer_contact_email: "Nous écrire" footer_nav_headline: "Naviguer" footer_join_headline: "Nous rejoindre" - footer_join_producers: "Inscription producteurs" - footer_join_hubs: "Inscription hubs" - footer_join_groups: "Inscription groupes" - footer_join_partners: "Partenaires" + footer_join_body: "Créer une liste, un répertoire de boutiques ou groupes sur Open Food France." + footer_join_cta: "Je veux en savoir plus!" footer_legal_call: "Lire nos" footer_legal_tos: "Termes et conditions" footer_legal_visit: "Nous trouver sur" @@ -145,7 +281,11 @@ fr: brandstory_part4: "Elle fonctionne partout. Elle change tout." brandstory_part5_strong: "Cette plateforme s'appelle Open Food Network." brandstory_part6: "Nous aimons notre nourriture. Maintenant nous pouvons aussi aimer notre système alimentaire." - system_headline: "Comment ça marche?" + learn_body: "Explorer les modèles, les histoires et les ressources disponibles pour vous aider à développer votre propre initiative de commerce/organisation oeuvrant pour un système alimentaire équitable et juste. Trouver des outils pour vous former, des événements et autres opportunités d'apprendre de vos pairs." + learn_cta: "Découvrir " + connect_body: "Rechercher dans le répertoire des producteurs, hubs et groupes pour trouver des commerçants éthiques à côté de chez vous. Inscrivez votre commerce ou organisation sur OFFrance pour que les acheteurs puissent vous trouver. Rejoignez la communauté pour recevoir du soutien et résoudre ensemble les problèmes." + connect_cta: "Explorer" + system_headline: "Faire mes courses - comment ça marche?" system_step1: "1. Recherche" system_step1_text: "Recherchez des produits locaux, de saison, parmi nos multiples boutiques indépendantes. Filtrez par localisation ou catégorie de produits, livraison en point retrait ou à domicile." system_step2: "2. Achat" @@ -188,13 +328,15 @@ fr: order_delivery_on: Livraison prévue order_delivery_address: Adresse de livraison order_special_instructions: "Vos commentaires:" - order_pickup_time: Disponible pour retrait + order_pickup_time: Prêt à être retirer order_pickup_instructions: Instructions de retrait order_produce: Produit order_total_price: Total order_includes_tax: (TVA inclue) order_payment_paypal_successful: Votre paiement via PayPal a été réalisé avec succès. order_hub_info: Hub Info + unsaved_changes_warning: "Des modifications n'ont pas été enregistrées et seront perdues si vous continuez." + unsaved_changes_error: "Les champs entourés en rouge contiennent des erreurs." products: "Produits" products_in: "dans %{oc}" products_at: "à %{distributor}" @@ -247,6 +389,11 @@ fr: email_signup_shop_html: "Vous pouvez maintenant commencer vos achats sur %{link}." email_signup_text: "Merci d'avoir rejoint le réseau. Si vous êtes un client, nous sommes impatients de vous faire découvrir de nombreux agriculteurs fantastiques, de merveilleux hubs de distribution et des plats délicieux! Si vous êtes un producteur ou autre entreprise alimentaire, nous sommes ravis de vous compter parmi les membres du réseau." email_signup_help_html: "Vos questions et suggestions sont les bienvenues; vous pouvez utiliser le bouton Envoyer un commentaire sur le site ou envoyez-nous un email à" + producer_mail_greeting: "Cher(ère)" + producer_mail_text_before: "Nous avons reçu toutes les commandes pour la prochaine livraison." + producer_mail_order_text: "Voilà la liste et les quantités des produits commandés vous concernant:" + producer_mail_delivery_instructions: "Modalités de livraison des produits:" + producer_mail_signoff: "Merci et belle fin de journée!" shopping_oc_closed: La boutique est actuellement fermée shopping_oc_closed_description: "Veuillez attendre l'ouverture du prochain cycle de vente (ou contactez-nous directement pour voir si nous pouvez accépter une commande tardive)" shopping_oc_last_closed: "Le dernier cycle de vente s'est terminé il y a %{distance_of_time}" @@ -258,9 +405,9 @@ fr: shopping_contact_social: "Suivre" shopping_groups_part_of: "fait partie de:" shopping_producers_of_hub: "Les producteurs de %{hub}:" - enterprises_next_closing: "Prochaine commande à passer avant" + enterprises_next_closing: "Clôture des commandes pour ce cycle" enterprises_ready_for: "Prêt pour" - enterprises_choose: "Choisissez votre date de commande:" + enterprises_choose: "Choisissez votre option de livraison/retrait:" hubs_buy: "Acheter:" hubs_shopping_here: "Achats en cours" hubs_orders_closed: "Boutique fermée" @@ -285,6 +432,11 @@ fr: products_cart_empty: "Panier vide" products_edit_cart: "Modifier votre panier" products_from: de + products_change: "Aucun changement à sauvegarder." + products_update_error: "Échec de l'enregistrement dû à:" + products_update_error_msg: "Échec de l'enregistrement." + products_update_error_data: "Échec de l'enregistrement dû à des données non valides." + products_changes_saved: "Modifications enregistrées." search_no_results_html: "Désolé, aucun résultat pour %{query}. Autre recherche?" components_profiles_popover: "Certaines entreprises ont juste créé leur profil sur Open Food France mais ne vendent pas via la plateforme. Elles ont peut-être une boutique physique, ou une boutique en ligne sur une autre plateforme." components_profiles_show: "Afficher aussi les profils" @@ -292,6 +444,7 @@ fr: components_filters_clearfilters: "Vider les filtres" groups_title: Groupes groups_headline: Groupes / réseaux territoriaux + groups_text: "Chaque producteur est unique. Chaque entreprise peut offrir quelque chose de différent. Nos groupes sont des collectifs de producteurs, des plateformes et des distributeurs qui partagent une proximité géographique, un marché fermier ou des valeurs. C'est ce qui rend votre expérience d'achat plus simple. Explorez donc ces groupes sélectionnés." groups_search: "Recherche par nom ou mot-clé" groups_no_groups: "Aucun groupe trouvé" groups_about: "A propos" @@ -332,30 +485,12 @@ fr: modal_how: "Comment ça marche" modal_how_shop: Faire vos courses sur Open Food France modal_how_shop_explained: Recherchez un food hub près de chez vous et commencez vos achats! Vous pouvez afficher plus d'infos sur chaque food hub pour voir le type de produits qu'il propose, et cliquer sur le hub pour commencer vos achats. (Vous ne pouvez faire vos courses que dans un food hub à la fois.) - modal_how_pickup: Frais de retraits, livraison, transport + modal_how_pickup: Frais de retrait, livraison et transport modal_how_pickup_explained: Certains food hubs livrent à domicile, d'autres vous demandent de venir récupérer vos achats dans un point de retrait. Vous pouvez voir quelle options sont proposées sur la page d'accueil du hub, et sélectionner votre choix au moment de la validation de la commande. La livraison à domicile coûtera souvent plus cher, et les prix diffèrent selon le hub. Chaque food hub est un point de vente et gère de façon indépendante ses opérations et sa logistique - attendez-vous donc à des disparités de fonctionnement entre les hubs. modal_how_more: En savoir plus modal_how_more_explained: "Pour en savoir plus sur Open Food France, comment ça marche, et contribuer, allez voir:" modal_producers: "Producteurs" modal_producers_explained: "Nos producteurs font pousser et fabriquent tous les délicieux produits que vous pouvez acheter sur Open Food France." - ocs_choice_hub: "Hub:" - ocs_choice_oc: "Cycle de vente:" - ocs_choice_text: "Vous n'avez pas encore sélectionné votre point de retrait." - ocs_closed_headline: La boutique est actuellement fermée - ocs_closed_time: "Le dernier cycle de vente s'est terminé il y a %{time}." - ocs_closed_contact: "Veuillez contacter le hub en direct pour voir s'il accepte des commandes tardives, ou patientez jusqu'à l'ouverture du prochain cycle de vente." - ocs_closed_opens: "Le prochain cycle de vente commence dans %{time}" - ocs_closed_email: "Email: %{email}" - ocs_closed_phone: "Téléphone: %{phone}" - ocs_pickup_time: "Votre commande sera prête pour %{pickup_time}" - ocs_change_date: "Changer la date de retrait" - ocs_change_date_notice: "(Votre panier sera vidé)" - ocs_close_time: "BOUTIQUE FERMÉE" - ocs_when_headline: Quand voulez-vous commander? - ocs_when_text: Les produits s'afficheront quand vous aurez sélectionné une date. - ocs_when_closing: "Fermera" - ocs_when_choose: "Choisir le cycle de vente" - ocs_list: "Afficher la liste" producers_about: A propos producers_buy: Acheter producers_contact: Contact @@ -364,6 +499,7 @@ fr: producers_buy_at_html: "Acheter les produits de %{enterprise} dans les boutiques suivantes:" producers_filter: Filtrer par producers_filter_type: Catégorie + producers_filter_property: Propriété producers_title: Producteurs producers_headline: Trouvez un producteur local producers_signup_title: S'inscrire en tant que producteur @@ -378,9 +514,24 @@ fr: products_item: Produit products_description: Description products_variant: Variante - products_availabel: En stock? - products_price: Prix + products_quantity: Quantité + products_available: Disponible? + products_producer: "Producteur" + products_price: "Prix" register_title: S'inscrire + sell_title: "S'inscrire" + sell_headline: "Aller sur Open Food France!" + sell_motivation: "Mettez en avant vos beaux aliments." + sell_producers: "Producteurs" + sell_hubs: "Hubs" + sell_groups: "Groupes" + sell_producers_detail: "Créer un profil pour votre entreprise sur OFFrance en quelques minutes. A tout moment vous pourrez créer une boutique en ligne pour vendre vos produits en direct aux acheteurs." + sell_hubs_detail: "Créer un profil pour votre entreprise de distribution ou organisation sur OFFrance. A tout moment vous pourrez créer une boutique multi-fournisseurs." + sell_groups_detail: "Créer un répertoire sur mesure (regroupant différents producteurs et hubs de distribution) pour votre région ou votre organisation." + sell_user_guide: "En savoir plus en explorant le guide utilisateur." + sell_listing_price: "L'inscription sur OFFrance est gratuite. Ouvrir est gérer une boutique sur OFFrance est gratuit. Créer un groupe sur OFFrance pour votre organisation ou réseau régional est gratuit." + sell_embed: "Nous pouvons aussi intégrer votre boutique OFFrance dans votre propre site web ou construire un site web d'alimentation locale sur mesure pour votre région." + sell_ask_services: "Nous consulter sur les services OFFrance." shops_title: Boutiques shops_headline: Des achats qui transforment. shops_text: Les aliments poussent selon des cycles naturels, les fermiers récoltent en cycles. Alors ici, nous achetons aussi en cycles. Si un cycle de vente est terminé, attendez le suivant ou demandez des infos au hub ! @@ -421,10 +572,12 @@ fr: products_oc_is: "Votre cycle de vente pour cette commande est %{name}." products_oc_error: "Veuillez terminer votre commande pour %{link} avant de faire vos courses pour un autre cycle de vente." products_oc_current: "votre cycle de vente actuel" - products_quantity: Quantité products_max_quantity: Quantité max products_distributor: Distributeur products_distributor_info: Quand vous choisissez un distributeur pour votre commande, les adresse et date de retrait seront affichées ici. + shop_trial_length: "Durée de la période de test (jours)" + shop_trial_expires_in: "Votre période de test se termine dans" + shop_trial_expired_notice: "Vous pouvez continuer à utiliser la plateforme en contrepartie d'une contribution libre et volontaire. Merci de nous informer de la façon dont vous souhaitez contribuer :-)" password: Mot de passe remember_me: Se souvenir de moi are_you_sure: "Confirmer?" @@ -478,8 +631,7 @@ fr: who_is_managing_enterprise: "Qui gère %{enterprise}?" enterprise_contact: "Personne référente" enterprise_contact_required: "Vous devez saisir une personne référente" - enterprise_email: "Adresse email" - enterprise_email_required: "Veuillez saisir une adresse email valide." + enterprise_email_address: "Adresse email" enterprise_phone: "Numéro de téléphone" back: "Retour" continue: "Suivant" @@ -554,7 +706,7 @@ fr: registration_type_producer: "Oui, je suis un producteur" registration_type_no_producer: "Non, je ne suis pas un producteur" registration_type_error: "Veuillez faire un choix. Etes vous un producteur?" - registration_type_producer_help: "Un \"producteur\" produit de toutes bonnes choses à manger ou à boire. Vous êtes un producteur si vous les faites pousser, si vous les élevez, si vous les pétrissez, transformez, fermentez, si vous les réduisez en grains, etc." + registration_type_producer_help: "Un producteur fabrique de bonnes choses à boire et à manger. Vous êtes un producteur si vous les faites pousser, les élevez, les pétrissez, transformez, fermentez, les réduisez en grains, etc." registration_type_no_producer_help: "Si vous n'êtes pas un producteur, vous êtes probablement un revendeur ou distributeur alimentaire: un \"hub\", une coopérative, un groupement d'achat, un revendeur, un grossiste, ou autre." create_profile: "Créer votre profil" registration_images_headline: "Merci!" @@ -570,14 +722,14 @@ fr: registration_detail_address1_placeholder: "ex: 123 rue des étangs" registration_detail_address1_error: "Veuillez saisir une adresse" registration_detail_address2: "Adresse ligne 2" - registration_detail_suburb: "Département:" + registration_detail_suburb: "Ville:" registration_detail_suburb_placeholder: "ex: Vendée" - registration_detail_suburb_error: "Veuillez saisir un Département" + registration_detail_suburb_error: "Veuillez saisir une ville" registration_detail_postcode: "Code postal:" registration_detail_postcode_placeholder: "ex: 44000" registration_detail_postcode_error: "Veuillez saisir le code postal" - registration_detail_state: "Région:" - registration_detail_state_error: "Veuillez saisir une Région" + registration_detail_state: "Département:" + registration_detail_state_error: "Veuillez saisir un Département" registration_detail_country: "Pays:" registration_detail_country_error: "Veuillez saisir une Pays" fees: "Frais" @@ -585,7 +737,6 @@ fr: bulk: "Vrac" shop_variant_quantity_min: "min" shop_variant_quantity_max: "max" - contact: "Contact" follow: "Suivre" shop_for_products_html: "Acheter les produits de %{enterprise} dans les boutiques suivantes:" change_shop: "Changer de boutique pour:" @@ -598,4 +749,231 @@ fr: fundraising_fee: "Frais recherche de financement" price_graph: "Légende détail du prix" included_tax: "Inclut TVA" + balance: "Solde" + transaction: "Transaction" + transaction_date: "Date" + payment_state: "Statut du paiement" + shipping_state: "Statut de la livraison" + value: "Montant" + balance_due: "Montant dû" + credit: "Crédit" + Paid: "Payé" + Ready: "Prêt" + you_have_no_orders_yet: "Vous n'avez pas encore de commande" + running_balance: "Solde courant" + outstanding_balance: "Solde restant" + admin_entreprise_relationships: "Liens inter-entreprises" + admin_entreprise_relationships_everything: "Tout" + admin_entreprise_relationships_permits: "autorise" + admin_entreprise_relationships_seach_placeholder: "Chercher" + admin_entreprise_relationships_button_create: "Créer" + admin_entreprise_groups: "Groupes d'entreprises" + admin_entreprise_groups_name: "Nom" + admin_entreprise_groups_owner: "Manager principal" + admin_entreprise_groups_on_front_page: "Sur la page d'accueil?" + admin_entreprise_groups_entreprise: "Entreprises" + admin_entreprise_groups_data_powertip: "L'utilisateur principal en charge de ce groupe." + admin_entreprise_groups_data_powertip_logo: "Il s'agit du logo du groupe" + admin_entreprise_groups_data_powertip_promo_image: "Cette image est affichée en haut du profil Groupe." + admin_entreprise_groups_contact: "Contact" + admin_entreprise_groups_contact_phone_placeholder: "ex: 06 13 24 35 46" + admin_entreprise_groups_contact_address1_placeholder: "ex: 24 rue de la croix verte" + admin_entreprise_groups_contact_city: "Ville" + admin_entreprise_groups_contact_city_placeholder: "ex: Bordeaux" + admin_entreprise_groups_contact_zipcode: "Code postal" + admin_entreprise_groups_contact_zipcode_placeholder: "ex: 14120" + admin_entreprise_groups_contact_state_id: "Département" + admin_entreprise_groups_contact_country_id: "Pays" + admin_entreprise_groups_web: "Liens web" + admin_entreprise_groups_web_twitter: "ex: @OpenFoodNet" + admin_entreprise_groups_web_website_placeholder: "ex: www.monepicerieenligne.fr" + admin_order_cycles: "Gérer les cycles de vente" + open: "Ouvre" + close: "Ferme" + supplier: "Fournisseurs" + coordinator: "Coordinateur" + distributor: "Distributeur" + fee_type: "Type de marge" + tax_category: "TVA applicable" + calculator: "Calculateur" + calculator_values: "Valeurs applicables" + new_order_cycles: "Nouveau cycle de vente" + select_a_coordinator_for_your_order_cycle: "Choisissez un coordinateur pour votre cycle de vente" + edit_order_cycle: "Modifier le cycle de vente" + roles: "Roles" + update: "Mettre à jour" + add_producer_property: "Ajouter une propriété" + admin_settings: "Paramètres" + update_invoice: "Mettre à jour les factures" + finalise_invoice: "Finaliser les factures" + finalise_user_invoices: "Finaliser les factures utilisateurs" + finalise_user_invoice_explained: "Cliquez ici pour finaliser toutes les factures pour le mois calendaire précédent. Cette tâche peut-être définie pour être opérée automatiquement une fois par mois." + manually_run_task: "Tache manuelle" + update_user_invoices: "Mettre à jour les factures utilisateurs" + update_user_invoice_explained: "Cliquez ici pour mettre à jour immédiatement les factures pour le mois en cours pour toutes les entreprises utilisant le système. Cette tache peut être définie pour s'effectuer automatiquement chaque nuit." + auto_finalise_invoices: "Finaliser automatiquement les factures le 2 de chaque mois à 01:30" + auto_update_invoices: "Mettre à jour automatiquement les factures chaque nuit à 01:00" + in_progress: "En cours" + started_at: "Commencé à" + queued: "En attente" + scheduled_for: "Prévu pour" + customers: "Acheteurs" + please_select_hub: "Veuillez sélectionner un Hub" + loading_customers: "Chargement de la liste des acheteurs" + no_customers_found: "Aucun acheteur trouvé" + go: "Lancer" + hub: "Hub" + accounts_administration_distributor: "entreprise d'administration des comptes (facturation des hubs)" + accounts_and_billing: "Compte & Facturation" + producer: "Producteur" + product: "Produit" + price: "Prix" + on_hand: "En stock" + save_changes: "Sauvegarder les modifications" + spree_admin_overview_enterprises_header: "Mes entreprises" + spree_admin_overview_enterprises_footer: "GÉRER MES ENTREPRISES" + spree_admin_enterprises_hubs_name: "Nom" + spree_admin_enterprises_create_new: "CRÉER NOUVELLE" + spree_admin_enterprises_shipping_methods: "Options de livraison" + spree_admin_enterprises_fees: "Marges de l'entreprise" + spree_admin_enterprises_none_create_a_new_enterprise: "CRÉER UNE NOUVELLE ENTREPRISE" + spree_admin_enterprises_none_text: "Vous n'avez pas encore d'entreprise" + spree_admin_enterprises_producers_name: "Nom" + spree_admin_enterprises_producers_total_products: "Total produits " + spree_admin_enterprises_producers_active_products: "Produits actifs" + spree_admin_enterprises_producers_order_cycles: "Produits dans le cycle de vente" + spree_admin_enterprises_tabs_hubs: "HUBS" + spree_admin_enterprises_tabs_producers: "PRODUCTEURS" + spree_admin_enterprises_producers_manage_order_cycles: "GÉRER MES CYCLES DE VENTES" + spree_admin_enterprises_producers_manage_products: "GÉRER LES PRODUITS" + spree_admin_enterprises_producers_orders_cycle_text: "Vous n'avez pas de cycle de vente actif." + spree_admin_enterprises_any_active_products_text: "Vous n'avez aucun produit actif." + spree_admin_enterprises_create_new_product: "CRÉER UN NOUVEAU PRODUIT" + spree_admin_order_cycles: "Cycles de vente" + spree_admin_order_cycles_tip: "Les cycles de vente déterminent quand et où vos produits peuvent être commandés et reçus par les acheteurs." + dashbord: "Tableau de bord" + spree_admin_single_enterprise_alert_mail_confirmation: "Veuillez confirmer l'adresse mail pour" + spree_admin_single_enterprise_alert_mail_sent: "Email envoyé à " + spree_admin_overview_action_required: "Action requise" + spree_admin_overview_check_your_inbox: "Veuillez vérifier votre messagerie et suivre les instructions. Merci!" + change_package: "Changer de pack" + spree_admin_single_enterprise_hint: "Astuce: Pour permettre aux gens de vous trouver, activez votre visibilité " + your_profil_live: "Votre profil en ligne" + on_ofn_map: "sur la carte Open Food France" + see: "Voir" + live: "En ligne" + manage: "Gérer" + resend: "Renvoyer" + add_and_manage_products: "Ajouter & gérer des produits" + add_and_manage_order_cycles: "Ajouter & gérer des cycles de vente" + manage_order_cycles: "Gérer les cycles de vente" + manage_products: "Gérer les produits" + edit_profile_details: "Modifier les informations du profil" + edit_profile_details_etc: "Modifier la description, les images, etc." + order_cycle: "Cycle de vente" remove_tax: "Retirer TVA" + tax_settings: "Paramètres TVA" + products_require_tax_category: "vous devez choisir la TVA applicable" + admin_shared_address_1: "Adresse" + admin_shared_address_2: "Adresse (cont.)" + admin_share_city: "Ville" + admin_share_zipcode: "Code postal" + admin_share_country: "Pays" + admin_share_state: "Département" + hub_sidebar_hubs: "Hubs" + hub_sidebar_none_available: "Aucun disponible" + hub_sidebar_manage: "Gérer" + hub_sidebar_at_least: "Sélectionnez un/des hubs" + hub_sidebar_blue: "bleu" + hub_sidebar_red: "rouge" + shop_trial_in_progress: "Votre période de test se termine dans %{days}." + shop_trial_expired: "Bonne nouvelle! Nous avons décidé d'étendre la période de test pour votre hub, nous vous informerons avant la fin de la période." + report_customers_distributor: "Distributeur" + report_customers_supplier: "Fournisseurs" + report_customers_cycle: "Cycle de vente" + report_customers_type: "Type de rapport" + report_customers_csv: "Télécharger en csv" + report_producers: "Producteurs:" + report_type: "Type de rapport: " + report_hubs: "Hubs:" + report_payment: "Méthodes de paiement:" + report_distributor: "Distributeurs:" + report_payment_by: 'Paiements par type' + report_itemised_payment: 'Détail du paiement' + report_payment_totals: 'Total des paiements' + report_all: 'tous' + report_order_cycle: "Cycle de vente:" + report_entreprises: "Entreprises:" + report_users: "Managers:" + initial_invoice_number: "N° de facture initial:" + invoice_date: "Date de facture:" + due_date: "Date d'échéance:" + account_code: "Code compte:" + equals: "Egal" + contains: "contients" + discount: "Réduction" + filter_products: "Filtrer les produits" + delete_product_variant: "La variante ne peut pas être supprimée!" + progress: "en cours" + saving: "Enregistrement..." + success: "succès" + failure: "échec" + unsaved_changes_confirmation: "Les changements non sauvegardés seront perdus. Continuer?" + one_product_unsaved: "Des changements sur un produit n'ont pas été sauvegardés." + products_unsaved: "Des changements sur %{n} produits n'ont pas été sauvegardés." + is_already_manager: "est déjà manager!" + no_change_to_save: "Pas de changement à sauvegarder" + add_manager: "Ajouter un manager" + users: "Managers" + about: "A propos" + images: "Images" + web: "Web" + primary_details: "Informations de base" + adrdress: "Adresse" + contact: "Contact" + social: "Réseaux sociaux" + business_details: "N° fiscaux" + properties: "Propriétés" + shipping_methods: "Méthodes de livraison" + payment_methods: "Méthodes de paiement" + payment_method_fee: "Frais de transaction" + enterprise_fees: "Marges de l'entreprise" + inventory_settings: "Paramètres de stock" + tag_rules: "Règles des tags" + shop_preferences: "Préférences boutique" + validation_msg_relationship_already_established: "^Un lien est déjà établi entre ces entreprises." + validation_msg_at_least_one_hub: "^Sélectionnez au moins un hub" + validation_msg_product_category_cant_be_blank: "^Veuillez sélectionner la catégorie produit" + validation_msg_tax_category_cant_be_blank: "^Veuillez sélectionner la TVA applicable" + validation_msg_is_associated_with_an_exising_customer: "est associé à un acheteur existant" + spree: + shipment_states: + backorder: réapprovisionnement + partial: partiel + pending: en attente + ready: prêt + shipped: envoyé + payment_states: + balance_due: solde dû + completed: effectué + checkout: Paiement + credit_owed: Crédit acheteur + failed: échec + paid: payé + pending: en attente + processing: en traitement + void: annuler + invalid: Invalide + order_state: + address: adresse + adjustments: ajustements + awaiting_return: attente du retour + canceled: annulé + cart: panier + complete: terminer + confirm: confirmer + delivery: livraison + payment: paiement + resumed: recommencé + returned: retourné + skrill: cash From 53e8056450d48341aa1b444b5a6feabfd257e2a6 Mon Sep 17 00:00:00 2001 From: Transifex-Openfoodnetwork Date: Fri, 12 Aug 2016 18:56:13 +1000 Subject: [PATCH 02/25] Updating translations for config/locales/fr.yml [skip ci] --- config/locales/fr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 90d9bce3ad..994bd45c07 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -529,7 +529,7 @@ fr: sell_hubs_detail: "Créer un profil pour votre entreprise de distribution ou organisation sur OFFrance. A tout moment vous pourrez créer une boutique multi-fournisseurs." sell_groups_detail: "Créer un répertoire sur mesure (regroupant différents producteurs et hubs de distribution) pour votre région ou votre organisation." sell_user_guide: "En savoir plus en explorant le guide utilisateur." - sell_listing_price: "L'inscription sur OFFrance est gratuite. Ouvrir est gérer une boutique sur OFFrance est gratuit. Créer un groupe sur OFFrance pour votre organisation ou réseau régional est gratuit." + sell_listing_price: "L'inscription sur OFFrance est gratuite. Ouvrir est gérer une boutique sur OFFrance ou créer un groupe sur OFFrance pour votre organisation ou réseau régional, n'est pas gratuit, mais le prix est libre: soit 2% du chiffre d'affaire (ou autre forme de contribution libre designée par votre hub), soit une contribution \"en compétences\" à Open Food France (développement de fonctionnalités, recherche de financement, support utilisateur, etc.), soit un mix des deux." sell_embed: "Nous pouvons aussi intégrer votre boutique OFFrance dans votre propre site web ou construire un site web d'alimentation locale sur mesure pour votre région." sell_ask_services: "Nous consulter sur les services OFFrance." shops_title: Boutiques From 1de2300099bf2f2a0631ca96c82b7ec2c1baa4f5 Mon Sep 17 00:00:00 2001 From: Transifex-Openfoodnetwork Date: Fri, 12 Aug 2016 19:07:43 +1000 Subject: [PATCH 03/25] Updating translations for config/locales/nb.yml [skip ci] --- config/locales/nb.yml | 164 +++++++++--------------------------------- 1 file changed, 33 insertions(+), 131 deletions(-) diff --git a/config/locales/nb.yml b/config/locales/nb.yml index b42643b74e..0b34b36824 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -1,25 +1,8 @@ -# English language file -# --------------------- -# -# This is the source language file maintained by the Australian OFN team. -# Visit Transifex to translate this file into other languages: -# -# https://www.transifex.com/open-food-foundation/open-food-network/ -# -# If you translate this file in a text editor, please share your results with us by -# -# - uploading the file to Transifex or -# - opening a pull request at GitHub. -# -# -# See http://community.openfoodnetwork.org/t/localisation-ofn-in-your-language/397 - nb: activerecord: - # Overridden here due to a bug in spree i18n (Issue #870) attributes: spree/order: - payment_state: Betalingsstatus + payment_state: Betallingsstatus shipment_state: Sendingsstatus devise: failure: @@ -37,13 +20,12 @@ nb: subject: "Vennligst bekreft e-postadressen til %{enterprise}" welcome: subject: "%{enterprise} er nå på %{sitename}" - home: "OFN" title: Open Food Network welcome_to: 'Velkommen til ' site_meta_description: "Vi begynner fra grunnen. Med bønder og dyrkere klare til å fortelle sine historier, stolt og virkelig. Med distributører klare til å koble mennesker med produkter på en rettferdig og ærlig måte. Med kunder som tror på at ukentlige innkjøpsrutiner kan..." search_by_name: Søk på navn eller sted... producers: 'Norske Produsenter' - producers_join: Norske produsenter er nå velkommen til å bli med i Open Food Network. #FIXME + producers_join: Norske produsenter er nå velkommen til å bli med i Open Food Network. charges_sales_tax: MVA-pliktig? print_invoice: "Skriv ut Faktura" send_invoice: "Send Faktura" @@ -70,12 +52,8 @@ nb: say_no: "Nei" say_yes: "Ja" then: vil - sort_order_cycles_on_shopfront_by: "Sorter Bestillingsrunder i Butikkvindu etter" - - admin: - # Common properties / models date: Dato email: Epost name: Navn @@ -92,23 +70,17 @@ nb: sku: SKU tags: Merker variant: Variant - - # General form elements quick_search: Hurtigsøk clear_all: Fjern Alt start_date: "Startdato" end_date: "Sluttdato" - columns: Kolonner actions: Handlinger viewing: "Viser: %{current_view_name}" - whats_this: Hva er dette? - tag_has_rules: "Gjeldende regler for denne merkelappen: %{num}" has_one_rule: "har én regel" has_n_rules: "har %{num} regler" - customers: index: add_customer: "Legge til kunde" @@ -118,7 +90,6 @@ nb: add_a_new_customer_for: Legge til en ny kunde for %{shop_name} code: kode duplicate_code: "Denne koden er allerede brukt." - products: bulk_edit: unit: Enhet @@ -128,7 +99,6 @@ nb: inherits_properties?: Arver Egenskaper? available_on: Tilgjengelig på av_on: "Til. på" - variant_overrides: index: title: Varelager @@ -149,7 +119,6 @@ nb: inventory_powertip: Dette er ditt varelager. For å legge til lageret, velg 'Nye Produkter' fra Visningslisten. hidden_powertip: Disse produktene har blitt skjult fra ditt varelager og vil ikke være tilgjengelig for å legge til din butikk. Du kan klikke "Legg til" for å legge et produkt til ditt varelager. new_powertip: Disse produktene er tilgjengelige for å bli lagt til ditt varelager. Klikk "Legg til" for å legge et produkt til lageret ditt, eller "Skjul" for å skjule det fra visning. Du kan alltids ombestemme deg senere! - orders: bulk_management: tip: "Bruk denne siden for å endre produktantall på tvers av flere bestillinger. Produkter kan også fjernes fra bestillinger helt, hvis påkrevd." @@ -160,7 +129,7 @@ nb: product_unit: "Produkt: Enhet" weight_volume: "Vekt/Volum" ask: "Spør?" - page_title: "Bulk Order Management" + page_title: "Bulk ordrehåndtering" actions_delete: "Slett Valgte" loading: "Laster bestillinger" no_results: "Fant ingen bestillinger." @@ -171,14 +140,11 @@ nb: max_fulfilled_units: "Max Oppfylte Enheter" order_error: "Noen feil må løses før du kan oppdatere bestillinger.\nAlle felt med røde kanter inneholder feil." variants_without_unit_value: "ADVARSEL: Noen varianter mangler enhetsverdi" - order_cycles: edit: choose_products_from: "Velg Produkter Fra:" - enterprise: select_outgoing_oc_products_from: Velg utgående bestillingsrundeprodukter fra - enterprises: index: producer?: Produsent? @@ -191,7 +157,6 @@ nb: shopfront_requires_login_tip: "Velg om kunder må logge inn for å se butikken eller ikke." shopfront_requires_login_false: "Offentlig" shopfront_requires_login_true: "Krev at kunder logger inn" - home: hubs: show_closed_shops: "Vis stengte butikker" @@ -209,19 +174,16 @@ nb: require_customer_login: "Denne butikken er kun for kunder." require_login_html: "Vennligst %{login} hvis du allerede har en konto. Hvis ikke, %{register} for å bli kunde." require_customer_html: "Vennligst %{contact} %{enterprise} for å bli kunde." - - # Printable Invoice Columns invoice_column_item: "Vare" invoice_column_qty: "Mengde" invoice_column_tax: "MVA" invoice_column_price: "Pris" - - logo: "Logo (640x130)" #FIXME - logo_mobile: "Mobil logo (75x26)" #FIXME - logo_mobile_svg: "Mobil logo (SVG)" #FIXME + logo: "Logo (640x130)" + logo_mobile: "Mobil logo (75x26)" + logo_mobile_svg: "Mobil logo (SVG)" home_hero: "Heltebilde" home_show_stats: "Vis statistikk" - footer_logo: "Logo (220x76)" #FIXME + footer_logo: "Logo (220x76)" footer_facebook_url: "Facebook URL" footer_twitter_url: "Twitter URL" footer_instagram_url: "Instagram URL" @@ -232,7 +194,6 @@ nb: footer_links_md: "Linker" footer_about_url: "Om URL" footer_tos_url: "Vilkår URL" - name: Navn first_name: Fornavn last_name: Etternavn @@ -249,12 +210,13 @@ nb: terms_of_service: "Vilkår" on_demand: Ved forespørsel none: Ingen - label_shops: "Butikker" label_map: "Kart" label_producers: "Produsenter" label_groups: "Grupper" label_about: "Om" + label_connect: "Koble til" + label_learn: "Lære" label_shopping: "Handle" label_login: "Logg inn" label_logout: "Logg ut" @@ -265,7 +227,6 @@ nb: label_more: "Vis mer" label_less: "Vis mindre" label_notices: "Meldinger" - items: "varer" cart_headline: "Din handlekurv" total: "Sum" @@ -273,11 +234,9 @@ nb: cart_updating: "Oppdaterer handlekurv..." cart_empty: "Handlekurven er tom" cart_edit: "Rediger handlekurv" - card_number: Kortnummer card_securitycode: "Sikkerhetskode" card_expiry_date: Utløpsdato - ofn_cart_headline: "Gjeldende handlekurv for:" ofn_cart_distributor: "Distributør:" ofn_cart_oc: "Bestillingsrunde:" @@ -286,45 +245,34 @@ nb: ofn_cart_product: "Produkt:" ofn_cart_quantitiy: "Antall:" ofn_cart_send: "Kjøp" - ie_warning_headline: "Din nettleser er for gammel :-(" ie_warning_text: "For den beste opplevelsen med Open Food Network anbefaler vi på det sterkeste å oppgradere nettleseren din:" ie_warning_chrome: Last ned Chrome ie_warning_firefox: Last ned Firefox ie_warning_ie: Oppgrader Internet Explorer ie_warning_other: "Kan ikke oppgradere nettleseren din? Prøv Open Food Network på smart-telefonen din :-)" - footer_global_headline: "OFN Globalt" footer_global_home: "Hjem" footer_global_news: "Nyheter" footer_global_about: "Om" footer_global_contact: "Kontakt" - footer_sites_headline: "OFN nettsteder" footer_sites_developer: "Utvikler" footer_sites_community: "Forum" footer_sites_userguide: "Brukerhåndbok" - footer_secure: "Sikker og klarert." footer_secure_text: "Open Food Network bruker SSL-kryptering (2048 bit RSA) overalt for å holde handlingen og betalingen din privat. Våre servere lagrer ikke kortopplysninger og betalinger behandles av PCI-kompatible tjenester." - footer_contact_headline: "Hold kontakten" footer_contact_email: "Send oss en epost" - footer_nav_headline: "Naviger" footer_join_headline: "Bli med" - footer_join_producers: "Bli med som Produsent" - footer_join_hubs: "Bli med som Hub" - footer_join_groups: "Bli med som Gruppe" - footer_join_partners: "Samarbeidspartnere" - + footer_join_body: "Opprette en profil, butikk eller gruppe på Open Food Network." + footer_join_cta: "Fortell meg mer!" footer_legal_call: "Les våre" footer_legal_tos: "Vilkår og betingelser" footer_legal_visit: "Finn oss på" footer_legal_text_html: "Open Food Network er en plattform med fri og åpen kildekode. Vårt innhold er lisensiert med %{content_license} og vår kode med %{code_license}." - home_shop: Handle nå - brandstory_headline: "Food, unincorporated." brandstory_intro: "Noen ganger er det best å fikse systemet ved å starte et nytt..." brandstory_part1: "Vi begynner fra grunnen. Med bønder og dyrkere klare til å fortelle sine historier, stolt og virkelig. Med distributører klare til å koble mennesker med produkter på en rettferdig og ærlig måte. Med kjøpere som tror på at ukentlige innkjøpsrutiner kan bidra til å forandre verden." @@ -333,24 +281,24 @@ nb: brandstory_part4: "Det fungerer overalt. Det forandrer alt." brandstory_part5_strong: "Vi kaller det Open Food Network." brandstory_part6: "Alle er vi glad i mat. Nå kan vi elske vårt matsystem også." - - system_headline: "Slik fungerer det." + learn_body: "See på modeller, historier og ressurser for å støtte deg å utvikle en god mat bedrift eller organisasjon. Finne opplæring, arrangement og andre muligheter til å lære fra andre." + learn_cta: "Bli Inspirert" + connect_body: "Søk i vår katalog av produsenter, hubs og grupper for å finne god mat nær deg. Vise din bedrift eller organisasjon på OFN slik at kjøpere kan finne deg. Bli med i fellesskapet for å få råd og løse problemer sammen." + connect_cta: "Utforske" + system_headline: "Shopping - slik virker det." system_step1: "1. Søk" system_step1_text: "Søk blant våre mangfoldige, uavhengige butikker for lokal mat i sesong. Søk i nabolag og matkategori, eller om du foretrekker levering eller å hente selv." system_step2: "2. Handle" system_step2_text: "Endre dine kjøpevaner med rimelig lokal mat fra mangfoldige produsenter og hubs. Oppdag historiene bak maten din og de som lager den!" system_step3: "3. Hent / Få det levert" system_step3_text: "Vent på din levering, eller besøk produsenten eller hub'en for en mer personlig kobling til maten din. Mathandling så mangfoldig slik det var ment fra naturens side." - cta_headline: "Handling som gjør verden til et bedre sted." cta_label: "Jeg er klar" - stats_headline: "Vi skaper et nytt matsystem." stats_producers: "matprodusenter" stats_shops: "matbutikker" stats_shoppers: "matkunder" stats_orders: "matbestillinger" - checkout_title: Kasse checkout_now: Gå til kassen checkout_order_ready: Bestilling klar for @@ -372,7 +320,6 @@ nb: checkout_shipping_price: Levering checkout_total_price: Sum checkout_back_to_cart: "Tilbake til Handlekurv" - order_paid: BETALT order_not_paid: IKKE BETALT order_total: Sum bestilling @@ -388,15 +335,12 @@ nb: order_includes_tax: (inkludert MVA) order_payment_paypal_successful: Din betaling via PayPal har blitt godkjent. order_hub_info: Hub info - unsaved_changes_warning: "Ulagrede endringer finnes og vil gå tapt hvis du fortsetter." unsaved_changes_error: "Felt med røde kanter inneholder feil." - products: "Produkter" products_in: "i %{oc}" products_at: "hos %{distributor}" products_elsewhere: "Produkter funnet andre steder" - email_welcome: "Velkommen" email_confirmed: "Takk for at du bekrefter din epostadresse" email_registered: "er nå en del av" @@ -414,7 +358,6 @@ nb: email_contact: "Send oss en epost:" email_signoff: "Mvh," email_signature: "%{sitename} Team" - email_confirm_customer_greeting: "Hei %{name}," email_confirm_customer_intro_html: "Takk for at du handler hos %{distributor}!" email_confirm_customer_number_html: "Ordrebekreftelse #%{number}" @@ -439,7 +382,6 @@ nb: email_shipping_collection_time: "Klar for henting:" email_shipping_collection_instructions: "Henteinstruksjoner:" email_special_instructions: "Dine kommentarer:" - email_signup_greeting: Hei! email_signup_welcome: "Velkommen til %{sitename}!" email_signup_login: Din innlogging @@ -447,14 +389,11 @@ nb: email_signup_shop_html: "Du kan begynne å handle på nett nå på %{link}." email_signup_text: "Takk for at du ble med i nettverket. Hvis du er kunde ser vi frem til å vise deg mange fantastiske bønder, flotte mathubs og deilig mat! Hvis du er produsent eller selskap er vi glade for å ha deg som en del av nettverket." email_signup_help_html: "Vi tar i mot alle dine spørsmål og tilbakemeldinger; du kan bruke Send tilbakemelding-knappen på nettsiden eller sende oss en epost på" - producer_mail_greeting: "Kjære" producer_mail_text_before: "Alle dine kunderbestillinger er klar." producer_mail_order_text: "Her er en oppsummering av bestillingene:" producer_mail_delivery_instructions: "Henting / leveringsdetaljer :" - producer_mail_text_after: "" producer_mail_signoff: "Med vennlig hilsen" - shopping_oc_closed: Stengt for bestilling shopping_oc_closed_description: "Vent til neste runde åpner (eller kontakt oss direkte for å se om vi tar i mot sene bestillinger)" shopping_oc_last_closed: "Den siste runden stengte for %{distance_of_time} siden" @@ -466,11 +405,9 @@ nb: shopping_contact_social: "Følg" shopping_groups_part_of: "er en del av:" shopping_producers_of_hub: "%{hub}s produsenter:" - enterprises_next_closing: "Neste runde stenger" enterprises_ready_for: "Klar til" enterprises_choose: "Velg når du ønsker din bestilling:" - hubs_buy: "Handle:" hubs_shopping_here: "Handler her" hubs_orders_closed: "Stengt for bestilling" @@ -486,7 +423,6 @@ nb: hubs_intro: Handle lokalt hubs_distance: Nærmest hubs_distance_filter: "Vis meg butikker nær %{location}" - products_clear_all: Fjern alt products_showing: "Viser:" products_with: med @@ -501,21 +437,17 @@ nb: products_update_error_msg: "Lagring mislyktes." products_update_error_data: "Lagring mislyktes på grunn av ugyldige data:" products_changes_saved: "Endringene er lagret." - search_no_results_html: "Beklager, ingen treff på %{query}. Prøv på nytt?" - components_profiles_popover: "Profiler har ikke butikkvindu på Open Food Network men kan ha sin egen fysiske butikk eller nettbutikk et annet sted" components_profiles_show: "Vis profiler" components_filters_nofilters: "Ingen filter" components_filters_clearfilters: "Fjern alle filtre" - groups_title: Grupper groups_headline: Grupper / regioner groups_text: "Hver prodsent er unik. Hver forretning har noe annet å tilby. Våre grupper er kollektiv av produsenter, hubs og distributører som deler noe i fellesskap som lokasjon, bondens marked eller filosofi. Dette gjør din handleopplevelse enklere. Så utforsk våre grupper og la de gjøre forberedelsene for deg." groups_search: "Søk på navn eller nøkkelord" groups_no_groups: "Fant ingen grupper" groups_about: "Om oss" - groups_producers: "Våre produsenter" groups_hubs: "Våre hubs" groups_contact_web: Kontakt @@ -542,18 +474,14 @@ nb: groups_signup_contact: Klar for å snakke sammen? groups_signup_contact_text: "Ta kontakt for å oppdage hva OFN kan gjøre for deg:" groups_signup_detail: "Her er detaljene." - login_invalid: "Ugyldig epost eller passord" - modal_hubs: "Mathubs" modal_hubs_abstract: Våre hubs er kontaktpunkt mellom deg og menneskene som lager maten din! modal_hubs_content1: Du kan søke etter en passende hub på lokasjon eller navn. Noen hubs har flere hentepunkt hvor du kan plukke opp det du har kjøpt, og noen tilbyr også levering. Hver mathub er en butikk med uavhengig drift og logistikk - så det vil være forskjeller mellom huber. modal_hubs_content2: Du kan kun handle hos en hub om gangen. - modal_groups: "Grupper / Regioner" modal_groups_content1: Dette er organisasjonene og hub-koblingene som utgjør Open Food Network. modal_groups_content2: Noen grupper er klynger basert på lokalnivå eller regionnivå, andre har ingen geografiske likheter. - modal_how: "Slik fungerer det" modal_how_shop: Handle på Open Food Network modal_how_shop_explained: Søk etter en mathub nær deg for å begynne å handle! Du kan se detaljer for hver mathub for å se hvilke godbiter som finnes, og klikk deg videre for å handle. (Du kan kun handle hos en mathub om gangen). @@ -561,29 +489,8 @@ nb: modal_how_pickup_explained: Noen mathubs leverer på døren, mens andre krever at du henter varene du har kjøpt. Du kan se hvilke alternativ som er tilgjengelige på hjemmesiden, og velge hvilket du ønsker på handle- og betalingssidene. Levering koster mer, og prisene varierer fra hub til hub. Hver mathub er en forretning med uavhengig drift og logistikk - så variasjoner mellom hubs er naturlig. modal_how_more: Finn ut mer modal_how_more_explained: "Hvis du ønsker å lære mer om Open Food Network, hvordan det fungerer og ta del, sjekk ut:" - modal_producers: "Produsenter" modal_producers_explained: "Våre produsenter lager all den herlige maten du kan handle på Open Food Network." - - ocs_choice_hub: "Hub:" - ocs_choice_oc: "Bestillingsrunde:" - ocs_choice_text: "Du har ennå ikke valgt hvor du vil handle fra." - ocs_closed_headline: Bestillinger er for tiden stengt for denne huben - ocs_closed_time: "Den siste runden stengte for %{time} siden." - ocs_closed_contact: "Vennligst kontakt din hub direkte for å se om de godtar sene bestillinger, eller vent til neste runde åpner." - ocs_closed_opens: "Den neste bestillingsrunden åpner om %{time}" - ocs_closed_email: "Epost: %{email}" - ocs_closed_phone: "Telefon: %{phone}" - ocs_pickup_time: "Din bestilling vil være klar %{pickup_time}" - ocs_change_date: "Endre hentedato" - ocs_change_date_notice: "(Dette nullstiller kurven din)" - ocs_close_time: "BESTILLINGER STENGER" - ocs_when_headline: Når ønsker du bestillingen din? - ocs_when_text: Ingen varer vises før du velger en dato. - ocs_when_closing: "Stenger" - ocs_when_choose: "Velg Bestillingsrunde" - ocs_list: "Listevisning" - producers_about: Om oss producers_buy: Handle producers_contact: Kontakt @@ -592,6 +499,7 @@ nb: producers_buy_at_html: "Handle produkter fra %{enterprise} hos:" producers_filter: Filtrer på producers_filter_type: Type + producers_filter_property: Egenskape producers_title: Produsenter producers_headline: Finn lokale produsenter producers_signup_title: Bli med som produsent @@ -603,8 +511,6 @@ nb: producers_signup_cta_headline: Bli med nå! producers_signup_cta_action: Bli med nå producers_signup_detail: Detaljene. - producer: Producer - products_item: Vare products_description: Beskrivelse products_variant: Variant @@ -612,9 +518,20 @@ nb: products_available: Tilgjengelig? products_producer: "Produsent" products_price: "Pris" - register_title: Registrer - + sell_title: "Registrer" + sell_headline: "Bli med på Open Food Network!" + sell_motivation: "Vis frem maten din." + sell_producers: "Produsenter" + sell_hubs: "Hubs" + sell_groups: "Grupper" + sell_producers_detail: "Sette opp en profil for virksomheten din på OFN i løpet av noen få minutter. Når som helst kan du oppgradere din profil til en nettbutikk og selger produkter direkte til kunder." + sell_hubs_detail: "Sette opp en profil for virksomheten eller organisasjonen din på OFN. Når som helst kan du oppgradere din profil til en multi-produsent butikk." + sell_groups_detail: "Definere en skreddersydd katalog av bedrifter (produsenter og andre foretak) eller organisasjonen." + sell_user_guide: "Finn ut mer i brukerhåndboken." + sell_listing_price: "Profil på OFN er gratis. Åpner og kjører en butikk på OFN er gratis. Sette opp en gruppe katalog på OFN for organisasjonen eller regionalt nettverk er gratis." + sell_embed: "Vi kan også bygge inn en OFN butikk i din egen skreddersydde nettside eller bygge en tilpasset lokalmat nettverk nettside for din region." + sell_ask_services: "Spør oss om ØFN tjenester." shops_title: Butikker shops_headline: Handling på en ny måte. shops_text: Mat gror i syklus, bønder høster i syklus, og vi bestiller mat i syklus. Hvis du møter en stengt bestillingsrunde, sjekk igjen snart. @@ -627,7 +544,6 @@ nb: shops_signup_help: Vi er klar til å hjelpe. shops_signup_help_text: Du trenger bedre resultater. Du trenger nye kunder og logistikkpartnere. Du trenger å få din historie fortalt hos grossister, i dagligvaren og rundt kjøkkenbordet. shops_signup_detail: Detaljene. - orders_fees: Gebyrer... orders_edit_title: Handlekurv orders_edit_headline: Din handlekurv @@ -647,7 +563,6 @@ nb: orders_show_title: Ordrebekreftelse orders_show_time: Bestilling klar for orders_show_number: Ordrebekreftelse - products_cart_distributor_choice: "Distributør for bestillingen:" products_cart_distributor_change: "Din distributør for denne ordren vil bli endret til %{name} hvis du legger til dette produktet i handlekurven din." products_cart_distributor_is: "Din distributør for denne ordren er %{name}." @@ -660,13 +575,9 @@ nb: products_max_quantity: Max mengde products_distributor: Distributør products_distributor_info: Når du velger en distributør for din bestilling, vil deres adresse og hentetider vises her. - shop_trial_length: "Lengden av prøveperioden (dager)" shop_trial_expires_in: "Din prøveperiode på butikkfront går ut om " shop_trial_expired_notice: "Gode nyheter! Vi har bestemt å forlenge butikkprøveperioder inntil ytterligere beskjed." - - - # keys used in javascript password: Passord remember_me: Husk meg are_you_sure: "er du sikker?" @@ -717,7 +628,6 @@ nb: forgot_password: "Glemt passord?" password_reset_sent: "En epost med instruksjoner om å nullstille passordet har blitt sendt!" reset_password: "Tilbakestill passord" - registration_greeting: "Greetings!" who_is_managing_enterprise: "Hvem er ansvarlig for å administrere %{enterprise}?" enterprise_contact: "Primærkontakt" enterprise_contact_required: "Du må oppgi en primærkontakt." @@ -827,7 +737,6 @@ nb: bulk: "Bulk" shop_variant_quantity_min: "min" shop_variant_quantity_max: "max" - contact: "Contact" follow: "Følg" shop_for_products_html: "Handle produkter fra %{enterprise} på:" change_shop: "Endre butikk til:" @@ -840,10 +749,9 @@ nb: fundraising_fee: "innsamlingsaksjon" price_graph: "Prisgraf" included_tax: "inkludert avgift" - remove_tax: "Remove tax" balance: "Balanse" transaction: "Transaksjon" - transaction_date: "Dato" #Transaction is only in key to avoid conflict with :date + transaction_date: "Dato" payment_state: "Betallingsstatus" shipping_state: "Leveringsstatus" value: "Verdi" @@ -885,8 +793,6 @@ nb: supplier: "Leverandør" coordinator: "Koordinator" distributor: "Distributør" - product: "Products" - enterprise_fees: "Enterprise Fees" fee_type: "Avfgiftstype" tax_category: "Avgiftskategori" calculator: "Kalkulator" @@ -936,7 +842,6 @@ nb: spree_admin_enterprises_producers_total_products: "Alle Produkter" spree_admin_enterprises_producers_active_products: "Aktive Produkter" spree_admin_enterprises_producers_order_cycles: "Produkter i Bestillingsrunder" - spree_admin_enterprises_producers_order_cycles_title: "" spree_admin_enterprises_tabs_hubs: "HUBS" spree_admin_enterprises_tabs_producers: "PRODUSENTER" spree_admin_enterprises_producers_manage_order_cycles: "ADMINISTRER BESTILLINGSRUNDER" @@ -982,7 +887,7 @@ nb: hub_sidebar_blue: "blå" hub_sidebar_red: "rød" shop_trial_in_progress: "Din prøveperiode på butikkfront går ut om %{days}." - shop_trial_expired: "Gode nyheter! Vi har bestemt å forlenge butikkprøveperioder inntil ytterligere beskjed (sannsynligvis rundt mars 2015)." #FIXME + shop_trial_expired: "Gode nyheter! Vi har bestemt å forlenge butikkprøveperioder inntil ytterligere beskjed (sannsynligvis rundt mars 2015)." report_customers_distributor: "Distributør" report_customers_supplier: "Leverandør" report_customers_cycle: "Bestillingsrunde" @@ -1016,14 +921,12 @@ nb: unsaved_changes_confirmation: "Ulagrede endringer vil gå tapt. Fortsett likevel?" one_product_unsaved: "Endringer i ett produkt er fortsatt ulagret." products_unsaved: "Endringer i %{n} produkter er fortsatt ulagret." - add_manager: "Add a manager" is_already_manager: "er allerede administrator!" no_change_to_save: "Ingen endring å lagre" add_manager: "Legg til administrator" - users: "Brukere" + users: "Brukere" about: "Om" images: "Bilder" - contact: "Contact" web: "Nett" primary_details: "Primærdetaljer" adrdress: "Adresse" @@ -1043,7 +946,6 @@ nb: validation_msg_product_category_cant_be_blank: "^Produktkategori kan ikke være blank" validation_msg_tax_category_cant_be_blank: "^Avgiftskategori kan ikke være blank" validation_msg_is_associated_with_an_exising_customer: "er assosiert med en eksisterende kunde" - spree: shipment_states: backorder: restordre From baeabdd668a9151f322da43535fec3e3680b2073 Mon Sep 17 00:00:00 2001 From: Transifex-Openfoodnetwork Date: Fri, 12 Aug 2016 19:53:12 +1000 Subject: [PATCH 04/25] Updating translations for config/locales/nb.yml [skip ci] --- config/locales/nb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/nb.yml b/config/locales/nb.yml index 0b34b36824..7ac15bd86d 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -529,7 +529,7 @@ nb: sell_hubs_detail: "Sette opp en profil for virksomheten eller organisasjonen din på OFN. Når som helst kan du oppgradere din profil til en multi-produsent butikk." sell_groups_detail: "Definere en skreddersydd katalog av bedrifter (produsenter og andre foretak) eller organisasjonen." sell_user_guide: "Finn ut mer i brukerhåndboken." - sell_listing_price: "Profil på OFN er gratis. Åpner og kjører en butikk på OFN er gratis. Sette opp en gruppe katalog på OFN for organisasjonen eller regionalt nettverk er gratis." + sell_listing_price: "En profil på OFN er gratis. Lese mer om hvor mye det koster å åpne en butikk på OFN eller å sette opp en gruppe katalog for organisasjonen eller regionalt nettverket ditt." sell_embed: "Vi kan også bygge inn en OFN butikk i din egen skreddersydde nettside eller bygge en tilpasset lokalmat nettverk nettside for din region." sell_ask_services: "Spør oss om ØFN tjenester." shops_title: Butikker From 528af8759d9119d2f7da99d0938b9355a5ad946a Mon Sep 17 00:00:00 2001 From: Transifex-Openfoodnetwork Date: Fri, 19 Aug 2016 01:23:43 +1000 Subject: [PATCH 05/25] Updating translations for config/locales/nb.yml [skip ci] --- config/locales/nb.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/nb.yml b/config/locales/nb.yml index 7ac15bd86d..67a1db7cd5 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -529,7 +529,7 @@ nb: sell_hubs_detail: "Sette opp en profil for virksomheten eller organisasjonen din på OFN. Når som helst kan du oppgradere din profil til en multi-produsent butikk." sell_groups_detail: "Definere en skreddersydd katalog av bedrifter (produsenter og andre foretak) eller organisasjonen." sell_user_guide: "Finn ut mer i brukerhåndboken." - sell_listing_price: "En profil på OFN er gratis. Lese mer om hvor mye det koster å åpne en butikk på OFN eller å sette opp en gruppe katalog for organisasjonen eller regionalt nettverket ditt." + sell_listing_price: "En profil på OFN er gratis. Les mer om hvor mye det koster å åpne en butikk på OFN eller å sette opp en gruppenettverk for organisasjonen din eller ditt regionale nettverk." sell_embed: "Vi kan også bygge inn en OFN butikk i din egen skreddersydde nettside eller bygge en tilpasset lokalmat nettverk nettside for din region." sell_ask_services: "Spør oss om ØFN tjenester." shops_title: Butikker From 7eeee78c4ecfee6a1db90f137d7bcb8eaa4e78ee Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 26 Aug 2016 11:40:21 +1000 Subject: [PATCH 06/25] WIP: Move hubs partials from home to shops, their rightful home --- app/views/{home => shops}/_fat.html.haml | 0 app/views/{home => shops}/_filters.html.haml | 0 app/views/{home => shops}/_hubs.html.haml | 0 app/views/{home => shops}/_hubs_table.html.haml | 0 app/views/{home => shops}/_skinny.html.haml | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename app/views/{home => shops}/_fat.html.haml (100%) rename app/views/{home => shops}/_filters.html.haml (100%) rename app/views/{home => shops}/_hubs.html.haml (100%) rename app/views/{home => shops}/_hubs_table.html.haml (100%) rename app/views/{home => shops}/_skinny.html.haml (100%) diff --git a/app/views/home/_fat.html.haml b/app/views/shops/_fat.html.haml similarity index 100% rename from app/views/home/_fat.html.haml rename to app/views/shops/_fat.html.haml diff --git a/app/views/home/_filters.html.haml b/app/views/shops/_filters.html.haml similarity index 100% rename from app/views/home/_filters.html.haml rename to app/views/shops/_filters.html.haml diff --git a/app/views/home/_hubs.html.haml b/app/views/shops/_hubs.html.haml similarity index 100% rename from app/views/home/_hubs.html.haml rename to app/views/shops/_hubs.html.haml diff --git a/app/views/home/_hubs_table.html.haml b/app/views/shops/_hubs_table.html.haml similarity index 100% rename from app/views/home/_hubs_table.html.haml rename to app/views/shops/_hubs_table.html.haml diff --git a/app/views/home/_skinny.html.haml b/app/views/shops/_skinny.html.haml similarity index 100% rename from app/views/home/_skinny.html.haml rename to app/views/shops/_skinny.html.haml From 4c4021935299aa8731164c104c7ecf9f5a397b6a Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 26 Aug 2016 11:43:23 +1000 Subject: [PATCH 07/25] Move hubs partials from home to shops, their rightful home --- app/views/groups/show.html.haml | 4 ++-- app/views/shops/_filters.html.haml | 6 +++--- app/views/shops/_hubs.html.haml | 6 +++--- app/views/shops/_hubs_table.html.haml | 4 ++-- app/views/shops/index.html.haml | 4 ++-- spec/features/consumer/shops_spec.rb | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index ef9e281155..49270dcc05 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -98,8 +98,8 @@ "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "GroupEnterpriseNodeCtrl"} .small-12.columns - = render partial: 'home/skinny' - = render partial: 'home/fat' + = render 'shops/skinny' + = render 'shops/fat' = render partial: 'shared/components/enterprise_no_results' diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml index bfd13fdf54..c6692e5a84 100644 --- a/app/views/shops/_filters.html.haml +++ b/app/views/shops/_filters.html.haml @@ -1,7 +1,7 @@ .row - = render partial: 'shared/components/filter_controls' + = render 'shared/components/filter_controls' -# .small-12.medium-6.columns   - = render partial: 'shared/components/show_profiles' + = render 'shared/components/show_profiles' .row.animate-show{"ng-show" => "filtersActive"} .small-12.columns @@ -19,4 +19,4 @@ = t :hubs_filter_delivery %shipping-type-selector -= render partial: 'shared/components/filter_box' += render 'shared/components/filter_box' diff --git a/app/views/shops/_hubs.html.haml b/app/views/shops/_hubs.html.haml index e899270efc..6087d2330c 100644 --- a/app/views/shops/_hubs.html.haml +++ b/app/views/shops/_hubs.html.haml @@ -7,14 +7,14 @@ = t :hubs_intro = render "shared/components/enterprise_search" - = render "home/filters" + = render "filters" .row .small-12.columns .name-matches{"ng-show" => "nameMatchesFiltered.length > 0"} %h2 = t :hubs_matches - = render "home/hubs_table", enterprises: "nameMatches" + = render "hubs_table", enterprises: "nameMatches" .distance-matches{"ng-if" => "nameMatchesFiltered.length == 0 || distanceMatchesShown"} %h2{"ng-show" => "nameMatchesFiltered.length > 0 || query.length > 0"} @@ -22,7 +22,7 @@ %span{"ng-show" => "nameMatchesFiltered.length > 0"} {{ nameMatchesFiltered[0].name }}... %span{"ng-hide" => "nameMatchesFiltered.length > 0"} {{ query }}... - = render "home/hubs_table", enterprises: "distanceMatches" + = render "hubs_table", enterprises: "distanceMatches" .show-distance-matches{"ng-show" => "nameMatchesFiltered.length > 0 && !distanceMatchesShown"} %a{href: "", "ng-click" => "showDistanceMatches()"} diff --git a/app/views/shops/_hubs_table.html.haml b/app/views/shops/_hubs_table.html.haml index edf9eb5ec8..3d8bfca7d1 100644 --- a/app/views/shops/_hubs_table.html.haml +++ b/app/views/shops/_hubs_table.html.haml @@ -4,7 +4,7 @@ "ng-controller" => "HubNodeCtrl", id: "{{hub.hash}}"} .small-12.columns - = render 'home/skinny' - = render 'home/fat' + = render 'skinny' + = render 'fat' = render 'shared/components/enterprise_no_results', enterprises: "#{enterprises}Filtered" diff --git a/app/views/shops/index.html.haml b/app/views/shops/index.html.haml index 1b3cf547a8..7e288f4157 100644 --- a/app/views/shops/index.html.haml +++ b/app/views/shops/index.html.haml @@ -10,5 +10,5 @@ %p.text-big = t :shops_text -= render partial: "home/hubs" -= render partial: "shared/footer" += render "hubs" += render "shared/footer" diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index 2a65a73aef..0d19eddf52 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -47,7 +47,7 @@ feature 'Shops', js: true do it "should show closed shops after clicking the button" do create(:simple_product, distributors: [d1, d2]) visit shops_path - click_link_and_ensure("Show closed shops", -> { page.has_selector? 'hub.inactive' }) + click_link_and_ensure("Show Closed Shops", -> { page.has_selector? 'hub.inactive' }) page.should have_selector 'hub.inactive', text: d2.name end From 38d568276247724bcf1df0a0a4e2fe090ae858bb Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 26 Aug 2016 12:43:21 +1000 Subject: [PATCH 08/25] Add property filters for shops --- app/views/shops/_filters.html.haml | 10 ++++++++- app/views/shops/_hubs_table.html.haml | 2 +- config/locales/en.yml | 1 + spec/features/consumer/shops_spec.rb | 30 +++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml index c6692e5a84..08d8b075f0 100644 --- a/app/views/shops/_filters.html.haml +++ b/app/views/shops/_filters.html.haml @@ -3,7 +3,7 @@ -# .small-12.medium-6.columns   = render 'shared/components/show_profiles' -.row.animate-show{"ng-show" => "filtersActive"} +.row.animate-show.filter-row{"ng-show" => "filtersActive"} .small-12.columns .row.filter-box .small-12.large-9.columns @@ -19,4 +19,12 @@ = t :hubs_filter_delivery %shipping-type-selector + .small-12.large-12.columns + %h5.tdhead + .light + = t :hubs_filter_by + = t :hubs_filter_property + .filter-shopfront.property-selectors + %single-line-selectors{ selectors: "filterSelectors", objects: "visibleMatches | filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | propertiesOf", "active-selectors" => "activeProperties"} + = render 'shared/components/filter_box' diff --git a/app/views/shops/_hubs_table.html.haml b/app/views/shops/_hubs_table.html.haml index 3d8bfca7d1..2f4d85af0e 100644 --- a/app/views/shops/_hubs_table.html.haml +++ b/app/views/shops/_hubs_table.html.haml @@ -1,5 +1,5 @@ .active_table - %hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])", + %hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | filter:filterExpression | taxons:activeTaxons | properties:activeProperties | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "HubNodeCtrl", id: "{{hub.hash}}"} diff --git a/config/locales/en.yml b/config/locales/en.yml index 1d8707a7b9..991c308c2f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -505,6 +505,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using hubs_filter_by: "Filter by" hubs_filter_type: "Type" hubs_filter_delivery: "Delivery" + hubs_filter_property: "Property" hubs_matches: "Did you mean?" hubs_intro: Shop in your local area hubs_distance: Closest to diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index 0d19eddf52..b744282952 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -56,6 +56,36 @@ feature 'Shops', js: true do expect(page).to have_current_path enterprise_shop_path(distributor) end + describe "filtering by product property" do + let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } + let(:p1) { create(:simple_product, supplier: producer) } + let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } + let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } + let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } + + before do + p2.set_property 'Local', 'XYZ 123' + + ex_d1.variants << p1.variants.first + ex_d2.variants << p2.variants.first + end + + it "filters" do + toggle_filters + + toggle_filter 'Organic' + + expect(page).to have_content d1.name + expect(page).not_to have_content d2.name + + toggle_filter 'Organic' + toggle_filter 'Local' + + expect(page).not_to have_content d1.name + expect(page).to have_content d2.name + end + end + describe "property badges" do let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [product.variants.first]) } let(:product) { create(:simple_product, supplier: producer) } From 63ef5de0e55b93d0a1efab6a39eff586312d9839 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 26 Aug 2016 14:19:18 +1000 Subject: [PATCH 09/25] Use short syntax for render partial --- app/views/groups/show.html.haml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 49270dcc05..6342e1af70 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -60,8 +60,8 @@ .small-12.columns %h1 = t :groups_producers - = render partial: "shared/components/enterprise_search" - = render partial: "producers/filters" + = render "shared/components/enterprise_search" + = render "producers/filters" .row .small-12.columns @@ -73,10 +73,10 @@ id: "{{producer.hash}}"} .small-12.columns - = render partial: 'producers/skinny' - = render partial: 'producers/fat' + = render "producers/skinny" + = render "producers/fat" - = render partial: 'shared/components/enterprise_no_results' + = render 'shared/components/enterprise_no_results' %tab{heading: t(:groups_hubs), active: "tabs.hubs.active", @@ -87,8 +87,8 @@ %h1 = t :groups_hubs - = render partial: "shared/components/enterprise_search" - = render partial: "hub_filters" + = render "shared/components/enterprise_search" + = render "hub_filters" .row .small-12.columns @@ -101,10 +101,10 @@ = render 'shops/skinny' = render 'shops/fat' - = render partial: 'shared/components/enterprise_no_results' + = render 'shared/components/enterprise_no_results' .small-12.medium-12.large-3.columns - = render partial: 'contact' + = render 'contact' .small-12.columns.pad-top .row.pad-top @@ -122,4 +122,4 @@ %p   -= render partial: "shared/footer" += render "shared/footer" From ed2522f6d2df1d996f850f5d5858771a5a9d9060 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 26 Aug 2016 15:49:43 +1000 Subject: [PATCH 10/25] Explicitly specify supplied or distributed properties for ng filters: properties, propertiesOf --- .../darkswarm/filters/properties.js.coffee | 8 ++++++-- .../darkswarm/filters/properties_of.js.coffee | 12 ++++++------ app/views/groups/show.html.haml | 4 ++-- app/views/producers/_filters.html.haml | 2 +- app/views/producers/index.html.haml | 2 +- app/views/shop/products/_filters.html.haml | 2 +- app/views/shops/_filters.html.haml | 2 +- app/views/shops/_hubs_table.html.haml | 2 +- spec/features/consumer/shops_spec.rb | 6 ++++-- 9 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/darkswarm/filters/properties.js.coffee b/app/assets/javascripts/darkswarm/filters/properties.js.coffee index 1453cac053..fe7ed71fa3 100644 --- a/app/assets/javascripts/darkswarm/filters/properties.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/properties.js.coffee @@ -1,13 +1,17 @@ Darkswarm.filter 'properties', -> # Filter anything that responds to object.supplied_properties - (objects, ids) -> + (objects, ids, source) -> objects ||= [] ids ?= [] + + source ||= 'properties' + return [] unless source in ['properties', 'supplied_properties', 'distributed_properties'] + if ids.length == 0 # No properties selected, pass all objects through. objects else objects.filter (obj) -> - properties = obj.supplied_properties || obj.properties + properties = obj[source] properties.some (property) -> property.id in ids diff --git a/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee b/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee index 7eac12bf1e..f3f4f51b5e 100644 --- a/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee @@ -1,12 +1,12 @@ Darkswarm.filter 'propertiesOf', -> - (objects) -> + (objects, source) -> + source ||= 'properties' + return {} unless source in ['properties', 'supplied_properties', 'distributed_properties'] + properties = {} for object in objects - if object.supplied_properties? - for property in object.supplied_properties - properties[property.id] = property - else - for property in object.properties + if object[source]? + for property in object[source] properties[property.id] = property properties diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 6342e1af70..2f2f0e7a62 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -67,7 +67,7 @@ .small-12.columns .active_table %producer.active_table_node.row.animate-repeat{id: "{{producer.path}}", - "ng-repeat" => "producer in filteredEnterprises = (group_producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties)", + "ng-repeat" => "producer in filteredEnterprises = (group_producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')", "ng-controller" => "GroupEnterpriseNodeCtrl", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}", id: "{{producer.hash}}"} @@ -94,7 +94,7 @@ .small-12.columns .active_table %hub.active_table_node.row.animate-repeat{id: "{{hub.hash}}", - "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+orders_close_at'])", + "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | properties:activeProperties:'distributed_properties' | orderBy:['-active', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "GroupEnterpriseNodeCtrl"} .small-12.columns diff --git a/app/views/producers/_filters.html.haml b/app/views/producers/_filters.html.haml index 771ed932c9..25f3d45af7 100644 --- a/app/views/producers/_filters.html.haml +++ b/app/views/producers/_filters.html.haml @@ -18,6 +18,6 @@ = t :producers_filter = t :producers_filter_property .filter-shopfront.property-selectors - %single-line-selectors{ selectors: "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | propertiesOf", "active-selectors" => "activeProperties"} + %single-line-selectors{ selectors: "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"} = render partial: 'shared/components/filter_box' diff --git a/app/views/producers/index.html.haml b/app/views/producers/index.html.haml index 04048ef77e..af6c2e4fd1 100644 --- a/app/views/producers/index.html.haml +++ b/app/views/producers/index.html.haml @@ -16,7 +16,7 @@ .small-12.columns .active_table %producer.active_table_node.row.animate-repeat{id: "{{producer.path}}", - "ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | visible | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties)", + "ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | visible | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')", "ng-controller" => "ProducerNodeCtrl", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}", id: "{{producer.hash}}"} diff --git a/app/views/shop/products/_filters.html.haml b/app/views/shop/products/_filters.html.haml index 7efaba6cc9..10c7c20deb 100644 --- a/app/views/shop/products/_filters.html.haml +++ b/app/views/shop/products/_filters.html.haml @@ -1,5 +1,5 @@ .filter-shopfront.taxon-selectors.text-right - %single-line-selectors{ selectors: "taxonSelectors", objects: "Products.products | products:query | properties: activeProperties | taxonsOf", "active-selectors" => "activeTaxons"} + %single-line-selectors{ selectors: "taxonSelectors", objects: "Products.products | products:query | properties:activeProperties | taxonsOf", "active-selectors" => "activeTaxons"} .filter-shopfront.property-selectors.text-right %single-line-selectors{ selectors: "propertySelectors", objects: "Products.products | products:query | taxons:activeTaxons | propertiesOf", "active-selectors" => "activeProperties"} diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml index 08d8b075f0..93d4e5b19f 100644 --- a/app/views/shops/_filters.html.haml +++ b/app/views/shops/_filters.html.haml @@ -25,6 +25,6 @@ = t :hubs_filter_by = t :hubs_filter_property .filter-shopfront.property-selectors - %single-line-selectors{ selectors: "filterSelectors", objects: "visibleMatches | filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | propertiesOf", "active-selectors" => "activeProperties"} + %single-line-selectors{ selectors: "filterSelectors", objects: "visibleMatches | filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | propertiesOf:'distributed_properties'", "active-selectors" => "activeProperties"} = render 'shared/components/filter_box' diff --git a/app/views/shops/_hubs_table.html.haml b/app/views/shops/_hubs_table.html.haml index 2f4d85af0e..6d5803b477 100644 --- a/app/views/shops/_hubs_table.html.haml +++ b/app/views/shops/_hubs_table.html.haml @@ -1,5 +1,5 @@ .active_table - %hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | filter:filterExpression | taxons:activeTaxons | properties:activeProperties | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])", + %hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | filter:filterExpression | taxons:activeTaxons | properties:activeProperties:'distributed_properties' | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "HubNodeCtrl", id: "{{hub.hash}}"} diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index b744282952..74fb5b955f 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -58,8 +58,8 @@ feature 'Shops', js: true do describe "filtering by product property" do let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } - let(:p1) { create(:simple_product, supplier: producer) } - let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } + let!(:p1) { create(:simple_product, supplier: producer) } + let!(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } @@ -68,6 +68,8 @@ feature 'Shops', js: true do ex_d1.variants << p1.variants.first ex_d2.variants << p2.variants.first + + visit shops_path end it "filters" do From 8339d247f86bf70553b4b99e61ff6b844a09b9f4 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 26 Aug 2016 16:22:05 +1000 Subject: [PATCH 11/25] Shops on groups page filter by property --- app/views/groups/_hub_filters.html.haml | 21 ------------- app/views/groups/show.html.haml | 4 +-- app/views/shops/_filters.html.haml | 8 +++-- spec/features/consumer/groups_spec.rb | 39 +++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 25 deletions(-) delete mode 100644 app/views/groups/_hub_filters.html.haml diff --git a/app/views/groups/_hub_filters.html.haml b/app/views/groups/_hub_filters.html.haml deleted file mode 100644 index 71924d5e85..0000000000 --- a/app/views/groups/_hub_filters.html.haml +++ /dev/null @@ -1,21 +0,0 @@ -.row - = render partial: 'shared/components/filter_controls' - = render partial: 'shared/components/show_profiles' - -.row.animate-show{"ng-show" => "filtersActive"} - .small-12.columns - .row.filter-box - .small-12.large-9.columns - %h5.tdhead - .light - = t :hubs_filter_by - = t :hubs_filter_type - %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{"selector-set" => "filterSelectors", objects: "group_hubs | searchEnterprises:query | shipping:shippingTypes | showHubProfiles:show_profiles | taxonsOf", "active-selectors" => "activeTaxons"} - .small-12.large-3.columns - %h5.tdhead - .light - = t :hubs_filter_by - = t :hubs_filter_delivery - %shipping-type-selector - -= render partial: 'shared/components/filter_box' diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 2f2f0e7a62..90b74c0b42 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -88,13 +88,13 @@ = t :groups_hubs = render "shared/components/enterprise_search" - = render "hub_filters" + = render "shops/filters", resource: "group_hubs", property_filters: "| searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles" .row .small-12.columns .active_table %hub.active_table_node.row.animate-repeat{id: "{{hub.hash}}", - "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | properties:activeProperties:'distributed_properties' | orderBy:['-active', '+orders_close_at'])", + "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | properties:activeProperties:'distributed_properties' | orderBy:['-active', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "GroupEnterpriseNodeCtrl"} .small-12.columns diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml index 93d4e5b19f..1094d81b2f 100644 --- a/app/views/shops/_filters.html.haml +++ b/app/views/shops/_filters.html.haml @@ -1,3 +1,6 @@ +- resource ||= "visibleMatches" +- property_filters ||= "| filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles" + .row = render 'shared/components/filter_controls' -# .small-12.medium-6.columns   @@ -11,7 +14,8 @@ .light = t :hubs_filter_by = t :hubs_filter_type - %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "visibleMatches | visible | taxonsOf", "active-selectors" => "activeTaxons" } + + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "#{resource} | visible | taxonsOf", "active-selectors" => "activeTaxons" } .small-12.large-3.columns %h5.tdhead .light @@ -25,6 +29,6 @@ = t :hubs_filter_by = t :hubs_filter_property .filter-shopfront.property-selectors - %single-line-selectors{ selectors: "filterSelectors", objects: "visibleMatches | filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | propertiesOf:'distributed_properties'", "active-selectors" => "activeProperties"} + %single-line-selectors{ selectors: "filterSelectors", objects: "#{resource} #{property_filters} | propertiesOf:'distributed_properties'", "active-selectors" => "activeProperties"} = render 'shared/components/filter_box' diff --git a/spec/features/consumer/groups_spec.rb b/spec/features/consumer/groups_spec.rb index 039322b379..4a5f166d7d 100644 --- a/spec/features/consumer/groups_spec.rb +++ b/spec/features/consumer/groups_spec.rb @@ -54,4 +54,43 @@ feature 'Groups', js: true do end end end + + describe "shops" do + describe "filtering by product property" do + let!(:group) { create(:enterprise_group, enterprises: [d1, d2], on_front_page: true) } + let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } + let(:producer) { create(:supplier_enterprise) } + let(:d1) { create(:distributor_enterprise) } + let(:d2) { create(:distributor_enterprise) } + let(:p1) { create(:simple_product, supplier: producer) } + let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } + let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } + let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } + + before do + producer.set_producer_property 'Organic', 'NASAA 12345' + p2.set_property 'Local', 'XYZ 123' + + ex_d1.variants << p1.variants.first + ex_d2.variants << p2.variants.first + + visit group_path(group, anchor: "/hubs") + end + + it "filters" do + toggle_filters + + toggle_filter 'Organic' + + expect(page).to have_content d1.name + expect(page).not_to have_content d2.name + + toggle_filter 'Organic' + toggle_filter 'Local' + + expect(page).not_to have_content d1.name + expect(page).to have_content d2.name + end + end + end end From e00846776e15a4469fcfffcc7fabbef85cb3372d Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Aug 2016 10:11:05 +1000 Subject: [PATCH 12/25] Client-side, always show properties by their presentation, not their name --- app/helpers/injection_helper.rb | 2 +- app/serializers/api/property_serializer.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index 6db2e583bc..dad9cf11f9 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -45,7 +45,7 @@ module InjectionHelper end def inject_properties - inject_json_ams "properties", Spree::Property.all, Api::IdNameSerializer + inject_json_ams "properties", Spree::Property.all, Api::PropertySerializer end def inject_currency_config diff --git a/app/serializers/api/property_serializer.rb b/app/serializers/api/property_serializer.rb index 7da4fce990..cdb3f2bae3 100644 --- a/app/serializers/api/property_serializer.rb +++ b/app/serializers/api/property_serializer.rb @@ -1,3 +1,9 @@ class Api::PropertySerializer < ActiveModel::Serializer attributes :id, :name, :presentation + + # Client-side we don't care about the property name. Send the presentation + # since this is what we want to show to the user. + def name + object.presentation + end end From 8ec2ebbf944c7b774aa59258b471a57535669bf4 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Aug 2016 11:32:38 +1000 Subject: [PATCH 13/25] Swap to using multi-line selectors for property filters - z-index issues with single-line-selectors --- app/assets/stylesheets/darkswarm/_shop-filters.css.sass | 2 +- app/views/producers/_filters.html.haml | 2 +- app/views/shops/_filters.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/darkswarm/_shop-filters.css.sass b/app/assets/stylesheets/darkswarm/_shop-filters.css.sass index 3c4f9a514d..07fea7a0b1 100644 --- a/app/assets/stylesheets/darkswarm/_shop-filters.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-filters.css.sass @@ -96,7 +96,7 @@ // content. Ensure that the dropdown appears above the content. .filter-row position: relative - z-index: 100 + z-index: 90 .filter-shopfront &.taxon-selectors, &.property-selectors diff --git a/app/views/producers/_filters.html.haml b/app/views/producers/_filters.html.haml index 25f3d45af7..3e067d73fb 100644 --- a/app/views/producers/_filters.html.haml +++ b/app/views/producers/_filters.html.haml @@ -18,6 +18,6 @@ = t :producers_filter = t :producers_filter_property .filter-shopfront.property-selectors - %single-line-selectors{ selectors: "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"} + %filter-selector{ "selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"} = render partial: 'shared/components/filter_box' diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml index 1094d81b2f..68caa353bb 100644 --- a/app/views/shops/_filters.html.haml +++ b/app/views/shops/_filters.html.haml @@ -29,6 +29,6 @@ = t :hubs_filter_by = t :hubs_filter_property .filter-shopfront.property-selectors - %single-line-selectors{ selectors: "filterSelectors", objects: "#{resource} #{property_filters} | propertiesOf:'distributed_properties'", "active-selectors" => "activeProperties"} + %filter-selector{ "selector-set" => "filterSelectors", objects: "#{resource} #{property_filters} | propertiesOf:'distributed_properties'", "active-selectors" => "activeProperties"} = render 'shared/components/filter_box' From 38c63fc88b910750f9fdfdd93d0552b598ad8cac Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Aug 2016 12:00:55 +1000 Subject: [PATCH 14/25] Available producer filters update when taxon filter changed --- app/views/producers/_filters.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/producers/_filters.html.haml b/app/views/producers/_filters.html.haml index 3e067d73fb..17f260196a 100644 --- a/app/views/producers/_filters.html.haml +++ b/app/views/producers/_filters.html.haml @@ -18,6 +18,6 @@ = t :producers_filter = t :producers_filter_property .filter-shopfront.property-selectors - %filter-selector{ "selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"} + %filter-selector{ "selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | taxons:activeTaxons | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"} = render partial: 'shared/components/filter_box' From 3a2e0b7effd22791c40f57294a36e035f2571792 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Aug 2016 12:11:20 +1000 Subject: [PATCH 15/25] Fix spacing --- app/views/shops/_filters.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml index 68caa353bb..42e2b2ec28 100644 --- a/app/views/shops/_filters.html.haml +++ b/app/views/shops/_filters.html.haml @@ -1,5 +1,5 @@ - resource ||= "visibleMatches" -- property_filters ||= "| filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles" +- property_filters ||= "| filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles" .row = render 'shared/components/filter_controls' From c37bf3d07748c87147f67d3f57c9b74c989463fc Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 9 Sep 2016 14:28:05 +1000 Subject: [PATCH 16/25] Rename Property#sold_by and ProducerProperty#sold_by to currently_sold_by --- app/models/producer_property.rb | 2 +- app/models/spree/property_decorator.rb | 2 +- app/serializers/api/enterprise_serializer.rb | 4 ++-- spec/models/producer_property_spec.rb | 12 ++++++------ spec/models/spree/property_spec.rb | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb index bf1f083936..7e2dd4ace1 100644 --- a/app/models/producer_property.rb +++ b/app/models/producer_property.rb @@ -8,7 +8,7 @@ class ProducerProperty < ActiveRecord::Base after_destroy :refresh_products_cache_from_destroy - scope :sold_by, ->(shop) { + scope :currently_sold_by, ->(shop) { joins(producer: {supplied_products: {variants: {exchanges: :order_cycle}}}). merge(Exchange.outgoing). merge(Exchange.to_enterprise(shop)). diff --git a/app/models/spree/property_decorator.rb b/app/models/spree/property_decorator.rb index 50e450a03b..c0abfda7e4 100644 --- a/app/models/spree/property_decorator.rb +++ b/app/models/spree/property_decorator.rb @@ -8,7 +8,7 @@ module Spree where('spree_product_properties.product_id IN (?)', enterprise.supplied_product_ids) } - scope :sold_by, ->(shop) { + scope :currently_sold_by, ->(shop) { joins(products: {variants: {exchanges: :order_cycle}}). merge(Exchange.outgoing). merge(Exchange.to_enterprise(shop)). diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index f68c8be679..7cdf3d4adc 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -42,8 +42,8 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer def distributed_properties # This results in 3 queries per enterprise - product_properties = Spree::Property.sold_by(object) - ids = ProducerProperty.sold_by(object).pluck(:property_id) + product_properties = Spree::Property.currently_sold_by(object) + ids = ProducerProperty.currently_sold_by(object).pluck(:property_id) producer_properties = Spree::Property.where(id: ids) OpenFoodNetwork::PropertyMerge.merge product_properties, producer_properties diff --git a/spec/models/producer_property_spec.rb b/spec/models/producer_property_spec.rb index 2d0009ce12..559e7c7a28 100644 --- a/spec/models/producer_property_spec.rb +++ b/spec/models/producer_property_spec.rb @@ -8,7 +8,7 @@ describe ProducerProperty do producer.set_producer_property 'Organic Certified', 'NASAA 54321' end - describe ".sold_by" do + describe ".currently_sold_by" do let!(:shop) { create(:distributor_enterprise) } let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } let(:product) { create(:simple_product, supplier: producer) } @@ -22,7 +22,7 @@ describe ProducerProperty do describe "with an associated producer property" do it "returns the producer property" do - expect(ProducerProperty.sold_by(shop)).to eq [pp] + expect(ProducerProperty.currently_sold_by(shop)).to eq [pp] end end @@ -30,7 +30,7 @@ describe ProducerProperty do let!(:exchange) { create(:exchange, order_cycle: oc, incoming: true, sender: producer_other, receiver: oc.coordinator) } it "doesn't return the producer property" do - expect(ProducerProperty.sold_by(shop)).not_to include pp_other + expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other end end @@ -40,7 +40,7 @@ describe ProducerProperty do let!(:exchange) { create(:exchange, order_cycle: oc, incoming: false, sender: oc.coordinator, receiver: shop_other, variants: [product_other.variants.first]) } it "doesn't return the producer property" do - expect(ProducerProperty.sold_by(shop)).not_to include pp_other + expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other end end @@ -50,7 +50,7 @@ describe ProducerProperty do end it "doesn't return the producer property" do - expect(ProducerProperty.sold_by(shop)).not_to include pp + expect(ProducerProperty.currently_sold_by(shop)).not_to include pp end end @@ -59,7 +59,7 @@ describe ProducerProperty do let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) } it "doesn't return duplicates" do - expect(ProducerProperty.sold_by(shop).to_a.count).to eq 1 + expect(ProducerProperty.currently_sold_by(shop).to_a.count).to eq 1 end end end diff --git a/spec/models/spree/property_spec.rb b/spec/models/spree/property_spec.rb index 6e6ed2d780..8ba93738cf 100644 --- a/spec/models/spree/property_spec.rb +++ b/spec/models/spree/property_spec.rb @@ -31,7 +31,7 @@ module Spree end end - describe ".sold_by" do + describe ".currently_sold_by" do let!(:shop) { create(:distributor_enterprise) } let!(:shop_other) { create(:distributor_enterprise) } let!(:product) { create(:simple_product) } @@ -54,19 +54,19 @@ module Spree end it "returns the property" do - expect(Property.sold_by(shop)).to eq [property] + expect(Property.currently_sold_by(shop)).to eq [property] end it "doesn't return the property from another exchange" do - expect(Property.sold_by(shop)).not_to include property_other_ex + expect(Property.currently_sold_by(shop)).not_to include property_other_ex end it "doesn't return the property with no order cycle" do - expect(Property.sold_by(shop)).not_to include property_no_oc + expect(Property.currently_sold_by(shop)).not_to include property_no_oc end it "doesn't return the property from a closed order cycle" do - expect(Property.sold_by(shop)).not_to include property_closed_oc + expect(Property.currently_sold_by(shop)).not_to include property_closed_oc end context "with another product in the order cycle" do @@ -78,7 +78,7 @@ module Spree end it "doesn't return duplicates" do - expect(Property.sold_by(shop).to_a.count).to eq 1 + expect(Property.currently_sold_by(shop).to_a.count).to eq 1 end end end From 1bc477f6b1678f4915f297411b68d8c87a46eaa4 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 9 Sep 2016 14:32:33 +1000 Subject: [PATCH 17/25] Add ProducerProperty.ever_sold_by --- app/models/producer_property.rb | 8 ++++++-- spec/models/producer_property_spec.rb | 12 ++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb index 7e2dd4ace1..b0bb1b6e51 100644 --- a/app/models/producer_property.rb +++ b/app/models/producer_property.rb @@ -8,14 +8,18 @@ class ProducerProperty < ActiveRecord::Base after_destroy :refresh_products_cache_from_destroy - scope :currently_sold_by, ->(shop) { + scope :ever_sold_by, ->(shop) { joins(producer: {supplied_products: {variants: {exchanges: :order_cycle}}}). merge(Exchange.outgoing). merge(Exchange.to_enterprise(shop)). - merge(OrderCycle.active). select('DISTINCT producer_properties.*') } + scope :currently_sold_by, ->(shop) { + ever_sold_by(shop). + merge(OrderCycle.active) + } + def property_name property.name if property diff --git a/spec/models/producer_property_spec.rb b/spec/models/producer_property_spec.rb index 559e7c7a28..0de7aae19b 100644 --- a/spec/models/producer_property_spec.rb +++ b/spec/models/producer_property_spec.rb @@ -8,7 +8,7 @@ describe ProducerProperty do producer.set_producer_property 'Organic Certified', 'NASAA 54321' end - describe ".currently_sold_by" do + describe ".currently_sold_by and .ever_sold_by" do let!(:shop) { create(:distributor_enterprise) } let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } let(:product) { create(:simple_product, supplier: producer) } @@ -23,6 +23,7 @@ describe ProducerProperty do describe "with an associated producer property" do it "returns the producer property" do expect(ProducerProperty.currently_sold_by(shop)).to eq [pp] + expect(ProducerProperty.ever_sold_by(shop)).to eq [pp] end end @@ -31,6 +32,7 @@ describe ProducerProperty do it "doesn't return the producer property" do expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other + expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other end end @@ -41,6 +43,7 @@ describe ProducerProperty do it "doesn't return the producer property" do expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other + expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other end end @@ -49,9 +52,13 @@ describe ProducerProperty do oc.update_attributes! orders_close_at: 1.week.ago end - it "doesn't return the producer property" do + it "doesn't return the producer property for .currently_sold_by" do expect(ProducerProperty.currently_sold_by(shop)).not_to include pp end + + it "returns the producer property for .ever_sold_by" do + expect(ProducerProperty.ever_sold_by(shop)).to include pp + end end describe "with a duplicate producer property" do @@ -60,6 +67,7 @@ describe ProducerProperty do it "doesn't return duplicates" do expect(ProducerProperty.currently_sold_by(shop).to_a.count).to eq 1 + expect(ProducerProperty.ever_sold_by(shop).to_a.count).to eq 1 end end end From f98b25b719bb3fadd65b431345163f5c45887a6e Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 9 Sep 2016 14:38:56 +1000 Subject: [PATCH 18/25] Add Spree::Property.ever_sold_by --- app/models/spree/property_decorator.rb | 8 ++++++-- spec/models/spree/property_spec.rb | 26 +++++++++++++++++++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/app/models/spree/property_decorator.rb b/app/models/spree/property_decorator.rb index c0abfda7e4..81577cef4e 100644 --- a/app/models/spree/property_decorator.rb +++ b/app/models/spree/property_decorator.rb @@ -8,14 +8,18 @@ module Spree where('spree_product_properties.product_id IN (?)', enterprise.supplied_product_ids) } - scope :currently_sold_by, ->(shop) { + scope :ever_sold_by, ->(shop) { joins(products: {variants: {exchanges: :order_cycle}}). merge(Exchange.outgoing). merge(Exchange.to_enterprise(shop)). - merge(OrderCycle.active). select('DISTINCT spree_properties.*') } + scope :currently_sold_by, ->(shop) { + ever_sold_by(shop). + merge(OrderCycle.active) + } + after_save :refresh_products_cache diff --git a/spec/models/spree/property_spec.rb b/spec/models/spree/property_spec.rb index 8ba93738cf..29046a8782 100644 --- a/spec/models/spree/property_spec.rb +++ b/spec/models/spree/property_spec.rb @@ -31,42 +31,53 @@ module Spree end end - describe ".currently_sold_by" do + describe ".currently_sold_by and .ever_sold_by" do let!(:shop) { create(:distributor_enterprise) } let!(:shop_other) { create(:distributor_enterprise) } let!(:product) { create(:simple_product) } let!(:product_other_ex) { create(:simple_product) } let!(:product_no_oc) { create(:simple_product) } - let!(:product_closed_oc) { create(:simple_product) } let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } - let!(:oc_closed) { create(:closed_order_cycle, distributors: [shop], variants: [product_closed_oc.variants.first]) } let!(:exchange_other_shop) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: shop_other, variants: [product_other_ex.variants.first]) } let(:property) { product.properties.last } let(:property_other_ex) { product_other_ex.properties.last } let(:property_no_oc) { product_no_oc.properties.last } - let(:property_closed_oc) { product_closed_oc.properties.last } before do product.set_property 'Organic', 'NASAA 12345' product_other_ex.set_property 'Biodynamic', 'ASDF 12345' product_no_oc.set_property 'Shiny', 'Very' - product_closed_oc.set_property 'Spiffy', 'Ooh yeah' end it "returns the property" do expect(Property.currently_sold_by(shop)).to eq [property] + expect(Property.ever_sold_by(shop)).to eq [property] end it "doesn't return the property from another exchange" do expect(Property.currently_sold_by(shop)).not_to include property_other_ex + expect(Property.ever_sold_by(shop)).not_to include property_other_ex end it "doesn't return the property with no order cycle" do expect(Property.currently_sold_by(shop)).not_to include property_no_oc + expect(Property.ever_sold_by(shop)).not_to include property_no_oc end - it "doesn't return the property from a closed order cycle" do - expect(Property.currently_sold_by(shop)).not_to include property_closed_oc + describe "closed order cyces" do + let!(:product_closed_oc) { create(:simple_product) } + let!(:oc_closed) { create(:closed_order_cycle, distributors: [shop], variants: [product_closed_oc.variants.first]) } + let(:property_closed_oc) { product_closed_oc.properties.last } + + before { product_closed_oc.set_property 'Spiffy', 'Ooh yeah' } + + it "doesn't return the property for .currently_sold_by" do + expect(Property.currently_sold_by(shop)).not_to include property_closed_oc + end + + it "returns the property for .ever_sold_by" do + expect(Property.ever_sold_by(shop)).to include property_closed_oc + end end context "with another product in the order cycle" do @@ -79,6 +90,7 @@ module Spree it "doesn't return duplicates" do expect(Property.currently_sold_by(shop).to_a.count).to eq 1 + expect(Property.ever_sold_by(shop).to_a.count).to eq 1 end end end From 306bd25dd98f991ccf7fb9f9713d55ba4566a8cb Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 9 Sep 2016 14:45:11 +1000 Subject: [PATCH 19/25] EnterpriseSerialiser shows current properties for open shops and all properties for closed shops --- app/serializers/api/enterprise_serializer.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index 7cdf3d4adc..d3d7159959 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -42,9 +42,17 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer def distributed_properties # This results in 3 queries per enterprise - product_properties = Spree::Property.currently_sold_by(object) - ids = ProducerProperty.currently_sold_by(object).pluck(:property_id) - producer_properties = Spree::Property.where(id: ids) + + if active + product_properties = Spree::Property.currently_sold_by(object) + producer_property_ids = ProducerProperty.currently_sold_by(object).pluck(:property_id) + + else + product_properties = Spree::Property.ever_sold_by(object) + producer_property_ids = ProducerProperty.ever_sold_by(object).pluck(:property_id) + end + + producer_properties = Spree::Property.where(id: producer_property_ids) OpenFoodNetwork::PropertyMerge.merge product_properties, producer_properties end From db583df19877fd80f1b5c25ad879e9989247b13e Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 16 Sep 2016 10:50:59 +1000 Subject: [PATCH 20/25] Use inner join for Spree::Taxon.distributed_taxons --- app/models/spree/taxon_decorator.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/app/models/spree/taxon_decorator.rb b/app/models/spree/taxon_decorator.rb index a051de98fa..fcc784475c 100644 --- a/app/models/spree/taxon_decorator.rb +++ b/app/models/spree/taxon_decorator.rb @@ -33,20 +33,18 @@ Spree::Taxon.class_eval do # Find all the taxons of distributed products for each enterprise, indexed by enterprise. # Format: {enterprise_id => [taxon_id, ...]} - def self.distributed_taxons - taxons = {} + def self.distributed_taxons(which_taxons=:all) + # TODO: Why can't we merge(Spree::Product.with_order_cycles_inner) here? + taxons = Spree::Taxon. + joins(products: {variants_including_master: {exchanges: :order_cycle}}). + merge(Exchange.outgoing). + select('spree_taxons.*, exchanges.receiver_id AS enterprise_id') - Spree::Taxon. - joins(:products). - merge(Spree::Product.with_order_cycles_outer). - where('o_exchanges.incoming = ?', false). - select('spree_taxons.*, o_exchanges.receiver_id AS enterprise_id'). - each do |t| - taxons[t.enterprise_id.to_i] ||= Set.new - taxons[t.enterprise_id.to_i] << t.id - end - - taxons + taxons.inject({}) do |ts, t| + ts[t.enterprise_id.to_i] ||= Set.new + ts[t.enterprise_id.to_i] << t.id + ts + end end From c0db23af90e9d1a6bed9836b1d7dff6976e5acdf Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 16 Sep 2016 11:13:24 +1000 Subject: [PATCH 21/25] Spree::Taxon.distributed_taxons can be scoped to taxons in open order cycles --- app/models/spree/taxon_decorator.rb | 5 +++++ spec/models/spree/taxon_spec.rb | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/models/spree/taxon_decorator.rb b/app/models/spree/taxon_decorator.rb index fcc784475c..1878a20e49 100644 --- a/app/models/spree/taxon_decorator.rb +++ b/app/models/spree/taxon_decorator.rb @@ -32,6 +32,9 @@ Spree::Taxon.class_eval do end # Find all the taxons of distributed products for each enterprise, indexed by enterprise. + # May return :all taxons (distributed in open and closed order cycles), + # or :current taxons (distributed in an open order cycle). + # # Format: {enterprise_id => [taxon_id, ...]} def self.distributed_taxons(which_taxons=:all) # TODO: Why can't we merge(Spree::Product.with_order_cycles_inner) here? @@ -40,6 +43,8 @@ Spree::Taxon.class_eval do merge(Exchange.outgoing). select('spree_taxons.*, exchanges.receiver_id AS enterprise_id') + taxons = taxons.merge(OrderCycle.active) if which_taxons == :current + taxons.inject({}) do |ts, t| ts[t.enterprise_id.to_i] ||= Set.new ts[t.enterprise_id.to_i] << t.id diff --git a/spec/models/spree/taxon_spec.rb b/spec/models/spree/taxon_spec.rb index 8fb4b22dc5..873a201013 100644 --- a/spec/models/spree/taxon_spec.rb +++ b/spec/models/spree/taxon_spec.rb @@ -29,13 +29,18 @@ module Spree end end - describe "finding all distributed taxons" do - let!(:oc) { create(:simple_order_cycle, distributors: [e], variants: [p1.master]) } - let!(:s) { create(:supplier_enterprise) } - let!(:p1) { create(:simple_product, supplier: s, taxons: [t1, t2]) } + describe "finding distributed taxons" do + let!(:oc_open) { create(:open_order_cycle, distributors: [e], variants: [p_open.variants.first]) } + let!(:oc_closed) { create(:closed_order_cycle, distributors: [e], variants: [p_closed.variants.first]) } + let!(:p_open) { create(:simple_product, primary_taxon: t1) } + let!(:p_closed) { create(:simple_product, primary_taxon: t2) } - it "finds taxons" do - Taxon.distributed_taxons.should == {e.id => Set.new(p1.taxons.map(&:id))} + it "finds all distributed taxons" do + expect(Taxon.distributed_taxons(:all)).to eq({e.id => Set.new([t1.id, t2.id])}) + end + + it "finds currently distributed taxons" do + expect(Taxon.distributed_taxons(:current)).to eq({e.id => Set.new([t1.id])}) end end end From 3ca42ae055f27d86c28031e33d4d2f95b80902f0 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 16 Sep 2016 11:24:47 +1000 Subject: [PATCH 22/25] Extract ids_to_objs to SerializerHelper --- app/helpers/serializer_helper.rb | 6 ++++++ app/serializers/api/enterprise_serializer.rb | 12 ++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 app/helpers/serializer_helper.rb diff --git a/app/helpers/serializer_helper.rb b/app/helpers/serializer_helper.rb new file mode 100644 index 0000000000..2e48e3741d --- /dev/null +++ b/app/helpers/serializer_helper.rb @@ -0,0 +1,6 @@ +module SerializerHelper + def ids_to_objs(ids) + return [] if ids.blank? + ids.map { |id| {id: id} } + end +end diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index d3d7159959..fd723a40e8 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -20,6 +20,8 @@ class Api::EnterpriseSerializer < ActiveModel::Serializer end class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer + include SerializerHelper + attributes :orders_close_at, :active has_many :supplied_properties, serializer: Api::PropertySerializer has_many :distributed_properties, serializer: Api::PropertySerializer @@ -59,6 +61,8 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer end class Api::CachedEnterpriseSerializer < ActiveModel::Serializer + include SerializerHelper + cached #delegate :cache_key, to: :object @@ -161,12 +165,4 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer } icon_fonts[object.category] end - - - private - - def ids_to_objs(ids) - return [] if ids.blank? - ids.map { |id| {id: id} } - end end From e8f96e4818d8388e61d3b76eba233c2418c78301 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 16 Sep 2016 11:28:23 +1000 Subject: [PATCH 23/25] When a shop is open, only show taxon badges for currently open order cycles --- app/serializers/api/enterprise_serializer.rb | 22 ++++++++------ .../enterprise_injection_data.rb | 8 +++-- spec/features/consumer/shops_spec.rb | 29 +++++++++++++++++++ .../serializers/enterprise_serializer_spec.rb | 3 +- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index fd723a40e8..3537bcdd24 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -23,6 +23,7 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer include SerializerHelper attributes :orders_close_at, :active + attributes :taxons, :supplied_taxons has_many :supplied_properties, serializer: Api::PropertySerializer has_many :distributed_properties, serializer: Api::PropertySerializer @@ -58,6 +59,18 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer OpenFoodNetwork::PropertyMerge.merge product_properties, producer_properties end + + def taxons + if active + ids_to_objs options[:data].current_distributed_taxons[object.id] + else + ids_to_objs options[:data].all_distributed_taxons[object.id] + end + end + + def supplied_taxons + ids_to_objs options[:data].supplied_taxons[object.id] + end end class Api::CachedEnterpriseSerializer < ActiveModel::Serializer @@ -77,16 +90,7 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer :email_address, :hash, :logo, :promo_image, :path, :pickup, :delivery, :icon, :icon_font, :producer_icon_font, :category, :producers, :hubs - attributes :taxons, :supplied_taxons - has_one :address, serializer: Api::AddressSerializer - def taxons - ids_to_objs options[:data].distributed_taxons[object.id] - end - - def supplied_taxons - ids_to_objs options[:data].supplied_taxons[object.id] - end def pickup services = options[:data].shipping_method_services[object.id] diff --git a/lib/open_food_network/enterprise_injection_data.rb b/lib/open_food_network/enterprise_injection_data.rb index 87516007c6..938c8b3aab 100644 --- a/lib/open_food_network/enterprise_injection_data.rb +++ b/lib/open_food_network/enterprise_injection_data.rb @@ -20,8 +20,12 @@ module OpenFoodNetwork @supplied_taxons ||= Spree::Taxon.supplied_taxons end - def distributed_taxons - @distributed_taxons ||= Spree::Taxon.distributed_taxons + def all_distributed_taxons + @all_distributed_taxons ||= Spree::Taxon.distributed_taxons(:all) + end + + def current_distributed_taxons + @current_distributed_taxons ||= Spree::Taxon.distributed_taxons(:current) end end end diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index 74fb5b955f..f8f54a197b 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -88,6 +88,35 @@ feature 'Shops', js: true do end end + describe "taxon badges" do + let!(:closed_oc) { create(:closed_order_cycle, distributors: [shop], variants: [p_closed.variants.first]) } + let!(:p_closed) { create(:simple_product, taxons: [taxon_closed]) } + let(:shop) { create(:distributor_enterprise) } + let(:taxon_closed) { create(:taxon, name: 'Closed') } + + describe "open shops" do + let!(:open_oc) { create(:open_order_cycle, distributors: [shop], variants: [p_open.variants.first]) } + let!(:p_open) { create(:simple_product, taxons: [taxon_open]) } + let(:taxon_open) { create(:taxon, name: 'Open') } + + it "shows taxons for open order cycles only" do + visit shops_path + expand_active_table_node shop.name + expect(page).to have_selector '.fat-taxons', text: 'Open' + expect(page).not_to have_selector '.fat-taxons', text: 'Closed' + end + end + + describe "closed shops" do + it "shows taxons for any order cycle" do + visit shops_path + click_link 'Show Closed Shops' + expand_active_table_node shop.name + expect(page).to have_selector '.fat-taxons', text: 'Closed' + end + end + end + describe "property badges" do let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [product.variants.first]) } let(:product) { create(:simple_product, supplier: producer) } diff --git a/spec/serializers/enterprise_serializer_spec.rb b/spec/serializers/enterprise_serializer_spec.rb index f5eff4f771..bea2672157 100644 --- a/spec/serializers/enterprise_serializer_spec.rb +++ b/spec/serializers/enterprise_serializer_spec.rb @@ -6,7 +6,8 @@ describe Api::EnterpriseSerializer do let(:taxon) { create(:taxon) } let(:data) { OpenStruct.new(earliest_closing_times: {}, active_distributors: [], - distributed_taxons: {enterprise.id => [123]}, + all_distributed_taxons: {enterprise.id => [123]}, + current_distributed_taxons: {enterprise.id => [123]}, supplied_taxons: {enterprise.id => [456]}, shipping_method_services: {}, relatives: {enterprise.id => {producers: [123], distributors: [456]}}) } From 7d149ed198a18ce602cf3b35eff93f55645df851 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Sun, 18 Sep 2016 17:46:43 +1000 Subject: [PATCH 24/25] Revert shop property filters - causing 10x slowdown This commit reverts commits 7eeee78c4ecfee6a1db90f137d7bcb8eaa4e78ee to e8f96e4818d8388e61d3b76eba233c2418c78301 (inclusive) --- .../darkswarm/filters/properties.js.coffee | 8 +-- .../darkswarm/filters/properties_of.js.coffee | 12 ++-- .../darkswarm/_shop-filters.css.sass | 2 +- app/helpers/injection_helper.rb | 2 +- app/helpers/serializer_helper.rb | 6 -- app/models/producer_property.rb | 8 +-- app/models/spree/property_decorator.rb | 8 +-- app/models/spree/taxon_decorator.rb | 27 ++++---- app/serializers/api/enterprise_serializer.rb | 48 ++++++-------- app/serializers/api/property_serializer.rb | 6 -- app/views/groups/_hub_filters.html.haml | 21 +++++++ app/views/groups/show.html.haml | 28 ++++----- app/views/{shops => home}/_fat.html.haml | 0 app/views/home/_filters.html.haml | 22 +++++++ app/views/{shops => home}/_hubs.html.haml | 6 +- .../{shops => home}/_hubs_table.html.haml | 6 +- app/views/{shops => home}/_skinny.html.haml | 0 app/views/producers/_filters.html.haml | 2 +- app/views/producers/index.html.haml | 2 +- app/views/shop/products/_filters.html.haml | 2 +- app/views/shops/_filters.html.haml | 34 ---------- app/views/shops/index.html.haml | 4 +- config/locales/en.yml | 1 - .../enterprise_injection_data.rb | 8 +-- spec/features/consumer/groups_spec.rb | 39 ------------ spec/features/consumer/shops_spec.rb | 63 +------------------ spec/models/producer_property_spec.rb | 22 +++---- spec/models/spree/property_spec.rb | 34 ++++------ spec/models/spree/taxon_spec.rb | 17 ++--- .../serializers/enterprise_serializer_spec.rb | 3 +- 30 files changed, 142 insertions(+), 299 deletions(-) delete mode 100644 app/helpers/serializer_helper.rb create mode 100644 app/views/groups/_hub_filters.html.haml rename app/views/{shops => home}/_fat.html.haml (100%) create mode 100644 app/views/home/_filters.html.haml rename app/views/{shops => home}/_hubs.html.haml (89%) rename app/views/{shops => home}/_hubs_table.html.haml (67%) rename app/views/{shops => home}/_skinny.html.haml (100%) delete mode 100644 app/views/shops/_filters.html.haml diff --git a/app/assets/javascripts/darkswarm/filters/properties.js.coffee b/app/assets/javascripts/darkswarm/filters/properties.js.coffee index fe7ed71fa3..1453cac053 100644 --- a/app/assets/javascripts/darkswarm/filters/properties.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/properties.js.coffee @@ -1,17 +1,13 @@ Darkswarm.filter 'properties', -> # Filter anything that responds to object.supplied_properties - (objects, ids, source) -> + (objects, ids) -> objects ||= [] ids ?= [] - - source ||= 'properties' - return [] unless source in ['properties', 'supplied_properties', 'distributed_properties'] - if ids.length == 0 # No properties selected, pass all objects through. objects else objects.filter (obj) -> - properties = obj[source] + properties = obj.supplied_properties || obj.properties properties.some (property) -> property.id in ids diff --git a/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee b/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee index f3f4f51b5e..7eac12bf1e 100644 --- a/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee +++ b/app/assets/javascripts/darkswarm/filters/properties_of.js.coffee @@ -1,12 +1,12 @@ Darkswarm.filter 'propertiesOf', -> - (objects, source) -> - source ||= 'properties' - return {} unless source in ['properties', 'supplied_properties', 'distributed_properties'] - + (objects) -> properties = {} for object in objects - if object[source]? - for property in object[source] + if object.supplied_properties? + for property in object.supplied_properties + properties[property.id] = property + else + for property in object.properties properties[property.id] = property properties diff --git a/app/assets/stylesheets/darkswarm/_shop-filters.css.sass b/app/assets/stylesheets/darkswarm/_shop-filters.css.sass index 07fea7a0b1..3c4f9a514d 100644 --- a/app/assets/stylesheets/darkswarm/_shop-filters.css.sass +++ b/app/assets/stylesheets/darkswarm/_shop-filters.css.sass @@ -96,7 +96,7 @@ // content. Ensure that the dropdown appears above the content. .filter-row position: relative - z-index: 90 + z-index: 100 .filter-shopfront &.taxon-selectors, &.property-selectors diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index dad9cf11f9..6db2e583bc 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -45,7 +45,7 @@ module InjectionHelper end def inject_properties - inject_json_ams "properties", Spree::Property.all, Api::PropertySerializer + inject_json_ams "properties", Spree::Property.all, Api::IdNameSerializer end def inject_currency_config diff --git a/app/helpers/serializer_helper.rb b/app/helpers/serializer_helper.rb deleted file mode 100644 index 2e48e3741d..0000000000 --- a/app/helpers/serializer_helper.rb +++ /dev/null @@ -1,6 +0,0 @@ -module SerializerHelper - def ids_to_objs(ids) - return [] if ids.blank? - ids.map { |id| {id: id} } - end -end diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb index b0bb1b6e51..bf1f083936 100644 --- a/app/models/producer_property.rb +++ b/app/models/producer_property.rb @@ -8,18 +8,14 @@ class ProducerProperty < ActiveRecord::Base after_destroy :refresh_products_cache_from_destroy - scope :ever_sold_by, ->(shop) { + scope :sold_by, ->(shop) { joins(producer: {supplied_products: {variants: {exchanges: :order_cycle}}}). merge(Exchange.outgoing). merge(Exchange.to_enterprise(shop)). + merge(OrderCycle.active). select('DISTINCT producer_properties.*') } - scope :currently_sold_by, ->(shop) { - ever_sold_by(shop). - merge(OrderCycle.active) - } - def property_name property.name if property diff --git a/app/models/spree/property_decorator.rb b/app/models/spree/property_decorator.rb index 81577cef4e..50e450a03b 100644 --- a/app/models/spree/property_decorator.rb +++ b/app/models/spree/property_decorator.rb @@ -8,18 +8,14 @@ module Spree where('spree_product_properties.product_id IN (?)', enterprise.supplied_product_ids) } - scope :ever_sold_by, ->(shop) { + scope :sold_by, ->(shop) { joins(products: {variants: {exchanges: :order_cycle}}). merge(Exchange.outgoing). merge(Exchange.to_enterprise(shop)). + merge(OrderCycle.active). select('DISTINCT spree_properties.*') } - scope :currently_sold_by, ->(shop) { - ever_sold_by(shop). - merge(OrderCycle.active) - } - after_save :refresh_products_cache diff --git a/app/models/spree/taxon_decorator.rb b/app/models/spree/taxon_decorator.rb index 1878a20e49..a051de98fa 100644 --- a/app/models/spree/taxon_decorator.rb +++ b/app/models/spree/taxon_decorator.rb @@ -32,24 +32,21 @@ Spree::Taxon.class_eval do end # Find all the taxons of distributed products for each enterprise, indexed by enterprise. - # May return :all taxons (distributed in open and closed order cycles), - # or :current taxons (distributed in an open order cycle). - # # Format: {enterprise_id => [taxon_id, ...]} - def self.distributed_taxons(which_taxons=:all) - # TODO: Why can't we merge(Spree::Product.with_order_cycles_inner) here? - taxons = Spree::Taxon. - joins(products: {variants_including_master: {exchanges: :order_cycle}}). - merge(Exchange.outgoing). - select('spree_taxons.*, exchanges.receiver_id AS enterprise_id') + def self.distributed_taxons + taxons = {} - taxons = taxons.merge(OrderCycle.active) if which_taxons == :current + Spree::Taxon. + joins(:products). + merge(Spree::Product.with_order_cycles_outer). + where('o_exchanges.incoming = ?', false). + select('spree_taxons.*, o_exchanges.receiver_id AS enterprise_id'). + each do |t| + taxons[t.enterprise_id.to_i] ||= Set.new + taxons[t.enterprise_id.to_i] << t.id + end - taxons.inject({}) do |ts, t| - ts[t.enterprise_id.to_i] ||= Set.new - ts[t.enterprise_id.to_i] << t.id - ts - end + taxons end diff --git a/app/serializers/api/enterprise_serializer.rb b/app/serializers/api/enterprise_serializer.rb index 3537bcdd24..f68c8be679 100644 --- a/app/serializers/api/enterprise_serializer.rb +++ b/app/serializers/api/enterprise_serializer.rb @@ -20,10 +20,7 @@ class Api::EnterpriseSerializer < ActiveModel::Serializer end class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer - include SerializerHelper - attributes :orders_close_at, :active - attributes :taxons, :supplied_taxons has_many :supplied_properties, serializer: Api::PropertySerializer has_many :distributed_properties, serializer: Api::PropertySerializer @@ -45,37 +42,15 @@ class Api::UncachedEnterpriseSerializer < ActiveModel::Serializer def distributed_properties # This results in 3 queries per enterprise - - if active - product_properties = Spree::Property.currently_sold_by(object) - producer_property_ids = ProducerProperty.currently_sold_by(object).pluck(:property_id) - - else - product_properties = Spree::Property.ever_sold_by(object) - producer_property_ids = ProducerProperty.ever_sold_by(object).pluck(:property_id) - end - - producer_properties = Spree::Property.where(id: producer_property_ids) + product_properties = Spree::Property.sold_by(object) + ids = ProducerProperty.sold_by(object).pluck(:property_id) + producer_properties = Spree::Property.where(id: ids) OpenFoodNetwork::PropertyMerge.merge product_properties, producer_properties end - - def taxons - if active - ids_to_objs options[:data].current_distributed_taxons[object.id] - else - ids_to_objs options[:data].all_distributed_taxons[object.id] - end - end - - def supplied_taxons - ids_to_objs options[:data].supplied_taxons[object.id] - end end class Api::CachedEnterpriseSerializer < ActiveModel::Serializer - include SerializerHelper - cached #delegate :cache_key, to: :object @@ -90,7 +65,16 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer :email_address, :hash, :logo, :promo_image, :path, :pickup, :delivery, :icon, :icon_font, :producer_icon_font, :category, :producers, :hubs + attributes :taxons, :supplied_taxons + has_one :address, serializer: Api::AddressSerializer + def taxons + ids_to_objs options[:data].distributed_taxons[object.id] + end + + def supplied_taxons + ids_to_objs options[:data].supplied_taxons[object.id] + end def pickup services = options[:data].shipping_method_services[object.id] @@ -169,4 +153,12 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer } icon_fonts[object.category] end + + + private + + def ids_to_objs(ids) + return [] if ids.blank? + ids.map { |id| {id: id} } + end end diff --git a/app/serializers/api/property_serializer.rb b/app/serializers/api/property_serializer.rb index cdb3f2bae3..7da4fce990 100644 --- a/app/serializers/api/property_serializer.rb +++ b/app/serializers/api/property_serializer.rb @@ -1,9 +1,3 @@ class Api::PropertySerializer < ActiveModel::Serializer attributes :id, :name, :presentation - - # Client-side we don't care about the property name. Send the presentation - # since this is what we want to show to the user. - def name - object.presentation - end end diff --git a/app/views/groups/_hub_filters.html.haml b/app/views/groups/_hub_filters.html.haml new file mode 100644 index 0000000000..71924d5e85 --- /dev/null +++ b/app/views/groups/_hub_filters.html.haml @@ -0,0 +1,21 @@ +.row + = render partial: 'shared/components/filter_controls' + = render partial: 'shared/components/show_profiles' + +.row.animate-show{"ng-show" => "filtersActive"} + .small-12.columns + .row.filter-box + .small-12.large-9.columns + %h5.tdhead + .light + = t :hubs_filter_by + = t :hubs_filter_type + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{"selector-set" => "filterSelectors", objects: "group_hubs | searchEnterprises:query | shipping:shippingTypes | showHubProfiles:show_profiles | taxonsOf", "active-selectors" => "activeTaxons"} + .small-12.large-3.columns + %h5.tdhead + .light + = t :hubs_filter_by + = t :hubs_filter_delivery + %shipping-type-selector + += render partial: 'shared/components/filter_box' diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 90b74c0b42..ef9e281155 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -60,23 +60,23 @@ .small-12.columns %h1 = t :groups_producers - = render "shared/components/enterprise_search" - = render "producers/filters" + = render partial: "shared/components/enterprise_search" + = render partial: "producers/filters" .row .small-12.columns .active_table %producer.active_table_node.row.animate-repeat{id: "{{producer.path}}", - "ng-repeat" => "producer in filteredEnterprises = (group_producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')", + "ng-repeat" => "producer in filteredEnterprises = (group_producers | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties)", "ng-controller" => "GroupEnterpriseNodeCtrl", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}", id: "{{producer.hash}}"} .small-12.columns - = render "producers/skinny" - = render "producers/fat" + = render partial: 'producers/skinny' + = render partial: 'producers/fat' - = render 'shared/components/enterprise_no_results' + = render partial: 'shared/components/enterprise_no_results' %tab{heading: t(:groups_hubs), active: "tabs.hubs.active", @@ -87,24 +87,24 @@ %h1 = t :groups_hubs - = render "shared/components/enterprise_search" - = render "shops/filters", resource: "group_hubs", property_filters: "| searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles" + = render partial: "shared/components/enterprise_search" + = render partial: "hub_filters" .row .small-12.columns .active_table %hub.active_table_node.row.animate-repeat{id: "{{hub.hash}}", - "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | properties:activeProperties:'distributed_properties' | orderBy:['-active', '+orders_close_at'])", + "ng-repeat" => "hub in filteredEnterprises = (group_hubs | searchEnterprises:query | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "GroupEnterpriseNodeCtrl"} .small-12.columns - = render 'shops/skinny' - = render 'shops/fat' + = render partial: 'home/skinny' + = render partial: 'home/fat' - = render 'shared/components/enterprise_no_results' + = render partial: 'shared/components/enterprise_no_results' .small-12.medium-12.large-3.columns - = render 'contact' + = render partial: 'contact' .small-12.columns.pad-top .row.pad-top @@ -122,4 +122,4 @@ %p   -= render "shared/footer" += render partial: "shared/footer" diff --git a/app/views/shops/_fat.html.haml b/app/views/home/_fat.html.haml similarity index 100% rename from app/views/shops/_fat.html.haml rename to app/views/home/_fat.html.haml diff --git a/app/views/home/_filters.html.haml b/app/views/home/_filters.html.haml new file mode 100644 index 0000000000..bfd13fdf54 --- /dev/null +++ b/app/views/home/_filters.html.haml @@ -0,0 +1,22 @@ +.row + = render partial: 'shared/components/filter_controls' + -# .small-12.medium-6.columns   + = render partial: 'shared/components/show_profiles' + +.row.animate-show{"ng-show" => "filtersActive"} + .small-12.columns + .row.filter-box + .small-12.large-9.columns + %h5.tdhead + .light + = t :hubs_filter_by + = t :hubs_filter_type + %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "visibleMatches | visible | taxonsOf", "active-selectors" => "activeTaxons" } + .small-12.large-3.columns + %h5.tdhead + .light + = t :hubs_filter_by + = t :hubs_filter_delivery + %shipping-type-selector + += render partial: 'shared/components/filter_box' diff --git a/app/views/shops/_hubs.html.haml b/app/views/home/_hubs.html.haml similarity index 89% rename from app/views/shops/_hubs.html.haml rename to app/views/home/_hubs.html.haml index 6087d2330c..e899270efc 100644 --- a/app/views/shops/_hubs.html.haml +++ b/app/views/home/_hubs.html.haml @@ -7,14 +7,14 @@ = t :hubs_intro = render "shared/components/enterprise_search" - = render "filters" + = render "home/filters" .row .small-12.columns .name-matches{"ng-show" => "nameMatchesFiltered.length > 0"} %h2 = t :hubs_matches - = render "hubs_table", enterprises: "nameMatches" + = render "home/hubs_table", enterprises: "nameMatches" .distance-matches{"ng-if" => "nameMatchesFiltered.length == 0 || distanceMatchesShown"} %h2{"ng-show" => "nameMatchesFiltered.length > 0 || query.length > 0"} @@ -22,7 +22,7 @@ %span{"ng-show" => "nameMatchesFiltered.length > 0"} {{ nameMatchesFiltered[0].name }}... %span{"ng-hide" => "nameMatchesFiltered.length > 0"} {{ query }}... - = render "hubs_table", enterprises: "distanceMatches" + = render "home/hubs_table", enterprises: "distanceMatches" .show-distance-matches{"ng-show" => "nameMatchesFiltered.length > 0 && !distanceMatchesShown"} %a{href: "", "ng-click" => "showDistanceMatches()"} diff --git a/app/views/shops/_hubs_table.html.haml b/app/views/home/_hubs_table.html.haml similarity index 67% rename from app/views/shops/_hubs_table.html.haml rename to app/views/home/_hubs_table.html.haml index 6d5803b477..edf9eb5ec8 100644 --- a/app/views/shops/_hubs_table.html.haml +++ b/app/views/home/_hubs_table.html.haml @@ -1,10 +1,10 @@ .active_table - %hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | filter:filterExpression | taxons:activeTaxons | properties:activeProperties:'distributed_properties' | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])", + %hub.active_table_node.row{"ng-repeat" => "hub in #{enterprises}Filtered = (#{enterprises} | filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles | orderBy:['-active', '+distance', '+orders_close_at'])", "ng-class" => "{'is_profile' : hub.category == 'hub_profile', 'closed' : !open(), 'open' : open(), 'inactive' : !hub.active, 'current' : current()}", "ng-controller" => "HubNodeCtrl", id: "{{hub.hash}}"} .small-12.columns - = render 'skinny' - = render 'fat' + = render 'home/skinny' + = render 'home/fat' = render 'shared/components/enterprise_no_results', enterprises: "#{enterprises}Filtered" diff --git a/app/views/shops/_skinny.html.haml b/app/views/home/_skinny.html.haml similarity index 100% rename from app/views/shops/_skinny.html.haml rename to app/views/home/_skinny.html.haml diff --git a/app/views/producers/_filters.html.haml b/app/views/producers/_filters.html.haml index 17f260196a..771ed932c9 100644 --- a/app/views/producers/_filters.html.haml +++ b/app/views/producers/_filters.html.haml @@ -18,6 +18,6 @@ = t :producers_filter = t :producers_filter_property .filter-shopfront.property-selectors - %filter-selector{ "selector-set" => "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | taxons:activeTaxons | propertiesOf:'supplied_properties'", "active-selectors" => "activeProperties"} + %single-line-selectors{ selectors: "filterSelectors", objects: "producers_to_filter | searchEnterprises:query | propertiesOf", "active-selectors" => "activeProperties"} = render partial: 'shared/components/filter_box' diff --git a/app/views/producers/index.html.haml b/app/views/producers/index.html.haml index af6c2e4fd1..04048ef77e 100644 --- a/app/views/producers/index.html.haml +++ b/app/views/producers/index.html.haml @@ -16,7 +16,7 @@ .small-12.columns .active_table %producer.active_table_node.row.animate-repeat{id: "{{producer.path}}", - "ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | visible | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties:'supplied_properties')", + "ng-repeat" => "producer in filteredEnterprises = (Enterprises.producers | visible | searchEnterprises:query | taxons:activeTaxons | properties:activeProperties)", "ng-controller" => "ProducerNodeCtrl", "ng-class" => "{'closed' : !open(), 'open' : open(), 'inactive' : !producer.active}", id: "{{producer.hash}}"} diff --git a/app/views/shop/products/_filters.html.haml b/app/views/shop/products/_filters.html.haml index 10c7c20deb..7efaba6cc9 100644 --- a/app/views/shop/products/_filters.html.haml +++ b/app/views/shop/products/_filters.html.haml @@ -1,5 +1,5 @@ .filter-shopfront.taxon-selectors.text-right - %single-line-selectors{ selectors: "taxonSelectors", objects: "Products.products | products:query | properties:activeProperties | taxonsOf", "active-selectors" => "activeTaxons"} + %single-line-selectors{ selectors: "taxonSelectors", objects: "Products.products | products:query | properties: activeProperties | taxonsOf", "active-selectors" => "activeTaxons"} .filter-shopfront.property-selectors.text-right %single-line-selectors{ selectors: "propertySelectors", objects: "Products.products | products:query | taxons:activeTaxons | propertiesOf", "active-selectors" => "activeProperties"} diff --git a/app/views/shops/_filters.html.haml b/app/views/shops/_filters.html.haml deleted file mode 100644 index 42e2b2ec28..0000000000 --- a/app/views/shops/_filters.html.haml +++ /dev/null @@ -1,34 +0,0 @@ -- resource ||= "visibleMatches" -- property_filters ||= "| filter:filterExpression | taxons:activeTaxons | shipping:shippingTypes | showHubProfiles:show_profiles" - -.row - = render 'shared/components/filter_controls' - -# .small-12.medium-6.columns   - = render 'shared/components/show_profiles' - -.row.animate-show.filter-row{"ng-show" => "filtersActive"} - .small-12.columns - .row.filter-box - .small-12.large-9.columns - %h5.tdhead - .light - = t :hubs_filter_by - = t :hubs_filter_type - - %filter-selector.small-block-grid-2.medium-block-grid-4.large-block-grid-5{ "selector-set" => "filterSelectors", objects: "#{resource} | visible | taxonsOf", "active-selectors" => "activeTaxons" } - .small-12.large-3.columns - %h5.tdhead - .light - = t :hubs_filter_by - = t :hubs_filter_delivery - %shipping-type-selector - - .small-12.large-12.columns - %h5.tdhead - .light - = t :hubs_filter_by - = t :hubs_filter_property - .filter-shopfront.property-selectors - %filter-selector{ "selector-set" => "filterSelectors", objects: "#{resource} #{property_filters} | propertiesOf:'distributed_properties'", "active-selectors" => "activeProperties"} - -= render 'shared/components/filter_box' diff --git a/app/views/shops/index.html.haml b/app/views/shops/index.html.haml index 7e288f4157..1b3cf547a8 100644 --- a/app/views/shops/index.html.haml +++ b/app/views/shops/index.html.haml @@ -10,5 +10,5 @@ %p.text-big = t :shops_text -= render "hubs" -= render "shared/footer" += render partial: "home/hubs" += render partial: "shared/footer" diff --git a/config/locales/en.yml b/config/locales/en.yml index 991c308c2f..1d8707a7b9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -505,7 +505,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using hubs_filter_by: "Filter by" hubs_filter_type: "Type" hubs_filter_delivery: "Delivery" - hubs_filter_property: "Property" hubs_matches: "Did you mean?" hubs_intro: Shop in your local area hubs_distance: Closest to diff --git a/lib/open_food_network/enterprise_injection_data.rb b/lib/open_food_network/enterprise_injection_data.rb index 938c8b3aab..87516007c6 100644 --- a/lib/open_food_network/enterprise_injection_data.rb +++ b/lib/open_food_network/enterprise_injection_data.rb @@ -20,12 +20,8 @@ module OpenFoodNetwork @supplied_taxons ||= Spree::Taxon.supplied_taxons end - def all_distributed_taxons - @all_distributed_taxons ||= Spree::Taxon.distributed_taxons(:all) - end - - def current_distributed_taxons - @current_distributed_taxons ||= Spree::Taxon.distributed_taxons(:current) + def distributed_taxons + @distributed_taxons ||= Spree::Taxon.distributed_taxons end end end diff --git a/spec/features/consumer/groups_spec.rb b/spec/features/consumer/groups_spec.rb index 4a5f166d7d..039322b379 100644 --- a/spec/features/consumer/groups_spec.rb +++ b/spec/features/consumer/groups_spec.rb @@ -54,43 +54,4 @@ feature 'Groups', js: true do end end end - - describe "shops" do - describe "filtering by product property" do - let!(:group) { create(:enterprise_group, enterprises: [d1, d2], on_front_page: true) } - let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } - let(:producer) { create(:supplier_enterprise) } - let(:d1) { create(:distributor_enterprise) } - let(:d2) { create(:distributor_enterprise) } - let(:p1) { create(:simple_product, supplier: producer) } - let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } - let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } - let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } - - before do - producer.set_producer_property 'Organic', 'NASAA 12345' - p2.set_property 'Local', 'XYZ 123' - - ex_d1.variants << p1.variants.first - ex_d2.variants << p2.variants.first - - visit group_path(group, anchor: "/hubs") - end - - it "filters" do - toggle_filters - - toggle_filter 'Organic' - - expect(page).to have_content d1.name - expect(page).not_to have_content d2.name - - toggle_filter 'Organic' - toggle_filter 'Local' - - expect(page).not_to have_content d1.name - expect(page).to have_content d2.name - end - end - end end diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index f8f54a197b..2a65a73aef 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -47,7 +47,7 @@ feature 'Shops', js: true do it "should show closed shops after clicking the button" do create(:simple_product, distributors: [d1, d2]) visit shops_path - click_link_and_ensure("Show Closed Shops", -> { page.has_selector? 'hub.inactive' }) + click_link_and_ensure("Show closed shops", -> { page.has_selector? 'hub.inactive' }) page.should have_selector 'hub.inactive', text: d2.name end @@ -56,67 +56,6 @@ feature 'Shops', js: true do expect(page).to have_current_path enterprise_shop_path(distributor) end - describe "filtering by product property" do - let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } - let!(:p1) { create(:simple_product, supplier: producer) } - let!(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } - let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } - let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } - - before do - p2.set_property 'Local', 'XYZ 123' - - ex_d1.variants << p1.variants.first - ex_d2.variants << p2.variants.first - - visit shops_path - end - - it "filters" do - toggle_filters - - toggle_filter 'Organic' - - expect(page).to have_content d1.name - expect(page).not_to have_content d2.name - - toggle_filter 'Organic' - toggle_filter 'Local' - - expect(page).not_to have_content d1.name - expect(page).to have_content d2.name - end - end - - describe "taxon badges" do - let!(:closed_oc) { create(:closed_order_cycle, distributors: [shop], variants: [p_closed.variants.first]) } - let!(:p_closed) { create(:simple_product, taxons: [taxon_closed]) } - let(:shop) { create(:distributor_enterprise) } - let(:taxon_closed) { create(:taxon, name: 'Closed') } - - describe "open shops" do - let!(:open_oc) { create(:open_order_cycle, distributors: [shop], variants: [p_open.variants.first]) } - let!(:p_open) { create(:simple_product, taxons: [taxon_open]) } - let(:taxon_open) { create(:taxon, name: 'Open') } - - it "shows taxons for open order cycles only" do - visit shops_path - expand_active_table_node shop.name - expect(page).to have_selector '.fat-taxons', text: 'Open' - expect(page).not_to have_selector '.fat-taxons', text: 'Closed' - end - end - - describe "closed shops" do - it "shows taxons for any order cycle" do - visit shops_path - click_link 'Show Closed Shops' - expand_active_table_node shop.name - expect(page).to have_selector '.fat-taxons', text: 'Closed' - end - end - end - describe "property badges" do let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), variants: [product.variants.first]) } let(:product) { create(:simple_product, supplier: producer) } diff --git a/spec/models/producer_property_spec.rb b/spec/models/producer_property_spec.rb index 0de7aae19b..2d0009ce12 100644 --- a/spec/models/producer_property_spec.rb +++ b/spec/models/producer_property_spec.rb @@ -8,7 +8,7 @@ describe ProducerProperty do producer.set_producer_property 'Organic Certified', 'NASAA 54321' end - describe ".currently_sold_by and .ever_sold_by" do + describe ".sold_by" do let!(:shop) { create(:distributor_enterprise) } let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } let(:product) { create(:simple_product, supplier: producer) } @@ -22,8 +22,7 @@ describe ProducerProperty do describe "with an associated producer property" do it "returns the producer property" do - expect(ProducerProperty.currently_sold_by(shop)).to eq [pp] - expect(ProducerProperty.ever_sold_by(shop)).to eq [pp] + expect(ProducerProperty.sold_by(shop)).to eq [pp] end end @@ -31,8 +30,7 @@ describe ProducerProperty do let!(:exchange) { create(:exchange, order_cycle: oc, incoming: true, sender: producer_other, receiver: oc.coordinator) } it "doesn't return the producer property" do - expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other - expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other + expect(ProducerProperty.sold_by(shop)).not_to include pp_other end end @@ -42,8 +40,7 @@ describe ProducerProperty do let!(:exchange) { create(:exchange, order_cycle: oc, incoming: false, sender: oc.coordinator, receiver: shop_other, variants: [product_other.variants.first]) } it "doesn't return the producer property" do - expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other - expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other + expect(ProducerProperty.sold_by(shop)).not_to include pp_other end end @@ -52,12 +49,8 @@ describe ProducerProperty do oc.update_attributes! orders_close_at: 1.week.ago end - it "doesn't return the producer property for .currently_sold_by" do - expect(ProducerProperty.currently_sold_by(shop)).not_to include pp - end - - it "returns the producer property for .ever_sold_by" do - expect(ProducerProperty.ever_sold_by(shop)).to include pp + it "doesn't return the producer property" do + expect(ProducerProperty.sold_by(shop)).not_to include pp end end @@ -66,8 +59,7 @@ describe ProducerProperty do let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) } it "doesn't return duplicates" do - expect(ProducerProperty.currently_sold_by(shop).to_a.count).to eq 1 - expect(ProducerProperty.ever_sold_by(shop).to_a.count).to eq 1 + expect(ProducerProperty.sold_by(shop).to_a.count).to eq 1 end end end diff --git a/spec/models/spree/property_spec.rb b/spec/models/spree/property_spec.rb index 29046a8782..6e6ed2d780 100644 --- a/spec/models/spree/property_spec.rb +++ b/spec/models/spree/property_spec.rb @@ -31,53 +31,42 @@ module Spree end end - describe ".currently_sold_by and .ever_sold_by" do + describe ".sold_by" do let!(:shop) { create(:distributor_enterprise) } let!(:shop_other) { create(:distributor_enterprise) } let!(:product) { create(:simple_product) } let!(:product_other_ex) { create(:simple_product) } let!(:product_no_oc) { create(:simple_product) } + let!(:product_closed_oc) { create(:simple_product) } let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } + let!(:oc_closed) { create(:closed_order_cycle, distributors: [shop], variants: [product_closed_oc.variants.first]) } let!(:exchange_other_shop) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: shop_other, variants: [product_other_ex.variants.first]) } let(:property) { product.properties.last } let(:property_other_ex) { product_other_ex.properties.last } let(:property_no_oc) { product_no_oc.properties.last } + let(:property_closed_oc) { product_closed_oc.properties.last } before do product.set_property 'Organic', 'NASAA 12345' product_other_ex.set_property 'Biodynamic', 'ASDF 12345' product_no_oc.set_property 'Shiny', 'Very' + product_closed_oc.set_property 'Spiffy', 'Ooh yeah' end it "returns the property" do - expect(Property.currently_sold_by(shop)).to eq [property] - expect(Property.ever_sold_by(shop)).to eq [property] + expect(Property.sold_by(shop)).to eq [property] end it "doesn't return the property from another exchange" do - expect(Property.currently_sold_by(shop)).not_to include property_other_ex - expect(Property.ever_sold_by(shop)).not_to include property_other_ex + expect(Property.sold_by(shop)).not_to include property_other_ex end it "doesn't return the property with no order cycle" do - expect(Property.currently_sold_by(shop)).not_to include property_no_oc - expect(Property.ever_sold_by(shop)).not_to include property_no_oc + expect(Property.sold_by(shop)).not_to include property_no_oc end - describe "closed order cyces" do - let!(:product_closed_oc) { create(:simple_product) } - let!(:oc_closed) { create(:closed_order_cycle, distributors: [shop], variants: [product_closed_oc.variants.first]) } - let(:property_closed_oc) { product_closed_oc.properties.last } - - before { product_closed_oc.set_property 'Spiffy', 'Ooh yeah' } - - it "doesn't return the property for .currently_sold_by" do - expect(Property.currently_sold_by(shop)).not_to include property_closed_oc - end - - it "returns the property for .ever_sold_by" do - expect(Property.ever_sold_by(shop)).to include property_closed_oc - end + it "doesn't return the property from a closed order cycle" do + expect(Property.sold_by(shop)).not_to include property_closed_oc end context "with another product in the order cycle" do @@ -89,8 +78,7 @@ module Spree end it "doesn't return duplicates" do - expect(Property.currently_sold_by(shop).to_a.count).to eq 1 - expect(Property.ever_sold_by(shop).to_a.count).to eq 1 + expect(Property.sold_by(shop).to_a.count).to eq 1 end end end diff --git a/spec/models/spree/taxon_spec.rb b/spec/models/spree/taxon_spec.rb index 873a201013..8fb4b22dc5 100644 --- a/spec/models/spree/taxon_spec.rb +++ b/spec/models/spree/taxon_spec.rb @@ -29,18 +29,13 @@ module Spree end end - describe "finding distributed taxons" do - let!(:oc_open) { create(:open_order_cycle, distributors: [e], variants: [p_open.variants.first]) } - let!(:oc_closed) { create(:closed_order_cycle, distributors: [e], variants: [p_closed.variants.first]) } - let!(:p_open) { create(:simple_product, primary_taxon: t1) } - let!(:p_closed) { create(:simple_product, primary_taxon: t2) } + describe "finding all distributed taxons" do + let!(:oc) { create(:simple_order_cycle, distributors: [e], variants: [p1.master]) } + let!(:s) { create(:supplier_enterprise) } + let!(:p1) { create(:simple_product, supplier: s, taxons: [t1, t2]) } - it "finds all distributed taxons" do - expect(Taxon.distributed_taxons(:all)).to eq({e.id => Set.new([t1.id, t2.id])}) - end - - it "finds currently distributed taxons" do - expect(Taxon.distributed_taxons(:current)).to eq({e.id => Set.new([t1.id])}) + it "finds taxons" do + Taxon.distributed_taxons.should == {e.id => Set.new(p1.taxons.map(&:id))} end end end diff --git a/spec/serializers/enterprise_serializer_spec.rb b/spec/serializers/enterprise_serializer_spec.rb index bea2672157..f5eff4f771 100644 --- a/spec/serializers/enterprise_serializer_spec.rb +++ b/spec/serializers/enterprise_serializer_spec.rb @@ -6,8 +6,7 @@ describe Api::EnterpriseSerializer do let(:taxon) { create(:taxon) } let(:data) { OpenStruct.new(earliest_closing_times: {}, active_distributors: [], - all_distributed_taxons: {enterprise.id => [123]}, - current_distributed_taxons: {enterprise.id => [123]}, + distributed_taxons: {enterprise.id => [123]}, supplied_taxons: {enterprise.id => [456]}, shipping_method_services: {}, relatives: {enterprise.id => {producers: [123], distributors: [456]}}) } From 23a216004ef58ccbd25679aa9909c59b4e4d9f32 Mon Sep 17 00:00:00 2001 From: Transifex-Openfoodnetwork Date: Tue, 20 Sep 2016 01:02:27 +1000 Subject: [PATCH 25/25] Updating translations for config/locales/en_GB.yml [skip ci] --- config/locales/en_GB.yml | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml index 41e3643699..611481720c 100644 --- a/config/locales/en_GB.yml +++ b/config/locales/en_GB.yml @@ -215,6 +215,8 @@ en_GB: label_producers: "Producers" label_groups: "Groups" label_about: "About" + label_connect: "Connect" + label_learn: "Learn" label_shopping: "Shopping" label_login: "Login" label_logout: "Logout" @@ -264,10 +266,8 @@ en_GB: footer_contact_email: "Email us" footer_nav_headline: "Navigate" footer_join_headline: "Join us" - footer_join_producers: "Producers sign-up" - footer_join_hubs: "Hubs sign-up" - footer_join_groups: "Groups sign-up" - footer_join_partners: "Food systems partners" + footer_join_body: "Create a listing, shop or group directory on the Open Food Network." + footer_join_cta: "Tell me more!" footer_legal_call: "Read our" footer_legal_tos: "Terms and conditions" footer_legal_visit: "Find us on" @@ -281,7 +281,11 @@ en_GB: brandstory_part4: "It works everywhere. It changes everything." brandstory_part5_strong: "We call it Open Food Network." brandstory_part6: "We all love food. Now we can love our food system too." - system_headline: "Here's how it works." + learn_body: "Explore models, stories and resources to support you to develop your fair food business or organisation. Find training, events and other opportunities to learn from peers." + learn_cta: "Get Inspired" + connect_body: "Search our full directories of producers, hubs and groups to find fair food traders near you. List your business or organisation on the OFN so buyers can find you. Join the community to get advice and solve problems together." + connect_cta: "Go Exploring" + system_headline: "Shopping - here's how it works." system_step1: "1. Search" system_step1_text: "Search our diverse, independent shops for seasonal local food. Search by neighbourhood and food category, or whether you prefer delivery or pickup." system_step2: "2. Shop" @@ -487,24 +491,6 @@ en_GB: modal_how_more_explained: "If you want to learn more about the Open Food Network, how it works, and get involved, check out:" modal_producers: "Producers" modal_producers_explained: "Our producers make all the delicious food you can shop for on the Open Food Network." - ocs_choice_hub: "Hub:" - ocs_choice_oc: "Order Cycle:" - ocs_choice_text: "You have not yet picked where you will get your order from." - ocs_closed_headline: Orders are currently closed for this hub - ocs_closed_time: "The last cycle closed %{time} ago." - ocs_closed_contact: "Please contact your hub directly to see if they accept late orders, or wait until the next cycle opens." - ocs_closed_opens: "The next order cycle opens in %{time}" - ocs_closed_email: "Email: %{email}" - ocs_closed_phone: "Phone: %{phone}" - ocs_pickup_time: "Your order will be ready on %{pickup_time}" - ocs_change_date: "Change Collection Date" - ocs_change_date_notice: "(This will reset your cart)" - ocs_close_time: "ORDERS CLOSE" - ocs_when_headline: When do you want your order? - ocs_when_text: No products are displayed until you select a date. - ocs_when_closing: "Closing on" - ocs_when_choose: "Choose Order Cycle" - ocs_list: "List view" producers_about: About us producers_buy: Shop for producers_contact: Contact @@ -513,6 +499,7 @@ en_GB: producers_buy_at_html: "Shop for %{enterprise} products at:" producers_filter: Filter by producers_filter_type: Type + producers_filter_property: Property producers_title: Producers producers_headline: Find local producers producers_signup_title: Sign up as a producer @@ -532,6 +519,19 @@ en_GB: products_producer: "Producer" products_price: "Price" register_title: Register + sell_title: "Register" + sell_headline: "Get on the Open Food Network!" + sell_motivation: "Showcase your beautiful food." + sell_producers: "Producers" + sell_hubs: "Hubs" + sell_groups: "Groups" + sell_producers_detail: "Set up a profile for your business on the OFN in just minutes. At any time you can upgrade your profile to an online store and sell your products direct to customers." + sell_hubs_detail: "Set up a profile for your food enterprise or organisation on the OFN. At any time you can upgrade your profile to a multi-producer shop." + sell_groups_detail: "Set up a tailored directory of enterprises (producers and other food enterprises) for your region or for your organisation." + sell_user_guide: "Find out more in our user guide." + sell_listing_price: "Listing on OFN is free. Opening and running a shop on OFN is free for six months and always free for small enterprises. We charge just 2% of sales for enterprises turning over more than £5000/year." + sell_embed: "We can also embed an OFN shop in your own customised website or build a customised local food network website for your region." + sell_ask_services: "Ask us about OFN services." shops_title: Shops shops_headline: Shopping, transformed. shops_text: Food grows in cycles, farmers harvest in cycles, and we order food in cycles. If you find an order cycle closed, check back soon.