Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2f03416
feat(userlib): support reference types
chenyan-dfinity Mar 6, 2020
90b3c67
fix
chenyan-dfinity Mar 6, 2020
513e760
fix
chenyan-dfinity Mar 6, 2020
0b723b9
fix
chenyan-dfinity Mar 7, 2020
098ac4d
Merge branch 'master' into idl-ref
chenyan-dfinity Mar 9, 2020
1c364d3
refactor canisterId
chenyan-dfinity Mar 9, 2020
eef4d6c
bump motoko
chenyan-dfinity Mar 10, 2020
44f4243
feat(userlib): support reference types
chenyan-dfinity Mar 11, 2020
da7e204
Merge remote-tracking branch 'origin/master' into idl-ref
chenyan-dfinity Mar 11, 2020
e66d2d1
remove ActorInterface, add CRC8 for canister id
chenyan-dfinity Mar 11, 2020
22b5c04
add tests
chenyan-dfinity Mar 11, 2020
b2b4a01
bump motoko
chenyan-dfinity Mar 12, 2020
09d9a00
Update src/userlib/js/src/canisterId.ts
chenyan-dfinity Mar 12, 2020
a882a91
fix
chenyan-dfinity Mar 12, 2020
f45886a
Merge branch 'idl-ref' into wired-ui
chenyan-dfinity Mar 12, 2020
ec6c8cb
wired UI
chenyan-dfinity Mar 13, 2020
af8b860
Merge branch 'master' into wired-ui
chenyan-dfinity Mar 13, 2020
6b0f20d
fix
chenyan-dfinity Mar 13, 2020
819c980
diff
chenyan-dfinity Mar 14, 2020
cf6b742
Merge remote-tracking branch 'origin/master' into wired-ui
chenyan-dfinity Mar 16, 2020
af81427
fix
chenyan-dfinity Mar 16, 2020
677776c
refactor: candid UI
chenyan-dfinity Mar 17, 2020
49e3c61
refactor out css
chenyan-dfinity Mar 17, 2020
73ffe44
fix
chenyan-dfinity Mar 17, 2020
eb6a4c8
Merge remote-tracking branch 'origin/candid-refactor' into wired-ui
chenyan-dfinity Mar 17, 2020
10663bf
fix
chenyan-dfinity Mar 18, 2020
a831df9
Merge remote-tracking branch 'origin/master' into wired-ui
chenyan-dfinity Mar 26, 2020
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
27 changes: 17 additions & 10 deletions src/userlib/js/bootstrap/candid/candid.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import * as UI from './candid-ui';
import './candid.css';
import * as UI from './wired';
import { WiredCard, WiredButton } from 'wired-elements';
import './wired.css';

export function render(id, canister) {
const font = document.createElement('link');
font.href = 'https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&display=swap';
font.rel = 'stylesheet';
document.head.appendChild(font);

document.getElementById('title').innerText = `Service ${id}`;
for (const [name, func] of Object.entries(canister.__actorInterface())) {
renderMethod(name, func, canister[name]);
}
const console = document.createElement("div");
console.className = 'console';
const console = document.createElement("wired-card");
console.classList.add('console');
document.body.appendChild(console);
}

Expand All @@ -26,22 +32,23 @@ function renderMethod(name, idl_func, f) {
inputbox.render(item);
});

const button = document.createElement("button");
button.className = 'btn';
const button = document.createElement("wired-button");
button.classList.add('btn');
if (idl_func.annotations.includes('query')) {
button.innerText = 'Query';
} else {
button.innerText = 'Call';
}
item.appendChild(button);

const random = document.createElement("button");
random.className = 'btn';
const random = document.createElement("wired-button");
random.classList.add('btn');
random.innerText = 'Lucky';
item.appendChild(random);

const result = document.createElement("div");
result.className = 'result';
const result = document.createElement("wired-card");

