Skip to content

Commit

Permalink
feat(gnoweb): improve help page (gnolang#3362)
Browse files Browse the repository at this point in the history
Adds JavaScript features listed gnolang#3355 regarding Help section in gnoweb.

- Adds localStorage feature for address
- Fixes txlink
- Minor UI styles
  • Loading branch information
alexiscolin authored and omarsy committed Dec 18, 2024
1 parent 9254abd commit d2e3de0
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 11 deletions.
2 changes: 1 addition & 1 deletion gno.land/pkg/gnoweb/components/help.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
{{ range .Params }}
<div class="flex flex-col gap-3 items-stretch text-gray-400 mb-2">
<div class="group relative overflow-hidden flex w-full border rounded-sm has-[:focus]:border-gray-300 hover:border-gray-300">
<label for="func-{{ $funcName }}-param-{{ .Name }}" class="flex gap-3 items-center bg-gray-50 px-4 font-semibold text-gray-600">{{ .Name }}</label>
<label for="func-{{ $funcName }}-param-{{ .Name }}" class="flex gap-3 items-center bg-gray-50 px-4 font-semibold text-gray-600 text-100">{{ .Name }}</label>
<input type="text"
{{- if eq $data.SelectedFunc $funcName }}
value="{{ getSelectedArgValue $data . }}"
Expand Down
4 changes: 2 additions & 2 deletions gno.land/pkg/gnoweb/components/index.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
{{ end }}

{{ define "header" }}
<header class="main-header sticky top-0 bg-light border-b border-gray-400 text-100 z-max">
<header class="main-header sticky top-0 bg-light border-b text-100 z-max">
<nav aria-label="Realm navigation" class="max-w-screen-max mx-auto px-4 md:px-10 grid grid-cols-10 grid-flow-dense gap-4 md:gap-x-8 lg:gap-x-20 xxl:gap-x-32 items-center">
<div class="main-navigation flex items-center gap-1 col-span-7 max-w-screen-max h-full py-2">
<a href="/" class="rounded border border-gray-100 cursor-pointer h-10 w-10 shrink-0">
Expand Down Expand Up @@ -118,7 +118,7 @@
{{ end }}

{{ define "footer" }}
<footer class="w-full text-100 py-1.5 border-t border-gray-300">
<footer class="w-full text-100 py-1.5 border-t">
<nav class="max-w-screen-max mx-auto px-4 md:px-10 mb-8 md:mb-0 grid grid-cols-1 md:grid-cols-4 justify-between items-start xl:items-center gap-2 xl:gap-20 pt-2 xl:pt-0">
<!-- Footer Navigation -->
<div class="col-span-1 pb-8 md:pb-0">
Expand Down
56 changes: 50 additions & 6 deletions gno.land/pkg/gnoweb/frontend/js/realmhelp.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { debounce } from "./utils";

class Help {
private DOM: {
el: HTMLElement | null;
Expand Down Expand Up @@ -40,18 +42,33 @@ class Help {
this.DOM.addressInput = el.querySelector<HTMLInputElement>(Help.SELECTORS.addressInput);
this.DOM.cmdModeSelect = el.querySelector<HTMLSelectElement>(Help.SELECTORS.cmdModeSelect);

console.log(this.DOM);
this.funcList = this.DOM.funcs.map((funcEl) => new HelpFunc(funcEl));

this.restoreAddress();
this.bindEvents();
}

private restoreAddress(): void {
const { addressInput } = this.DOM;
if (addressInput) {
const storedAddress = localStorage.getItem("helpAddressInput");
if (storedAddress) {
addressInput.value = storedAddress;
this.funcList.forEach((func) => func.updateAddr(storedAddress));
}
}
}

private bindEvents(): void {
const { addressInput, cmdModeSelect } = this.DOM;

addressInput?.addEventListener("input", () => {
this.funcList.forEach((func) => func.updateAddr(addressInput.value));
const debouncedUpdate = debounce((addressInput: HTMLInputElement) => {
const address = addressInput.value;

localStorage.setItem("helpAddressInput", address);
this.funcList.forEach((func) => func.updateAddr(address));
});
addressInput?.addEventListener("input", () => debouncedUpdate(addressInput));

cmdModeSelect?.addEventListener("change", (e) => {
const target = e.target as HTMLSelectElement;
Expand All @@ -66,6 +83,7 @@ class HelpFunc {
addrs: HTMLElement[];
args: HTMLElement[];
modes: HTMLElement[];
paramInputs: HTMLInputElement[];
};

private funcName: string | null;
Expand All @@ -83,27 +101,52 @@ class HelpFunc {
addrs: Array.from(el.querySelectorAll<HTMLElement>(HelpFunc.SELECTORS.address)),
args: Array.from(el.querySelectorAll<HTMLElement>(HelpFunc.SELECTORS.args)),
modes: Array.from(el.querySelectorAll<HTMLElement>(HelpFunc.SELECTORS.mode)),
paramInputs: Array.from(el.querySelectorAll<HTMLInputElement>(HelpFunc.SELECTORS.paramInput)),
};

this.funcName = el.dataset.func || null;

this.initializeArgs();
this.bindEvents();
}

private static sanitizeArgsInput(input: HTMLInputElement) {
const paramName = input.dataset.param || "";
const paramValue = input.value.trim();

if (!paramName) {
console.warn("sanitizeArgsInput: param is missing in arg input dataset.");
}

return { paramName, paramValue };
}

private bindEvents(): void {
const debouncedUpdate = debounce((paramName: string, paramValue: string) => {
if (paramName) this.updateArg(paramName, paramValue);
});

this.DOM.el.addEventListener("input", (e) => {
const target = e.target as HTMLInputElement;
if (target.dataset.role === "help-param-input") {
this.updateArg(target.dataset.param || "", target.value);
const { paramName, paramValue } = HelpFunc.sanitizeArgsInput(target);
debouncedUpdate(paramName, paramValue);
}
});
}

private initializeArgs(): void {
this.DOM.paramInputs.forEach((input) => {
const { paramName, paramValue } = HelpFunc.sanitizeArgsInput(input);
if (paramName) this.updateArg(paramName, paramValue);
});
}

public updateArg(paramName: string, paramValue: string): void {
this.DOM.args
.filter((arg) => arg.dataset.arg === paramName)
.forEach((arg) => {
arg.textContent = paramValue.trim() || "";
arg.textContent = paramValue || "";
});
}

Expand All @@ -116,7 +159,8 @@ class HelpFunc {
public updateMode(mode: string): void {
this.DOM.modes.forEach((cmd) => {
const isVisible = cmd.dataset.codeMode === mode;
cmd.className = isVisible ? "inline" : "hidden";
cmd.classList.toggle("inline", isVisible);
cmd.classList.toggle("hidden", !isVisible);
cmd.dataset.copyContent = isVisible ? `help-cmd-${this.funcName}` : "";
});
}
Expand Down
12 changes: 12 additions & 0 deletions gno.land/pkg/gnoweb/frontend/js/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function debounce<T extends (...args: any[]) => void>(func: T, delay: number = 250): (...args: Parameters<T>) => void {
let timeoutId: ReturnType<typeof setTimeout> | undefined;

return function (this: any, ...args: Parameters<T>) {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
2 changes: 1 addition & 1 deletion gno.land/pkg/gnoweb/public/js/realmhelp.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gno.land/pkg/gnoweb/public/js/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
function r(t,n=250){let e;return function(...i){e!==void 0&&clearTimeout(e),e=setTimeout(()=>{t.apply(this,i)},n)}}export{r as debounce};
2 changes: 1 addition & 1 deletion gno.land/pkg/gnoweb/public/styles.css

Large diffs are not rendered by default.

0 comments on commit d2e3de0

Please sign in to comment.