Skip to content

Commit

Permalink
chore(web-vis): refactor app.js into web components (#101)
Browse files Browse the repository at this point in the history
- Move out logic for manipulating vector data into its own file
- Refactor app.js into web components for better separation
  • Loading branch information
arazabishov authored Jul 16, 2023
1 parent d8a4603 commit eb8790f
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 113 deletions.
5 changes: 5 additions & 0 deletions web-vis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ pub fn set_vec_size(vec_idx: usize, size: usize) {
}
}

#[wasm_bindgen]
pub fn get_vec_size(vec_idx: usize) -> usize {
unsafe { STATE.get(vec_idx).unwrap().len() }
}

#[wasm_bindgen]
pub fn split_off_vec(vec_idx: usize, idx: usize) {
unsafe {
Expand Down
172 changes: 66 additions & 106 deletions web-vis/www/src/app.js
Original file line number Diff line number Diff line change
@@ -1,135 +1,95 @@
import "./styles.css";
import * as wasm from "web-vis";
import { RrbVec } from "./rrbtree";
import { VectorFactory, VectorVis } from "./vector";

class Vector {
constructor(id) {
this._id = id;
class VectorComponent extends HTMLElement {
constructor(vectorVis) {
super();
this.vectorVis = vectorVis;
}

id() {
return this._id;
}
connectedCallback() {
this.id = this.vectorVis.id();
this.classList.add("vector");

setSize(size) {
wasm.set_vec_size(this._id, size);
}
const sliderContainer = document.createElement("div");
sliderContainer.classList.add("slider-container");

json() {
return JSON.parse(wasm.get(this._id));
}
}
const sliderTooltip = document.createElement("output");
sliderTooltip.classList.add("tooltip-value");

class VectorVis {
constructor(vector) {
this.vector = vector;
}

id() {
return `tree${this.vector.id()}`;
}
const slider = document.createElement("input");
slider.addEventListener("change", () =>
this.vectorVis.setSize(slider.value)
);
slider.type = "range";
slider.min = 1;
slider.max = 512;

setSize(size) {
if (this.rrbVecVis === undefined) {
this.rrbVecVis = new RrbVec(`#${this.id()}`);
}
sliderContainer.appendChild(slider);
sliderContainer.appendChild(sliderTooltip);

this.vector.setSize(size);
const rrbVec = this.vector.json();
const updateTooltip = () => {
const offset =
((slider.value - slider.min) * 100) / (slider.max - slider.min);
sliderTooltip.innerHTML = `<span>${slider.value}</span>`;

this.rrbVecVis.set(rrbVec);
}
}
// Kind of magic numbers based on size of the native UI thumb
sliderTooltip.style.left = `calc(${offset}% + (${5 - offset * 0.1}px))`;
};

class VectorFactory {
static create() {
const vecId = wasm.len();
slider.addEventListener("input", updateTooltip);
updateTooltip();

wasm.push_vec();
this.appendChild(sliderContainer);

return new Vector(vecId);
if (this.vectorVis.size() > 0) {
slider.value = this.vectorVis.size();
slider.dispatchEvent(new Event("input"));
slider.dispatchEvent(new Event("change"));
}
}
}

function createTree(vectorVis) {
const tree = document.createElement("div");
tree.id = vectorVis.id();
tree.classList.add("tree");

const sliderContainer = document.createElement("div");
sliderContainer.classList.add("slider-container");

const sliderTooltip = document.createElement("output");
sliderTooltip.classList.add("tooltip-value");

const slider = document.createElement("input");
slider.addEventListener("change", () => vectorVis.setSize(slider.value));
slider.type = "range";
slider.min = 1;
slider.max = 512;

sliderContainer.appendChild(slider);
sliderContainer.appendChild(sliderTooltip);

const updateTooltip = () => {
const offset =
((slider.value - slider.min) * 100) / (slider.max - slider.min);
sliderTooltip.innerHTML = `<span>${slider.value}</span>`;

// Kind of magic numbers based on size of the native UI thumb
sliderTooltip.style.left = `calc(${offset}% + (${5 - offset * 0.1}px))`;
};

slider.addEventListener("input", updateTooltip);
updateTooltip();

tree.appendChild(sliderContainer);
return { tree, slider };
}

function createAddTreeButton(onClick) {
const container = document.createElement("div");
container.classList.add("button-add-tree-container");

const button = document.createElement("button");
button.type = "button";
button.classList.add("button-add-tree");
class AddVectorButtonComponent extends HTMLElement {
constructor() {
super();
this.onClick = null;
}

const plusIcon = document.createElement("span");
plusIcon.classList.add("button-add-tree-icon");
plusIcon.innerHTML = "+";
connectedCallback() {
const plusIcon = document.createElement("span");
plusIcon.classList.add("button-add-vector");
plusIcon.innerHTML = "+";

button.appendChild(plusIcon);
button.addEventListener("click", () => onClick(container));
this.classList.add("button-add-vector-container");
this.addEventListener("click", (event) => {
this.onClick(event);
});

container.appendChild(button);
return container;
this.appendChild(plusIcon);
}
}

function createGrid() {
const grid = document.createElement("div");
grid.classList.add("grid-tree");

return grid;
class GridComponent extends HTMLElement {
connectedCallback() {
this.classList.add("grid-vector");
}
}
const grid = createGrid();

const addTree = (button, initialSize) => {
const vector = VectorFactory.create();
const vectorVis = new VectorVis(vector);
const { tree, slider } = createTree(vectorVis);
customElements.define("vector-component", VectorComponent);
customElements.define("add-vector-button-component", AddVectorButtonComponent);
customElements.define("grid-component", GridComponent);

grid.insertBefore(tree, button);
const grid = new GridComponent();
const addVectorButton = new AddVectorButtonComponent();
addVectorButton.onClick = (event) => {
const vectorVis = new VectorVis(VectorFactory.create(64));
const vectorComponent = new VectorComponent(vectorVis);

if (initialSize !== undefined) {
slider.value = initialSize;
slider.dispatchEvent(new Event("input"));
slider.dispatchEvent(new Event("change"));
}
grid.insertBefore(vectorComponent, event.currentTarget);
};
const addTreeButton = createAddTreeButton(addTree);

grid.appendChild(addTreeButton);
grid.appendChild(addVectorButton);
document.body.appendChild(grid);

addTree(addTreeButton, 256);
addVectorButton.dispatchEvent(new Event("click"));
File renamed without changes.
11 changes: 4 additions & 7 deletions web-vis/www/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,21 @@ body {
background: radial-gradient(#000 1px, transparent 0px) 0 0 / 24px 24px;
}

.grid-tree {
.grid-vector {
@apply grid grid-cols-1 md:grid-cols-1 lg:grid-cols-2 gap-4 m-4;
}

.tree {
.vector {
@apply bg-white rounded-lg border border-gray-300 p-4 min-h-[600px] relative;
}

.button-add-tree-container {
.button-add-vector-container {
@apply flex justify-center items-center min-h-[600px];
}

.button-add-tree {
.button-add-vector {
@apply bg-white hover:bg-gray-50 border-gray-300 focus:outline-none rounded-lg p-4;
@apply min-h-[196px] min-w-[196px] py-2.5 px-5 border flex items-center justify-center;
}

.button-add-tree-icon {
@apply text-gray-500 text-4xl;
}

Expand Down
63 changes: 63 additions & 0 deletions web-vis/www/src/vector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { RrbVec } from "./rrbvec.js";
import * as wasm from "web-vis";

export class Vector {
constructor(id) {
this._id = id;
}

id() {
return this._id;
}

setSize(size) {
wasm.set_vec_size(this._id, size);
}

size() {
return wasm.get_vec_size(this._id);
}

json() {
return JSON.parse(wasm.get(this._id));
}
}

export class VectorFactory {
static create(initialSize) {
const vecId = wasm.len();

wasm.push_vec();

const vector = new Vector(vecId);
if (initialSize !== undefined) {
vector.setSize(initialSize);
}
return vector;
}
}

export class VectorVis {
constructor(vector) {
this.vector = vector;
}

id() {
return `vec${this.vector.id()}`;
}

setSize(size) {
if (this.rrbVecVis === undefined) {
this.rrbVecVis = new RrbVec(`#${this.id()}`);
}

this.vector.setSize(size);
const rrbVec = this.vector.json();

this.rrbVecVis.set(rrbVec);
}

size() {
return this.vector.size();
}
}

1 comment on commit eb8790f

@vercel
Copy link

@vercel vercel bot commented on eb8790f Jul 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

pvec-rs – ./

pvec-rs-git-trunk-arazabishov.vercel.app
pvec-rs-arazabishov.vercel.app
pvec-rs.vercel.app

Please sign in to comment.