Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web-ui): replace dropdown menus with checkboxes #3455

Merged
merged 3 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions src_assets/common/assets/web/Checkbox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<script setup>
const model = defineModel({ required: true });
const slots = defineSlots();
const props = defineProps({
class: {
type: String,
default: ""
},
desc: {
type: String,
default: null
},
id: {
type: String,
required: true
},
label: {
type: String,
default: null
},
localePrefix: {
type: String,
default: "missing-prefix"
},
default: {
type: undefined,
default: null,
}
});

// Add the mandatory class values
const extendedClassStr = (() => {
let values = props.class.split(" ");
if (!values.includes("form-check")) {
values.push("form-check");
}
return values.join(" ");
})();

// Map the value to boolean representation if possible, otherwise return null.
const mapToBoolRepresentation = (value) => {
// Try literal values first
if (value === true || value === false) {
return { possibleValues: [true, false], value: value };
}
if (value === 1 || value === 0) {
return { possibleValues: [1, 0], value: value };
}

const stringPairs = [
["true", "false"],
["1", "0"],
["enabled", "disabled"],
["enable", "disable"],
["yes", "no"],
["on", "off"]
];

value = `${value}`.toLowerCase().trim();
for (const pair of stringPairs) {
if (value === pair[0] || value === pair[1]) {
return { possibleValues: pair, value: value };
}
}

return null;
}

// Determine the true/false values for the checkbox
const checkboxValues = (() => {
const mappedValues = (() => {
const boolValues = mapToBoolRepresentation(model.value);
if (boolValues !== null) {
return boolValues.possibleValues;
}

// Return fallback if nothing matches
console.error(`Checkbox value ${model.value} did not match any acceptable pattern!`);
return ["true", "false"];
})();

return { truthy: mappedValues[0], falsy: mappedValues[1] };
})();
const parsedDefaultPropValue = (() => {
const boolValues = mapToBoolRepresentation(props.default);
if (boolValues !== null) {
// Convert truthy to true/false.
return boolValues.value === boolValues.possibleValues[0];
}

return null;
})();

const labelField = props.label ?? `${props.localePrefix}.${props.id}`;
const descField = props.desc ?? `${props.localePrefix}.${props.id}_desc`;
const showDesc = props.desc !== "" || Object.entries(slots).length > 0;
const showDefValue = parsedDefaultPropValue !== null;
const defValue = parsedDefaultPropValue ? "_common.enabled_def_cbox" : "_common.disabled_def_cbox";
</script>

