Whole lotta love.
This commit is contained in:
parent
40324ae10b
commit
13971f626c
@ -25,6 +25,7 @@
|
||||
"drupal/core-project-message": "^10.3",
|
||||
"drupal/core-recommended": "^10.3",
|
||||
"drupal/devel_entity_updates": "^4.1",
|
||||
"drupal/entity_clone": "^2.1@beta",
|
||||
"drupal/entity_hierarchy": "^3.3",
|
||||
"drupal/field_group": "^3.4",
|
||||
"drupal/flexslider": "^3.0@alpha",
|
||||
@ -35,6 +36,7 @@
|
||||
"drupal/html_formatter": "^2.0",
|
||||
"drupal/jsonapi_permission_access": "1.0.1",
|
||||
"drupal/layout_builder_admin_theme": "^2.0",
|
||||
"drupal/layout_builder_block_clone": "^1.3",
|
||||
"drupal/layout_builder_styles": "^2.0",
|
||||
"drupal/mailsystem": "^4.5",
|
||||
"drupal/migrate_plus": "^6.0",
|
||||
@ -45,6 +47,7 @@
|
||||
"drupal/stage_file_proxy": "^3.1",
|
||||
"drupal/views_bulk_operations": "^4.2",
|
||||
"drupal/views_json_source": "^2.0",
|
||||
"drupal/workflow": "^1.8",
|
||||
"drush/drush": "^12.4",
|
||||
"symfony/css-selector": "^6",
|
||||
"symfony/dom-crawler": "^6",
|
||||
@ -65,7 +68,8 @@
|
||||
"phpstan/extension-installer": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||
"php-http/discovery": true,
|
||||
"cweagans/composer-patches": true
|
||||
"cweagans/composer-patches": true,
|
||||
"tbachert/spi": true
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
|
||||
1424
composer.lock
generated
1424
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
name: Auto Alt
|
||||
description: 'AI generated alt text on media items.'
|
||||
type: module
|
||||
package: Media
|
||||
core_version_requirement: ^10 || ^11
|
||||
@ -1,9 +0,0 @@
|
||||
auto_alt:
|
||||
css:
|
||||
theme:
|
||||
css/styles.css: { }
|
||||
js:
|
||||
js/autoAlt.js: { }
|
||||
dependencies:
|
||||
- core/once
|
||||
- core/drupal
|
||||
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
function auto_alt_form_alter(&$form, &$form_state, $form_id) {
|
||||
if ($form_id !== 'media_image_edit_form') {
|
||||
return;
|
||||
}
|
||||
$form['auto_alt'] = [
|
||||
'#type' => 'markup',
|
||||
'#markup' => '<span id="autoalt">🪄</span>'
|
||||
];
|
||||
$form['#attached']['library'][] = 'auto_alt/auto_alt';
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
auto_alt.content:
|
||||
path: '/ai/alt-text-generator'
|
||||
defaults:
|
||||
_controller: '\Drupal\auto_alt\Controller\AltTextGenerator::generate'
|
||||
_title: ''
|
||||
requirements:
|
||||
_permission: 'access content'
|
||||
@ -1,19 +0,0 @@
|
||||
.form-managed-file__meta-items {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#autoalt {
|
||||
position: absolute;
|
||||
top: 46px;
|
||||
right: 3px;
|
||||
padding: 8px;
|
||||
background: 'whitesmoke';
|
||||
transform: translateY(-50%);
|
||||
border-radius: 0 5px 5px 0;
|
||||
cursor: pointer;
|
||||
transition: background .2s ease;
|
||||
}
|
||||
|
||||
#autoalt:hover {
|
||||
background: lightgray;
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
(function (Drupal, once) {
|
||||
Drupal.behaviors.autoAltBehavior = {
|
||||
attach: function (context, settings) {
|
||||
once('autoAltBehavior', '#edit-field-media-image-0-alt', context).forEach(function (element) {
|
||||
// Move the wand to where it should be.
|
||||
let wand = context.getElementById("autoalt");
|
||||
let mediaMeta = context.querySelector('.form-managed-file__meta-items');
|
||||
mediaMeta.append(wand);
|
||||
wand.addEventListener('click', generateAltText);
|
||||
});
|
||||
|
||||
async function generateAltText() {
|
||||
let imageUrl = document.querySelector('.image-preview__img-wrapper img').src;
|
||||
const url = "/ai/alt-text-generator?";
|
||||
try {
|
||||
const response = await fetch(url + new URLSearchParams({
|
||||
image: imageUrl,
|
||||
}).toString());
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
let altInput = document.getElementById('edit-field-media-image-0-alt');
|
||||
altInput.value = json;
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
})(Drupal, once);
|
||||
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\auto_alt\Controller;
|
||||
|
||||
use \Drupal\Core\Controller\ControllerBase;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Generate Alt Text for an image.
|
||||
*/
|
||||
class AltTextGenerator extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Returns a renderable array for a test page.
|
||||
*
|
||||
* return []
|
||||
*/
|
||||
public function generate() {
|
||||
// Get the url to the image from the request.
|
||||
$image_url = \Drupal::request()->get('image');
|
||||
if (!$image_url) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$image_contents = file_get_contents($image_url);
|
||||
$encoded_image = base64_encode($image_contents);
|
||||
// Now send this to chat gpt / ai to generate alt text.
|
||||
|
||||
$response = [
|
||||
"This is some alt text for an image.",
|
||||
"A new string for alt text",
|
||||
"Another string about alt text",
|
||||
];
|
||||
$text_to_return = rand(0,2);
|
||||
$json_response = new JsonResponse();
|
||||
$json_response->headers->set('Content-Type', 'application/json');
|
||||
$json_response->setData($response[$text_to_return]);
|
||||
return $json_response;
|
||||
}
|
||||
|
||||
}
|
||||
24
web/modules/custom/dc_core/css/admin.css
Normal file
24
web/modules/custom/dc_core/css/admin.css
Normal file
@ -0,0 +1,24 @@
|
||||
#block-gin-content .admin-item {
|
||||
margin: 20px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#block-gin-content .admin-item__description {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.draggable .tabledrag-cell {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.entity-form-display-form {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.entity-form-display-form select, .field-plugin-summary {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.layout-builder-block {
|
||||
padding: 0 !important;
|
||||
}
|
||||
5
web/modules/custom/dc_core/dc_core.info.yml
Normal file
5
web/modules/custom/dc_core/dc_core.info.yml
Normal file
@ -0,0 +1,5 @@
|
||||
name: DC Core
|
||||
description: 'Core functionality and overrides.'
|
||||
package: DC Core
|
||||
type: module
|
||||
core_version_requirement: ^10 || ^11
|
||||
4
web/modules/custom/dc_core/dc_core.libraries.yml
Normal file
4
web/modules/custom/dc_core/dc_core.libraries.yml
Normal file
@ -0,0 +1,4 @@
|
||||
admin_overrides:
|
||||
css:
|
||||
theme:
|
||||
css/admin.css: { }
|
||||
10
web/modules/custom/dc_core/dc_core.module
Normal file
10
web/modules/custom/dc_core/dc_core.module
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
function dc_core_page_attachments(array &$attachments) {
|
||||
if (\Drupal::service('router.admin_context')->isAdminRoute()) {
|
||||
$attachments['#attached']['library'][] = 'dc_core/admin_overrides';
|
||||
}
|
||||
if (\Drupal::routeMatch()->getRouteObject()->getOption('_layout_builder')) {
|
||||
$attachments['#attached']['library'][] = 'dc_core/admin_overrides';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
name: Accordion
|
||||
props:
|
||||
type: object
|
||||
properties:
|
||||
accordionType:
|
||||
type: string
|
||||
title: Accordion Type
|
||||
description: 'The type of accordion.'
|
||||
slots:
|
||||
headline:
|
||||
title: Headline
|
||||
required: true
|
||||
description: This is the headline for an accordion.
|
||||
body:
|
||||
title: Body
|
||||
required: true
|
||||
description: This is the body for an accordion.
|
||||
libraryOverrides:
|
||||
dependencies:
|
||||
- core/drupal
|
||||
- core/once
|
||||
@ -0,0 +1 @@
|
||||
@charset "UTF-8";.ib-accordion__item{margin:10px 0;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.ib-accordion__headline{background-color:#efefef;padding:20px;cursor:pointer;display:flex;align-items:center}.ib-accordion__headline h1,.ib-accordion__headline h2,.ib-accordion__headline h3,.ib-accordion__headline h4,.ib-accordion__headline h5,.ib-accordion__headline h6{font-size:18px!important;margin:0!important;color:#3272b3;--bs-heading-color:#3272b3}.ib-accordion__headline::before{display:flex;float:left;content:"+";font-size:30px;font-weight:700;justify-content:center;align-items:center;background-color:var(--site-primary);border-radius:100%;width:30px;height:30px;color:#fff;margin-right:10px}.ib-accordion__body{padding:0 20px;max-height:0;overflow:hidden;will-change:max-height;transition:.25s ease-out;align-items:center}.ib-accordion__body>:first-child{margin:20px 0}.ib-accordion__active .ib-accordion__headline::before{content:"−"}
|
||||
@ -0,0 +1,38 @@
|
||||
(function (Drupal, once) {
|
||||
Drupal.behaviors.accordion = {
|
||||
attach(context) {
|
||||
const accordions = once('accordion', '.ib-accordion__item', context);
|
||||
if (!accordions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const openAccordion = (accordion) => {
|
||||
const content = accordion.querySelector(".ib-accordion__body");
|
||||
accordion.classList.add("ib-accordion__active");
|
||||
content.style.maxHeight = content.scrollHeight + "px";
|
||||
content.setAttribute('aria-expanded', true);
|
||||
}
|
||||
|
||||
const closeAccordion = (accordion) => {
|
||||
const content = accordion.querySelector(".ib-accordion__body");
|
||||
accordion.classList.remove("ib-accordion__active");
|
||||
content.style.maxHeight = null;
|
||||
content.setAttribute('aria-expanded', false)
|
||||
}
|
||||
|
||||
accordions.forEach((accordion) => {
|
||||
const headline = accordion.querySelector(".ib-accordion__headline");
|
||||
const content = accordion.querySelector(".ib-accordion__body");
|
||||
|
||||
headline.onclick = () => {
|
||||
if (content.style.maxHeight) {
|
||||
closeAccordion(accordion);
|
||||
} else {
|
||||
accordions.forEach((accordion) => closeAccordion(accordion));
|
||||
openAccordion(accordion);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}(Drupal, once));
|
||||
@ -0,0 +1,59 @@
|
||||
.ib-accordion {
|
||||
|
||||
&__item {
|
||||
margin: 10px 0;
|
||||
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
&__headline {
|
||||
background-color: #EFEFEF;
|
||||
padding: 20px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: 18px !important;
|
||||
margin: 0 !important;
|
||||
color: #3272b3;
|
||||
--bs-heading-color: #3272b3;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: flex;
|
||||
float: left;
|
||||
content: "\002B";
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: var(--site-primary);
|
||||
border-radius: 100%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
color: #fff;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 0 20px;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
will-change: max-height;
|
||||
transition: all 0.25s ease-out;
|
||||
align-items: center;
|
||||
|
||||
> :first-child {
|
||||
margin: 20px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__active {
|
||||
.ib-accordion__headline::before {
|
||||
content: "\2212";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
{% set classes = [
|
||||
'ib-accordion__item',
|
||||
'ib-accordion__' ~ type|clean_class,
|
||||
] %}
|
||||
|
||||
{% set ariaLabel = 'accordion-' ~ random(0, 10000) %}
|
||||
<div class="{{ classes|join(" ") }}">
|
||||
<div class="ib-accordion__headline">
|
||||
{% block headline %}{% endblock %}
|
||||
</div>
|
||||
<div class="ib-accordion__body" aria-labelledby="{{ ariaLabel }}" aria-expanded="false">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,21 @@
|
||||
name: Banner
|
||||
props:
|
||||
type: object
|
||||
properties:
|
||||
bannerText:
|
||||
type: string
|
||||
title: Banner Text
|
||||
description: This is the text for the banner.
|
||||
bannerImage:
|
||||
type: string
|
||||
title: Banner Image
|
||||
description: This is the image for the banner.
|
||||
bannerType:
|
||||
type: string
|
||||
title: Banner Type
|
||||
description: The type of banner.
|
||||
enum: ["full", "thin"]
|
||||
addClasses:
|
||||
type: string
|
||||
title: Additonal Classes
|
||||
description: String of additional classses to add to the banner.
|
||||
@ -0,0 +1 @@
|
||||
.banner__thin{height:192px}.banner__thin .banner__text{position:relative;top:50%;transform:translateY(-50%)}.banner-image{background-size:cover;background-position:center;background-repeat:no-repeat}
|
||||
@ -0,0 +1,21 @@
|
||||
.banner {
|
||||
|
||||
&__thin {
|
||||
height: 192px;
|
||||
|
||||
.banner__text {
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
&-image {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
{%
|
||||
set classes = [
|
||||
'banner',
|
||||
'banner__' ~ bannerType|clean_class,
|
||||
]
|
||||
%}
|
||||
|
||||
{% if addClasses %}
|
||||
{% set classes = classes|merge([addClasses]) %}
|
||||
{% endif %}
|
||||
|
||||
<div class="{{ classes|join(" ") }}" style="background-image: url({{ bannerImage }})">
|
||||
<div class="banner__text container">
|
||||
{{ include('lawa:heading', { level: '1', headingText: bannerText, color: textColor }, with_context = false) }}
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,28 @@
|
||||
name: Heading
|
||||
props:
|
||||
type: object
|
||||
required:
|
||||
- level
|
||||
properties:
|
||||
level:
|
||||
type: string
|
||||
title: Heading Level
|
||||
description: 'The level of the heading, i.e. h1'
|
||||
enum: ['1', '2', '3', '4', '5', '6']
|
||||
headingText:
|
||||
type: string
|
||||
title: Heading Text
|
||||
description: 'The text within the heading.'
|
||||
color:
|
||||
type: string
|
||||
title: Heading Text Color
|
||||
description: The color of the text for the heading.
|
||||
enum: ['primary', 'secondary', 'white', 'black', 'neutral', 'teal']
|
||||
addClasses:
|
||||
type: string
|
||||
title: Classes
|
||||
description: Additional classes for the heading.
|
||||
subheading:
|
||||
type: string
|
||||
title: Subheading
|
||||
description: Text that can appear under the heading.
|
||||
@ -0,0 +1 @@
|
||||
.heading{margin:0}.heading__primary{color:#1d53a3}.heading__white{color:#fff}.heading__black{color:#000}.heading__neutral{color:#121212}.heading__teal{color:#01b9b6}
|
||||
@ -0,0 +1,27 @@
|
||||
@import 'src/sass/partials/variables';
|
||||
|
||||
.heading {
|
||||
|
||||
margin: 0;
|
||||
|
||||
&__primary {
|
||||
color: $primary_navy;
|
||||
}
|
||||
|
||||
&__white {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&__black {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
&__neutral {
|
||||
color: $neutrals;
|
||||
}
|
||||
|
||||
&__teal {
|
||||
color: $teal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{% set classes = ['heading'] %}
|
||||
|
||||
{% if color %}
|
||||
{% set classes = classes|merge(['heading__' ~ color|clean_class]) %}
|
||||
{% endif %}
|
||||
|
||||
{% if addClasses %}
|
||||
{% set classes = classes|merge([addClasses])%}
|
||||
{% endif %}
|
||||
|
||||
{% set heading = headingText.0['#context']['value']|default(headingText) %}
|
||||
|
||||
{% if ariaLabel %}
|
||||
<h{{ level }} id="{{ ariaLabel }}" class="{{ classes|join(" ")}}">{{ heading }}</h{{ level}}>
|
||||
{% else %}
|
||||
<h{{ level }} class="{{ classes|join(" ")}}">
|
||||
{{ heading }}
|
||||
{% if subheading %}
|
||||
<br><em>{{ subheading }}</em>
|
||||
{% endif %}
|
||||
</h{{ level}}>
|
||||
{% endif %}
|
||||
@ -1,2 +0,0 @@
|
||||
.idea
|
||||
.idea/
|
||||
@ -1,39 +0,0 @@
|
||||
## JSON Ingestion Examples
|
||||
|
||||
The data is pulled from https://jsonplaceholder.typicode.com/
|
||||
|
||||
### Approach 1: Migrate API
|
||||
#### Requirements
|
||||
- Migrate
|
||||
- Migrate Plus
|
||||
|
||||
There are 2 migrations:
|
||||
- images (5000 total)
|
||||
- json_posts_to_posts (100 total)
|
||||
|
||||
To run them you can do:
|
||||
```
|
||||
drush mim images --limit=100
|
||||
drush mim json_posts_to_posts
|
||||
```
|
||||
there are only 100 posts, so for our purposes we don't need more than 100 images.
|
||||
|
||||
Once both migrations have been run you can see the data at `/migration-posts` which is controller by a view.
|
||||
This approach has the advantage of requiring migrate API which pulls in a lot of helpful things,
|
||||
such as rollbacks, update old items, only importing new items...etc.
|
||||
### Approach 2: Custom Drush Command
|
||||
Will import the first 100 images only, followed by 100 posts.
|
||||
Also available for viewing on `/migration-posts` after import.
|
||||
```
|
||||
drush jie-posts
|
||||
```
|
||||
### Approach 3: Views JSON Source
|
||||
#### Requirements
|
||||
- views_json_source
|
||||
|
||||
Make sure `views_json_source` module is included in your codebase.
|
||||
Then visit `/views-json-source` after enabling this module which is a preconfigured view of titles and body fields from external JSON.
|
||||
|
||||
### Approach 4: Javascript Only
|
||||
1. Attach a javascript library to a page
|
||||
2. Fetch the API data and render it all client side
|
||||
@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "drupal/json_ingestion_examples",
|
||||
"type": "drupal-module",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dan Chadwick",
|
||||
"email": "dan.chadwick@acquia.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"drupal/core": "^9 || ^10",
|
||||
"drupal/migrate_plus": "^6.0",
|
||||
"drupal/views_json_source": "^1.4"
|
||||
}
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.field.node.post.body
|
||||
- field.field.node.post.field_image
|
||||
- image.style.thumbnail
|
||||
- node.type.post
|
||||
module:
|
||||
- image
|
||||
- path
|
||||
- text
|
||||
id: node.post.default
|
||||
targetEntityType: node
|
||||
bundle: post
|
||||
mode: default
|
||||
content:
|
||||
body:
|
||||
type: text_textarea_with_summary
|
||||
weight: 121
|
||||
region: content
|
||||
settings:
|
||||
rows: 9
|
||||
summary_rows: 3
|
||||
placeholder: ''
|
||||
show_summary: false
|
||||
third_party_settings: { }
|
||||
created:
|
||||
type: datetime_timestamp
|
||||
weight: 10
|
||||
region: content
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
field_image:
|
||||
type: image_image
|
||||
weight: 1
|
||||
region: content
|
||||
settings:
|
||||
progress_indicator: throbber
|
||||
preview_image_style: thumbnail
|
||||
third_party_settings: { }
|
||||
path:
|
||||
type: path
|
||||
weight: 30
|
||||
region: content
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
promote:
|
||||
type: boolean_checkbox
|
||||
weight: 15
|
||||
region: content
|
||||
settings:
|
||||
display_label: true
|
||||
third_party_settings: { }
|
||||
status:
|
||||
type: boolean_checkbox
|
||||
weight: 120
|
||||
region: content
|
||||
settings:
|
||||
display_label: true
|
||||
third_party_settings: { }
|
||||
sticky:
|
||||
type: boolean_checkbox
|
||||
weight: 16
|
||||
region: content
|
||||
settings:
|
||||
display_label: true
|
||||
third_party_settings: { }
|
||||
title:
|
||||
type: string_textfield
|
||||
weight: -5
|
||||
region: content
|
||||
settings:
|
||||
size: 60
|
||||
placeholder: ''
|
||||
third_party_settings: { }
|
||||
uid:
|
||||
type: entity_reference_autocomplete
|
||||
weight: 5
|
||||
region: content
|
||||
settings:
|
||||
match_operator: CONTAINS
|
||||
match_limit: 10
|
||||
size: 60
|
||||
placeholder: ''
|
||||
third_party_settings: { }
|
||||
hidden: { }
|
||||
@ -1,41 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.field.node.post.body
|
||||
- field.field.node.post.field_image
|
||||
- image.style.wide
|
||||
- node.type.post
|
||||
module:
|
||||
- image
|
||||
- text
|
||||
- user
|
||||
id: node.post.default
|
||||
targetEntityType: node
|
||||
bundle: post
|
||||
mode: default
|
||||
content:
|
||||
body:
|
||||
type: text_default
|
||||
label: hidden
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
weight: 101
|
||||
region: content
|
||||
field_image:
|
||||
type: image
|
||||
label: hidden
|
||||
settings:
|
||||
image_link: ''
|
||||
image_style: wide
|
||||
image_loading:
|
||||
attribute: eager
|
||||
third_party_settings: { }
|
||||
weight: -1
|
||||
region: content
|
||||
links:
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
weight: 100
|
||||
region: content
|
||||
hidden: { }
|
||||
@ -1,43 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.node.teaser
|
||||
- field.field.node.post.body
|
||||
- field.field.node.post.field_image
|
||||
- image.style.medium
|
||||
- node.type.post
|
||||
module:
|
||||
- image
|
||||
- text
|
||||
- user
|
||||
id: node.post.teaser
|
||||
targetEntityType: node
|
||||
bundle: post
|
||||
mode: teaser
|
||||
content:
|
||||
body:
|
||||
type: text_summary_or_trimmed
|
||||
label: hidden
|
||||
settings:
|
||||
trim_length: 600
|
||||
third_party_settings: { }
|
||||
weight: 101
|
||||
region: content
|
||||
field_image:
|
||||
type: image
|
||||
label: hidden
|
||||
settings:
|
||||
image_link: content
|
||||
image_style: medium
|
||||
image_loading:
|
||||
attribute: lazy
|
||||
third_party_settings: { }
|
||||
weight: -1
|
||||
region: content
|
||||
links:
|
||||
settings: { }
|
||||
third_party_settings: { }
|
||||
weight: 100
|
||||
region: content
|
||||
hidden: { }
|
||||
@ -1,23 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.node.body
|
||||
- node.type.post
|
||||
module:
|
||||
- text
|
||||
id: node.post.body
|
||||
field_name: body
|
||||
entity_type: node
|
||||
bundle: post
|
||||
label: Body
|
||||
description: ''
|
||||
required: false
|
||||
translatable: true
|
||||
default_value: { }
|
||||
default_value_callback: ''
|
||||
settings:
|
||||
display_summary: true
|
||||
required_summary: false
|
||||
allowed_formats: { }
|
||||
field_type: text_with_summary
|
||||
@ -1,37 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.node.field_image
|
||||
- node.type.post
|
||||
module:
|
||||
- image
|
||||
id: node.post.field_image
|
||||
field_name: field_image
|
||||
entity_type: node
|
||||
bundle: post
|
||||
label: Image
|
||||
description: ''
|
||||
required: false
|
||||
translatable: false
|
||||
default_value: { }
|
||||
default_value_callback: ''
|
||||
settings:
|
||||
handler: 'default:file'
|
||||
handler_settings: { }
|
||||
file_directory: '[date:custom:Y]-[date:custom:m]'
|
||||
file_extensions: 'png gif jpg jpeg webp'
|
||||
max_filesize: ''
|
||||
max_resolution: ''
|
||||
min_resolution: ''
|
||||
alt_field: true
|
||||
alt_field_required: true
|
||||
title_field: false
|
||||
title_field_required: false
|
||||
default_image:
|
||||
uuid: ''
|
||||
alt: ''
|
||||
title: ''
|
||||
width: null
|
||||
height: null
|
||||
field_type: image
|
||||
@ -1,33 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- file
|
||||
- image
|
||||
- node
|
||||
_core:
|
||||
default_config_hash: EymokncRIZ7SgQT2IdOQhQJicX4nNc0K89ik-LxmOHE
|
||||
id: node.field_image
|
||||
field_name: field_image
|
||||
entity_type: node
|
||||
type: image
|
||||
settings:
|
||||
target_type: file
|
||||
display_field: false
|
||||
display_default: false
|
||||
uri_scheme: public
|
||||
default_image:
|
||||
uuid: ''
|
||||
alt: ''
|
||||
title: ''
|
||||
width: null
|
||||
height: null
|
||||
module: image
|
||||
locked: false
|
||||
cardinality: 1
|
||||
translatable: true
|
||||
indexes:
|
||||
target_id:
|
||||
- target_id
|
||||
persist_with_no_fields: false
|
||||
custom_storage: false
|
||||
@ -1,17 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- menu_ui
|
||||
third_party_settings:
|
||||
menu_ui:
|
||||
available_menus:
|
||||
- main
|
||||
parent: 'main:'
|
||||
name: Post
|
||||
type: post
|
||||
description: ''
|
||||
help: ''
|
||||
new_revision: true
|
||||
preview_mode: 1
|
||||
display_submitted: true
|
||||
@ -1,191 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.node.teaser
|
||||
- node.type.post
|
||||
module:
|
||||
- node
|
||||
- user
|
||||
id: migration_based_posts
|
||||
label: 'Migration Based Posts'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
display:
|
||||
default:
|
||||
id: default
|
||||
display_title: Default
|
||||
display_plugin: default
|
||||
position: 0
|
||||
display_options:
|
||||
title: 'Migration Based Posts'
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
plugin_id: field
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
make_link: false
|
||||
absolute: false
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
strip_tags: false
|
||||
trim: false
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
offset: 0
|
||||
items_per_page: 10
|
||||
total_pages: null
|
||||
id: 0
|
||||
tags:
|
||||
next: ››
|
||||
previous: ‹‹
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
empty: { }
|
||||
sorts:
|
||||
created:
|
||||
id: created
|
||||
table: node_field_data
|
||||
field: created
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
entity_type: node
|
||||
entity_field: created
|
||||
plugin_id: date
|
||||
order: DESC
|
||||
expose:
|
||||
label: ''
|
||||
field_identifier: ''
|
||||
exposed: false
|
||||
granularity: second
|
||||
arguments: { }
|
||||
filters:
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
plugin_id: boolean
|
||||
value: '1'
|
||||
group: 1
|
||||
expose:
|
||||
operator: ''
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
value:
|
||||
post: post
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: 'entity:node'
|
||||
options:
|
||||
view_mode: teaser
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
query_comment: ''
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_tags: { }
|
||||
relationships: { }
|
||||
header: { }
|
||||
footer: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
page_1:
|
||||
id: page_1
|
||||
display_title: Page
|
||||
display_plugin: page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: migration-posts
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
@ -1,199 +0,0 @@
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- views_json_source
|
||||
id: views_json_source_demo
|
||||
label: 'Views JSON Source'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: json
|
||||
base_field: ''
|
||||
display:
|
||||
default:
|
||||
id: default
|
||||
display_title: Default
|
||||
display_plugin: default
|
||||
position: 0
|
||||
display_options:
|
||||
title: 'Views JSON Source'
|
||||
fields:
|
||||
value:
|
||||
id: value
|
||||
table: json
|
||||
field: value
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
entity_type: null
|
||||
entity_field: null
|
||||
plugin_id: views_json_source_field
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: h2
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
key: title
|
||||
trusted_html: 0
|
||||
value_1:
|
||||
id: value_1
|
||||
table: json
|
||||
field: value
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
plugin_id: views_json_source_field
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
key: body
|
||||
trusted_html: 0
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
offset: 0
|
||||
items_per_page: 10
|
||||
total_pages: null
|
||||
id: 0
|
||||
tags:
|
||||
next: ››
|
||||
previous: ‹‹
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
access:
|
||||
type: none
|
||||
options: { }
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
empty: { }
|
||||
sorts: { }
|
||||
arguments: { }
|
||||
filters: { }
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: fields
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
json_file: 'https://jsonplaceholder.typicode.com/posts'
|
||||
row_apath: /
|
||||
headers: ''
|
||||
single_payload: 0
|
||||
show_errors: 1
|
||||
relationships: { }
|
||||
header: { }
|
||||
footer: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
tags: { }
|
||||
page_1:
|
||||
id: page_1
|
||||
display_title: Page
|
||||
display_plugin: page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: views-json-source
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
tags: { }
|
||||
@ -1,5 +0,0 @@
|
||||
services:
|
||||
json_ingestion_examples.commands:
|
||||
class: Drupal\json_ingestion_examples\Drush\Commands\JsonIngestionCommands
|
||||
tags:
|
||||
- { name: drush.command }
|
||||
@ -1,9 +0,0 @@
|
||||
name: JSON Ingestion Examples
|
||||
type: module
|
||||
package: custom
|
||||
description: 'Ways to import JSON data to Drupal'
|
||||
core_version_requirement: ^9 || ^10
|
||||
dependencies:
|
||||
- drupal:migrate
|
||||
- drupal:migrate_plus
|
||||
- drupal:views_json_source
|
||||
@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
function json_ingestion_examples_install() {
|
||||
$mod_installer = \Drupal::service('module_installer');
|
||||
$mod_installer->install(['migrate', 'migrate_plus', 'views_json_source']);
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
id: images
|
||||
label: 'Import remote images.'
|
||||
source:
|
||||
plugin: url
|
||||
data_fetcher_plugin: http
|
||||
data_parser_plugin: json
|
||||
urls: 'https://jsonplaceholder.typicode.com/photos'
|
||||
item_selector: /
|
||||
constants:
|
||||
file_dest_dir: 'public://migrated-images/'
|
||||
jpeg: '.jpeg'
|
||||
ids:
|
||||
image_id:
|
||||
type: string
|
||||
fields:
|
||||
-
|
||||
name: image_id
|
||||
label: 'Image ID'
|
||||
selector: /id
|
||||
-
|
||||
name: image_title
|
||||
label: 'Image URL'
|
||||
selector: /title
|
||||
-
|
||||
name: image_url
|
||||
label: 'Image URL'
|
||||
selector: /url
|
||||
process:
|
||||
_prep_filename:
|
||||
-
|
||||
plugin: callback
|
||||
callable: basename
|
||||
source: image_url
|
||||
filename:
|
||||
plugin: concat
|
||||
source:
|
||||
- '@_prep_filename'
|
||||
- constants/jpeg
|
||||
_prep_file_destination:
|
||||
plugin: concat
|
||||
source:
|
||||
- constants/file_dest_dir
|
||||
- '@filename'
|
||||
uri:
|
||||
plugin: file_copy
|
||||
source:
|
||||
- image_url
|
||||
- '@_prep_file_destination'
|
||||
status:
|
||||
plugin: default_value
|
||||
default_value: 1
|
||||
alt: image_title
|
||||
destination:
|
||||
plugin: 'entity:file'
|
||||
@ -1,37 +0,0 @@
|
||||
id: json_posts_to_posts
|
||||
label: 'JSON Migrate - Posts to Posts'
|
||||
migration_group: migrate_posts
|
||||
source:
|
||||
plugin: url
|
||||
data_fetcher_plugin: http
|
||||
data_parser_plugin: json
|
||||
urls: 'https://jsonplaceholder.typicode.com/posts'
|
||||
item_selector: /
|
||||
ids:
|
||||
post_id:
|
||||
type: string
|
||||
fields:
|
||||
-
|
||||
name: post_id
|
||||
label: 'Post ID'
|
||||
selector: /id
|
||||
-
|
||||
name: post_title
|
||||
label: 'Post Title'
|
||||
selector: /title
|
||||
-
|
||||
name: post_body
|
||||
label: 'Post Body'
|
||||
selector: /body
|
||||
process:
|
||||
title: post_title
|
||||
body/value: post_body
|
||||
field_image:
|
||||
plugin: migration_lookup
|
||||
migration: images
|
||||
source: post_id # this gets an image with the same ID as the post.
|
||||
|
||||
destination:
|
||||
plugin: 'entity:node'
|
||||
default_bundle: post
|
||||
migration_dependencies: { }
|
||||
@ -1,90 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\json_ingestion_examples\Drush\Commands;
|
||||
|
||||
use Drupal\Core\File\FileSystemInterface;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drush\Commands\DrushCommands;
|
||||
|
||||
/**
|
||||
* Drush command file.
|
||||
*/
|
||||
class JsonIngestionCommands extends DrushCommands {
|
||||
|
||||
/**
|
||||
* A custom Drush command to displays the given text.
|
||||
*
|
||||
* @command json-ingestion-examples:update-posts
|
||||
* The amount to iterate over
|
||||
* @aliases jie-posts
|
||||
*/
|
||||
public function updatePosts() {
|
||||
$this->importImages();
|
||||
$this->importPosts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports all images.
|
||||
*/
|
||||
public function importImages() {
|
||||
// Go fetch JSON for images.
|
||||
$http_client = \Drupal::httpClient();
|
||||
$images_json_url = 'https://jsonplaceholder.typicode.com/photos';
|
||||
$images_json = $http_client->request('GET', $images_json_url)->getBody()->getContents();
|
||||
// Reduce to 100 images as only have 100 posts.
|
||||
$images_array = array_slice(json_decode($images_json), 0, 100);
|
||||
$directory = 'public://drush-generated';
|
||||
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
||||
$file_system = \Drupal::service('file_system');
|
||||
// Make sure directory exists.
|
||||
$file_system->prepareDirectory($directory, FileSystemInterface:: CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
|
||||
foreach ($images_array as $img_ob) {
|
||||
// Download file, always replace.
|
||||
$file = file_get_contents($img_ob->url);
|
||||
$filename = basename($img_ob->url) . '.jpeg';
|
||||
$filepath = $directory . '/' . $filename;
|
||||
$file_system->saveData($file, $filepath, FileSystemInterface::EXISTS_REPLACE);
|
||||
// Create file entity.
|
||||
$file = File::create([
|
||||
'filename' => $filename,
|
||||
'uri' => $filepath,
|
||||
'status' => 1,
|
||||
'uid' => 1,
|
||||
]);
|
||||
if ($file->save()) {
|
||||
$this->writeln("File $filename created");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports all posts.
|
||||
*/
|
||||
public function importPosts() {
|
||||
// Go fetch JSON for posts.
|
||||
$http_client = \Drupal::httpClient();
|
||||
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
|
||||
$posts_json_url = 'https://jsonplaceholder.typicode.com/posts';
|
||||
$posts_json = $http_client->request('GET', $posts_json_url)->getBody()->getContents();
|
||||
$posts_array = json_decode($posts_json);
|
||||
foreach ($posts_array as $post) {
|
||||
$node_check = $node_storage->loadByProperties([
|
||||
'type' => 'post',
|
||||
'title' => $post->title
|
||||
]);
|
||||
// If title already exists, skip.
|
||||
if ($node_check) {
|
||||
continue;
|
||||
}
|
||||
$new_post = Node::create(['type' => 'post']);
|
||||
$new_post->set('title', $post->title);
|
||||
$new_post->set('body', $post->body);
|
||||
$new_post->set('field_image', $post->id);
|
||||
$new_post->enforceIsNew();
|
||||
if ($new_post->save()) {
|
||||
$this->writeln("New post created: $post->title");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
name: Video Compressor
|
||||
description: 'Compresses videos to smaller size prior to upload.'
|
||||
core_version_requirement: ^10 || ^11
|
||||
package: Media
|
||||
type: module
|
||||
10
web/modules/custom/video_compressor/video_compressor.module
Normal file
10
web/modules/custom/video_compressor/video_compressor.module
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_presave().
|
||||
*/
|
||||
function video_compressor_entity_presave(EntityInterface $entity) {
|
||||
/* dump($entity); */
|
||||
}
|
||||
1408
web/themes/custom/dchadwick/package-lock.json
generated
1408
web/themes/custom/dchadwick/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,9 +11,12 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.20",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-sass": "^5.1.0"
|
||||
"gulp-sass": "^5.1.0",
|
||||
"postcss": "^8.4.47",
|
||||
"tailwindcss": "^3.4.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"sass": "^1.71.1"
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
// Colors.
|
||||
:root {
|
||||
--site-primary: #009FB7;
|
||||
|
||||
12
web/themes/custom/dchadwick/tailwind.config.js
Normal file
12
web/themes/custom/dchadwick/tailwind.config.js
Normal file
@ -0,0 +1,12 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./src/**/**.{scss}"],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user