Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External Maptiler keys #58

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion lib/assets/map_cell/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ input[type="number"] {
.special-field {
display: flex;
flex-direction: column;
margin-bottom: 16px;
flex-basis: 50%;
max-width: 348px;
}
Expand Down Expand Up @@ -354,6 +353,10 @@ input::-webkit-inner-spin-button {
padding: 12px 0 0 16px;
}

.add-key {
margin: 14px;
}

input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
Expand Down Expand Up @@ -503,6 +506,66 @@ input[type="color"] {
border-radius: 0.5rem;
}

.hidden-checkbox-input {
display: none;
}

.input-icon {
border: 1px solid var(--gray-200);
outline: none;
padding: 8px 12px 8px 42px;
}

.input-icon:hover {
cursor: pointer;
}

.input-icon.unavailable {
border-color: var(--red-300);
}

.input-icon-container {
position: relative;
}

.icon-container {
position: absolute;
top: 20px;
left: 4px;
padding: 5px 6px;
border-right: 1px solid var(--gray-200);
width: 22px;
height: 23px;
background-color: var(--gray-200);
border-radius: 0.5rem;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin-left: 1px;
}

.icon-container:hover {
cursor: pointer;
background-color: var(--gray-300);
}

.input-icon-text {
border: 1px solid var(--gray-200);
outline: none;
padding: 8px 12px 8px 42px;
}

.input-icon.required {
border: 1px solid var(--red--300);
}

.input-icon-text.required {
border: 1px solid var(--red--300);
}

.hidden-checkbox:hover {
cursor: pointer;
}

/* Switch SM */

.switch-sm {
Expand Down
140 changes: 138 additions & 2 deletions lib/assets/map_cell/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export async function init(ctx, payload) {
type: String,
default: "",
},
inputClass: {
type: String,
default: "input",
},
modelValue: {
type: [String, Number],
default: "",
Expand All @@ -32,8 +36,7 @@ export async function init(ctx, payload) {
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
v-bind="$attrs"
class="input"
:class="{ required: !modelValue && required }"
:class="[inputClass, { required: !modelValue && required }]"
>
</div>
`,
Expand Down Expand Up @@ -250,13 +253,128 @@ export async function init(ctx, payload) {
`,
};

const BaseSecret = {
name: "BaseSecret",

components: {
BaseInput: BaseInput,
},

props: {
textInputName: {
type: String,
default: "",
},
secretInputName: {
type: String,
default: "",
},
toggleInputName: {
type: String,
default: "",
},
label: {
type: String,
default: "",
},
toggleInputValue: {
type: [String, Number],
default: "",
},
secretInputValue: {
type: [String, Number],
default: "",
},
textInputValue: {
type: [String, Number],
default: "",
},
modalTitle: {
type: String,
default: "Select secret",
},
required: {
type: Boolean,
default: false,
},
},

methods: {
selectSecret() {
const preselectName = this.secretInputValue || "";
ctx.selectSecret(
(secretName) => {
ctx.pushEvent("update_field", {
field: this.secretInputName,
value: secretName,
idx: null,
});
},
preselectName,
{ title: this.modalTitle }
);
},
},

template: `
<div class="input-icon-container grow">
<BaseInput
v-if="toggleInputValue"
:name="secretInputName"
:label="label"
:value="secretInputValue"
inputClass="input input-icon"
:grow
readonly
@click="selectSecret"
@input="$emit('update:secretInputValue', $event.target.value)"
:required="!secretInputValue && required"
/>
<BaseInput
v-else
:name="textInputName"
:label="label"
type="text"
:value="textInputValue"
inputClass="input input-icon-text"
:grow
@input="$emit('update:textInputValue', $event.target.value)"
:required="!textInputValue && required"
/>
<div class="icon-container">
<label class="hidden-checkbox">
<input
type="checkbox"
:name="toggleInputName"
:checked="toggleInputValue"
@input="$emit('update:toggleInputValue', $event.target.checked)"
class="hidden-checkbox-input"
/>
<svg v-if="toggleInputValue" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
width="22" height="22">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M18 8h2a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1h2V7a6 6 0 1 1 12 0v1zM5
10v10h14V10H5zm6 4h2v2h-2v-2zm-4 0h2v2H7v-2zm8 0h2v2h-2v-2zm1-6V7a4 4 0 1 0-8 0v1h8z" fill="#000"/>
</svg>
<svg v-else xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z"/>
<path d="M21 3v18H3V3h18zm-8.001 3h-2L6.6 17h2.154l1.199-3h4.09l1.201 3h2.155l-4.4-11zm-1 2.885L13.244
12h-2.492l1.247-3.115z" fill="#445668"/>
</svg>
</label>
</div>
</div>
`,
};

const app = Vue.createApp({
components: {
BaseSelect,
BaseInput,
Accordion,
FieldGroup,
BaseSwitch,
BaseSecret,
Container: VueDndrop.Container,
Draggable: VueDndrop.Draggable,
},
Expand Down Expand Up @@ -311,6 +429,19 @@ export async function init(ctx, payload) {
<span class="zoom-value">{{ rootFields.zoom }}</span>
</div>
</div>
<div class="add-key" v-if="commercial">
<BaseSecret
textInputName="maptiler_key"
secretInputName="maptiler_key_secret"
toggleInputName="use_maptiler_key_secret"
label="Maptiler Key"
v-model:textInputValue="rootFields.maptiler_key"
v-model:secretInputValue="rootFields.maptiler_key_secret"
v-model:toggleInputValue="rootFields.use_maptiler_key_secret"
modalTitle="Set maptiler key"
:required
/>
</div>
<div class="layers">
<Container @drop="handleItemDrop" lock-axis="y" non-drag-area-selector=".accordion-body">
<Draggable v-for="(layer, index) in layers">
Expand Down Expand Up @@ -532,6 +663,8 @@ export async function init(ctx, payload) {
"default",
"street (non-commercial)",
"terrain (non-commercial)",
"street (commercial)",
"terrain (commercial)",
],
sourceVariables: payload.source_variables.map((data) => data.variable),
coordinateOptions: [
Expand All @@ -550,6 +683,9 @@ export async function init(ctx, payload) {
noSourceVariable() {
return !this.layers[0].layer_source;
},
commercial() {
return this.rootFields.style.includes("(commercial)");
}
},

methods: {
Expand Down
34 changes: 30 additions & 4 deletions lib/kino_maplibre/map_cell.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ defmodule KinoMapLibre.MapCell do
@as_atom ["layer_type", "source_type", "symbol_type"]
@as_float ["layer_opacity"]
@geometries [Geo.Point, Geo.LineString, Geo.Polygon, Geo.GeometryCollection]
@styles %{"street (non-commercial)" => :street, "terrain (non-commercial)" => :terrain}
@styles %{
"street (non-commercial)" => :street,
"terrain (non-commercial)" => :terrain,
"street (commercial)" => :street,
"terrain (commercial)" => :terrain
}
@geocode_options ["fill", "line", "circle"]

@query_source %{columns: nil, type: "query", variable: "🌎 Geocoding"}
Expand All @@ -19,7 +24,10 @@ defmodule KinoMapLibre.MapCell do
root_fields = %{
"style" => attrs["style"] || "default",
"center" => attrs["center"],
"zoom" => attrs["zoom"] || 0
"zoom" => attrs["zoom"] || 0,
"maptiler_key" => attrs["maptiler_key"],
"use_maptiler_key_secret" => attrs["use_maptiler_key_secret"] || true,
"maptiler_key_secret" => attrs["maptiler_key_secret"]
}

layers =
Expand Down Expand Up @@ -248,6 +256,7 @@ defmodule KinoMapLibre.MapCell do
layers = attrs["layers"]
sources = build_sources(layers)
symbols = build_symbols(layers)
key = maptiler_key(attrs)

attrs =
Map.take(attrs, ["style", "center", "zoom", "ml_alias"])
Expand All @@ -257,7 +266,7 @@ defmodule KinoMapLibre.MapCell do
field: nil,
name: :new,
module: attrs.ml_alias,
args: build_arg_root(style: attrs.style, center: attrs.center, zoom: attrs.zoom)
args: build_arg_root(style: attrs.style, center: attrs.center, zoom: attrs.zoom, key: key)
}

sources =
Expand Down Expand Up @@ -482,7 +491,7 @@ defmodule KinoMapLibre.MapCell do

defp missing_dep() do
unless Code.ensure_loaded?(MapLibre) do
~s/{:maplibre, "~> 0.1.0"}/
~s/{:maplibre, "~> 0.1.6"}/
end
end

Expand Down Expand Up @@ -545,4 +554,21 @@ defmodule KinoMapLibre.MapCell do
|> String.replace(~r/\W+/, "_")
end
end

defp maptiler_key(%{"style" => style, "use_maptiler_key_secret" => secret} = attrs) do
if String.contains?(style, "(commercial)"), do: maptiler_key(secret, attrs)
end

# Always return an empty key for commercial styles when a key is not provided to ensure
# that the :key argument will be passed (preventing using our key as a fallback)
defp maptiler_key(true, %{"maptiler_key_secret" => secret}), do: from_secret(secret)
defp maptiler_key(false, %{"maptiler_key" => key}), do: key || ""

defp from_secret(nil), do: ""

defp from_secret(secret) do
quote do
System.fetch_env!(unquote("LB_#{secret}"))
end
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ defmodule KinoMapLibre.MixProject do
[
{:kino, "~> 0.7"},
{:table, "~> 0.1.0"},
{:maplibre, "~> 0.1.3"},
{:maplibre, "~> 0.1.6"},
{:ex_doc, "~> 0.28", only: :dev, runtime: false}
]
end
Expand Down
4 changes: 2 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
%{
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
"ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"},
"geo": {:hex, :geo, "3.4.3", "0ddf3f681993d32c397e5ef346e7b4b6f36f39ed138502429832fa4000ebb9d5", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "e23f2892e5437ec8b063cee1beccec89c58fd841ae11133304700235feb25552"},
"geo": {:hex, :geo, "3.5.1", "a7b1581770c5f0de3f19fe0977eb828b79af269669854ca944038f70188f47b5", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "c65cfdc5f214402b52a32c11ae9dec9530bbee4973303a67e75312db3ec7b59c"},
"kino": {:hex, :kino, "0.7.0", "98d2623bebf8d1c4d761c5ed9741c6aae2f1909706baec501f2fdad347cb9d92", [:mix], [{:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "3dd1ee761c241caa30364333e3102a954d68188414a46e867f95c858d745f3fd"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"maplibre": {:hex, :maplibre, "0.1.3", "510476c23ac9958d3adddc5d349f40907309718639a9b1a93eebd586a39ef2f3", [:mix], [{:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: false]}, {:req, "~> 0.3.0", [hex: :req, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "8439795a90365c4363e26a8b66676d88ef44fda8db0060279451343d2259d640"},
"maplibre": {:hex, :maplibre, "0.1.6", "9244bd95064a989079907318e84fc47117ce0fb696f4fc9a12208aff8d6fabe7", [:mix], [{:geo, "~> 3.5.1 or ~> 3.6", [hex: :geo, repo: "hexpm", optional: false]}, {:req, "~> 0.3.0", [hex: :req, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "6dcb36a4941529a6370a82dd8a6b0bd882c554d0e41662f93c91b894e94680c0"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"table": {:hex, :table, "0.1.2", "87ad1125f5b70c5dea0307aa633194083eb5182ec537efc94e96af08937e14a8", [:mix], [], "hexpm", "7e99bc7efef806315c7e65640724bf165c3061cdc5d854060f74468367065029"},
}
Loading