Skip to content

Commit

Permalink
eh?
Browse files Browse the repository at this point in the history
  • Loading branch information
markhuot committed Oct 26, 2023
1 parent 5b2992d commit e3612cf
Show file tree
Hide file tree
Showing 33 changed files with 425 additions and 59 deletions.
11 changes: 7 additions & 4 deletions src/Keystone.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
namespace markhuot\keystone;

use craft\base\Element;
use craft\fields\PlainText;
use craft\services\Fields;
use craft\web\Application as WebApplication;
use craft\web\UrlManager;
use craft\web\View;
use markhuot\keystone\actions\GetAttributeTypes;
use markhuot\keystone\actions\GetComponentType;
use markhuot\keystone\actions\GetIcons;
use markhuot\keystone\base\Plugin;
use markhuot\keystone\behaviors\CssRuleBehavior;
use markhuot\keystone\listeners\AddBodyParamObjectBehavior;
use markhuot\keystone\listeners\AttachInlineEditBehavior;
use markhuot\keystone\listeners\AttachPerRequestBehaviors;
use markhuot\keystone\listeners\AttachElementBehaviors;
use markhuot\keystone\listeners\DiscoverSiteComponentTypes;
use markhuot\keystone\listeners\MarkClassesSafeForTwig;
Expand All @@ -28,20 +32,19 @@ class Keystone extends Plugin
public function init(): void
{
listen(
[WebApplication::class, WebApplication::EVENT_BEFORE_REQUEST, AddBodyParamObjectBehavior::class],
[WebApplication::class, WebApplication::EVENT_BEFORE_REQUEST, AttachPerRequestBehaviors::class],
[Fields::class, Fields::EVENT_REGISTER_FIELD_TYPES, RegisterKeystoneFieldType::class],
[UrlManager::class, UrlManager::EVENT_REGISTER_CP_URL_RULES, RegisterCpUrlRules::class],
[GetComponentType::class, GetComponentType::EVENT_REGISTER_COMPONENT_TYPES, RegisterDefaultComponentTypes::class],
[GetComponentType::class, GetComponentType::EVENT_REGISTER_COMPONENT_TYPES, DiscoverSiteComponentTypes::class],
[GetAttributeTypes::class, GetAttributeTypes::EVENT_REGISTER_ATTRIBUTE_TYPE, RegisterDefaultAttributeTypes::class],
[Element::class, Element::EVENT_DEFINE_BEHAVIORS, AttachElementBehaviors::class],
[PlainText::class, PlainText::EVENT_DEFINE_BEHAVIORS, AttachInlineEditBehavior::class],
[Plugin::class, Plugin::EVENT_INIT, MarkClassesSafeForTwig::class],
[Plugin::class, Plugin::EVENT_INIT, RegisterTwigExtensions::class],
[Plugin::class, Plugin::EVENT_INIT, RegisterCollectionMacros::class],
);

\Craft::$app->getView()->attachBehaviors([CssRuleBehavior::class]);

parent::init();
}
}
18 changes: 18 additions & 0 deletions src/actions/GetIcons.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace markhuot\keystone\actions;

class GetIcons
{
public function handle()
{
$iconPath = \Craft::getAlias('@templates/icons/');
$icons = glob($iconPath.'*.svg');

return collect($icons)
->map(fn ($path) => [
'path' => str_replace($iconPath, '', $path),
'name' => ucfirst(pathinfo($path, PATHINFO_FILENAME)),
]);
}
}
2 changes: 1 addition & 1 deletion src/actions/MapExpandedAttributeValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public function handle(?array $value, string $property, string $expandedProperty
->mapWithKeys(fn ($value, $key) => [str_replace('&', $key, $expandedProperty) => $value])
->filter();
} else {
return collect([$property => $value['shorthand']])
return collect([$property => $value['shorthand'] ?? null])
->filter();
}
}
Expand Down
44 changes: 44 additions & 0 deletions src/actions/NormalizeFieldDataForComponent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace markhuot\keystone\actions;

use craft\base\FieldInterface;
use markhuot\keystone\base\InlineEditData;
use markhuot\keystone\models\Component;

