Merge remote-tracking branch 'upstream/master' into dev/issue-328

# Conflicts:
#	CHANGELOG.md
#	src/components/RecipeView.vue
This commit is contained in:
Christian Wolf 2020-11-10 19:04:12 +01:00
Родитель 9d87baf18c d8807ddbd7
Коммит a779bc8100
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 9FC3120E932F73F1
39 изменённых файлов: 252 добавлений и 12 удалений

2
.github/actions/run-tests/tests/install.sh поставляемый
Просмотреть файл

@ -18,7 +18,7 @@ function configure_gd_without ()
function configure_gd()
{
if [ "$1" = "7.2" ]; then
if [ "$1" = "7.2" -o "$1" = "7.3" ]; then
configure_gd_without
return $?
else

Просмотреть файл

@ -17,12 +17,17 @@
[#366](https://github.com/nextcloud/cookbook/pull/366/) @christianlupus
- Enfoce update of changelog through CI
[#366](https://github.com/nextcloud/cookbook/pull/366/) @christianlupus
- Keyword cloud is displayed in recipe
[#373](https://github.com/nextcloud/cookbook/pull/373/) @seyfeb
### Changed
- Switch of project ownership to neextcloud organization in GitHub
- Chanage in issue managment
- Changes to `.gitignore` file
- Translation issues
- Added available Android apps to README
- Update dev dependencies to recent phpunit to avoid warnings and issues
[#376](https://github.com/nextcloud/cookbook/pull/376) @christianlupus
- Made the layout more responsive to shift the metadata right of the image in very wide screens
[#349](https://github.com/nextcloud/cookbook/pull/349/) @christianlupus
@ -45,6 +50,10 @@
[#350](https://github.com/nextcloud/cookbook/pull/350) @maxammann
- Make complete sentence in transifex translation from parts
[#358](https://github.com/nextcloud/cookbook/pull/358) @christianlupus
- Avoid recipe are no longer reachable when user changes locales
[#371](https://github.com/nextcloud/cookbook/pull/371) @christianlupus
- Hide tooltips in printouts
[#343](https://github.com/nextcloud/cookbook/pull/343/) @christianlupus
### Removed
- Travis build system
@ -58,4 +67,4 @@
### Fixed
- Swapping ingredients and instructions cause items been deleted
[#278](https://github.com/nextcloud/cookbook/pull/278) @sam-19
[#278](https://github.com/nextcloud/cookbook/pull/278) @sam-19

Просмотреть файл

@ -8,6 +8,14 @@
A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings.
## Clients
### Android
The currently available clients are
- Nextcloud Cookbook (by MicMun) ([Google Play](https://play.google.com/store/apps/details?id=de.micmun.android.nextcloudcookbook&hl=en_US&gl=US), [FDroid](https://f-droid.org/en/packages/de.micmun.android.nextcloudcookbook/), [homepage](https://micmun.de/nextcloud-cookbook-english/))
- Nextcloud Cookbook (by Teifun2) ([Google Play](https://play.google.com/store/apps/details?id=com.nextcloud_cookbook_flutter&hl=en_US&gl=US))
## Join the discussion
* [#nextcloud-cookbook:matrix.org](https://matrix.to/#/#nextcloud-cookbook:matrix.org)

Просмотреть файл

@ -26,6 +26,7 @@ return [
['name' => 'config#config', 'url' => '/config', 'verb' => 'POST'],
/* API routes */
['name' => 'main#category', 'url' => '/api/category/{category}', 'verb' => 'GET'],
['name' => 'main#tags', 'url' => '/api/tags/{keywords}', 'verb' => 'GET'],
['name' => 'main#search', 'url' => '/api/search/{query}', 'verb' => 'GET'],
],

Просмотреть файл

@ -12,6 +12,7 @@
"ext-libxml": "*"
},
"require-dev": {
"phpunit/phpunit": "^5.4"
"phpunit/phpunit": ">=8.0",
"nikic/php-parser": "4.2"
}
}

Просмотреть файл

@ -7,6 +7,7 @@ OC.L10N.register(
"Save changes" : "حفظ التعديلات",
"Loading…" : "التحميل جارٍ…",
"Category" : "الفئة",
"Uncategorized recipes" : "وصفات غير مصنفة",
"Add" : "إضافة",
"Name" : "الاسم",
"Description" : "الوصف",

Просмотреть файл

@ -5,6 +5,7 @@
"Save changes" : "حفظ التعديلات",
"Loading…" : "التحميل جارٍ…",
"Category" : "الفئة",
"Uncategorized recipes" : "وصفات غير مصنفة",
"Add" : "إضافة",
"Name" : "الاسم",
"Description" : "الوصف",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Skrýt navigační panel",
"Create recipe" : "Vytvořit recept",
"Download recipe from URL" : "Stáhnout si recept z URL adresy",
"Uncategorized recipes" : "Nezařazené recepty",
"Rescan library" : "Znovu projít knihovnu",
"Recipe folder" : "Složka pro recepty",
"Please pick a folder" : "Vyberte složku",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Skrýt navigační panel",
"Create recipe" : "Vytvořit recept",
"Download recipe from URL" : "Stáhnout si recept z URL adresy",
"Uncategorized recipes" : "Nezařazené recepty",
"Rescan library" : "Znovu projít knihovnu",
"Recipe folder" : "Složka pro recepty",
"Please pick a folder" : "Vyberte složku",

Просмотреть файл

@ -4,7 +4,7 @@ OC.L10N.register(
"Recipes" : "Rezepte",
"Cookbook" : "Kochbuch",
"An integrated cookbook using schema.org JSON files as recipes" : "Ein integriertes Kochbuch, das schema.org-JSON-Dateien als Speicher für Rezepte verwendet",
"A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings." : "Eine Bibliothek für all Deine Rezepte. Sie nutzt JSON-Dateien, die dem schema.org-Standard für Rezepte folgen. Um weitere Rezepte zu der Sammlung hinzuzufügen, kann die URL des Rezepts eingefügt werden, so dass die Internetseite heruntergeladen, verarbeitet und in einem benutzerspezifizierten Ordner abgelegt wird.",
"A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings." : "Eine Bibliothek für all Deine Rezepte. Sie nutzt JSON-Dateien, die dem schema.org-Standard für Rezepte folgen. Um weitere Rezepte zu der Sammlung hinzuzufügen, kann die URL des Rezepts eingefügt werden, so dass die Internetseite heruntergeladen, verarbeitet und in einem benutzerspezifizierten Verzeichnis abgelegt wird.",
"Open navigation" : "Navigation öffnen",
"Home" : "Zuhause",
"All recipes" : "Alle Rezepte",
@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Navigation ausblenden",
"Create recipe" : "Neues Rezept anlegen",
"Download recipe from URL" : "Rezept von URL herunterladen",
"Uncategorized recipes" : "Nicht kategorisierte Rezepte",
"Rescan library" : "Bibliothek neu einlesen",
"Recipe folder" : "Rezept-Ordner",
"Please pick a folder" : "Bitte einen Ordner auswählen",

Просмотреть файл

@ -2,7 +2,7 @@
"Recipes" : "Rezepte",
"Cookbook" : "Kochbuch",
"An integrated cookbook using schema.org JSON files as recipes" : "Ein integriertes Kochbuch, das schema.org-JSON-Dateien als Speicher für Rezepte verwendet",
"A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings." : "Eine Bibliothek für all Deine Rezepte. Sie nutzt JSON-Dateien, die dem schema.org-Standard für Rezepte folgen. Um weitere Rezepte zu der Sammlung hinzuzufügen, kann die URL des Rezepts eingefügt werden, so dass die Internetseite heruntergeladen, verarbeitet und in einem benutzerspezifizierten Ordner abgelegt wird.",
"A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings." : "Eine Bibliothek für all Deine Rezepte. Sie nutzt JSON-Dateien, die dem schema.org-Standard für Rezepte folgen. Um weitere Rezepte zu der Sammlung hinzuzufügen, kann die URL des Rezepts eingefügt werden, so dass die Internetseite heruntergeladen, verarbeitet und in einem benutzerspezifizierten Verzeichnis abgelegt wird.",
"Open navigation" : "Navigation öffnen",
"Home" : "Zuhause",
"All recipes" : "Alle Rezepte",
@ -28,6 +28,7 @@
"Hide navigation" : "Navigation ausblenden",
"Create recipe" : "Neues Rezept anlegen",
"Download recipe from URL" : "Rezept von URL herunterladen",
"Uncategorized recipes" : "Nicht kategorisierte Rezepte",
"Rescan library" : "Bibliothek neu einlesen",
"Recipe folder" : "Rezept-Ordner",
"Please pick a folder" : "Bitte einen Ordner auswählen",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Navigation ausblenden",
"Create recipe" : "Neues Rezept anlegen",
"Download recipe from URL" : "Rezept von URL herunterladen",
"Uncategorized recipes" : "Nicht kategorisierte Rezepte",
"Rescan library" : "Bibliothek neu einlesen",
"Recipe folder" : "Rezept-Ordner",
"Please pick a folder" : "Bitte einen Ordner auswählen",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Navigation ausblenden",
"Create recipe" : "Neues Rezept anlegen",
"Download recipe from URL" : "Rezept von URL herunterladen",
"Uncategorized recipes" : "Nicht kategorisierte Rezepte",
"Rescan library" : "Bibliothek neu einlesen",
"Recipe folder" : "Rezept-Ordner",
"Please pick a folder" : "Bitte einen Ordner auswählen",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Esconder navegación",
"Create recipe" : "Crear nueva receta",
"Download recipe from URL" : "Descargar receta desde URL",
"Uncategorized recipes" : "Recetas sin categoría",
"Rescan library" : "Releer biblioteca",
"Recipe folder" : "Carpeta de recetas",
"Please pick a folder" : "Seleccionar una carpeta",
@ -39,6 +40,8 @@ OC.L10N.register(
"Could not set preference for image printing" : "No se pudo ajustar las preferencias para impresión de imágenes",
"Could not set recipe update interval to {interval}" : "No se puede ajustar el intervalo de actualización de la receta a {interval}",
"Loading config failed" : "Fallo al cargar la configuración",
"Failed to load category {category} recipes" : "Error al cargar la categoría {category} de las recetas",
"Loading category recipes …" : "Cargando las categorías de las recetas...",
"Failed to fetch categories" : "Fallo al buscar las categorías",
"Path to your recipe collection" : "Ruta a tu colección de recetas",
"Could not set recipe folder to {path}" : "No fue posible establecer {path} como ruta para la carpeta de recetas",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Esconder navegación",
"Create recipe" : "Crear nueva receta",
"Download recipe from URL" : "Descargar receta desde URL",
"Uncategorized recipes" : "Recetas sin categoría",
"Rescan library" : "Releer biblioteca",
"Recipe folder" : "Carpeta de recetas",
"Please pick a folder" : "Seleccionar una carpeta",
@ -37,6 +38,8 @@
"Could not set preference for image printing" : "No se pudo ajustar las preferencias para impresión de imágenes",
"Could not set recipe update interval to {interval}" : "No se puede ajustar el intervalo de actualización de la receta a {interval}",
"Loading config failed" : "Fallo al cargar la configuración",
"Failed to load category {category} recipes" : "Error al cargar la categoría {category} de las recetas",
"Loading category recipes …" : "Cargando las categorías de las recetas...",
"Failed to fetch categories" : "Fallo al buscar las categorías",
"Path to your recipe collection" : "Ruta a tu colección de recetas",
"Could not set recipe folder to {path}" : "No fue posible establecer {path} como ruta para la carpeta de recetas",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Masquer la navigation",
"Create recipe" : "Créer une recette",
"Download recipe from URL" : "Télécharger la recette depuis l'URL",
"Uncategorized recipes" : "Recettes non catégorisées",
"Rescan library" : "Rescanner la bibliothèque",
"Recipe folder" : "Dossier des recettes",
"Please pick a folder" : "Veuillez choisir un dossier",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Masquer la navigation",
"Create recipe" : "Créer une recette",
"Download recipe from URL" : "Télécharger la recette depuis l'URL",
"Uncategorized recipes" : "Recettes non catégorisées",
"Rescan library" : "Rescanner la bibliothèque",
"Recipe folder" : "Dossier des recettes",
"Please pick a folder" : "Veuillez choisir un dossier",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Agochar a navegación",
"Create recipe" : "Crear unha receita",
"Download recipe from URL" : "Descargar a receita do URL",
"Uncategorized recipes" : "Receitas sen categorizar",
"Rescan library" : "Volver escanear a biblioteca",
"Recipe folder" : "Cartafol de receitas",
"Please pick a folder" : "Escolla un cartafol",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Agochar a navegación",
"Create recipe" : "Crear unha receita",
"Download recipe from URL" : "Descargar a receita do URL",
"Uncategorized recipes" : "Receitas sen categorizar",
"Rescan library" : "Volver escanear a biblioteca",
"Recipe folder" : "Cartafol de receitas",
"Please pick a folder" : "Escolla un cartafol",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Nascondi navigazione",
"Create recipe" : "Crea ricetta",
"Download recipe from URL" : "Scarica ricetta da URL",
"Uncategorized recipes" : "Ricette senza categoria",
"Rescan library" : "Nuova scansione raccolta",
"Recipe folder" : "Cartella delle ricette",
"Please pick a folder" : "Scegli una cartella",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Nascondi navigazione",
"Create recipe" : "Crea ricetta",
"Download recipe from URL" : "Scarica ricetta da URL",
"Uncategorized recipes" : "Ricette senza categoria",
"Rescan library" : "Nuova scansione raccolta",
"Recipe folder" : "Cartella delle ricette",
"Please pick a folder" : "Scegli una cartella",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Slėpti naršymą",
"Create recipe" : "Sukurti receptą",
"Download recipe from URL" : "Atsisiųsti receptą iš URL",
"Uncategorized recipes" : "Nekategorizuoti receptai",
"Rescan library" : "Peržiūrėti biblioteką iš naujo",
"Recipe folder" : "Receptų aplankas",
"Please pick a folder" : "Pasirinkite aplanką",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Slėpti naršymą",
"Create recipe" : "Sukurti receptą",
"Download recipe from URL" : "Atsisiųsti receptą iš URL",
"Uncategorized recipes" : "Nekategorizuoti receptai",
"Rescan library" : "Peržiūrėti biblioteką iš naujo",
"Recipe folder" : "Receptų aplankas",
"Please pick a folder" : "Pasirinkite aplanką",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Ukryj nawigację",
"Create recipe" : "Stwórz przepis",
"Download recipe from URL" : "Pobierz przepis z adresu URL",
"Uncategorized recipes" : "Przepisy bez kategorii",
"Rescan library" : "Skanowanie biblioteki",
"Recipe folder" : "Folder przepisu",
"Please pick a folder" : "Proszę wybierać folder",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Ukryj nawigację",
"Create recipe" : "Stwórz przepis",
"Download recipe from URL" : "Pobierz przepis z adresu URL",
"Uncategorized recipes" : "Przepisy bez kategorii",
"Rescan library" : "Skanowanie biblioteki",
"Recipe folder" : "Folder przepisu",
"Please pick a folder" : "Proszę wybierać folder",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Ocultar navegação",
"Create recipe" : "Criar receita",
"Download recipe from URL" : "Baixar a receita da URL",
"Uncategorized recipes" : "Receitas sem categoria",
"Rescan library" : "Verificar biblioteca novamente",
"Recipe folder" : "Pasta da receita",
"Please pick a folder" : "Escolha uma pasta",
@ -39,6 +40,8 @@ OC.L10N.register(
"Could not set preference for image printing" : "Não foi possível definir a preferência para impressão de imagem",
"Could not set recipe update interval to {interval}" : "Não foi possível definir o intervalo de atualização da receita para {interval}",
"Loading config failed" : "Erro ao carregar a configuração",
"Failed to load category {category} recipes" : "Não foi possível carregar as receitas da categoria {category}",
"Loading category recipes …" : "Carregando receitas da categoria...",
"Failed to fetch categories" : "Erro ao obter categorias",
"Path to your recipe collection" : "Caminho para sua coleção de receitas",
"Could not set recipe folder to {path}" : "Não foi possível definir a pasta de receitas para {path}",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Ocultar navegação",
"Create recipe" : "Criar receita",
"Download recipe from URL" : "Baixar a receita da URL",
"Uncategorized recipes" : "Receitas sem categoria",
"Rescan library" : "Verificar biblioteca novamente",
"Recipe folder" : "Pasta da receita",
"Please pick a folder" : "Escolha uma pasta",
@ -37,6 +38,8 @@
"Could not set preference for image printing" : "Não foi possível definir a preferência para impressão de imagem",
"Could not set recipe update interval to {interval}" : "Não foi possível definir o intervalo de atualização da receita para {interval}",
"Loading config failed" : "Erro ao carregar a configuração",
"Failed to load category {category} recipes" : "Não foi possível carregar as receitas da categoria {category}",
"Loading category recipes …" : "Carregando receitas da categoria...",
"Failed to fetch categories" : "Erro ao obter categorias",
"Path to your recipe collection" : "Caminho para sua coleção de receitas",
"Could not set recipe folder to {path}" : "Não foi possível definir a pasta de receitas para {path}",

Просмотреть файл

@ -5,6 +5,7 @@ OC.L10N.register(
"Cookbook" : "Kuhar'ca",
"An integrated cookbook using schema.org JSON files as recipes" : "Kuharica v oblaku, ki omogoča prikaz datotek receptov schema.org JSON",
"A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings." : "Zbirka vaših receptov uporablja datoteke JSON, ki so oblikovani po predlogi schema.org. Za dodajanje recepta v zbirko, lahko enostavno prilepite naslov URL recepta in vsebina bo razčlenjena in shranjena v ciljno mapo v vašem oblaku.",
"Open navigation" : "Odpri bočno okno",
"Home" : "Začetna stran",
"All recipes" : "Vsi recepti",
"Filter" : "Filter",
@ -26,8 +27,10 @@ OC.L10N.register(
"Search for recipes" : "Iskanje med recepti",
"Are you sure you want to delete this recipe?" : "Ali ste prepričani, da želite izbrisati recept?",
"Delete failed" : "Brisanje je spodletelo",
"Hide navigation" : "Skrij bočno okno",
"Create recipe" : "Ustvari recept",
"Download recipe from URL" : "Prejmi recept prek naslova URL",
"Uncategorized recipes" : "Neopredeljeni recepti",
"Rescan library" : "Ponovno preišči zbirko",
"Recipe folder" : "Mapa receptov",
"Please pick a folder" : "Izbrati je treba mapo",
@ -37,6 +40,8 @@ OC.L10N.register(
"Could not set preference for image printing" : "Ni mogoče nastaviti lastnostni za tiskanje slike",
"Could not set recipe update interval to {interval}" : "Ni mogoče nastaviti posodobitve receptov na {interval}",
"Loading config failed" : "Nalaganje nastavitev je spodletelo",
"Failed to load category {category} recipes" : "Nalaganje kategorije {category} je spodletelo",
"Loading category recipes …" : "Poteka nalaga receptov kategorije ...",
"Failed to fetch categories" : "Pridobivanje kategorij je spodletelo",
"Path to your recipe collection" : "Pot do zbirke receptov",
"Could not set recipe folder to {path}" : "Ni mogoče nastaviti mape receptov na {path}",

Просмотреть файл

@ -3,6 +3,7 @@
"Cookbook" : "Kuhar'ca",
"An integrated cookbook using schema.org JSON files as recipes" : "Kuharica v oblaku, ki omogoča prikaz datotek receptov schema.org JSON",
"A library for all your recipes. It uses JSON files following the schema.org recipe format. To add a recipe to the collection, you can paste in the URL of the recipe, and the provided web page will be parsed and downloaded to whichever folder you specify in the app settings." : "Zbirka vaših receptov uporablja datoteke JSON, ki so oblikovani po predlogi schema.org. Za dodajanje recepta v zbirko, lahko enostavno prilepite naslov URL recepta in vsebina bo razčlenjena in shranjena v ciljno mapo v vašem oblaku.",
"Open navigation" : "Odpri bočno okno",
"Home" : "Začetna stran",
"All recipes" : "Vsi recepti",
"Filter" : "Filter",
@ -24,8 +25,10 @@
"Search for recipes" : "Iskanje med recepti",
"Are you sure you want to delete this recipe?" : "Ali ste prepričani, da želite izbrisati recept?",
"Delete failed" : "Brisanje je spodletelo",
"Hide navigation" : "Skrij bočno okno",
"Create recipe" : "Ustvari recept",
"Download recipe from URL" : "Prejmi recept prek naslova URL",
"Uncategorized recipes" : "Neopredeljeni recepti",
"Rescan library" : "Ponovno preišči zbirko",
"Recipe folder" : "Mapa receptov",
"Please pick a folder" : "Izbrati je treba mapo",
@ -35,6 +38,8 @@
"Could not set preference for image printing" : "Ni mogoče nastaviti lastnostni za tiskanje slike",
"Could not set recipe update interval to {interval}" : "Ni mogoče nastaviti posodobitve receptov na {interval}",
"Loading config failed" : "Nalaganje nastavitev je spodletelo",
"Failed to load category {category} recipes" : "Nalaganje kategorije {category} je spodletelo",
"Loading category recipes …" : "Poteka nalaga receptov kategorije ...",
"Failed to fetch categories" : "Pridobivanje kategorij je spodletelo",
"Path to your recipe collection" : "Pot do zbirke receptov",
"Could not set recipe folder to {path}" : "Ni mogoče nastaviti mape receptov na {path}",

Просмотреть файл

@ -30,6 +30,7 @@ OC.L10N.register(
"Hide navigation" : "Gezinmeyi gizle",
"Create recipe" : "Yemek tarifi oluştur",
"Download recipe from URL" : "Yemek tarifini adresten indir",
"Uncategorized recipes" : "Kategorisiz tarifler",
"Rescan library" : "Kitaplığı yeniden tara",
"Recipe folder" : "Yemek tarifi klasörü",
"Please pick a folder" : "Lütfen bir klasör seçin",
@ -39,6 +40,8 @@ OC.L10N.register(
"Could not set preference for image printing" : "Görsel yazdırma ayarı yapılamadı",
"Could not set recipe update interval to {interval}" : "Yemek tarifi güncelleme sıklığı {interval} olarak ayarlanamadı",
"Loading config failed" : "Yapılandırma yüklenemedi",
"Failed to load category {category} recipes" : "{category} kategorisindeki tarifler yüklenemedi",
"Loading category recipes …" : "Kategorinin tarifleri yükleniyor …",
"Failed to fetch categories" : "Kategoriler alınamadı",
"Path to your recipe collection" : "Yemek tarifi derlemenizin yolu",
"Could not set recipe folder to {path}" : "Yemek tarifi derleme klasörü {path} olarak ayarlanamadı",

Просмотреть файл

@ -28,6 +28,7 @@
"Hide navigation" : "Gezinmeyi gizle",
"Create recipe" : "Yemek tarifi oluştur",
"Download recipe from URL" : "Yemek tarifini adresten indir",
"Uncategorized recipes" : "Kategorisiz tarifler",
"Rescan library" : "Kitaplığı yeniden tara",
"Recipe folder" : "Yemek tarifi klasörü",
"Please pick a folder" : "Lütfen bir klasör seçin",
@ -37,6 +38,8 @@
"Could not set preference for image printing" : "Görsel yazdırma ayarı yapılamadı",
"Could not set recipe update interval to {interval}" : "Yemek tarifi güncelleme sıklığı {interval} olarak ayarlanamadı",
"Loading config failed" : "Yapılandırma yüklenemedi",
"Failed to load category {category} recipes" : "{category} kategorisindeki tarifler yüklenemedi",
"Loading category recipes …" : "Kategorinin tarifleri yükleniyor …",
"Failed to fetch categories" : "Kategoriler alınamadı",
"Path to your recipe collection" : "Yemek tarifi derlemenizin yolu",
"Could not set recipe folder to {path}" : "Yemek tarifi derleme klasörü {path} olarak ayarlanamadı",

Просмотреть файл

@ -192,6 +192,35 @@ class MainController extends Controller
}
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function tags($keywords)
{
$this->dbCacheService->triggerCheck();
$keywords = urldecode($keywords);
try {
$recipes = $this->service->getRecipesByKeywords($keywords);
foreach ($recipes as $i => $recipe) {
$recipes[$i]['imageUrl'] = $this->urlGenerator->linkToRoute(
'cookbook.recipe.image',
[
'id' => $recipe['recipe_id'],
'size' => 'thumb',
't' => $this->service->getRecipeMTime($recipe['recipe_id'])
]
);
}
return new DataResponse($recipes, Http::STATUS_OK, ['Content-Type' => 'application/json']);
} catch (\Exception $e) {
error_log($e->getMessage());
return new DataResponse($e->getMessage(), 500);
}
}
/**
* @NoAdminRequired
* @NoCSRFRequired

Просмотреть файл

@ -234,6 +234,34 @@ class RecipeDb {
return $this->unique($result);
}
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found
*
*/
public function getRecipesByKeywords(string $keywords, string $user_id) {
$keywords_arr = explode(',', $keywords);
$qb = $this->db->getQueryBuilder();
$qb->select(['r.recipe_id', 'r.name'])
->from(self::DB_TABLE_KEYWORDS, 'k')
->where('k.name IN (:keywords)')
->andWhere('k.user_id = :user')
->having('COUNT(DISTINCT k.name) = :keywordsCount')
->setParameter('user', $user_id, TYPE::INTEGER)
->setParameter('keywords', $keywords_arr, IQueryBuilder::PARAM_STR_ARRAY)
->setParameter('keywordsCount', sizeof($keywords_arr), TYPE::INTEGER);
$qb->join('k', self::DB_TABLE_RECIPES, 'r', 'k.recipe_id = r.recipe_id');
$qb->groupBy(['r.name', 'r.recipe_id']);
$qb->orderBy('r.name');
$cursor = $qb->execute();
$result = $cursor->fetchAll();
$cursor->closeCursor();
return $this->unique($result);
}
/**
* @throws \OCP\AppFramework\Db\DoesNotExistException if not found

Просмотреть файл

@ -917,6 +917,18 @@ class RecipeService
return $this->db->getRecipesByCategory($category, $this->user_id);
}
/**
* Get all recipes containing all of the keywords.
*
* @param string $keywords Keywords/tags as a comma-separated string.
*
* @return array
*/
public function getRecipesByKeywords($keywords)
{
return $this->db->getRecipesByKeywords($keywords, $this->user_id);
}
/**
* Search for recipes by keywords
*
@ -954,6 +966,7 @@ class RecipeService
if (!$path) {
$path = '/' . $this->il10n->t('Recipes');
$this->config->setUserValue($this->user_id, 'cookbook', 'folder', $path);
}
return $path;

Просмотреть файл

@ -13,7 +13,7 @@
</Breadcrumb>
<!-- SEARCH PAGE -->
<Breadcrumb v-if="isSearch" class="not-link" :title="searchTitle" :disableDrop="true" />
<Breadcrumb v-if="isSearch && $route.params.value" class="active" :title="$route.params.value=='_'?'None':$route.params.value" :disableDrop="true" />
<Breadcrumb v-if="isSearch && $route.params.value" class="active" :title="$route.params.value=='_'?'None':decodeURIComponent($route.params.value)" :disableDrop="true" />
<!-- RECIPE PAGES -->
<!-- Edit recipe -->
<Breadcrumb v-if="isEdit" class="not-link" :title="t('cookbook', 'Edit recipe')" :disableDrop="true" />
@ -179,8 +179,8 @@ export default {
return t('cookbook', 'Category')
} else if (this.$route.name === 'search-name') {
return t('cookbook', 'Recipe name')
} else if (this.$route.name === 'search-tag') {
return t('cookbook', 'Tag')
} else if (this.$route.name === 'search-tags') {
return t('cookbook', 'Tags')
} else {
return t('cookbook', 'Search for recipes')
}
@ -283,3 +283,16 @@ export default {
}
</style>
<style>
@media print {
.vue-tooltip {
display: none !important;
}
}
</style>

Просмотреть файл

@ -0,0 +1,61 @@
<template>
<a v-on:click="clicked" ref="link"><li>{{ keyword }}</li></a>
</template>
<script>
export default {
name: 'RecipeKeyword',
props: ['keyword'],
data () {
return {
};
},
computed: {
},
methods: {
clicked() {
if(!this.$refs.link.classList.contains('disabled')) {
this.$emit('keyword-clicked')
}
}
}
}
</script>
<style scoped>
li {
display: inline-block;
margin-right: .3em;
margin-bottom: .3em;
padding: 0px .5em;
border: 1px solid var(--color-border-dark);
border-radius: var(--border-radius-pill);
/* prevent text selection - doesn't look good */
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+/Edge */
user-select: none; /* Standard */
}
.active li {
background-color: var(--color-primary);
color: var(--color-primary-text);
}
.disabled li {
background-color: #FFF;
border-color: var(--color-border);
color: var(--color-border);
}
.disabled li:hover {
border-color: var(--color-border);
cursor: default;
}
li:hover, .active li:hover {
border: 1px solid var(--color-primary);
}
</style>

Просмотреть файл

@ -10,6 +10,11 @@
<h2>{{ $store.state.recipe.name }}</h2>
<div class="details">
<p v-if="keywords.length">
<ul v-if="keywords.length">
<RecipeKeyword v-for="(keyword,idx) in keywords" :key="'keyw'+idx" :keyword="keyword" v-on:keyword-clicked="keywordClicked(keyword)" />
</ul>
</p>
<p class="description">{{ $store.state.recipe.description }}</p>
<p v-if="$store.state.recipe.url">
<strong>{{ t('cookbook', 'Source') }}: </strong><a target="_blank" :href="$store.state.recipe.url" class='source-url'>{{ $store.state.recipe.url }}</a>
@ -57,6 +62,7 @@
import RecipeImages from './RecipeImages'
import RecipeIngredient from './RecipeIngredient'
import RecipeInstruction from './RecipeInstruction'
import RecipeKeyword from './RecipeKeyword'
import RecipeTimer from './RecipeTimer'
import RecipeTool from './RecipeTool'
@ -66,6 +72,7 @@ export default {
RecipeImages,
RecipeIngredient,
RecipeInstruction,
RecipeKeyword,
RecipeTimer,
RecipeTool,
},
@ -74,6 +81,7 @@ export default {
// Own properties
ingredients: [],
instructions: [],
keywords: [],
timerCook: null,
timerPrep: null,
timerTotal: null,
@ -81,6 +89,14 @@ export default {
}
},
methods: {
/**
* Callback for click on keyword
*/
keywordClicked: function(keyword) {
if(keyword) {
this.$router.push('/tags/'+keyword);
}
},
setup: function() {
// Make the control row show that a recipe is loading
if (!this.$store.state.recipe) {
@ -116,6 +132,10 @@ export default {
$this.instructions = Object.values($this.$store.state.recipe.recipeInstructions)
}
if ($this.$store.state.recipe.keywords) {
$this.keywords = String($this.$store.state.recipe.keywords).split(',');
}
if ($this.$store.state.recipe.cookTime) {
let cookT = $this.$store.state.recipe.cookTime.match(/PT(\d+?)H(\d+?)M/)
$this.timerCook = { hours: parseInt(cookT[1]), minutes: parseInt(cookT[2]) }

Просмотреть файл

@ -24,10 +24,21 @@ export default {
if (this.query === 'name') {
// Search by name
}
if (this.query === 'tag') {
// Search by tag
else if (this.query === 'tags') {
// Search by tags
let $this = this
let tags = this.$route.params.value
$.get(this.$window.baseUrl + '/api/tags/'+tags).done(function(json) {
$this.results = json
}).fail(function (jqXHR, textStatus, errorThrown) {
$this.results = []
alert(t('cookbook', 'Failed to load recipes with keywords: ' + tags))
if (errorThrown && errorThrown instanceof Error) {
throw errorThrown
}
})
}
if (this.query === 'cat') {
else if (this.query === 'cat') {
// Search by category
let $this = this
let cat = this.$route.params.value

Просмотреть файл

@ -28,7 +28,7 @@ const routes = [
{ path: '/category/:value', name: 'search-category', component: Search, props: { query: 'cat' } },
{ path: '/name/:value', name: 'search-name', component: Search, props: { query: 'name' } },
{ path: '/search/:value', name: 'search-general', component: Search, props: { query: 'general' } },
{ path: '/tag/:value', name: 'search-tag', component: Search, props: { query: 'tag' } },
{ path: '/tags/:value', name: 'search-tags', component: Search, props: { query: 'tags' } },
// Recipe routes
// Vue router has a strange way of determining when it renders a component again and when not.