generated from Seekra/repository-template
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a17de3f132
|
||
|
|
1959be3b49
|
||
|
|
229087d3e6
|
||
|
|
c82a113b4e
|
@@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useSettingsStore } from '../stores/settingsStore';
|
import { useSettingsStore } from '../stores/settingsStore';
|
||||||
import { ref, useId, watch } from 'vue';
|
import { useId } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -35,16 +35,8 @@ const switchId = useId();
|
|||||||
|
|
||||||
const store = useSettingsStore();
|
const store = useSettingsStore();
|
||||||
|
|
||||||
const enabled = ref(null);
|
|
||||||
watch(store, (newStore) => {
|
|
||||||
enabled.value = newStore.get(props.path);
|
|
||||||
});
|
|
||||||
// set value after registering watcher to avoid immediate value change
|
|
||||||
enabled.value = store.get(props.path) ?? props.setting.default;
|
|
||||||
|
|
||||||
const toggle = function toggle () {
|
const toggle = function toggle () {
|
||||||
enabled.value = !enabled.value;
|
store.set(props.path, !store.get(props.path));
|
||||||
store.set(props.path, enabled.value);
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -55,7 +47,7 @@ const toggle = function toggle () {
|
|||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
class="switch-wrapper"
|
class="switch-wrapper"
|
||||||
:class="{ enabled }"
|
:class="{ enabled: store.get(props.path) }"
|
||||||
:title="t('settings.switch.title')"
|
:title="t('settings.switch.title')"
|
||||||
:aria-label="t('settings.switch.ariaLabel')"
|
:aria-label="t('settings.switch.ariaLabel')"
|
||||||
:aria-labelledby="labelId"
|
:aria-labelledby="labelId"
|
||||||
|
|||||||
@@ -20,23 +20,17 @@ import { useSettingsStore } from '../../stores/settingsStore.js';
|
|||||||
import { expect, describe, test } from 'vitest';
|
import { expect, describe, test } from 'vitest';
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
const getWrapper = function getWrapper ({
|
const getWrapper = function getWrapper ({ i18n = 'switch1', translations = {} } = {}) {
|
||||||
i18n = 'switch1',
|
|
||||||
defaultValue = undefined,
|
|
||||||
translations = {},
|
|
||||||
piniaOptions = {}
|
|
||||||
} = {}) {
|
|
||||||
return mountComponent(Switch, {
|
return mountComponent(Switch, {
|
||||||
attrs: {
|
attrs: {
|
||||||
setting: {
|
setting: {
|
||||||
type: 'bool',
|
type: 'bool',
|
||||||
name: 'switch',
|
name: 'switch',
|
||||||
i18n,
|
i18n
|
||||||
default: defaultValue
|
|
||||||
},
|
},
|
||||||
path: 'switch'
|
path: 'switch'
|
||||||
}
|
}
|
||||||
}, translations, [], piniaOptions);
|
}, translations);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Switch', () => {
|
describe('Switch', () => {
|
||||||
@@ -59,42 +53,6 @@ describe('Switch', () => {
|
|||||||
expect(switchElementClasses2).not.toContain('enabled');
|
expect(switchElementClasses2).not.toContain('enabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('shows default value', () => {
|
|
||||||
const wrapper = getWrapper({
|
|
||||||
defaultValue: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const switchElement = wrapper.find('.switch-wrapper');
|
|
||||||
expect(switchElement.classes('enabled')).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('shows stored value instead of default value', () => {
|
|
||||||
const wrapper = getWrapper({
|
|
||||||
defaultValue: true,
|
|
||||||
piniaOptions: {
|
|
||||||
setupStores: () => {
|
|
||||||
const store = useSettingsStore();
|
|
||||||
store.set('switch', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const switchElement = wrapper.find('.switch-wrapper');
|
|
||||||
expect(switchElement.classes('enabled')).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('reacts on store change', async () => {
|
|
||||||
const wrapper = getWrapper();
|
|
||||||
const store = useSettingsStore();
|
|
||||||
|
|
||||||
const switchElement = wrapper.find('.switch-wrapper');
|
|
||||||
expect(switchElement.classes('enabled')).toBeFalsy();
|
|
||||||
|
|
||||||
store.set('switch', true);
|
|
||||||
await nextTick();
|
|
||||||
expect(switchElement.classes('enabled')).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('toggles value in store', async () => {
|
test('toggles value in store', async () => {
|
||||||
const wrapper = getWrapper();
|
const wrapper = getWrapper();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 Seekra
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useSettingsConfigCacheStore } from '../../stores/settingsConfigCacheStore';
|
||||||
|
import { useSettingsStore } from '../../stores/settingsStore';
|
||||||
|
import { useSettings } from '../useSettings';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
|
import { setActivePinia } from 'pinia';
|
||||||
|
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
|
const settingDefaultValue = 42;
|
||||||
|
const settingPath = ['test', 'number'];
|
||||||
|
|
||||||
|
describe('useSettings', () => {
|
||||||
|
describe('getSetting', () => {
|
||||||
|
test('returns stored value', () => {
|
||||||
|
const { getSetting } = useSettings();
|
||||||
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
|
const key = 'setting';
|
||||||
|
const value = 42;
|
||||||
|
|
||||||
|
settings.set(key, value);
|
||||||
|
|
||||||
|
expect(getSetting(key)).toBe(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns default value', () => {
|
||||||
|
const { getSetting } = useSettings();
|
||||||
|
expect(getSetting(settingPath)).toBe(settingDefaultValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns stored value instead of default value', () => {
|
||||||
|
const { getSetting } = useSettings();
|
||||||
|
const settings = useSettingsStore();
|
||||||
|
|
||||||
|
const value = 43;
|
||||||
|
|
||||||
|
expect(getSetting(settingPath)).toBe(settingDefaultValue);
|
||||||
|
|
||||||
|
settings.set(settingPath, value);
|
||||||
|
expect(getSetting(settingPath)).toBe(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns undefined if there is no value', () => {
|
||||||
|
const { getSetting } = useSettings();
|
||||||
|
expect(getSetting(['test', 'bool'])).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(
|
||||||
|
createTestingPinia({
|
||||||
|
createSpy: vi.fn,
|
||||||
|
stubActions: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const settingsConfigCache = useSettingsConfigCacheStore();
|
||||||
|
settingsConfigCache.set({
|
||||||
|
contents: [
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
i18n: '',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'number',
|
||||||
|
i18n: '',
|
||||||
|
name: 'number',
|
||||||
|
default: settingDefaultValue
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'bool',
|
||||||
|
i18n: '',
|
||||||
|
name: 'bool'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 Seekra
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useSettingsConfigCacheStore } from '../stores/settingsConfigCacheStore';
|
||||||
|
import { useSettingsStore } from '../stores/settingsStore';
|
||||||
|
import { getSettingRecursively } from '../utils/getSetting';
|
||||||
|
import { loadSettingsConfig } from '../utils/settingsParser';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the stored settings.
|
||||||
|
*/
|
||||||
|
export const useSettings = function useSettings () {
|
||||||
|
/**
|
||||||
|
* Returns the value of a specific setting.
|
||||||
|
* @param {string[]} key - The settings key.
|
||||||
|
* @return The value of the setting.
|
||||||
|
*/
|
||||||
|
const getSetting = function getSetting (key) {
|
||||||
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
|
const settings = useSettingsConfigCacheStore().get();
|
||||||
|
return (
|
||||||
|
settingsStore.get(key) ??
|
||||||
|
getSettingRecursively(
|
||||||
|
key, settings.contents ?? []
|
||||||
|
)?.default
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { getSetting };
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 Seekra
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
export const useSettingsConfigCacheStore = defineStore('settingsConfigCache', () => {
|
||||||
|
let settingsConfig = undefined;
|
||||||
|
|
||||||
|
const set = function set (value) {
|
||||||
|
settingsConfig = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const get = function get () {
|
||||||
|
return settingsConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { set, get };
|
||||||
|
});
|
||||||
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useSettingsConfigCacheStore } from '../stores/settingsConfigCacheStore';
|
||||||
import { validateSettingsConfig } from './settingsValidator.js';
|
import { validateSettingsConfig } from './settingsValidator.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,10 +22,12 @@ import { validateSettingsConfig } from './settingsValidator.js';
|
|||||||
* @returns {Promise<import('../types/settingsConfig').SettingsConfig>}
|
* @returns {Promise<import('../types/settingsConfig').SettingsConfig>}
|
||||||
*/
|
*/
|
||||||
export async function loadSettingsConfig() {
|
export async function loadSettingsConfig() {
|
||||||
|
const settingsConfigCache = useSettingsConfigCacheStore();
|
||||||
let raw;
|
let raw;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
raw = (await import('../settings.json')).default;
|
raw = (await import('../settings.json')).default;
|
||||||
|
settingsConfigCache.set(raw);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`[settings] Failed to load settings.json: ${e.message}`);
|
throw new Error(`[settings] Failed to load settings.json: ${e.message}`);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user