class NormalizeFieldDataForComponent
{
public function __construct(
protected Component $component
) { }

public function handle(mixed $value, string $handle)
{
// Get the field from the component type
$field = $this->component->getType()->getField($handle);

// $field may be null if the field has been deleted from the twig code
// but still remains in the database.
// If possible normalize the data so the DB stored ID gets turned in to
// a Query object, for example.
$value = $field?->normalizeValue($value) ?? $value;

if ($field?->getBehavior('inlineEdit')) {
if ($field->isEditableInPreview()) {
return new InlineEditData($this->component, $handle, $value);
}
}

// @TODO add in logic to return a custom class here
// the custom class will be responsible for rendering the
// value in normal situations or a live editor in
// live preview situations.
// We'll monkey patch on a behavior to the PlainText field
// type to make this possible
// if ($this->getType()->getHandle() === 'site/components/tab' && $handle === 'description') {
// return 'foo';
// }

return $value;
}
}
32 changes: 32 additions & 0 deletions src/attributes/Alignment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace markhuot\keystone\attributes;

use Illuminate\Support\Collection;
use markhuot\keystone\base\Attribute;

class Alignment extends Attribute
{
public function __construct(
protected ?array $value = []
) {
}

public function getInputHtml(): string
{
return \Craft::$app->getView()->renderTemplate('keystone/styles/alignment', [
'name' => get_class($this),
'value' => $this->value,
]);
}

public function getCssRules(): Collection
{
return collect($this->value)

// re-map everything to proper CSS rules
->mapWithKeys(fn ($value, $key) => match ($key) {
default => [$key => $value],
});
}
}
31 changes: 31 additions & 0 deletions src/attributes/Grid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace markhuot\keystone\attributes;

use Illuminate\Support\Collection;
use markhuot\keystone\base\Attribute;

class Grid extends Attribute
{
public function __construct(
protected ?array $value = []
) {
}

public function getInputHtml(): string
{
return \Craft::$app->getView()->renderTemplate('keystone/styles/grid', [
'name' => get_class($this),
'value' => $this->value,
]);
}

public function getCssRules(): Collection
{
return collect($this->value)
->mapWithKeys(fn ($value, $key) => match($key) {
'grid-template-columns' => [$key => 'repeat(' . $value . ', minmax(0, 1fr))'],
default => [$key => $value],
});
}
}
3 changes: 3 additions & 0 deletions src/base/FieldDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public function build(): FieldInterface
if (empty($config['name'])) {
$config['name'] = ucfirst($config['handle']);
}
if ($className === Assets::class) {
$config['defaultUploadLocationSource'] = 'volume:' . (Craft::$app->getVolumes()->getAllVolumes()[0]->uid ?? null);
}

return Craft::$container->get($className, $params, $config);
}
Expand Down
24 changes: 24 additions & 0 deletions src/base/InlineEditData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace markhuot\keystone\base;

use craft\web\View;
use markhuot\keystone\models\Component;

class InlineEditData
{
public function __construct(
protected Component $component,
protected string $handle,
protected string $value
) { }

public function __toString()
{
return \Craft::$app->getView()->renderTemplate('keystone/inline-edit', [
'component' => $this->component,
'handle' => $this->handle,
'value' => $this->value,
], View::TEMPLATE_MODE_CP);
}
}
20 changes: 20 additions & 0 deletions src/behaviors/InlineEditBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace markhuot\keystone\behaviors;

use yii\base\Behavior;

class InlineEditBehavior extends Behavior
{
protected bool $editableInPreview = false;

public function setEditableInPreview(bool $editable=true)
{
$this->editableInPreview = $editable;
}

public function isEditableInPreview()
{
return $this->editableInPreview;
}
}
3 changes: 3 additions & 0 deletions src/controllers/ComponentsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public function actionAdd()
$path = $this->request->getQueryParam('path');
$slot = $this->request->getQueryParam('slot');
$sortOrder = $this->request->getRequiredQueryParam('sortOrder');
$parentId = last(explode('/', $path));
$parent = $parentId ? Component::findOne(['elementId' => $elementId, 'fieldId' => $fieldId, 'id' => $parentId]) : null;

return $this->asCpScreen()
->title('Add component')
Expand All @@ -38,6 +40,7 @@ public function actionAdd()
'field' => $field,
'path' => $path,
'slot' => $slot,
'parent' => $parent,
'types' => (new GetComponentType())->all(),
'sortOrder' => $sortOrder,
]);
Expand Down
14 changes: 0 additions & 14 deletions src/listeners/AddBodyParamObjectBehavior.php

This file was deleted.

14 changes: 14 additions & 0 deletions src/listeners/AttachInlineEditBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace markhuot\keystone\listeners;

use craft\events\DefineBehaviorsEvent;
use markhuot\keystone\behaviors\InlineEditBehavior;

class AttachInlineEditBehavior
{
public function handle(DefineBehaviorsEvent $event): void
{
$event->behaviors['inlineEdit'] = InlineEditBehavior::class;
}
}
18 changes: 18 additions & 0 deletions src/listeners/AttachPerRequestBehaviors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace markhuot\keystone\listeners;

