Skip to content

Commit

Permalink
Merge pull request #160 from karlomikus/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
karlomikus authored Feb 17, 2024
2 parents 7c0c870 + 81dcce0 commit 6f6c4c2
Show file tree
Hide file tree
Showing 15 changed files with 730 additions and 350 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# v2.10.0
## New
- Added API tokens page to settings

## Changes
- Updated loader positions on ingredient page

## Fixes
- Cocktail import information now uses user defined units
- Fixed base ingredient tag showing on all ingredients when importing

# v2.9.0
## New
- Added bar menu managing
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,19 @@ Salt Rim is a web client used for connecting to your [Bar Assistant](https://git

## Features

- Beautiful UI for your Bar Asistant server
- Implements all supported features of Bar Assistant
- Intuitive UI for your Bar Assistant instance
- Supports all features of Bar Assistant
- Desktop and mobile support
- Powerful search and filtering using [Vue Instantsearch](https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/vue/)
- Powerful search and filtering capabilities using [Vue Instantsearch](https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/vue/)
- Support for multiple measurement units
- Manage your personal shopping list
- Support for markdown in cocktails and ingredients
- Automatically add missing ingredients to your shopping cart
- Personal shopping list management and exporting
- Markdown support for cocktails and ingredients
- Automatic ingredient suggestions
- Dark theme support
- Localizations available: English, German, Croatian, French
- PWA Support
- Progressive Web App (PWA) capabilities
- Organize your personal recipe collections
- Easily copy and share your recipes
- Easy recipe copying and sharing

## Documentation

Expand Down
627 changes: 321 additions & 306 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/ApiRequests.js
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,28 @@ class ApiRequests

return this.parseResponse(jsonResp)
}

/**
* =============================
* Tokens
* =============================
*/

static async fetchTokens() {
let jsonResp = await this.getRequest('/api/tokens')

return this.parseResponse(jsonResp)
}

static async saveToken(data) {
const jsonResp = await this.postRequest('/api/tokens', data)

return this.parseResponse(jsonResp)
}

static async removeToken(tokenId) {
return await this.deleteRequest(`/api/tokens/${tokenId}`)
}
}

export default ApiRequests
7 changes: 7 additions & 0 deletions src/assets/alerts.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@
--_clr-border: #2c4b79;
--_clr-bg: #0e213d;
}

