mirror of
https://github.com/Lissy93/awesome-privacy.git
synced 2026-03-11 08:55:33 +00:00
Adds edit functionality
This commit is contained in:
parent
282e3bc060
commit
7fef7d3edd
14 changed files with 467 additions and 13 deletions
|
|
@ -5,7 +5,7 @@ import FontAwesome from "@components/form/FontAwesome.svelte"
|
|||
<div class="hero">
|
||||
<h1>Awesome Privacy</h1>
|
||||
<p class="intro">
|
||||
Your guide to finding privacy-respecting alternatives to popular software and services.
|
||||
Your guide to finding and comparing privacy-respecting alternatives to popular software and services.
|
||||
</p>
|
||||
<div class="github-link-wrap">
|
||||
<a href="https://github.com/lissy93/awesome-privacy">
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ const {
|
|||
text,
|
||||
url,
|
||||
className,
|
||||
title,
|
||||
} = Astro.props;
|
||||
|
||||
---
|
||||
|
||||
<div class={`button ${className || ''}`}>
|
||||
<div class={`button ${className || ''}`} title={title}>
|
||||
<a href={url}>{text}<slot /></a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
// Service actions
|
||||
delete: solidIcons.faTrash,
|
||||
edit: solidIcons.faPenToSquare,
|
||||
add: solidIcons.faPlusHexagon,
|
||||
|
||||
// Website Detailed Stats
|
||||
blacklistFound: solidIcons.faDoNotEnter,
|
||||
|
|
|
|||
300
web/src/components/things/AddNewService.svelte
Normal file
300
web/src/components/things/AddNewService.svelte
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
<script lang="ts">
|
||||
import yaml from 'js-yaml';
|
||||
import { writable } from 'svelte/store';
|
||||
import { makeAdditionRequest } from '../../utils/data-src-delete-n-edit';
|
||||
|
||||
// Defining writable stores for each form field
|
||||
const listingCategory = writable('');
|
||||
const serviceName = writable('');
|
||||
const serviceUrl = writable('');
|
||||
const serviceIcon = writable('');
|
||||
const serviceDescription = writable('');
|
||||
const serviceGithub = writable('');
|
||||
const serviceTosdrId = writable('');
|
||||
const serviceOpenSource = writable(false);
|
||||
const serviceSecurityAudited = writable(false);
|
||||
const serviceCrypto = writable(false);
|
||||
const additionalInfo = writable('');
|
||||
|
||||
$: yamlText = yaml.dump([{
|
||||
name: $serviceName,
|
||||
url: $serviceUrl,
|
||||
icon: $serviceIcon,
|
||||
description: $serviceDescription,
|
||||
github: $serviceGithub,
|
||||
tosdrId: $serviceTosdrId,
|
||||
openSource: $serviceOpenSource,
|
||||
securityAudited: $serviceSecurityAudited,
|
||||
acceptsCrypto: $serviceCrypto,
|
||||
}]);
|
||||
|
||||
$: issueUrl = makeAdditionRequest({
|
||||
listingCategory: $listingCategory,
|
||||
serviceName: $serviceName,
|
||||
serviceUrl: $serviceUrl,
|
||||
serviceIcon: $serviceIcon,
|
||||
serviceDescription: $serviceDescription,
|
||||
serviceGithub: $serviceGithub,
|
||||
serviceTosdrId: $serviceTosdrId,
|
||||
serviceOpenSource: $serviceOpenSource,
|
||||
serviceSecurityAudited: $serviceSecurityAudited,
|
||||
serviceCrypto: $serviceCrypto,
|
||||
additionalInfo: $additionalInfo,
|
||||
}, yamlText);
|
||||
|
||||
// Form submission handler
|
||||
function handleSubmit() {
|
||||
const formData = {
|
||||
listingCategory: $listingCategory,
|
||||
serviceName: $serviceName,
|
||||
serviceUrl: $serviceUrl,
|
||||
serviceIcon: $serviceIcon,
|
||||
serviceDescription: $serviceDescription,
|
||||
serviceGithub: $serviceGithub,
|
||||
serviceTosdrId: $serviceTosdrId,
|
||||
serviceOpenSource: $serviceOpenSource,
|
||||
serviceSecurityAudited: $serviceSecurityAudited,
|
||||
serviceCrypto: $serviceCrypto,
|
||||
additionalInfo: $additionalInfo,
|
||||
};
|
||||
const issueCreationUrl = makeAdditionRequest(formData, yamlText);
|
||||
window.open(issueCreationUrl, '_blank');
|
||||
}
|
||||
</script>
|
||||
|
||||
<p>
|
||||
Before completing this form, you must ensure that the service you are adding aligns
|
||||
with the <a href="/about#creteria">Requirements</a> for Awesome Privacy.
|
||||
<br />
|
||||
You'll need a GitHub account in order to submit this form.
|
||||
</p>
|
||||
|
||||
<form on:submit|preventDefault={handleSubmit}>
|
||||
<!-- Category Dropdown -->
|
||||
<div class="form-row">
|
||||
<label for="listing-category">Category</label>
|
||||
<select bind:value={$listingCategory} id="listing-category" required autocomplete="off">
|
||||
<option value="">--Please choose an option--</option>
|
||||
<option value="Essentials">Essentials</option>
|
||||
<option value="Communication">Communication</option>
|
||||
<option value="Security Tools">Security Tools</option>
|
||||
<option value="Networking">Networking</option>
|
||||
<option value="Productivity">Productivity</option>
|
||||
<option value="Utilities">Utilities</option>
|
||||
<option value="Operating Systems">Operating Systems</option>
|
||||
<option value="Development">Development</option>
|
||||
<option value="Home and IoT">Home and IoT</option>
|
||||
<option value="Finance">Finance</option>
|
||||
<option value="Social">Social</option>
|
||||
<option value="Media">Media</option>
|
||||
<option value="Creativity">Creativity</option>
|
||||
</select>
|
||||
<p>
|
||||
Choose the top-level category, which should align with
|
||||
the <a href="/browse">one of these</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Listing Name -->
|
||||
<div class="form-row">
|
||||
<label for="service-name">Listing Name</label>
|
||||
<input type="text" bind:value={$serviceName} id="service-name" required autocomplete="off">
|
||||
<p>Enter the name of the app, software or service</p>
|
||||
</div>
|
||||
|
||||
<!-- Listing URL -->
|
||||
<div class="form-row">
|
||||
<label for="service-url">Listing URL</label>
|
||||
<input type="url" bind:value={$serviceUrl} id="service-url" required autocomplete="off">
|
||||
<p>Enter the fully-qualified domain name of the homepage for this listing</p>
|
||||
</div>
|
||||
|
||||
<!-- Listing Icon -->
|
||||
<div class="form-row">
|
||||
<label for="service-icon">Listing Icon</label>
|
||||
<input type="url" bind:value={$serviceIcon} id="service-icon" required autocomplete="off">
|
||||
<p>Paste a URL to a square logo for the service. Dimensions must be no less than 64x64, and no more than 512x512 pixels</p>
|
||||
</div>
|
||||
|
||||
<!-- Listing Description -->
|
||||
<div class="form-row">
|
||||
<label for="service-description">Listing Description</label>
|
||||
<textarea bind:value={$serviceDescription} id="service-description" required autocomplete="off"></textarea>
|
||||
<p>Please provide a description for this listing. Keep it factual and objective. Markdown is supported.</p>
|
||||
</div>
|
||||
|
||||
<!-- GitHub Repository -->
|
||||
<div class="form-row">
|
||||
<label for="service-github">GitHub Repository</label>
|
||||
<input type="text" bind:value={$serviceGithub} id="service-github" required autocomplete="off">
|
||||
<p>Share a link to where the project's source is located</p>
|
||||
</div>
|
||||
|
||||
<!-- ToS;DR ID -->
|
||||
<div class="form-row">
|
||||
<label for="service-tosdr-id">ToS;DR ID</label>
|
||||
<input type="number" bind:value={$serviceTosdrId} id="service-tosdr-id" autocomplete="off">
|
||||
<p>
|
||||
Has the Privacy policy been documented by <a href="https://tosdr.org/">tosdr.org</a>?
|
||||
If so, please include the report reference below (this is a 3 or 4-digit numerical ID).
|
||||
Skip section if not applicable.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Open Source Checkbox -->
|
||||
<div class="form-row">
|
||||
<label for="service-open-source">Is Open Source?</label>
|
||||
<input type="checkbox" bind:checked={$serviceOpenSource} id="service-open-source">
|
||||
<p>Is this service fully open source? Aka, can it be compiled from source by the user, or self-hosted?</p>
|
||||
</div>
|
||||
|
||||
<!-- Security Audited Checkbox -->
|
||||
<div class="form-row">
|
||||
<label for="service-security-audited">Security Audited?</label>
|
||||
<input type="checkbox" bind:checked={$serviceSecurityAudited} id="service-security-audited">
|
||||
<p>Has this service been independently security audited by an accredited auditor?</p>
|
||||
</div>
|
||||
|
||||
<!-- Accepts Crypto Checkbox -->
|
||||
<div class="form-row">
|
||||
<label for="service-crypto">Accepts Anon Payment?</label>
|
||||
<input type="checkbox" bind:checked={$serviceCrypto} id="service-crypto">
|
||||
<p>If this is a hosted and paid for service, does it accept anonymous payment methods, including crypto (e.g., Monero)?</p>
|
||||
</div>
|
||||
|
||||
<div class="final-info">
|
||||
<p>
|
||||
Finally, please provide any supporting material, including:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
A justification of why this app/service should be included in the list
|
||||
</li>
|
||||
<li>
|
||||
Links to any published security audit, if they exist
|
||||
</li>
|
||||
<li>
|
||||
Links to the services privacy policy, terms of service and other relevant
|
||||
documents where applicable
|
||||
</li>
|
||||
<li>
|
||||
Your affiliation with the service.
|
||||
For transparency, you must disclose if you are associated
|
||||
with them or any similar items in any way
|
||||
</li>
|
||||
<li>Links to relevant discussions, past issues/PRs related to this service</li>
|
||||
</ul>
|
||||
<textarea bind:value={$additionalInfo} id="additional-info" rows="5"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<a href={issueUrl} target="_blank" class="open-in-gh">Open in GitHub Issues</a>
|
||||
</form>
|
||||
|
||||
<div class="output-yaml">
|
||||
<p>Below is the YAML content, which will be appended to the appropriate section
|
||||
within <a href="github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml">awesome-privacy.yml</a>
|
||||
upon approval.
|
||||
</p>
|
||||
<pre>{@html yamlText}</pre>
|
||||
<p>Your submission will need to be reviewed by a maintainer and the community before it can be merged.</p>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr 2fr;
|
||||
gap: 1rem;
|
||||
padding: 0.5rem 0;
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid var(--transparent-accent);
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
.final-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem 0;
|
||||
gap: 1rem;
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
ul {
|
||||
padding-left: 0.25rem;
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.6;
|
||||
list-style: circle;
|
||||
}
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
width: 100%;
|
||||
border: 1px solid var(--accent-3);
|
||||
border-radius: var(--curve-md);
|
||||
font-size: 1.2rem;
|
||||
padding: 0.5rem 0;
|
||||
&:focus {
|
||||
outline: none;
|
||||
border: 2px solid var(--accent);
|
||||
}
|
||||
}
|
||||
input {
|
||||
height: fit-content;
|
||||
&[type="number"]::-webkit-outer-spin-button,
|
||||
&[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
&[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
&[type="checkbox"] {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
}
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
.open-in-gh {
|
||||
margin: 0 auto;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.6;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
background: var(--accent-3);
|
||||
color: var(--accent-fg);
|
||||
padding: 0.5rem 2rem;
|
||||
border: 1px solid var(--foreground);
|
||||
box-shadow: 3px 3px 0 var(--foreground);
|
||||
border-radius: var(--curve-lg);
|
||||
font-size: 1.8rem;
|
||||
font-family: "Lekton", sans-serif;
|
||||
margin: 1rem auto;
|
||||
display: flex;
|
||||
transition: all 0.2s ease-in-out;
|
||||
&:hover {
|
||||
background: var(--accent);
|
||||
}
|
||||
}
|
||||
|
||||
.output-yaml {
|
||||
pre {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
background: #cecbf780;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: var(--curve-sm);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -64,6 +64,9 @@
|
|||
href={makeEditRequest(categoryName, sectionName, serviceName, yamlContent)}>
|
||||
<FontAwesome iconName="edit" /> Submit Edit to {serviceName}
|
||||
</a>
|
||||
<a class="button-link" href="/edit">
|
||||
<FontAwesome iconName="add" /> Add alternative
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import FontAwesome from '@components/form/FontAwesome.svelte';
|
||||
import { fetchSrcData, makeRemovalRequest, makeEditRequest } from '@utils/data-src-delete-n-edit';
|
||||
import { fetchSrcData, makeRemovalRequest } from '@utils/data-src-delete-n-edit';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
|
||||
|
|
@ -9,18 +9,26 @@
|
|||
export let sectionName: string;
|
||||
export let serviceName: string;
|
||||
|
||||
const apYaml = 'https://github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml';
|
||||
|
||||
let yamlContent = '';
|
||||
let editLink = apYaml;
|
||||
|
||||
onMount(async () => {
|
||||
const results = await fetchSrcData(categoryName, sectionName, serviceName);
|
||||
yamlContent = results.yamlContent;
|
||||
|
||||
const lineNumbers = results.lineNumbers || null;
|
||||
const numberRange = lineNumbers ? `#L${lineNumbers.start}-L${lineNumbers.end}` : '';
|
||||
const yamlLink = 'https://github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml';
|
||||
editLink = `${yamlLink}${numberRange}`;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="actions">
|
||||
<a title="Edit" target="_blank"
|
||||
href={makeEditRequest(categoryName, sectionName, serviceName, yamlContent)}>
|
||||
href={editLink}>
|
||||
<FontAwesome iconName="edit" />
|
||||
</a>
|
||||
<a title="Delete" target="_blank"
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ function generateChartData(languages: Record<string, number>): string {
|
|||
'cpp': '#00599C',
|
||||
'C++': '#00599C',
|
||||
'Dockerfile': '#2496ED',
|
||||
'SCSS': '#CC6699',
|
||||
};
|
||||
|
||||
// Arrays to hold the data, labels, and colors
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ const {
|
|||
|
||||
|
||||
<section>
|
||||
{services ? (
|
||||
{services && services.length > 0 ? (
|
||||
<ul>
|
||||
{services.map((service: Service) => (
|
||||
<li id={slugify(service.name)}>
|
||||
|
|
@ -126,7 +126,9 @@ const {
|
|||
</p>
|
||||
)}
|
||||
|
||||
{buttonLink && ( <Button className="view-all" text="View More..." url={buttonLink} /> )}
|
||||
{buttonLink && (
|
||||
<Button title={`View all ${categoryName}`} className="view-all" text="View More..." url={buttonLink} />
|
||||
)}
|
||||
</section>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const categoryLabels: {[key: string]: string} = {
|
|||
};
|
||||
|
||||
const siteCategories = Object.entries(websiteInfo.site_category)
|
||||
.filter(([key, value]) => value)
|
||||
.filter(([_key, value]) => value)
|
||||
.map(([key]) => categoryLabels[key]);
|
||||
|
||||
const securityChecks = analyzeSecurityChecks(websiteInfo.security_checks);
|
||||
|
|
@ -311,6 +311,10 @@ h4 {
|
|||
width: 180px;
|
||||
float: right;
|
||||
font-size: 1rem;
|
||||
transform: scale(0.8);
|
||||
opacity: 0.85;
|
||||
transition: all 0.2s ease-in-out;
|
||||
&:hover { transform: scale(0.85); opacity: 1; }
|
||||
:global(.button) {
|
||||
background: var(--accent-3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ const getApiEndpoint = () => {
|
|||
{ url && (
|
||||
<li>
|
||||
<b>Web info:</b>
|
||||
<a href={`https://web-check.xyz/results/${formatLink(url)}`}>{`web-check.xyz/results/${formatLink(url)}`}</a>
|
||||
<a href={`https://web-check.xyz/results/${formatLink(url)}`}>{`web-check.xyz/results/${formatLink(url).split('/')[0]}`}</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ as Git makes it possible to maintain a full log of what was changed, when, by wh
|
|||
|
||||
### Augmention
|
||||
The data is augmented with some extra info, to add additional context to each service.
|
||||
The aim of this is to give you a broader picture of each service, to help you make a more informed decision.
|
||||
The aim of this is to give you a broader picture of each listing, to help you make a more informed decision.
|
||||
Currently, this extra data is pulled from:
|
||||
|
||||
- **GitHub API** - To fetch info about each project's repository
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { APIRoute } from 'astro';
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
import type { AwesomePrivacy, Service } from '../../types/Service';
|
||||
import type { AwesomePrivacy, Service, Category } from '../../types/Service';
|
||||
|
||||
interface LineNumberRange {
|
||||
start: number;
|
||||
|
|
@ -25,13 +25,15 @@ const awesomePrivacyYamlPath = 'https://raw.githubusercontent.com/Lissy93/awesom
|
|||
* Given a service object and an array of string lines from the raw YAML
|
||||
* Find the starting and ending line number for that service
|
||||
*/
|
||||
const calculateServiceRange = (service: Service, yamlLines: string[]): LineNumberRange | null => {
|
||||
const calculateServiceRange = (service: Service, category: Category, yamlLines: string[]): LineNumberRange | null => {
|
||||
const lookFor = `- name: ${service.name}`;
|
||||
const start = yamlLines.findIndex(line => line.includes(lookFor)) + 1;
|
||||
const categoryStart = yamlLines.findIndex(line => line.includes(category.name));
|
||||
const start = yamlLines.slice(categoryStart).findIndex(line => line.includes(lookFor)) + categoryStart + 1;
|
||||
if (start === -1) return null;
|
||||
const detectEnd = (line: string) => {
|
||||
return line.trim().length === 0
|
||||
|| line.startsWith(' - ')
|
||||
|| line.includes('- name:')
|
||||
|| line.includes('notableMentions:')
|
||||
|| line.includes('furtherInfo:')
|
||||
|| line.includes('wordOfWarning:')
|
||||
|
|
@ -61,7 +63,7 @@ const makeResults = (yamlObject: AwesomePrivacy, yamlLines: string[]): LineNumbe
|
|||
organizedData[category.name][section.name] = {};
|
||||
section.services.forEach((service) => {
|
||||
organizedData[category.name][section.name][service.name] = {
|
||||
lineNumbers: calculateServiceRange(service, yamlLines),
|
||||
lineNumbers: calculateServiceRange(service, category, yamlLines),
|
||||
yaml: convertJsonIntoYaml(service),
|
||||
};
|
||||
});
|
||||
|
|
|
|||
80
web/src/pages/edit.astro
Normal file
80
web/src/pages/edit.astro
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
|
||||
|
||||
import Layout from '@layouts/Layout.astro';
|
||||
import AddNewService from '@components/things/AddNewService.svelte';
|
||||
import type { AwesomePrivacy, Section } from '../types/Service';
|
||||
import { fetchData, slugify } from '@utils/fetch-data';
|
||||
import FontAwesome from '@components/form/FontAwesome.svelte';
|
||||
|
||||
const categories = (await fetchData() as AwesomePrivacy)?.categories || [];
|
||||
|
||||
---
|
||||
|
||||
<Layout title="Awesome Privacy">
|
||||
<section>
|
||||
<h2>About our Data</h2>
|
||||
<p>
|
||||
All data on Awesome Privacy is community maintained via Git.
|
||||
<br />
|
||||
You can make edits/additions/removals by editing the
|
||||
<a href="github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml">awesome-privacy.yml</a> file.
|
||||
To learn more, see the <a href="/about#our-data">about page</a>.
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Submit an Addition</h2>
|
||||
<AddNewService client:load />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Submit a Removal Request</h2>
|
||||
<p>
|
||||
You can submit a removal request by browsing to a given service's page,
|
||||
and clicking the "Request Removal" button.
|
||||
This will open a form where you can justify your reasoning, to get it
|
||||
deleted from the <a href="github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml">awesome-privacy.yml</a> file.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Edit a Listing</h2>
|
||||
<p>
|
||||
Edits are welcome! All data is located in
|
||||
<a href="github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml">awesome-privacy.yml</a>.
|
||||
<br>
|
||||
To modify an entry, navigate to it's page, scroll to the bottom, and click "Edit".
|
||||
This will take you to directly to the relevant lines in the file, where you can make your changes.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
</Layout>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
section {
|
||||
margin: 2rem auto;
|
||||
padding: 1rem;
|
||||
width: 1000px;
|
||||
max-width: calc(100% - 5rem);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 0 2rem;
|
||||
border: 2px solid var(--foreground);
|
||||
box-shadow: 6px 6px 0 var(--foreground);
|
||||
background: var(--accent-fg);
|
||||
@media(max-width: 768px) {
|
||||
max-width: 95%;
|
||||
padding: 0.5rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -24,6 +24,58 @@ export const makeEditRequest = (categoryName: string, sectionName: string, servi
|
|||
return `${issueCreate}${baseOptions}${removalData}`;
|
||||
};
|
||||
|
||||
export const makeAdditionRequest = (formData: {
|
||||
listingCategory: string;
|
||||
serviceName: string;
|
||||
serviceUrl: string;
|
||||
serviceIcon: string;
|
||||
serviceDescription: string;
|
||||
serviceGithub: string;
|
||||
serviceTosdrId: string;
|
||||
serviceOpenSource: boolean;
|
||||
serviceSecurityAudited: boolean;
|
||||
serviceCrypto: boolean;
|
||||
additionalInfo: string;
|
||||
}, yamlText?: string) => {
|
||||
|
||||
const userInfo = formData.additionalInfo.split('\n').map(line => `> ${line}`).join('\n');
|
||||
const additionalInfoText: string = `\n${userInfo}`
|
||||
+ `\n\n**YAML Content for Addition**\n\n\`\`\`yaml\n${yamlText || '# nothing yet'}\n\`\`\`\n`
|
||||
+ `\n\n<sup>This ticket was submitted via `
|
||||
+ `<a href="https://awesome-privacy.xyz/edit">awesome-privacy.xyz/edit</a></sup>`;
|
||||
|
||||
const issueTitle = `[ADDITION] ${formData.serviceName} (Complete)`;
|
||||
const queryParams = new URLSearchParams({
|
||||
'assignees': 'lissy93,liss-bot',
|
||||
'labels': '',
|
||||
'projects': '',
|
||||
'template': 'complete-addition.yml',
|
||||
'title': issueTitle,
|
||||
'listing-category': formData.listingCategory,
|
||||
'service-name': formData.serviceName,
|
||||
'service-url': formData.serviceUrl,
|
||||
'service-icon': formData.serviceIcon,
|
||||
'service-description': formData.serviceDescription,
|
||||
'service-github': formData.serviceGithub,
|
||||
'service-tosdr-id': formData.serviceTosdrId,
|
||||
'service-opensource': formData.serviceOpenSource ? 'true' : 'false',
|
||||
'service-security-audited': formData.serviceSecurityAudited ? 'true' : 'false',
|
||||
'service-crypto': formData.serviceCrypto ? 'true' : 'false',
|
||||
'additional-info': additionalInfoText,
|
||||
});
|
||||
const issueCreateUrl = 'https://github.com/Lissy93/awesome-privacy/issues/new';
|
||||
return `${issueCreateUrl}?${queryParams.toString()}`;
|
||||
};
|
||||
|
||||
|
||||
export const makeSourceYamlLink = async (categoryName: string, sectionName: string, serviceName: string) => {
|
||||
const sourceData = await fetchSrcData(categoryName, sectionName, serviceName);
|
||||
const lineNumbers = sourceData.lineNumbers || null;
|
||||
const numberRange = lineNumbers ? `L${lineNumbers.start}-L${lineNumbers.end}` : '';
|
||||
const yamlLink = 'https://github.com/lissy93/awesome-privacy/blob/main/awesome-privacy.yml';
|
||||
return `${yamlLink}${numberRange}`;
|
||||
};
|
||||
|
||||
export const fetchSrcData = async (categoryName: string, sectionName: string, serviceName: string) => {
|
||||
const lineNumberData = await fetch('/api/line-numbers.json')
|
||||
.then((res) => res.json());
|
||||
|
|
|
|||
Loading…
Reference in a new issue