Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions layers/base/components/global/drupal-view--default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<div class="view">
<h1 class="text-4xl font-bold mb-8 text-center tracking-tight">{{ title }}</h1>
<div class="lg:flex lg:justify-around">
<component
:is="renderCustomElements(row)"
v-for="(row, index) in rows"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

index is following row, looks strange

:key="index"
class="w-full mb-8 lg:w-[33%]"
/>
</div>
<div class="text-center">
<DrupalViewsPagination
:total-pages="pager.totalPages"
:current="pager.current"
/>
</div>
</div>
</template>

<script setup lang="ts">
defineProps<{
title: string
rows?: object[]
pager?: object
}>()

const {renderCustomElements} = useDrupalCe()
</script>
21 changes: 21 additions & 0 deletions layers/base/components/global/media-image--default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<div class="relative">
<img
:src="image.url"
:title="image.title"
:alt="image.alt"
:width="image.width"
:height="image.height"
>
<div v-if="copyright" class="absolute bottom-0 right-0 bg-black/50 text-white text-xs px-2 py-1">
{{ copyright }}
</div>
</div>
</template>

<script setup lang="ts">
defineProps<{
image?: object
copyright?: string
}>()
</script>
19 changes: 19 additions & 0 deletions layers/base/components/global/node--default.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<div class="max-w-4xl mx-auto px-4 py-8">
<div class="mb-8">
<component :is="useDrupalCe().renderCustomElements(featuredImage)" class="w-full h-auto rounded-lg shadow-lg mb-6" />
<h1 v-if="title" class="text-4xl font-bold mb-4">{{ title }}</h1>
</div>
<div class="prose max-w-none mb-8 dark:prose-invert" v-html="content"></div>
</div>
</template>

<script setup lang="ts">
defineProps<{
// Layout-builder support.
sections?: object;
title?: string;
featuredImage?: object;
content?: string;
}>();
</script>
5 changes: 5 additions & 0 deletions layers/base/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({

})

52 changes: 52 additions & 0 deletions layers/blog/components/global/node-blog-card.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<nuxt-link :to="path.pathAlias" class="block">
<article class="rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 transition-all duration-200 bg-white dark:bg-gray-800 shadow-sm hover:shadow-md dark:shadow-gray-900/50 overflow-hidden">
<div class="overflow-hidden">
<component
:is="renderCustomElements(featuredImage)"
class="w-full h-full object-cover transition-transform duration-300 hover:scale-105"
/>
</div>
<div class="p-4">
<h2 v-if="title" class="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-2">
{{ title }}
</h2>
<div v-if="author || created" class="flex items-center gap-3 text-xs text-gray-600 dark:text-gray-400">
<span v-if="author" class="flex items-center gap-1">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
{{ author }}
</span>
<span v-if="created" class="flex items-center gap-1">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
{{ formatDate(created) }}
</span>
</div>
</div>
</article>
</nuxt-link>
</template>

<script setup lang="ts">
const { renderCustomElements } = useDrupalCe()
defineProps<{
title?: String;
path?: object;
featuredImage?: CustomElementContent;
author?: string;
created?: string;
}>()

const formatDate = (dateString: string) => {
if (!dateString) return '';
const date = new Date(dateString);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: but why not format the date with the formatter on the backend?

return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
}).format(date);
}
</script>
66 changes: 43 additions & 23 deletions layers/blog/components/global/node-blog-full.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
<template>
<div class="node">
<h2 v-if="title">Blog: {{ title }}</h2>
<slot name="image">
<component :is="useDrupalCe().renderCustomElements($attrs.image)" />
</slot>
<slot name="body">
<component :is="useDrupalCe().renderCustomElements($attrs.body)" />
</slot>
<div class="max-w-4xl mx-auto px-4 py-8">
<div class="mb-8">
<component :is="useDrupalCe().renderCustomElements(featuredImage)" class="w-full h-auto rounded-lg shadow-lg mb-6" />
<h1 v-if="title" class="text-4xl font-bold mb-4">{{ title }}</h1>
<div v-if="author || created" class="flex items-center gap-4 text-sm text-gray-600 dark:text-gray-400">
<span v-if="author" class="flex items-center gap-1">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
{{ author }}
</span>
<span v-if="created" class="flex items-center gap-1">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
{{ formatDate(created) }}
</span>
</div>
</div>
</template>

<script setup lang="ts">
defineSlots<{
body();
image();
}>()
defineProps<{
title?: string;
type?: string;
created?: number | string;
// Layout-builder support.
sections?: object;
}>()
</script>
<div class="prose max-w-none mb-8 dark:prose-invert" v-html="content"></div>
</div>
</template>

<script setup lang="ts">
defineProps<{
// Layout-builder support.
sections?: object;
title?: string;
featuredImage?: object;
content?: string;
author?: string;
created?: string;
}>();

const formatDate = (dateString: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would make sense to move it into composable to avoid defining it multiple times?

if (!dateString) return '';
const date = new Date(dateString);
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(date);
};
</script>
26 changes: 26 additions & 0 deletions layers/case-studies/components/global/node-case-study-card.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<nuxt-link :to="path.pathAlias" class="block">
<article class="rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 transition-all duration-200 bg-white dark:bg-gray-800 shadow-sm hover:shadow-md dark:shadow-gray-900/50 overflow-hidden">
<div class="overflow-hidden">
<component
:is="renderCustomElements(featuredImage)"
class="w-full h-full object-cover transition-transform duration-300 hover:scale-105"
/>
</div>
<div class="p-4">
<h2 v-if="title" class="text-lg font-semibold text-gray-900 dark:text-gray-100">
{{ title }}
</h2>
</div>
</article>
</nuxt-link>
</template>