result.classList.add('result');
const left = document.createElement("span");
left.className = 'left';
const right = document.createElement("span");
Expand Down
66 changes: 66 additions & 0 deletions src/userlib/js/bootstrap/candid/wired.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.signature {
margin: 5px;
}
.argument, .result, .status, .composite {
font-family: 'Gloria Hallelujah', cursive;
font-weight: 400;
margin-right: 10px;
margin-bottom: 10px;
}
.open {
font-family: 'Gloria Hallelujah', cursive;
margin: 5px;
}
.reject {
color: #cc0000;
}
.result {
display: none;
}
.error {
color: #cc0000;
}
.status {
color: #cc0000;
display: none;
}
.btn {
margin: 5px;
}
.left {
text-align: left;
width: 84%;
display: inline-block;
overflow-wrap: break-word;
}
.right {
text-align: right;
width: 15%;
display: inline-block;
}
.popup-form {
padding-top: 10px;
padding-left: 15px;
}
.console {
display: flex;
flex: 1;
flex-direction: column;
background-color: #F9F9F9;
color: #545454;
}
.console-line {
overflow-wrap: break-word;
flex: 0;
flex-basis: auto;
border: 0;
margin-left: 5px;
margin-bottom: 5px;
}
body {
font-family: 'Gloria Hallelujah', cursive;
font-weight: 400;
font-size: 19px;
letter-spacing: 0.05em;
line-height: 2;
}
186 changes: 186 additions & 0 deletions src/userlib/js/bootstrap/candid/wired.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { CanisterId, IDL } from '@internet-computer/userlib';
import BigNumber from 'bignumber.js';
import { WiredCombo, WiredItem } from 'wired-elements';
import * as UI from './candid-core';

// tslint:disable:max-classes-per-file
type InputBox = UI.InputBox;

const InputConfig: UI.UIConfig = { parse: parsePrimitive };
const FormConfig: UI.FormConfig = { render: renderInput, container: 'div' };

const inputBox = (t: IDL.Type, config: Partial<UI.UIConfig>) => {
return new UI.InputBox(t, {...InputConfig, ...config});
};
const recordForm = (fields: Array<[string, IDL.Type]>, config: Partial<UI.FormConfig>) => {
return new UI.RecordForm(fields, {...FormConfig, ...config});
};
const variantForm = (fields: Array<[string, IDL.Type]>, config: Partial<UI.FormConfig>) => {
return new VariantForm(fields, {...FormConfig, ...config});
};
const optForm = (ty: IDL.Type, config: Partial<UI.FormConfig>) => {
return new UI.OptionForm(ty, {...FormConfig, ...config});
};
const vecForm = (ty: IDL.Type, config: Partial<UI.FormConfig>) => {
return new UI.VecForm(ty, {...FormConfig, ...config});
};

class Render extends IDL.Visitor<null, InputBox> {
public visitType<T>(t: IDL.Type<T>, d: null): InputBox {
const input = document.createElement('wired-input') as HTMLInputElement;
input.classList.add('argument');
input.placeholder = t.display();
return inputBox(t, { input });
}
public visitNull(t: IDL.NullClass, d: null): InputBox {
return inputBox(t, {});
}
public visitRecord(t: IDL.RecordClass, fields: Array<[string, IDL.Type]>, d: null): InputBox {
const form = recordForm(fields, {});
return inputBox(t, { form });
}
public visitVariant(t: IDL.VariantClass, fields: Array<[string, IDL.Type]>, d: null): InputBox {
const select = document.createElement('wired-combo');
for (const [key, type] of fields) {
const option = document.createElement('wired-item') as WiredItem;
option.innerText = key;
option.value = key;
select.appendChild(option);
}
select.classList.add('open');
const form = variantForm(fields, { open: select, event: 'selected' });
return inputBox(t, { form });
}
public visitOpt<T>(t: IDL.OptClass<T>, ty: IDL.Type<T>, d: null): InputBox {
const checkbox = document.createElement('wired-checkbox');
checkbox.classList.add('open');
const form = optForm(ty, { open: checkbox, event: 'change' });
return inputBox(t, { form });
}
public visitVec<T>(t: IDL.VecClass<T>, ty: IDL.Type<T>, d: null): InputBox {
const len = document.createElement('wired-input') as HTMLInputElement;
len.type = 'number';
len.min = '0';
len.max = '100';
len.style.width = '3em';
len.placeholder = 'len';
len.classList.add('open');
const form = vecForm(ty, { open: len, event: 'change' });
return inputBox(t, { form });
}
public visitRec<T>(t: IDL.RecClass<T>, ty: IDL.ConstructType<T>, d: null): InputBox {
return renderInput(ty);
}
}