use Craft;
use markhuot\keystone\behaviors\BodyParamObjectBehavior;
use markhuot\keystone\behaviors\CssRuleBehavior;

class AttachPerRequestBehaviors
{
public function handle(): void
{
Craft::$app->getRequest()->attachBehaviors(['bodyParamObject' => BodyParamObjectBehavior::class]);

Craft::$app->getView()->attachBehaviors(['cssRules' => CssRuleBehavior::class]);
Craft::$app->getView()->clearCssRules();
}
}
2 changes: 2 additions & 0 deletions src/listeners/MarkClassesSafeForTwig.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use craft\base\Event;
use craft\web\View;
use markhuot\keystone\base\AttributeBag;
use markhuot\keystone\base\InlineEditData;
use markhuot\keystone\base\SlotDefinition;
use markhuot\keystone\collections\SlotCollection;
use markhuot\keystone\models\Component;
Expand All @@ -27,6 +28,7 @@ public function handle(Event $event)
$escaper->addSafeClass(Component::class, ['all']);
$escaper->addSafeClass(SlotCollection::class, ['all']);
$escaper->addSafeClass(SlotDefinition::class, ['all']);
$escaper->addSafeClass(InlineEditData::class, ['all']);
}
Craft::$app->getView()->setTemplateMode($oldTemplateMode);
}
Expand Down
8 changes: 5 additions & 3 deletions src/listeners/RegisterDefaultAttributeTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ class RegisterDefaultAttributeTypes
{
public function handle(RegisterAttributeType $event)
{
$event->add(\markhuot\keystone\attributes\Display::class);
$event->add(\markhuot\keystone\attributes\Alignment::class);
$event->add(\markhuot\keystone\attributes\Background::class);
$event->add(\markhuot\keystone\attributes\Border::class);
$event->add(\markhuot\keystone\attributes\Display::class);
$event->add(\markhuot\keystone\attributes\Grid::class);
$event->add(\markhuot\keystone\attributes\Margin::class);
$event->add(\markhuot\keystone\attributes\Padding::class);
$event->add(\markhuot\keystone\attributes\Rotate::class);
$event->add(\markhuot\keystone\attributes\SpaceBetween::class);
$event->add(\markhuot\keystone\attributes\Background::class);
$event->add(\markhuot\keystone\attributes\Size::class);
$event->add(\markhuot\keystone\attributes\SpaceBetween::class);
$event->add(\markhuot\keystone\attributes\Text::class);
}
}
1 change: 1 addition & 0 deletions src/listeners/RegisterDefaultComponentTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ public function handle(RegisterComponentTypes $event)
$event->registerTwigTemplate('keystone/text', 'cp:keystone/components/text.twig');
$event->registerTwigTemplate('keystone/asset', 'cp:keystone/components/asset.twig');
$event->registerTwigTemplate('keystone/link', 'cp:keystone/components/link.twig');
$event->registerTwigTemplate('keystone/icon', 'cp:keystone/components/icon.twig');
}
}
3 changes: 2 additions & 1 deletion src/models/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Craft;
use markhuot\keystone\actions\GetComponentType;
use markhuot\keystone\actions\NormalizeFieldDataForComponent;
use markhuot\keystone\base\AttributeBag;
use markhuot\keystone\base\ComponentType;
use markhuot\keystone\base\SlotDefinition;
Expand Down Expand Up @@ -70,7 +71,7 @@ public function __get($name)
}

if ($name === 'data') {
$value->setNormalizer(fn ($handle, $value) => $this->getType()->getField($handle)?->normalizeValue($value) ?? $value);
$value->setNormalizer((new NormalizeFieldDataForComponent($this))->handle(...));
}

return $value;
Expand Down
2 changes: 1 addition & 1 deletion src/models/ComponentData.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function offsetGet(mixed $offset): mixed
$value = $this->getData()[$offset] ?? null;

if ($this->normalizer) {
return ($this->normalizer)($offset, $value);
return ($this->normalizer)($value, $offset);
}

return $value;
Expand Down
10 changes: 10 additions & 0 deletions src/resources/components/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,13 @@ document.addEventListener('click', async event => {
// ...
});
});

document.addEventListener('dblclick', event => {
const label = event.target.closest && event.target.closest('[data-keystone-select-type]');
if (! label) {
return;
}

const form = label.closest('form');
$(form).data('cpScreen').submit();
});
Loading

0 comments on commit e3612cf

Please sign in to comment.