Neue Komponente für Article-Media-Image sowie eine allgemeine Image Komponente. Article-Komponente WorkInProgress.

This commit is contained in:
Mario Linz 2022-06-09 08:23:39 +02:00
parent d872767845
commit 4824effccb
12 changed files with 180 additions and 343 deletions

View File

@ -19,26 +19,22 @@ meta:
mediaQuery: "(max-width:599px)" mediaQuery: "(max-width:599px)"
primaryText: path primaryText: path
columns: columns:
- source: article.general.locale
type: flag
- article.general.public - article.general.public
- article.content.title - article.content.title
- article.general.position
- article.general.sort - article.general.sort
- source: article.general.locale
type: flag
# Desktop # Desktop
- type: table - type: table
mediaQuery: "(min-width:600px)" mediaQuery: "(min-width:600px)"
columns: columns:
- source: article.general.locale
type: flag
- article.general.public - article.general.public
- label: { de: "Titel", en: "Title" } - label: { de: "Titel", en: "Title" }
source: article.content.title source: article.content.title
filter: true filter: true
- label: { de: "Position", en: "Position" }
source: article.general.position
filter: true
- article.general.sort - article.general.sort
- source: article.general.locale
type: flag
imageFilter: imageFilter:
xs: xs:

View File

@ -5,7 +5,7 @@ meta:
label: label:
de: Einstellungen zum Artikel de: Einstellungen zum Artikel
en: Article Setings en: Article Setings
activeTab: 0 activeTab: 1
subFields: subFields:
- name: general - name: general
type: object type: object
@ -61,6 +61,7 @@ subFields:
label: label:
de: Schlagworte / Tags / Labels de: Schlagworte / Tags / Labels
en: Linking Tags en: Linking Tags
addAllowed: true
defaultValue: [] defaultValue: []
choices: choices:
endpoint: "tags" endpoint: "tags"
@ -106,7 +107,7 @@ subFields:
label: label:
de: Inhalt dieses Artikel de: Inhalt dieses Artikel
en: Article Content en: Article Content
activeTab: 1 activeTab: 2
subFields: subFields:
- name: teaser - name: teaser
type: string type: string
@ -118,15 +119,14 @@ subFields:
meta: meta:
widget: richtext widget: richtext
label: { de: "Detail-Text des Artikel", en: "Article Detail Text" } label: { de: "Detail-Text des Artikel", en: "Article Detail Text" }
- name: contentMedia - name: media
type: object type: object
meta: meta:
label: label:
de: Medien de: Medien
en: Media en: Media
css:
subFields: subFields:
- name: mediaFiles - name: files
type: object[] type: object[]
meta: meta:
label: { de: "Bilder", en: "Images" } label: { de: "Bilder", en: "Images" }
@ -142,6 +142,7 @@ subFields:
- name: id - name: id
type: string type: string
meta: meta:
editableWhileCreating: true
label: { de: "Technischer Name / ID", en: "Technical name / ID" } label: { de: "Technischer Name / ID", en: "Technical name / ID" }
- name: file - name: file
type: file type: file
@ -152,7 +153,7 @@ subFields:
type: string type: string
meta: meta:
label: { de: "Bildunterschrift", en: "Caption" } label: { de: "Bildunterschrift", en: "Caption" }
- name: contentAttachments - name: attachments
type: object type: object
meta: meta:
label: label:
@ -160,7 +161,7 @@ subFields:
en: Attachments / Downloads en: Attachments / Downloads
css: css:
subFields: subFields:
- name: attachments - name: files
type: object[] type: object[]
meta: meta:
label: { de: "Anhänge", en: "Attachments" } label: { de: "Anhänge", en: "Attachments" }
@ -189,7 +190,7 @@ subFields:
label: label:
de: Erscheinungsbild de: Erscheinungsbild
en: Appearance en: Appearance
defaultValue: ["_self"] defaultValue: top-left
choices: choices:
- { - {
id: "top", id: "top",
@ -215,13 +216,8 @@ subFields:
en: "Article picture under teaser (full width)", en: "Article picture under teaser (full width)",
}, },
} }
- { id: "top-left", name: { de: "Artikelbild oben links", en: "Article picture above left" } } - { id: "default", name: { de: "Artikelbild oben links", en: "Article picture above left" } }
- { id: "top-right", name: { de: "Artikelbild oben rechts", en: "Article picture above right" } } - { id: "top-right", name: { de: "Artikelbild oben rechts", en: "Article picture above right" } }
- { id: "bottom-left", name: { de: "Artikelbild unten links", en: "Article picture below left" } }
- {
id: "bottom-right",
name: { de: "Artikelbild unten rechts", en: "Article picture below right" },
}
- name: properties - name: properties
type: object type: object
meta: meta:

View File

@ -217,17 +217,25 @@ export const getGeneralInformation = async (): Promise<GeneralInfo[]> => {
} }
} }
export const getArticles = async (): Promise<TibiArticle[]> => { export const getArticles = async (
collectionName: string,
filter: APIParams,
params?: APIParams
): Promise<TibiArticle[]> => {
try { try {
let response = await api<TibiArticle[]>("articles", { let response = await api<TibiArticle[]>(collectionName, {
method: "get", method: "get",
offset: 0, offset: 0,
params,
filter: { filter: {
active: true, "article.general.public": true,
...filter,
}, },
sort: "article.general.sort",
}) })
return response.data return response.data
} catch (e) { } catch (e) {
console.error(e)
return null return null
} }
} }

View File

@ -1,45 +1,36 @@
<script lang="ts"> <script lang="ts">
import * as animateScroll from "svelte-scrollto" import * as animateScroll from "svelte-scrollto"
import { generalInfo } from "../../store" import { generalInfo, currentLang } from "../../store"
import { getArticles } from "../../api"
import GoogleMaps from "../widgets/GoogleMaps.svelte" import GoogleMaps from "../widgets/GoogleMaps.svelte"
import ScrollTo from "../widgets/ScrollTo.svelte" import ScrollTo from "../widgets/ScrollTo.svelte"
import ContactForm from "../widgets/ContactForm.svelte" import ContactForm from "../widgets/ContactForm.svelte"
import GeneralMediaImage from "../widgets/GeneralMediaImage.svelte" import GeneralMediaImage from "../widgets/GeneralMediaImage.svelte"
import Article from "../widgets/Article.svelte"
let expandedForm: string = "recipe" let expandedForm: string = "recipe"
</script> let articleEntries: CollectionEntry[] = []
<!-- <svelte:head> $: if ($currentLang) {
{#if $generalInfo?.meta?.metaTitle} getArticles("articles", {
<title>{$generalInfo?.meta?.metaTitle}</title> "article.general.locale": $currentLang,
{/if} }).then((response) => {
{#if $generalInfo?.meta?.metaDescription} articleEntries = response
<meta name="description" content="{$generalInfo?.meta?.metaDescription}" /> })
{/if} }
{#if $generalInfo?.meta?.metaKeywords} </script>
<meta name="keywords" content="{$generalInfo?.meta?.metaKeywords.replaceAll(' ', '')}" />
{/if}
{#if $generalInfo?.person?.firstname || $generalInfo?.person?.lastname}
<meta
name="author"
content="{$generalInfo?.person?.firstname ? $generalInfo?.person?.firstname : ''} {$generalInfo?.person
?.lastname
? $generalInfo?.person?.lastname
: ''}"
/>
{/if}
{#if $generalInfo?.meta?.metaTagRobots}
<meta name="robots" content="{$generalInfo?.meta?.metaTagRobots}" />
{/if}
{#if $generalInfo?.media?.favicon}
<link rel="shortcut icon" type="image/x-icon" href="{$generalInfo?.media?.favicon.src}" />
{/if}
</svelte:head> -->
<section class="contact"> <section class="contact">
<div class="container"> <div class="container">
<div class="row">
<div class="col-md-12">
{#each articleEntries || [] as entry}
<Article entry="{entry}" />
{/each}
</div>
</div>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<GeneralMediaImage id="test1" /> <GeneralMediaImage id="test1" />

View File

@ -1,73 +1,77 @@
<script lang="ts"> <script lang="ts">
import { navigate } from "svelte-routing" // import { navigate } from "svelte-routing"
import { apiBaseURL } from "../../config" import { apiBaseURL } from "../../config"
import TibiArticleMediaFile from "./TibiArticleMediaFile.svelte"
export let article: SWArticle export let entry: CollectionEntry
export let cssClass: string = "" export let cssClass: string = ""
export let showDetails: boolean = false export let showDetails: boolean = false
const getImageSrc = () => { let article = entry.article
return `${apiBaseURL}articles/${article?.id}/${article?.image?.src}?filter=l` let marginClasses: string = ""
let paddingClasses: string = ""
$: if (article) {
marginClasses = Object.values(article?.layout?.properties?.margin).join(" ").replace(" ", " ")
paddingClasses = Object.values(article?.layout?.properties?.padding).join(" ").replace(" ", " ")
} }
</script> </script>
<article class="{article?.position} {cssClass}"> {#if article}
{#if article?.position !== "content"} <article class="{cssClass} {article?.layout?.variant} {marginClasses} {paddingClasses}">
<div {#if article?.layout?.variant === "default"}
class="article-image" {#if article?.content?.types?.media?.files?.length}
style="background-image: url({getImageSrc()});" <TibiArticleMediaFile
> collectionName="articles"
{#if article?.title} entryId="{entry.id}"
<div class="article-title">{@html article?.title}</div> mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if} {/if}
{#if article?.position === "top" || article?.position === "end-of-content"} {#if article?.content?.title}
{#if article?.subtitle} <div class="article-title">{@html article?.content?.title}</div>
<div class="article-subtitle">
{@html article?.subtitle}
</div>
{/if}
{/if}
</div>
{/if} {/if}
{#if article?.position !== "top"} {#if article?.content?.subtitle}
<div class="article-content"> <div class="article-subtitle">{@html article?.content?.subtitle}</div>
{#if article?.position === "content"}
{#if article?.title}
<div class="article-title">{@html article?.title}</div>
{/if}
{/if}
{#if article?.position === "content" || article?.position === "top-of-content"}
{#if article?.subtitle}
<div class="article-subtitle mb-md">
{@html article?.subtitle}
</div>
{/if}
{/if} {/if}
{#if !showDetails && article?.content} {#if article?.content?.types?.teaser}
<div class="mb-lg"> <div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{@html article?.content}
</div>
{/if} {/if}
{#if showDetails && article?.details?.length} {#if article?.content?.types?.details && showDetails}
<div class="mb-lg"> <div class="article-details">{@html article?.content?.types?.details}</div>
{@html article?.details} {/if}
</div> {:else if article?.layout?.variant === "left"}
<div class="row">
<div class="col-md-4">
{#if article?.content?.types?.media?.files?.length}
<TibiArticleMediaFile
collectionName="articles"
entryId="{entry.id}"
mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if} {/if}
</div> </div>
<div class="col-md-8">
{#if article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if} {/if}
{#if !showDetails && article?.details} {#if article?.content?.subtitle}
<div <div class="article-subtitle">{@html article?.content?.subtitle}</div>
class="article-link" {/if}
on:click="{() => {
navigate('/articles/' + article?.id) {#if article?.content?.types?.teaser}
}}" <div class="article-teaser">{@html article?.content?.types?.teaser}</div>
> {/if}
Details
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{/if}
</div>
</div> </div>
{/if} {/if}
</article> </article>
{/if}

View File

@ -1,11 +0,0 @@
<script lang="ts">
import { generalInfo } from "../../store"
</script>
<div class="contact-information" id="contact-information">
<div class="container">
<div class="row">
<div class="col-md-12">...</div>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@
</script> </script>
{#if collectionName && entryId && file} {#if collectionName && entryId && file}
{#if file.src.includes(";base64,")} {#if file?.src?.includes(";base64,")}
<img src="{file.src}" alt="{alt ? alt + ' - ' : ''}{file.path}" class="{cssClass}" /> <img src="{file.src}" alt="{alt ? alt + ' - ' : ''}{file.path}" class="{cssClass}" />
{:else} {:else}
<img <img
@ -19,3 +19,30 @@
/> />
{/if} {/if}
{/if} {/if}
<!-- <picture>
<source
media="(min-width: 1400px)"
data-srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3.jpg"
srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3.jpg"
/>
<source
media="(min-width: 768px)"
data-srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3.jpg"
srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3.jpg"
/>
<source
media="(min-width: 400px)"
data-srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3.jpg"
srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3.jpg"
/>
<source
data-srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3-400x267.jpg"
srcset="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3-400x267.jpg"
/>
<img
data-src="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3-400x267.jpg"
alt="fresh IT GmbH"
src="https://www.framos-holding.de/wp-content/uploads/2020/09/fresh-IT-3-400x267.jpg"
/>
</picture> -->

View File

@ -0,0 +1,12 @@
<script lang="ts">
import { apiBaseURL } from "../../config"
import Image from "./Image.svelte"
export let collectionName: string = null
export let entryId: string = null
export let mediaFile: TibiArticleImage = null
export let cssClass: string = ""
</script>
<Image collectionName="{collectionName}" entryId="{entryId}" file="{mediaFile.file}" cssClass="{cssClass}" />

View File

@ -1,211 +1,23 @@
article, article,
.article { .article {
font-size: 20px;
border-radius: 10px;
overflow-wrap: anywhere; overflow-wrap: anywhere;
background: rgba(0, 0, 0, 0.03);
padding: @space-md;
strong { & ~ article,
color: @secondary; & ~ .article {
font-weight: 600; margin-top: @space-md;
}
&.top,
&.top-of-content,
&.end-of-content {
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2);
border-radius: 10px;
background-color: @surface;
color: @on-surface;
display: flex;
flex-direction: column;
.article-image {
min-height: 200px;
background-size: cover;
background-position: top center;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 10px 20px;
color: #f1ebe4;
text-shadow: 0 2px 10px #000;
overflow-wrap: anywhere;
flex-grow: 1;
} }
.article-title { .article-title {
font-size: 32px;
font-weight: 600;
overflow-wrap: anywhere;
}
.article-subtitle {
font-size: 20px;
overflow-wrap: anywhere;
}
.article-content {
padding: 20px;
overflow-wrap: anywhere;
.article-subtitle {
font-size: @font-size-default;
}
}
&.end-of-content {
.article-image {
height: 400px;
}
}
.article-link {
background: @primary;
color: @on-primary;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
height: 44px;
font-size: 20px;
font-weight: 700;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
}
ul {
list-style-type: none;
padding-left: 0px;
li {
background-image: url("../css/theme/components/img/arrow-right-3.png");
background-repeat: no-repeat;
line-height: 30px;
padding-left: 35px;
color: @primary; color: @primary;
font-weight: 700; font-size: 2rem;
font-size: 20px; line-height: 2.4rem;
}
}
.article-content {
strong {
color: @primary;
font-weight: 600;
}
.article-title:not(h1) {
color: @primary;
font-size: 32px;
font-weight: 700;
margin-bottom: @space-sm;
} }
.article-subtitle { .article-subtitle {
color: @secondary; color: @secondary;
font-size: 20px; font-size: 1.4rem;
font-weight: 700; line-height: 1.8rem;
margin-bottom: @space-md;
}
}
&.content {
margin-bottom: @space-lg;
.article-link {
border: 1px solid @primary;
border-bottom: 3px solid #c4253e;
color: @primary;
font-size: 18px;
font-weight: 700;
padding: 5px 10px;
border-radius: 10px;
transition: @transition-default;
display: inline-flex;
justify-content: center;
align-items: center;
gap: @space-sm;
text-decoration: none;
cursor: pointer;
&:hover {
background: @on-primary;
color: @primary;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2);
}
}
}
&.end-of-content {
.article-image {
justify-content: flex-start;
.article-title {
margin-top: 20px;
color: #fff;
font-family: "Caveat", sans-serif;
text-shadow: none;
font-size: 72px;
line-height: 72px;
font-weight: 700;
padding-right: 10%;
}
.article-subtitle {
color: #fff;
font-family: "Caveat", sans-serif;
text-shadow: none;
font-size: 32px;
font-weight: 700;
}
}
}
&.article-details {
img {
border-radius: 10px;
width: 300px;
display: inline-block;
&.layout-1 {
float: left;
margin: 0 @space-md @space-md 0;
}
&.layout-2 {
float: right;
margin: 0 0 @space-md @space-md;
}
}
.article-subtitle {
font-size: 24px;
}
.article-link {
margin-top: @space-lg;
border: 1px solid @primary;
border-bottom: 3px solid #c4253e;
color: @primary;
font-size: 18px;
font-weight: 700;
padding: 5px 10px;
border-radius: 10px;
transition: @transition-default;
display: inline-flex;
justify-content: center;
align-items: center;
gap: @space-sm;
text-decoration: none;
cursor: pointer;
&:hover {
background: @on-primary;
color: @primary;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2);
}
}
} }
} }

View File

@ -51,5 +51,6 @@
@import "components/top-section"; @import "components/top-section";
@import "components/forms"; @import "components/forms";
@import "components/language-chooser"; @import "components/language-chooser";
@import "components/article";
@import "components/cc-bar"; @import "components/cc-bar";

View File

@ -34,15 +34,6 @@ const getGeneralProjectInformation = async () => {
} }
getGeneralProjectInformation() getGeneralProjectInformation()
// Articles
// export const articles = writable<TibiArticle[]>()
// const getAllArticles = async () => {
// const list = await getArticles()
// articles.set(list)
// }
// getAllArticles()
// Navigations // Navigations
export const navigations = writable<Navigation[]>([]) export const navigations = writable<Navigation[]>([])

26
types/global.d.ts vendored
View File

@ -7,6 +7,14 @@ interface APIParams {
} }
count?: 1 count?: 1
} }
interface CollectionEntry {
id?: string
insertTime?: string
updateTime?: string
[key: string]: any
}
interface ContentBlock { interface ContentBlock {
layout: 1 | 2 | 3 | 4 layout: 1 | 2 | 3 | 4
title?: string title?: string
@ -64,15 +72,17 @@ interface GeneralInfo {
interface TibiArticle { interface TibiArticle {
id: string id: string
active: boolean article: any
content: string insertTime?: string
details: string updateTime?: string
image: File }
insertTime: string
position: string interface TibiArticleImage {
subtitle: string id: string
title: string title: string
updateTime: string alternateText: string
caption: string
file: File[]
} }
interface File { interface File {