class VariantForm extends UI.InputForm {
constructor(public fields: Array<[string, IDL.Type]>, public ui: UI.FormConfig) {
super(ui);
}
public generateForm(): void {
const key = (this.ui.open as WiredCombo).selected;
for (const [k, t] of this.fields) {
if (key === k) {
const variant = this.ui.render(t);
this.form = [variant];
return;
}
}
}
public parse(config: UI.ParseConfig): Record<string, any> | undefined {
const select = this.ui.open as WiredCombo;
const selected = select.selected!;
const value = this.form[0].parse(config);
if (value === undefined) {
return undefined;
}
const v: Record<string, any> = {};
v[selected] = value;
return v;
}
}

class Parse extends IDL.Visitor<string, any> {
public visitNull(t: IDL.NullClass, v: string): null {
return null;
}
public visitBool(t: IDL.BoolClass, v: string): boolean {
if (v === 'true') {
return true;
}
if (v === 'false') {
return false;
}
throw new Error(`Cannot parse ${v} as boolean`);
}
public visitText(t: IDL.TextClass, v: string): string {
return v;
}
public visitInt(t: IDL.IntClass, v: string): BigNumber {
return new BigNumber(v);
}
public visitNat(t: IDL.NatClass, v: string): BigNumber {
return new BigNumber(v);
}
public visitFixedInt(t: IDL.FixedIntClass, v: string): BigNumber {
return new BigNumber(v);
}
public visitFixedNat(t: IDL.FixedNatClass, v: string): BigNumber {
return new BigNumber(v);
}
public visitPrincipal(t: IDL.PrincipalClass, v: string): CanisterId {
return CanisterId.fromText(v);
}
public visitService(t: IDL.ServiceClass, v: string): CanisterId {
return CanisterId.fromText(v);
}
public visitFunc(t: IDL.FuncClass, v: string): [CanisterId, string] {
const x = v.split('.', 2);
return [CanisterId.fromText(x[0]), x[1]];
}
}

class Random extends IDL.Visitor<string, any> {
public visitNull(t: IDL.NullClass, v: string): null {
return null;
}
public visitBool(t: IDL.BoolClass, v: string): boolean {
return Math.random() < 0.5;
}
public visitText(t: IDL.TextClass, v: string): string {
return Math.random().toString(36).substring(6);
}
public visitInt(t: IDL.IntClass, v: string): BigNumber {
return new BigNumber(this.generateNumber(true));
}
public visitNat(t: IDL.NatClass, v: string): BigNumber {
return new BigNumber(this.generateNumber(false));
}
public visitFixedInt(t: IDL.FixedIntClass, v: string): BigNumber {
return new BigNumber(this.generateNumber(true));
}
public visitFixedNat(t: IDL.FixedNatClass, v: string): BigNumber {
return new BigNumber(this.generateNumber(false));
}
private generateNumber(signed: boolean): number {
const num = Math.floor(Math.random() * 100);
if (signed && Math.random() < 0.5) {
return -num;
} else {
return num;
}
}
}

export function renderInput(t: IDL.Type): InputBox {
return t.accept(new Render(), null);
}

function parsePrimitive(t: IDL.Type, config: UI.ParseConfig, d: string) {
if (config.random && d === '') {
return t.accept(new Random(), d);
} else {
return t.accept(new Parse(), d);
}
}

Loading