From 63571d9711f56e25754d0575c14a3d485afe898e Mon Sep 17 00:00:00 2001 From: projectmoon Date: Mon, 4 Jan 2021 22:36:21 +0000 Subject: [PATCH] WIP on reimplementing edit character script with typescript --- src/models/proto.rs | 20 ---- .../characters/edit_character.html.tera | 7 +- static/scripts/characters/edit.js | 6 +- static/scripts/src/api.ts | 15 +++ static/scripts/src/characters/edit.ts | 63 ++++++++++++ static/scripts/src/index.ts | 2 + static/scripts/tsconfig.json | 6 +- static/scripts/webpack.config.js | 97 ++++++++++--------- 8 files changed, 142 insertions(+), 74 deletions(-) create mode 100644 static/scripts/src/api.ts create mode 100644 static/scripts/src/characters/edit.ts diff --git a/src/models/proto.rs b/src/models/proto.rs index 9e32492..31b6d95 100644 --- a/src/models/proto.rs +++ b/src/models/proto.rs @@ -6,15 +6,6 @@ use std::ops::Deref; pub mod cofd; -const CRATE_NAME: &'static str = env!("CARGO_BIN_NAME"); - -/// Convert an incoming protobuf content-type to the equivalent type -/// name produced by std::any::type_name(). Currently does NOT work -/// with nested types due to how prost generates the module names. -fn convert_to_rust_name(proto_type: &str) -> String { - format!("{}::{}", CRATE_NAME, proto_type.replace(".", "::")) -} - /// A struct wrapping a protobuf that allows it to be used as binary /// data submitted via POST using fetch API. Can automatically be /// dereferenced into its wrapped type. @@ -40,21 +31,10 @@ where .map(|ct| ct.top() == "application" && ct.sub() == "x-protobuf") .unwrap_or(false); - let message_type: Option = content_type.and_then(|ct| { - ct.params() - .find(|&(name, _)| name == "messageType") - .map(|(_, message_type)| convert_to_rust_name(message_type)) - }); - if !is_protobuf { return Outcome::Failure((Status::new(422, "invalid protobuf"), Error::InvalidInput)); } - if message_type.as_ref().map(String::as_str) != Some(std::any::type_name::()) { - println!("message type is {:?}", message_type); - return Outcome::Forward(data); - } - let bytes: Vec = match data.open(2.mebibytes()).stream_to_vec().await { Ok(read_bytes) => read_bytes, Err(e) => return Outcome::Failure((Status::new(422, "invalid protobuf"), e.into())), diff --git a/src/templates/characters/edit_character.html.tera b/src/templates/characters/edit_character.html.tera index 681b919..99f9e4a 100644 --- a/src/templates/characters/edit_character.html.tera +++ b/src/templates/characters/edit_character.html.tera @@ -85,8 +85,11 @@ - - + {# #} + {# #} + {# Webpack Templating for API script #} + <%= htmlWebpackPlugin.tags.bodyTags %> +

Core Sheet

Name:

diff --git a/static/scripts/characters/edit.js b/static/scripts/characters/edit.js index b9e46c5..bb97d83 100644 --- a/static/scripts/characters/edit.js +++ b/static/scripts/characters/edit.js @@ -2,12 +2,12 @@ //TODO start refactoring these into a separate script, and make API calls //take all necessary info (e.g. username and character ID, plus other stuff) //as object params. - const root = await protobuf.load("/protos/cofd_api.proto"); + //const root = await protobuf.load("/protos/cofd_api.proto"); const [, , USERNAME, CHARACTER_ID] = window.location.pathname.split('/'); - const api = makeAPI(root); - console.log("api is", api); + //const api = makeAPI(root); + //console.log("api is", api); function setupAttributes() { const attributeInputs = document.querySelectorAll('#attributes input[type="number"]'); diff --git a/static/scripts/src/api.ts b/static/scripts/src/api.ts new file mode 100644 index 0000000..ce7a8e6 --- /dev/null +++ b/static/scripts/src/api.ts @@ -0,0 +1,15 @@ +import { UpdateSkillValueRequest } from "../_proto/cofd_api_pb"; + +const PROTOBUF_CONTENT_TYPE = { 'Content-Type': 'application/x-protobuf' }; + +export async function updateSkillValue(params: UpdateSkillValueRequest) { + let resp = await fetch('/api/rpc/cofd/update_skill_value', { + method: 'POST', + headers: { ...PROTOBUF_CONTENT_TYPE }, + body: params.serializeBinary() + }).then(async resp => { + console.log("resp is", await resp.text()); + }).catch(async err => { + console.log("err is", err.text()); + }); +} diff --git a/static/scripts/src/characters/edit.ts b/static/scripts/src/characters/edit.ts new file mode 100644 index 0000000..1b30065 --- /dev/null +++ b/static/scripts/src/characters/edit.ts @@ -0,0 +1,63 @@ +import { UpdateSkillValueRequest } from "../../_proto/cofd_api_pb"; +import * as api from "../api"; + +(async () => { + //TODO start refactoring these into a separate script, and make API calls + //take all necessary info (e.g. username and character ID, plus other stuff) + //as object params. + //const root = await protobuf.load("/protos/cofd_api.proto"); + + const [, , USERNAME, CHARACTER_ID] = window.location.pathname.split('/'); + + //const api = makeAPI(root); + //console.log("api is", api); + + function setupAttributes() { + // const attributeInputs = document.querySelectorAll('#skills input[type="number"]'); + + // async function skillValueHandler(event: Event) { + // const input = event.target as HTMLInputElement; + // console.log("updating attr"); + // const attribute = input.id; + // const newValue = parseInt(input.value); + // const params = new UpdateSkillValueRequest(); + // params.setCharacterUsername(USERNAME); + // params.setCharacterId(parseInt(CHARACTER_ID)); + // params.setSkillName(attribute); + // params.setSkillValue(newValue); + // await api.updateSkillValue(params); + // } + + // Array.from(attributeInputs).forEach(input => { + // input.addEventListener('change', skillValueHandler); + // }); + } + + function setupSkills() { + const skillInputs = document.querySelectorAll('#skills input[type="number"]'); + + async function skillValueHandler(event: Event) { + const input = event.target as HTMLInputElement; + console.log("updating attr"); + const attribute = input.id; + const newValue = parseInt(input.value); + + const params = new UpdateSkillValueRequest(); + params.setCharacterUsername(USERNAME); + params.setCharacterId(parseInt(CHARACTER_ID)); + params.setSkillName(attribute); + params.setSkillValue(newValue); + + await api.updateSkillValue(params); + } + + Array.from(skillInputs).forEach(input => { + input.addEventListener('change', skillValueHandler); + }); + } + + setupAttributes(); + setupSkills(); +})().catch(e => { + alert(e); +}); diff --git a/static/scripts/src/index.ts b/static/scripts/src/index.ts index 06fbc28..0849a05 100644 --- a/static/scripts/src/index.ts +++ b/static/scripts/src/index.ts @@ -1,8 +1,10 @@ +import * as api from "./api"; import { grpc } from "@improbable-eng/grpc-web"; import { CofdApi } from "../_proto/cofd_api_pb_service"; import { UpdateSkillValueRequest } from "../_proto/cofd_api_pb"; import { CofdSheet } from "../_proto/cofd_pb"; +console.log(api.updateSkillValue); let x = new UpdateSkillValueRequest(); x.setCharacterId(1); x.setCharacterUsername("guy"); diff --git a/static/scripts/tsconfig.json b/static/scripts/tsconfig.json index 8db2126..3f15881 100644 --- a/static/scripts/tsconfig.json +++ b/static/scripts/tsconfig.json @@ -9,7 +9,9 @@ "strictNullChecks": true, "stripInternal": true, "noFallthroughCasesInSwitch": true, - "noEmitOnError": true + "noEmitOnError": true, + "lib": [ + "dom" + ] } } - diff --git a/static/scripts/webpack.config.js b/static/scripts/webpack.config.js index 35ca0d0..9d7bdf8 100644 --- a/static/scripts/webpack.config.js +++ b/static/scripts/webpack.config.js @@ -6,56 +6,59 @@ const path = require('path'); const root = path.resolve(__dirname, '..', '..'); function packPage(page, chunks) { - if (!chunks) chunks = []; - return new HtmlWebpackPlugin({ - template: `${root}/src/templates/${page}`, - filename: `${root}/static/templates/${page}`, - chunks: chunks, - inject: false, - minify: false - }); + if (!chunks) chunks = []; + return new HtmlWebpackPlugin({ + template: `${root}/src/templates/${page}`, + filename: `${root}/static/templates/${page}`, + publicPath: '/scripts/dist', + scriptLoading: 'defer', + chunks: chunks, + inject: false, + minify: false + }); } module.exports = { - entry: { - index: "./src/index.ts", - blah: "./src/blah.ts", + entry: { + index: "./src/index.ts", + edit_character: "./src/characters/edit.ts", + blah: "./src/blah.ts", + }, + optimization: { + runtimeChunk: "single", + splitChunks: { + chunks: 'all', }, - optimization: { - runtimeChunk: "single", - splitChunks: { - chunks: 'all', - }, - }, - mode: "development", - output: { - path: path.resolve(__dirname, 'dist'), - filename: '[name].bundle.js' - }, - devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.ts$/, - include: /src|_proto/, - exclude: /node_modules/, - loader: "ts-loader" - } - ] - }, - resolve: { - extensions: [".ts", ".js"] - }, - plugins: [ - new CleanWebpackPlugin(), - packPage('login.html.tera', ['index']), - packPage('base.html.tera'), - packPage('error.html.tera'), - packPage('index.html.tera'), - packPage('registration.html.tera'), - packPage('characters/edit_character.html.tera'), - packPage('characters/edit_character_macros.html.tera'), - packPage('characters/new_character.html.tera'), - packPage('characters/view_character.html.tera') + }, + mode: "development", + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].bundle.js' + }, + devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.ts$/, + include: /src|_proto/, + exclude: /node_modules/, + loader: "ts-loader" + } ] + }, + resolve: { + extensions: [".ts", ".js"] + }, + plugins: [ + new CleanWebpackPlugin(), + packPage('login.html.tera', ['index']), + packPage('base.html.tera'), + packPage('error.html.tera'), + packPage('index.html.tera'), + packPage('registration.html.tera'), + packPage('characters/edit_character.html.tera', ['edit_character']), + packPage('characters/edit_character_macros.html.tera'), + packPage('characters/new_character.html.tera'), + packPage('characters/view_character.html.tera') + ] };