splitbill/annotation-tool
0
1<html>2<head>3 <link href="https://cdnjs.cloudflare.com/ajax/libs/flowbite/1.6.3/flowbite.min.css" rel="stylesheet" />4</head>5 6<!--7----------------------------------------------------8Your custom static HTML goes in the body:9-->10 11<body>12 <div class="inline-flex rounded-md shadow-sm" role="group">13 <button id="up" type="button" onclick="call(this)" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-l-lg hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white">14 <svg aria-hidden="true" class="w-4 h-4 mr-2 fill-current" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">15 <path fill-rule="evenodd" d="M4.5 15.75l7.5-7.5 7.5 7.5" clip-rule="evenodd"></path>16 </svg>17 Up18 </button>19 <button id="down" type="button" onclick="call(this)" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-900 bg-white border-t border-b border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white">20 <svg aria-hidden="true" class="w-4 h-4 mr-2 fill-current" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">21 <path d="M19.5 8.25l-7.5 7.5-7.5-7.5"></path>22 </svg>23 Down24 </button>25 <button id="save" type="button" onclick="call(this)" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-r-md hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white">26 <svg aria-hidden="true" class="w-4 h-4 mr-2 fill-current" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">27 <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd"></path>28 </svg>29 Save30 </button>31 </div>32</body>33 34<script type="text/javascript">35 // ----------------------------------------------------36 // Use these functions as is to perform required Streamlit37 // component lifecycle actions:38 //39 // 1. Signal Streamlit client that component is ready40 // 2. Signal Streamlit client to set visible height of the component41 // (this is optional, in case Streamlit doesn't correctly auto-set it)42 // 3. Pass values from component to Streamlit client43 //44 45 // Helper function to send type and data messages to Streamlit client46 47 const SET_COMPONENT_VALUE = "streamlit:setComponentValue"48 const RENDER = "streamlit:render"49 const COMPONENT_READY = "streamlit:componentReady"50 const SET_FRAME_HEIGHT = "streamlit:setFrameHeight"51 52 function _sendMessage(type, data) {53 // copy data into object54 var outboundData = Object.assign({55 isStreamlitMessage: true,56 type: type,57 }, data)58 59 if (type == SET_COMPONENT_VALUE) {60 console.log("_sendMessage data: " + JSON.stringify(data))61 console.log("_sendMessage outboundData: " + JSON.stringify(outboundData))62 }63 64 window.parent.postMessage(outboundData, "*")65 }66 67 function initialize(pipeline) {68 69 // Hook Streamlit's message events into a simple dispatcher of pipeline handlers70 window.addEventListener("message", (event) => {71 if (event.data.type == RENDER) {72 // The event.data.args dict holds any JSON-serializable value73 // sent from the Streamlit client. It is already deserialized.74 pipeline.forEach(handler => {75 handler(event.data.args)76 })77 }78 })79 80 _sendMessage(COMPONENT_READY, { apiVersion: 1 });81 82 // Component should be mounted by Streamlit in an iframe, so try to autoset the iframe height.83 window.addEventListener("load", () => {84 window.setTimeout(function () {85 setFrameHeight(document.documentElement.clientHeight)86 }, 0)87 })88 89 // Optionally, if auto-height computation fails, you can manually set it90 // (uncomment below)91 //setFrameHeight(200)92 }93 94 function setFrameHeight(height) {95 _sendMessage(SET_FRAME_HEIGHT, { height: height })96 }97 98 // The `data` argument can be any JSON-serializable value.99 function notifyHost(data) {100 _sendMessage(SET_COMPONENT_VALUE, data)101 }102 103 // ----------------------------------------------------104 // Your custom functionality for the component goes here:105 106 function call(button) {107 timestamp = Date.now()108 action = {109 "action": button.id,110 "timestamp": timestamp111 }112 notifyHost({113 value: action,114 dataType: "json",115 })116 }117 118 // ----------------------------------------------------119 // Here you can customize a pipeline of handlers for120 // inbound properties from the Streamlit client app121 122 // Set initial value sent from Streamlit!123 function initializeProps_Handler(props) {124 for (let key of Object.keys(props.buttons)) {125 btn = document.getElementById(key)126 btn.disabled = props.buttons[key]['disabled']127 btn.style.display = props.buttons[key]['rendered']128 }129 }130 // Access values sent from Streamlit!131 function dataUpdate_Handler(props) {132 // let msgLabel = document.getElementById("message_label")133 // msgLabel.innerText = `Update [${props.counter}] at ${props.datetime}`134 }135 // Simply log received data dictionary136 function log_Handler(props) {137 console.log("Received from Streamlit: " + JSON.stringify(props))138 }139 140 let pipeline = [initializeProps_Handler, dataUpdate_Handler, log_Handler]141 142 // ----------------------------------------------------143 // Finally, initialize component passing in pipeline144 145 initialize(pipeline)146 147</script>148 149</html>