Skip to content

Commit

Permalink
ui to add new pinconfigs. Pinconfigs will be saved to the current con…
Browse files Browse the repository at this point in the history
…troller and will be available from the pin config picker.
  • Loading branch information
pljakobs committed Jan 5, 2025
1 parent 5d60bd6 commit e226446
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 44 deletions.
4 changes: 2 additions & 2 deletions public/config/pinconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": 2,
"available-pins": [
"version": 3,
"available_pins": [
{
"soc": "esp8266",
"pins": [0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16]
Expand Down
296 changes: 255 additions & 41 deletions src/components/ControllerConfigCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,97 @@
map-options
dropdown-icon="img:icons/arrow_drop_down.svg"
@update:model-value="handlePinConfigChange"
style="width: auto"
></q-select>
<q-btn
label="Update Configuration"
color="primary"
class="q-mt-md"
@click="updatePinConfig"
/>
<q-toggle v-model="showDetails" label="Show Details" />
<data-table v-if="showDetails" :items="formattedPinConfigData" />
<q-separator />
<div v-if="!showAddConfigPane">
<q-btn
label="Add Config"
color="primary"
class="q-mt-md"
@click="handleAddConfigPane(true)"
/>
</div>
<div v-else>
<q-input
v-model="newConfigName"
label="Config Name"
class="config-name-input"
/>
<div
v-for="(channel, index) in newConfigChannels"
:key="index"
class="channel-select"
>
<div class="color-circle" :class="channel.name"></div>
<q-select
v-model="channel.pin"
:options="filteredAvailablePins"
:label="channel.name"
emit-value
map-options
dropdown-icon="img:icons/arrow_drop_down.svg"
@update:model-value="updateAvailablePins"
class="pin-select"
></q-select>
</div>
<div class="button-row">
<q-btn
label="Cancel"
color="primary"
@click="handleAddConfigPane(false)"
/>
<q-btn label="Add" color="primary" @click="addNewConfig" />
</div>
</div>
</q-card-section>
</MyCard>
</template>

<script>
import { ref, onMounted, watch } from "vue";
import { ref, onMounted, computed, watch } from "vue";
import { useQuasar } from "quasar";
import { configDataStore } from "src/stores/configDataStore";
import { infoDataStore } from "src/stores/infoDataStore";
import MyCard from "src/components/myCard.vue";
import DataTable from "src/components/dataTable.vue";
export default {
name: "ControllerConfigCard",
components: {
MyCard,
DataTable,
},
setup() {
const $q = useQuasar();
const configData = configDataStore();
const infoData = infoDataStore();
const pinConfigData = ref([]);
const currentPinConfigName = ref(
configData.data.general.current_pin_config_name,
);
const showManualConfig = ref(false);
const showDetails = ref(false);
const pinConfigNames = ref([]);
const showAddConfigPane = ref(false);
const newConfigName = ref("");
const availablePins = ref([]);
const newConfigChannels = ref([
{ name: "red", pin: null },
{ name: "green", pin: null },
{ name: "blue", pin: null },
{ name: "warmwhite", pin: null },
{ name: "coldwhite", pin: null },
]);
const getPinConfigNames = () => {
pinConfigNames.value = configData.data.hardware.pinconfigs.map(
(config) => config.name,
);
pinConfigNames.value = configData.data.hardware.pinconfigs
.filter(
(config) =>
config.soc.toLowerCase() === infoData.data.soc.toLowerCase(),
)
.map((config) => config.name);
};
const getCurrentPinConfig = () => {
Expand All @@ -61,43 +115,87 @@ export default {
const handlePinConfigChange = (newConfigName) => {
currentPinConfigName.value = newConfigName;
getCurrentPinConfig();
updatePinConfig();
};
const handleAddConfigPane = (show) => {
console.log(
"in handleAddConfigPane, setting up for soc",
infoData.data.soc,
);
newConfigName.value = "new";
newConfigChannels.value = [
{ name: "red", pin: null },
{ name: "green", pin: null },
{ name: "blue", pin: null },
{ name: "warmwhite", pin: null },
{ name: "coldwhite", pin: null },
];
console.log(
"available_pins",
JSON.stringify(configData.data.hardware.available_pins),
);
const socPins = configData.data.hardware.available_pins.find(
(pinConfig) =>
pinConfig.soc.toLowerCase() === infoData.data.soc.toLowerCase(),
);
console.log("socPins", JSON.stringify(socPins));
if (socPins) {
availablePins.value = socPins.pins.map((pin) => ({
label: `Pin ${pin}`,
value: pin,
}));
} else {
availablePins.value = [];
}
console.log("mapped pins:", JSON.stringify(availablePins.value));
console.log("finished handleAddConfigPane");
showAddConfigPane.value = show;
};
const updatePinConfig = async () => {
try {
const response = await fetch("/api/update-config", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(configData.data.general),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
useQuasar().notify({
type: "positive",
message: "Configuration updated successfully!",
});
} catch (error) {
console.error("Error updating configuration:", error);
useQuasar().notify({
type: "negative",
message: `Error updating configuration: ${error.message}`,
});
const currentConfig = configData.data.hardware.pinconfigs.find(
(config) => config.name === currentPinConfigName.value,
);
if (currentConfig) {
configData.updateData("general.channels", currentConfig.channels);
configData.updateData(
"general.current_pin_config_name",
currentPinConfigName.value,
);
}
};
const loadPinConfigData = async () => {
console.log("loading pinConfigData");
try {
const response = await fetch(configData.data.general.pin_config_url);
if (!response.ok) throw new Error("Error loading pin config from URL");
const remotePinConfigData = await response.json();
const remoteVersion = remotePinConfigData.version;
if (remoteVersion > configData.data.hardware.version) {
configData.data.hardware.pinconfigs = remotePinConfigData.pinconfigs;
configData.data.hardware.version = remoteVersion;
const localPinConfigs = configData.data.hardware.pinconfigs;
const remotePinConfigs = remotePinConfigData.pinconfigs;
// Merge arrays, avoiding duplicates based on the 'name' property
const mergedPinConfigs = [
...localPinConfigs,
...remotePinConfigs.filter(
(remoteConfig) =>
!localPinConfigs.some(
(localConfig) => localConfig.name === remoteConfig.name,
),
),
];
console.log("mergedPinConfigs", JSON.stringify(mergedPinConfigs));
configData.updateData("hardware.pinconfigs", mergedPinConfigs, false);
configData.updateData("hardware.version", remoteVersion, false);
}
pinConfigData.value = configData.data.hardware.pinconfigs.filter(
Expand All @@ -106,34 +204,98 @@ export default {
);
} catch (error) {
console.error("Error loading pin config:", error);
$q.notify({
type: "negative",
message: `Error loading pin config: ${error.message}`,
});
}
getPinConfigNames();
getCurrentPinConfig();
};
const addNewConfig = () => {
if (!newConfigName.value) {
$q.notify({
type: "negative",
message: "Config name is required",
});
return;
}
const newConfig = {
name: newConfigName.value,
soc: infoData.data.soc,
channels: newConfigChannels.value,
};
configData.updateData("hardware.pinconfigs", [
...configData.data.hardware.pinconfigs,
newConfig,
]);
showAddConfigPane.value = false;
getPinConfigNames();
};
const filteredAvailablePins = computed(() => {
const selectedPins = newConfigChannels.value.map(
(channel) => channel.pin,
);
return availablePins.value.filter(
(pin) => !selectedPins.includes(pin.value),
);
});
const updateAvailablePins = () => {
// Trigger reactivity for filteredAvailablePins
filteredAvailablePins.value;
};
const formattedPinConfigData = computed(() => {
return pinConfigData.value.map((channel) => ({
label: channel.name,
value: channel.pin,
}));
});
onMounted(() => {
loadPinConfigData();
});
watch(currentPinConfigName, (newVal) => {
if (newVal === "manual") {
showManualConfig.value = true;
} else {
showManualConfig.value = false;
// Watch for changes in showDetails to ensure reactivity
watch(showDetails, (newVal) => {
if (newVal) {
// Force re-render or perform any necessary updates
getCurrentPinConfig();
}
});
// Watch for changes in infoData.data.soc to ensure availablePins is reactive
watch(
() => infoData.data.soc,
(newSoc) => {
console.log("infoData.data.soc changed to", newSoc);
},
);
return {
currentPinConfigName,
pinConfigData,
showManualConfig,
showDetails,
handlePinConfigChange,
handleAddConfigPane,
updatePinConfig,
getPinConfigNames,
getCurrentPinConfig,
loadPinConfigData,
pinConfigNames,
infoData,
formattedPinConfigData,
showAddConfigPane,
newConfigName,
newConfigChannels,
addNewConfig,
availablePins,
filteredAvailablePins,
updateAvailablePins,
};
},
};
Expand All @@ -143,4 +305,56 @@ export default {
.q-mt-md {
margin-top: 16px;
}
.config-name-input {
width: 50%;
margin-left: 15%;
min-width: 100px;
}
.channel-select {
display: flex;
align-items: center;
margin-left: 25%;
}
.color-circle {
width: 15px;
height: 15px;
border-radius: 50%;
margin-right: 10px;
}
.color-circle.red {
background-color: red;
}
.color-circle.green {
background-color: green;
}
.color-circle.blue {
background-color: blue;
}
.color-circle.warmwhite {
background-color: yellow;
}
.color-circle.coldwhite {
background-color: white;
border: 1px solid #ccc; /* Add a border to make the white circle visible */
}
.pin-select {
width: 30%;
}
.button-row {
display: flex;
justify-content: space-between;
margin-top: 16px;
margin-left: 20%;
margin-right: 40%;
}
</style>
Loading

0 comments on commit e226446

Please sign in to comment.