mirror of
https://github.com/unraid/api.git
synced 2025-12-30 21:19:49 -06:00
feat: update os ignore release
This commit is contained in:
@@ -48,6 +48,7 @@ class ServerState
|
||||
private $caseModel = '';
|
||||
private $keyfileBase64UrlSafe = '';
|
||||
private $updateOsResponse;
|
||||
private $updateOsIgnoredReleases = [];
|
||||
|
||||
public $myServersFlashCfg = [];
|
||||
public $myServersMemoryCfg = [];
|
||||
@@ -168,6 +169,11 @@ class ServerState
|
||||
* updateOsResponse is provided by the dynamix.plugin.manager/scripts/unraidcheck script saving to /tmp/unraidcheck/result.json
|
||||
*/
|
||||
$this->updateOsResponse = @json_decode(@file_get_contents('/tmp/unraidcheck/result.json'), true);
|
||||
|
||||
/**
|
||||
* updateOsIgnoredReleases is set by the dynamix.plugin.manager/inclue/UnraidIgnore.php script saving to /tmp/unraidcheck/ignored.json
|
||||
*/
|
||||
$this->updateOsIgnoredReleases = @json_decode(@file_get_contents('/tmp/unraidcheck/ignored.json'), true) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,6 +259,10 @@ class ServerState
|
||||
$serverState['updateOsResponse'] = $this->updateOsResponse;
|
||||
}
|
||||
|
||||
if ($this->updateOsIgnoredReleases) {
|
||||
$serverState['updateOsIgnoredReleases'] = $this->updateOsIgnoredReleases;
|
||||
}
|
||||
|
||||
return $serverState;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,10 +88,23 @@ if (array_key_exists('json',$_GET) && $_GET['json']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// before sending a notification, check to see if the user requested to ignore the version
|
||||
$ignoredReleasesFile = '/tmp/unraidcheck/ignored.json';
|
||||
$ignoredReleasesResult = [];
|
||||
if (file_exists($ignoredReleasesFile)) {
|
||||
$ignoredData = json_decode(file_get_contents($ignoredReleasesFile), true);
|
||||
if (is_array($ignoredData) && array_key_exists('updateOsIgnoredReleases', $ignoredData)) {
|
||||
$ignoredReleasesResult = $ignoredData['updateOsIgnoredReleases'];
|
||||
}
|
||||
}
|
||||
|
||||
// send notification if a newer version is available
|
||||
if ($json && array_key_exists('isNewer',$json) && $json['isNewer']) {
|
||||
$isNewerVersion = array_key_exists('isNewer',$json) ? $json['isNewer'] : false;
|
||||
$isReleaseIgnored = in_array($json['version'], $ignoredReleasesResult);
|
||||
|
||||
if ($json && $isNewerVersion && !$isReleaseIgnored) {
|
||||
$newver = (array_key_exists('version',$json) && $json['version']) ? $json['version'] : 'unknown';
|
||||
exec("$script -e ".escapeshellarg("System - Unraid [$newver]")." -s ".escapeshellarg("Notice [$server] - Version update $newver")." -d ".escapeshellarg("A new version of Unraid is available")." -i ".escapeshellarg("normal $output")." -l '/Tools/Update' -x");
|
||||
}
|
||||
exit(0);
|
||||
?>
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
/**
|
||||
* @param removeAll {boolean} - if true, will remove all versions from the JSON file
|
||||
* @param removeVersion {string} - the version of the OS release we want to remove
|
||||
* @param version {string} - the version of the OS release we want to ignore
|
||||
*/
|
||||
$json_file_key = 'updateOsIgnoredReleases';
|
||||
$json_file = '/tmp/unraidcheck/ignored.json';
|
||||
|
||||
function isValidSemVerFormat($version) {
|
||||
return preg_match('/^\d+\.\d+(\.\d+)?(-.+)?$/',$version);
|
||||
}
|
||||
|
||||
// Ensure that the request is a GET request
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
|
||||
// Read the JSON data from the request body
|
||||
// $json_data = file_get_contents('php://input');
|
||||
$json_data = $_GET;
|
||||
|
||||
if (empty($json_data)) {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "No JSON data found";
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $json_data;
|
||||
|
||||
if ($data !== null) {
|
||||
// Check if the "removeAll" key exists in the $data array
|
||||
if (isset($data['removeAll']) && $data['removeAll'] === true) {
|
||||
|
||||
// Check if the JSON file exists
|
||||
if (file_exists($json_file)) {
|
||||
// Delete the JSON file
|
||||
unlink($json_file);
|
||||
// return empty array to represent no ignored versions
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([$json_file_key => []], JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "No JSON file found";
|
||||
}
|
||||
}
|
||||
// Check if the "removeVersion" key exists in the $data array
|
||||
else if (isset($data['removeVersion'])) {
|
||||
// Check if the "removeVersion" value is a valid PHP-standardized version number string
|
||||
$remove_version = $data['removeVersion'];
|
||||
if (isValidSemVerFormat($remove_version)) {
|
||||
// Check if the JSON file exists
|
||||
if (file_exists($json_file)) {
|
||||
// If the file exists, read its content
|
||||
$existing_data = json_decode(file_get_contents($json_file), true);
|
||||
|
||||
// Check if key exists
|
||||
if (isset($existing_data[$json_file_key])) {
|
||||
// Remove the specified version from the array
|
||||
$existing_data[$json_file_key] = array_diff($existing_data[$json_file_key], [$remove_version]);
|
||||
|
||||
// Save the updated data to the JSON file
|
||||
file_put_contents($json_file, json_encode($existing_data, JSON_PRETTY_PRINT));
|
||||
|
||||
http_response_code(200); // OK
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($existing_data, JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "No versions to remove in the JSON file";
|
||||
}
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "No JSON file found";
|
||||
}
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "Invalid removeVersion format";
|
||||
}
|
||||
}
|
||||
// Check if the "version" key exists in the $data array
|
||||
else if (isset($data['version'])) {
|
||||
|
||||
// Check if the "version" value is a valid PHP-standardized version number string
|
||||
$version = $data['version'];
|
||||
if (isValidSemVerFormat($version)) {
|
||||
// Prepare the new data structure
|
||||
$new_data = [$json_file_key => [$version]];
|
||||
|
||||
// Check if the JSON file already exists
|
||||
if (file_exists($json_file)) {
|
||||
// If the file exists, read its content
|
||||
$existing_data = json_decode(file_get_contents($json_file), true);
|
||||
|
||||
// Check if key already exists
|
||||
if (isset($existing_data[$json_file_key])) {
|
||||
// Append the new version to the existing array
|
||||
$existing_data[$json_file_key][] = $version;
|
||||
} else {
|
||||
// If key doesn't exist, create it
|
||||
$existing_data[$json_file_key] = [$version];
|
||||
}
|
||||
|
||||
// Update the data to be saved
|
||||
$new_data = $existing_data;
|
||||
}
|
||||
|
||||
// Save the data to the JSON file
|
||||
file_put_contents($json_file, json_encode($new_data, JSON_PRETTY_PRINT));
|
||||
|
||||
http_response_code(200); // OK
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($new_data, JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "Invalid version format";
|
||||
}
|
||||
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "Invalid param data";
|
||||
}
|
||||
|
||||
} else {
|
||||
http_response_code(400); // Bad Request
|
||||
echo "Error decoding JSON data";
|
||||
}
|
||||
|
||||
} else {
|
||||
// Handle non-GET requests
|
||||
http_response_code(405); // Method Not Allowed
|
||||
echo "Only GET requests are allowed";
|
||||
}
|
||||
34
web/components/Ui/Switch.vue
Normal file
34
web/components/Ui/Switch.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<script setup lang="ts">
|
||||
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
|
||||
|
||||
export interface Props {
|
||||
label?: string;
|
||||
// propChecked?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
label: '',
|
||||
// propChecked: false,
|
||||
});
|
||||
|
||||
const checked = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SwitchGroup>
|
||||
<div class="flex items-center gap-8px p-8px rounded">
|
||||
<Switch
|
||||
v-model="checked"
|
||||
:class="checked ? 'bg-gradient-to-r from-unraid-red to-orange' : 'bg-transparent'"
|
||||
class="relative inline-flex h-24px w-[48px] items-center rounded-full overflow-hidden"
|
||||
>
|
||||
<span v-show="!checked" class="absolute z-0 inset-0 opacity-10 bg-beta" />
|
||||
<span
|
||||
:class="checked ? 'translate-x-[26px]' : 'translate-x-[2px]'"
|
||||
class="inline-block h-20px w-20px transform rounded-full bg-white transition"
|
||||
/>
|
||||
</Switch>
|
||||
<SwitchLabel>{{ label }}</SwitchLabel>
|
||||
</div>
|
||||
</SwitchGroup>
|
||||
</template>
|
||||
@@ -7,7 +7,6 @@ import { useAccountStore } from '~/store/account';
|
||||
import { usePurchaseStore } from '~/store/purchase';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
// import { useUpdateOsActionsStore } from '~/store/updateOsActions';
|
||||
import { useUpdateOsChangelogStore } from '~/store/updateOsChangelog';
|
||||
import type { ButtonProps } from '~/types/ui/button';
|
||||
|
||||
@@ -24,10 +23,9 @@ const accountStore = useAccountStore();
|
||||
const purchaseStore = usePurchaseStore();
|
||||
const serverStore = useServerStore();
|
||||
const updateOsStore = useUpdateOsStore();
|
||||
// const updateOsActionsStore = useUpdateOsActionsStore();
|
||||
const updateOsChangelogStore = useUpdateOsChangelogStore();
|
||||
|
||||
const { osVersionBranch, updateOsResponse } = storeToRefs(serverStore);
|
||||
const { osVersionBranch, updateOsResponse, updateOsIgnoredReleases } = storeToRefs(serverStore);
|
||||
const { available, availableWithRenewal, checkForUpdatesLoading } = storeToRefs(updateOsStore);
|
||||
|
||||
interface ModalCopy {
|
||||
@@ -109,13 +107,13 @@ const close = () => {
|
||||
// then ignore the release if applicable
|
||||
if (ignoreThisRelease.value && (availableWithRenewal.value || available.value)) {
|
||||
setTimeout(() => {
|
||||
updateOsStore.ignoreRelease(availableWithRenewal.value ?? available.value ?? '');
|
||||
serverStore.updateOsIgnoreRelease(availableWithRenewal.value ?? available.value ?? '');
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
const renderMainSlot = computed(() => {
|
||||
return checkForUpdatesLoading.value || available.value || availableWithRenewal.value;
|
||||
return checkForUpdatesLoading.value || available.value || availableWithRenewal.value || updateOsIgnoredReleases.value.length > 0;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -145,10 +143,21 @@ const renderMainSlot = computed(() => {
|
||||
class="inline-block h-20px w-20px transform rounded-full bg-white transition"
|
||||
/>
|
||||
</Switch>
|
||||
<SwitchLabel>Ignore this release</SwitchLabel>
|
||||
<SwitchLabel>{{ t('Ignore this release') }}</SwitchLabel>
|
||||
</div>
|
||||
</SwitchGroup>
|
||||
</div>
|
||||
<div v-else-if="updateOsIgnoredReleases.length > 0" class="w-full flex flex-col gap-8px my-24px">
|
||||
<h3 class="text-16px font-semibold italic">
|
||||
{{ t('Ignored Releases') }}
|
||||
</h3>
|
||||
<UpdateOsIgnoredRelease
|
||||
v-for="ignoredRelease in updateOsIgnoredReleases"
|
||||
:key="ignoredRelease"
|
||||
:label="ignoredRelease"
|
||||
:t="t"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="!checkForUpdatesLoading" #footer>
|
||||
|
||||
38
web/components/UpdateOs/IgnoredRelease.vue
Normal file
38
web/components/UpdateOs/IgnoredRelease.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import { XMarkIcon } from '@heroicons/vue/24/solid';
|
||||
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useThemeStore } from '~/store/theme';
|
||||
|
||||
export interface Props {
|
||||
label: string;
|
||||
t: any;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
label: '',
|
||||
});
|
||||
|
||||
const serverStore = useServerStore();
|
||||
const { darkMode } = storeToRefs(useThemeStore());
|
||||
|
||||
const evenBgColor = computed(() => {
|
||||
return darkMode.value ? 'even:bg-grey-darkest' : 'even:bg-black/5';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="text-16px p-12px flex flex-row gap-4px sm:px-20px sm:gap-16px items-center justify-between rounded"
|
||||
:class="evenBgColor"
|
||||
>
|
||||
<span class="font-semibold">{{ label }}</span>
|
||||
<BrandButton
|
||||
:btn-style="'underline'"
|
||||
:icon-right="XMarkIcon"
|
||||
:text="t('Remove')"
|
||||
:title="t('Remove from ignore list')"
|
||||
@click="serverStore.updateOsRemoveIgnoredRelease(label)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
13
web/components/UpdateOs/IgnoredReleases.vue
Normal file
13
web/components/UpdateOs/IgnoredReleases.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { useServerStore } from '~/store/server';
|
||||
const serverStore = useServerStore();
|
||||
const { updateOsIgnoredReleases } = storeToRefs(serverStore);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UpdateOsIgnoredRelease
|
||||
v-for="ignoredRelease in updateOsIgnoredReleases"
|
||||
:key="ignoredRelease"
|
||||
:label="ignoredRelease"
|
||||
/>
|
||||
</template>
|
||||
@@ -118,3 +118,30 @@ export const WebguiCheckForUpdate = async (): Promise<ServerUpdateOsResponse | u
|
||||
throw new Error('Error checking for updates');
|
||||
}
|
||||
};
|
||||
|
||||
export interface WebguiUpdateIgnorePayload {
|
||||
removeAll?: boolean;
|
||||
removeVersion?: string;
|
||||
version?: string;
|
||||
}
|
||||
export const WebguiUpdateIgnore = async (payload: WebguiUpdateIgnorePayload): Promise<any | void> => {
|
||||
console.debug('[WebguiUpdateIgnore] payload', payload);
|
||||
try {
|
||||
const response = await request
|
||||
.url('/plugins/dynamix.plugin.manager/include/UnraidIgnore.php')
|
||||
.query(payload)
|
||||
.get()
|
||||
.json((json) => {
|
||||
console.debug('[WebguiUpdateIgnore] response', json);
|
||||
return json;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[WebguiUpdateIgnore] catch failed to execute UpdateIgnore', error);
|
||||
throw new Error('Error ignoring update');
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('[WebguiUpdateIgnore] catch failed to execute UpdateIgnore', error);
|
||||
throw new Error('Error ignoring update');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -344,5 +344,8 @@
|
||||
"Extend Key to Update": "Extend Key to Update",
|
||||
"Install Unraid OS {0}": "Install Unraid OS {0}",
|
||||
"View Changelog to Start Update": "View Changelog to Start Update",
|
||||
"Unraid OS {0} Update Available": "Unraid OS {0} Update Available"
|
||||
"Unraid OS {0} Update Available": "Unraid OS {0} Update Available",
|
||||
"Remove": "Remove",
|
||||
"Remove from ignore list": "Remove from ignore list",
|
||||
"Ignored Releases": "Ignored Releases"
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { useQuery } from '@vue/apollo-composable';
|
||||
|
||||
import { SERVER_CLOUD_FRAGMENT, SERVER_STATE_QUERY } from './server.fragment';
|
||||
import { useFragment } from '~/composables/gql/fragment-masking';
|
||||
import { WebguiState } from '~/composables/services/webgui';
|
||||
import { WebguiState, WebguiUpdateIgnore } from '~/composables/services/webgui';
|
||||
import { WEBGUI_SETTINGS_MANAGMENT_ACCESS } from '~/helpers/urls';
|
||||
import { useAccountStore } from '~/store/account';
|
||||
import { useErrorsStore, type Error } from '~/store/errors';
|
||||
@@ -117,6 +117,7 @@ export const useServerStore = defineStore('server', () => {
|
||||
if (newVal) { themeStore.setTheme(newVal); }
|
||||
});
|
||||
const updateOsResponse = ref<ServerUpdateOsResponse>();
|
||||
const updateOsIgnoredReleases = ref<string[]>([]);
|
||||
const uptime = ref<number>(0);
|
||||
const username = ref<string>(''); // @todo potentially move to a user store
|
||||
const wanFQDN = ref<string>('');
|
||||
@@ -822,6 +823,7 @@ export const useServerStore = defineStore('server', () => {
|
||||
if (typeof data?.state !== 'undefined') { state.value = data.state; }
|
||||
if (typeof data?.theme !== 'undefined') { theme.value = data.theme; }
|
||||
if (typeof data?.updateOsResponse !== 'undefined') { updateOsResponse.value = data.updateOsResponse; }
|
||||
if (typeof data?.updateOsIgnoredReleases !== 'undefined') { updateOsIgnoredReleases.value = data.updateOsIgnoredReleases; }
|
||||
if (typeof data?.uptime !== 'undefined') { uptime.value = data.uptime; }
|
||||
if (typeof data?.username !== 'undefined') { username.value = data.username; }
|
||||
if (typeof data?.wanFQDN !== 'undefined') { wanFQDN.value = data.wanFQDN; }
|
||||
@@ -965,6 +967,31 @@ export const useServerStore = defineStore('server', () => {
|
||||
}
|
||||
});
|
||||
|
||||
const updateOsIgnoreRelease = (release: string) => {
|
||||
updateOsIgnoredReleases.value.push(release);
|
||||
const response = WebguiUpdateIgnore({
|
||||
version: release,
|
||||
});
|
||||
console.debug('[updateOsIgnoreRelease] response', response);
|
||||
/** @todo when update check modal is displayed and there's no available updates, allow users to remove ignored releases from the list */
|
||||
};
|
||||
|
||||
const updateOsRemoveIgnoredRelease = (release: string) => {
|
||||
updateOsIgnoredReleases.value = updateOsIgnoredReleases.value.filter(r => r !== release);
|
||||
const response = WebguiUpdateIgnore({
|
||||
removeVersion: release,
|
||||
});
|
||||
console.debug('[updateOsRemoveIgnoredRelease] response', response);
|
||||
};
|
||||
|
||||
const updateOsRemoveAllIgnoredReleases = () => {
|
||||
updateOsIgnoredReleases.value = [];
|
||||
const response = WebguiUpdateIgnore({
|
||||
removeAll: true,
|
||||
});
|
||||
console.debug('[updateOsRemoveAllIgnoredReleases] response', response);
|
||||
};
|
||||
|
||||
return {
|
||||
// state
|
||||
apiKey,
|
||||
@@ -1003,6 +1030,7 @@ export const useServerStore = defineStore('server', () => {
|
||||
site,
|
||||
state,
|
||||
theme,
|
||||
updateOsIgnoredReleases,
|
||||
updateOsResponse,
|
||||
uptime,
|
||||
username,
|
||||
@@ -1030,5 +1058,8 @@ export const useServerStore = defineStore('server', () => {
|
||||
refreshServerState,
|
||||
filteredKeyActions,
|
||||
setRebootVersion,
|
||||
updateOsIgnoreRelease,
|
||||
updateOsRemoveIgnoredRelease,
|
||||
updateOsRemoveAllIgnoredReleases,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -17,31 +17,24 @@ setActivePinia(createPinia());
|
||||
extend(customParseFormat);
|
||||
extend(relativeTime);
|
||||
|
||||
const KEY_IGNORED_RELEASES = 'updateOsIgnoredReleases';
|
||||
|
||||
export const useUpdateOsStore = defineStore('updateOs', () => {
|
||||
// state
|
||||
const checkForUpdatesLoading = ref<boolean>(false);
|
||||
const modalOpen = ref<boolean>(false);
|
||||
const ignoredReleases = ref<string[]>(
|
||||
localStorage.getItem(KEY_IGNORED_RELEASES)
|
||||
? (JSON.parse(localStorage.getItem(KEY_IGNORED_RELEASES) ?? '') ?? [])
|
||||
: []
|
||||
);
|
||||
|
||||
// getters from other stores
|
||||
const serverStore = useServerStore();
|
||||
|
||||
const regExp = computed(() => serverStore.regExp);
|
||||
const regUpdatesExpired = computed(() => serverStore.regUpdatesExpired);
|
||||
const updateOsResponse = computed(() => serverStore.updateOsResponse);
|
||||
const updateOsIgnoredReleases = computed(() => serverStore.updateOsIgnoredReleases);
|
||||
// local getters
|
||||
const available = computed(() => {
|
||||
if (!updateOsResponse.value) {
|
||||
return undefined;
|
||||
}
|
||||
// ignore any releases that are in the ignoredReleases array
|
||||
if (ignoredReleases.value.includes(updateOsResponse.value.version)) {
|
||||
// ignore any releases that are in the updateOsIgnoredReleases array
|
||||
if (updateOsIgnoredReleases.value.includes(updateOsResponse.value.version)) {
|
||||
return undefined;
|
||||
}
|
||||
return updateOsResponse.value.isNewer ? updateOsResponse.value.version : undefined;
|
||||
@@ -83,25 +76,17 @@ export const useUpdateOsStore = defineStore('updateOs', () => {
|
||||
modalOpen.value = val;
|
||||
};
|
||||
|
||||
const ignoreRelease = (release: string) => {
|
||||
ignoredReleases.value.push(release);
|
||||
localStorage.setItem(KEY_IGNORED_RELEASES, JSON.stringify(ignoredReleases.value));
|
||||
/** @todo submit to an endpoint on the server to save to a file */
|
||||
/** @todo when update check modal is displayed and there's no available updates, allow users to remove ignored releases from the list */
|
||||
};
|
||||
|
||||
return {
|
||||
// state
|
||||
available,
|
||||
availableWithRenewal,
|
||||
checkForUpdatesLoading,
|
||||
modalOpen,
|
||||
ignoredReleases,
|
||||
updateOsIgnoredReleases,
|
||||
// getters
|
||||
availableReleaseDate,
|
||||
// actions
|
||||
localCheckForUpdate,
|
||||
setModalOpen,
|
||||
ignoreRelease,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -101,6 +101,7 @@ export interface Server {
|
||||
state?: ServerState;
|
||||
theme?: Theme | undefined;
|
||||
updateOsResponse?: ServerUpdateOsResponse;
|
||||
updateOsIgnoredReleases?: string[];
|
||||
uptime?: number;
|
||||
username?: string;
|
||||
wanFQDN?: string;
|
||||
|
||||
Reference in New Issue
Block a user