diff --git a/assets/js/components/Sessions/SessionDetailsModal.vue b/assets/js/components/Sessions/SessionDetailsModal.vue index f49c1a000..b2d0aee26 100644 --- a/assets/js/components/Sessions/SessionDetailsModal.vue +++ b/assets/js/components/Sessions/SessionDetailsModal.vue @@ -26,7 +26,21 @@ {{ $t("sessions.loadpoint") }} - {{ session.loadpoint }} + + + {{ + session.loadpoint + ? session.loadpoint + : $t("main.loadpoint.fallbackName") + }} + + @@ -185,17 +199,19 @@ import "@h2d2/shopicons/es/regular/checkmark"; import Modal from "bootstrap/js/dist/modal"; import formatter from "../../mixins/formatter"; import VehicleOptions from "../VehicleOptions.vue"; +import CustomSelect from "../CustomSelect.vue"; import { distanceUnit, distanceValue } from "../../units"; import api from "../../api"; export default { name: "SessionDetailsModal", - components: { VehicleOptions }, + components: { VehicleOptions, CustomSelect }, mixins: [formatter], props: { session: Object, currency: String, vehicles: Array, + loadpoints: Array, }, emits: ["session-changed"], computed: { @@ -215,6 +231,12 @@ export default { title: v.title, })); }, + loadpointOptions: function () { + return this.loadpoints.map((loadpoint) => ({ + value: loadpoint, + name: loadpoint, + })); + }, }, methods: { openSessionDetailsModal() { @@ -236,6 +258,9 @@ export default { async removeVehicle() { await this.updateSession({ vehicle: null }); }, + async changeLoadpoint(title) { + await this.updateSession({ loadpoint: title }); + }, async updateSession(data) { try { await api.put("session/" + this.session.id, data); @@ -260,4 +285,8 @@ export default { .options .vehicle-name { text-decoration: underline; } + +.options .loadpoint-name { + text-decoration: underline; +} diff --git a/assets/js/views/Sessions.vue b/assets/js/views/Sessions.vue index 8e07ae841..be4260fda 100644 --- a/assets/js/views/Sessions.vue +++ b/assets/js/views/Sessions.vue @@ -182,6 +182,7 @@ @@ -470,6 +471,10 @@ export default { const vehicles = store.state.vehicles || {}; return Object.entries(vehicles).map(([name, vehicle]) => ({ name, ...vehicle })); }, + loadpointList() { + const loadpoints = store.state.loadpoints || []; + return loadpoints.map(({ title }) => title); + }, selectedSession() { return this.sessions.find((s) => s.id == this.selectedSessionId); }, diff --git a/server/http_session_handler.go b/server/http_session_handler.go index 2f6190a9b..6102a56c8 100644 --- a/server/http_session_handler.go +++ b/server/http_session_handler.go @@ -117,20 +117,28 @@ func updateSessionHandler(w http.ResponseWriter, r *http.Request) { return } - vars := mux.Vars(r) - id := vars["id"] + id := mux.Vars(r)["id"] - var session struct { - Vehicle string + var data map[string]interface{} + if err := json.NewDecoder(r.Body).Decode(&data); err != nil { + jsonError(w, http.StatusBadRequest, errors.New("invalid JSON")) + return } - if err := json.NewDecoder(r.Body).Decode(&session); err != nil { - jsonError(w, http.StatusBadRequest, err) + updates := map[string]interface{}{} + for _, field := range []string{"vehicle", "loadpoint"} { + if val, ok := data[field]; ok { + updates[field] = val + } + } + + if len(updates) == 0 { + jsonError(w, http.StatusBadRequest, errors.New("no valid fields to update")) return } // https://github.com/evcc-io/evcc/issues/13738#issuecomment-2094070362 - if txn := db.Instance.Table("sessions").Where("id = ?", id).Select("vehicle").Updates(&session); txn.Error != nil { + if txn := db.Instance.Table("sessions").Where("id = ?", id).Updates(updates); txn.Error != nil { jsonError(w, http.StatusBadRequest, txn.Error) return }