<template>
<div :class="extendedClassStr">
<label :for="props.id" :class="`form-check-label${showDesc ? ' mb-2' : ''}`">
{{ $t(labelField) }}
<div class="mt-0 form-text" v-if="showDefValue">
{{ $t(defValue) }}
</div>
</label>
<input type="checkbox"
class="form-check-input"
:id="props.id"
v-model="model"
:true-value="checkboxValues.truthy"
:false-value="checkboxValues.falsy" />
<div class="form-text" v-if="showDesc">
{{ $t(descField) }}
<slot></slot>
</div>
</div>
</template>
76 changes: 40 additions & 36 deletions src_assets/common/assets/web/apps.html
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,13 @@ <h1>{{ $t('apps.applications_title') }}</h1>
<div id="appOutputHelp" class="form-text">{{ $t('apps.output_desc') }}</div>
</div>
<!-- prep-cmd -->
<div class="mb-3">
<label for="excludeGlobalPrep" class="form-label">{{ $t('apps.global_prep_name') }}</label>
<select id="excludeGlobalPrep" class="form-select" v-model="editForm['exclude-global-prep-cmd']">
<option v-for="val in [false, true]" :value="val">
{{ !val ? $t('_common.enabled') : $t('_common.disabled') }}
</option>
</select>
<div class="form-text">{{ $t('apps.global_prep_desc') }}</div>
</div>
<Checkbox class="mb-3"
id="excludeGlobalPrep"
label="apps.global_prep_name"
desc="apps.global_prep_desc"
v-model="editForm['exclude-global-prep-cmd']"
default="true"
></Checkbox>
<div class="mb-3">
<label for="appName" class="form-label">{{ $t('apps.cmd_prep_name') }}</label>
<div class="form-text">{{ $t('apps.cmd_prep_desc') }}</div>
Expand Down Expand Up @@ -152,12 +150,12 @@ <h1>{{ $t('apps.applications_title') }}</h1>
<td>
<input type="text" class="form-control monospace" v-model="c.undo" />
</td>
<td v-if="platform === 'windows'">
<div class="form-check">
<input type="checkbox" class="form-check-input" :id="'prep-cmd-admin-' + i" v-model="c.elevated"
true-value="true" false-value="false" />
<label :for="'prep-cmd-admin-' + i" class="form-check-label">{{ $t('_common.elevated') }}</label>
</div>
<td v-if="platform === 'windows'" class="align-middle">
<Checkbox :id="'prep-cmd-admin-' + i"
label="_common.elevated"
desc=""
v-model="c.elevated"
></Checkbox>
</td>
<td>
<button class="btn btn-danger" @click="editForm['prep-cmd'].splice(i,1)">
Expand Down Expand Up @@ -208,26 +206,30 @@ <h1>{{ $t('apps.applications_title') }}</h1>
<div id="appWorkingDirHelp" class="form-text">{{ $t('apps.working_dir_desc') }}</div>
</div>
<!-- elevation -->
<div class="mb-3 form-check" v-if="platform === 'windows'">
<label for="appElevation" class="form-check-label">{{ $t('_common.run_as') }}</label>
<input type="checkbox" class="form-check-input" id="appElevation" v-model="editForm.elevated"
true-value="true" false-value="false" />
<div class="form-text">{{ $t('apps.run_as_desc') }}</div>
</div>
<Checkbox v-if="platform === 'windows'"
class="mb-3"
id="appElevation"
label="_common.run_as"
desc="apps.run_as_desc"
v-model="editForm.elevated"
default="false"
></Checkbox>
<!-- auto-detach -->
<div class="mb-3 form-check">
<label for="autoDetach" class="form-check-label">{{ $t('apps.auto_detach') }}</label>
<input type="checkbox" class="form-check-input" id="autoDetach" v-model="editForm['auto-detach']"
true-value="true" false-value="false" />
<div class="form-text">{{ $t('apps.auto_detach_desc') }}</div>
</div>
<Checkbox class="mb-3"
id="autoDetach"
label="apps.auto_detach"
desc="apps.auto_detach_desc"
v-model="editForm['auto-detach']"
default="true"
></Checkbox>
<!-- wait for all processes -->
<div class="mb-3 form-check">
<label for="waitAll" class="form-check-label">{{ $t('apps.wait_all') }}</label>
<input type="checkbox" class="form-check-input" id="waitAll" v-model="editForm['wait-all']"
true-value="true" false-value="false" />
<div class="form-text">{{ $t('apps.wait_all_desc') }}</div>
</div>
<Checkbox class="mb-3"
id="waitAll"
label="apps.wait_all"
desc="apps.wait_all_desc"
v-model="editForm['wait-all']"
default="true"
></Checkbox>
<!-- exit timeout -->
<div class="mb-3">
<label for="exitTimeout" class="form-label">{{ $t('apps.exit_timeout') }}</label>
Expand Down Expand Up @@ -358,11 +360,13 @@ <h4>{{ $t('apps.env_vars_about') }}</h4>
import { createApp } from 'vue'
import { initApp } from './init'
import Navbar from './Navbar.vue'
import Checkbox from './Checkbox.vue'
import { Dropdown } from 'bootstrap/dist/js/bootstrap'

