From 7aa882c568af7f4f3227a508f8584c43741b8be5 Mon Sep 17 00:00:00 2001 From: Conor_Mack Date: Sat, 30 May 2020 18:59:33 +0100 Subject: [PATCH 01/34] Complete HSVAColor Class and Utils --- .../Colorpicker/Colorpicker.svelte | 0 .../Colorpicker/utils/HSVAColor.js | 66 +++++++++++ .../userInterface/Colorpicker/utils/utils.js | 108 ++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js create mode 100644 packages/builder/src/components/userInterface/Colorpicker/utils/utils.js diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js b/packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js new file mode 100644 index 0000000000..e39e700903 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js @@ -0,0 +1,66 @@ +import { + getHexaValues, + getRgbaValues, + hsvToHSL, + isValidRgba, + rgbToHSV, + hsvToRgb, +} from "./utils" + +export class HSVAColor { + h = 0 + s = 0 + v = 0 + a = 1 + + constructor(color) { + if (color.startsWith("#")) { + let [rHex, gHex, bHex, aHex] = getHexaValues(color) + this.hexaToHSVA([rHex, gHex, bHex], aHex) + } else if (color.startsWith("rgb")) { + let rgba = getRgbaValues(color) + this.rgbaToHSVA(rgba) + } + } + + setHSVA([h, s, v, a]) { + this.h = h + this.s = s + this.v = v + this.a = a + } + + getHSLA() { + const [h, s, l] = hsvToHSL([this.h, this.s, this.v]) + return `hsla(${h}, ${s}, ${l}, ${this.a})` + } + + hexaToHSVA(hex, alpha = "FF") { + const rgba = hex + .map(v => parseInt(v, 16)) + .concat((parseInt(alpha, 16) / 255).toFixed(1)) + this.rgbaToHSVA(rgba) + } + + rgbaToHSVA(rgba) { + if (isValidRgba(rgba)) { + const [r, g, b, a = "1"] = rgba + let hsv = rgbToHSV([r, g, b]) + this.setHSVA([...hsv, a]) + } + } + + hsvaToHexa() { + const [r, g, b, a] = this.hsvaToRgba() + const hexa = [r, g, b] + .map(v => v.toString(16)) + .concat((a * 255).toFixed(1).toString(16)) + return hexa + } + + hsvaToRgba() { + const { h, s, v, a } = this + let rgb = hsvToRgb([h, s, v]) + return [...rgb, a] + } +} diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils/utils.js b/packages/builder/src/components/userInterface/Colorpicker/utils/utils.js new file mode 100644 index 0000000000..7412c42e27 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/utils/utils.js @@ -0,0 +1,108 @@ +export const getRgbaValues = rgbaString => + rgbaString.replace(/[a-z\(\)\s]/gi, "").split(",") + +export const getHexaValues = hexString => + hexString.match(/[A-F]{2}|[A-F]\d{1}|\d{2}|\d[A-F]/gi) + +export const isValidRgba = rgba => { + let [r, g, b, a = 1] = rgba + + let isValidLengthRange = rgba.length === 3 || rgba.length === 4 + let isValidColorRange = [r, g, b].every(v => v >= 0 && v <= 255) + let isValidAlphaRange = rgba.length === 3 || (a >= 0 && a <= 1) + + return isValidLengthRange && isValidColorRange && isValidAlphaRange +} + +//Credit : https://github.com/Qix-/color-convert +export const rgbToHSV = rgb => { + let rdif + let gdif + let bdif + let h + let s + + const r = rgb[0] / 255 + const g = rgb[1] / 255 + const b = rgb[2] / 255 + const v = Math.max(r, g, b) + const diff = v - Math.min(r, g, b) + const diffc = function(c) { + return (v - c) / 6 / diff + 1 / 2 + } + + if (diff === 0) { + h = 0 + s = 0 + } else { + s = diff / v + rdif = diffc(r) + gdif = diffc(g) + bdif = diffc(b) + + if (r === v) { + h = bdif - gdif + } else if (g === v) { + h = 1 / 3 + rdif - bdif + } else if (b === v) { + h = 2 / 3 + gdif - rdif + } + + if (h < 0) { + h += 1 + } else if (h > 1) { + h -= 1 + } + } + + const hsvResult = [h * 360, s * 100, v * 100].map(v => v.toFixed(0)) + return hsvResult +} + +//Credit : https://github.com/Qix-/color-convert +export const hsvToRgb = hsv => { + const h = hsv[0] / 60 + const s = hsv[1] / 100 + let v = hsv[2] / 100 + const hi = Math.floor(h) % 6 + + const f = h - Math.floor(h) + const p = 255 * v * (1 - s) + const q = 255 * v * (1 - s * f) + const t = 255 * v * (1 - s * (1 - f)) + v *= 255 + + switch (hi) { + case 0: + return [v, t, p] + case 1: + return [q, v, p] + case 2: + return [p, v, t] + case 3: + return [p, q, v] + case 4: + return [t, p, v] + case 5: + return [v, p, q] + } +} + +//Credit : https://github.com/Qix-/color-convert +export const hsvToHSL = hsv => { + const h = hsv[0] + const s = hsv[1] / 100 + const v = hsv[2] / 100 + const vmin = Math.max(v, 0.01) + let sl + let l + + l = (2 - s) * v + const lmin = (2 - s) * vmin + sl = s * vmin + sl /= lmin <= 1 ? lmin : 2 - lmin + sl = sl || 0 + l /= 2 + + return [h, sl * 100, l * 100] +} From 2ec8ed5464e2e6df7768b59a63e73097aac9be46 Mon Sep 17 00:00:00 2001 From: Conor_Mack Date: Sun, 31 May 2020 20:55:51 +0100 Subject: [PATCH 02/34] Palette, Slider Components and Util Updates --- .../Colorpicker/Colorpicker.svelte | 32 ++++ .../userInterface/Colorpicker/Palette.svelte | 49 ++++++ .../userInterface/Colorpicker/Slider.svelte | 87 +++++++++++ .../userInterface/Colorpicker/drag.js | 23 +++ .../userInterface/Colorpicker/index.js | 2 + .../userInterface/Colorpicker/utils.js | 146 ++++++++++++++++++ .../Colorpicker/utils/HSVAColor.js | 66 -------- .../userInterface/Colorpicker/utils/utils.js | 108 ------------- 8 files changed, 339 insertions(+), 174 deletions(-) create mode 100644 packages/builder/src/components/userInterface/Colorpicker/Palette.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/Slider.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/drag.js create mode 100644 packages/builder/src/components/userInterface/Colorpicker/index.js create mode 100644 packages/builder/src/components/userInterface/Colorpicker/utils.js delete mode 100644 packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js delete mode 100644 packages/builder/src/components/userInterface/Colorpicker/utils/utils.js diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte index e69de29bb2..db70f3ad64 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte @@ -0,0 +1,32 @@ + + + + +
+ + + + (h = hue.detail)} /> + + (a = alpha.detail)} /> +
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte new file mode 100644 index 0000000000..4a4decfda8 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte @@ -0,0 +1,49 @@ + + + + +
+
+
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte new file mode 100644 index 0000000000..82e00baa93 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte @@ -0,0 +1,87 @@ + + + + +
handleClick(event.clientX)} + class="color-format-slider" + class:hue={type === 'hue'} + class:alpha={type === 'alpha'}> +
handleClick(e.detail)} + class="slider-thumb" + {style} /> +
diff --git a/packages/builder/src/components/userInterface/Colorpicker/drag.js b/packages/builder/src/components/userInterface/Colorpicker/drag.js new file mode 100644 index 0000000000..eb15c8d4fb --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/drag.js @@ -0,0 +1,23 @@ +export default function(node) { + function handleMouseDown() { + window.addEventListener('mousemove', handleMouseMove); + window.addEventListener('mouseup', handleMouseUp); + } + + function handleMouseMove(event) { + let mouseX = event.clientX; + console.log(mouseX); + node.dispatchEvent( + new CustomEvent('drag', { + detail: mouseX + }) + ); + } + + function handleMouseUp() { + window.removeEventListener('mousedown', handleMouseDown); + window.removeEventListener('mousemove', handleMouseMove); + } + + node.addEventListener('mousedown', handleMouseDown); +} diff --git a/packages/builder/src/components/userInterface/Colorpicker/index.js b/packages/builder/src/components/userInterface/Colorpicker/index.js new file mode 100644 index 0000000000..ad8187a09b --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/index.js @@ -0,0 +1,2 @@ +import Colorpicker from './Colorpicker.svelte'; +export default Colorpicker; diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils.js b/packages/builder/src/components/userInterface/Colorpicker/utils.js new file mode 100644 index 0000000000..98bb96d259 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/utils.js @@ -0,0 +1,146 @@ +export const getRgbaValues = (rgbaString) => rgbaString.replace(/[a-z()\s]/gi, '').split(','); + +export const getHexaValues = (hexString) => hexString.match(/[A-F]{2}|[A-F]\d{1}|\d{2}|\d[A-F]/gi); + +export const isValidRgba = (rgba) => { + let [ r, g, b, a = 1 ] = rgba; + + let isValidLengthRange = rgba.length === 3 || rgba.length === 4; + let isValidColorRange = [ r, g, b ].every((v) => v >= 0 && v <= 255); + let isValidAlphaRange = rgba.length === 3 || (a >= 0 && a <= 1); + + return isValidLengthRange && isValidColorRange && isValidAlphaRange; +}; + +export const determineColorType = (color) => { + let hsva = []; + if (color.startsWith('#')) { + let [ rHex, gHex, bHex, aHex ] = getHexaValues(color); + hsva = hexaToHSVA([ rHex, gHex, bHex ], aHex); + } else if (color.startsWith('rgb')) { + let rgba = getRgbaValues(color); + hsva = rgbaToHSVA(rgba); + } +}; + +export const getHSLA = (hsv, a) => { + const [ h, s, l ] = hsvToHSL(hsv); + return `hsla(${h}, ${s}, ${l}, ${a})`; +}; + +export const hexaToHSVA = (hex, alpha = 'FF') => { + const rgba = hex.map((v) => parseInt(v, 16)).concat((parseInt(alpha, 16) / 255).toFixed(1)); + return rgbaToHSVA(rgba); +}; + +export const rgbaToHSVA = (rgba) => { + if (isValidRgba(rgba)) { + const [ r, g, b, a = '1' ] = rgba; + let hsv = rgbToHSV([ r, g, b ]); + return [ ...hsv, a ]; + } +}; + +export const hsvaToHexa = () => { + const [ r, g, b, a ] = hsvaToRgba(); + const hexa = [ r, g, b ].map((v) => v.toString(16)).concat((a * 255).toFixed(1).toString(16)); + return hexa; +}; + +export const hsvaToRgba = (h, s, v, a) => { + let rgb = _hsvToRgb([ h, s, v ]); + return [ ...rgb, a ]; +}; + +//Credit : https://github.com/Qix-/color-convert +export const _rgbToHSV = (rgb) => { + let rdif; + let gdif; + let bdif; + let h; + let s; + + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function(c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = 1 / 3 + rdif - bdif; + } else if (b === v) { + h = 2 / 3 + gdif - rdif; + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + const hsvResult = [ h * 360, s * 100, v * 100 ].map((v) => v.toFixed(0)); + return hsvResult; +}; + +//Credit : https://github.com/Qix-/color-convert +export const _hsvToRgb = (hsv) => { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; + + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - s * f); + const t = 255 * v * (1 - s * (1 - f)); + v *= 255; + + switch (hi) { + case 0: + return [ v, t, p ]; + case 1: + return [ q, v, p ]; + case 2: + return [ p, v, t ]; + case 3: + return [ p, q, v ]; + case 4: + return [ t, p, v ]; + case 5: + return [ v, p, q ]; + } +}; + +//Credit : https://github.com/Qix-/color-convert +export const _hsvToHSL = (hsv) => { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; + + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= lmin <= 1 ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [ h, sl * 100, l * 100 ]; +}; diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js b/packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js deleted file mode 100644 index e39e700903..0000000000 --- a/packages/builder/src/components/userInterface/Colorpicker/utils/HSVAColor.js +++ /dev/null @@ -1,66 +0,0 @@ -import { - getHexaValues, - getRgbaValues, - hsvToHSL, - isValidRgba, - rgbToHSV, - hsvToRgb, -} from "./utils" - -export class HSVAColor { - h = 0 - s = 0 - v = 0 - a = 1 - - constructor(color) { - if (color.startsWith("#")) { - let [rHex, gHex, bHex, aHex] = getHexaValues(color) - this.hexaToHSVA([rHex, gHex, bHex], aHex) - } else if (color.startsWith("rgb")) { - let rgba = getRgbaValues(color) - this.rgbaToHSVA(rgba) - } - } - - setHSVA([h, s, v, a]) { - this.h = h - this.s = s - this.v = v - this.a = a - } - - getHSLA() { - const [h, s, l] = hsvToHSL([this.h, this.s, this.v]) - return `hsla(${h}, ${s}, ${l}, ${this.a})` - } - - hexaToHSVA(hex, alpha = "FF") { - const rgba = hex - .map(v => parseInt(v, 16)) - .concat((parseInt(alpha, 16) / 255).toFixed(1)) - this.rgbaToHSVA(rgba) - } - - rgbaToHSVA(rgba) { - if (isValidRgba(rgba)) { - const [r, g, b, a = "1"] = rgba - let hsv = rgbToHSV([r, g, b]) - this.setHSVA([...hsv, a]) - } - } - - hsvaToHexa() { - const [r, g, b, a] = this.hsvaToRgba() - const hexa = [r, g, b] - .map(v => v.toString(16)) - .concat((a * 255).toFixed(1).toString(16)) - return hexa - } - - hsvaToRgba() { - const { h, s, v, a } = this - let rgb = hsvToRgb([h, s, v]) - return [...rgb, a] - } -} diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils/utils.js b/packages/builder/src/components/userInterface/Colorpicker/utils/utils.js deleted file mode 100644 index 7412c42e27..0000000000 --- a/packages/builder/src/components/userInterface/Colorpicker/utils/utils.js +++ /dev/null @@ -1,108 +0,0 @@ -export const getRgbaValues = rgbaString => - rgbaString.replace(/[a-z\(\)\s]/gi, "").split(",") - -export const getHexaValues = hexString => - hexString.match(/[A-F]{2}|[A-F]\d{1}|\d{2}|\d[A-F]/gi) - -export const isValidRgba = rgba => { - let [r, g, b, a = 1] = rgba - - let isValidLengthRange = rgba.length === 3 || rgba.length === 4 - let isValidColorRange = [r, g, b].every(v => v >= 0 && v <= 255) - let isValidAlphaRange = rgba.length === 3 || (a >= 0 && a <= 1) - - return isValidLengthRange && isValidColorRange && isValidAlphaRange -} - -//Credit : https://github.com/Qix-/color-convert -export const rgbToHSV = rgb => { - let rdif - let gdif - let bdif - let h - let s - - const r = rgb[0] / 255 - const g = rgb[1] / 255 - const b = rgb[2] / 255 - const v = Math.max(r, g, b) - const diff = v - Math.min(r, g, b) - const diffc = function(c) { - return (v - c) / 6 / diff + 1 / 2 - } - - if (diff === 0) { - h = 0 - s = 0 - } else { - s = diff / v - rdif = diffc(r) - gdif = diffc(g) - bdif = diffc(b) - - if (r === v) { - h = bdif - gdif - } else if (g === v) { - h = 1 / 3 + rdif - bdif - } else if (b === v) { - h = 2 / 3 + gdif - rdif - } - - if (h < 0) { - h += 1 - } else if (h > 1) { - h -= 1 - } - } - - const hsvResult = [h * 360, s * 100, v * 100].map(v => v.toFixed(0)) - return hsvResult -} - -//Credit : https://github.com/Qix-/color-convert -export const hsvToRgb = hsv => { - const h = hsv[0] / 60 - const s = hsv[1] / 100 - let v = hsv[2] / 100 - const hi = Math.floor(h) % 6 - - const f = h - Math.floor(h) - const p = 255 * v * (1 - s) - const q = 255 * v * (1 - s * f) - const t = 255 * v * (1 - s * (1 - f)) - v *= 255 - - switch (hi) { - case 0: - return [v, t, p] - case 1: - return [q, v, p] - case 2: - return [p, v, t] - case 3: - return [p, q, v] - case 4: - return [t, p, v] - case 5: - return [v, p, q] - } -} - -//Credit : https://github.com/Qix-/color-convert -export const hsvToHSL = hsv => { - const h = hsv[0] - const s = hsv[1] / 100 - const v = hsv[2] / 100 - const vmin = Math.max(v, 0.01) - let sl - let l - - l = (2 - s) * v - const lmin = (2 - s) * vmin - sl = s * vmin - sl /= lmin <= 1 ? lmin : 2 - lmin - sl = sl || 0 - l /= 2 - - return [h, sl * 100, l * 100] -} From e1ecc3f31b66e524dbbc69576f01aebb18998015 Mon Sep 17 00:00:00 2001 From: Conor_Mack Date: Mon, 1 Jun 2020 23:01:56 +0100 Subject: [PATCH 03/34] Completed Palette and Slider with integration --- .../Colorpicker/Colorpicker.svelte | 44 +++++++++++++++-- .../userInterface/Colorpicker/Palette.svelte | 48 +++++++++++-------- .../userInterface/Colorpicker/Slider.svelte | 26 +++++----- .../userInterface/Colorpicker/drag.js | 1 - .../userInterface/Colorpicker/utils.js | 37 +++++++------- 5 files changed, 99 insertions(+), 57 deletions(-) diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte index db70f3ad64..4ca425bcb0 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte @@ -1,13 +1,49 @@ -
-
+
+
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte index 82e00baa93..13254c29c8 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte @@ -2,35 +2,30 @@ import { onMount, createEventDispatcher } from "svelte"; import dragable from "./drag.js"; + export let value = 1 export let type = "hue"; const dispatch = createEventDispatcher(); let slider; - let dimensions = {}; - let thumbPosition = 0; - - onMount(() => { - if (slider) { - dimensions = slider.getBoundingClientRect(); - } - }); + let sliderWidth = 0; function handleClick(mouseX) { - const { left, width } = dimensions; + const { left } = slider.getBoundingClientRect(); let clickPosition = mouseX - left; - debugger; - if (clickPosition >= 0 && clickPosition <= width) { - thumbPosition = clickPosition; - let percentageClick = thumbPosition / width; + + if (clickPosition >= 0 && clickPosition <= sliderWidth) { + let percentageClick = clickPosition / sliderWidth; let value = type === "hue" - ? Math.round(360 * percentageClick).toString() - : percentageClick.toFixed(2); + ? 360 * percentageClick.toString() + : percentageClick.toString(); dispatch("change", value); } } + $: thumbPosition = type === "hue" ? sliderWidth * (value / 360) : sliderWidth * (value) + $: style = `transform: translateX(${thumbPosition - 6}px);`; @@ -75,6 +70,7 @@
handleClick(event.clientX)} class="color-format-slider" class:hue={type === 'hue'} diff --git a/packages/builder/src/components/userInterface/Colorpicker/drag.js b/packages/builder/src/components/userInterface/Colorpicker/drag.js index eb15c8d4fb..842d157ad2 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/drag.js +++ b/packages/builder/src/components/userInterface/Colorpicker/drag.js @@ -6,7 +6,6 @@ export default function(node) { function handleMouseMove(event) { let mouseX = event.clientX; - console.log(mouseX); node.dispatchEvent( new CustomEvent('drag', { detail: mouseX diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils.js b/packages/builder/src/components/userInterface/Colorpicker/utils.js index 98bb96d259..6c8c8d48ed 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/utils.js +++ b/packages/builder/src/components/userInterface/Colorpicker/utils.js @@ -12,19 +12,19 @@ export const isValidRgba = (rgba) => { return isValidLengthRange && isValidColorRange && isValidAlphaRange; }; -export const determineColorType = (color) => { - let hsva = []; - if (color.startsWith('#')) { - let [ rHex, gHex, bHex, aHex ] = getHexaValues(color); - hsva = hexaToHSVA([ rHex, gHex, bHex ], aHex); - } else if (color.startsWith('rgb')) { - let rgba = getRgbaValues(color); - hsva = rgbaToHSVA(rgba); - } -}; -export const getHSLA = (hsv, a) => { - const [ h, s, l ] = hsvToHSL(hsv); +export const getAndConvertHexa = (color) => { + let [ rHex, gHex, bHex, aHex ] = getHexaValues(color); + return hexaToHSVA([ rHex, gHex, bHex ], aHex); +} + +export const getAndConvertRgba = color => { + let rgba = getRgbaValues(color); + return rgbaToHSVA(rgba); +} + +export const getHSLA = ([hue, sat, val, a]) => { + const [ h, s, l ] = _hsvToHSL([hue, sat, val]); return `hsla(${h}, ${s}, ${l}, ${a})`; }; @@ -36,20 +36,21 @@ export const hexaToHSVA = (hex, alpha = 'FF') => { export const rgbaToHSVA = (rgba) => { if (isValidRgba(rgba)) { const [ r, g, b, a = '1' ] = rgba; - let hsv = rgbToHSV([ r, g, b ]); + let hsv = _rgbToHSV([ r, g, b ]); return [ ...hsv, a ]; } }; -export const hsvaToHexa = () => { - const [ r, g, b, a ] = hsvaToRgba(); +export const hsvaToHexa = (hsva) => { + const [ r, g, b, a ] = hsvaToRgba(hsva); const hexa = [ r, g, b ].map((v) => v.toString(16)).concat((a * 255).toFixed(1).toString(16)); - return hexa; + return `#${hexa.join()}` }; -export const hsvaToRgba = (h, s, v, a) => { +export const hsvaToRgba = ([h, s, v, a]) => { let rgb = _hsvToRgb([ h, s, v ]); - return [ ...rgb, a ]; + let rgba = [ ...rgb, a ]; + return `rgba(${rgba.join(",")})` }; //Credit : https://github.com/Qix-/color-convert From ed1b30d83aa4dbda6df41b84dc19688b16140eec Mon Sep 17 00:00:00 2001 From: Conor_Mack Date: Mon, 8 Jun 2020 21:41:10 +0100 Subject: [PATCH 04/34] Utils update and Jest Tests --- .../Colorpicker/Colorpicker.svelte | 80 +++++++--- .../userInterface/Colorpicker/utils.js | 139 +++++++++++++++--- .../userInterface/Colorpicker/utils.test.js | 90 ++++++++++++ 3 files changed, 264 insertions(+), 45 deletions(-) create mode 100644 packages/builder/src/components/userInterface/Colorpicker/utils.test.js diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte index 4ca425bcb0..015114ded8 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte @@ -1,48 +1,80 @@ @@ -62,7 +94,7 @@ - (h = hue.detail)} /> + setHue(hue.detail)} /> - (a = alpha.detail)} /> + setAlpha(alpha.detail)} />
diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils.js b/packages/builder/src/components/userInterface/Colorpicker/utils.js index 6c8c8d48ed..b46ad6d202 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/utils.js +++ b/packages/builder/src/components/userInterface/Colorpicker/utils.js @@ -1,17 +1,82 @@ -export const getRgbaValues = (rgbaString) => rgbaString.replace(/[a-z()\s]/gi, '').split(','); +export const isValidHex = (str) => /^#(?:[A-F0-9]{3}$|[A-F0-9]{6}$|[A-F0-9]{8})$/gi.test(str) -export const getHexaValues = (hexString) => hexString.match(/[A-F]{2}|[A-F]\d{1}|\d{2}|\d[A-F]/gi); +const getHexaValues = (hexString) => hexString.match(/[A-F0-9]{2}/gi); -export const isValidRgba = (rgba) => { - let [ r, g, b, a = 1 ] = rgba; +export const isValidRgb = (str) => { + const hasValidStructure = /^(?:rgba\(|rgb\()[0-9,.\s]*\)$/gi.test(str); + if(hasValidStructure) { + return testRgbaValues(str.toLowerCase()); + } +} - let isValidLengthRange = rgba.length === 3 || rgba.length === 4; +const findNonNumericChars = /[a-z()%\s]/gi + +export const getNumericValues = (str) => str.replace(findNonNumericChars, '').split(',').map(c => Number(c)); + +export const testRgbaValues = (str) => { + const rgba = getNumericValues(str) + let [ r, g, b, a ] = rgba; + + let isValidLengthRange = (str.startsWith("rgb(") && rgba.length === 3) || (str.startsWith("rgba(") && rgba.length === 4); let isValidColorRange = [ r, g, b ].every((v) => v >= 0 && v <= 255); - let isValidAlphaRange = rgba.length === 3 || (a >= 0 && a <= 1); + let isValidAlphaRange = str.startsWith("rgba(") ? a >= 0 && a <= 1 : true; return isValidLengthRange && isValidColorRange && isValidAlphaRange; }; +export const isValidHsl = (str) => { + const hasValidStructure = /^(?:hsl\(|hsla\()[0-9,.\s]*\)$/gi.test(str) + if(hasValidStructure) { + return testHslaValues(str.toLowerCase()) + } +} + +export const testHslaValues = (str) => { + + const hsla = getNumericValues(str) + const [h, s, l, a] = hsla + + let isValidLengthRange = (str.startsWith("hsl(") && hsla.length === 3) || (str.startsWith("hsla(") && hsla.length === 4); + let isValidColorRange = (h >= 0 && h <= 360) && [s, l].every(v => v >= 0 && v <= 100) + let isValidAlphaRange = str.startsWith("hsla(") ? (a >= 0 && a <= 1) : true + + return isValidLengthRange && isValidColorRange && isValidAlphaRange; +} + +export const getColorFormat = (color) => { + if(typeof color === "string") { + if(isValidHex(color)) { + return 'hex' + }else if(isValidRgb(color)) { + return 'rgb' + }else if(isValidHsl(color)) { + return 'hsl' + } + } +} + +export const convertToHSVA = (value, format) => { + switch(format) { + case "hex": + return getAndConvertHexa(value) + case "rgb": + return getAndConvertRgba(value) + case "hsl": + return getAndConvertHsla(value) + } +} + +export const convertHsvaToFormat = (hsva, format) => { + switch(format) { + case "hex": + return hsvaToHexa(hsva, true) + case "rgb": + return hsvaToRgba(hsva, true) + case "hsl": + return hsvaToHsla(hsva, true) + } +} + export const getAndConvertHexa = (color) => { let [ rHex, gHex, bHex, aHex ] = getHexaValues(color); @@ -19,40 +84,71 @@ export const getAndConvertHexa = (color) => { } export const getAndConvertRgba = color => { - let rgba = getRgbaValues(color); + let rgba = getNumericValues(color); return rgbaToHSVA(rgba); } +export const getAndConvertHsla = color => { + let hsla = getNumericValues(color); + return hslaToHSVA(hsla) +} + export const getHSLA = ([hue, sat, val, a]) => { const [ h, s, l ] = _hsvToHSL([hue, sat, val]); return `hsla(${h}, ${s}, ${l}, ${a})`; }; export const hexaToHSVA = (hex, alpha = 'FF') => { - const rgba = hex.map((v) => parseInt(v, 16)).concat((parseInt(alpha, 16) / 255).toFixed(1)); + const rgba = hex.map((v) => parseInt(v, 16)).concat(Number((parseInt(alpha, 16) / 255).toFixed(2))); return rgbaToHSVA(rgba); }; export const rgbaToHSVA = (rgba) => { - if (isValidRgba(rgba)) { - const [ r, g, b, a = '1' ] = rgba; - let hsv = _rgbToHSV([ r, g, b ]); - return [ ...hsv, a ]; - } + const [ r, g, b, a = 1 ] = rgba; + let hsv = _rgbToHSV([ r, g, b ]); + return [ ...hsv, a ]; }; -export const hsvaToHexa = (hsva) => { +export const hslaToHSVA = ([h, s, l, a = 1]) => { + let hsv = _hslToHSV([h, s, l]) + return [...hsv, a] +} + +export const hsvaToHexa = (hsva, asString = false) => { const [ r, g, b, a ] = hsvaToRgba(hsva); - const hexa = [ r, g, b ].map((v) => v.toString(16)).concat((a * 255).toFixed(1).toString(16)); - return `#${hexa.join()}` + + const hexa = [ r, g, b ].map((v) => Math.round(v).toString(16)).concat(Math.round((a * 255)).toString(16)); + return asString ? `#${hexa.join('')}` : hexa }; -export const hsvaToRgba = ([h, s, v, a]) => { - let rgb = _hsvToRgb([ h, s, v ]); +export const hsvaToRgba = ([h, s, v, a], asString = false) => { + let rgb = _hsvToRgb([ h, s, v ]).map(x => Math.round(x)); let rgba = [ ...rgb, a ]; - return `rgba(${rgba.join(",")})` + return asString ? `rgba(${rgba.join(",")})` : rgba }; +export const hsvaToHsla = ([h, s, v, a = 1], asString = false) => { + let hsl = _hsvToHSL([h, s, v]) + let hsla = [...hsl, a] + return asString ? `hsla(${hsla.join(",")})` : hsla +} + +export const _hslToHSV = (hsl) => { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +} + //Credit : https://github.com/Qix-/color-convert export const _rgbToHSV = (rgb) => { let rdif; @@ -94,7 +190,7 @@ export const _rgbToHSV = (rgb) => { } } - const hsvResult = [ h * 360, s * 100, v * 100 ].map((v) => v.toFixed(0)); + const hsvResult = [ h * 360, s * 100, v * 100 ].map((v) => Math.round(v)); return hsvResult; }; @@ -129,6 +225,7 @@ export const _hsvToRgb = (hsv) => { //Credit : https://github.com/Qix-/color-convert export const _hsvToHSL = (hsv) => { + const h = hsv[0]; const s = hsv[1] / 100; const v = hsv[2] / 100; @@ -143,5 +240,5 @@ export const _hsvToHSL = (hsv) => { sl = sl || 0; l /= 2; - return [ h, sl * 100, l * 100 ]; + return [ h, Number((sl * 100).toFixed(1)), Number((l * 100).toFixed(1)) ]; }; diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils.test.js b/packages/builder/src/components/userInterface/Colorpicker/utils.test.js new file mode 100644 index 0000000000..0354468b75 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/utils.test.js @@ -0,0 +1,90 @@ +import {getColorFormat, convertToHSVA, convertHsvaToFormat} from "./utils" + +describe('convertToHSVA - convert to hsva from format', () => { + test("convert from hexa", () => { + expect(convertToHSVA("#f222d382", "hex")).toEqual([309, 86, 95, 0.51]) + }) + + test("convert from hex", () => { + expect(convertToHSVA("#f222d3", "hex")).toEqual([309, 86, 95, 1]) + }) + + test("convert from rgba", () => { + expect(convertToHSVA("rgba(242, 34, 211, 1)", "rgb")).toEqual([309, 86, 95, 1]) + }) + + test("convert from rgb", () => { + expect(convertToHSVA("rgb(150, 80, 255)", "rgb")).toEqual([264, 69, 100, 1]) + }) + + test("convert from from hsl", () => { + expect(convertToHSVA("hsl(264, 100%, 65.7%)", "hsl")).toEqual([264, 68.6, 100, 1]) + }) + + test("convert from from hsla", () => { + expect(convertToHSVA("hsla(264, 100%, 65.7%, 0.51)", "hsl")).toEqual([264, 68.6, 100, 0.51]) + }) + +}) + +describe('convertHsvaToFormat - convert from hsva to format', () => { + test('Convert to hexa', () => { + expect(convertHsvaToFormat([264, 68.63, 100, 0.5], "hex")).toBe("#9650ff80") + }) + + test('Convert to rgba', () => { + expect(convertHsvaToFormat([264, 68.63, 100, 0.75], "rgb")).toBe("rgba(150,80,255,0.75)") + }) + + test('Convert to hsla', () => { + expect(convertHsvaToFormat([264, 68.63, 100, 1], "hsl")).toBe("hsla(264,100,65.7,1)") + }) +}) + + +describe('Get Color Format', () => { + test("Testing valid hex string", () => { + expect(getColorFormat("#FFF")).toBe("hex") + }) + + test("Testing invalid hex string", () => { + expect(getColorFormat("#FFZ")).toBeUndefined() + }) + + test("Testing valid hex with alpha", () => { + expect(getColorFormat("#FF00BB80")).toBe("hex") + }) + + test("Test valid rgb value", () => { + expect(getColorFormat("RGB(255, 20, 50)")).toBe("rgb") + }) + + test("Testing invalid rgb value", () => { + expect(getColorFormat("rgb(255, 0)")).toBeUndefined() + }) + + test("Testing rgb value with alpha", () => { + expect(getColorFormat("rgba(255, 0, 50, 0.5)")).toBe("rgb") + }) + + test("Testing rgb value with incorrectly provided alpha", () => { + expect(getColorFormat("rgb(255, 0, 50, 0.5)")).toBeUndefined() + }) + + test("Testing invalid hsl value", () => { + expect(getColorFormat("hsla(255, 0)")).toBeUndefined() + }) + + test("Testing hsla value with alpha", () => { + expect(getColorFormat("hsla(150, 60, 50, 0.5)")).toBe("hsl") + }) + + test("Testing hsl value with incorrectly provided alpha", () => { + expect(getColorFormat("hsl(150, 0, 50, 0.5)")).toBeUndefined() + }) + + test("Testing out of bounds hsl", () => { + expect(getColorFormat("hsl(375, 0, 50)")).toBeUndefined() + }) +}) + From f8cfc8e7d7f347defe38ec3e0b0094e2d6c5d82f Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 11 Jun 2020 14:35:45 +0100 Subject: [PATCH 05/34] adding record models for brevity --- packages/server/package.json | 2 +- packages/server/src/api/controllers/record.js | 11 +++++- packages/server/src/api/index.js | 4 ++ packages/server/src/api/routes/index.js | 2 + packages/server/src/api/routes/model.js | 38 +------------------ packages/server/src/api/routes/record.js | 36 ++++++++++++++++++ .../server/src/api/routes/tests/model.spec.js | 1 - .../src/api/routes/tests/record.spec.js | 24 ++++++++++++ 8 files changed, 78 insertions(+), 40 deletions(-) create mode 100644 packages/server/src/api/routes/record.js diff --git a/packages/server/package.json b/packages/server/package.json index 0888ef2ae4..49a5626f6f 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -25,7 +25,7 @@ "scripts": { "test": "jest routes --runInBand", "test:integration": "jest workflow --runInBand", - "test:watch": "jest -w", + "test:watch": "jest --watch", "initialise": "node ../cli/bin/budi init -b local -q", "budi": "node ../cli/bin/budi", "dev:builder": "nodemon ../cli/bin/budi run", diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index 5fab413f04..cf8eb27606 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -61,7 +61,7 @@ exports.fetchView = async function(ctx) { ctx.body = response.rows.map(row => row.doc) } -exports.fetchModel = async function(ctx) { +exports.fetchModelRecords = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) const response = await db.query(`database/all_${ctx.params.modelId}`, { include_docs: true, @@ -69,6 +69,15 @@ exports.fetchModel = async function(ctx) { ctx.body = response.rows.map(row => row.doc) } +exports.search = async function(ctx) { + const db = new CouchDB(ctx.params.instanceId) + const response = await db.allDocs({ + include_docs: true, + ...ctx.request.body, + }) + ctx.body = response.rows.map(row => row.doc) +} + exports.find = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) const record = await db.get(ctx.params.recordId) diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index 990714fdc7..e6143d6725 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -10,6 +10,7 @@ const { instanceRoutes, clientRoutes, applicationRoutes, + recordRoutes, modelRoutes, viewRoutes, staticRoutes, @@ -69,6 +70,9 @@ router.use(viewRoutes.allowedMethods()) router.use(modelRoutes.routes()) router.use(modelRoutes.allowedMethods()) +router.use(recordRoutes.routes()) +router.use(recordRoutes.allowedMethods()) + router.use(userRoutes.routes()) router.use(userRoutes.allowedMethods()) diff --git a/packages/server/src/api/routes/index.js b/packages/server/src/api/routes/index.js index c515d5f437..b50fee788a 100644 --- a/packages/server/src/api/routes/index.js +++ b/packages/server/src/api/routes/index.js @@ -5,6 +5,7 @@ const instanceRoutes = require("./instance") const clientRoutes = require("./client") const applicationRoutes = require("./application") const modelRoutes = require("./model") +const recordRoutes = require("./record") const viewRoutes = require("./view") const staticRoutes = require("./static") const componentRoutes = require("./component") @@ -18,6 +19,7 @@ module.exports = { instanceRoutes, clientRoutes, applicationRoutes, + recordRoutes, modelRoutes, viewRoutes, staticRoutes, diff --git a/packages/server/src/api/routes/model.js b/packages/server/src/api/routes/model.js index 388f4618bd..f1ec46dbe5 100644 --- a/packages/server/src/api/routes/model.js +++ b/packages/server/src/api/routes/model.js @@ -1,46 +1,10 @@ const Router = require("@koa/router") const modelController = require("../controllers/model") -const recordController = require("../controllers/record") const authorized = require("../../middleware/authorized") -const { - READ_MODEL, - WRITE_MODEL, - BUILDER, -} = require("../../utilities/accessLevels") +const { BUILDER } = require("../../utilities/accessLevels") const router = Router() -// records - -router - .get( - "/api/:instanceId/:modelId/records", - authorized(READ_MODEL, ctx => ctx.params.modelId), - recordController.fetchModel - ) - .get( - "/api/:instanceId/:modelId/records/:recordId", - authorized(READ_MODEL, ctx => ctx.params.modelId), - recordController.find - ) - .post( - "/api/:instanceId/:modelId/records", - authorized(WRITE_MODEL, ctx => ctx.params.modelId), - recordController.save - ) - .post( - "/api/:instanceId/:modelId/records/validate", - authorized(WRITE_MODEL, ctx => ctx.params.modelId), - recordController.validate - ) - .delete( - "/api/:instanceId/:modelId/records/:recordId/:revId", - authorized(WRITE_MODEL, ctx => ctx.params.modelId), - recordController.destroy - ) - -// models - router .get("/api/:instanceId/models", authorized(BUILDER), modelController.fetch) .get("/api/:instanceId/models/:id", authorized(BUILDER), modelController.find) diff --git a/packages/server/src/api/routes/record.js b/packages/server/src/api/routes/record.js new file mode 100644 index 0000000000..d555d3d8c8 --- /dev/null +++ b/packages/server/src/api/routes/record.js @@ -0,0 +1,36 @@ +const Router = require("@koa/router") +const recordController = require("../controllers/record") +const authorized = require("../../middleware/authorized") +const { READ_MODEL, WRITE_MODEL } = require("../../utilities/accessLevels") + +const router = Router() + +router + .get( + "/api/:instanceId/:modelId/records", + authorized(READ_MODEL, ctx => ctx.params.modelId), + recordController.fetchModelRecords + ) + .get( + "/api/:instanceId/:modelId/records/:recordId", + authorized(READ_MODEL, ctx => ctx.params.modelId), + recordController.find + ) + .post("/api/:instanceId/records/search", recordController.search) + .post( + "/api/:instanceId/:modelId/records", + authorized(WRITE_MODEL, ctx => ctx.params.modelId), + recordController.save + ) + .post( + "/api/:instanceId/:modelId/records/validate", + authorized(WRITE_MODEL, ctx => ctx.params.modelId), + recordController.validate + ) + .delete( + "/api/:instanceId/:modelId/records/:recordId/:revId", + authorized(WRITE_MODEL, ctx => ctx.params.modelId), + recordController.destroy + ) + +module.exports = router diff --git a/packages/server/src/api/routes/tests/model.spec.js b/packages/server/src/api/routes/tests/model.spec.js index 65a44b677a..df3b7d8b52 100644 --- a/packages/server/src/api/routes/tests/model.spec.js +++ b/packages/server/src/api/routes/tests/model.spec.js @@ -97,7 +97,6 @@ describe("/models", () => { instanceId: instance._id, }) }) - }); describe("destroy", () => { diff --git a/packages/server/src/api/routes/tests/record.spec.js b/packages/server/src/api/routes/tests/record.spec.js index 2c8c542715..22ac67ecdc 100644 --- a/packages/server/src/api/routes/tests/record.spec.js +++ b/packages/server/src/api/routes/tests/record.spec.js @@ -110,6 +110,30 @@ describe("/records", () => { expect(res.body.find(r => r.name === record.name)).toBeDefined() }) + it("lists records when queried by their ID", async () => { + const newRecord = { + modelId: model._id, + name: "Second Contact", + status: "new" + } + const record = await createRecord() + const secondRecord = await createRecord(newRecord) + + const recordIds = [record.body._id, secondRecord.body._id] + + const res = await request + .post(`/api/${instance._id}/records/search`) + .set(defaultHeaders) + .send({ + keys: recordIds + }) + .expect('Content-Type', /json/) + .expect(200) + + expect(res.body.length).toBe(2) + expect(res.body.map(response => response._id)).toEqual(expect.arrayContaining(recordIds)) + }) + it("load should return 404 when record does not exist", async () => { await createRecord() await request From 3900b216e999cc381e02d5b8941ed496848f0697 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 11 Jun 2020 17:24:09 +0100 Subject: [PATCH 06/34] remove other link fields when you delete a model --- packages/server/src/api/controllers/model.js | 32 ++++++++++++++- .../src/api/routes/tests/couchTestUtils.js | 4 ++ .../server/src/api/routes/tests/model.spec.js | 40 ++++++++++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index 9d06c7a413..c35a0ddd49 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -27,6 +27,23 @@ exports.create = async function(ctx) { const result = await db.post(newModel) newModel._rev = result.rev + const { schema } = ctx.request.body + for (let key in schema) { + // model has a linked record + if (schema[key].type === "link") { + // create the link field in the other model + const linkedModel = await db.get(schema[key].modelId); + linkedModel.schema[newModel.name] = { + type: "link", + modelId: newModel._id, + constraints: { + type: "array" + } + } + await db.put(linkedModel); + } + } + const designDoc = await db.get("_design/database") designDoc.views = { ...designDoc.views, @@ -50,7 +67,9 @@ exports.update = async function() {} exports.destroy = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) - await db.remove(ctx.params.modelId, ctx.params.revId) + const modelToDelete = await db.get(ctx.params.modelId); + + await db.remove(modelToDelete) const modelViewId = `all_${ctx.params.modelId}` // Delete all records for that model @@ -59,6 +78,17 @@ exports.destroy = async function(ctx) { records.rows.map(record => ({ id: record.id, _deleted: true })) ) + // Delete linked record fields in dependent models + for (let key in modelToDelete.schema) { + const { type, modelId } = modelToDelete.schema[key]; + if (type === "link") { + const linkedModel = await db.get(modelId); + delete linkedModel.schema[modelToDelete.name] + await db.put(linkedModel) + } + } + + // delete the "all" view const designDoc = await db.get("_design/database") delete designDoc.views[modelViewId] diff --git a/packages/server/src/api/routes/tests/couchTestUtils.js b/packages/server/src/api/routes/tests/couchTestUtils.js index 6029e080cc..495b841b10 100644 --- a/packages/server/src/api/routes/tests/couchTestUtils.js +++ b/packages/server/src/api/routes/tests/couchTestUtils.js @@ -253,3 +253,7 @@ exports.insertDocument = async (databaseId, document) => { exports.destroyDocument = async (databaseId, documentId) => { return await new CouchDB(databaseId).destroy(documentId) } + +exports.getDocument = async (databaseId, documentId) => { + return await new CouchDB(databaseId).get(documentId) +} diff --git a/packages/server/src/api/routes/tests/model.spec.js b/packages/server/src/api/routes/tests/model.spec.js index df3b7d8b52..1fb16beb8b 100644 --- a/packages/server/src/api/routes/tests/model.spec.js +++ b/packages/server/src/api/routes/tests/model.spec.js @@ -3,9 +3,10 @@ const { createModel, supertest, createClientDatabase, - createApplication , + createApplication, defaultHeaders, - builderEndpointShouldBlockNormalUsers + builderEndpointShouldBlockNormalUsers, + getDocument } = require("./couchTestUtils") describe("/models", () => { @@ -119,6 +120,41 @@ describe("/models", () => { }); }) + it("deletes linked references to the model after deletion", async done => { + const linkedModel = await createModel(request, instance._id, { + name: "LinkedModel", + type: "model", + key: "name", + schema: { + name: { + type: "text", + constraints: { + type: "string", + }, + }, + TestModel: { + type: "link", + modelId: testModel._id, + constraints: { + type: "array" + } + } + }, + }) + + request + .delete(`/api/${instance._id}/models/${testModel._id}/${testModel._rev}`) + .set(defaultHeaders) + .expect('Content-Type', /json/) + .expect(200) + .end(async (_, res) => { + expect(res.res.statusMessage).toEqual(`Model ${testModel._id} deleted.`); + const dependentModel = await getDocument(instance._id, linkedModel._id) + expect(dependentModel.schema.TestModel).not.toBeDefined(); + done(); + }); + }) + it("should apply authorization to endpoint", async () => { await builderEndpointShouldBlockNormalUsers({ request, From 2b312d4c1f8ca1dfb61341c5790c9c85f26a2e5d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 11 Jun 2020 17:28:19 +0100 Subject: [PATCH 07/34] lint :sparkles: --- packages/server/src/api/controllers/model.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index c35a0ddd49..f1e3f51747 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -32,15 +32,15 @@ exports.create = async function(ctx) { // model has a linked record if (schema[key].type === "link") { // create the link field in the other model - const linkedModel = await db.get(schema[key].modelId); + const linkedModel = await db.get(schema[key].modelId) linkedModel.schema[newModel.name] = { type: "link", modelId: newModel._id, constraints: { - type: "array" - } + type: "array", + }, } - await db.put(linkedModel); + await db.put(linkedModel) } } @@ -67,7 +67,7 @@ exports.update = async function() {} exports.destroy = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) - const modelToDelete = await db.get(ctx.params.modelId); + const modelToDelete = await db.get(ctx.params.modelId) await db.remove(modelToDelete) const modelViewId = `all_${ctx.params.modelId}` @@ -80,15 +80,14 @@ exports.destroy = async function(ctx) { // Delete linked record fields in dependent models for (let key in modelToDelete.schema) { - const { type, modelId } = modelToDelete.schema[key]; + const { type, modelId } = modelToDelete.schema[key] if (type === "link") { - const linkedModel = await db.get(modelId); + const linkedModel = await db.get(modelId) delete linkedModel.schema[modelToDelete.name] await db.put(linkedModel) } } - // delete the "all" view const designDoc = await db.get("_design/database") delete designDoc.views[modelViewId] From 4ed4866bca75c020108dab5cab200de7027d6340 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 11 Jun 2020 18:11:56 +0100 Subject: [PATCH 08/34] update _rev for deleted test model --- packages/server/src/api/controllers/model.js | 1 + packages/server/src/api/routes/tests/model.spec.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index f1e3f51747..650342b33c 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -70,6 +70,7 @@ exports.destroy = async function(ctx) { const modelToDelete = await db.get(ctx.params.modelId) await db.remove(modelToDelete) + const modelViewId = `all_${ctx.params.modelId}` // Delete all records for that model diff --git a/packages/server/src/api/routes/tests/model.spec.js b/packages/server/src/api/routes/tests/model.spec.js index 1fb16beb8b..7134245fb3 100644 --- a/packages/server/src/api/routes/tests/model.spec.js +++ b/packages/server/src/api/routes/tests/model.spec.js @@ -108,7 +108,11 @@ describe("/models", () => { testModel = await createModel(request, instance._id, testModel) }); - it("returns a success response when a model is deleted.", done => { + afterEach(() => { + delete testModel._rev + }) + + it("returns a success response when a model is deleted.", async done => { request .delete(`/api/${instance._id}/models/${testModel._id}/${testModel._rev}`) .set(defaultHeaders) From 9830725ac1cf325dc112023a6c6f6e08b9ae0b71 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 11 Jun 2020 20:18:59 +0100 Subject: [PATCH 09/34] embed component, rename main and login to public and private --- .../src/components/userInterface/PagesList.svelte | 4 ++-- .../userInterface/temporaryPanelStructure.js | 12 ++++++++++++ packages/standard-components/components.json | 7 +++++++ packages/standard-components/src/Embed.svelte | 5 +++++ packages/standard-components/src/index.js | 1 + 5 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 packages/standard-components/src/Embed.svelte diff --git a/packages/builder/src/components/userInterface/PagesList.svelte b/packages/builder/src/components/userInterface/PagesList.svelte index 4a87c4ac8a..5a78ef7121 100644 --- a/packages/builder/src/components/userInterface/PagesList.svelte +++ b/packages/builder/src/components/userInterface/PagesList.svelte @@ -9,11 +9,11 @@ const pages = [ { - title: "Main", + title: "Private", id: "main", }, { - title: "Login", + title: "Public", id: "unauthenticated", }, ] diff --git a/packages/builder/src/components/userInterface/temporaryPanelStructure.js b/packages/builder/src/components/userInterface/temporaryPanelStructure.js index afd3a06694..7315e09736 100644 --- a/packages/builder/src/components/userInterface/temporaryPanelStructure.js +++ b/packages/builder/src/components/userInterface/temporaryPanelStructure.js @@ -11,6 +11,18 @@ export default { name: "Basic", isCategory: true, children: [ + { + _component: "@budibase/standard-components/embed", + icon: "ri-code-line", + name: "Embed", + description: "Embed content from 3rd party sources", + properties: { + design: { + ...all, + }, + settings: [{ label: "Embed", key: "embed", control: Input }], + }, + }, { _component: "@budibase/standard-components/container", name: "Container", diff --git a/packages/standard-components/components.json b/packages/standard-components/components.json index a562650b85..c4c0246672 100644 --- a/packages/standard-components/components.json +++ b/packages/standard-components/components.json @@ -6,6 +6,13 @@ "component": "button" } }, + "embed": { + "name": "Embed", + "description": "Embed stuff", + "props": { + "embed": "string" + } + }, "Navigation": { "name": "Navigation", "description": "A basic header navigation component", diff --git a/packages/standard-components/src/Embed.svelte b/packages/standard-components/src/Embed.svelte new file mode 100644 index 0000000000..2640864681 --- /dev/null +++ b/packages/standard-components/src/Embed.svelte @@ -0,0 +1,5 @@ + + +{@html embed} diff --git a/packages/standard-components/src/index.js b/packages/standard-components/src/index.js index 2284ab1fcb..24342066e8 100644 --- a/packages/standard-components/src/index.js +++ b/packages/standard-components/src/index.js @@ -21,3 +21,4 @@ export { default as datalist } from "./DataList.svelte" export { default as list } from "./List.svelte" export { default as datasearch } from "./DataSearch.svelte" export { default as datamap } from "./DataMap.svelte" +export { default as embed } from "./Embed.svelte" From ebc47a9b1b6a227d8912c24cd7c26afaac825367 Mon Sep 17 00:00:00 2001 From: Conor_Mack Date: Fri, 12 Jun 2020 10:48:20 +0100 Subject: [PATCH 10/34] Fully functional Colorpicker with Preview --- .../Colorpicker/ButtonGroup.svelte | 27 ++ .../Colorpicker/Colorpicker.svelte | 142 ++++-- .../Colorpicker/Colorpreview.svelte | 78 ++++ .../Colorpicker/FlatButton.svelte | 26 ++ .../userInterface/Colorpicker/Input.svelte | 28 ++ .../userInterface/Colorpicker/Palette.svelte | 1 + .../userInterface/Colorpicker/Slider.svelte | 22 +- .../userInterface/Colorpicker/helpers.js | 14 + .../userInterface/Colorpicker/index.js | 5 +- .../userInterface/Colorpicker/utils.js | 426 +++++++++--------- 10 files changed, 510 insertions(+), 259 deletions(-) create mode 100644 packages/builder/src/components/userInterface/Colorpicker/ButtonGroup.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/Input.svelte create mode 100644 packages/builder/src/components/userInterface/Colorpicker/helpers.js diff --git a/packages/builder/src/components/userInterface/Colorpicker/ButtonGroup.svelte b/packages/builder/src/components/userInterface/Colorpicker/ButtonGroup.svelte new file mode 100644 index 0000000000..f9c402ac81 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/ButtonGroup.svelte @@ -0,0 +1,27 @@ + + + + +
+ {#each colorFormats as text} + onclick(text)} /> + {/each} +
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte index 015114ded8..8ec53d9b86 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte @@ -1,10 +1,17 @@ @@ -94,7 +125,24 @@ - setHue(hue.detail)} /> +
+
+
+
+
+
+ setHue(hue.detail)} /> + setAlpha(alpha.detail)} /> +
+
+ +
+ + handleColorInput(event.target.value)} /> +
+
- setAlpha(alpha.detail)} />
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte new file mode 100644 index 0000000000..329d4e4adc --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte @@ -0,0 +1,78 @@ + + +
+
+ {#if open} +
+ +
+ {/if} +
+{#if open} +
open = false} class="overlay">
+{/if} + + \ No newline at end of file diff --git a/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte b/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte new file mode 100644 index 0000000000..af1ea5e945 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte @@ -0,0 +1,26 @@ + + + + +
{text}
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Input.svelte b/packages/builder/src/components/userInterface/Colorpicker/Input.svelte new file mode 100644 index 0000000000..04966c1f30 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/Input.svelte @@ -0,0 +1,28 @@ + + + + +
+ +
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte index 5f344e74a7..01a614124c 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte @@ -42,6 +42,7 @@ width: 100%; height: 175px; cursor: crosshair; + overflow: hidden; } .picker { diff --git a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte index 13254c29c8..ec8d99248d 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte @@ -2,7 +2,7 @@ import { onMount, createEventDispatcher } from "svelte"; import dragable from "./drag.js"; - export let value = 1 + export let value = 1; export let type = "hue"; const dispatch = createEventDispatcher(); @@ -11,20 +11,22 @@ let sliderWidth = 0; function handleClick(mouseX) { - const { left } = slider.getBoundingClientRect(); + const { left, width } = slider.getBoundingClientRect(); let clickPosition = mouseX - left; + + let percentageClick = (clickPosition / sliderWidth).toFixed(2) - if (clickPosition >= 0 && clickPosition <= sliderWidth) { - let percentageClick = clickPosition / sliderWidth; + if (percentageClick >= 0 && percentageClick <= 1) { let value = type === "hue" - ? 360 * percentageClick.toString() - : percentageClick.toString(); + ? 360 * percentageClick + : percentageClick; dispatch("change", value); } } - $: thumbPosition = type === "hue" ? sliderWidth * (value / 360) : sliderWidth * (value) + $: thumbPosition = + type === "hue" ? sliderWidth * (value / 360) : sliderWidth * value; $: style = `transform: translateX(${thumbPosition - 6}px);`; @@ -34,10 +36,11 @@ position: relative; align-self: center; height: 8px; - width: 220px; + width: 185px; border-radius: 10px; margin: 10px 0px; border: 1px solid #e8e8ef; + cursor: pointer; } .hue { @@ -62,9 +65,10 @@ bottom: -3px; height: 12px; width: 12px; - border: 1px solid black; + border: 1px solid #777676; border-radius: 50%; background-color: #ffffff; + cursor:grab; } diff --git a/packages/builder/src/components/userInterface/Colorpicker/helpers.js b/packages/builder/src/components/userInterface/Colorpicker/helpers.js new file mode 100644 index 0000000000..69f94bf208 --- /dev/null +++ b/packages/builder/src/components/userInterface/Colorpicker/helpers.js @@ -0,0 +1,14 @@ +export const buildStyle = styles => { + let str = "" + for (let s in styles) { + if (styles[s]) { + let key = convertCamel(s) + str += `${key}: ${styles[s]}; ` + } + } + return str + } + + export const convertCamel = str => { + return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`) + } \ No newline at end of file diff --git a/packages/builder/src/components/userInterface/Colorpicker/index.js b/packages/builder/src/components/userInterface/Colorpicker/index.js index ad8187a09b..b497601edf 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/index.js +++ b/packages/builder/src/components/userInterface/Colorpicker/index.js @@ -1,2 +1,3 @@ -import Colorpicker from './Colorpicker.svelte'; -export default Colorpicker; +import Colorpreview from './Colorpreview.svelte'; + +export default Colorpreview; diff --git a/packages/builder/src/components/userInterface/Colorpicker/utils.js b/packages/builder/src/components/userInterface/Colorpicker/utils.js index b46ad6d202..518e94ec9f 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/utils.js +++ b/packages/builder/src/components/userInterface/Colorpicker/utils.js @@ -1,244 +1,268 @@ -export const isValidHex = (str) => /^#(?:[A-F0-9]{3}$|[A-F0-9]{6}$|[A-F0-9]{8})$/gi.test(str) +export const isValidHex = str => + /^#(?:[A-F0-9]{3}$|[A-F0-9]{4}$|[A-F0-9]{6}$|[A-F0-9]{8})$/gi.test(str); -const getHexaValues = (hexString) => hexString.match(/[A-F0-9]{2}/gi); - -export const isValidRgb = (str) => { - const hasValidStructure = /^(?:rgba\(|rgb\()[0-9,.\s]*\)$/gi.test(str); - if(hasValidStructure) { - return testRgbaValues(str.toLowerCase()); - } -} - -const findNonNumericChars = /[a-z()%\s]/gi - -export const getNumericValues = (str) => str.replace(findNonNumericChars, '').split(',').map(c => Number(c)); - -export const testRgbaValues = (str) => { - const rgba = getNumericValues(str) - let [ r, g, b, a ] = rgba; - - let isValidLengthRange = (str.startsWith("rgb(") && rgba.length === 3) || (str.startsWith("rgba(") && rgba.length === 4); - let isValidColorRange = [ r, g, b ].every((v) => v >= 0 && v <= 255); - let isValidAlphaRange = str.startsWith("rgba(") ? a >= 0 && a <= 1 : true; - - return isValidLengthRange && isValidColorRange && isValidAlphaRange; +const getHexaValues = hexString => { + if (hexString.length <= 5) { + let hexArr = hexString.match(/[A-F0-9]/gi); + let t = hexArr.map(c => (c += c)); + return t; + } else { + return hexString.match(/[A-F0-9]{2}/gi); + } }; -export const isValidHsl = (str) => { - const hasValidStructure = /^(?:hsl\(|hsla\()[0-9,.\s]*\)$/gi.test(str) - if(hasValidStructure) { - return testHslaValues(str.toLowerCase()) - } -} +export const isValidRgb = str => { + const hasValidStructure = /^(?:rgba\(|rgb\()(?:[0-9,\s]|\.(?=\d))*\)$/gi.test(str); + if (hasValidStructure) { + return testRgbaValues(str.toLowerCase()); + } +}; -export const testHslaValues = (str) => { +const findNonNumericChars = /[a-z()\s]/gi; - const hsla = getNumericValues(str) - const [h, s, l, a] = hsla +export const getNumericValues = str => + str + .replace(findNonNumericChars, "") + .split(",") + .map(v => v !== "" ? v : undefined); - let isValidLengthRange = (str.startsWith("hsl(") && hsla.length === 3) || (str.startsWith("hsla(") && hsla.length === 4); - let isValidColorRange = (h >= 0 && h <= 360) && [s, l].every(v => v >= 0 && v <= 100) - let isValidAlphaRange = str.startsWith("hsla(") ? (a >= 0 && a <= 1) : true +export const testRgbaValues = str => { + const rgba = getNumericValues(str); + const [r, g, b, a] = rgba; + + let isValidLengthRange = + (str.startsWith("rgb(") && rgba.length === 3) || + (str.startsWith("rgba(") && rgba.length === 4); + let isValidColorRange = [r, g, b].every(v => v >= 0 && v <= 255); + let isValidAlphaRange = str.startsWith("rgba(") ? `${a}`.length <= 4 && a >= 0 && a <= 1 : true; - return isValidLengthRange && isValidColorRange && isValidAlphaRange; -} + return isValidLengthRange && isValidColorRange && isValidAlphaRange; +}; -export const getColorFormat = (color) => { - if(typeof color === "string") { - if(isValidHex(color)) { - return 'hex' - }else if(isValidRgb(color)) { - return 'rgb' - }else if(isValidHsl(color)) { - return 'hsl' - } - } -} +export const isValidHsl = str => { + const hasValidStructure = /^(?:hsl\(|hsla\()(?:[0-9,%\s]|\.(?=\d))*\)$/gi.test(str); + if (hasValidStructure) { + return testHslaValues(str.toLowerCase()); + } +}; + +export const testHslaValues = str => { + const hsla = getNumericValues(str); + const [h, s, l, a] = hsla; + const isUndefined = [h,s,l].some(v => v === undefined) + + if(isUndefined) return false; + + let isValidLengthRange = + (str.startsWith("hsl(") && hsla.length === 3) || + (str.startsWith("hsla(") && hsla.length === 4); + let isValidHue = h >= 0 && h <= 360 + let isValidSatLum = [s, l].every(v => v.endsWith('%') && parseInt(v) >= 0 && parseInt(v) <= 100 ) + let isValidAlphaRange = str.startsWith("hsla(") ? `${a}`.length <= 4 && a >= 0 && a <= 1 : true; + + return isValidLengthRange && isValidHue && isValidSatLum && isValidAlphaRange; +}; + +export const getColorFormat = color => { + if (typeof color === "string") { + if (isValidHex(color)) { + return "hex"; + } else if (isValidRgb(color)) { + return "rgb"; + } else if (isValidHsl(color)) { + return "hsl"; + } + } +}; export const convertToHSVA = (value, format) => { - switch(format) { - case "hex": - return getAndConvertHexa(value) - case "rgb": - return getAndConvertRgba(value) - case "hsl": - return getAndConvertHsla(value) - } -} + switch (format) { + case "hex": + return getAndConvertHexa(value); + case "rgb": + return getAndConvertRgba(value); + case "hsl": + return getAndConvertHsla(value); + } +}; export const convertHsvaToFormat = (hsva, format) => { - switch(format) { - case "hex": - return hsvaToHexa(hsva, true) - case "rgb": - return hsvaToRgba(hsva, true) - case "hsl": - return hsvaToHsla(hsva, true) - } -} + switch (format) { + case "hex": + return hsvaToHexa(hsva, true); + case "rgb": + return hsvaToRgba(hsva, true); + case "hsl": + return hsvaToHsla(hsva); + } +}; - -export const getAndConvertHexa = (color) => { - let [ rHex, gHex, bHex, aHex ] = getHexaValues(color); - return hexaToHSVA([ rHex, gHex, bHex ], aHex); -} +export const getAndConvertHexa = color => { + let [rHex, gHex, bHex, aHex] = getHexaValues(color); + return hexaToHSVA([rHex, gHex, bHex], aHex); +}; export const getAndConvertRgba = color => { - let rgba = getNumericValues(color); - return rgbaToHSVA(rgba); -} + let rgba = getNumericValues(color); + return rgbaToHSVA(rgba); +}; export const getAndConvertHsla = color => { - let hsla = getNumericValues(color); - return hslaToHSVA(hsla) -} - -export const getHSLA = ([hue, sat, val, a]) => { - const [ h, s, l ] = _hsvToHSL([hue, sat, val]); - return `hsla(${h}, ${s}, ${l}, ${a})`; + let hsla = getNumericValues(color); + return hslaToHSVA(hsla); }; -export const hexaToHSVA = (hex, alpha = 'FF') => { - const rgba = hex.map((v) => parseInt(v, 16)).concat(Number((parseInt(alpha, 16) / 255).toFixed(2))); - return rgbaToHSVA(rgba); + +export const hexaToHSVA = (hex, alpha = "FF") => { + const rgba = hex + .map(v => parseInt(v, 16)) + .concat(Number((parseInt(alpha, 16) / 255).toFixed(2))); + return rgbaToHSVA(rgba); }; -export const rgbaToHSVA = (rgba) => { - const [ r, g, b, a = 1 ] = rgba; - let hsv = _rgbToHSV([ r, g, b ]); - return [ ...hsv, a ]; +export const rgbaToHSVA = rgba => { + const [r, g, b, a = 1] = rgba; + let hsv = _rgbToHSV([r, g, b]); + return [...hsv, a]; }; export const hslaToHSVA = ([h, s, l, a = 1]) => { - let hsv = _hslToHSV([h, s, l]) - return [...hsv, a] -} - -export const hsvaToHexa = (hsva, asString = false) => { - const [ r, g, b, a ] = hsvaToRgba(hsva); - - const hexa = [ r, g, b ].map((v) => Math.round(v).toString(16)).concat(Math.round((a * 255)).toString(16)); - return asString ? `#${hexa.join('')}` : hexa + let hsv = _hslToHSV([h, s, l]); + return [...hsv, a]; }; -export const hsvaToRgba = ([h, s, v, a], asString = false) => { - let rgb = _hsvToRgb([ h, s, v ]).map(x => Math.round(x)); - let rgba = [ ...rgb, a ]; - return asString ? `rgba(${rgba.join(",")})` : rgba +export const hsvaToHexa = (hsva, asString = false) => { + const [r, g, b, a] = hsvaToRgba(hsva); + + const hexa = [r, g, b] + .map(v => { + let hex = Math.round(v).toString(16) + return hex.length === 1 ? `0${hex}` : hex + }) + .concat(Math.round(a * 255).toString(16)); + return asString ? `#${hexa.join("")}` : hexa; +}; + +export const hsvaToRgba = ([h, s, v, a = 1], asString = false) => { + let rgb = _hsvToRgb([h, s, v]).map(x => Math.round(x)); + let rgba = [...rgb, a < 1 ? _fixNum(a, 2) : a]; + return asString ? `rgba(${rgba.join(",")})` : rgba; }; export const hsvaToHsla = ([h, s, v, a = 1], asString = false) => { - let hsl = _hsvToHSL([h, s, v]) - let hsla = [...hsl, a] - return asString ? `hsla(${hsla.join(",")})` : hsla -} + let [hue, sat, lum] = _hsvToHSL([h, s, v]); + let hsla = [hue, sat + "%", lum + "%", a < 1 ? _fixNum(a, 2) : a]; + return `hsla(${hsla.join(",")})`; +}; -export const _hslToHSV = (hsl) => { - const h = hsl[0]; - let s = hsl[1] / 100; - let l = hsl[2] / 100; - let smin = s; - const lmin = Math.max(l, 0.01); +export const _hslToHSV = hsl => { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); - l *= 2; - s *= (l <= 1) ? l : 2 - l; - smin *= lmin <= 1 ? lmin : 2 - lmin; - const v = (l + s) / 2; - const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + l *= 2; + s *= l <= 1 ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); - return [h, sv * 100, v * 100]; -} - -//Credit : https://github.com/Qix-/color-convert -export const _rgbToHSV = (rgb) => { - let rdif; - let gdif; - let bdif; - let h; - let s; - - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const v = Math.max(r, g, b); - const diff = v - Math.min(r, g, b); - const diffc = function(c) { - return (v - c) / 6 / diff + 1 / 2; - }; - - if (diff === 0) { - h = 0; - s = 0; - } else { - s = diff / v; - rdif = diffc(r); - gdif = diffc(g); - bdif = diffc(b); - - if (r === v) { - h = bdif - gdif; - } else if (g === v) { - h = 1 / 3 + rdif - bdif; - } else if (b === v) { - h = 2 / 3 + gdif - rdif; - } - - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } - } - - const hsvResult = [ h * 360, s * 100, v * 100 ].map((v) => Math.round(v)); - return hsvResult; + return [h, sv * 100, v * 100]; }; //Credit : https://github.com/Qix-/color-convert -export const _hsvToRgb = (hsv) => { - const h = hsv[0] / 60; - const s = hsv[1] / 100; - let v = hsv[2] / 100; - const hi = Math.floor(h) % 6; +export const _rgbToHSV = rgb => { + let rdif; + let gdif; + let bdif; + let h; + let s; - const f = h - Math.floor(h); - const p = 255 * v * (1 - s); - const q = 255 * v * (1 - s * f); - const t = 255 * v * (1 - s * (1 - f)); - v *= 255; + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function(c) { + return (v - c) / 6 / diff + 1 / 2; + }; - switch (hi) { - case 0: - return [ v, t, p ]; - case 1: - return [ q, v, p ]; - case 2: - return [ p, v, t ]; - case 3: - return [ p, q, v ]; - case 4: - return [ t, p, v ]; - case 5: - return [ v, p, q ]; - } + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = 1 / 3 + rdif - bdif; + } else if (b === v) { + h = 2 / 3 + gdif - rdif; + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + const hsvResult = [h * 360, s * 100, v * 100].map(v => Math.round(v)); + return hsvResult; }; //Credit : https://github.com/Qix-/color-convert -export const _hsvToHSL = (hsv) => { - - const h = hsv[0]; - const s = hsv[1] / 100; - const v = hsv[2] / 100; - const vmin = Math.max(v, 0.01); - let sl; - let l; +export const _hsvToRgb = hsv => { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; - l = (2 - s) * v; - const lmin = (2 - s) * vmin; - sl = s * vmin; - sl /= lmin <= 1 ? lmin : 2 - lmin; - sl = sl || 0; - l /= 2; + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - s * f); + const t = 255 * v * (1 - s * (1 - f)); + v *= 255; - return [ h, Number((sl * 100).toFixed(1)), Number((l * 100).toFixed(1)) ]; + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } }; + +//Credit : https://github.com/Qix-/color-convert +export const _hsvToHSL = hsv => { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; + + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= lmin <= 1 ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [_fixNum(h, 0), _fixNum(sl * 100, 0), _fixNum(l * 100, 0)]; +}; + +export const _fixNum = (value, decimalPlaces) => + Number(parseFloat(value).toFixed(decimalPlaces)); From 0c35f46b5f147a403f8a38034e9f4be01f62ba46 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Fri, 12 Jun 2020 12:15:17 +0100 Subject: [PATCH 11/34] bugfix - screen/page > settings throwing error --- .../builder/src/builderStore/store/index.js | 56 +++++-------------- .../builder/src/builderStore/storeUtils.js | 13 +++++ .../ComponentPropertiesPanel.svelte | 29 ++-------- .../userInterface/SettingsView.svelte | 40 +++++++++++++ 4 files changed, 72 insertions(+), 66 deletions(-) diff --git a/packages/builder/src/builderStore/store/index.js b/packages/builder/src/builderStore/store/index.js index 9f91550bca..1f3ea9c0ef 100644 --- a/packages/builder/src/builderStore/store/index.js +++ b/packages/builder/src/builderStore/store/index.js @@ -5,7 +5,6 @@ import { writable, get } from "svelte/store" import api from "../api" import { DEFAULT_PAGES_OBJECT } from "../../constants" import { getExactComponent } from "components/userInterface/pagesParsing/searchComponents" -import { rename } from "components/userInterface/pagesParsing/renameScreen" import { createProps, makePropsSafe, @@ -24,6 +23,7 @@ import { saveCurrentPreviewItem as _saveCurrentPreviewItem, saveScreenApi as _saveScreenApi, regenerateCssForCurrentScreen, + renameCurrentScreen, } from "../storeUtils" export const getStore = () => { @@ -52,7 +52,6 @@ export const getStore = () => { store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store) store.saveScreen = saveScreen(store) - store.renameScreen = renameScreen(store) store.deleteScreen = deleteScreen(store) store.setCurrentScreen = setCurrentScreen(store) store.setCurrentPage = setCurrentPage(store) @@ -63,6 +62,7 @@ export const getStore = () => { store.addChildComponent = addChildComponent(store) store.selectComponent = selectComponent(store) store.setComponentProp = setComponentProp(store) + store.setPageOrScreenProp = setPageOrScreenProp(store) store.setComponentStyle = setComponentStyle(store) store.setComponentCode = setComponentCode(store) store.setScreenType = setScreenType(store) @@ -207,46 +207,6 @@ const deleteScreen = store => name => { }) } -const renameScreen = store => (oldname, newname) => { - store.update(s => { - const { screens, pages, error, changedScreens } = rename( - s.pages, - s.screens, - oldname, - newname - ) - - if (error) { - // should really do something with this - return s - } - - s.screens = screens - s.pages = pages - if (s.currentPreviewItem.name === oldname) - s.currentPreviewItem.name = newname - - const saveAllChanged = async () => { - for (let screenName of changedScreens) { - const changedScreen = getExactComponent(screens, screenName) - await api.post(`/_builder/api/${s.appId}/screen`, changedScreen) - } - } - - api - .patch(`/_builder/api/${s.appId}/screen`, { - oldname, - newname, - }) - .then(() => saveAllChanged()) - .then(() => { - _savePage(s) - }) - - return s - }) -} - const savePage = store => async page => { store.update(state => { if (state.currentFrontEndType !== "page" || !state.currentPageName) { @@ -400,6 +360,18 @@ const setComponentProp = store => (name, value) => { }) } +const setPageOrScreenProp = store => (name, value) => { + store.update(state => { + if (name === "name" && state.currentFrontEndType === "screen") { + state = renameCurrentScreen(value, state) + } else { + state.currentPreviewItem[name] = value + _saveCurrentPreviewItem(state) + } + return state + }) +} + const setComponentStyle = store => (type, name, value) => { store.update(state => { if (!state.currentComponentInfo._styles) { diff --git a/packages/builder/src/builderStore/storeUtils.js b/packages/builder/src/builderStore/storeUtils.js index d6aa4d0308..ff951e6b6f 100644 --- a/packages/builder/src/builderStore/storeUtils.js +++ b/packages/builder/src/builderStore/storeUtils.js @@ -45,6 +45,19 @@ export const saveScreenApi = (screen, s) => { .then(() => savePage(s)) } +export const renameCurrentScreen = (newname, state) => { + const oldname = state.currentPreviewItem.name + state.currentPreviewItem.name = newname + api.patch( + `/_builder/api/${state.appId}/pages/${state.currentPageName}/screen`, + { + oldname, + newname, + } + ) + return state +} + export const walkProps = (props, action, cancelToken = null) => { cancelToken = cancelToken || { cancelled: false } action(props, () => { diff --git a/packages/builder/src/components/userInterface/ComponentPropertiesPanel.svelte b/packages/builder/src/components/userInterface/ComponentPropertiesPanel.svelte index 7d33b9c963..bcebb4d2d4 100644 --- a/packages/builder/src/components/userInterface/ComponentPropertiesPanel.svelte +++ b/packages/builder/src/components/userInterface/ComponentPropertiesPanel.svelte @@ -13,7 +13,6 @@ import CodeEditor from "./CodeEditor.svelte" import LayoutEditor from "./LayoutEditor.svelte" import EventsEditor from "./EventsEditor" - import panelStructure from "./temporaryPanelStructure.js" import CategoryTab from "./CategoryTab.svelte" import DesignView from "./DesignView.svelte" @@ -40,28 +39,8 @@ let panelDefinition = {} - $: { - if (componentPropDefinition.properties) { - if (selectedCategory.value === "design") { - panelDefinition = componentPropDefinition.properties["design"] - } else { - let panelDef = componentPropDefinition.properties["settings"] - if ( - $store.currentFrontEndType === "page" && - $store.currentView !== "component" - ) { - panelDefinition = [...page, ...panelDef] - } else if ( - $store.currentFrontEndType === "screen" && - $store.currentView !== "component" - ) { - panelDefinition = [...screen, ...panelDef] - } else { - panelDefinition = panelDef - } - } - } - } + $: panelDefinition = componentPropDefinition.properties && + componentPropDefinition.properties[selectedCategory.value] const onStyleChanged = store.setComponentStyle const onPropChanged = store.setComponentProp @@ -107,7 +86,9 @@ {componentInstance} {componentDefinition} {panelDefinition} - onChange={onPropChanged} /> + onChange={onPropChanged} + onScreenPropChange={store.setPageOrScreenProp} + screenOrPageInstance={$store.currentView !== "component" && $store.currentPreviewItem} /> {:else if selectedCategory.value === 'events'} {/if} diff --git a/packages/builder/src/components/userInterface/SettingsView.svelte b/packages/builder/src/components/userInterface/SettingsView.svelte index 99e704d1d9..17e4fe5e71 100644 --- a/packages/builder/src/components/userInterface/SettingsView.svelte +++ b/packages/builder/src/components/userInterface/SettingsView.svelte @@ -2,20 +2,60 @@ import PropertyControl from "./PropertyControl.svelte" import InputGroup from "../common/Inputs/InputGroup.svelte" import Colorpicker from "../common/Colorpicker.svelte" + import { goto } from "@sveltech/routify" import { excludeProps } from "./propertyCategories.js" + import Input from "../common/Input.svelte" export let panelDefinition = [] export let componentDefinition = {} export let componentInstance = {} export let onChange = () => {} + export let onScreenPropChange = () => {} + export let screenOrPageInstance const propExistsOnComponentDef = prop => prop in componentDefinition.props function handleChange(key, data) { data.target ? onChange(key, data.target.value) : onChange(key, data) } + + function handleScreenPropChange (name, value) { + onScreenPropChange(name,value) + if(!isPage && name === "name") { + // screen name is changed... change URL + $goto(`./:page/${value}`) + } + } + + const screenDefinition = [ + { key: "name", label: "Name", control: Input }, + { key: "description", label: "Description", control: Input }, + { key: "route", label: "Route", control: Input }, + ] + + const pageDefinition = [ + { key: "title", label: "Title", control: Input }, + { key: "favicon", label: "Favicon", control: Input }, + ] + + $: isPage = screenOrPageInstance && screenOrPageInstance.favicon + $: screenOrPageDefinition = isPage ? pageDefinition : screenDefinition + +{#if screenOrPageInstance} + {#each screenOrPageDefinition as def} + + {/each} +
+{/if} + {#if panelDefinition && panelDefinition.length > 0} {#each panelDefinition as definition} {#if propExistsOnComponentDef(definition.key)} From 19d132c6c24b35a185f5426ee681d0a50eb3c2db Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Fri, 12 Jun 2020 20:42:55 +0100 Subject: [PATCH 12/34] removal of appRoot - appId comes in cookie --- packages/builder/cypress/plugins/index.js | 21 +++ .../builder/src/builderStore/store/index.js | 56 ++---- .../builder/src/builderStore/storeUtils.js | 13 ++ .../common/Inputs/InputGroup.svelte | 7 +- .../AppPreview/CurrentItemPreview.svelte | 40 +++-- .../AppPreview/CurrentItemPreview.svelte.orig | 161 ++++++++++++++++++ .../AppPreview/iframeTemplate.js | 1 + .../ComponentPropertiesPanel.svelte | 26 +-- .../components/userInterface/PagesList.svelte | 4 +- .../userInterface/SettingsView.svelte | 40 +++++ .../userInterface/propertyCategories.js | 82 +++++++-- .../userInterface/temporaryPanelStructure.js | 12 ++ packages/client/src/api/index.js | 5 +- packages/client/src/createApp.js | 11 +- packages/client/src/index.js | 9 +- packages/client/src/render/getAppId.js | 5 + packages/client/src/render/screenRouter.js | 16 +- packages/client/src/state/bbComponentApi.js | 14 +- packages/client/src/state/eventHandlers.js | 3 +- packages/client/src/state/stateManager.js | 5 +- packages/client/tests/testAppDef.js | 9 +- .../src/Test/createApp.js | 8 +- packages/server/package.json | 2 +- packages/server/src/api/controllers/auth.js | 12 +- packages/server/src/api/controllers/model.js | 32 +++- packages/server/src/api/controllers/record.js | 11 +- packages/server/src/api/controllers/static.js | 30 +++- packages/server/src/api/index.js | 9 + packages/server/src/api/routes/auth.js | 2 +- packages/server/src/api/routes/index.js | 2 + packages/server/src/api/routes/model.js | 38 +---- packages/server/src/api/routes/record.js | 36 ++++ packages/server/src/api/routes/static.js | 5 +- .../src/api/routes/tests/couchTestUtils.js | 4 + .../server/src/api/routes/tests/model.spec.js | 47 ++++- .../src/api/routes/tests/record.spec.js | 24 +++ .../server/src/utilities/builder/buildPage.js | 6 +- .../src/utilities/builder/index.template.html | 8 +- packages/standard-components/components.json | 7 + .../public/clientAppDefinition.js | 1 - packages/standard-components/src/Embed.svelte | 5 + packages/standard-components/src/Login.svelte | 19 +-- .../standard-components/src/Test/createApp.js | 2 +- packages/standard-components/src/index.js | 1 + 44 files changed, 616 insertions(+), 235 deletions(-) create mode 100644 packages/builder/cypress/plugins/index.js create mode 100644 packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte.orig create mode 100644 packages/client/src/render/getAppId.js create mode 100644 packages/server/src/api/routes/record.js create mode 100644 packages/standard-components/src/Embed.svelte diff --git a/packages/builder/cypress/plugins/index.js b/packages/builder/cypress/plugins/index.js new file mode 100644 index 0000000000..aa9918d215 --- /dev/null +++ b/packages/builder/cypress/plugins/index.js @@ -0,0 +1,21 @@ +/// +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +/** + * @type {Cypress.PluginConfig} + */ +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/packages/builder/src/builderStore/store/index.js b/packages/builder/src/builderStore/store/index.js index 9f91550bca..1f3ea9c0ef 100644 --- a/packages/builder/src/builderStore/store/index.js +++ b/packages/builder/src/builderStore/store/index.js @@ -5,7 +5,6 @@ import { writable, get } from "svelte/store" import api from "../api" import { DEFAULT_PAGES_OBJECT } from "../../constants" import { getExactComponent } from "components/userInterface/pagesParsing/searchComponents" -import { rename } from "components/userInterface/pagesParsing/renameScreen" import { createProps, makePropsSafe, @@ -24,6 +23,7 @@ import { saveCurrentPreviewItem as _saveCurrentPreviewItem, saveScreenApi as _saveScreenApi, regenerateCssForCurrentScreen, + renameCurrentScreen, } from "../storeUtils" export const getStore = () => { @@ -52,7 +52,6 @@ export const getStore = () => { store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store) store.saveScreen = saveScreen(store) - store.renameScreen = renameScreen(store) store.deleteScreen = deleteScreen(store) store.setCurrentScreen = setCurrentScreen(store) store.setCurrentPage = setCurrentPage(store) @@ -63,6 +62,7 @@ export const getStore = () => { store.addChildComponent = addChildComponent(store) store.selectComponent = selectComponent(store) store.setComponentProp = setComponentProp(store) + store.setPageOrScreenProp = setPageOrScreenProp(store) store.setComponentStyle = setComponentStyle(store) store.setComponentCode = setComponentCode(store) store.setScreenType = setScreenType(store) @@ -207,46 +207,6 @@ const deleteScreen = store => name => { }) } -const renameScreen = store => (oldname, newname) => { - store.update(s => { - const { screens, pages, error, changedScreens } = rename( - s.pages, - s.screens, - oldname, - newname - ) - - if (error) { - // should really do something with this - return s - } - - s.screens = screens - s.pages = pages - if (s.currentPreviewItem.name === oldname) - s.currentPreviewItem.name = newname - - const saveAllChanged = async () => { - for (let screenName of changedScreens) { - const changedScreen = getExactComponent(screens, screenName) - await api.post(`/_builder/api/${s.appId}/screen`, changedScreen) - } - } - - api - .patch(`/_builder/api/${s.appId}/screen`, { - oldname, - newname, - }) - .then(() => saveAllChanged()) - .then(() => { - _savePage(s) - }) - - return s - }) -} - const savePage = store => async page => { store.update(state => { if (state.currentFrontEndType !== "page" || !state.currentPageName) { @@ -400,6 +360,18 @@ const setComponentProp = store => (name, value) => { }) } +const setPageOrScreenProp = store => (name, value) => { + store.update(state => { + if (name === "name" && state.currentFrontEndType === "screen") { + state = renameCurrentScreen(value, state) + } else { + state.currentPreviewItem[name] = value + _saveCurrentPreviewItem(state) + } + return state + }) +} + const setComponentStyle = store => (type, name, value) => { store.update(state => { if (!state.currentComponentInfo._styles) { diff --git a/packages/builder/src/builderStore/storeUtils.js b/packages/builder/src/builderStore/storeUtils.js index d6aa4d0308..ff951e6b6f 100644 --- a/packages/builder/src/builderStore/storeUtils.js +++ b/packages/builder/src/builderStore/storeUtils.js @@ -45,6 +45,19 @@ export const saveScreenApi = (screen, s) => { .then(() => savePage(s)) } +export const renameCurrentScreen = (newname, state) => { + const oldname = state.currentPreviewItem.name + state.currentPreviewItem.name = newname + api.patch( + `/_builder/api/${state.appId}/pages/${state.currentPageName}/screen`, + { + oldname, + newname, + } + ) + return state +} + export const walkProps = (props, action, cancelToken = null) => { cancelToken = cancelToken || { cancelled: false } action(props, () => { diff --git a/packages/builder/src/components/common/Inputs/InputGroup.svelte b/packages/builder/src/components/common/Inputs/InputGroup.svelte index e5fed68103..385623ca19 100644 --- a/packages/builder/src/components/common/Inputs/InputGroup.svelte +++ b/packages/builder/src/components/common/Inputs/InputGroup.svelte @@ -19,9 +19,10 @@ onChange(_value) } - $: displayValues = value && suffix - ? value.map(v => v.replace(new RegExp(`${suffix}$`), "")) - : value || [] + $: displayValues = + value && suffix + ? value.map(v => v.replace(new RegExp(`${suffix}$`), "")) + : value || []
diff --git a/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte index 53450c2200..f97f91df6b 100644 --- a/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte @@ -21,7 +21,7 @@ return componentName || "element" } - const screenPlaceholder = { + const screenPlaceholder = { name: "Screen Placeholder", route: "*", props: { @@ -60,9 +60,8 @@ }, } - $: hasComponent = !!$store.currentPreviewItem - + $: { styles = "" // Apply the CSS from the currently selected page and its screens @@ -88,11 +87,10 @@ libraries: $store.libraries, page: $store.pages[$store.currentPageName], screens: [ - $store.currentFrontEndType === "page" - ? screenPlaceholder - : $store.currentPreviewItem, + $store.currentFrontEndType === "page" + ? screenPlaceholder + : $store.currentPreviewItem, ], - appRootPath: "", } $: selectedComponentType = getComponentTypeName($store.currentComponentInfo) @@ -102,20 +100,26 @@ : "" const refreshContent = () => { - iframe.contentWindow.postMessage(JSON.stringify({ - styles, - stylesheetLinks, - selectedComponentType, - selectedComponentId, - frontendDefinition, - })) + iframe.contentWindow.postMessage( + JSON.stringify({ + styles, + stylesheetLinks, + selectedComponentType, + selectedComponentId, + frontendDefinition, + appId: $store.appId, + }) + ) } - $: if(iframe) iframe.contentWindow.addEventListener("bb-ready", refreshContent, { once: true }) + $: if (iframe) + iframe.contentWindow.addEventListener("bb-ready", refreshContent, { + once: true, + }) - $: if(iframe && frontendDefinition) { - refreshContent() - } + $: if (iframe && frontendDefinition) { + refreshContent() + }
diff --git a/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte.orig b/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte.orig new file mode 100644 index 0000000000..81c3624274 --- /dev/null +++ b/packages/builder/src/components/userInterface/AppPreview/CurrentItemPreview.svelte.orig @@ -0,0 +1,161 @@ + + +
+ {#if hasComponent && $store.currentPreviewItem} +