stash
This commit is contained in:
parent
49a063f2a7
commit
23028f0027
6 changed files with 159 additions and 54 deletions
114
frontend/src/components/PropertyBadge.vue
Normal file
114
frontend/src/components/PropertyBadge.vue
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<template>
|
||||||
|
<div class="input-group" :title="prettyDescription">
|
||||||
|
<label class="input-group-text form-control-inline form-control-sm text-light border-dark bg-dark badge">
|
||||||
|
{{ property.name }} =
|
||||||
|
</label>
|
||||||
|
<input type="number" min="0"
|
||||||
|
class="form-control form-control-inline form-control-sm text-light border-dark bg-dark badge"
|
||||||
|
placeholder="Enter value"
|
||||||
|
v-model="localValue" :style="inputStyle"/>
|
||||||
|
<span class="input-group-text form-control-sm text-light border-dark bg-dark badge"
|
||||||
|
v-if="property.unit_symbol" :title="(property.unit_name?property.unit_name:property.unit_symbol)">
|
||||||
|
{{ property.unit_symbol }}
|
||||||
|
</span>
|
||||||
|
<span class="input-group-text form-control-sm text-light border-dark bg-dark badge">
|
||||||
|
<b-icon-x-circle @click="removeProperty()"></b-icon-x-circle>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.form-control-inline {
|
||||||
|
display: inline;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
width: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control.badge {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-text.badge {
|
||||||
|
padding: .3rem 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group .badge:first-child {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group .badge:last-child {
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.badge {
|
||||||
|
--width: 0em;
|
||||||
|
min-height: calc(1.2rem);
|
||||||
|
line-height: 1;
|
||||||
|
min-width: calc(var(--width) + 1.35em + 18px);
|
||||||
|
width: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=number].badge {
|
||||||
|
}
|
||||||
|
|
||||||
|
input.badge:empty {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as BIcons from "bootstrap-icons-vue";
|
||||||
|
import {mapActions, mapState} from "vuex";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "PropertyBadge",
|
||||||
|
components: {
|
||||||
|
...BIcons
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
property: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
prop: "value",
|
||||||
|
event: "input"
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
localValue: {
|
||||||
|
get() {
|
||||||
|
return this.property.value
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit("input", value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prettyDescription() {
|
||||||
|
var d = this.property.description ? this.property.description : this.property.name
|
||||||
|
if (this.property.unit_name) {
|
||||||
|
d += " (" + this.property.unit_name + ")"
|
||||||
|
}
|
||||||
|
return d.replace(/<[^>]*>?/gm, '')
|
||||||
|
},
|
||||||
|
inputStyle() {
|
||||||
|
const w = this.property.value ? Math.max(1, this.property.value.toString().length) : 1
|
||||||
|
if (this.property.value === undefined) {
|
||||||
|
console.log("No value for property", this.property)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"--width": w + "ex"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
removeProperty() {
|
||||||
|
this.$emit("remove")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,48 +1,35 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="taglist form-control form-control-lg">
|
<div class="taglist form-control form-control-lg">
|
||||||
<span class="badge bg-dark" v-for="(property, index) in value" :key="index">
|
<PropertyBadge v-for="(property, index) in splicedValue"
|
||||||
{{ property.name }} =
|
:key="index"
|
||||||
<input type="number" class="form-control form-control-inline form-control-sm form-control-xsm bg-dark text-light border-dark"
|
:property="property"
|
||||||
id="propertyValue" name="propertyValue" placeholder="Enter value"
|
@input="setValue(index, $event)"
|
||||||
v-model="property.value">
|
@remove="removeProperty(index)"/>
|
||||||
<i class="bi bi-x-circle-fill" @click="removeProperty(index)"></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<select class="form-select form-control form-control-lg" id="property" name="property" v-model="property">
|
<select class="form-select form-control form-control-lg" name="property" v-model="property"
|
||||||
<option v-for="(property, index) in availableProperties" :key="index" :value="property">{{ property }}</option>
|
v-if="availableProperties.length > 0">
|
||||||
|
<option v-for="(property, index) in availableProperties" :key="index" :value="property">
|
||||||
|
{{ property.name }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="btn btn-outline-secondary" type="button" @click="addProperty">Add</button>
|
<button class="btn btn-outline-secondary form-control-lg" type="button" @click="addProperty">Add</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.form-control-inline {
|
|
||||||
display: inline;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.taglist {
|
.taglist {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 0.3rem;
|
gap: 0.3rem;
|
||||||
}
|
padding: .25rem;
|
||||||
|
|
||||||
.form-control-xsm {
|
|
||||||
min-height: calc(.6rem);
|
|
||||||
padding: .0rem .5rem;
|
|
||||||
font-size: .6rem;
|
|
||||||
border-radius: .1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=number].form-control-xsm{
|
|
||||||
padding: 0 0 0 .5rem;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as BIcons from "bootstrap-icons-vue";
|
import * as BIcons from "bootstrap-icons-vue";
|
||||||
import {mapActions, mapState} from "vuex";
|
import {mapActions, mapState} from "vuex";
|
||||||
|
import PropertyBadge from "@/components/PropertyBadge.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PropertyField",
|
name: "PropertyField",
|
||||||
|
@ -52,6 +39,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
PropertyBadge,
|
||||||
...BIcons
|
...BIcons
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -67,28 +55,46 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["properties"]),
|
...mapState(["properties"]),
|
||||||
availableProperties() {
|
availableProperties() {
|
||||||
return this.properties.filter(property => !this.localValue.map(p => p.name).includes(property));
|
if (!this.properties) return [];
|
||||||
|
if (!this.value) return this.properties;
|
||||||
|
return this.properties.filter(property => !this.value.map(p => p.name).includes(property.name));
|
||||||
},
|
},
|
||||||
localValue: {
|
localValue: {
|
||||||
get() {
|
get() {
|
||||||
|
if (!this.value) return [];
|
||||||
return this.value;
|
return this.value;
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
this.$emit("input", value);
|
this.$emit("input", value);
|
||||||
console.log("set", value);
|
console.log("set", value);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
splicedValue() {
|
||||||
|
if (!this.value || !this.properties) return [];
|
||||||
|
return this.value.map(property => {
|
||||||
|
return {
|
||||||
|
...this.properties.find(p => p.name === property.name),
|
||||||
|
value: property.value
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(["fetchProperties"]),
|
...mapActions(["fetchProperties"]),
|
||||||
addProperty() {
|
addProperty() {
|
||||||
if (this.property !== "") {
|
if (this.property !== "") {
|
||||||
this.localValue.push({name: this.property, value: 0});
|
this.localValue.push({name: this.property.name, value: 0});
|
||||||
this.property = "";
|
this.property = "";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeProperty(index) {
|
removeProperty(index) {
|
||||||
this.localValue.splice(index, 1);
|
this.localValue.splice(index, 1);
|
||||||
|
},
|
||||||
|
setValue(index, value) {
|
||||||
|
if (value.target)
|
||||||
|
return;
|
||||||
|
this.localValue[index].value = value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="taglist form-control">
|
<div class="taglist form-control form-control-lg">
|
||||||
<span class="badge bg-dark" v-for="(tag, index) in value" :key="index">
|
<span class="badge bg-dark" v-for="(tag, index) in value" :key="index">
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
<i class="bi bi-x-circle-fill" @click="removeTag(index)"></i>
|
<b-icon-x-circle @click="removeTag(index)"></b-icon-x-circle>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<select class="form-select" id="tag" name="tag" v-model="tag">
|
<select class="form-select form-control form-control-lg" id="tag" name="tag" v-model="tag">
|
||||||
<option v-for="tag in availableTags" :key="tag" :value="tag">{{ tag }}</option>
|
<option v-for="tag in availableTags" :key="tag" :value="tag">{{ tag }}</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="btn btn-outline-secondary" type="button" @click="addTag">Add</button>
|
<button class="btn btn-outline-secondary form-control-lg" type="button" @click="addTag">Add</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -18,6 +18,11 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 0.3rem;
|
gap: 0.3rem;
|
||||||
|
padding: .25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
padding: .3rem .5rem
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -169,12 +169,12 @@ export default createStore({
|
||||||
},
|
},
|
||||||
async createInventoryItem({state, dispatch, getters}, item) {
|
async createInventoryItem({state, dispatch, getters}, item) {
|
||||||
const servers = await dispatch('getHomeServers')
|
const servers = await dispatch('getHomeServers')
|
||||||
const data = {availability_policy: 'friends', category: 'other', ...item}
|
const data = {availability_policy: 'friends', ...item}
|
||||||
return await servers.post(getters.signAuth, '/api/inventory_items/', data)
|
return await servers.post(getters.signAuth, '/api/inventory_items/', data)
|
||||||
},
|
},
|
||||||
async updateInventoryItem({state, dispatch, getters}, item) {
|
async updateInventoryItem({state, dispatch, getters}, item) {
|
||||||
const servers = await dispatch('getHomeServers')
|
const servers = await dispatch('getHomeServers')
|
||||||
const data = {availability_policy: 'friends', category: 'other', ...item}
|
const data = {availability_policy: 'friends', ...item}
|
||||||
return await servers.patch(getters.signAuth, '/api/inventory_items/' + item.id + '/', data)
|
return await servers.patch(getters.signAuth, '/api/inventory_items/' + item.id + '/', data)
|
||||||
},
|
},
|
||||||
async deleteInventoryItem({state, dispatch, getters}, item) {
|
async deleteInventoryItem({state, dispatch, getters}, item) {
|
||||||
|
|
|
@ -17,20 +17,10 @@
|
||||||
placeholder="Enter description" v-model="item.description"></textarea>
|
placeholder="Enter description" v-model="item.description"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<ul>
|
|
||||||
<li v-for="tag in item.tags" :key="tag">
|
|
||||||
{{ tag }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<label for="tags" class="form-label">Tags</label>
|
<label for="tags" class="form-label">Tags</label>
|
||||||
<tag-field :value="item.tags"></tag-field>
|
<tag-field :value="item.tags"></tag-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<ul>
|
|
||||||
<li v-for="property in item.properties" :key="property">
|
|
||||||
{{ property.name }}: {{ property.value }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<label for="property" class="form-label">Property</label>
|
<label for="property" class="form-label">Property</label>
|
||||||
<property-field :value="item.properties"></property-field>
|
<property-field :value="item.properties"></property-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,20 +17,10 @@
|
||||||
placeholder="Enter description" v-model="item.description"></textarea>
|
placeholder="Enter description" v-model="item.description"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<ul>
|
|
||||||
<li v-for="tag in item.tags" :key="tag">
|
|
||||||
{{ tag }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<label for="tags" class="form-label">Tags</label>
|
<label for="tags" class="form-label">Tags</label>
|
||||||
<tag-field :value="item.tags"></tag-field>
|
<tag-field :value="item.tags"></tag-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<ul>
|
|
||||||
<li v-for="property in item.properties" :key="property">
|
|
||||||
{{ property.name }}: {{ property.value }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<label for="property" class="form-label">Property</label>
|
<label for="property" class="form-label">Property</label>
|
||||||
<property-field :value="item.properties"></property-field>
|
<property-field :value="item.properties"></property-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue