Homarr v0.11
{active === 0 && "Good to see you back! Let's get started"}
{active === 1 && progress !== 100 && 'Migrating your configs'}
{active === 1 && progress === 100 && 'Migration complete!'}
A few things have changed since the last time you used Homarr. We'll
help you migrate your old configuration to the new format. This process is automatic
and should take less than a minute. Then, you'll be able to use the new
features of Homarr!
}
title="Please make a backup of your configs!"
color="red"
radius="md"
variant="outline"
>
Please make sure to have a backup of your configs in case something goes wrong.{' '}
Not all settings can be migrated, so you'll have to re-do some
configuration yourself.
}
label="Step 2"
description="Migrating your configs"
>
Homarr v0.11 brings a lot of new features, if you are interested in learning
about them, please check out the{' '}
documentation page
That's it ! We hope you enjoy the new flexibility v0.11 brings. If you spot any
bugs make sure to report them as a{' '}
github issue{' '}
or directly on the
discord !
}
onClick={active === 3 ? () => window.location.reload() : nextStep}
variant="filled"
disabled={active === 1 && progress < 100}
>
{active === 3 ? 'Finish' : 'Next'}
);
}
function SwitchToggle() {
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
const theme = useMantineTheme();
return (
toggleColorScheme()}
size="lg"
onLabel={}
offLabel={}
/>
);
}
export async function getServerSideProps({ req, res, locale }: GetServerSidePropsContext) {
// Get all the configs in the /data/configs folder
const configs = fs.readdirSync('./data/configs');
if (configs.length === 0) {
res.writeHead(302, {
Location: '/',
});
res.end();
return { props: {} };
}
// If all the configs are migrated (contains a schemaVersion), redirect to the index
if (
configs.every(
(config) => JSON.parse(fs.readFileSync(`./data/configs/${config}`, 'utf8')).schemaVersion
)
) {
res.writeHead(302, {
Location: '/',
});
res.end();
return {
processed: true,
};
}
return {
props: {
configs: configs.map(
// Get all the file names in ./data/configs
(config) => config.replace('.json', '')
),
...(await serverSideTranslations(locale!, [])),
// Will be passed to the page component as props
},
};
}
const ICON_SIZE = 60;
export function StatsCard({
configs,
progress,
setProgress,
}: {
configs: string[];
progress: number;
setProgress: (progress: number) => void;
}) {
const { classes } = useStyles();
const numberOfConfigs = configs.length;
// Update the progress every 100ms
const [treatedConfigs, setTreatedConfigs] = useState([]);
// Stop the progress at 100%
useEffect(() => {
const data = axios.post('/api/migrate').then((response) => {
setProgress(100);
});
const interval = setInterval(() => {
if (configs.length === 0) {
clearInterval(interval);
setProgress(100);
return;
}
// Add last element of configs to the treatedConfigs array
setTreatedConfigs((treatedConfigs) => [...treatedConfigs, configs[configs.length - 1]]);
// Remove last element of configs
configs.pop();
}, 500);
return () => clearInterval(interval);
}, [configs]);
return (
Progress
{(100 / (numberOfConfigs + 1)).toFixed(1)}%
}
>
{configs.map((config, index) => (
}>
{config ?? 'Unknown'}
))}
{treatedConfigs.map((config, index) => (
{config ?? 'Unknown'}
))}
{configs.length} configs left
);
}