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)"
primaryText: path
columns:
- source: article.general.locale
type: flag
- article.general.public
- article.content.title
- article.general.position
- article.general.sort
- source: article.general.locale
type: flag
# Desktop
- type: table
mediaQuery: "(min-width:600px)"
columns:
- source: article.general.locale
type: flag
- article.general.public
- label: { de: "Titel", en: "Title" }
source: article.content.title
filter: true
- label: { de: "Position", en: "Position" }
source: article.general.position
filter: true
- article.general.sort
- source: article.general.locale
type: flag
imageFilter:
xs:

View File

@ -5,7 +5,7 @@ meta:
label:
de: Einstellungen zum Artikel
en: Article Setings
activeTab: 0
activeTab: 1
subFields:
- name: general
type: object
@ -61,6 +61,7 @@ subFields:
label:
de: Schlagworte / Tags / Labels
en: Linking Tags
addAllowed: true
defaultValue: []
choices:
endpoint: "tags"
@ -106,7 +107,7 @@ subFields:
label:
de: Inhalt dieses Artikel
en: Article Content
activeTab: 1
activeTab: 2
subFields:
- name: teaser
type: string
@ -118,15 +119,14 @@ subFields:
meta:
widget: richtext
label: { de: "Detail-Text des Artikel", en: "Article Detail Text" }
- name: contentMedia
- name: media
type: object
meta:
label:
de: Medien
en: Media
css:
subFields:
- name: mediaFiles
- name: files
type: object[]
meta:
label: { de: "Bilder", en: "Images" }
@ -142,6 +142,7 @@ subFields:
- name: id
type: string
meta:
editableWhileCreating: true
label: { de: "Technischer Name / ID", en: "Technical name / ID" }
- name: file
type: file
@ -152,7 +153,7 @@ subFields:
type: string
meta:
label: { de: "Bildunterschrift", en: "Caption" }
- name: contentAttachments
- name: attachments
type: object
meta:
label:
@ -160,7 +161,7 @@ subFields:
en: Attachments / Downloads
css:
subFields:
- name: attachments
- name: files
type: object[]
meta:
label: { de: "Anhänge", en: "Attachments" }
@ -189,7 +190,7 @@ subFields:
label:
de: Erscheinungsbild
en: Appearance
defaultValue: ["_self"]
defaultValue: top-left
choices:
- {
id: "top",
@ -215,13 +216,8 @@ subFields:
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: "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
type: object
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 {
let response = await api<TibiArticle[]>("articles", {
let response = await api<TibiArticle[]>(collectionName, {
method: "get",
offset: 0,
params,
filter: {
active: true,
"article.general.public": true,
...filter,
},
sort: "article.general.sort",
})
return response.data
} catch (e) {
console.error(e)
return null
}
}

View File

@ -1,45 +1,36 @@
<script lang="ts">
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 ScrollTo from "../widgets/ScrollTo.svelte"
import ContactForm from "../widgets/ContactForm.svelte"
import GeneralMediaImage from "../widgets/GeneralMediaImage.svelte"
import Article from "../widgets/Article.svelte"
let expandedForm: string = "recipe"
</script>
let articleEntries: CollectionEntry[] = []
<!-- <svelte:head>
{#if $generalInfo?.meta?.metaTitle}
<title>{$generalInfo?.meta?.metaTitle}</title>
{/if}
{#if $generalInfo?.meta?.metaDescription}
<meta name="description" content="{$generalInfo?.meta?.metaDescription}" />
{/if}
{#if $generalInfo?.meta?.metaKeywords}
<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> -->
$: if ($currentLang) {
getArticles("articles", {
"article.general.locale": $currentLang,
}).then((response) => {
articleEntries = response
})
}
</script>
<section class="contact">
<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="col-md-12">
<GeneralMediaImage id="test1" />

View File

@ -1,73 +1,77 @@
<script lang="ts">
import { navigate } from "svelte-routing"
// import { navigate } from "svelte-routing"
import { apiBaseURL } from "../../config"
import TibiArticleMediaFile from "./TibiArticleMediaFile.svelte"
export let article: SWArticle
export let entry: CollectionEntry
export let cssClass: string = ""
export let showDetails: boolean = false
const getImageSrc = () => {
return `${apiBaseURL}articles/${article?.id}/${article?.image?.src}?filter=l`
let article = entry.article
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>
<article class="{article?.position} {cssClass}">
{#if article?.position !== "content"}
<div
class="article-image"
style="background-image: url({getImageSrc()});"
>
{#if article?.title}
<div class="article-title">{@html article?.title}</div>
{#if article}
<article class="{cssClass} {article?.layout?.variant} {marginClasses} {paddingClasses}">
{#if article?.layout?.variant === "default"}
{#if article?.content?.types?.media?.files?.length}
<TibiArticleMediaFile
collectionName="articles"
entryId="{entry.id}"
mediaFile="{article?.content?.types?.media?.files[0]}"
/>
{/if}
{#if article?.position === "top" || article?.position === "end-of-content"}
{#if article?.subtitle}
<div class="article-subtitle">
{@html article?.subtitle}
</div>
{/if}
{/if}
</div>
{/if}
{#if article?.position !== "top"}
<div class="article-content">
{#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 article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if}
{#if !showDetails && article?.content}
<div class="mb-lg">
{@html article?.content}
{#if article?.content?.subtitle}
<div class="article-subtitle">{@html article?.content?.subtitle}</div>
{/if}
{#if article?.content?.types?.teaser}
<div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{/if}
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{/if}
{: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}
</div>
{/if}
<div class="col-md-8">
{#if article?.content?.title}
<div class="article-title">{@html article?.content?.title}</div>
{/if}
{#if showDetails && article?.details?.length}
<div class="mb-lg">
{@html article?.details}
{#if article?.content?.subtitle}
<div class="article-subtitle">{@html article?.content?.subtitle}</div>
{/if}
{#if article?.content?.types?.teaser}
<div class="article-teaser">{@html article?.content?.types?.teaser}</div>
{/if}
{#if article?.content?.types?.details && showDetails}
<div class="article-details">{@html article?.content?.types?.details}</div>
{/if}
</div>
{/if}
</div>
{/if}
{#if !showDetails && article?.details}
<div
class="article-link"
on:click="{() => {
navigate('/articles/' + article?.id)
}}"
>
Details
</div>
{/if}
</article>
</div>
{/if}
</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>
{#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}" />
{:else}
<img
@ -19,3 +19,30 @@
/>
{/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 {
font-size: 20px;
border-radius: 10px;
overflow-wrap: anywhere;
background: rgba(0, 0, 0, 0.03);
padding: @space-md;
strong {
& ~ article,
& ~ .article {
margin-top: @space-md;
}
.article-title {
color: @primary;
font-size: 2rem;
line-height: 2.4rem;
}
.article-subtitle {
color: @secondary;
font-weight: 600;
}
&.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 {
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;
font-weight: 700;
font-size: 20px;
}
}
.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 {
color: @secondary;
font-size: 20px;
font-weight: 700;
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);
}
}
font-size: 1.4rem;
line-height: 1.8rem;
}
}

View File

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

View File

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

26
types/global.d.ts vendored
View File

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