This commit is contained in:
@@ -1 +1,4 @@
|
|||||||
legacy-peer-deps=true
|
legacy-peer-deps=true
|
||||||
|
ignore-scripts=true
|
||||||
|
save-exact=true
|
||||||
|
fund=false
|
||||||
|
|||||||
@@ -6,4 +6,8 @@ Issues live as markdown files under `.scratch/`. See `docs/agents/issue-tracker.
|
|||||||
|
|
||||||
### Domain docs
|
### Domain docs
|
||||||
|
|
||||||
Single-context layout — `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.
|
Single-context layout - `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.
|
||||||
|
|
||||||
|
### Writing style
|
||||||
|
|
||||||
|
Use regular dashes (`-`) in content, not em-dashes (`—`).
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
title: 'Complex Excel Uploads with Excel Maps'
|
||||||
|
description: Extract scattered, dynamic data from any Excel workbook using configurable Excel Maps - no manual reformatting required.
|
||||||
|
date: '2026-07-26 09:00:00'
|
||||||
|
author: 'Data Controller'
|
||||||
|
authorLink: https://www.linkedin.com/showcase/data_controller
|
||||||
|
tags:
|
||||||
|
- Announcements
|
||||||
|
---
|
||||||
|
|
||||||
|
# Complex Excel Uploads with Excel Maps
|
||||||
|
|
||||||
|
Not all spreadsheets arrive in a tidy, tabular format - and now they don't have to. Data Controller's **Complex Excel Upload** feature lets you extract data from anywhere in a workbook using an **Excel Map**: a configurable set of rules for loading specific cells and ranges. Each rule defines a range ID, a start, and an end, and can use absolute or relative references - for example, matching a specific string in a cell, then moving down and across to capture the desired value. This makes it ideal for business reports and financial spreadsheets where the layout is dynamic and the data you need is scattered across multiple locations.
|
||||||
|
|
||||||
|
Once you've dragged in the spreadsheet and the rules have run, submitting the data stages it alongside a copy of the original Excel file - preserving a complete audit trail right back to the source. The extracted data is transposed into a single column in the [`MPE_XLMAP_DATA`](https://docs.datacontroller.io/tables/mpe_xlmap_data/) table, ready for you to build jobs that present it however your business requires. You can also adjust your map's attributes in the [`MPE_XLMAP_INFO`](https://docs.datacontroller.io/tables/mpe_xlmap_info/) table to load data into different target tables.
|
||||||
|
|
||||||
|
All of this flows through the standard Data Controller approval process and data quality checks - governance included, straight out of the box.
|
||||||
|
|
||||||
|
See it in action:
|
||||||
|
|
||||||
|
<div style="position: relative; padding-top: 56.25%; margin-bottom: 2rem;"><iframe title="Complex Excel Uploads" width="100%" height="100%" src="https://vid.4gl.io/videos/embed/7jRSxNs2ENJ3dBEZun4cPf?peertubeLink=0" style="border: 0px; position: absolute; inset: 0px;" allow="fullscreen" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"></iframe></div>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Learn more in the [documentation](https://docs.datacontroller.io/excel/#complex-excel-uploads).
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 254 KiB |
@@ -15,7 +15,6 @@ module.exports = {
|
|||||||
plugins: [
|
plugins: [
|
||||||
'gatsby-plugin-styled-components',
|
'gatsby-plugin-styled-components',
|
||||||
'gatsby-plugin-image',
|
'gatsby-plugin-image',
|
||||||
'gatsby-plugin-react-helmet',
|
|
||||||
'gatsby-plugin-sitemap',
|
'gatsby-plugin-sitemap',
|
||||||
{
|
{
|
||||||
resolve: 'gatsby-plugin-manifest',
|
resolve: 'gatsby-plugin-manifest',
|
||||||
|
|||||||
Generated
+439
-395
File diff suppressed because it is too large
Load Diff
+1
-9
@@ -30,7 +30,6 @@
|
|||||||
"gatsby-plugin-local-search": "^2.0.1",
|
"gatsby-plugin-local-search": "^2.0.1",
|
||||||
"gatsby-plugin-manifest": "^5.15.0",
|
"gatsby-plugin-manifest": "^5.15.0",
|
||||||
"gatsby-plugin-matomo": "^0.17.0",
|
"gatsby-plugin-matomo": "^0.17.0",
|
||||||
"gatsby-plugin-react-helmet": "^6.15.0",
|
|
||||||
"gatsby-plugin-sharp": "^5.15.0",
|
"gatsby-plugin-sharp": "^5.15.0",
|
||||||
"gatsby-plugin-sitemap": "^6.15.0",
|
"gatsby-plugin-sitemap": "^6.15.0",
|
||||||
"gatsby-plugin-styled-components": "^6.15.0",
|
"gatsby-plugin-styled-components": "^6.15.0",
|
||||||
@@ -43,7 +42,6 @@
|
|||||||
"nostr-tools": "^2.7.0",
|
"nostr-tools": "^2.7.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-helmet": "^6.1.0",
|
|
||||||
"react-icons": "^5.2.1",
|
"react-icons": "^5.2.1",
|
||||||
"react-share": "^5.1.0",
|
"react-share": "^5.1.0",
|
||||||
"react-use-flexsearch": "^0.1.1",
|
"react-use-flexsearch": "^0.1.1",
|
||||||
@@ -56,19 +54,13 @@
|
|||||||
"@types/node": "^20.19.43",
|
"@types/node": "^20.19.43",
|
||||||
"@types/react": "^18.3.31",
|
"@types/react": "^18.3.31",
|
||||||
"@types/react-dom": "^18.3.7",
|
"@types/react-dom": "^18.3.7",
|
||||||
"@types/react-helmet": "^6.1.11",
|
|
||||||
"bootstrap": "^5.0.0-beta3",
|
"bootstrap": "^5.0.0-beta3",
|
||||||
"cloudron-surfer": "^6.4.1",
|
"cloudron-surfer": "^6.4.1",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"typescript": "^7.0.2"
|
"typescript": "^7.0.2"
|
||||||
},
|
},
|
||||||
"allowScripts": {
|
|
||||||
"lmdb@2.5.2": true,
|
|
||||||
"lmdb@2.5.3": true,
|
|
||||||
"msgpackr@1.10.2": true,
|
|
||||||
"@parcel/watcher@2.5.1": true
|
|
||||||
},
|
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
"sharp": "^0.33.5",
|
||||||
"msgpackr": "^1.12.1",
|
"msgpackr": "^1.12.1",
|
||||||
"lmdb": "^2.9.4",
|
"lmdb": "^2.9.4",
|
||||||
"ordered-binary": "^1.6.1",
|
"ordered-binary": "^1.6.1",
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import background from '../../images/home_hero_bg.png'
|
|
||||||
|
|
||||||
export const Hero = styled.main<{ bg?: boolean }>`
|
export const Hero = styled.main<{ bg?: boolean }>`
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 50px 0;
|
padding: 50px 0;
|
||||||
color: white;
|
color: white;
|
||||||
background-color: #314351;
|
background-color: #314351;
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-image: ${(props) => (props.bg ? `url(${background})` : 'none')};
|
|
||||||
background-attachment: scroll;
|
|
||||||
background-position: bottom right;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
export const HeroHeading = styled.h1`
|
export const HeroHeading = styled.h1`
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const naviLinks: NaviLink[] = [
|
|||||||
{ name: 'Feed', url: '/feed/', active: 'no' },
|
{ name: 'Feed', url: '/feed/', active: 'no' },
|
||||||
{ name: 'FAQ', url: '/faq/', active: 'no' },
|
{ name: 'FAQ', url: '/faq/', active: 'no' },
|
||||||
{
|
{
|
||||||
name: 'Documentation',
|
name: 'Docs',
|
||||||
url: 'https://docs.datacontroller.io/',
|
url: 'https://docs.datacontroller.io/',
|
||||||
active: 'no'
|
active: 'no'
|
||||||
},
|
},
|
||||||
|
|||||||
+21
-17
@@ -1,5 +1,4 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
|
||||||
import { useStaticQuery, graphql } from 'gatsby'
|
import { useStaticQuery, graphql } from 'gatsby'
|
||||||
|
|
||||||
import type { SeoProps } from '../types'
|
import type { SeoProps } from '../types'
|
||||||
@@ -38,21 +37,7 @@ const Seo: React.FC<SeoProps> = ({
|
|||||||
? `${siteUrl}${previewImg}`
|
? `${siteUrl}${previewImg}`
|
||||||
: `${siteUrl}/img/data-controller.svg`
|
: `${siteUrl}/img/data-controller.svg`
|
||||||
|
|
||||||
return (
|
const metaTags = (
|
||||||
<Helmet
|
|
||||||
htmlAttributes={{
|
|
||||||
lang
|
|
||||||
}}
|
|
||||||
title={pageTitle}
|
|
||||||
link={[
|
|
||||||
{
|
|
||||||
rel: 'alternate',
|
|
||||||
type: 'application/rss+xml',
|
|
||||||
title: `${defaultTitle} RSS Feed`,
|
|
||||||
href: `${siteUrl}rss.xml`
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
meta={(
|
|
||||||
[
|
[
|
||||||
{ name: 'author', property: 'author', content: author },
|
{ name: 'author', property: 'author', content: author },
|
||||||
{
|
{
|
||||||
@@ -71,8 +56,27 @@ const Seo: React.FC<SeoProps> = ({
|
|||||||
{ property: `og:title`, content: title },
|
{ property: `og:title`, content: title },
|
||||||
{ property: `og:type`, content: `website` }
|
{ property: `og:type`, content: `website` }
|
||||||
] as Array<{ name?: string; property?: string; content?: string }>
|
] as Array<{ name?: string; property?: string; content?: string }>
|
||||||
).concat(meta)}
|
).concat(meta)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<html lang={lang} />
|
||||||
|
<title>{pageTitle}</title>
|
||||||
|
<link
|
||||||
|
rel="alternate"
|
||||||
|
type="application/rss+xml"
|
||||||
|
title={`${defaultTitle} RSS Feed`}
|
||||||
|
href={`${siteUrl}rss.xml`}
|
||||||
/>
|
/>
|
||||||
|
{metaTags.map((tag, index) => (
|
||||||
|
<meta
|
||||||
|
key={tag.name || tag.property || index}
|
||||||
|
name={tag.name}
|
||||||
|
property={tag.property}
|
||||||
|
content={tag.content}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -14,7 +14,6 @@ const NotFound: React.FC<PageProps<unknown, PageContext>> = ({
|
|||||||
pageContext
|
pageContext
|
||||||
}) => (
|
}) => (
|
||||||
<Layout location={location} heroSection={false}>
|
<Layout location={location} heroSection={false}>
|
||||||
<Seo title="Page Not Found" />
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<SideBar
|
<SideBar
|
||||||
pageContext={pageContext}
|
pageContext={pageContext}
|
||||||
@@ -26,3 +25,5 @@ const NotFound: React.FC<PageProps<unknown, PageContext>> = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
export default NotFound
|
export default NotFound
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="Page Not Found" />
|
||||||
|
|||||||
+2
-1
@@ -17,7 +17,6 @@ const About: React.FC<PageProps<unknown>> = ({ location }) => {
|
|||||||
heading="Behind Data Controller"
|
heading="Behind Data Controller"
|
||||||
desc="Data Controller is a product of 4GL, a brand of Bowe IO Ltd"
|
desc="Data Controller is a product of 4GL, a brand of Bowe IO Ltd"
|
||||||
>
|
>
|
||||||
<Seo title="About" />
|
|
||||||
<Section color="black" bgColor="white">
|
<Section color="black" bgColor="white">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="offset-md-2 col-md-8">
|
<div className="offset-md-2 col-md-8">
|
||||||
@@ -46,3 +45,5 @@ const About: React.FC<PageProps<unknown>> = ({ location }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default About
|
export default About
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="About" />
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ const Contact: React.FC<PageProps<unknown>> = ({ location }) => {
|
|||||||
heading="Book a Demo"
|
heading="Book a Demo"
|
||||||
desc="Schedule a demonstration of the Data Controller to see our latest features and explore use cases"
|
desc="Schedule a demonstration of the Data Controller to see our latest features and explore use cases"
|
||||||
>
|
>
|
||||||
<Seo title="Contact" />
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
@@ -193,3 +192,5 @@ Message: ${message}`
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default Contact
|
export default Contact
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="Contact" />
|
||||||
|
|||||||
+2
-1
@@ -20,7 +20,6 @@ const Faq: React.FC<PageProps<unknown>> = ({ location }) => {
|
|||||||
heading="Data Controller – FAQ"
|
heading="Data Controller – FAQ"
|
||||||
desc="Most common user questions and answers regarding the Data Controller"
|
desc="Most common user questions and answers regarding the Data Controller"
|
||||||
>
|
>
|
||||||
<Seo title="FAQ" />
|
|
||||||
<Section color="black" bgColor="white">
|
<Section color="black" bgColor="white">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-8">
|
<div className="col-md-8">
|
||||||
@@ -67,3 +66,5 @@ const Faq: React.FC<PageProps<unknown>> = ({ location }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default Faq
|
export default Faq
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="FAQ" />
|
||||||
|
|||||||
+2
-1
@@ -67,7 +67,6 @@ const Home: React.FC<PageProps<IndexPageData>> = ({ data, location }) => {
|
|||||||
heading="Flexible and Secure Data Modification"
|
heading="Flexible and Secure Data Modification"
|
||||||
desc="Data Controller for SAS® enables business users to update IT owned source tables, secured by review / approve workflow and full audit trail."
|
desc="Data Controller for SAS® enables business users to update IT owned source tables, secured by review / approve workflow and full audit trail."
|
||||||
>
|
>
|
||||||
<Seo />
|
|
||||||
<Section color="black" bgColor="white">
|
<Section color="black" bgColor="white">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-3">
|
<div className="col-md-3">
|
||||||
@@ -262,3 +261,5 @@ export const pageQuery = graphql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const Head = () => <Seo />
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ const MarkdownPageTemplate: React.FC<
|
|||||||
heading={frontmatter.heading}
|
heading={frontmatter.heading}
|
||||||
desc={frontmatter.desc}
|
desc={frontmatter.desc}
|
||||||
>
|
>
|
||||||
<Seo title={frontmatter.title} />
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<StyledMarkdown dangerouslySetInnerHTML={{ __html: html }} />
|
<StyledMarkdown dangerouslySetInnerHTML={{ __html: html }} />
|
||||||
</Section>
|
</Section>
|
||||||
@@ -50,6 +49,10 @@ const MarkdownPageTemplate: React.FC<
|
|||||||
|
|
||||||
export default MarkdownPageTemplate
|
export default MarkdownPageTemplate
|
||||||
|
|
||||||
|
export const Head: React.FC<{ data: MarkdownPageData }> = ({ data }) => (
|
||||||
|
<Seo title={data.markdownRemark.frontmatter.title} />
|
||||||
|
)
|
||||||
|
|
||||||
export const pageQuery = graphql`
|
export const pageQuery = graphql`
|
||||||
query ($id: String!) {
|
query ($id: String!) {
|
||||||
markdownRemark(id: { eq: $id }) {
|
markdownRemark(id: { eq: $id }) {
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ const BlogListTemplate: React.FC<PageProps<BlogListData, PageContext>> = ({
|
|||||||
heading="Data Controller’s Knowledge Base"
|
heading="Data Controller’s Knowledge Base"
|
||||||
desc="A section dedicated to news, updates and educational pieces."
|
desc="A section dedicated to news, updates and educational pieces."
|
||||||
>
|
>
|
||||||
<Seo title="Blog" />
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
@@ -126,3 +125,5 @@ export const pageQuery = graphql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="Blog" />
|
||||||
|
|||||||
@@ -14,17 +14,9 @@ const BlogPostTemplate: React.FC<
|
|||||||
PageProps<{ post: PostNode }, PageContext>
|
PageProps<{ post: PostNode }, PageContext>
|
||||||
> = ({ data, location, pageContext }) => {
|
> = ({ data, location, pageContext }) => {
|
||||||
const { post } = data
|
const { post } = data
|
||||||
const { previewImg } = post.frontmatter
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout location={location} heroSection={false}>
|
<Layout location={location} heroSection={false}>
|
||||||
<Seo
|
|
||||||
title={post.frontmatter.title}
|
|
||||||
description={post.frontmatter.description}
|
|
||||||
previewImg={
|
|
||||||
previewImg?.childImageSharp?.gatsbyImageData?.images?.fallback?.src
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
@@ -41,6 +33,21 @@ const BlogPostTemplate: React.FC<
|
|||||||
|
|
||||||
export default BlogPostTemplate
|
export default BlogPostTemplate
|
||||||
|
|
||||||
|
export const Head: React.FC<{ data: { post: PostNode } }> = ({ data }) => {
|
||||||
|
const { post } = data
|
||||||
|
const { previewImg } = post.frontmatter
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Seo
|
||||||
|
title={post.frontmatter.title}
|
||||||
|
description={post.frontmatter.description}
|
||||||
|
previewImg={
|
||||||
|
previewImg?.childImageSharp?.gatsbyImageData?.images?.fallback?.src
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const pageQuery = graphql`
|
export const pageQuery = graphql`
|
||||||
query PostByPath($id: String!) {
|
query PostByPath($id: String!) {
|
||||||
post: markdownRemark(id: { eq: $id }) {
|
post: markdownRemark(id: { eq: $id }) {
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ const BlogSearchTemplate: React.FC<PageProps<SearchData, PageContext>> = ({
|
|||||||
heading="Data Controller’s Knowledge Base"
|
heading="Data Controller’s Knowledge Base"
|
||||||
desc="A section dedicated to news, updates and educational pieces."
|
desc="A section dedicated to news, updates and educational pieces."
|
||||||
>
|
>
|
||||||
<Seo title="Blog" />
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
@@ -96,3 +95,5 @@ const BlogSearchTemplate: React.FC<PageProps<SearchData, PageContext>> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default BlogSearchTemplate
|
export default BlogSearchTemplate
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="Blog" />
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ const FeedListTemplate: React.FC<PageProps<FeedListData, PageContext>> = ({
|
|||||||
heading="Data Controller’s Feed"
|
heading="Data Controller’s Feed"
|
||||||
desc="Announcements and social media style updates from the Data Controller team."
|
desc="Announcements and social media style updates from the Data Controller team."
|
||||||
>
|
>
|
||||||
<Seo title="Feed" />
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
@@ -129,3 +128,5 @@ export const pageQuery = graphql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const Head = () => <Seo title="Feed" />
|
||||||
|
|||||||
@@ -14,17 +14,9 @@ const FeedPostTemplate: React.FC<
|
|||||||
PageProps<{ post: PostNode }, PageContext>
|
PageProps<{ post: PostNode }, PageContext>
|
||||||
> = ({ data, location, pageContext }) => {
|
> = ({ data, location, pageContext }) => {
|
||||||
const { post } = data
|
const { post } = data
|
||||||
const { previewImg } = post.frontmatter
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout location={location} heroSection={false}>
|
<Layout location={location} heroSection={false}>
|
||||||
<Seo
|
|
||||||
title={post.frontmatter.title}
|
|
||||||
description={post.frontmatter.description}
|
|
||||||
previewImg={
|
|
||||||
previewImg?.childImageSharp?.gatsbyImageData?.images?.fallback?.src
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Section color="black" bgColor="white" bottomArrow={false}>
|
<Section color="black" bgColor="white" bottomArrow={false}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
@@ -45,6 +37,21 @@ const FeedPostTemplate: React.FC<
|
|||||||
|
|
||||||
export default FeedPostTemplate
|
export default FeedPostTemplate
|
||||||
|
|
||||||
|
export const Head: React.FC<{ data: { post: PostNode } }> = ({ data }) => {
|
||||||
|
const { post } = data
|
||||||
|
const { previewImg } = post.frontmatter
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Seo
|
||||||
|
title={post.frontmatter.title}
|
||||||
|
description={post.frontmatter.description}
|
||||||
|
previewImg={
|
||||||
|
previewImg?.childImageSharp?.gatsbyImageData?.images?.fallback?.src
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const pageQuery = graphql`
|
export const pageQuery = graphql`
|
||||||
query FeedPostByPath($id: String!) {
|
query FeedPostByPath($id: String!) {
|
||||||
post: markdownRemark(id: { eq: $id }) {
|
post: markdownRemark(id: { eq: $id }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user