.alert.alert--warning {
--_clr-text: rgb(173, 68, 7);
--_clr-border: rgb(173, 68, 7);
--_clr-bg: rgb(255, 250, 247);
border-color: var(--_clr-border);
}
24 changes: 12 additions & 12 deletions src/components/Bar/BarForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
</div>
<div class="form-group">
<label class="form-label" for="slug">{{ $t('bar.url') }}:</label>
<input id="slug" v-model="bar.slug" class="form-input" type="text" @blur="updateSlug" :disabled="bar.id != null">
<p class="form-input-hint" v-show="urlWithSlug">
<input id="slug" v-model="bar.slug" class="form-input" type="text" :disabled="bar.id != null" @blur="updateSlug">
<p v-show="urlWithSlug" class="form-input-hint">
{{ $t('bar.url-help', {url: urlWithSlug}) }}
</p>
</div>
Expand Down Expand Up @@ -72,22 +72,22 @@ export default {
]
}
},
watch: {
'bar.options': function (newVal) {
if (newVal && newVal.includes('cocktails') && !newVal.includes('ingredients')) {
newVal.push('ingredients')
}
}
},
computed: {
urlWithSlug() {
if (!this.bar.slug) {
return null;
return null
}
return `${window.location.origin}/bars/${slug(this.bar.slug)}`
},
},
watch: {
'bar.options': function (newVal) {
if (newVal && newVal.includes('cocktails') && !newVal.includes('ingredients')) {
newVal.push('ingredients')
}
}
},
created() {
document.title = `${this.$t('bars.bar')} \u22C5 ${this.site_title}`
Expand All @@ -108,13 +108,13 @@ export default {
methods: {
updateSlug(e) {
if (this.bar.id) {
return;
return
}
this.bar.slug = slug(e.target.value)
},
submit() {
let postSlug = null;
let postSlug = null
if (this.bar.slug) {
postSlug = slug(this.bar.slug)
}
Expand Down
18 changes: 17 additions & 1 deletion src/components/Cocktail/CocktailImport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@
<label class="form-label" :for="'ingredient_amount_' + idx">{{ $t('amount') }}</label>
<input :id="'ingredient_amount_' + idx" v-model="ingredient.amount" type="text" class="form-input">
</div>
<div v-if="ingredient.amount_max" class="form-group">
<label class="form-label" :for="'ingredient_amount_max_' + idx">{{ $t('amount-max') }}</label>
<input :id="'ingredient_amount_max_' + idx" v-model="ingredient.amount_max" type="text" class="form-input">
</div>
<div class="form-group">
<label class="form-label" :for="'ingredient_units_' + idx">{{ $t('units') }}</label>
<input :id="'ingredient_units_' + idx" v-model="ingredient.units" type="text" class="form-input">
Expand Down Expand Up @@ -147,6 +151,7 @@ import IngredientFinder from './../IngredientFinder.vue'
import SaltRimDialog from '../Dialog/SaltRimDialog.vue'
import SubscriptionCheck from '../SubscriptionCheck.vue'
import AppState from '../../AppState'
import UnitHandler from '../../UnitHandler'
export default {
components: {
Expand Down Expand Up @@ -209,6 +214,15 @@ export default {
ApiRequests.importCocktail({ source: this.source, duplicate_actions: this.duplicateAction }, { type: this.importType }).then(data => {
this.result = data
this.result.ingredients.map(i => i.existingIngredient = null)
this.result.ingredients.map(i => {
const newAmount = UnitHandler.convertFromTo(i.units, i.amount, this.appState.defaultUnit)
if (i.amount != newAmount) {
i.units = this.appState.defaultUnit
}
i.amount = newAmount
return i
})
this.cocktailTags = data.tags
this.isLoading = false
}).catch(e => {
Expand All @@ -218,11 +232,13 @@ export default {
}
},
async matchIngredients() {
let sortIdx = 0
for (const key in this.result.ingredients) {
if (Object.hasOwnProperty.call(this.result.ingredients, key)) {
sortIdx++
const scrapedIngredient = this.result.ingredients[key]
scrapedIngredient.substitutes = []
scrapedIngredient.sort = 1
scrapedIngredient.sort = sortIdx
if (scrapedIngredient.existingIngredient) {
continue
Expand Down
49 changes: 30 additions & 19 deletions src/components/Ingredient/IngredientDetails.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<OverlayLoader v-if="isLoadingIngredient" />
<div v-if="ingredient.id" class="ingredient-details">
<OverlayLoader v-if="isLoading" />
<div class="block-container block-container--padded ingredient-details__box" style="margin-top: 100px;">
<div class="ingredient-details__box__content">
<div class="ingredient-details__title">
Expand Down Expand Up @@ -64,6 +64,7 @@
<div class="block-container block-container--padded ingredient-details__cocktails">
<div class="ingredient-details__actions">
<button type="button" class="button-circle" @click="toggleShelf">
<OverlayLoader v-if="isLoadingShelf" />
<svg v-if="!isAddedToShelf" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path d="M4 3h16a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm1 2v14h14V5H5z" />
Expand All @@ -76,6 +77,7 @@
<Dropdown>
<template #default="{ toggleDropdown }">
<button type="button" class="button-circle" @click="toggleDropdown">
<OverlayLoader v-if="isLoadingShoppingList" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path d="M12 3c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 14c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-7c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" />
Expand Down Expand Up @@ -114,6 +116,7 @@
</div>
<h2 class="details-block-container__title">{{ $t('ingredient.cocktail-children', { total: ingredient.cocktails.length }) }}</h2>
<RouterLink v-if="ingredient.cocktails.length > 0" :to="{name: 'cocktails', query: {'filter[ingredient_id]': ingredient.id}}" style="display: inline-block; margin-bottom: 1rem;">{{ $t('view-all') }}</RouterLink>
<OverlayLoader v-if="isLoadingExtra" />
<ul v-if="ingredient.cocktails.length > 0" class="ingredient-chips-list">
<li v-if="extraIfAddedToShelf.length > 0" class="ingredient-chips-list__label">{{ $t('ingredient.extra-cocktails') }}:</li>
<li v-for="cocktail in extraIfAddedToShelf" :key="cocktail.id">
Expand Down Expand Up @@ -152,7 +155,10 @@ export default {
OverlayLoader
},
data: () => ({
isLoading: false,
isLoadingIngredient: false,
isLoadingShelf: false,
isLoadingShoppingList: false,
isLoadingExtra: false,
ingredient: {},
isAddedToShelf: false,
isAddedToShoppingList: false,
Expand Down Expand Up @@ -207,42 +213,47 @@ export default {
},
methods: {
async refreshIngredient() {
this.isLoading = true
this.isLoadingIngredient = true
this.ingredient = await ApiRequests.fetchIngredient(this.$route.params.id).catch(e => {
this.$toast.error(e.message)
return {}
})
this.isLoadingIngredient = false
this.isLoadingShelf = true
const shelfIngredients = await ApiRequests.fetchMyShelf().catch(() => [])
this.isLoadingShelf = false
this.isLoadingShoppingList = true
const shoppingListIngredients = await ApiRequests.fetchShoppingList().catch(() => [])
this.isLoadingShoppingList = false
this.isAddedToShelf = shelfIngredients.filter(i => i.ingredient_id == this.ingredient.id).length > 0
this.isAddedToShoppingList = shoppingListIngredients.filter(i => i.ingredient_id == this.ingredient.id).length > 0
this.isLoadingExtra = true
await this.refreshExtraCocktails()
this.isLoading = false
this.isLoadingExtra = false
},
deleteIngredient() {
this.$confirm(this.$t('ingredient.delete-confirm', { name: this.ingredient.name, total: this.ingredient.cocktails.length }), {
onResolved: (dialog) => {
dialog.close()
this.isLoading = true
this.isLoadingIngredient = true
ApiRequests.deleteIngredient(this.ingredient.id).then(() => {
this.$toast.default(`Ingredient "${this.ingredient.name}" successfully removed`)
this.$router.push({ name: 'ingredients' })
this.isLoading = false
this.isLoadingIngredient = false
}).catch(e => {
this.$toast.error(e.message)
this.isLoading = false
this.isLoadingIngredient = false
})
}
})
},
toggleShelf() {
this.isLoading = true
this.isLoadingShelf = true
const postData = {
ingredient_ids: [this.ingredient.id]
Expand All @@ -252,26 +263,26 @@ export default {
ApiRequests.removeIngredientsFromShelf(postData).then(() => {
this.isAddedToShelf = false
this.$toast.default(this.$t('ingredient.shelf-remove-success', { name: this.ingredient.name }))
this.isLoading = false
this.isLoadingShelf = false
this.refreshExtraCocktails()
}).catch(e => {
this.$toast.error(e.message)
this.isLoading = false
this.isLoadingShelf = false
})
} else {
ApiRequests.addIngredientsToShelf(postData).then(() => {
this.isAddedToShelf = true
this.$toast.default(this.$t('ingredient.shelf-add-success', { name: this.ingredient.name }))
this.isLoading = false
this.isLoadingShelf = false
this.refreshExtraCocktails()
}).catch(e => {
this.$toast.error(e.message)
this.isLoading = false
this.isLoadingShelf = false
})
}
},
toggleShoppingList() {
this.isLoading = true
this.isLoadingShoppingList = true
const postData = {
ingredient_ids: [this.ingredient.id]
Expand All @@ -281,19 +292,19 @@ export default {
ApiRequests.removeIngredientsFromShoppingList(postData).then(() => {
this.$toast.default(this.$t('ingredient.list-remove-success', { name: this.ingredient.name }))
this.isAddedToShoppingList = false
this.isLoading = false
this.isLoadingShoppingList = false
}).catch(e => {
this.$toast.error(e.message)
this.isLoading = false
this.isLoadingShoppingList = false
})
} else {
ApiRequests.addIngredientsToShoppingList(postData).then(() => {
this.$toast.default(this.$t('ingredient.list-add-success', { name: this.ingredient.name }))
this.isAddedToShoppingList = true
this.isLoading = false
this.isLoadingShoppingList = false
}).catch(e => {
this.$toast.error(e.message)
this.isLoading = false
this.isLoadingShoppingList = false
})
}
},
Expand Down
3 changes: 0 additions & 3 deletions src/components/Menu/MenuIndex.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<PageHeader>
{{ $t('menu.bar-title-menu', { name: appState.bar.name }) }}
</PageHeader>
<SubscriptionCheck>Subscribe to "Mixologist" plan to manage your bar menu!</SubscriptionCheck>
<div class="menu-details">
<div class="block-container block-container--padded" style="width: 100%;">
<p style="margin-bottom: 1rem;">{{ $t('menu.description') }}</p>
Expand Down Expand Up @@ -90,7 +89,6 @@ import AppState from '../../AppState'
import QRCodeVue3 from 'qrcode-vue3'
import ApiRequests from './../../ApiRequests.js'
import OverlayLoader from '../OverlayLoader.vue'
import SubscriptionCheck from '../SubscriptionCheck.vue'
export default {
components: {
Expand All @@ -99,7 +97,6 @@ export default {
SaltRimDialog,
QRCodeVue3,
OverlayLoader,
SubscriptionCheck,
},
data() {
return {
Expand Down
Loading

0 comments on commit 6f6c4c2

Please sign in to comment.