Merge branch 'feature/rest-redesign' into feature/query-auth
This commit is contained in:
commit
9fa4fe6c76
|
@ -9,6 +9,7 @@
|
|||
export let size = "M"
|
||||
export let hoverable = false
|
||||
export let disabled = false
|
||||
export let color
|
||||
|
||||
$: rotation = getRotation(direction)
|
||||
|
||||
|
@ -25,7 +26,9 @@
|
|||
focusable="false"
|
||||
aria-hidden={hidden}
|
||||
aria-label={name}
|
||||
style={`transform: rotate(${rotation}deg)`}
|
||||
style={`transform: rotate(${rotation}deg); ${
|
||||
color ? `color: ${color};` : ""
|
||||
}`}
|
||||
>
|
||||
<use xlink:href="#spectrum-icon-18-{name}" />
|
||||
</svg>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<div class="icon-container">
|
||||
<div
|
||||
class="icon"
|
||||
class:icon-small={size === "M" || size === "S"}
|
||||
on:mouseover={() => (showTooltip = true)}
|
||||
on:mouseleave={() => (showTooltip = false)}
|
||||
>
|
||||
|
@ -44,6 +45,7 @@
|
|||
}
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.icon-container {
|
||||
position: relative;
|
||||
|
@ -64,4 +66,8 @@
|
|||
.icon {
|
||||
transform: scale(0.75);
|
||||
}
|
||||
.icon-small {
|
||||
margin-top: -2px;
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
export let quiet = false
|
||||
export let emphasized = false
|
||||
|
||||
let thisSelected = undefined
|
||||
|
||||
let _id = id()
|
||||
const tab = writable({ title: selected, id: _id, emphasized })
|
||||
setContext("tab", tab)
|
||||
|
@ -20,9 +22,18 @@
|
|||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: {
|
||||
if ($tab.title !== selected) {
|
||||
selected = $tab.title
|
||||
dispatch("select", selected)
|
||||
if (thisSelected !== selected) {
|
||||
thisSelected = selected
|
||||
dispatch("select", thisSelected)
|
||||
} else if ($tab.title !== thisSelected) {
|
||||
thisSelected = $tab.title
|
||||
dispatch("select", thisSelected)
|
||||
}
|
||||
if ($tab.title !== thisSelected) {
|
||||
tab.update(state => {
|
||||
state.title = thisSelected
|
||||
return state
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 424.9 376.9" style="enable-background:new 0 0 424.9 376.9;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:url(#SVGID_00000173146453699406745440000014498258185172885933_);}
|
||||
.st2{fill:url(#SVGID_00000072276482643233320020000011975551142177928352_);}
|
||||
.st3{fill:url(#SVGID_00000000209806784423878430000006497884456548529061_);}
|
||||
.st4{fill:url(#SVGID_00000145771761158215620900000018209346423627093124_);}
|
||||
.st5{fill:#FFFFFF;}
|
||||
.st6{fill:url(#SVGID_00000134247842479715961920000014109114775597637809_);}
|
||||
.st7{fill:url(#SVGID_00000119810811088729404010000001339012453506459048_);}
|
||||
.st8{fill:url(#SVGID_00000056391310230795810690000008029868739465234354_);}
|
||||
.st9{fill:#010202;}
|
||||
</style>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="51.0692" y1="421.4218" x2="245.8004" y2="138.7009">
|
||||
<stop offset="0" style="stop-color:#90D1E1"/>
|
||||
<stop offset="0.9921" style="stop-color:#F195BE"/>
|
||||
</linearGradient>
|
||||
<circle class="st0" cx="211.1" cy="189.1" r="179.2"/>
|
||||
<linearGradient id="SVGID_00000181791594591671767050000008664012113219957652_" gradientUnits="userSpaceOnUse" x1="240.147" y1="117.7065" x2="241.3703" y2="117.7065">
|
||||
<stop offset="6.070287e-03" style="stop-color:#EAB593"/>
|
||||
<stop offset="0.9975" style="stop-color:#F4C278"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000181791594591671767050000008664012113219957652_);" d="M240.1,118
|
||||
C241.1,117.6,242.4,117,240.1,118L240.1,118z"/>
|
||||
<linearGradient id="SVGID_00000058550945621228767580000005935124031691961279_" gradientUnits="userSpaceOnUse" x1="94.8494" y1="142.6618" x2="97.0305" y2="142.6618">
|
||||
<stop offset="6.070287e-03" style="stop-color:#EAB593"/>
|
||||
<stop offset="0.9975" style="stop-color:#F4C278"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000058550945621228767580000005935124031691961279_);" d="M97,142.9c-3.2-0.6-2.2-0.3-1.3-0.2
|
||||
c0.4,0,0.7,0.1,1.1,0.2C96.9,142.8,97,142.8,97,142.9z"/>
|
||||
<linearGradient id="SVGID_00000137132525261985581510000000877506361518317499_" gradientUnits="userSpaceOnUse" x1="178.9468" y1="243.9432" x2="180.17" y2="243.9432">
|
||||
<stop offset="6.070287e-03" style="stop-color:#EAB593"/>
|
||||
<stop offset="0.9975" style="stop-color:#F4C278"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000137132525261985581510000000877506361518317499_);" d="M178.9,244.2
|
||||
C179.9,243.8,181.2,243.3,178.9,244.2L178.9,244.2z"/>
|
||||
<linearGradient id="SVGID_00000147899999161542128250000012606861005779996338_" gradientUnits="userSpaceOnUse" x1="147.0169" y1="218.2912" x2="147.8155" y2="218.2912">
|
||||
<stop offset="6.070287e-03" style="stop-color:#EAB593"/>
|
||||
<stop offset="0.9975" style="stop-color:#F4C278"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000147899999161542128250000012606861005779996338_);" d="M147.8,218.4c-1.2-0.2-0.8-0.1-0.5-0.1
|
||||
C147.5,218.3,147.6,218.3,147.8,218.4C147.8,218.4,147.8,218.4,147.8,218.4z"/>
|
||||
<path class="st5" d="M136.2,205.2l0.6,2.3l-6.8,1.6l0.8,3.3l-1.9,0.5l-1.3-5.6L136.2,205.2z"/>
|
||||
<path class="st5" d="M134.6,216.1c2.7-1.1,4.9-0.1,5.8,2.1c0.9,2.3,0,4.5-2.7,5.6c-2.7,1.1-5,0.2-5.9-2.1
|
||||
C130.9,219.4,131.9,217.2,134.6,216.1z M136.8,221.5c1.5-0.6,2.1-1.6,1.7-2.6c-0.4-1-1.5-1.3-3-0.7c-1.5,0.6-2.2,1.6-1.8,2.6
|
||||
C134.1,221.9,135.3,222.1,136.8,221.5z"/>
|
||||
<radialGradient id="SVGID_00000148647616164358038390000000096934996311696560_" cx="211.1145" cy="189.2326" r="154.4542" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="3.599497e-04" style="stop-color:#FFFFFF"/>
|
||||
<stop offset="0.9083" style="stop-color:#FFFFFF;stop-opacity:9.169579e-02"/>
|
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||
</radialGradient>
|
||||
<circle style="fill:url(#SVGID_00000148647616164358038390000000096934996311696560_);" cx="211.1" cy="189.2" r="154.5"/>
|
||||
<linearGradient id="SVGID_00000181795849749029799540000017664282943098263974_" gradientUnits="userSpaceOnUse" x1="201.3407" y1="294.9478" x2="220.3445" y2="87.1506">
|
||||
<stop offset="0" style="stop-color:#5760A9"/>
|
||||
<stop offset="0.5157" style="stop-color:#ADB3D9"/>
|
||||
<stop offset="0.6156" style="stop-color:#BEC4E2"/>
|
||||
<stop offset="0.7199" style="stop-color:#BBC1DF"/>
|
||||
<stop offset="0.8218" style="stop-color:#B0B7D7"/>
|
||||
<stop offset="0.9223" style="stop-color:#9FA6CA"/>
|
||||
<stop offset="1" style="stop-color:#8D95BD"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_00000181795849749029799540000017664282943098263974_);" d="M397.7,131.5L314,95.7L85.6,142.5l-2.7-4.6
|
||||
l-4.4,0.8l-2-4.5c0,0-0.8-2.1,2.2-1.8c3,0.3,4.7,0.2,10.6-3.7c5.9-3.9,2.3-2.2,2.8-5.5c0.5-3.3-5.2-6.1-11.5-10.7
|
||||
c-6.3-4.6-12.4-5.9-14.1-2.7c-4.9,11,1.7,17.2,1.7,17.2l3.9,3.3l-0.6,2.1l2.7,7.4l-4,0.7l-1,5.4l-46.2,9.5l1.3,19.3
|
||||
c-0.3-0.6,0.8,1.9-0.8,2c-3.1,0.1-5.7,0.5-8.1,1.6c-5.4,2.4-9.5,7-11.2,12.6C2.4,196.4,5,203.4,10,207c3.3,2.4,5.2,4.1,8.9,3.4
|
||||
c0.8,0.2,1.2,0,2,0c1,0,3-0.1,3.8-0.5c1,0.1,1.3,1,1.4-0.3c0-0.1,1.6,0.1,1.6,0c0.1-0.1-0.3,1.8-0.1,1.7l-0.5,3.8
|
||||
c-5.1,0.8-10.1,2.8-13.7,6.6c-4,4.3-5.4,9.6-4.9,15.3c0.4,5.2,1.3,9.2,6.7,11.3c2.9,1.1,6.6,2.3,9.5,1.5c1.6-0.4,4.5-0.2,6.1-0.6
|
||||
l1.2,9l44.4,25.4l276.3-52.7l67.8-67.9L397.7,131.5z M26.2,202.7c0-0.2,0-0.4,0-0.6L26.2,202.7C26.2,202.7,26.2,202.7,26.2,202.7z
|
||||
M28,229.2l0.1,0.9c-0.2-0.2-0.3-0.3-0.5-0.4C27.7,229.5,27.9,229.4,28,229.2z M27.2,233.9c0,0-0.1,0-0.1,0c0.4-0.4,0.7-0.8,1.1-1.1
|
||||
c0.1-0.1,0.1-0.1,0.1-0.2l0.1,1.1C28,233.6,27.6,233.7,27.2,233.9z M28.8,244.6c0.1-0.1,0.1-0.2,0.2-0.3c0-0.1,0.1-0.3,0.1-0.4
|
||||
l0,0.7C29,244.5,28.9,244.6,28.8,244.6z"/>
|
||||
<linearGradient id="SVGID_00000152227878615532122350000012236979203658928007_" gradientUnits="userSpaceOnUse" x1="318.3721" y1="135.4384" x2="340.2567" y2="95.2667" gradientTransform="matrix(0.921 -3.872472e-02 0 1 31.6061 15.4856)">
|
||||
<stop offset="0" style="stop-color:#B263A4"/>
|
||||
<stop offset="2.387382e-02" style="stop-color:#B465A4"/>
|
||||
<stop offset="0.7022" style="stop-color:#E5A177"/>
|
||||
<stop offset="0.9988" style="stop-color:#FAB84D"/>
|
||||
</linearGradient>
|
||||
<polygon style="fill:url(#SVGID_00000152227878615532122350000012236979203658928007_);" points="312.1,97 315.4,129.8 367,120.3
|
||||
"/>
|
||||
<g>
|
||||
<path class="st9" d="M422.2,162.2c-0.3-1.1-1.1-1.9-1.7-2.8c-0.8-1-1.6-2-2.3-3.1c-2.6-3.4-4.4-6.6-7-10c-1.6-2.1-3-4.2-4.6-6.4
|
||||
c-1.3-1.9-4.9-6.9-7.8-9.6c-1.6-1.4-11-5.7-19.1-9.2C352.7,54.5,287.3,7.3,211.1,7.3c-87.4,0-160.5,62-177.8,144.4c0,0-0.1,0-0.1,0
|
||||
c-1.2,0.3-2.4,0.5-3.6,0.8c-0.9,0.2-1.9,0.4-2.8,0.6c-0.7,0.1-1.4,0.3-2,0.4c-0.4,0.1-0.8,0.2-1.2,0.2c-0.1,0-0.2,0-0.3,0.1
|
||||
l-1.7,0.2l0.2,1.8l1.5,18.7c-0.7,0.1-1.5,0.3-2.2,0.4c-0.9,0.2-1.8,0.4-2.7,0.5c-4.8,0.8-9,3.5-11.9,7.6c-2.9,4.1-4.2,9-3.5,13.9
|
||||
c0.6,4.9,3.1,9.2,6.9,12.1c3.2,2.5,7.1,3.7,11.1,3.5c0.7,0,1.5-0.1,2.2-0.2l1.7-0.3c0.5-0.1,0.9-0.2,1.4-0.3l0.2,2.4
|
||||
c-0.6,0.1-1.1,0.2-1.7,0.3c-0.9,0.2-1.8,0.4-2.7,0.5c-4.8,0.8-9,3.5-11.9,7.6c-2.9,4.1-4.2,9-3.5,13.9c1.2,9.4,9,16,18,15.6
|
||||
c0.7,0,1.4-0.1,2.2-0.2l1.7-0.3c0.3-0.1,0.6-0.1,0.9-0.2l0.5,6.4l0.2,1.1l0.8,0.4l17.6,10.1c29.7,59.9,91.5,101.3,162.9,101.3
|
||||
c98.8,0,179.5-79.3,181.6-177.7c1.3-1.3,2.7-2.6,4-4c2.7-2.6,5.4-5.3,8.1-7.9c2.3-2.3,4.7-4.6,7-6.9c2.1-2.1,4.2-4.2,6.3-6.2
|
||||
c1-1,2-1.9,3-2.9C421.9,164.3,422.5,163.3,422.2,162.2z M211.1,12.3c72.3,0,134.6,43.7,161.9,106.1c-7-3-14.1-5.9-21.1-8.9
|
||||
c-8.4-3.6-16.9-7.1-25.3-10.7c-2.5-1.1-5-2.1-7.5-3.2c-1.3-0.5-2.5-1.1-3.8-1.6c-1.1-0.5-2.4-1.2-3.6-1c-0.2,0-0.3,0.1-0.5,0.1
|
||||
c-0.5,0.1-1.1,0.2-1.6,0.3c-0.8,0.2-1.6,0.3-2.4,0.5c-1.1,0.2-2.2,0.5-3.2,0.7c-1.3,0.3-2.7,0.6-4,0.8c-1.6,0.3-3.1,0.7-4.7,1
|
||||
c-1.8,0.4-3.6,0.7-5.3,1.1c-2,0.4-4,0.8-6,1.3c-2.2,0.5-4.4,0.9-6.5,1.4c-2.4,0.5-4.7,1-7.1,1.5c-2.5,0.5-5,1.1-7.5,1.6
|
||||
c-2.7,0.6-5.3,1.1-8,1.7c-2.8,0.6-5.6,1.2-8.4,1.8c-2.9,0.6-5.8,1.2-8.7,1.8c-3,0.6-6,1.3-9.1,1.9c-3.1,0.7-6.2,1.3-9.3,2
|
||||
c-3.2,0.7-6.4,1.3-9.6,2c-3.2,0.7-6.5,1.4-9.7,2.1c-3.3,0.7-6.6,1.4-9.9,2.1c-3.3,0.7-6.7,1.4-10,2.1c-3.3,0.7-6.7,1.4-10,2.1
|
||||
c-3.3,0.7-6.7,1.4-10,2.1c-3.3,0.7-6.7,1.4-10,2.1c-3.3,0.7-6.6,1.4-9.9,2.1c-3.3,0.7-6.5,1.4-9.8,2.1c-3.2,0.7-6.4,1.4-9.7,2
|
||||
c-3.1,0.7-6.3,1.3-9.4,2c-3.1,0.6-6.1,1.3-9.2,1.9c-3,0.6-5.9,1.3-8.9,1.9c-2.4,0.5-4.8,1-7.2,1.5c-0.7-1.2-1.5-2.3-2.5-3.2
|
||||
c-0.2-0.2-0.5-0.2-0.8-0.2c-0.3-0.3-0.7-0.3-1.1-0.2c-0.9,0.2-1.7,0.4-2.6,0.5c-0.7-1.4-1.3-2.9-1.8-4.4c6.3,1,12.7-1.9,16.6-7.4
|
||||
c0.3-0.4,0.2-0.8-0.1-1c0-1.9-1.7-4.2-3.6-6.1c0.6-1.1,1.3-2.1,1.8-3.2c0.7-0.1,1.3-0.5,1.6-1.1c0.6-1.2-0.1-2.7-1.4-3.1
|
||||
c-1.3-0.4-3.1,1.1-2.3,2.5c0,0.3,0.1,0.5,0.2,0.8c-0.6,0.9-1.1,1.7-1.6,2.6c-1.4-1.2-2.7-2.2-3.4-2.8c-3.1-2.2-13.4-9.7-18-6.5
|
||||
c-0.3,0-0.6,0.1-0.7,0.4c-0.1,0.2-0.2,0.4-0.3,0.6c-0.1,0.1-0.1,0.2-0.2,0.4c-3.8,7.4-2.1,16.7,5.2,21.5c0.1,0,0.2,0.1,0.2,0.1
|
||||
c-0.2,0.3-0.4,0.7-0.5,1.1c-0.2,0.2-0.2,0.5-0.1,0.8c0,0.1,0,0.1,0.1,0.2c0,0.6,0.3,1.2,0.6,1.7c0.5,1.5,1.1,3,1.6,4.4
|
||||
c-0.9,0.2-1.8,0.4-2.7,0.7c-0.4,0-0.8,0.2-1,0.6c-0.5,1.4-1.1,2.7-1.4,4.2c-2.2,0.5-4.4,0.9-6.5,1.4c-2.3,0.5-4.5,1-6.8,1.4
|
||||
c-2.1,0.4-4.2,0.9-6.2,1.3c-1.9,0.4-3.8,0.8-5.7,1.2c-1.3,0.3-2.6,0.5-3.9,0.8C56.3,71.6,126.9,12.3,211.1,12.3z M312.1,97
|
||||
L312.1,97l10.6,4.4c-0.1,0.1-0.2,0.3-0.3,0.4c-0.1,0.2-0.3,0.4-0.5,0.6c0,0-0.2,0.2-0.3,0.3c-0.1,0.1-0.3,0.3-0.3,0.4
|
||||
c-0.2,0.2-0.3,0.4-0.5,0.6c-0.3,0.4-0.7,0.8-1.1,1.1c-0.7,0.7-1.4,1.4-2.2,2c0,0-0.4,0.3-0.4,0.3c-0.1,0.1-0.3,0.2-0.4,0.3
|
||||
c-0.4,0.3-0.9,0.6-1.3,0.9c-0.6,0.4-1.3,0.8-2,1.1L312.1,97z M327.3,115.9c3.5-1.8,8.4-4.4,11.4-7.8l6.6,2.8c0,0.1,0,0.2,0,0.3
|
||||
c0,0.3,0,0,0,0.4c-0.1,0.3-0.1,0.7-0.2,1c-0.3,1.2-0.6,1.8-1.3,2.9c-1.2,2-3.1,3.9-4.9,5.2c-3.3,2.3-6.8,4.2-10.3,6.3l-12.7,2.6
|
||||
l-0.4-3.8C317.4,121.1,323.1,118.1,327.3,115.9z M359.2,116.8l6.4,2.7l-7.2,1.5C358.8,119.6,359.1,118.2,359.2,116.8z M70.8,141.6
|
||||
c3.9-0.5,7.7-1.3,11.5-2.2c0.1,0,0.1-0.1,0.2-0.1c0.3,0.7,0.6,1.3,1,1.9c-2.4,0.5-4.7,1-7.1,1.5c-2.2,0.5-4.3,0.9-6.5,1.4
|
||||
C70.2,143.2,70.5,142.4,70.8,141.6z M66.3,112.9c0.7,1.2,1.7,2.4,2.8,3.5c-1.3,2-1.6,4.7-1.3,7.1c0.1,0.5,0.2,1.2,0.4,1.9
|
||||
C65.6,121.8,65.1,117.2,66.3,112.9z M84,115.9c0.6,0.5,1.9,1.7,3.3,3c-0.3,0.5-0.5,0.9-0.8,1.4c-0.8,1.3-1.7,2.7-2.2,4.1
|
||||
c-1.1-0.5-2.2-1-3.3-1.6c-0.2-0.5-0.7-0.8-1.1-0.7c-1.6-1-3.2-2-4.6-3.1c0,0-0.1-0.1-0.1-0.1c0.1-0.9,0-1.8,0.1-2.7
|
||||
c0.3-1.6,1.2-2.8,2-4.1c0.1-0.2,0.1-0.4,0.1-0.6C79.6,112.8,81.9,114.4,84,115.9z M76.3,131c0-0.1-0.1-0.1-0.1-0.1
|
||||
c0.9-0.5,1.6-1.8,2.2-2.6c0.7-1.1,1.4-2.3,2-3.5c2,1.1,4.1,2.2,6.1,2.7c-0.9,0.9-1.8,1.6-2.9,2.2c-1.3,0.7-2.7,0.9-3.9,1.7
|
||||
C78.6,131.4,77.4,131.3,76.3,131z M88.6,127.9c0.2,0,0.3,0,0.5,0c-0.5,0.4-1.1,0.8-1.6,1.1C87.9,128.7,88.3,128.3,88.6,127.9z
|
||||
M87.8,125.5c-0.6-0.1-1.3-0.3-1.9-0.5c0.9-1.1,1.6-2.5,2.3-3.7c0.2-0.3,0.3-0.5,0.5-0.8C91.3,123.5,92.8,126.5,87.8,125.5z
|
||||
M76,111.3c-1.3,1.1-2,3-2.3,4.6c-0.1,0.5-0.2,1.1-0.2,1.8c-3.2-3-8.8-9.1-3-8.3c2,0.3,3.9,0.9,5.8,1.8
|
||||
C76.2,111.2,76.1,111.2,76,111.3z M69.7,123.8c-0.4-2.2,0.1-4.1,0.7-6.2c1.6,1.4,3.1,2.5,3.8,3.1c0.9,0.7,2.6,1.9,4.5,3.1
|
||||
c-0.5,1.2-1,2.3-1.7,3.4c-0.5,0.9-1.5,1.9-1.8,2.9c-0.6-0.8-1.7-0.9-2.6-0.6c-0.3-0.2-0.6-0.3-0.8-0.5c-0.3-0.2-0.5-0.4-0.7-0.6
|
||||
C71.3,126.9,70,125.3,69.7,123.8z M74.3,132.4c0.1,0.2,0.1,0.4,0,0.6c-0.2,0.5-0.9,0.5-1.3,0.2c-0.5-0.3-0.5-1-0.2-1.5
|
||||
C73.3,132,73.8,132.2,74.3,132.4z M73.7,135.7c0.8,0,1.5-0.3,2.1-0.8c0.4,1,0.8,2,1.3,3c-0.8,0.2-1.6,0.4-2.4,0.6
|
||||
C74.4,137.5,74,136.6,73.7,135.7z M91.7,113.1C91.7,113.1,91.7,113.1,91.7,113.1c0.1,0.1,0.2,0.2,0.1,0.3c0,0,0,0-0.1,0
|
||||
c-0.1,0-0.1-0.1-0.2-0.1C91.5,113.2,91.6,113.1,91.7,113.1z M12.3,206.2c0.4-0.1,0.7-0.3,1.1-0.4c0.5-0.2,1-0.6,1.5-0.8
|
||||
c0.4-0.2,0.1-0.7-0.3-0.7c-0.6,0.1-1.1,0.1-1.7,0.2c-0.5,0.1-1.1,0.2-1.6,0.4c-0.1,0-0.3,0.1-0.4,0.1c-1.2-1.2-2.2-2.5-2.9-4
|
||||
c0.3-0.1,0.5-0.2,0.8-0.3c0.5-0.2,1.1-0.4,1.6-0.7c0.5-0.2,1-0.6,1.5-0.8c0.4-0.2,0.1-0.7-0.3-0.7c-0.6,0.1-1.1,0.1-1.7,0.2
|
||||
c-0.5,0.1-1.1,0.2-1.6,0.4c-0.3,0.1-0.6,0.2-0.9,0.3c-0.3-1-0.6-2-0.7-3c-0.1-0.7-0.1-1.4-0.1-2.2c0.4-0.2,0.9-0.3,1.3-0.5
|
||||
c0.5-0.2,1.1-0.4,1.6-0.7c0.5-0.2,1-0.6,1.5-0.8c0.4-0.2,0.1-0.7-0.3-0.7c-0.6,0.1-1.1,0.1-1.7,0.2c-0.5,0.1-1.1,0.2-1.6,0.4
|
||||
c-0.2,0.1-0.4,0.1-0.7,0.2c0.2-1.5,0.6-3.1,1.3-4.5c0.2,0,0.3,0,0.5,0c0.3-0.1,0.5-0.1,0.8-0.2c0.5-0.1,1-0.3,1.4-0.4
|
||||
c0.5-0.1,1-0.3,1.4-0.4c0.5-0.2,1-0.4,1.5-0.6c0.4-0.1,0.4-0.8-0.1-0.8c-0.3,0-0.5,0-0.8,0c-0.3,0-0.5,0-0.8,0
|
||||
c-0.5,0.1-1.1,0.1-1.6,0.3c-0.4,0.1-0.9,0.2-1.3,0.3c0.2-0.2,0.3-0.5,0.5-0.7c2.1-2.9,5-4.9,8.2-5.7c-0.8,1.2-1.5,2.4-2.1,3.7
|
||||
c-1.4,3.2-2.1,6.7-2,10.1c0.1,3.3,1.1,6.6,2.7,9.5c0.8,1.6,1.9,3,3,4.4c0.3,0.4,0.7,0.9,1.1,1.4C17.4,208.8,14.6,207.9,12.3,206.2z
|
||||
M24.3,208.3l-0.7,0.1c-0.6-0.9-1.6-1.6-2.2-2.4c-1-1.2-1.9-2.5-2.7-3.9c-1.5-2.7-2.4-5.7-2.6-8.7c-0.1-3.2,0.5-6.3,1.8-9.2
|
||||
c0.7-1.5,1.5-2.9,2.4-4.3c0.2-0.3,0.5-0.7,0.7-1c0.2,0,0.4-0.1,0.6-0.1c0.7-0.1,1.3-0.2,1.9-0.4l2.3,29.6
|
||||
C25.3,208.1,24.8,208.2,24.3,208.3z M15.9,245.7c0.5-0.2,1-0.4,1.4-0.6c0.5-0.2,1-0.6,1.5-0.8c0.4-0.2,0.1-0.7-0.3-0.7
|
||||
c-0.6,0.1-1.1,0.1-1.7,0.2c-0.5,0.1-1.1,0.2-1.6,0.4c-0.3,0.1-0.6,0.2-0.9,0.3c-1.2-1.2-2.2-2.6-3-4.2c0.4-0.2,0.9-0.3,1.3-0.5
|
||||
c0.5-0.2,1.1-0.4,1.6-0.7c0.5-0.2,1-0.6,1.5-0.8c0.4-0.2,0.1-0.7-0.3-0.7c-0.6,0.1-1.1,0.1-1.7,0.2c-0.5,0.1-1.1,0.2-1.6,0.4
|
||||
c-0.5,0.1-0.9,0.3-1.4,0.4c-0.3-0.9-0.5-1.8-0.6-2.8c-0.1-1.1-0.2-2.1-0.1-3.2c0.1,0,0.2-0.1,0.3-0.1c0.5-0.2,1.1-0.3,1.6-0.5
|
||||
c0.5-0.2,1.1-0.4,1.6-0.6c0.5-0.2,0.9-0.6,1.4-0.8c0.3-0.2,0.2-0.7-0.2-0.7c-0.5,0.1-1.1,0-1.6,0.1c-0.6,0.1-1.2,0.2-1.7,0.3
|
||||
c-0.4,0.1-0.8,0.2-1.1,0.3c0.4-1.9,1.1-3.6,2.2-5.3c0.1,0,0.1,0,0.2,0c0.3-0.1,0.5-0.1,0.8-0.2c0.5-0.1,1-0.3,1.4-0.4
|
||||
c0.5-0.1,1-0.3,1.4-0.4c0.5-0.2,1-0.4,1.5-0.6c0.4-0.1,0.4-0.8-0.1-0.8c-0.3,0-0.5,0-0.8,0c-0.3,0-0.5,0-0.8,0
|
||||
c-0.5,0.1-1.1,0.1-1.6,0.3c-0.1,0-0.3,0.1-0.4,0.1c2.2-2.4,5.1-4,8.3-4.6c0,0,0,0,0.1,0c-0.4,0.5-0.7,1.1-1,1.6
|
||||
c-0.8,1.4-1.5,2.9-2.1,4.5c-1.1,3.2-1.4,6.7-0.9,10c0.4,3.2,1.5,6.2,3.2,8.9c0.8,1.3,1.8,2.6,2.9,3.8c0.2,0.2,0.4,0.4,0.6,0.6
|
||||
C21.7,248.6,18.5,247.6,15.9,245.7z M28.4,247.7c-0.7-0.6-1.4-1.1-2-1.7c-1-1-1.8-2.1-2.5-3.2c-1.6-2.5-2.6-5.3-3-8.2
|
||||
c-0.4-3-0.1-6,0.8-8.9c0.4-1.5,1-2.8,1.7-4.2c0.6-1,1.5-2.1,1.8-3.3c0,0,0,0,0,0c0.5-0.1,0.9-0.2,1.4-0.3l2.3,29.6
|
||||
C28.7,247.7,28.6,247.7,28.4,247.7z M25.7,157.2l282.7-59.5c0.5,4,0.9,7.9,1.4,11.9c0.7,6.2,1.4,12.4,2.1,18.6c0.1,1,0.3,6,2,5.6
|
||||
c0.5-0.1,1.1-0.2,1.6-0.3c1.7-0.4,3.5-0.7,5.2-1.1c5.3-1.1,10.7-2.2,16-3.3c6-1.2,12-2.4,18-3.7c4.6-0.9,9.1-1.9,13.7-2.8
|
||||
c1.2-0.2,2.4-0.5,3.6-0.7l23.3,10.4L325,198.2L33.4,255.5L25.7,157.2z M325.2,202.1l23.2,27.2L76.3,281.1l-39.2-22.5L325.2,202.1z
|
||||
M211.1,365.8c-66.6,0-124.7-37.1-154.8-91.6L75,284.8l0.7,0.2h0.6c0.7-0.1,1.3-0.3,2-0.4c1.9-0.4,3.8-0.7,5.7-1.1
|
||||
c3-0.6,6-1.2,9.1-1.7c4-0.8,8-1.5,12-2.3c4.8-0.9,9.6-1.8,14.5-2.8c5.5-1.1,11-2.1,16.5-3.2c6.1-1.2,12.1-2.3,18.2-3.5
|
||||
c6.5-1.2,13-2.5,19.4-3.7c6.8-1.3,13.5-2.6,20.3-3.9c6.9-1.3,13.8-2.6,20.7-3.9c6.9-1.3,13.8-2.6,20.7-3.9
|
||||
c6.7-1.3,13.5-2.6,20.2-3.9c6.5-1.2,12.9-2.5,19.4-3.7c6-1.2,12.1-2.3,18.1-3.5c5.5-1,11-2.1,16.5-3.1c4.8-0.9,9.6-1.8,14.4-2.7
|
||||
c4-0.8,7.9-1.5,11.9-2.3c3-0.6,6-1.1,9-1.7c1.9-0.4,3.8-0.7,5.6-1.1c1.2-0.2,2.3-0.3,3.2-1.2c1.6-1.6,3.2-3.2,4.8-4.8
|
||||
c1.9-1.9,3.8-3.8,5.7-5.7c2.4-2.4,4.8-4.7,7.2-7.1c2.7-2.7,5.4-5.3,8.1-8c2.6-2.6,5.3-5.2,7.9-7.8
|
||||
C382.7,291.4,305.5,365.8,211.1,365.8z M352.1,227.7l-23.5-27.6l68.9-64.5l20.6,27.1L352.1,227.7z"/>
|
||||
<path class="st9" d="M180.7,145.3l6.5,65.1l27.8-4.7l-5.8-65.5L180.7,145.3z M188.9,208.2l-6.1-61.3l24.7-4.4l5.5,61.6L188.9,208.2
|
||||
z"/>
|
||||
<path class="st9" d="M150.8,168.3l4.4,48.5l20.4-4.2l-4.6-48.2L150.8,168.3z M156.9,214.5l-4.1-44.7l16.4-3.1l4.1,44.4L156.9,214.5
|
||||
z"/>
|
||||
<path class="st9" d="M120.2,199.8l2.5,24l28.7-6.4l-1.9-24.7L120.2,199.8z M124.5,221.4l-2.1-20.2l25.4-6.1l1.6,20.8L124.5,221.4z"
|
||||
/>
|
||||
<path class="st9" d="M40.5,215.3l2.9,27.8l22.4-3.3l-2.5-28.5L40.5,215.3z M45.2,240.9l-2.5-24l19-3.3l2.2,24.6L45.2,240.9z"/>
|
||||
<path class="st9" d="M308.3,222.2l-10.7-7.4l-25.9,4.3l10.7,7.4L308.3,222.2z M297.3,216.3l7.3,5l-21.8,3.7l-7.3-5L297.3,216.3z"/>
|
||||
<path class="st9" d="M295.2,236.7l25.9-4.3l-10.7-7.4l-25.9,4.3L295.2,236.7z M317.4,231.5l-21.8,3.7l-7.3-5l21.8-3.7L317.4,231.5z
|
||||
"/>
|
||||
<path class="st9" d="M88.7,275.9l25.9-4.3l-10.7-7.4l-25.9,4.3L88.7,275.9z M110.8,270.8L89,274.4l-7.3-5l21.8-3.7L110.8,270.8z"/>
|
||||
<path class="st9" d="M91.3,254.3l-25.9,4.3l10.7,7.4l25.9-4.3L91.3,254.3z M69.1,259.4l21.8-3.7l7.3,5l-21.8,3.7L69.1,259.4z"/>
|
||||
<path class="st9" d="M245.4,175l-2.8-36c-0.2-2-1.9-3.5-3.9-3.3c-1,0.1-1.9,0.5-2.5,1.3c-0.6,0.7-0.9,1.7-0.9,2.6l2.9,36.7
|
||||
l-1.9,0.3l-2.8-35.8c-0.1-1-0.5-1.9-1.3-2.5c-0.7-0.6-1.7-0.9-2.6-0.9c-1,0.1-1.8,0.5-2.5,1.3c-0.6,0.7-0.9,1.7-0.9,2.6l2.9,36.5
|
||||
l-1.9,0.3l-2.7-35.1c-0.2-2-1.9-3.5-3.9-3.3c-1,0.1-1.9,0.5-2.5,1.3c-0.6,0.7-0.9,1.7-0.9,2.6l2.8,35.7l-1.5,0.3l2.5,24.2l28.1-4.3
|
||||
l-1.9-24.8L245.4,175z M237.2,139.4c0-0.5,0.1-0.9,0.4-1.2c0.3-0.3,0.7-0.6,1.2-0.6c0,0,0.1,0,0.1,0c0.9,0,1.6,0.7,1.7,1.6
|
||||
l2.8,36.2l-3.4,0.6L237.2,139.4z M228.2,141.1c0-0.5,0.1-0.9,0.4-1.2c0.3-0.3,0.7-0.6,1.2-0.6h0c0,0,0.1,0,0.1,0
|
||||
c0.4,0,0.8,0.1,1.1,0.4c0.3,0.3,0.6,0.7,0.6,1.2l2.8,36l-3.4,0.6L228.2,141.1z M219.1,143.4c0-0.5,0.1-0.9,0.4-1.2
|
||||
c0.3-0.3,0.7-0.6,1.2-0.6c0,0,0.1,0,0.1,0c0.9,0,1.6,0.7,1.7,1.6l2.8,35.3l-3.4,0.6L219.1,143.4z M222.6,201.5l-2.1-20.4l24.8-4.2
|
||||
l1.6,20.9L222.6,201.5z"/>
|
||||
<path class="st9" d="M99.7,179c0.2-2.1-2.5-3-4.1-2.1c-1.1,0.7-1.8,2.1-1.5,3.3c-1.6-0.8-3.5,0-5.3,0.3c-2.6,0.4-5.2,0.9-7.8,1.5
|
||||
c0.1-2.5-0.1-5-0.3-7.4c2.6-0.2,5.3-0.6,7.9-1.1c0.2,0,0.3-0.1,0.4-0.2c1.1,1.3,3.5,1.5,4.5,0c0.4-0.6,0.6-1.6,0.4-2.5
|
||||
c0,0,0,0,0-0.1c0.2-2.1-2.5-3-4.1-2.1c-1,0.6-1.6,1.9-1.6,3c-0.1,0-0.2,0-0.2,0c-2.5,0.4-5,0.8-7.5,1.4c0-0.2,0-0.4-0.1-0.6
|
||||
c-0.2-2.4-0.3-5-1.2-7.2c2.7-0.3,5.3-0.6,8-1c1.9-0.3,4.5-0.1,5.8-1.8c0.1,0.4,0.2,0.7,0.4,1c1.1,1.4,3.6,1.7,4.6,0.2
|
||||
c0.4-0.6,0.6-1.6,0.4-2.5c0,0,0,0,0-0.1c0.2-2.1-2.5-3-4.1-2.1c-1.1,0.6-1.7,2-1.5,3.2c-1.6-1.2-3.8-0.2-5.7,0.1
|
||||
c-2.9,0.5-5.7,1-8.5,1.6c-0.7,0.2-0.6,1.2,0,1.3c-0.2,0.7-0.3,1.4-0.3,2.1c-1.8-0.4-3.7,0.3-5.6,0.7c-3.4,0.6-6.9,1.2-10.3,1.9
|
||||
c-0.7,0.1-0.6,1.2,0,1.3c-0.6,4.3,0.1,8.7,0.4,12.9c0.3,4.4,0.6,8.7,1.4,13c-1.7-0.4-3.6-0.2-5.4,0.2c0.1-1.4-0.1-2.7-0.3-4.1
|
||||
c-0.1-1-0.1-2.1-0.4-3.1c0.5-0.1,1-0.2,1.5-0.2c0.4-0.1,0.7-0.5,0.7-0.9c-0.2-2.5-0.4-5.1-0.6-7.6c0-0.5-0.4-1-0.9-0.9
|
||||
c-5.9,0.7-10.8-2.7-11.6-8.7c0-0.1,0-0.1,0-0.1c0,0,0,0,0,0c0-0.1-0.1-0.2-0.1-0.3c0-0.1-0.1-0.1-0.1-0.2c0,0,0,0-0.1-0.1
|
||||
c-0.2-0.2-0.5-0.3-0.8-0.2c-2.5,0.4-5.1,0.8-7.6,1.2c-0.4,0.1-0.7,0.5-0.7,0.9c0.5,6.4,1.1,12.7,1.6,19.1c0.1,0.7,0.6,1,1.2,0.9
|
||||
c0.4-0.1,0.8-0.1,1.1-0.2c-0.1,0.9,0,1.8,0.1,2.7c0.1,1.8,0.2,3.7,0.8,5.4c0,0.4,0.2,0.9,0.6,0.8c3.7-0.5,7.4-1,11.1-1.5
|
||||
c3.2-0.5,7.3-0.5,10.1-2.2c0.1,0.5,0.9,0.4,0.9-0.1c0.1-4.9-0.4-9.7-0.8-14.6c-0.3-4-0.4-8.1-1.6-11.9c3-0.3,6-0.7,9-1.2
|
||||
c2-0.3,4.5-0.3,6.4-1.2c0.1,1.7,0.3,3.4,0.4,5c0.2,2.9,0.4,5.7,1,8.5c-0.2,0.4,0,1.1,0.6,1.1c2.8-0.3,5.5-0.7,8.3-1.1
|
||||
c1.8-0.3,4.2-0.1,5.5-1.5c0.1,0.2,0.1,0.3,0.2,0.4c1.1,1.4,3.6,1.7,4.6,0.2C99.7,180.9,99.9,179.9,99.7,179
|
||||
C99.7,179,99.7,179,99.7,179z M90.9,170.5c0.7-0.5,1.2,0.1,1.5,0.7c0,0.3,0,0.5-0.2,0.8c-0.3,0.6-1.2,0.6-1.6,0.1
|
||||
C90.1,171.7,90.4,170.8,90.9,170.5z M95.5,160.8c0.7-0.5,1.2,0.1,1.5,0.7c0,0.3,0,0.5-0.2,0.8c-0.3,0.6-1.2,0.6-1.6,0.1
|
||||
C94.8,162,95,161.2,95.5,160.8z M40.1,174.1c0-0.1,0-0.1,0-0.2c1.8,0.1,4-0.5,5.9-1c1.3,6,6.1,9.8,12.3,9.5c0,1.9-0.1,4.2,0.5,5.8
|
||||
c-0.1,0-0.1,0-0.2,0c-1-0.1-2.6,0.4-3.6,0.6c-4.5,0.7-9,1.5-13.4,2.2c-0.4-4.5-0.7-9-1.1-13.5C40.3,176.6,40.5,175.1,40.1,174.1z
|
||||
M49.6,191.6c-0.1,0.9,0,2,0.1,2.9c0.1,1.6,0.1,3.1,0.5,4.6c-2,0.4-4.1,0.7-6.1,1.1c0.1-1.6-0.1-3.1-0.2-4.7
|
||||
c-0.1-0.9-0.1-2-0.4-2.9C45.5,192.3,47.6,192,49.6,191.6z M51.7,198.9c0.1-1.4-0.1-2.9-0.3-4.3c-0.1-1-0.1-2.1-0.4-3.1
|
||||
c2.1-0.3,4.1-0.7,6.2-1c-0.1,0.9,0,2,0.1,2.9c0.1,1.5,0.1,3,0.5,4.4c-0.7,0.1-1.3,0.3-2,0.4C54.4,198.4,53,198.6,51.7,198.9z
|
||||
M97.9,180.2c-0.3,0.6-1.2,0.6-1.6,0.1c-0.4-0.5-0.2-1.3,0.3-1.7c0.7-0.5,1.2,0.1,1.5,0.7C98.1,179.6,98.1,179.9,97.9,180.2z"/>
|
||||
<path class="st9" d="M293.1,170.4c-5.6,0.8-11.1,1.6-16.7,2.4c0.2-6.9-0.6-14.5-2.3-21.1c0.5-0.2,0.9-0.4,1.2-0.9
|
||||
c0.4-0.6,0.6-1.6,0.4-2.5c0,0,0,0,0-0.1c0.2-2.1-2.5-3-4.1-2.1c-1.5,0.9-2.1,3.1-1,4.5c0.6,0.8,1.7,1.3,2.8,1.2
|
||||
c-0.6,6.8-0.1,14.5,1.3,21.2c-2.4,0.4-4.7,0.8-7.1,1.2c0.2-4-0.3-8.1-0.7-12.1c-0.3-2.8-0.4-5.5-1.3-8.1c0.6-0.1,1.2-0.4,1.5-0.9
|
||||
c0.4-0.6,0.6-1.6,0.4-2.5c0,0,0,0,0-0.1c0.2-2.1-2.5-3-4.1-2.1c-1.5,0.9-2.1,3.1-1,4.5c0.5,0.7,1.3,1.1,2.1,1.2
|
||||
c-0.5,3.2-0.1,6.6,0.2,9.8c0.3,3.6,0.5,7.2,1.2,10.7c-2.2,0.4-4.5,0.8-6.7,1.3c-0.1-7-0.4-15-2.3-21.8c0.5-0.2,0.9-0.4,1.2-0.9
|
||||
c0.4-0.6,0.6-1.6,0.4-2.5c0,0,0,0,0-0.1c0.2-2.1-2.5-3-4.1-2.1c-1.5,0.9-2.1,3.1-1,4.5c0.5,0.7,1.5,1.2,2.4,1.2
|
||||
c-0.7,7.3,0.3,15.7,1.5,22.7c0.1,0.5,0.5,0.7,0.9,0.7c0.1,0.1,0.3,0.2,0.6,0.2c11.5-1.4,23-3.3,34.4-5.4c-0.4,3.7,0.1,7.7,0.5,11.3
|
||||
c0,0.1,0,0.2,0.1,0.2c-2.7,0-5.4,0.5-8,1c-1.9,0.3-4.1,0.4-5.8,1.4c-0.9-0.8-2.4-1-3.4-0.4c-1.5,0.9-2.1,3.1-1,4.5
|
||||
c1.1,1.4,3.6,1.7,4.6,0.2c0.4-0.6,0.6-1.6,0.4-2.5c0,0,0,0,0-0.1c0-0.2,0-0.3,0-0.5c1.5,0.1,3-0.2,4.5-0.5c3-0.5,6.2-0.8,9.1-1.8
|
||||
c0.3-0.1,0.5-0.4,0.5-0.7c0.4,0,0.7-0.3,0.7-0.8c-0.2-3.8-0.3-8.1-1.5-11.8C294.6,171.2,294,170.2,293.1,170.4z M272.4,149.6
|
||||
c-0.4-0.5-0.2-1.3,0.3-1.7c0.7-0.5,1.2,0.1,1.5,0.7c0,0.3,0,0.5-0.2,0.8C273.7,150.1,272.8,150.1,272.4,149.6z M264.6,150.2
|
||||
c0.7-0.5,1.2,0.1,1.5,0.7c0,0.3,0,0.5-0.2,0.8c-0.3,0.6-1.2,0.6-1.6,0.1C263.8,151.4,264.1,150.6,264.6,150.2z M255.5,151.9
|
||||
c-0.4-0.5-0.2-1.3,0.3-1.7c0.7-0.5,1.2,0.1,1.5,0.7c0,0.3,0,0.5-0.2,0.8C256.8,152.4,255.9,152.4,255.5,151.9z M279.2,189.1
|
||||
c-0.3,0.6-1.2,0.6-1.6,0.1c-0.4-0.5-0.2-1.3,0.3-1.7c0.7-0.5,1.2,0.1,1.5,0.7C279.4,188.5,279.4,188.8,279.2,189.1z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 21 KiB |
|
@ -8,6 +8,7 @@
|
|||
import EditQueryPopover from "./popovers/EditQueryPopover.svelte"
|
||||
import NavItem from "components/common/NavItem.svelte"
|
||||
import TableNavigator from "components/backend/TableNavigator/TableNavigator.svelte"
|
||||
import { customQueryIconText, customQueryIconColor } from "helpers/data/utils"
|
||||
import ICONS from "./icons"
|
||||
|
||||
let openDataSources = []
|
||||
|
@ -129,6 +130,8 @@
|
|||
<NavItem
|
||||
indentLevel={1}
|
||||
icon="SQLQuery"
|
||||
iconText={customQueryIconText(datasource, query)}
|
||||
iconColor={customQueryIconColor(datasource, query)}
|
||||
text={query.name}
|
||||
opened={$queries.selected === query._id}
|
||||
selected={$queries.selected === query._id}
|
||||
|
|
|
@ -1,12 +1,30 @@
|
|||
<script>
|
||||
import { Icon } from "@budibase/bbui"
|
||||
import { Icon, Body } from "@budibase/bbui"
|
||||
</script>
|
||||
|
||||
<a target="_blank" href="https://github.com/Budibase/budibase/discussions">
|
||||
<Icon hoverable name="Help" size="XXL" />
|
||||
<div class="inner hoverable">
|
||||
<div class="hidden hoverable">
|
||||
<Body size="S">Need help? Go to our forums</Body>
|
||||
</div>
|
||||
<Icon name="Help" size="XXL" />
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-s);
|
||||
}
|
||||
.inner :global(*) {
|
||||
pointer-events: all;
|
||||
transition: color var(--spectrum-global-animation-duration-100, 130ms);
|
||||
}
|
||||
.inner:hover :global(*) {
|
||||
color: var(--spectrum-alias-icon-color-selected-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
position: absolute;
|
||||
|
@ -14,4 +32,10 @@
|
|||
right: var(--spacing-m);
|
||||
border-radius: 55%;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.inner:hover .hidden {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
export let selected = false
|
||||
export let opened = false
|
||||
export let draggable = false
|
||||
export let iconText
|
||||
export let iconColor
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
@ -42,9 +44,13 @@
|
|||
{/if}
|
||||
|
||||
<slot name="icon" />
|
||||
{#if icon}
|
||||
{#if iconText}
|
||||
<div class="iconText" style={iconColor ? `color: ${iconColor};` : ""}>
|
||||
{iconText}
|
||||
</div>
|
||||
{:else if icon}
|
||||
<div class="icon">
|
||||
<Icon size="S" name={icon} />
|
||||
<Icon color={iconColor} size="S" name={icon} />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="text">{text}</div>
|
||||
|
@ -123,4 +129,9 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.iconText {
|
||||
margin-top: 1px;
|
||||
font-size: var(--spectrum-global-dimension-font-size-50);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
queries as queriesStore,
|
||||
} from "stores/backend"
|
||||
import { datasources, integrations } from "stores/backend"
|
||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||
import BindingBuilder from "components/integration/QueryBindingBuilder.svelte"
|
||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||
|
||||
|
@ -148,15 +148,15 @@
|
|||
/>
|
||||
{#if value?.type === "query"}
|
||||
<i class="ri-settings-5-line" on:click={openQueryParamsDrawer} />
|
||||
<Drawer title={"Query Parameters"} bind:this={drawer}>
|
||||
<Drawer title={"Query Bindings"} bind:this={drawer}>
|
||||
<Button slot="buttons" cta on:click={saveQueryParams}>Save</Button>
|
||||
<DrawerContent slot="body">
|
||||
<Layout noPadding>
|
||||
<Layout noPadding gap="XS">
|
||||
{#if getQueryParams(value).length > 0}
|
||||
<ParameterBuilder
|
||||
<BindingBuilder
|
||||
bind:customParams={tmpQueryParams}
|
||||
parameters={getQueryParams(value)}
|
||||
{bindings}
|
||||
bindings={getQueryParams(value)}
|
||||
bind:bindableOptions={bindings}
|
||||
/>
|
||||
{/if}
|
||||
<IntegrationQueryEditor
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { Select, Layout, Input, Checkbox } from "@budibase/bbui"
|
||||
import { datasources, integrations, queries } from "stores/backend"
|
||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||
import BindingBuilder from "components/integration/QueryBindingBuilder.svelte"
|
||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||
|
||||
export let parameters
|
||||
|
@ -53,10 +53,10 @@
|
|||
|
||||
{#if query?.parameters?.length > 0}
|
||||
<div>
|
||||
<ParameterBuilder
|
||||
<BindingBuilder
|
||||
bind:customParams={parameters.queryParams}
|
||||
parameters={query.parameters}
|
||||
{bindings}
|
||||
bindings={query.parameters}
|
||||
bind:bindableOptions={bindings}
|
||||
/>
|
||||
<IntegrationQueryEditor
|
||||
height={200}
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
export let headings = false
|
||||
export let options
|
||||
export let toggle
|
||||
export let keyPlaceholder = "Key"
|
||||
export let valuePlaceholder = "Value"
|
||||
export let tooltip
|
||||
|
||||
let fields = Object.entries(object).map(([name, value]) => ({ name, value }))
|
||||
let fieldActivity = []
|
||||
|
@ -76,8 +79,8 @@
|
|||
{#if Object.keys(object || {}).length > 0}
|
||||
{#if headings}
|
||||
<div class="container" class:container-active={toggle}>
|
||||
<Label>Key</Label>
|
||||
<Label>Value</Label>
|
||||
<Label {tooltip}>{keyPlaceholder}</Label>
|
||||
<Label>{valuePlaceholder}</Label>
|
||||
{#if toggle}
|
||||
<Label>Active</Label>
|
||||
{/if}
|
||||
|
@ -85,12 +88,16 @@
|
|||
{/if}
|
||||
<div class="container" class:container-active={toggle} class:readOnly>
|
||||
{#each fields as field, idx}
|
||||
<Input placeholder="Key" bind:value={field.name} on:change={changed} />
|
||||
<Input
|
||||
placeholder={keyPlaceholder}
|
||||
bind:value={field.name}
|
||||
on:change={changed}
|
||||
/>
|
||||
{#if options}
|
||||
<Select bind:value={field.value} on:change={changed} {options} />
|
||||
{:else}
|
||||
<Input
|
||||
placeholder="Value"
|
||||
placeholder={valuePlaceholder}
|
||||
bind:value={field.value}
|
||||
on:change={changed}
|
||||
/>
|
||||
|
@ -127,4 +134,7 @@
|
|||
.container-active {
|
||||
grid-template-columns: 1fr 1fr 50px 20px;
|
||||
}
|
||||
.readOnly {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Icon, Body, Button, Input, Heading, Layout } from "@budibase/bbui"
|
||||
import { Body, Button, Heading, Icon, Input, Layout } from "@budibase/bbui"
|
||||
import {
|
||||
readableToRuntimeBinding,
|
||||
runtimeToReadableBinding,
|
||||
|
@ -7,83 +7,82 @@
|
|||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||
|
||||
export let bindable = true
|
||||
export let parameters = []
|
||||
export let bindings = []
|
||||
export let bindableOptions = []
|
||||
export let customParams = {}
|
||||
|
||||
function newQueryParameter() {
|
||||
parameters = [...parameters, {}]
|
||||
function newQueryBinding() {
|
||||
bindings = [...bindings, {}]
|
||||
}
|
||||
|
||||
function deleteQueryParameter(idx) {
|
||||
parameters.splice(idx, 1)
|
||||
parameters = parameters
|
||||
function deleteQueryBinding(idx) {
|
||||
bindings.splice(idx, 1)
|
||||
bindings = bindings
|
||||
}
|
||||
|
||||
// This is necessary due to the way readable and writable bindings are stored.
|
||||
// The readable binding in the UI gets converted to a UUID value that the client understands
|
||||
// for parsing, then converted back so we can display it the readable form in the UI
|
||||
function onBindingChange(param, valueToParse) {
|
||||
const parsedBindingValue = readableToRuntimeBinding(bindings, valueToParse)
|
||||
customParams[param] = parsedBindingValue
|
||||
customParams[param] = readableToRuntimeBinding(
|
||||
bindableOptions,
|
||||
valueToParse
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout paddingX="none" gap="S">
|
||||
<div class="controls">
|
||||
<Heading size="XS">Parameters</Heading>
|
||||
<Layout noPadding={bindable} gap="S">
|
||||
<div class="controls" class:height={!bindable}>
|
||||
<Heading size="XS">Bindings</Heading>
|
||||
{#if !bindable}
|
||||
<Button secondary on:click={newQueryParameter}>Add Param</Button>
|
||||
<Button secondary on:click={newQueryBinding}>Add Binding</Button>
|
||||
{/if}
|
||||
</div>
|
||||
<Body size="S">
|
||||
{#if !bindable}
|
||||
Parameters come in two parts: the parameter name, and a default/fallback
|
||||
value.
|
||||
Bindings come in two parts: the binding name, and a default/fallback
|
||||
value. These bindings can be used as Handlebars expressions throughout the
|
||||
query.
|
||||
{:else}
|
||||
Enter a value for each parameter. The default values will be used for any
|
||||
Enter a value for each binding. The default values will be used for any
|
||||
values left blank.
|
||||
{/if}
|
||||
</Body>
|
||||
<div class="parameters" class:bindable>
|
||||
{#each parameters as parameter, idx}
|
||||
<div class="bindings" class:bindable>
|
||||
{#each bindings as binding, idx}
|
||||
<Input
|
||||
placeholder="Parameter Name"
|
||||
placeholder="Binding Name"
|
||||
thin
|
||||
disabled={bindable}
|
||||
bind:value={parameter.name}
|
||||
bind:value={binding.name}
|
||||
/>
|
||||
<Input
|
||||
placeholder="Default"
|
||||
thin
|
||||
disabled={bindable}
|
||||
bind:value={parameter.default}
|
||||
bind:value={binding.default}
|
||||
/>
|
||||
{#if bindable}
|
||||
<DrawerBindableInput
|
||||
title={`Query parameter "${parameter.name}"`}
|
||||
title={`Query binding "${binding.name}"`}
|
||||
placeholder="Value"
|
||||
thin
|
||||
on:change={evt => onBindingChange(parameter.name, evt.detail)}
|
||||
on:change={evt => onBindingChange(binding.name, evt.detail)}
|
||||
value={runtimeToReadableBinding(
|
||||
bindings,
|
||||
customParams?.[parameter.name]
|
||||
bindableOptions,
|
||||
customParams?.[binding.name]
|
||||
)}
|
||||
{bindings}
|
||||
{bindableOptions}
|
||||
/>
|
||||
{:else}
|
||||
<Icon
|
||||
hoverable
|
||||
name="Close"
|
||||
on:click={() => deleteQueryParameter(idx)}
|
||||
/>
|
||||
<Icon hoverable name="Close" on:click={() => deleteQueryBinding(idx)} />
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.parameters.bindable {
|
||||
.bindings.bindable {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
|
@ -91,13 +90,16 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.parameters {
|
||||
.bindings {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 5%;
|
||||
grid-gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.height {
|
||||
height: 40px;
|
||||
}
|
||||
</style>
|
|
@ -17,7 +17,7 @@
|
|||
import ExtraQueryConfig from "./ExtraQueryConfig.svelte"
|
||||
import IntegrationQueryEditor from "components/integration/index.svelte"
|
||||
import ExternalDataSourceTable from "components/backend/DataTable/ExternalDataSourceTable.svelte"
|
||||
import ParameterBuilder from "components/integration/QueryParameterBuilder.svelte"
|
||||
import BindingBuilder from "components/integration/QueryBindingBuilder.svelte"
|
||||
import { datasources, integrations, queries } from "stores/backend"
|
||||
import { capitalise } from "../../helpers"
|
||||
import CodeMirrorEditor from "components/common/CodeMirrorEditor.svelte"
|
||||
|
@ -120,7 +120,7 @@
|
|||
config={integrationInfo.extra}
|
||||
/>
|
||||
{/if}
|
||||
<ParameterBuilder bind:parameters={query.parameters} bindable={false} />
|
||||
<BindingBuilder bind:bindings={query.parameters} bindable={false} />
|
||||
{/if}
|
||||
</div>
|
||||
{#if shouldShowQueryConfig}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { IntegrationTypes } from "constants/backend"
|
||||
|
||||
export function schemaToFields(schema) {
|
||||
const response = {}
|
||||
if (schema && typeof schema === "object") {
|
||||
|
@ -49,3 +51,60 @@ export function buildQueryString(obj) {
|
|||
}
|
||||
return str
|
||||
}
|
||||
|
||||
export function keyValueToQueryParameters(obj) {
|
||||
let array = []
|
||||
if (obj && typeof obj === "object") {
|
||||
for (let [key, value] of Object.entries(obj)) {
|
||||
array.push({ name: key, default: value })
|
||||
}
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
export function queryParametersToKeyValue(array) {
|
||||
let obj = {}
|
||||
if (Array.isArray(array)) {
|
||||
for (let param of array) {
|
||||
obj[param.name] = param.default
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
export function customQueryIconText(datasource, query) {
|
||||
if (datasource.source !== IntegrationTypes.REST) {
|
||||
return
|
||||
}
|
||||
switch (query.queryVerb) {
|
||||
case "create":
|
||||
return "POST"
|
||||
case "update":
|
||||
return "PUT"
|
||||
case "read":
|
||||
return "GET"
|
||||
case "delete":
|
||||
return "DELETE"
|
||||
case "patch":
|
||||
return "PATCH"
|
||||
}
|
||||
}
|
||||
|
||||
export function customQueryIconColor(datasource, query) {
|
||||
if (datasource.source !== IntegrationTypes.REST) {
|
||||
return
|
||||
}
|
||||
switch (query.queryVerb) {
|
||||
case "create":
|
||||
return "#dcc339"
|
||||
case "update":
|
||||
return "#5197ec"
|
||||
case "read":
|
||||
return "#53a761"
|
||||
case "delete":
|
||||
return "#ea7d82"
|
||||
case "patch":
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
Heading,
|
||||
RadioGroup,
|
||||
Label,
|
||||
Body,
|
||||
TextArea,
|
||||
Table,
|
||||
notifications,
|
||||
|
@ -30,6 +31,8 @@
|
|||
schemaToFields,
|
||||
breakQueryString,
|
||||
buildQueryString,
|
||||
keyValueToQueryParameters,
|
||||
queryParametersToKeyValue,
|
||||
} from "helpers/data/utils"
|
||||
import {
|
||||
RestBodyTypes as bodyTypes,
|
||||
|
@ -37,9 +40,12 @@
|
|||
} from "constants/backend"
|
||||
import JSONPreview from "components/integration/JSONPreview.svelte"
|
||||
import AccessLevelSelect from "components/integration/AccessLevelSelect.svelte"
|
||||
import Placeholder from "assets/bb-spaceship.svg"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
|
||||
let query, datasource
|
||||
let breakQs = {}
|
||||
let breakQs = {},
|
||||
bindings = {}
|
||||
let url = ""
|
||||
let saveId
|
||||
let response, schema, isGet
|
||||
|
@ -56,7 +62,7 @@
|
|||
response?.info?.code >= 200 && response?.info?.code <= 206
|
||||
|
||||
function getSelectedQuery() {
|
||||
return (
|
||||
return cloneDeep(
|
||||
$queries.list.find(q => q._id === $queries.selected) || {
|
||||
datasourceId: $params.selectedDatasource,
|
||||
parameters: [],
|
||||
|
@ -85,7 +91,9 @@
|
|||
return qs.length > 0 ? `${newUrl}?${qs}` : newUrl
|
||||
}
|
||||
|
||||
function learnMoreBanner() {}
|
||||
function learnMoreBanner() {
|
||||
window.open("https://docs.budibase.com/building-apps/data/transformers")
|
||||
}
|
||||
|
||||
function buildQuery() {
|
||||
const newQuery = { ...query }
|
||||
|
@ -93,6 +101,7 @@
|
|||
newQuery.fields.path = url.split("?")[0]
|
||||
newQuery.fields.queryString = queryString
|
||||
newQuery.schema = fieldsToSchema(schema)
|
||||
newQuery.parameters = keyValueToQueryParameters(bindings)
|
||||
return newQuery
|
||||
}
|
||||
|
||||
|
@ -101,6 +110,7 @@
|
|||
try {
|
||||
const { _id } = await queries.save(toSave.datasourceId, toSave)
|
||||
saveId = _id
|
||||
query = getSelectedQuery()
|
||||
notifications.success(`Request saved successfully.`)
|
||||
} catch (err) {
|
||||
notifications.error(`Error creating query. ${err.message}`)
|
||||
|
@ -114,6 +124,7 @@
|
|||
notifications.info("Request did not return any data.")
|
||||
} else {
|
||||
response.info = response.info || { code: 200 }
|
||||
schema = response.schema
|
||||
notifications.success("Request sent successfully.")
|
||||
}
|
||||
} catch (err) {
|
||||
|
@ -127,6 +138,7 @@
|
|||
breakQs = breakQueryString(qs)
|
||||
url = buildUrl(query.fields.path, breakQs)
|
||||
schema = schemaToFields(query.schema)
|
||||
bindings = queryParametersToKeyValue(query.parameters)
|
||||
if (query && !query.transformer) {
|
||||
query.transformer = "return data"
|
||||
}
|
||||
|
@ -168,11 +180,21 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="url">
|
||||
<Input bind:value={url} />
|
||||
<Input bind:value={url} placeholder="http://www.api.com/endpoint" />
|
||||
</div>
|
||||
<Button cta disabled={!url} on:click={runQuery}>Send</Button>
|
||||
</div>
|
||||
<Tabs selected="Params" quiet noPadding noHorizPadding>
|
||||
<Tabs selected="Bindings" quiet noPadding noHorizPadding>
|
||||
<Tab title="Bindings">
|
||||
<KeyValueBuilder
|
||||
bind:object={bindings}
|
||||
tooltip="Set the name of the binding which can be used in Handlebars statements throughout your query"
|
||||
name="binding"
|
||||
headings
|
||||
keyPlaceholder="Binding name"
|
||||
valuePlaceholder="Default"
|
||||
/>
|
||||
</Tab>
|
||||
<Tab title="Params">
|
||||
<KeyValueBuilder bind:object={breakQs} name="param" headings />
|
||||
</Tab>
|
||||
|
@ -219,29 +241,52 @@
|
|||
</Tabs>
|
||||
</Layout>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<Layout paddingY="S" gap="S">
|
||||
<Divider size="S" />
|
||||
{#if !response}
|
||||
{#if !response && Object.keys(schema).length === 0}
|
||||
<Heading size="M">Response</Heading>
|
||||
<div class="placeholder">
|
||||
<div class="placeholder-internal">
|
||||
<img alt="placeholder" src={Placeholder} />
|
||||
<Body size="XS" textAlign="center"
|
||||
>{"enter a url in the textbox above and click send to get a response".toUpperCase()}</Body
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<Tabs selected="JSON" quiet noPadding noHorizPadding>
|
||||
<Tabs
|
||||
selected={!response ? "Schema" : "JSON"}
|
||||
quiet
|
||||
noPadding
|
||||
noHorizPadding
|
||||
>
|
||||
{#if response}
|
||||
<Tab title="JSON">
|
||||
<div>
|
||||
<JSONPreview height="300" data={response.rows[0]} />
|
||||
</div>
|
||||
</Tab>
|
||||
{/if}
|
||||
{#if schema || response}
|
||||
<Tab title="Schema">
|
||||
<KeyValueBuilder
|
||||
bind:object={response.schema}
|
||||
name="header"
|
||||
bind:object={schema}
|
||||
name="schema"
|
||||
headings
|
||||
options={SchemaTypeOptions}
|
||||
/>
|
||||
</Tab>
|
||||
{/if}
|
||||
{#if response}
|
||||
<Tab title="Raw">
|
||||
<TextArea disabled value={response.raw} height="300" />
|
||||
<TextArea disabled value={response.extra?.raw} height="300" />
|
||||
</Tab>
|
||||
<Tab title="Headers">
|
||||
<KeyValueBuilder object={response.extra?.headers} readOnly />
|
||||
</Tab>
|
||||
<Tab title="Preview">
|
||||
<div class="table">
|
||||
{#if response}
|
||||
<Table
|
||||
schema={response?.schema}
|
||||
|
@ -251,6 +296,7 @@
|
|||
allowSelectRows={false}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</Tab>
|
||||
<div class="stats">
|
||||
<Label size="L">
|
||||
|
@ -272,10 +318,12 @@
|
|||
>Save query</Button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
</Tabs>
|
||||
{/if}
|
||||
</Layout>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
@ -284,6 +332,9 @@
|
|||
margin: 0 auto;
|
||||
height: 100%;
|
||||
}
|
||||
.table {
|
||||
width: 960px;
|
||||
}
|
||||
.url-block {
|
||||
display: flex;
|
||||
gap: var(--spacing-s);
|
||||
|
@ -297,6 +348,9 @@
|
|||
.top {
|
||||
min-height: 50%;
|
||||
}
|
||||
.bottom {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.stats {
|
||||
display: flex;
|
||||
gap: var(--spacing-xl);
|
||||
|
@ -319,4 +373,15 @@
|
|||
gap: var(--spacing-m);
|
||||
align-items: center;
|
||||
}
|
||||
.placeholder-internal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 200px;
|
||||
gap: var(--spacing-l);
|
||||
}
|
||||
.placeholder {
|
||||
display: flex;
|
||||
margin-top: var(--spacing-xl);
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -6,6 +6,9 @@ module FetchMock {
|
|||
return {
|
||||
status,
|
||||
headers: {
|
||||
raw: () => {
|
||||
return { "content-type": ["application/json"] }
|
||||
},
|
||||
get: () => {
|
||||
return ["application/json"]
|
||||
},
|
||||
|
|
|
@ -123,7 +123,7 @@ async function enrichQueryFields(fields, parameters = {}) {
|
|||
enrichedQuery.requestBody
|
||||
)
|
||||
} catch (err) {
|
||||
throw { message: `JSON Invalid - error: ${err}` }
|
||||
// no json found, ignore
|
||||
}
|
||||
delete enrichedQuery.customData
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ exports.preview = async function (ctx) {
|
|||
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
||||
|
||||
try {
|
||||
const { rows, keys, info, raw } = await Runner.run({
|
||||
const { rows, keys, info, extra } = await Runner.run({
|
||||
datasource,
|
||||
queryVerb,
|
||||
query: enrichedQuery,
|
||||
|
@ -162,7 +162,7 @@ exports.preview = async function (ctx) {
|
|||
rows,
|
||||
schemaFields: [...new Set(keys)],
|
||||
info,
|
||||
raw,
|
||||
extra,
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.throw(400, err)
|
||||
|
|
|
@ -19,6 +19,7 @@ exports.queryValidation = () => {
|
|||
extra: Joi.object().optional(),
|
||||
schema: Joi.object({}).required().unknown(true),
|
||||
transformer: Joi.string().optional(),
|
||||
flags: Joi.object().optional(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,18 @@ module RestModule {
|
|||
const { formatBytes } = require("../utilities")
|
||||
const { performance } = require("perf_hooks")
|
||||
|
||||
interface RestQuery {
|
||||
path: string
|
||||
queryString?: string
|
||||
headers: { [key: string]: any }
|
||||
enabledHeaders: { [key: string]: any }
|
||||
requestBody: any
|
||||
bodyType: string
|
||||
json: object
|
||||
method: string
|
||||
authConfigId: string
|
||||
}
|
||||
|
||||
interface RestConfig {
|
||||
url: string
|
||||
defaultHeaders: {
|
||||
|
@ -70,13 +82,6 @@ module RestModule {
|
|||
authConfigs: AuthConfig[]
|
||||
}
|
||||
|
||||
interface Request {
|
||||
path: string
|
||||
queryString?: string
|
||||
headers?: string
|
||||
json?: any
|
||||
}
|
||||
|
||||
const SCHEMA: Integration = {
|
||||
docs: "https://github.com/node-fetch/node-fetch",
|
||||
description:
|
||||
|
@ -140,7 +145,7 @@ module RestModule {
|
|||
}
|
||||
|
||||
async parseResponse(response: any) {
|
||||
let data, raw
|
||||
let data, raw, headers
|
||||
const contentType = response.headers.get("content-type")
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
data = await response.json()
|
||||
|
@ -149,8 +154,12 @@ module RestModule {
|
|||
data = await response.text()
|
||||
raw = data
|
||||
}
|
||||
const size = formatBytes(response.headers.get("content-length") || 0)
|
||||
const size = formatBytes(response.headers.get("content-length") || Buffer.byteLength(raw, "utf8"))
|
||||
const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
|
||||
headers = response.headers.raw()
|
||||
for (let [key, value] of Object.entries(headers)) {
|
||||
headers[key] = Array.isArray(value) ? value[0] : value
|
||||
}
|
||||
return {
|
||||
data,
|
||||
info: {
|
||||
|
@ -158,23 +167,26 @@ module RestModule {
|
|||
size,
|
||||
time,
|
||||
},
|
||||
extra: {
|
||||
raw,
|
||||
headers,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
getUrl(path: string, queryString: string): string {
|
||||
const main = `${path}?${queryString}`
|
||||
if (!this.config.url) {
|
||||
return main
|
||||
} else {
|
||||
return `${this.config.url}/${main}`
|
||||
let complete = !this.config.url ? main : `${this.config.url}/${main}`
|
||||
if (!complete.startsWith("http")) {
|
||||
complete = `http://${complete}`
|
||||
}
|
||||
return complete
|
||||
}
|
||||
|
||||
processAuth(authConfigId: string) {
|
||||
if (!this.config.authConfigs || !authConfigId) {
|
||||
return
|
||||
}
|
||||
getAuthHeaders(authConfigId: string): { [key: string]: any }{
|
||||
let headers: any = {}
|
||||
|
||||
if (this.config.authConfigs && authConfigId) {
|
||||
const authConfig = this.config.authConfigs.filter(
|
||||
c => c._id === authConfigId
|
||||
)[0]
|
||||
|
@ -182,31 +194,47 @@ module RestModule {
|
|||
switch (authConfig.type) {
|
||||
case AuthType.BASIC:
|
||||
config = authConfig.config as BasicAuthConfig
|
||||
this.headers.Authorization = `Basic ${Buffer.from(
|
||||
headers.Authorization = `Basic ${Buffer.from(
|
||||
`${config.username}:${config.password}`
|
||||
).toString("base64")}`
|
||||
break
|
||||
case AuthType.BEARER:
|
||||
config = authConfig.config as BearerAuthConfig
|
||||
this.headers.Authorization = `Bearer ${config.token}`
|
||||
headers.Authorization = `Bearer ${config.token}`
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async _req({
|
||||
path = "",
|
||||
queryString = "",
|
||||
headers = {},
|
||||
json = {},
|
||||
method = "GET",
|
||||
authConfigId = "",
|
||||
}) {
|
||||
return headers
|
||||
}
|
||||
|
||||
async _req(query: RestQuery) {
|
||||
const { path = "", queryString = "", headers = {}, method = "GET", enabledHeaders, bodyType, requestBody, authConfigId } = query
|
||||
|
||||
const authHeaders = this.getAuthHeaders(authConfigId)
|
||||
|
||||
this.headers = {
|
||||
...this.config.defaultHeaders,
|
||||
...headers,
|
||||
...authHeaders,
|
||||
}
|
||||
|
||||
this.processAuth(authConfigId)
|
||||
if (enabledHeaders) {
|
||||
for (let headerKey of Object.keys(this.headers)) {
|
||||
if (!enabledHeaders[headerKey]) {
|
||||
delete this.headers[headerKey]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let json
|
||||
if (bodyType === BodyTypes.JSON && requestBody) {
|
||||
try {
|
||||
json = JSON.parse(requestBody)
|
||||
} catch (err) {
|
||||
throw "Invalid JSON for request body"
|
||||
}
|
||||
}
|
||||
|
||||
const input: any = { method, headers: this.headers }
|
||||
if (json && typeof json === "object" && Object.keys(json).length > 0) {
|
||||
|
@ -218,23 +246,23 @@ module RestModule {
|
|||
return await this.parseResponse(response)
|
||||
}
|
||||
|
||||
async create(opts: Request) {
|
||||
async create(opts: RestQuery) {
|
||||
return this._req({ ...opts, method: "POST" })
|
||||
}
|
||||
|
||||
async read(opts: Request) {
|
||||
async read(opts: RestQuery) {
|
||||
return this._req({ ...opts, method: "GET" })
|
||||
}
|
||||
|
||||
async update(opts: Request) {
|
||||
async update(opts: RestQuery) {
|
||||
return this._req({ ...opts, method: "PUT" })
|
||||
}
|
||||
|
||||
async patch(opts: Request) {
|
||||
async patch(opts: RestQuery) {
|
||||
return this._req({ ...opts, method: "PATCH" })
|
||||
}
|
||||
|
||||
async delete(opts: Request) {
|
||||
async delete(opts: RestQuery) {
|
||||
return this._req({ ...opts, method: "DELETE" })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
jest.mock("node-fetch", () =>
|
||||
jest.fn(() => ({
|
||||
headers: {
|
||||
raw: () => {
|
||||
return { "content-type": ["application/json"] }
|
||||
},
|
||||
get: () => ["application/json"]
|
||||
},
|
||||
json: jest.fn(),
|
||||
|
@ -25,6 +28,7 @@ describe("REST Integration", () => {
|
|||
config = new TestConfiguration({
|
||||
url: BASE_URL,
|
||||
})
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls the create method with the correct params", async () => {
|
||||
|
@ -34,9 +38,10 @@ describe("REST Integration", () => {
|
|||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
json: {
|
||||
bodyType: "json",
|
||||
requestBody: JSON.stringify({
|
||||
name: "test",
|
||||
},
|
||||
}),
|
||||
}
|
||||
const response = await config.integration.create(query)
|
||||
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
|
||||
|
@ -61,6 +66,7 @@ describe("REST Integration", () => {
|
|||
headers: {
|
||||
Accept: "text/html",
|
||||
},
|
||||
method: "GET",
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -71,13 +77,14 @@ describe("REST Integration", () => {
|
|||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
json: {
|
||||
bodyType: "json",
|
||||
requestBody: JSON.stringify({
|
||||
name: "test",
|
||||
},
|
||||
}),
|
||||
}
|
||||
const response = await config.integration.update(query)
|
||||
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
|
||||
method: "POST",
|
||||
method: "PUT",
|
||||
body: '{"name":"test"}',
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
|
@ -92,9 +99,10 @@ describe("REST Integration", () => {
|
|||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
json: {
|
||||
bodyType: "json",
|
||||
requestBody: JSON.stringify({
|
||||
name: "test",
|
||||
},
|
||||
}),
|
||||
}
|
||||
const response = await config.integration.delete(query)
|
||||
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
|
||||
|
@ -102,6 +110,7 @@ describe("REST Integration", () => {
|
|||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: '{"name":"test"}',
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ function hasExtraData(response) {
|
|||
return (
|
||||
typeof response === "object" &&
|
||||
!Array.isArray(response) &&
|
||||
response.data &&
|
||||
response.info
|
||||
response.data != null &&
|
||||
response.info != null
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -34,11 +34,11 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
|
|||
let output = formatResponse(await integration[queryVerb](query))
|
||||
let rows = output,
|
||||
info = undefined,
|
||||
raw = undefined
|
||||
extra = undefined
|
||||
if (hasExtraData(output)) {
|
||||
rows = output.data
|
||||
info = output.info
|
||||
raw = output.raw
|
||||
extra = output.extra
|
||||
}
|
||||
|
||||
// transform as required
|
||||
|
@ -64,7 +64,7 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
|
|||
integration.end()
|
||||
}
|
||||
|
||||
return { rows, keys, info, raw }
|
||||
return { rows, keys, info, extra }
|
||||
}
|
||||
|
||||
module.exports = (input, callback) => {
|
||||
|
|
Loading…
Reference in New Issue