Hello Everyone
cc: @asehmi @aghasemi @thiago
I deployed my streamlit app with a custom component using this post as an example.
After deploying my streamlit as a microservice in kubernetes, I am getting this error up on the screen
Your app is having trouble loading the idx_db_component.frontend.idxdb_component component.
If this is an installed component that works locally, the app may be having trouble accessing the component frontend assets due to network latency or proxy settings in your app deployment.
I really need urgent help. Please advise.
<!-- See: https://discuss.streamlit.io/t/code-snippet-create-components-without-any-frontend-tooling-no-react-babel-webpack-etc/13064 -->
<style>
body {
background-color: lightblue;
border-color: rgb(246, 51, 102);
border-width: medium;
font-family: sans-serif;
font-size: 16px;
}
h1 {
font-family: sans-serif;
font-size: 24px;
font-weight: normal;
color: #262730;
}
#message_div {
font-family: sans-serif;
font-size: 12px;
font-weight: normal;
color: #262730;
}
</style>
<html>
<head>
<script src="./idxdbwrapper.js"></script>
</head>
<body>
<script>
const SET_COMPONENT_VALUE = "streamlit:setComponentValue"
const RENDER = "streamlit:render"
const COMPONENT_READY = "streamlit:componentReady"
const SET_FRAME_HEIGHT = "streamlit:setFrameHeight"
function _sendMessage(type, data) {
// copy data into object
var outData = Object.assign({
isStreamlitMessage: true,
type: type,
}, data)
if (type == SET_COMPONENT_VALUE) {
console.log("_sendMessage data: " + JSON.stringify(data))
console.log("_sendMessage outData: " + JSON.stringify(outData))
}
window.parent.postMessage(outData, "*")
}
function initialize(pipeline) {
// Hook Streamlit's message events into a simple dispatcher of pipeline handlers
window.addEventListener("message", (event) => {
if (event.data.type == RENDER) {
// The event.data.args dict holds any JSON-serializable value
// sent from the Streamlit client. It is already deserialized.
pipeline.forEach(handler => {
handler(event.data.args)
})
}
})
_sendMessage(COMPONENT_READY, { apiVersion: 1 });
// Component should be mounted by Streamlit in an iframe, so try to autoset the iframe height.
window.addEventListener("load", () => {
window.setTimeout(function () {
// setFrameHeight(document.documentElement.clientHeight)
setFrameHeight(1)
}, 0)
})
// Optionally, if auto-height computation fails, you can manually set it
// (uncomment below)
//setFrameHeight(200)
}
function setFrameHeight(height) {
_sendMessage(SET_FRAME_HEIGHT, { height: height })
}
// The `data` argument can be any JSON-serializable value.
function notifyHost(data) {
_sendMessage(SET_COMPONENT_VALUE, data)
}
function sortJsonListByTimestampDesc(jsonList) {
return jsonList.sort((a, b) => {
const timestampA = new Date(a.timestamp);
const timestampB = new Date(b.timestamp);
return timestampB - timestampA;
}).slice(0, 20); // Add .slice(0, 10) to get the top 10
}
// ----------------------------------------------------
// Define a pipeline of inbound property handlers
let isInitialized = false;
// Set initial value sent from Streamlit!
function initializeProps_Handler(props) {
if (!isInitialized) { // Check the flag
isInitialized = true; // Set the flag
setTimeout(async function() {
db = await initDb("askgbp", "sessions", 1, "sessionid", "sessionid");
// if (props.operation.includes("set")) {
await createRecord(db, "sessions", {"sessionid": props.sessionid, "timestamp": new Date().toISOString()});
notifyHost({
value: props.sessionid,
dataType: "json",
})
// }
// if (props.operation.includes("get")) {
let records = await getAllRecords(db, "sessions");
notifyHost({
value: sortJsonListByTimestampDesc(records),
dataType: "json",
})
// }
}, 5);
}
}
// Access values sent from Streamlit!
function dataUpdate_Handler(props) {
}
// Simply log received data dictionary
function log_Handler(props) {
console.log("Received from Streamlit: " + JSON.stringify(props))
}
let pipeline = [initializeProps_Handler, dataUpdate_Handler, log_Handler]
// ----------------------------------------------------
// Finally, initialize component passing in pipeline
initialize(pipeline)
</script>
</body>
</html>
idxdbwrapper.js
async function initDb(db, store, version, key, idx, uniq=false) {
return new Promise((resolve, reject) => {
let request = indexedDB.open(db, version);
request.onerror = event => {
alert('Error Event, check console');
console.error(event);
}
request.onupgradeneeded = event => {
console.log('idb onupgradeneeded firing');
let db = event.target.result;
let objectStore = db.createObjectStore(store, { keyPath: key, autoIncrement:true });
objectStore.createIndex(idx, idx, { unique: uniq });
};
request.onsuccess = event => {
resolve(event.target.result);
};
});
}
async function getAllRecords(db, s) {
return new Promise((resolve, reject) => {
let transaction = db.transaction([s], 'readonly');
transaction.onerror = event => {
reject(event);
};
let store = transaction.objectStore(s);
store.getAll().onsuccess = event => {
resolve(event.target.result);
};
});
}
async function getAllRecordsByKey(db, s, k, idxname) {
return new Promise((resolve, reject) => {
let transaction = db.transaction([s], 'readonly');
var objectStore = transaction.objectStore("logs");
const index = objectStore.index(idxname);
let query = index.getAll(k);
query.onsuccess = function(event) { resolve(event.target.result); };
query.onerror = function(event) { reject(event); };
// transaction.oncomplete = function(event) { db.close(); };
});
}
async function createRecord(db, s, data) {
return new Promise((resolve, reject) => {
let transaction = db.transaction([s], 'readwrite');
transaction.oncomplete = event => {
resolve();
};
transaction.onerror = event => {
reject(event);
};
let store = transaction.objectStore(s);
store.put(data);
});
}
async function removeRecord(db, store, key) {
return new Promise((resolve, reject) => {
let transaction = db.transaction([store], 'readwrite');
transaction.oncomplete = event => {
resolve();
};
transaction.onerror = event => {
reject(event);
};
let store = transaction.objectStore(store);
store.delete(key);
});
}
function deleteDB(db) {
let DBDeleteRequest = window.indexedDB.deleteDatabase(db);
DBDeleteRequest.onerror = (event) => {
console.error("Error deleting database.");
};
DBDeleteRequest.onsuccess = (event) => {
console.log("Database deleted successfully");
console.log(event.result); // should be undefined
};
}