Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
David Kempe
Meerkat
Commits
8eaca0e2
Commit
8eaca0e2
authored
Sep 18, 2020
by
Max Reeves
Browse files
dont stretch me broooo
parent
261196a8
Changes
5
Hide whitespace changes
Inline
Side-by-side
dashboard.go
View file @
8eaca0e2
...
@@ -11,7 +11,9 @@ import (
...
@@ -11,7 +11,9 @@ import (
"path"
"path"
"path/filepath"
"path/filepath"
"regexp"
"regexp"
"strconv"
"strings"
"strings"
"unicode/utf8"
"github.com/go-chi/chi"
"github.com/go-chi/chi"
)
)
...
@@ -21,6 +23,8 @@ type Dashboard struct {
...
@@ -21,6 +23,8 @@ type Dashboard struct {
Title
string
`json:"title"`
Title
string
`json:"title"`
Slug
string
`json:"slug"`
Slug
string
`json:"slug"`
Background
string
`json:"background"`
Background
string
`json:"background"`
Width
string
`json:"width"`
Height
string
`json:"height"`
Tags
[]
string
`json:"tags"`
Tags
[]
string
`json:"tags"`
Elements
[]
Element
`json:"elements"`
Elements
[]
Element
`json:"elements"`
}
}
...
@@ -29,9 +33,35 @@ type Dashboard struct {
...
@@ -29,9 +33,35 @@ type Dashboard struct {
//This is an incomplete representation of the Element
//This is an incomplete representation of the Element
//options arn't included
//options arn't included
type
Element
struct
{
type
Element
struct
{
Type
string
`json:"type"`
Type
string
`json:"type"`
Title
string
`json:"title"`
Title
string
`json:"title"`
Rect
Rect
`json:"rect"`
Rect
Rect
`json:"rect"`
Options
Option
`json:"options"`
}
//Option contains element options
type
Option
struct
{
CheckID
string
`json:"checkId"`
NameFontSize
int
`json:"nameFontSize"`
StatusFontSize
int
`json:"statusFontSize"`
RightArrow
bool
`json:"rightArrow"`
LeftArrow
bool
`json:"leftArrow"`
StrokeWidth
int
`json:"strokeWidth"`
Image
string
`json:"image"`
OKSvg
string
`json:"checkSquare"`
OKStrokeColor
string
`json:"okStrokeColor"`
WarningStrokeColor
string
`json:"warningStrokeColor"`
WarningSvg
string
`json:"warningSvg"`
UnknownStrokeColor
string
`json:"unknownStrokeColor"`
UnknownSvg
string
`json:"unknownSvg"`
CriticalStrokeColor
string
`json:"criticalStrokeColor"`
CriticalSvg
string
`json:"criticalSvg"`
CriticalImage
string
`json:"criticalImage"`
OkImage
string
`json:"okImage"`
UnknownImage
string
`json:"unknownImage"`
WarningImage
string
`json:"warningImage"`
Svg
string
`json:"svg"`
StrokeColor
string
`json:"strokeColor"`
}
}
//Rect helper struct for positions
//Rect helper struct for positions
...
@@ -177,6 +207,11 @@ func handleCreateDashboard(w http.ResponseWriter, r *http.Request) {
...
@@ -177,6 +207,11 @@ func handleCreateDashboard(w http.ResponseWriter, r *http.Request) {
enc
.
Encode
(
SlugResponse
{
Slug
:
slug
})
enc
.
Encode
(
SlugResponse
{
Slug
:
slug
})
}
}
func
trimFirstRune
(
s
string
)
string
{
_
,
i
:=
utf8
.
DecodeRuneInString
(
s
)
return
s
[
i
:
]
}
func
handleUpdateDashboard
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
handleUpdateDashboard
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
slug
:=
chi
.
URLParam
(
r
,
"slug"
)
slug
:=
chi
.
URLParam
(
r
,
"slug"
)
...
@@ -186,6 +221,12 @@ func handleUpdateDashboard(w http.ResponseWriter, r *http.Request) {
...
@@ -186,6 +221,12 @@ func handleUpdateDashboard(w http.ResponseWriter, r *http.Request) {
var
dashboard
Dashboard
var
dashboard
Dashboard
err
:=
json
.
Unmarshal
(
buf
.
Bytes
(),
&
dashboard
)
err
:=
json
.
Unmarshal
(
buf
.
Bytes
(),
&
dashboard
)
width
,
height
:=
getImageDimension
(
trimFirstRune
(
dashboard
.
Background
))
dashboard
.
Height
=
strconv
.
Itoa
(
height
)
dashboard
.
Width
=
strconv
.
Itoa
(
width
)
// fmt.Println(width, height)
if
err
!=
nil
{
if
err
!=
nil
{
http
.
Error
(
w
,
"Error decoding json body: "
+
err
.
Error
(),
http
.
StatusBadRequest
)
http
.
Error
(
w
,
"Error decoding json body: "
+
err
.
Error
(),
http
.
StatusBadRequest
)
return
return
...
@@ -204,8 +245,10 @@ func handleUpdateDashboard(w http.ResponseWriter, r *http.Request) {
...
@@ -204,8 +245,10 @@ func handleUpdateDashboard(w http.ResponseWriter, r *http.Request) {
return
return
}
}
dashboardJSON
,
err
:=
json
.
Marshal
(
dashboard
)
// fmt.Println(dashboardJSON, err)
//Write updated file
//Write updated file
err
=
ioutil
.
WriteFile
(
path
.
Join
(
"dashboards"
,
slugNew
+
".json"
),
buf
.
Bytes
()
,
0655
)
err
=
ioutil
.
WriteFile
(
path
.
Join
(
"dashboards"
,
slugNew
+
".json"
),
dashboardJSON
,
0655
)
if
err
!=
nil
{
if
err
!=
nil
{
http
.
Error
(
w
,
"Error writing file: "
+
err
.
Error
(),
http
.
StatusInternalServerError
)
http
.
Error
(
w
,
"Error writing file: "
+
err
.
Error
(),
http
.
StatusInternalServerError
)
return
return
...
...
frontend/src/editor.jsx
View file @
8eaca0e2
import
{
h
,
Fragment
}
from
'
preact
'
;
import
{
h
,
Fragment
}
from
'
preact
'
;
import
{
route
}
from
'
preact-router
'
;
import
{
route
}
from
'
preact-router
'
;
import
{
useEffect
,
useReducer
,
useState
}
from
'
preact/hooks
'
;
import
{
useEffect
,
useReducer
,
useState
,
useRef
,
useLayoutEffect
}
from
'
preact/hooks
'
;
import
*
as
meerkat
from
'
./meerkat
'
import
*
as
meerkat
from
'
./meerkat
'
import
{
routeParam
,
removeParam
,
TagEditor
}
from
'
./util
'
;
import
{
routeParam
,
removeParam
,
TagEditor
}
from
'
./util
'
;
...
@@ -47,7 +47,11 @@ const dashboardReducer = (state, action) => {
...
@@ -47,7 +47,11 @@ const dashboardReducer = (state, action) => {
case
'
deleteElement
'
:
case
'
deleteElement
'
:
console
.
log
(
'
Deleting element
'
)
console
.
log
(
'
Deleting element
'
)
case
'
duplicateElement
'
:
case
'
duplicateElement
'
:
console
.
log
(
'
Duplicating element
'
)
console
.
log
(
'
Duplicating element
'
)
case
'
getDimensions
'
:
console
.
log
(
'
Getting Dimensions
'
)
console
.
log
({
height
:
action
.
height
,
width
:
action
.
width
})
return
{...
state
,
height
:
action
.
height
,
width
:
action
.
width
};
case
'
updateElement
'
:
case
'
updateElement
'
:
console
.
log
(
'
Updating element
'
)
console
.
log
(
'
Updating element
'
)
const
newState
=
{...
state
};
const
newState
=
{...
state
};
...
@@ -298,14 +302,16 @@ function DashboardElements({dashboardDispatch, selectedElementId, elements, high
...
@@ -298,14 +302,16 @@ function DashboardElements({dashboardDispatch, selectedElementId, elements, high
}
}
//The actual dashboard being rendered
//The actual dashboard being rendered
function
DashboardView
({
dashboard
,
dashboardDispatch
,
selectedElementId
,
highlightedElementId
})
{
export
function
DashboardView
({
dashboard
,
dashboardDispatch
,
selectedElementId
,
highlightedElementId
})
{
const
backgroundImage
=
dashboard
.
background
?
`url(
${
dashboard
.
background
}
)`
:
'
none
'
;
const
backgroundImage
=
dashboard
.
background
?
dashboard
.
background
:
'
none
'
;
return
<
div
class
=
"dashboard-wrap"
>
return
<
div
class
=
"dashboard-wrap"
style
=
{
{
Height
:
dashboard
.
height
,
Width
:
dashboard
.
width
}
}
>
<
div
class
=
"dashboard"
style
=
{
{
backgroundImage
:
backgroundImage
}
}
>
<
div
class
=
"dashboard"
>
<
img
src
=
{
backgroundImage
}
style
=
"height: 100%; width: 100%"
id
=
"dashboard-dimensions"
/>
<
DashboardElements
elements
=
{
dashboard
.
elements
}
selectedElementId
=
{
selectedElementId
}
<
DashboardElements
elements
=
{
dashboard
.
elements
}
selectedElementId
=
{
selectedElementId
}
dashboardDispatch
=
{
dashboardDispatch
}
highlightedElementId
=
{
highlightedElementId
}
/>
dashboardDispatch
=
{
dashboardDispatch
}
highlightedElementId
=
{
highlightedElementId
}
/>
</
div
>
{
console
.
log
(
dashboard
.
height
)
}
</
div
>
</
div
>
</
div
>
}
}
...
@@ -409,12 +415,9 @@ function SidePanelElements({dashboard, dashboardDispatch, setHighlightedElementI
...
@@ -409,12 +415,9 @@ function SidePanelElements({dashboard, dashboardDispatch, setHighlightedElementI
<
div
class
=
"element-item"
draggable
=
{
true
}
id
=
{
index
}
onDragStart
=
{
handleDragStart
}
>
<
div
class
=
"element-item"
draggable
=
{
true
}
id
=
{
index
}
onDragStart
=
{
handleDragStart
}
>
<
div
onClick
=
{
e
=>
routeParam
(
'
selectedElementId
'
,
index
.
toString
())
}
>
<
div
onClick
=
{
e
=>
routeParam
(
'
selectedElementId
'
,
index
.
toString
())
}
>
<
div
class
=
"element-title"
>
{
element
.
title
}
</
div
>
<
div
class
=
"element-title"
>
{
element
.
title
}
</
div
>
<
span
>
<
button
class
=
"rounded btn-dark btn-sml m-1 medium"
onClick
=
{
e
=>
duplicateElement
(
e
,
index
)
}
>
Duplicate
</
button
>
<
button
class
=
"rounded btn-danger btn-sml m-1 medium"
onClick
=
{
e
=>
deleteElement
(
e
,
index
)
}
>
Delete
</
button
>
</
span
>
</
div
>
</
div
>
<
button
class
=
"rounded btn-dark btn-sml m-0 mr-1 mt-1 medium"
onClick
=
{
e
=>
duplicateElement
(
e
,
index
)
}
>
Duplicate
</
button
>
<
button
class
=
"rounded btn-danger btn-sml m-0 mr-1 mt-1 medium"
onClick
=
{
e
=>
deleteElement
(
e
,
index
)
}
>
Delete
</
button
>
<
div
class
=
"drop-zone"
onDrop
=
{
handleDrop
}
id
=
{
index
}
<
div
class
=
"drop-zone"
onDrop
=
{
handleDrop
}
id
=
{
index
}
onDragEnter
=
{
e
=>
{
e
.
preventDefault
();
e
.
currentTarget
.
classList
.
add
(
'
active
'
)}
}
onDragEnter
=
{
e
=>
{
e
.
preventDefault
();
e
.
currentTarget
.
classList
.
add
(
'
active
'
)}
}
onDragOver
=
{
e
=>
e
.
preventDefault
()
}
onDragOver
=
{
e
=>
e
.
preventDefault
()
}
...
...
frontend/src/viewer.jsx
View file @
8eaca0e2
import
{
h
}
from
'
preact
'
;
import
{
h
}
from
'
preact
'
;
import
{
route
}
from
'
preact-router
'
;
import
{
route
}
from
'
preact-router
'
;
import
{
useState
,
useEffect
}
from
'
preact/hooks
'
;
import
{
useState
,
useEffect
,
useRef
}
from
'
preact/hooks
'
;
import
*
as
meerkat
from
'
./meerkat
'
;
import
*
as
meerkat
from
'
./meerkat
'
;
import
{
CheckCard
}
from
'
./elements/card
'
;
import
{
CheckCard
}
from
'
./elements/card
'
;
...
@@ -15,7 +15,7 @@ import { StaticSVG } from './statics/svg';
...
@@ -15,7 +15,7 @@ import { StaticSVG } from './statics/svg';
import
{
StaticImage
}
from
'
./statics/image
'
;
import
{
StaticImage
}
from
'
./statics/image
'
;
//Read only page
//Read only page
export
function
Viewer
({
slug
})
{
export
function
Viewer
({
slug
,
dashboardReducer
})
{
const
[
dashboard
,
setDashboard
]
=
useState
(
null
);
const
[
dashboard
,
setDashboard
]
=
useState
(
null
);
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -30,8 +30,8 @@ export function Viewer({slug}) {
...
@@ -30,8 +30,8 @@ export function Viewer({slug}) {
const
left
=
`
${
element
.
rect
.
x
}
%`
;
const
left
=
`
${
element
.
rect
.
x
}
%`
;
const
top
=
`
${
element
.
rect
.
y
}
%`
;
const
top
=
`
${
element
.
rect
.
y
}
%`
;
const
width
=
`
${
element
.
rect
.
w
}
%`
;
const
width
=
`
${
element
.
rect
.
w
}
%`
;
const
height
=
`
${
element
.
rect
.
h
}
%`
;
const
height
=
`
${
(
element
.
rect
.
h
/
dashboard
.
height
)
+
11
}
%`
;
console
.
log
(
height
)
const
rotation
=
element
.
rotation
?
`rotate(
${
element
.
rotation
}
rad)`
:
`rotate(0rad)`
;
const
rotation
=
element
.
rotation
?
`rotate(
${
element
.
rotation
}
rad)`
:
`rotate(0rad)`
;
let
ele
=
null
;
let
ele
=
null
;
...
@@ -49,10 +49,12 @@ export function Viewer({slug}) {
...
@@ -49,10 +49,12 @@ export function Viewer({slug}) {
{
ele
}
{
ele
}
</
div
>
</
div
>
});
});
// style={{Height: height, Width: width}}
const
backgroundImage
=
dashboard
.
background
?
dashboard
.
background
:
'
none
'
;
const
backgroundImage
=
dashboard
.
background
?
`url(
${
dashboard
.
background
}
)`
:
'
none
'
;
return
<
div
class
=
"dashboard view-only"
>
return
<
div
class
=
"dashboard view-only"
style
=
{
{
backgroundImage
:
backgroundImage
}
}
>
<
img
src
=
{
backgroundImage
}
id
=
"dashboard-dimensions"
style
=
"height: 100%; width: 100%;"
/>
{
elements
}
{
elements
}
{
/* <button class="view-only-button" onClick={e => route('/')}>Home</button> */
}
</
div
>
</
div
>
}
}
\ No newline at end of file
frontend/style.css
View file @
8eaca0e2
...
@@ -443,9 +443,6 @@ div.dashboard-wrap {
...
@@ -443,9 +443,6 @@ div.dashboard-wrap {
}
}
.dashboard-wrap
.dashboard
{
.dashboard-wrap
.dashboard
{
background-size
:
contain
;
background-position
:
center
;
background-repeat
:
no-repeat
;
border
:
1.5px
solid
rgba
(
0
,
0
,
0
,
0.2
);
;
border
:
1.5px
solid
rgba
(
0
,
0
,
0
,
0.2
);
;
flex-grow
:
1
;
flex-grow
:
1
;
border-radius
:
4px
;
border-radius
:
4px
;
...
@@ -453,11 +450,17 @@ div.dashboard-wrap {
...
@@ -453,11 +450,17 @@ div.dashboard-wrap {
}
}
.dashboard.view-only
{
.dashboard.view-only
{
background-size
:
contain
;
display
:
flex
;
background-position
:
center
;
flex-direction
:
column
;
background-repeat
:
no-repeat
;
position
:
relative
;
width
:
100vw
;
flex-grow
:
1
;
height
:
100vh
;
min-height
:
calc
(
100vh
-
40px
);
}
#dashboard-dimensions
{
object-fit
:
contain
;
/* min-height: calc(100vh - 40px); */
}
}
.dashboard.view-only
.check
{
.dashboard.view-only
.check
{
...
...
upload.go
View file @
8eaca0e2
...
@@ -5,8 +5,13 @@ import (
...
@@ -5,8 +5,13 @@ import (
"crypto/sha256"
"crypto/sha256"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"image"
_
"image/jpeg"
_
"image/png"
"io/ioutil"
"io/ioutil"
"log"
"net/http"
"net/http"
"os"
"path"
"path"
"path/filepath"
"path/filepath"
)
)
...
@@ -17,6 +22,19 @@ type ResponseURL struct {
...
@@ -17,6 +22,19 @@ type ResponseURL struct {
URL
string
`json:"url"`
URL
string
`json:"url"`
}
}
func
getImageDimension
(
imagePath
string
)
(
int
,
int
)
{
file
,
err
:=
os
.
Open
(
imagePath
)
if
err
!=
nil
{
log
.
Println
(
err
)
}
image
,
_
,
err
:=
image
.
DecodeConfig
(
file
)
if
err
!=
nil
{
log
.
Println
(
imagePath
,
err
)
}
return
image
.
Width
,
image
.
Height
}
func
handleUpload
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
handleUpload
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
extension
:=
filepath
.
Ext
(
r
.
Header
.
Get
(
"filename"
))
extension
:=
filepath
.
Ext
(
r
.
Header
.
Get
(
"filename"
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment