Merge pull request #228 from goteo/feat/blog-template
Feat: blog template
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
<script lang="ts">
|
||||
import { marked } from "marked";
|
||||
import { twMerge, type ClassNameValue } from "tailwind-merge";
|
||||
|
||||
import ShareButton from "./Share/ShareButton.svelte";
|
||||
|
||||
interface BlogPost {
|
||||
title?: string;
|
||||
description?: string;
|
||||
cover?: string;
|
||||
date: Date;
|
||||
author?: { name: string; avatar: string };
|
||||
body?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
post: BlogPost;
|
||||
class?: ClassNameValue;
|
||||
}
|
||||
|
||||
let { post, class: className = "" }: Props = $props();
|
||||
|
||||
const containerClasses = $derived(twMerge("flex justify-center min-h-screen", className));
|
||||
const parsedBody = $derived(marked(post.body ?? ""));
|
||||
</script>
|
||||
|
||||
<div class={containerClasses}>
|
||||
<div class="w-full max-w-4xl p-4" id="top">
|
||||
<h1>{post.title}</h1>
|
||||
<p class="text-content pb-4">
|
||||
{post.description}
|
||||
</p>
|
||||
|
||||
{#if post.cover}
|
||||
<img src={post.cover} class="big-img" alt={post.title} />
|
||||
{/if}
|
||||
|
||||
<div class="meta-container pt-6">
|
||||
<div class="profile-section">
|
||||
<img src={post.author?.avatar} class="avatar" alt={post.author?.name} />
|
||||
<div class="info">
|
||||
<p class="author-name">{post.author?.name}</p>
|
||||
<p class="date">{post.date}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ShareButton shareText={post.title ?? ""} variant="blog" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="blog-body marked-content mt-8 flex flex-col gap-6"
|
||||
style="overflow-wrap: break-word; word-wrap: break-word; word-break: break-word;"
|
||||
>
|
||||
{@html parsedBody}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
padding-bottom: 16px;
|
||||
color: var(--color-secondary);
|
||||
font-size: 40px;
|
||||
font-weight: var(--font-weight-black);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.big-img {
|
||||
width: 100%;
|
||||
max-width: 898px;
|
||||
height: 400px;
|
||||
border-radius: 16px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.meta-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.profile-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border-radius: 8px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
color: var(--color-secondary);
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.date {
|
||||
color: #575757;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.btn-share {
|
||||
display: flex;
|
||||
padding: 8px 16px;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--color-secondary);
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
color: var(--color-secondary);
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.blog-body :global(h2) {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 8px;
|
||||
color: var(--color-secondary);
|
||||
font-family: var(--font-body);
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.blog-body :global(h3) {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 8px;
|
||||
color: var(--color-secondary);
|
||||
font-family: var(--font-body);
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.blog-body :global(p) {
|
||||
color: var(--color-content);
|
||||
font-family: var(--font-body);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.blog-body :global(blockquote) {
|
||||
border-left: 4px solid var(--color-secondary);
|
||||
padding-left: 16px;
|
||||
margin: 16px 0;
|
||||
color: var(--color-content);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.blog-body :global(ul),
|
||||
.blog-body :global(ol) {
|
||||
padding-left: 24px;
|
||||
color: var(--color-content);
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
list-style: initial;
|
||||
}
|
||||
|
||||
.blog-body :global(ol) {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.blog-body :global(li) {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.blog-body :global(strong) {
|
||||
font-weight: 700;
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.blog-body :global(em) {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.blog-body :global(a) {
|
||||
color: var(--color-primary);
|
||||
text-decoration: underline;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.blog-body :global(pre) {
|
||||
overflow-x: auto;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { t } from "../../../i18n/store";
|
||||
import WebIcon from "../../../svgs/WebIcon.svelte";
|
||||
import Tooltip from "../../Admin/Tooltip.svelte";
|
||||
|
||||
interface Props {
|
||||
url?: string;
|
||||
}
|
||||
|
||||
let { url = "" }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Tooltip
|
||||
text={$t("contributions.tootip.copied")}
|
||||
tooltipClass="bg-secondary -translate-x-[50%]"
|
||||
className="cursor-copy shrink-0 w-auto h-auto"
|
||||
>
|
||||
<button
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
onclick={() => navigator.clipboard.writeText(url)}
|
||||
>
|
||||
<WebIcon />
|
||||
</button>
|
||||
</Tooltip>
|
||||
@@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import FacebookIcon from "../../../svgs/FacebookIcon.svelte";
|
||||
|
||||
interface Props {
|
||||
url?: string;
|
||||
appId?: string;
|
||||
}
|
||||
|
||||
let { url = "", appId = import.meta.env.PUBLIC_FACEBOOK_APP_ID }: Props = $props();
|
||||
|
||||
let fbWindow: Window | null = null;
|
||||
|
||||
const fbShareUrl = $derived(() => {
|
||||
const encoded = encodeURIComponent(url);
|
||||
return `https://www.facebook.com/dialog/share?app_id=${appId}&display=popup&href=${encoded}&redirect_uri=${encoded}`;
|
||||
});
|
||||
|
||||
function openFbPopup() {
|
||||
const width = 626;
|
||||
const height = 436;
|
||||
const left = window.screenX + (window.innerWidth - width) / 2;
|
||||
const top = window.screenY + (window.innerHeight - height) / 2;
|
||||
|
||||
if (fbWindow && !fbWindow.closed) {
|
||||
fbWindow.close();
|
||||
}
|
||||
|
||||
fbWindow = window.open(
|
||||
fbShareUrl(),
|
||||
"facebook-share-dialog",
|
||||
`width=${width},height=${height},top=${top},left=${left}`,
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={openFbPopup}
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
>
|
||||
<FacebookIcon />
|
||||
</button>
|
||||
@@ -0,0 +1,85 @@
|
||||
<script lang="ts">
|
||||
import { Modal } from "flowbite-svelte";
|
||||
|
||||
import { t } from "../../../i18n/store";
|
||||
import CodeIcon from "../../../svgs/CodeIcon.svelte";
|
||||
import Loader from "../../../svgs/Loader.svelte";
|
||||
|
||||
interface Props {
|
||||
url?: string;
|
||||
}
|
||||
|
||||
let { url = "" }: Props = $props();
|
||||
|
||||
const iframeCode = $derived(
|
||||
`<iframe frameborder="0" height="492px" src="${url}" width="300px" scrolling="no"></iframe>`,
|
||||
);
|
||||
|
||||
let iframeModal = $state(false);
|
||||
let iframeLoaded = $state(false);
|
||||
let copied = $state(false);
|
||||
|
||||
$effect(() => {
|
||||
if (iframeModal) {
|
||||
iframeLoaded = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
onclick={() => (iframeModal = true)}
|
||||
>
|
||||
<CodeIcon />
|
||||
</button>
|
||||
|
||||
<Modal
|
||||
bind:open={iframeModal}
|
||||
closeBtnClass="top-7 end-7 bg-transparent text-secondary hover:bg-transparent hover:text-secondary hover:scale-110 transition-transform duration-200 transform focus:ring-0 shadow-none dark:text-secondary dark:hover:text-secondary dark:hover:bg-transparent cursor-pointer"
|
||||
class="left-1/2! max-w-[600px] p-4 backdrop:bg-[#878282B2] backdrop:backdrop-blur-[5px]"
|
||||
title={$t("project.share.iframe-modal.title")}
|
||||
headerClass="py-2 text-secondary text-2xl"
|
||||
>
|
||||
<p>{$t("project.share.iframe-modal.description")}</p>
|
||||
|
||||
<div class="flex w-full flex-row items-stretch justify-center gap-4">
|
||||
<div class="flex w-1/2 items-center justify-center rounded-lg border p-4">
|
||||
{#if !iframeLoaded}
|
||||
<Loader />
|
||||
{/if}
|
||||
<iframe
|
||||
onload={() => (iframeLoaded = true)}
|
||||
src={url}
|
||||
width="100%"
|
||||
height="492px"
|
||||
frameborder="0"
|
||||
scrolling="no"
|
||||
title="Project widget preview"
|
||||
class:hidden={!iframeLoaded}
|
||||
class="grayscale"
|
||||
></iframe>
|
||||
</div>
|
||||
<div class="flex w-1/2 rounded-lg border p-4">
|
||||
<textarea
|
||||
readonly
|
||||
class="w-full resize-none border-none focus:ring-0 focus:outline-none"
|
||||
rows="4">{iframeCode}</textarea
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="bg-primary text-secondary h-auto w-full cursor-pointer rounded-3xl px-6 py-4 font-bold"
|
||||
class:bg-primary={!copied}
|
||||
class:bg-variant1={copied}
|
||||
onclick={() => {
|
||||
navigator.clipboard.writeText(iframeCode);
|
||||
copied = true;
|
||||
setTimeout(() => (copied = false), 1000);
|
||||
}}
|
||||
>
|
||||
{copied
|
||||
? $t("project.share.iframe-modal.btnCopied")
|
||||
: $t("project.share.iframe-modal.btnCopy")}
|
||||
</button>
|
||||
</Modal>
|
||||
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import { Modal } from "flowbite-svelte";
|
||||
|
||||
import CopyUrl from "./CopyUrl.svelte";
|
||||
import Facebook from "./Facebook.svelte";
|
||||
import Iframe from "./Iframe.svelte";
|
||||
import X from "./X.svelte";
|
||||
import { t } from "../../../i18n/store";
|
||||
import ShareIcon from "../../../svgs/ShareIcon.svelte";
|
||||
|
||||
interface Props {
|
||||
shareText?: string;
|
||||
variant?: "blog" | "project";
|
||||
projectSlug?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
let { shareText = "", variant = "project", projectSlug = "", url = "" }: Props = $props();
|
||||
|
||||
const widgetUrl = $derived(`https://www.goteo.org/widget/project/${projectSlug}`);
|
||||
|
||||
let openModal = $state(false);
|
||||
|
||||
const modalTitle = $derived(
|
||||
variant === "blog" ? $t("blog.share.modal.title") : $t("project.share.modal.title"),
|
||||
);
|
||||
|
||||
const modalDescription = $derived(
|
||||
variant === "blog"
|
||||
? $t("blog.share.modal.description")
|
||||
: $t("project.share.modal.description"),
|
||||
);
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={() => (openModal = true)}
|
||||
class="text-secondary flex cursor-pointer flex-row items-center gap-2 p-2 font-bold"
|
||||
>
|
||||
<ShareIcon />
|
||||
{$t("project.actions.share")}
|
||||
</button>
|
||||
|
||||
<Modal
|
||||
bind:open={openModal}
|
||||
closeBtnClass="top-7 end-7 bg-transparent text-secondary hover:bg-transparent hover:text-secondary hover:scale-110 transition-transform duration-200 transform focus:ring-0 shadow-none dark:text-secondary dark:hover:text-secondary dark:hover:bg-transparent cursor-pointer"
|
||||
class="fixed top-1/2 left-1/2 w-full max-w-[475px] -translate-x-1/2 -translate-y-1/2 rounded-3xl bg-white p-6 shadow-lg backdrop:bg-[#878282B2] backdrop:backdrop-blur-[5px]"
|
||||
title={modalTitle}
|
||||
headerClass="py-2 text-secondary text-2xl"
|
||||
>
|
||||
<p>{modalDescription}</p>
|
||||
|
||||
<div class="flex flex-row items-center justify-center gap-6">
|
||||
<CopyUrl {url} />
|
||||
<Facebook {url} />
|
||||
<X text={shareText} {url} />
|
||||
{#if variant === "project"}
|
||||
<Iframe url={widgetUrl} />
|
||||
{/if}
|
||||
</div>
|
||||
</Modal>
|
||||
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import XIcon from "../../../svgs/XIcon.svelte";
|
||||
|
||||
interface Props {
|
||||
text?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
let { text = "", url = "" }: Props = $props();
|
||||
|
||||
const encodedUrl = $derived(encodeURIComponent(url));
|
||||
</script>
|
||||
|
||||
<a
|
||||
href={`https://twitter.com/intent/tweet?url=${encodedUrl}&text=${text}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
>
|
||||
<XIcon />
|
||||
</a>
|
||||
@@ -1,167 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { Modal } from "flowbite-svelte";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { t } from "../../i18n/store";
|
||||
import CodeIcon from "../../svgs/CodeIcon.svelte";
|
||||
import FacebookIcon from "../../svgs/FacebookIcon.svelte";
|
||||
import Loader from "../../svgs/Loader.svelte";
|
||||
import ShareIcon from "../../svgs/ShareIcon.svelte";
|
||||
import WebIcon from "../../svgs/WebIcon.svelte";
|
||||
import XIcon from "../../svgs/XIcon.svelte";
|
||||
import Tooltip from "../Admin/Tooltip.svelte";
|
||||
|
||||
import type { Project } from "../../openapi/client/index";
|
||||
|
||||
const appId = "184483011630708";
|
||||
|
||||
/* TODO: Implement URL dynamically */
|
||||
const iframeCode = `<iframe frameborder="0" height="492px" src="https://www.goteo.org/widget/project/mostra-de-cinema-arab-i-mediterrani-de-catalunya" width="300px" scrolling="no"></iframe>`;
|
||||
|
||||
let { project }: { project: Project } = $props();
|
||||
|
||||
let currentUrl = $state("");
|
||||
let fbShareUrl = $state("");
|
||||
let openModal = $state(false);
|
||||
let iframeModal = $state(false);
|
||||
let iframeLoaded = $state(false);
|
||||
let copied = $state(false);
|
||||
|
||||
let fbWindow: Window | null = null;
|
||||
|
||||
function openFbPopup() {
|
||||
const width = 626;
|
||||
const height = 436;
|
||||
const left = window.screenX + (window.innerWidth - width) / 2;
|
||||
const top = window.screenY + (window.innerHeight - height) / 2;
|
||||
|
||||
if (fbWindow && !fbWindow.closed) {
|
||||
fbWindow.close();
|
||||
}
|
||||
|
||||
fbWindow = window.open(
|
||||
fbShareUrl,
|
||||
"facebook-share-dialog",
|
||||
`width=${width},height=${height},top=${top},left=${left}`,
|
||||
);
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (iframeModal) {
|
||||
iframeLoaded = false;
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
currentUrl = encodeURIComponent(window.location.href);
|
||||
// currentUrl = encodeURIComponent("https://developers.facebook.com/docs/");
|
||||
fbShareUrl = `https://www.facebook.com/dialog/share?app_id=${appId}&display=popup&href=${currentUrl}&redirect_uri=${currentUrl}`;
|
||||
});
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={() => (openModal = true)}
|
||||
class="text-secondary flex cursor-pointer flex-row items-center gap-2 p-2 font-bold"
|
||||
>
|
||||
<ShareIcon />
|
||||
{$t("project.actions.share")}
|
||||
</button>
|
||||
|
||||
<Modal
|
||||
bind:open={openModal}
|
||||
closeBtnClass="top-7 end-7 bg-transparent text-secondary hover:bg-transparent hover:text-secondary hover:scale-110 transition-transform duration-200 transform focus:ring-0 shadow-none dark:text-secondary dark:hover:text-secondary dark:hover:bg-transparent cursor-pointer"
|
||||
class="fixed top-1/2 left-1/2 w-full max-w-[475px] -translate-x-1/2 -translate-y-1/2 rounded-3xl bg-white p-6 shadow-lg backdrop:bg-[#878282B2] backdrop:backdrop-blur-[5px]"
|
||||
title={$t("project.share.modal.title")}
|
||||
headerClass="py-2 text-secondary text-2xl"
|
||||
>
|
||||
<p>{$t("project.share.modal.description")}</p>
|
||||
|
||||
<div class="flex flex-row items-center justify-center gap-6">
|
||||
<Tooltip
|
||||
text={$t("contributions.tootip.copied")}
|
||||
tooltipClass="bg-secondary -translate-x-[50%]"
|
||||
className="cursor-copy shrink-0 w-auto h-auto"
|
||||
>
|
||||
<button
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
onclick={() => navigator.clipboard.writeText(window.location.href)}
|
||||
>
|
||||
<WebIcon />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<!-- TODO: Implement Facebook share popup -->
|
||||
<button
|
||||
onclick={openFbPopup}
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
>
|
||||
<FacebookIcon />
|
||||
</button>
|
||||
|
||||
<a
|
||||
href={`https://twitter.com/intent/tweet?url=${currentUrl}&text=${project.title}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
>
|
||||
<XIcon />
|
||||
</a>
|
||||
|
||||
<button
|
||||
class="flex h-23 w-23 items-center justify-center rounded-2xl shadow-[0_1px_3px_0_rgba(0,0,0,0.1)]"
|
||||
onclick={() => (iframeModal = true)}
|
||||
>
|
||||
<CodeIcon />
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
bind:open={iframeModal}
|
||||
closeBtnClass="top-7 end-7 bg-transparent text-secondary hover:bg-transparent hover:text-secondary hover:scale-110 transition-transform duration-200 transform focus:ring-0 shadow-none dark:text-secondary dark:hover:text-secondary dark:hover:bg-transparent cursor-pointer"
|
||||
class="!left-1/2 max-w-[600px] p-4 backdrop:bg-[#878282B2] backdrop:backdrop-blur-[5px]"
|
||||
title={$t("project.share.iframe-modal.title")}
|
||||
headerClass="py-2 text-secondary text-2xl"
|
||||
>
|
||||
<p>{$t("project.share.iframe-modal.description")}</p>
|
||||
|
||||
<div class="flex w-full flex-row items-stretch justify-center gap-4">
|
||||
<div class="flex w-1/2 items-center justify-center rounded-lg border p-4">
|
||||
{#if !iframeLoaded}
|
||||
<Loader />
|
||||
{/if}
|
||||
<iframe
|
||||
onload={() => (iframeLoaded = true)}
|
||||
src="https://www.goteo.org/widget/project/mostra-de-cinema-arab-i-mediterrani-de-catalunya"
|
||||
width="100%"
|
||||
height="492px"
|
||||
frameborder="0"
|
||||
scrolling="no"
|
||||
title="Project widget preview"
|
||||
class:hidden={!iframeLoaded}
|
||||
class="grayscale"
|
||||
></iframe>
|
||||
</div>
|
||||
<div class="flex w-1/2 rounded-lg border p-4">
|
||||
<textarea
|
||||
readonly
|
||||
class="w-full resize-none border-none focus:ring-0 focus:outline-none"
|
||||
rows="4">{iframeCode}</textarea
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="bg-primary text-secondary h-auto w-full cursor-pointer rounded-3xl px-6 py-4 font-bold"
|
||||
class:bg-primary={!copied}
|
||||
class:bg-variant1={copied}
|
||||
onclick={() => {
|
||||
navigator.clipboard.writeText(iframeCode);
|
||||
copied = true;
|
||||
setTimeout(() => (copied = false), 1000);
|
||||
}}
|
||||
>
|
||||
{copied
|
||||
? $t("project.share.iframe-modal.btnCopied")
|
||||
: $t("project.share.iframe-modal.btnCopy")}
|
||||
</button>
|
||||
</Modal>
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Banner from "./Banner.svelte";
|
||||
import Card from "./Card.svelte";
|
||||
import Sharebutton from "./Sharebutton.svelte";
|
||||
import Tabs from "./Tabs.svelte";
|
||||
import TopRewards from "./TopRewards.svelte";
|
||||
import { setLocale, t } from "../../i18n/store";
|
||||
@@ -17,6 +16,7 @@
|
||||
import Countdown from "../Countdown.svelte";
|
||||
import LanguagesDropdown from "../LanguagesDropdown.svelte";
|
||||
import Button from "../library/Button.svelte";
|
||||
import Sharebutton from "../library/Share/ShareButton.svelte";
|
||||
import Toast from "../library/Toast.svelte";
|
||||
import Player from "../Player/Player.svelte";
|
||||
import Tags from "../Tags.svelte";
|
||||
@@ -200,7 +200,7 @@
|
||||
<div class="mb-12 flex w-full flex-col justify-between gap-4 lg:flex-row">
|
||||
<Tags {project} />
|
||||
<div class="flex flex-row justify-between gap-6">
|
||||
<Sharebutton {project} />
|
||||
<Sharebutton shareText={project.title ?? ""} projectSlug={project.slug ?? ""} />
|
||||
<Button kind="invert" size="sm" class="px-0">
|
||||
<RememberIcon />
|
||||
{$t("project.actions.remember")}
|
||||
|
||||
@@ -1046,6 +1046,14 @@
|
||||
}
|
||||
},
|
||||
"loading": "Cargando...",
|
||||
"blog": {
|
||||
"share": {
|
||||
"modal": {
|
||||
"title": "Difunde este blog por el mundo",
|
||||
"description": "Puedes copiar el enlace para enviarlo y también compartirla en Facebook o X."
|
||||
}
|
||||
}
|
||||
},
|
||||
"lang": {
|
||||
"error": {
|
||||
"notAvailable": "El idioma seleccionado \"{{lang}}\" no está disponible para este proyecto. Mostrando contenido en el idioma disponible."
|
||||
|
||||
Reference in New Issue
Block a user