forked from cms/tibi-svelte-starter
Erste kleine Anpassungen am Tibi-Svelte-Starter um später mehr Zeit in neuen Projekten zu sparen. Hier werden noch weitere Anpassungen folgen, die grundlegend in den meisten Projekten benötigt werden.
This commit is contained in:
parent
44270c6187
commit
c723f1e1d4
@ -1,13 +1,15 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"semi": false,
|
||||
"newline-before-return": true,
|
||||
"no-duplicate-variable": [true, "check-parameters"],
|
||||
"no-duplicate-variable": [
|
||||
true,
|
||||
"check-parameters"
|
||||
],
|
||||
"no-var-keyword": true,
|
||||
|
||||
"svelteSortOrder": "scripts-styles-markup",
|
||||
"svelteStrictMode": true,
|
||||
"svelteBracketNewLine": true,
|
||||
|
150
api/collections/articles.yml
Normal file
150
api/collections/articles.yml
Normal file
@ -0,0 +1,150 @@
|
||||
########################################################################
|
||||
# Articles
|
||||
########################################################################
|
||||
|
||||
name: articles
|
||||
uploadPath: ../media/articles
|
||||
meta:
|
||||
# Navigationseintrag in der Admin-UI
|
||||
label: { de: "Artikel auf der Seite", en: "Page articles" }
|
||||
# Icon (Material UI) für den Navigationseintrag
|
||||
muiIcon: file-document-edit-outline
|
||||
# Standardsortierung der Liste
|
||||
defaultSort: { field: "name", order: "ASC" }
|
||||
# Admin-Backend Ansichten
|
||||
defaultImageFilter: s
|
||||
views:
|
||||
# Mobile Darstellung
|
||||
- type: simpleList
|
||||
mediaQuery: "(max-width:599px)"
|
||||
primaryText: path
|
||||
columns:
|
||||
- public
|
||||
- image
|
||||
- title
|
||||
- position
|
||||
# Desktop
|
||||
- type: table
|
||||
mediaQuery: "(min-width:600px)"
|
||||
columns:
|
||||
- public
|
||||
- image
|
||||
- title
|
||||
- position
|
||||
|
||||
imageFilter:
|
||||
xs:
|
||||
- fit: true
|
||||
height: 90
|
||||
width: 90
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
s:
|
||||
- fit: true
|
||||
height: 300
|
||||
width: 300
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
m:
|
||||
- fit: true
|
||||
height: 600
|
||||
width: 600
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
l:
|
||||
- fit: true
|
||||
height: 1200
|
||||
width: 1200
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
xl:
|
||||
- fit: true
|
||||
height: 2000
|
||||
width: 2000
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
|
||||
permissions:
|
||||
public:
|
||||
methods:
|
||||
get: true
|
||||
post: false
|
||||
put: false
|
||||
delete: false
|
||||
user:
|
||||
methods:
|
||||
get: true
|
||||
post: true
|
||||
put: true
|
||||
delete: true
|
||||
# token als Zusatzsicherung gegen Spam, mehr siehe Hook
|
||||
"token:${PUBLIC_TOKEN}":
|
||||
methods:
|
||||
get: false
|
||||
post: false
|
||||
put: false
|
||||
delete: false
|
||||
|
||||
# hooks:
|
||||
# post:
|
||||
# create:
|
||||
# type: javascript
|
||||
# file: hooks/article/post_create.js
|
||||
# put:
|
||||
# update:
|
||||
# type: javascript
|
||||
# file: hooks/article/put_return.js
|
||||
# delete:
|
||||
# return:
|
||||
# type: javascript
|
||||
# file: hooks/article/delete_return.js
|
||||
|
||||
fields:
|
||||
- name: articleTabs
|
||||
type: tabs
|
||||
meta:
|
||||
label:
|
||||
de: Informationen zu einem Artikel
|
||||
en: Article Information
|
||||
activeTab: 0
|
||||
subFields:
|
||||
- name: articleTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Artikel
|
||||
en: Article
|
||||
css:
|
||||
subFields:
|
||||
- name: articleLayoutTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Layout
|
||||
en: Layout
|
||||
css:
|
||||
subFields:
|
||||
- name: articleMediaTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Bilder
|
||||
en: Images
|
||||
css:
|
||||
subFields:
|
||||
- name: articleAttachmentsTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Anhänge / Downloads
|
||||
en: Attachments / Downloads
|
||||
css:
|
||||
subFields:
|
||||
- name: articleMetaTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Meta
|
||||
en: Meta
|
||||
css:
|
||||
subFields:
|
306
api/collections/general.yml
Normal file
306
api/collections/general.yml
Normal file
@ -0,0 +1,306 @@
|
||||
########################################################################
|
||||
# General Information
|
||||
########################################################################
|
||||
|
||||
name: general
|
||||
uploadPath: ../media/general
|
||||
meta:
|
||||
# Navigationseintrag in der Admin-UI
|
||||
label: { de: "Allgemeine Informationen", en: "General Information" }
|
||||
# Icon (Material UI) für den Navigationseintrag
|
||||
muiIcon: information-outline
|
||||
# Identifizierung eines Eintrags für z.B. Select-Boxen in der Admin-UI
|
||||
rowIdentTpl: { twig: "{{ email }} - {{ subject }}" }
|
||||
# Standardsortierung der Liste
|
||||
defaultSort: { field: "path", order: "ASC" }
|
||||
# Admin-Backend Ansichten
|
||||
defaultImageFilter: s
|
||||
views:
|
||||
# Mobile Darstellung
|
||||
- type: simpleList
|
||||
mediaQuery: "(max-width:599px)"
|
||||
primaryText: firstname
|
||||
columns:
|
||||
- public
|
||||
- firstname
|
||||
- lastname
|
||||
- companyName
|
||||
# Desktop
|
||||
- type: table
|
||||
mediaQuery: "(min-width:600px)"
|
||||
columns:
|
||||
- public
|
||||
- firstname
|
||||
- lastname
|
||||
- companyName
|
||||
|
||||
imageFilter:
|
||||
xs:
|
||||
- fit: true
|
||||
height: 90
|
||||
width: 90
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
s:
|
||||
- fit: true
|
||||
height: 300
|
||||
width: 300
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
m:
|
||||
- fit: true
|
||||
height: 600
|
||||
width: 600
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
l:
|
||||
- fit: true
|
||||
height: 1200
|
||||
width: 1200
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
xl:
|
||||
- fit: true
|
||||
height: 2000
|
||||
width: 2000
|
||||
resampling: lanczos
|
||||
quality: 60
|
||||
|
||||
permissions:
|
||||
public:
|
||||
methods:
|
||||
get: true
|
||||
post: false
|
||||
put: false
|
||||
delete: false
|
||||
user:
|
||||
methods:
|
||||
get: true
|
||||
post: true
|
||||
put: true
|
||||
delete: true
|
||||
# token als Zusatzsicherung gegen Spam, mehr siehe Hook
|
||||
"token:${PUBLIC_TOKEN}":
|
||||
methods:
|
||||
get: false
|
||||
post: false
|
||||
put: false
|
||||
delete: false
|
||||
|
||||
fields:
|
||||
- name: generalInformationTabs
|
||||
type: tabs
|
||||
meta:
|
||||
label:
|
||||
de: Allgemeine Information
|
||||
en: General Information
|
||||
activeTab: 0
|
||||
subFields:
|
||||
- name: generalInformationTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Allgemein
|
||||
en: General
|
||||
css:
|
||||
subFields:
|
||||
- name: public
|
||||
type: boolean
|
||||
meta:
|
||||
label:
|
||||
de: Veröffentlicht
|
||||
en: Public
|
||||
helperText:
|
||||
de: "Alle allgemeinen Informationen werden auf der Seite angezeigt."
|
||||
en: "All general information are displayed on the page."
|
||||
- name: metaInformationTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Meta / SEO
|
||||
en: Meta / SEO
|
||||
css:
|
||||
subFields:
|
||||
- name: metaTitle
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Titel der Webseite", en: "Page Title" }
|
||||
- name: metaDescription
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Beschreibung der Webseite", en: "Page Description" }
|
||||
- name: metaTagRobots
|
||||
type: string[]
|
||||
meta:
|
||||
widget: chipArray
|
||||
label:
|
||||
de: Robots
|
||||
en: Robots
|
||||
inputProps:
|
||||
placeholder: "nofollow"
|
||||
defaultValue: []
|
||||
autocomplete: true
|
||||
choices:
|
||||
- { id: "noindex", name: "noindex" }
|
||||
- { id: "index", name: "index" }
|
||||
- { id: "follow", name: "follow" }
|
||||
- { id: "nofollow", name: "nofollow" }
|
||||
- { id: "noimageindex", name: "noimageindex" }
|
||||
- { id: "none", name: "none" }
|
||||
- { id: "noarchive", name: "noarchive" }
|
||||
- { id: "nocache", name: "nocache" }
|
||||
- { id: "nosnippet", name: "nosnippet" }
|
||||
- { id: "nnavailable_after", name: "nnavailable_after" }
|
||||
helperText:
|
||||
de: "<strong>Noindex</strong>: Weist eine Suchmaschine an, eine Seite nicht zu indizieren.<br/><strong>index</strong>: Weist eine Suchmaschine an, eine Seite zu indizieren. Beachten Sie, dass Sie dieses Meta-Tag nicht hinzufügen müssen; es ist die Voreinstellung.<br/><strong>follow</strong>: Auch wenn die Seite nicht indexiert ist, sollte der Crawler allen Links auf einer Seite folgen und Eigenkapital an die verlinkten Seiten weitergeben.<br/><strong>nofollow</strong>: Weist einen Crawler an, keinen Links auf einer Seite zu folgen oder Link-Equity weiterzugeben.<br/><strong>noimageindex</strong>: Weist einen Crawler an, keine Bilder auf einer Seite zu indizieren.<br/><strong>none</strong>: Entspricht der gleichzeitigen Verwendung der noindex- und nofollow-Tags.<br/><strong>noarchive</strong>: Suchmaschinen sollten keinen zwischengespeicherten Link zu dieser Seite auf einem SERP anzeigen.<br/><strong>nocache</strong>: Wie noarchive, aber nur von Internet Explorer und Firefox verwendet.<br/><strong>nosnippet</strong>: Weist eine Suchmaschine an, kein Snippet dieser Seite (d. h. Meta-Beschreibung) dieser Seite auf einem SERP anzuzeigen.<br/><strong>nnavailable_after</strong>: Suchmaschinen sollen diese Seite nach einem bestimmten Datum nicht mehr indexieren.<br/>"
|
||||
en: "<strong>Noindex</strong>: Tells a search engine not to index a page.<br/><strong>index</strong>: Tells a search engine to index a page. Note that you don’t need to add this meta tag; it’s the default.<br/><strong>follow</strong>: Even if the page isn’t indexed, the crawler should follow all the links on a page and pass equity to the linked pages.<br/><strong>nofollow</strong>: Tells a crawler not to follow any links on a page or pass along any link equity.<br/><strong>noimageindex</strong>: Tells a crawler not to index any images on a page.<br/><strong>none</strong>: Equivalent to using both the noindex and nofollow tags simultaneously.<br/><strong>noarchive</strong>: Search engines should not show a cached link to this page on a SERP.<br/><strong>nocache</strong>: Same as noarchive, but only used by Internet Explorer and Firefox.<br/><strong>nosnippet</strong>: Tells a search engine not to show a snippet of this page (i.e. meta description) of this page on a SERP.<br/><strong>nnavailable_after</strong>: Search engines should no longer index this page after a particular date.<br/>"
|
||||
- name: metaKeywords
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "SEO / Schlüsselwörter", en: "SEO / Keywords" }
|
||||
helperText:
|
||||
de: "Beispiel: Stichwort1, Stichwort2, Stichwort3"
|
||||
en: "Example: keyword1, keyword2, keyword3"
|
||||
- name: personalInformationTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Personendaten
|
||||
en: Personal Data
|
||||
css:
|
||||
subFields:
|
||||
- name: firstname
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Vorname", en: "Firstname" }
|
||||
- name: lastname
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Nachname", en: "Lastname" }
|
||||
- name: street
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Straße", en: "Street" }
|
||||
- name: postcode
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Postleitzahl", en: "Postcode" }
|
||||
- name: city
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Ort", en: "City" }
|
||||
- name: tel
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Telefonnummer", en: "Phone number" }
|
||||
- name: mobile
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Handynummer", en: "Mobile number" }
|
||||
- name: email
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "E-Mail", en: "E-Mail" }
|
||||
- name: companyInformationTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Unternehmensdaten
|
||||
en: Company Data
|
||||
css:
|
||||
subFields:
|
||||
- name: companyName
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Name des Unternehmens", en: "Company Name" }
|
||||
- name: companyWebUrl
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "URL zur Webseite", en: "Website URL" }
|
||||
- name: companyAddresses
|
||||
type: object[]
|
||||
meta:
|
||||
label:
|
||||
de: Adresse
|
||||
en: Adresse
|
||||
css:
|
||||
subFields:
|
||||
- name: street
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Straße", en: "Street" }
|
||||
- name: houseNr
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Hausnummer", en: "House number" }
|
||||
- name: postcode
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "PLZ", en: "ZIP" }
|
||||
- name: city
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Ort", en: "City" }
|
||||
- name: tel
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Telefon", en: "Phone number" }
|
||||
- name: fax
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Fax", en: "Fax" }
|
||||
- name: email
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "E-Mail", en: "E-Mail" }
|
||||
- name: mediaInformationTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Media
|
||||
en: Media
|
||||
css:
|
||||
subFields:
|
||||
- name: favicon
|
||||
type: file
|
||||
meta:
|
||||
label: { de: "Favicon", en: "Favicon" }
|
||||
helperText:
|
||||
de: "Ein Favicon ist ein kleines Icon, Symbol oder Logo, das von Webbrowsern verwendet wird, um eine Website auf wiedererkennbare Weise zu kennzeichnen."
|
||||
en: "A favicon is a small icon, symbol, or logo used by web browsers to identify a website in a recognizable way."
|
||||
- name: favicon
|
||||
type: file
|
||||
meta:
|
||||
label: { de: "Logo / Brand", en: "Logo / Brand" }
|
||||
helperText:
|
||||
de: "Logo der Seite"
|
||||
en: "Page Logo"
|
||||
- name: mediaFiles
|
||||
type: object[]
|
||||
meta:
|
||||
label: { de: "Dateien", en: "Files" }
|
||||
subFields:
|
||||
- name: title
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Datei-Titel", en: "File Title" }
|
||||
- name: id
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Technischer Name / ID", en: "Technical name / ID" }
|
||||
- name: file
|
||||
type: file
|
||||
meta:
|
||||
label: { de: "", en: "" }
|
||||
- name: copyrightInformationTab
|
||||
type: object
|
||||
meta:
|
||||
label:
|
||||
de: Copyright
|
||||
en: Copyright
|
||||
css:
|
||||
subFields:
|
||||
- name: copyright
|
||||
type: string
|
||||
meta:
|
||||
label: { de: "Copyright Text", en: "Copyright Text" }
|
@ -7,6 +7,8 @@ meta:
|
||||
|
||||
# Liste aller möglichen Kollektionen (Listen, Seiten...) zum Projekt
|
||||
collections:
|
||||
- !include collections/general.yml
|
||||
- !include collections/articles.yml
|
||||
- !include collections/content.yml
|
||||
- !include collections/contact_form.yml
|
||||
- !include collections/ssr.yml
|
||||
|
@ -5,8 +5,7 @@ const resolvePlugin = {
|
||||
// url in css does not resolve via esbuild-svelte correctly
|
||||
build.onResolve({ filter: /.*/, namespace: "fakecss" }, (args) => {
|
||||
// console.log(args)
|
||||
if (args.path.match(/^\./))
|
||||
return { path: path.dirname(args.importer) + "/" + args.path }
|
||||
if (args.path.match(/^\./)) return { path: path.dirname(args.importer) + "/" + args.path }
|
||||
// return { path: path.join(args.resolveDir, "public", args.path) }
|
||||
})
|
||||
},
|
||||
@ -54,6 +53,8 @@ const options = {
|
||||
".eot": "file",
|
||||
".svg": "file",
|
||||
".ttf": "file",
|
||||
".png": "file",
|
||||
".jpg": "file",
|
||||
},
|
||||
sourcemap: true,
|
||||
target: ["es2020", "chrome61", "firefox60", "safari11", "edge18"],
|
||||
@ -63,9 +64,7 @@ const bsMiddleware = []
|
||||
|
||||
if (process.argv[2] == "start") {
|
||||
const { createProxyMiddleware } = require("http-proxy-middleware")
|
||||
const apiBase =
|
||||
process.env.API_BASE ||
|
||||
"http://localhost:8080/api/v1/_/" + process.env.NAMESPACE
|
||||
const apiBase = process.env.API_BASE || "http://localhost:8080/api/v1/_/" + process.env.NAMESPACE
|
||||
bsMiddleware.push(
|
||||
createProxyMiddleware("/api", {
|
||||
target: apiBase,
|
||||
|
@ -7,8 +7,8 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"validate": "svelte-check && tsc --noEmit",
|
||||
"start": "node scripts/esbuild-wrapper.js start",
|
||||
"start:localapi": "API_BASE=http://localhost:8080 node scripts/esbuild-wrapper.js start",
|
||||
"start": "NAMESPACE=__NAMESPACE__ node scripts/esbuild-wrapper.js start",
|
||||
"start:remoteapi": "API_BASE=https://login.tibicms.de/api/v1/_/__NAMESPACE__ node scripts/esbuild-wrapper.js start",
|
||||
"dev": "node scripts/esbuild-wrapper.js watch",
|
||||
"build": "node scripts/esbuild-wrapper.js build",
|
||||
"build:legacy": "node scripts/esbuild-wrapper.js build esbuild.config.legacy.js && babel _temp/index.js -o _temp/index.babeled.js && esbuild _temp/index.babeled.js --outfile=dist/_dist_/index.es5.js --target=es5 --bundle --minify --sourcemap",
|
||||
|
48
src/api.ts
48
src/api.ts
@ -43,9 +43,7 @@ const _f = function (url, options): Promise<Response> {
|
||||
.replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, (m, key, value) => {
|
||||
keys.push((key = key.toLowerCase()))
|
||||
all.push([key, value])
|
||||
headers[key] = headers[key]
|
||||
? `${headers[key]},${value}`
|
||||
: value
|
||||
headers[key] = headers[key] ? `${headers[key]},${value}` : value
|
||||
})
|
||||
resolve(response())
|
||||
}
|
||||
@ -62,12 +60,7 @@ const _f = function (url, options): Promise<Response> {
|
||||
})
|
||||
}
|
||||
|
||||
const _fetch =
|
||||
typeof fetch === "undefined"
|
||||
? typeof window === "undefined"
|
||||
? _f
|
||||
: window.fetch || _f
|
||||
: fetch
|
||||
const _fetch = typeof fetch === "undefined" ? (typeof window === "undefined" ? _f : window.fetch || _f) : fetch
|
||||
|
||||
export const api = async <T>(
|
||||
endpoint: string,
|
||||
@ -107,8 +100,7 @@ export const api = async <T>(
|
||||
let method = "GET"
|
||||
|
||||
let query = "&count=1"
|
||||
if (options?.filter)
|
||||
query += "&filter=" + encodeURIComponent(JSON.stringify(options.filter))
|
||||
if (options?.filter) query += "&filter=" + encodeURIComponent(JSON.stringify(options.filter))
|
||||
if (options?.sort) query += "&sort=" + options.sort + "&sort=_id"
|
||||
if (options?.limit) query += "&limit=" + options.limit
|
||||
if (options?.offset) query += "&offset=" + options.offset
|
||||
@ -149,8 +141,7 @@ export const api = async <T>(
|
||||
// @ts-ignore
|
||||
let data = (await response?.json()) || null
|
||||
|
||||
if (response?.status < 200 || response?.status >= 400)
|
||||
throw { response, data }
|
||||
if (response?.status < 200 || response?.status >= 400) throw { response, data }
|
||||
|
||||
// @ts-ignore
|
||||
return { data, count: response?.headers?.get("x-results-count") || 0 }
|
||||
@ -163,3 +154,34 @@ export const getContent = async (path: string): Promise<Content> => {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const getGeneralInformation = async (): Promise<GeneralInformation[]> => {
|
||||
try {
|
||||
let response = await api<GeneralInformation[]>("general", {
|
||||
method: "get",
|
||||
offset: 0,
|
||||
limit: 1,
|
||||
filter: {
|
||||
active: true,
|
||||
},
|
||||
})
|
||||
return response.data
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const getArticles = async (): Promise<TibiArticle[]> => {
|
||||
try {
|
||||
let response = await api<TibiArticle[]>("articles", {
|
||||
method: "get",
|
||||
offset: 0,
|
||||
filter: {
|
||||
active: true,
|
||||
},
|
||||
})
|
||||
return response.data
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
35
src/store.ts
35
src/store.ts
@ -1,4 +1,5 @@
|
||||
import { writable, get } from "svelte/store"
|
||||
import { getGeneralInformation, getArticles } from "./api"
|
||||
|
||||
const initLoc = {
|
||||
path: (typeof window !== "undefined" && window.location?.pathname) || "/",
|
||||
@ -10,3 +11,37 @@ const initLoc = {
|
||||
initLoc.categoryPath = initLoc.path.replace(/\/\d{4,99}[^\/]+$/, "")
|
||||
|
||||
export const location = writable(initLoc)
|
||||
|
||||
// General Information
|
||||
|
||||
export const generalInformation = writable<GeneralInformation>()
|
||||
const getGeneralProjectInformation = async () => {
|
||||
const infos = await getGeneralInformation()
|
||||
if (infos && infos.length) {
|
||||
generalInformation.set(infos[0])
|
||||
}
|
||||
}
|
||||
getGeneralProjectInformation()
|
||||
|
||||
// Articles
|
||||
|
||||
export const articles = writable<TibiArticle[]>()
|
||||
const getAllArticles = async () => {
|
||||
const list = await getArticles()
|
||||
articles.set(list)
|
||||
}
|
||||
getAllArticles()
|
||||
|
||||
// Cookies - Webmakers Cookie Bar
|
||||
|
||||
export const ccTags = writable<string[]>([])
|
||||
|
||||
const updateCcTtags = () => {
|
||||
// @ts-ignore
|
||||
ccTags.set(window.ccLoadedTags || [])
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window.addEventListener("ccInit", updateCcTtags)
|
||||
window.addEventListener("ccAccept", updateCcTtags)
|
||||
}
|
||||
|
45
types/global.d.ts
vendored
45
types/global.d.ts
vendored
@ -8,9 +8,52 @@ interface ContentBlock {
|
||||
images?: ImageEntry[]
|
||||
}
|
||||
|
||||
|
||||
interface Content {
|
||||
id: string
|
||||
path: string
|
||||
blocks: ContentBlock[]
|
||||
}
|
||||
|
||||
interface GeneralInformation {
|
||||
id: string
|
||||
active: boolean
|
||||
firstname: string
|
||||
lastname: string
|
||||
street: string
|
||||
postcode: number
|
||||
city: string
|
||||
tel: string
|
||||
mobile: string
|
||||
email: string
|
||||
images: GeneralImage[]
|
||||
insertTime: string
|
||||
updateTime: string
|
||||
lastPageUpdate: string
|
||||
}
|
||||
|
||||
interface GeneralImage {
|
||||
file: File[]
|
||||
id: string
|
||||
label: string
|
||||
}
|
||||
|
||||
interface TibiArticle {
|
||||
id: string
|
||||
active: boolean
|
||||
content: string
|
||||
details: string
|
||||
image: File
|
||||
insertTime: string
|
||||
position: string
|
||||
subtitle: string
|
||||
title: string
|
||||
updateTime: string
|
||||
}
|
||||
|
||||
interface File {
|
||||
lastModified?: number
|
||||
path: string
|
||||
size?: string
|
||||
src: string
|
||||
type: string
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user