<script setup lang="ts">
const { renderCustomElements } = useDrupalCe()
defineProps<{
title?: String;
path?: object;
featuredImage?: CustomElementContent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe define as slot also?

}>()
</script>
23 changes: 23 additions & 0 deletions layers/case-studies/components/global/node-case-study-full.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<div class="max-w-4xl mx-auto px-4 py-8">
<div class="mb-8">
<component :is="useDrupalCe().renderCustomElements(featuredImage)" class="w-full h-auto rounded-lg shadow-lg mb-6" />
<component :is="useDrupalCe().renderCustomElements(clientLogo)" class="w-80 mb-6" />
<h1 v-if="title" class="text-4xl font-bold mb-4">{{ title }}</h1>
</div>
<div class="prose max-w-none mb-8 dark:prose-invert" v-html="content"></div>
<a v-if="clientLink" :href="clientLink.clientLinkUri" target="_blank" class="inline-block px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg shadow-md transition-colors duration-200">Visit website</a>
</div>
</template>

<script setup lang="ts">
defineProps<{
// Layout-builder support.
sections?: object;
title?: string;
featuredImage?: object;
clientLogo?: object;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's differ CustomElementContent vs some object? link is not very nice like this, would it make sense to flatten?

clientLink?: object;
content?: string;
}>();
</script>
3 changes: 3 additions & 0 deletions layers/case-studies/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
})
26 changes: 26 additions & 0 deletions layers/events/components/global/node-event-card.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<nuxt-link :to="path.pathAlias" class="block">
<article class="rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 transition-all duration-200 bg-white dark:bg-gray-800 shadow-sm hover:shadow-md dark:shadow-gray-900/50 overflow-hidden">
<div class="overflow-hidden">
<component
:is="renderCustomElements(featuredImage)"
class="w-full h-full object-cover transition-transform duration-300 hover:scale-105"
/>
</div>
<div class="p-4">
<h2 v-if="title" class="text-lg font-semibold text-gray-900 dark:text-gray-100">
{{ title }}
</h2>
</div>
</article>
</nuxt-link>
</template>

<script setup lang="ts">
const { renderCustomElements } = useDrupalCe()
defineProps<{
title?: String;
path?: object;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is now some solution for the path I think latest CE-release has some special formatter, see 3.1 release notes

featuredImage?: CustomElementContent;
}>()
</script>
99 changes: 99 additions & 0 deletions layers/events/components/global/node-event-full.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<template>
<div class="max-w-4xl mx-auto px-4 py-8">
<div class="mb-8">
<component :is="useDrupalCe().renderCustomElements(featuredImage)" class="w-full h-auto rounded-lg shadow-lg mb-6" />
<h1 v-if="title" class="text-4xl font-bold mb-4">{{ title }}</h1>
</div>
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
<div v-if="date" class="mb-4">
<h3 class="text-lg font-semibold mb-2">Date:</h3>
<p>{{ formatDate(date.value) }} - {{ formatDate(date.endValue) }}</p>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a defined structure? (endDate is sometimes optional)

</div>
<div v-if="locationName" class="mb-4">
<h3 class="text-lg font-semibold mb-2">Venue:</h3>
<p>{{ locationName }}</p>
</div>
<div v-if="locationAddress" class="mb-4">
<p>{{ locationAddress.addressLine1 }}</p>
<p>{{ locationAddress.locality }},
{{ locationAddress.administrativeArea }} {{ locationAddress.postalCode }}</p>
</div>
<div v-if="link" class="mb-4">
<a :href="link.uri" target="_blank">{{ link.title }}</a>
</div>
</div>
<div class="prose max-w-none mb-8 dark:prose-invert" v-html="content"></div>
<div v-if="geofield" class="rounded-lg overflow-hidden shadow-lg">
<div class="h-[400px]">
<LMap
ref="map"
:zoom="zoom"
:center="latlng"
:use-global-leaflet="false"
class="h-full w-full"
>
<LTileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="&copy; <a href='https://www.openstreetmap.org/'>OpenStreetMap</a> contributors"
layer-type="base"
name="OpenStreetMap"
/>
<LMarker :lat-lng="latlng" />
</LMap>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import type { LatLngExpression } from 'leaflet';

const props = defineProps<{
// Layout-builder support.
sections?: object;
title?: string;
featuredImage?: object;
content?: string;
geofield?: {
lat: number;
lon: number;
};
date?: {
value: string;
endValue: string;
duration: string;
rrule: string;
rruleIndex: string;
timezone: string;
};
locationName?: string;
locationAddress?: {
addressLine1: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I was not aware it works like this also, that's nice, maybe we could use that for the link structure also?

locality: string;
administrativeArea: string;
postalCode: string;
};
link?: {
uri: string;
title: string;
};
}>();

const zoom = ref(13);
const latlng = computed<LatLngExpression>(() => {
if (props.geofield) {
return [props.geofield.lat, props.geofield.lon];
}
return [0, 0];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe find a better default location than south of coast of Africa.
Or maybe we could add a check that doesn't display the location if 0,0 is output although null response would be better in that case

});

const formatDate = (timestamp: string) => {
if (!timestamp) return '';
const date = new Date(Number(timestamp) * 1000);
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(date);
};
</script>
4 changes: 4 additions & 0 deletions layers/events/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
modules: ['@nuxtjs/leaflet']
})
Loading