Skip to content

Commit

Permalink
Merge pull request #11 from vokseverk/update-build-system
Browse files Browse the repository at this point in the history
Preparation for version 1.0
  • Loading branch information
greystate authored Mar 22, 2021
2 parents 6572d60 + 0bcc1e4 commit 57a8027
Show file tree
Hide file tree
Showing 22 changed files with 612 additions and 242 deletions.
79 changes: 32 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,60 @@
# Image Hotspot Property Editor for Umbraco 7
# Image Hotspot for Umbraco

This is an attempt to provide similar functionality to what was previously
available with the
[uComponents ImagePoint](http://ucomponents.github.io/data-types/image-point/)
data type in Umbraco, versions 4 and 6.
<img align="right" src="images/vv-imagehotspot-icon.png" width="180" height="180" alt="A rectangle with a circular hotspot inside a square with the Vokseværk ‘fire-heart’ logo">

This one's just called “Image Hotspot” because that's what our clients call it
when they ask for this kind of thing :-)
This property editor provides similar functionality to what was previously available with the [uComponents ImagePoint](http://ucomponents.github.io/data-types/image-point/) data type in Umbraco, versions 4 and 6.

_**PLEASE NOTE:** This may not at all be production ready for your particular
use, but if you want to try it out there's an Umbraco package available on the
releases page._
(This one's just called “Image Hotspot” because that's what our clients call it when they ask for this kind of thing 😁)

## What does it look like?
It's a property editor that displays an image and lets the editor place a hotspot on it.

Currently, it looks like this:
## Screenshots

### Configuration:
### Property editor:

<img src="screenshots/ImageHotspot_Config.jpg" width="467" alt="DataType Configuration" />
![Imagehotspot Editor](images/imagehotspot-editor.jpg "Property editor with insets of the alternate color themes")

*DataType Configuration*

The property editor looks for the **Image** by looking up the alias recursively,
so it's possible to use it on a doctype that's used by e.g. **Nested Content**
or something like [Embedded Content Blocks](https://our.umbraco.com/packages/backoffice-extensions/embedded-content-blocks/).
*Property editor with insets showing the alternate colors*

***

### Property editor:
The configuration looks like this:

<img src="screenshots/ImageHotspot_Themes.png" width="640" alt="Property editor with variant themes" />
### Configuration:

*Property editor with variant colors*
![Imagehotspot Config](images/imagehotspot-config.jpg "DataType Configuration")

("Color" defines the color of the Hotspot - all colors shown above)
*DataType Configuration*

The property editor looks for the **Image** by looking up the alias recursively,
so it's possible to use it on a doctype that's used by e.g. **Nested Content**, **Block List** or something like [Embedded Content Blocks](https://our.umbraco.com/packages/backoffice-extensions/embedded-content-blocks/).

***

### Property Data

The raw JSON data looks like this:

<img src="screenshots/ImageHotspot_JSON.png" width="431" alt="JSON Data" />

*JSON Data*
```json
{
"image": "/media/1492/what-a-nice-picture.jpg",
"left": 223,
"top": 307,
"percentX": 55.75,
"percentY": 74.878048780487804878,
"width": 400,
"height": 410
}
```

The hotspot coordinate is saved both as exact pixel values and as percentage
values, along with the image's path and width & height.
values, along with the image's path, width & height.

The [releases page][RELS] has **PropertyConverters** for v7 and v8, that you can grab and throw in your solution (or drop in the `App_Code` folder.

There's a **PropertyConverter** you can grab and throw in your solution (or
drop in the `App_Code` folder) here:
[ImageHotspotPropertyConverter.cs](src/ImageHotspotPropertyConverter.cs),
or you can download it from the release page.
[RELS]: https://github.com/vokseverk/Vokseverk.ImageHotspot/releases

This enables ModelsBuilder to do its magic and provide you with an ImageHotspot
object instead:
This enables ModelsBuilder to do its magic and provide you with an `ImageHotspot` object instead:

```csharp
public class ImageHotspot {
Expand All @@ -68,17 +67,3 @@ public class ImageHotspot {
public int Height { get; set; }
}
```

***

## TODO

- [ ] Add configuration prevalue for the `width` used in the backoffice
- [x] Get `imageSrc` from a mediapicker value of some sorts (e.g. recursively look for `umbracoFile` as the uComponents data type did)
- [x] Rename Theme config to Hotspot Color (or similar)
- [x] Add configuration prevalue for `theme`
- [x] Build script

## Credits

* LEGO image from [Louieland](http://reserve.louie.land/Wallpapers/LEGO/ "Index of /Wallpapers/LEGO")
42 changes: 22 additions & 20 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
PACKAGE_NAME=ImageHotspot

# Get the current version
VERSION=`grep -o ' packageVersion \"\(.*\)\"' src/version.ent | awk '{print $2}' | sed 's/"//g'`
VERSION=`grep -o ' packageVersion \"\(.*\)\"' src/package.ent | awk '{print $2}' | sed 's/"//g'`
NAMESPACE=`grep -o ' orgNamespace \"\(.*\)\"' src/package.ent | awk '{print $2}' | sed 's/"//g'`
PACKAGE=`grep -o ' propertyEditorAlias \"\(.*\)\"' src/package.ent | awk '{print $2}' | sed 's/"//g'`
PKG_NAME="${NAMESPACE}.${PACKAGE}"

# Create the dist directory if needed
if [[ ! -d dist ]]
then mkdir dist
fi
# Likewise, create the package dir
if [[ ! -d package ]]
then mkdir package
then mkdir -p dist/package
else
rm dist/package/*.*
fi

# Transform the package.xml file, pulling in the README
xsltproc --novalid --xinclude --output package/package.xml lib/packager.xslt src/package.xml
# Copy files
cp src/*.css dist/package/
cp src/*.js dist/package/
cp src/*.html dist/package/
# cp src/lang/*.xml dist/package/

# Copy files into package
cp src/*.js package/
cp src/*.css package/
cp src/*.html package/
cp src/*.manifest package/
# Copy the Value Converters to the dist/ folder
cp src/*.cs dist/

# Build the ZIP file
zip -j "dist/Vokseverk.$PACKAGE_NAME-$VERSION.zip" package/* -x \*.DS_Store
# Transform the package.xml file
xsltproc --novalid --xinclude --output dist/package/package.xml lib/packager.xslt src/package.xml

# Copy the PropertyConverter file for manual distribution
cp src/*.cs dist/
# Transform the manifest.xml file
xsltproc --novalid --xinclude --output dist/package/package.manifest lib/manifester.xslt src/manifest.xml


# Build the ZIP file
zip -j "dist/${PKG_NAME}-${VERSION}.zip" dist/package/* -x \*.DS_Store
Binary file added images/imagehotspot-config.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/imagehotspot-editor.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/vv-imagehotspot-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
153 changes: 153 additions & 0 deletions lib/manifester.xslt
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY % packageInfo SYSTEM "../src/package.ent">
%packageInfo;
]>
<!--
This stylesheet transforms a `manifest.xml` file into the `package.manifest`.
Yes, this is XSLT building JSON so don't look if you're not into either :)
You're welcome to ask me anything about this though.
-->
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
exclude-result-prefixes="str"
>
<xsl:output method="text"
indent="yes"
omit-xml-declaration="yes"
/>

<xsl:variable name="packageAlias" select="'&packageAlias;'" />
<xsl:variable name="version" select="'v&packageVersion;'" />

<xsl:variable name="quot">&quot;</xsl:variable>
<xsl:variable name="objStart">{</xsl:variable>
<xsl:variable name="objEnd">}</xsl:variable>
<xsl:variable name="newline">__NEWLINE__</xsl:variable>
<xsl:variable name="indent">__INDENT__</xsl:variable>

<xsl:template match="manifest">
<xsl:value-of select="$objStart" />
<xsl:text>propertyEditors: [</xsl:text>
<xsl:apply-templates select="propertyEditor" />
<xsl:text>],</xsl:text>

<xsl:text>css: [</xsl:text>
<xsl:for-each select="css">
<xsl:apply-templates select="." mode="quoted" />
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:for-each>
<xsl:text>],</xsl:text>

<xsl:text>javascript: [</xsl:text>
<xsl:for-each select="javascript">
<xsl:apply-templates select="." mode="quoted" />
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:for-each>
<xsl:text>]</xsl:text>
<xsl:text>}</xsl:text>
</xsl:template>

<xsl:template match="propertyEditor | field">
<xsl:text>{</xsl:text>
<xsl:apply-templates select="*" mode="json" />
<xsl:text>}</xsl:text>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="prevalues" mode="json">
<xsl:value-of select="name()" />
<xsl:text>: {</xsl:text>
<xsl:text>fields: [</xsl:text>
<xsl:apply-templates select="field" />
<xsl:text>]</xsl:text>
<xsl:text>}</xsl:text>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<!-- == == == == == == -->

<xsl:template match="view[contains(., '.')]" mode="json">
<xsl:value-of select="name()" />
<xsl:text>: &quot;</xsl:text>
<xsl:apply-templates select="." mode="versioned" />
<xsl:text>&quot;</xsl:text>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="*" mode="array">
<xsl:value-of select="name()" />
<xsl:text>: [</xsl:text>
<xsl:apply-templates select="*" mode="json" />
<xsl:text>]</xsl:text>
</xsl:template>

<xsl:template match="*" mode="json" priority="-1">
<xsl:value-of select="name()" />
<xsl:text>: </xsl:text>
<xsl:apply-templates select="text()" mode="quoted" />
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="*[. = 'true'] | *[. = 'false']" mode="json">
<xsl:value-of select="name()" />
<xsl:text>: </xsl:text>
<xsl:value-of select="." />
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="*[not(text()) and not(*)]" mode="json">
<xsl:value-of select="name()" />
<xsl:text>: ""</xsl:text>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="@*" mode="json" priority="-1">
<xsl:value-of select="name()" />
<xsl:text>: </xsl:text>
<xsl:apply-templates select="text()" mode="quoted" />
</xsl:template>

<xsl:template match="*[@type = 'int'] | *[@type = 'bool']" mode="json" priority="-1">
<xsl:value-of select="name()" />
<xsl:text>: </xsl:text>
<xsl:value-of select="." />
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="*[*]" mode="json" priority="-1">
<xsl:value-of select="name()" />
<xsl:text>: {</xsl:text>
<xsl:apply-templates select="*" mode="json" />
<xsl:text>}</xsl:text>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:template>

<xsl:template match="css | javascript" mode="quoted">
<xsl:text>&quot;</xsl:text>
<xsl:apply-templates select="." mode="versioned" />
<xsl:text>&quot;</xsl:text>
</xsl:template>

<xsl:template match="text()" mode="quoted">
<xsl:value-of select="concat($quot, ., $quot)" />
</xsl:template>

<xsl:template match="*" mode="versioned">
<xsl:variable name="pluginpath" select="concat('~/App_Plugins/', $packageAlias, '/')" />
<xsl:variable name="parts" select="str:split(., '.')" />
<xsl:value-of select="$pluginpath" />
<xsl:for-each select="$parts">
<xsl:if test="not(position() = 1) and not(position() = last())">.</xsl:if>
<xsl:if test="not(position() = last())">
<xsl:value-of select="." />
</xsl:if>
<xsl:if test="position() = last()">
<xsl:value-of select="concat('-', $version, '.', .)" />
</xsl:if>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>
Loading

0 comments on commit 57a8027

Please sign in to comment.