mirror of
https://github.com/Lissy93/personal-security-checklist.git
synced 2024-10-01 01:35:37 -04:00
Adds reccomended software functionality to sections
This commit is contained in:
parent
9439d7f490
commit
81e77ed22d
@ -119,21 +119,52 @@ export default component$((props: { section: Section }) => {
|
||||
filterState.show = originalFilters.show;
|
||||
});
|
||||
|
||||
const calculateProgress = (): { done: number, total: number, percent: number, disabled: number} => {
|
||||
let done = 0;
|
||||
let disabled = 0;
|
||||
let total = 0;
|
||||
|
||||
props.section.checklist.forEach((item) => {
|
||||
const itemId = generateId(item.point);
|
||||
if (isIgnored(itemId)) {
|
||||
disabled += 1;
|
||||
} else if (isChecked(itemId)) {
|
||||
done += 1;
|
||||
total += 1;
|
||||
} else {
|
||||
total += 1;
|
||||
}
|
||||
});
|
||||
|
||||
const percent = Math.round((done / total) * 100);
|
||||
return { done, total: props.section.checklist.length, percent, disabled };
|
||||
};
|
||||
|
||||
const { done, total, percent, disabled } = calculateProgress();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<div class="flex flex-wrap justify-between items-center">
|
||||
<div>
|
||||
<progress class="progress w-64" value={percent} max="100"></progress>
|
||||
<p class="text-xs text-center">
|
||||
{done} out of {total} ({percent}%)
|
||||
complete, {disabled} ignored</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-2 justify-end my-4">
|
||||
{(sortState.column || JSON.stringify(filterState) !== JSON.stringify(originalFilters)) && (
|
||||
<button class="btn btn-sm hover:btn-primary" onClick$={resetFilters}>
|
||||
<Icon width={18} height={16} icon="clear"/>
|
||||
Reset Filters
|
||||
<div class="flex flex-wrap gap-2 justify-end my-4">
|
||||
{(sortState.column || JSON.stringify(filterState) !== JSON.stringify(originalFilters)) && (
|
||||
<button class="btn btn-sm hover:btn-primary" onClick$={resetFilters}>
|
||||
<Icon width={18} height={16} icon="clear"/>
|
||||
Reset Filters
|
||||
</button>
|
||||
)}
|
||||
<button class="btn btn-sm hover:btn-primary" onClick$={() => { showFilters.value = !showFilters.value; }}>
|
||||
<Icon width={18} height={16} icon="filters"/>
|
||||
{showFilters.value ? 'Hide' : 'Show'} Filters
|
||||
</button>
|
||||
)}
|
||||
<button class="btn btn-sm hover:btn-primary" onClick$={() => { showFilters.value = !showFilters.value; }}>
|
||||
<Icon width={18} height={16} icon="filters"/>
|
||||
{showFilters.value ? 'Hide' : 'Show'} Filters
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showFilters.value && (
|
||||
|
@ -1,6 +1,6 @@
|
||||
// src/routes/articles/[slug].tsx
|
||||
import { component$, Resource, useResource$, useStore } from '@builder.io/qwik';
|
||||
import { useLocation } from '@builder.io/qwik-city';
|
||||
import { type DocumentHead, useLocation, useDocumentHead } from '@builder.io/qwik-city';
|
||||
import { marked } from "marked";
|
||||
|
||||
import articles from '~/data/articles';
|
||||
@ -14,6 +14,20 @@ export default component$(() => {
|
||||
const slug = location.params.slug;
|
||||
const article = articles.find(a => a.slug === slug);
|
||||
|
||||
// useDocumentHead(() => {
|
||||
// if (!article) {
|
||||
// return {
|
||||
// title: '404 Not Found | Your Site Name',
|
||||
// meta: [{ name: 'description', content: 'The requested article was not found.' }],
|
||||
// };
|
||||
// }
|
||||
|
||||
// return {
|
||||
// title: `${article.title} | Your Site Name`,
|
||||
// meta: [{ name: 'description', content: article.description }],
|
||||
// };
|
||||
// });
|
||||
|
||||
const parseMarkdown = (text: string | undefined): string => {
|
||||
if (!text) return '';
|
||||
|
||||
@ -98,3 +112,13 @@ export default component$(() => {
|
||||
);
|
||||
});
|
||||
|
||||
export const head: DocumentHead = {
|
||||
title: "Article | Digital Defense",
|
||||
meta: [
|
||||
{
|
||||
name: "description",
|
||||
content: "",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -4,19 +4,17 @@ import { marked } from 'marked';
|
||||
|
||||
import Icon from '~/components/core/icon';
|
||||
import { ChecklistContext } from '~/store/checklist-context';
|
||||
import { useChecklist } from '~/store/local-checklist-store';
|
||||
import type { Section } from "~/types/PSC";
|
||||
import Table from '~/components/psc/checklist-table';
|
||||
|
||||
export default component$(() => {
|
||||
|
||||
const checklists = useContext(ChecklistContext);
|
||||
const localChecklist = useChecklist();
|
||||
|
||||
const loc = useLocation();
|
||||
const slug = loc.params.title;
|
||||
|
||||
const section: Section | undefined = (localChecklist.checklist.checklist || checklists.value)
|
||||
const section: Section | undefined = (checklists.value)
|
||||
.find((item: Section) => item.slug === slug);
|
||||
|
||||
const parseMarkdown = (text: string | undefined): string => {
|
||||
@ -36,6 +34,20 @@ export default component$(() => {
|
||||
{section && (<Table section={section} />)}
|
||||
</div>
|
||||
|
||||
{section && section.softwareLinks && (
|
||||
<>
|
||||
<div class="divider my-4">Useful Links</div>
|
||||
<h3 class="text-xl my-2">Recommended Software</h3>
|
||||
<ul class="list-disc pl-4">
|
||||
{section.softwareLinks.map((link, index) => (
|
||||
<li key={index}>
|
||||
<a class="link link-primary" href={link.url} title={link.description}>{link.title}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
|
||||
</article>
|
||||
</div>
|
||||
);
|
||||
|
@ -8,7 +8,7 @@ import { ChecklistContext } from "~/store/checklist-context";
|
||||
import type { Sections } from "~/types/PSC";
|
||||
|
||||
export const useChecklists = routeLoader$(async () => {
|
||||
const remoteUrl = 'https://gist.githubusercontent.com/Lissy93/0c26e4255b6fabc2c027ac72a4428aeb/raw/4ccdbc71e0fffdef53472cf98acbe40b0acf982b/personal-security-checklist.yml';
|
||||
const remoteUrl = 'https://gist.githubusercontent.com/Lissy93/0c26e4255b6fabc2c027ac72a4428aeb/raw/c36fc0430df223534eaf76c035943f4b343915e4/personal-security-checklist.yml';
|
||||
// TODO: Update this URL to point to the Git repository
|
||||
return fetch(remoteUrl)
|
||||
.then((res) => res.text())
|
||||
|
@ -13,7 +13,9 @@ export interface Section {
|
||||
icon: string,
|
||||
color: string,
|
||||
checklist: Checklist[],
|
||||
furtherLinks?: FurtherLink[],
|
||||
softwareLinks?: Link[],
|
||||
helpfulTools?: Link[],
|
||||
furtherResources?: Link[],
|
||||
}
|
||||
|
||||
export type Priority = 'recommended' | 'optional' | 'advanced';
|
||||
@ -24,8 +26,8 @@ export interface Checklist {
|
||||
details: string,
|
||||
}
|
||||
|
||||
export interface FurtherLink {
|
||||
export interface Link {
|
||||
title: string,
|
||||
url: string,
|
||||
description: string,
|
||||
description?: string,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user