const app = createApp({
components: {
Navbar
Navbar,
Checkbox
},
data() {
return {
Expand Down Expand Up @@ -415,9 +419,9 @@ <h4>{{ $t('apps.env_vars_about') }}</h4>
if (this.editForm["detached"] === undefined)
this.editForm["detached"] = [];
if (this.editForm["exclude-global-prep-cmd"] === undefined)
this.editForm["exclude-global-prep-cmd"] = [];
this.editForm["exclude-global-prep-cmd"] = false;
if (this.editForm["elevated"] === undefined && this.platform === 'windows') {
this.editForm["elevated"] = [];
this.editForm["elevated"] = false;
}
if (this.editForm["auto-detach"] === undefined) {
this.editForm["auto-detach"] = true;
Expand Down
15 changes: 7 additions & 8 deletions src_assets/common/assets/web/configs/tabs/AudioVideo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import AdapterNameSelector from './audiovideo/AdapterNameSelector.vue'
import DisplayOutputSelector from './audiovideo/DisplayOutputSelector.vue'
import DisplayDeviceOptions from "./audiovideo/DisplayDeviceOptions.vue";
import DisplayModesSettings from "./audiovideo/DisplayModesSettings.vue";
import Checkbox from "../../Checkbox.vue";

const props = defineProps([
'platform',
Expand Down Expand Up @@ -54,14 +55,12 @@ const config = ref(props.config)
</div>

<!-- Install Steam Audio Drivers -->
<div class="mb-3">
<label for="install_steam_audio_drivers" class="form-label">{{ $t('config.install_steam_audio_drivers') }}</label>
<select id="install_steam_audio_drivers" class="form-select" v-model="config.install_steam_audio_drivers">
<option value="disabled">{{ $t('_common.disabled') }}</option>
<option value="enabled">{{ $t('_common.enabled_def') }}</option>
</select>
<div class="form-text">{{ $t('config.install_steam_audio_drivers_desc') }}</div>
</div>
<Checkbox class="mb-3"
id="install_steam_audio_drivers"
locale-prefix="config"
ReenigneArcher marked this conversation as resolved.
Show resolved Hide resolved
v-model="config.install_steam_audio_drivers"
default="true"
></Checkbox>
</template>
</PlatformLayout>

Expand Down
27 changes: 13 additions & 14 deletions src_assets/common/assets/web/configs/tabs/General.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup>
import Checkbox from '../../Checkbox.vue'
import { ref } from 'vue'

const props = defineProps({
Expand Down Expand Up @@ -100,12 +101,12 @@ function removeCmd(index) {
<td>
<input type="text" class="form-control monospace" v-model="c.undo" />
</td>
<td v-if="platform === 'windows'">
<div class="form-check">
<input type="checkbox" class="form-check-input" :id="'prep-cmd-admin-' + i" v-model="c.elevated"
true-value="true" false-value="false" />
<label :for="'prep-cmd-admin-' + i" class="form-check-label">{{ $t('config.elevated') }}</label>
</div>
<td v-if="platform === 'windows'" class="align-middle">
<Checkbox :id="'prep-cmd-admin-' + i"
label="_common.elevated"
desc=""
v-model="c.elevated"
></Checkbox>
</td>
<td>
<button class="btn btn-danger" @click="removeCmd(i)">
Expand All @@ -124,14 +125,12 @@ function removeCmd(index) {
</div>

<!-- Notify Pre-Releases -->
<div class="mb-3">
<label for="notify_pre_releases" class="form-label">{{ $t('config.notify_pre_releases') }}</label>
<select id="notify_pre_releases" class="form-select" v-model="config.notify_pre_releases">
<option value="disabled">{{ $t('_common.disabled') }}</option>
<option value="enabled">{{ $t('_common.enabled') }}</option>
</select>
<div class="form-text">{{ $t('config.notify_pre_releases_desc') }}</div>
</div>
<Checkbox class="mb-3"
id="notify_pre_releases"
locale-prefix="config"
v-model="config.notify_pre_releases"
default="false"
></Checkbox>
</div>
</template>

Expand Down
Loading
Loading