From 04d82f75a02f7cae360dc17c6be292ffbf78d424 Mon Sep 17 00:00:00 2001 From: techno-newb <100881084+techno-newb@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:17:49 -0700 Subject: [PATCH] updating to latest --- app.js | 168 +++++++++++++++------ index.html | 5 +- pages/editor.html | 42 ++++++ pages/editor.js | 80 ++++++++++ resources/.DS_Store | Bin 0 -> 6148 bytes resources/favicon.ico | Bin 15086 -> 0 bytes resources/old-styles.css | 307 --------------------------------------- resources/styles.css | 49 +++++-- 8 files changed, 283 insertions(+), 368 deletions(-) create mode 100644 pages/editor.html create mode 100644 pages/editor.js create mode 100644 resources/.DS_Store delete mode 100644 resources/favicon.ico delete mode 100644 resources/old-styles.css diff --git a/app.js b/app.js index 90a736c..1d4a951 100644 --- a/app.js +++ b/app.js @@ -25,6 +25,7 @@ class App { patientEverythingToggleContainer: document.getElementById( "patient-everything-toggle-container" ), + editButton: document.getElementById("edit-button"), }; } @@ -42,6 +43,9 @@ class App { // Setup event listeners for the UI elements based on the capability statement this.setupEventListeners(capabilityStatement); } + + // Build the query string when the page loads + this.buildQueryString(); } // Asynchronous function to fetch and validate the capability statement @@ -112,22 +116,55 @@ class App { // Set up the event listeners for the pagination buttons this.setupPaginationButtons(); + + // Add an event listener to the "Edit" button that opens the edit page when clicked + this.getElement.editButton.addEventListener("click", () => + this.openEditPage(this.currentResource) + ); + + // Add an event listener to the read operation toggle + this.getElement.readOperationToggle.addEventListener("change", () => { + this.buildQueryString(); + }); + + // Add an event listener to the patient everything operation toggle + this.getElement.patientEverythingToggle.addEventListener("change", () => { + this.buildQueryString(); + }); + } + + openEditPage(resource) { + // Get the JSON representation of the FHIR resource + const resourceJson = JSON.stringify(resource, null, 2); + + // Encode the JSON string so it can be included in a URL + const encodedJson = encodeURIComponent(resourceJson); + + // Get the server URL + const serverUrl = this.getElement.serverUrl.value; + + // Encode the server URL so it can be included in a URL + const encodedServerUrl = encodeURIComponent(serverUrl); + + // Open the edit page in a new tab and pass the JSON and server URL as URL parameters + window.open( + `./pages/editor.html?resource=${encodedJson}&serverUrl=${encodedServerUrl}`, + "_blank" + ); } // Function to set up event listeners for pagination buttons setupPaginationButtons() { // Add an event listener to the "Next Page" button // When the button is clicked, it retrieves the next page of results - this.getElement.nextPageButton.addEventListener( - "click", - () => this.getNextPage() + this.getElement.nextPageButton.addEventListener("click", () => + this.getNextPage() ); // Add an event listener to the "Previous Page" button // When the button is clicked, it retrieves the previous page of results - this.getElement.previousPageButton.addEventListener( - "click", - () => this.getPreviousPage() + this.getElement.previousPageButton.addEventListener("click", () => + this.getPreviousPage() ); } @@ -156,6 +193,9 @@ class App { // Populate the parameters for the selected resource based on the capability statement this.populateParameters(selectedResource, capabilityStatement); + + // Build the query string when the resource type is changed + this.buildQueryString(); } // Function to handle the event when the form is submitted @@ -238,25 +278,30 @@ class App { // Method to handle addition of a new parameter by the user addParameter() { - // Retrieve user input for parameter name and value const parameterName = this.getElement.parameterNameInput.value; const parameterValue = this.getElement.parameterValueInput.value; - // If both parameter name and value are not empty if (parameterName && parameterValue) { - // Create a container element to display the user added parameter - const parameterContainer = this.createParameterContainer( - parameterName, - parameterValue - ); - - // Append this new parameter container to the parameters container element - this.getElement.parametersContainer.appendChild(parameterContainer); + let parameterContainer; + if (this.getElement.addParameterButton.dataset.editing) { + const parameterContainerId = + this.getElement.addParameterButton.dataset.editing; + parameterContainer = document.getElementById(parameterContainerId); + parameterContainer.querySelector(".userParameterName").innerText = + parameterName; + parameterContainer.querySelector(".userParameterValue").innerText = + parameterValue; + this.getElement.addParameterButton.innerText = "Add Parameter"; + delete this.getElement.addParameterButton.dataset.editing; + } else { + parameterContainer = this.createParameterContainer( + parameterName, + parameterValue + ); + this.getElement.parametersContainer.appendChild(parameterContainer); + } - // Rebuild the query string to include this new parameter this.buildQueryString(); - - // Clear the parameter input fields for next entry this.getElement.parameterNameInput.value = ""; this.getElement.parameterValueInput.value = ""; } @@ -320,11 +365,14 @@ class App { const searchParams = collectSearchParams(); // Create an instance of URLSearchParams with the collected search parameters - const queryParams = new URLSearchParams(searchParams); + const queryParams = new URLSearchParams(); + for (const [key, value] of searchParams) { + queryParams.append(key, value); + } // Check if the read operation toggle is checked const isReadOperation = this.getElement.readOperationToggle.checked; - + // Check if the patient everything operation is checked and the selected resource is 'Patient' const isPatientEverything = this.getElement.patientEverythingToggle.checked && @@ -333,33 +381,33 @@ class App { // Start building the URL with the server URL and the selected resource let queryString = `${serverUrl}/${resourceType}`; - // If it's a read operation and there's an _id parameter, append it to the URL - if (isReadOperation && searchParams._id) { - // Read operation - queryString += `/${searchParams._id}`; - } else if (isPatientEverything) { - // If it's a patient everything operation, append '$everything' to the URL + // Find the _id parameter in the searchParams array + const idParam = searchParams.find((param) => param[0] === "_id"); + + // If it's a patient everything operation, append '$everything' to the URL + if (isPatientEverything) { // If there's an _id parameter, append it to the URL before '$everything' - if (searchParams._id) { + if (idParam) { // Patient $everything operation with _id - queryString += `/${searchParams._id}/$everything`; + queryString += `/${idParam[1]}/$everything`; + // Remove the _id parameter from the queryParams queryParams.delete("_id"); } else { // Patient $everything operation without _id queryString += `/$everything`; } - - //TODO - I think this IF/ELSE statement is doing the same thing - // If there are any parameters left after deleting _id, append them to the URL - if (queryParams.toString().length > 0) { - queryString += `?${queryParams}`; - } - } else { - // If there are any parameters, append them to the URL - const hasSearchParams = Array.from(queryParams).length > 0; - queryString += `${hasSearchParams ? "?" : ""}${queryParams}`; + } else if (isReadOperation && idParam) { + // If it's a read operation and there's an _id parameter, append it to the URL + // Read operation + queryString += `/${idParam[1]}`; + // Remove the _id parameter from the queryParams + queryParams.delete("_id"); } + // If there are any parameters, append them to the URL + const hasSearchParams = Array.from(queryParams).length > 0; + queryString += `${hasSearchParams ? "?" : ""}${queryParams}`; + // Update the query string output text in the form if (this.getElement.queryStringOutput) { this.getElement.queryStringOutput.innerText = queryString; @@ -460,6 +508,8 @@ class App { const cardBody = createCardBody(resource); card.appendChild(cardBody); + + // Add an event listener to the card card.addEventListener("click", () => { const jsonString = JSON.stringify(resource, null, 2); @@ -481,14 +531,24 @@ class App { this.getElement.modal.style.display = "none"; } }; + + // Store the current resource + this.currentResource = resource; + + // Show the "Edit" button + this.getElement.editButton.style.display = "block"; }); return card; } + createParameterContainer(parameterName, parameterValue) { const parameterContainer = document.createElement("div"); parameterContainer.classList.add("form-group"); + // Assign an id to the parameterContainer + parameterContainer.id = `param-${parameterName}`; + const parameterNameElement = document.createElement("span"); parameterNameElement.classList.add("userParameterName"); parameterNameElement.label = "Parameter"; @@ -498,18 +558,38 @@ class App { parameterValueElement.classList.add("userParameterValue"); parameterValueElement.innerText = parameterValue; + const editButton = document.createElement("button"); + editButton.classList.add("edit-button"); + editButton.classList.add("btn"); + editButton.innerText = "Edit"; + editButton.addEventListener("click", (e) => { + e.preventDefault(); // Prevent the form from being submitted + this.getElement.parameterNameInput.value = parameterName; + this.getElement.parameterValueInput.value = parameterValue; + this.getElement.addParameterButton.innerText = "Update Parameter"; + this.getElement.addParameterButton.dataset.editing = parameterContainer; + this.getElement.addParameterButton.dataset.editing = + parameterContainer.id; + }); + const removeButton = document.createElement("button"); removeButton.classList.add("remove-button"); removeButton.classList.add("btn"); - removeButton.innerText = "x"; + removeButton.innerText = "Remove"; removeButton.addEventListener("click", () => { parameterContainer.remove(); this.buildQueryString(); }); + const buttonContainer = document.createElement("div"); + buttonContainer.classList.add("button-container"); + + buttonContainer.appendChild(editButton); + buttonContainer.appendChild(removeButton); + parameterContainer.appendChild(parameterNameElement); parameterContainer.appendChild(parameterValueElement); - parameterContainer.appendChild(removeButton); + parameterContainer.appendChild(buttonContainer); return parameterContainer; } @@ -596,7 +676,7 @@ function createTokenInput(parameter) { } function collectSearchParams() { - const searchParams = {}; + const searchParams = []; document .querySelectorAll( @@ -604,7 +684,7 @@ function collectSearchParams() { ) .forEach((input) => { if (input.value !== "") { - searchParams[input.name] = input.value; + searchParams.push([input.name, input.value]); } }); @@ -621,7 +701,7 @@ function collectSearchParams() { const parameterValue = parameterValueElement.innerText; if (parameterName && parameterValue) { - searchParams[parameterName] = parameterValue; + searchParams.push([parameterName, parameterValue]); } } }); diff --git a/index.html b/index.html index 84d5e69..68909b4 100644 --- a/index.html +++ b/index.html @@ -38,12 +38,12 @@
-
@@ -75,6 +75,7 @@

Query Result

diff --git a/pages/editor.html b/pages/editor.html new file mode 100644 index 0000000..1152036 --- /dev/null +++ b/pages/editor.html @@ -0,0 +1,42 @@ + + + + + Edit FHIR Resource + + + +
+

Edit FHIR Resource

+
+
+ + +
+
+ + +
+
+ +
+
+
+
+ +
+
+ +
+ + + + \ No newline at end of file diff --git a/pages/editor.js b/pages/editor.js new file mode 100644 index 0000000..4d1a7c2 --- /dev/null +++ b/pages/editor.js @@ -0,0 +1,80 @@ +window.addEventListener("load", () => { + // Get the JSON and server URL from the URL parameters + const urlParams = new URLSearchParams(window.location.search); + const resourceJson = urlParams.get("resource"); + const serverUrl = urlParams.get("serverUrl"); + + // Decode the JSON string and server URL + const decodedJson = decodeURIComponent(resourceJson); + const decodedServerUrl = decodeURIComponent(serverUrl); + + // Populate the text area with the JSON + const jsonEditor = document.getElementById("json-editor"); + jsonEditor.value = decodedJson; + + // Adjust the rows attribute of the textarea based on the number of lines in the JSON + jsonEditor.rows = decodedJson.split('\n').length; + + // Set the value of the server URL input field + document.getElementById("server-url").value = decodedServerUrl; + + // Add an event listener for the save button + document + .getElementById("save-button") + .addEventListener("click", () => saveChanges(decodedServerUrl)); +}); + +async function saveChanges() { + // Get the edited JSON from the text area + const editedJson = document.getElementById("json-editor").value; + + // Get the server URL from the input field + const serverUrl = document.getElementById("server-url").value; + + // Get the selected HTTP method + const httpMethod = document.getElementById("http-method").value; + + // Convert the JSON to a JavaScript object + const editedResource = JSON.parse(editedJson); + + // Construct the URL + let url = `${serverUrl}/${editedResource.resourceType}`; + if (httpMethod === "PUT") { + url += `/${editedResource.id}`; + } + + // Send the edited resource to the server + const response = await fetch(url, { + method: httpMethod, + headers: { + "Content-Type": "application/fhir+json", + }, + body: editedJson, + }); + + // Get the response text + const responseText = await response.text(); + + // Create a string with the status and headers + const responseInfo = `Status: ${response.status} ${ + response.statusText + }\n\nHeaders:\n${Array.from(response.headers.entries()) + .map(([key, value]) => `${key}: ${value}`) + .join("\n")}\n\nBody:\n${responseText}`; + + // Display the response in the modal + document.getElementById("json-display").textContent = responseInfo; + document.getElementById("json-modal").style.display = "block"; + + // Close the modal when the close button is clicked + document.getElementById("close-modal").onclick = () => { + document.getElementById("json-modal").style.display = "none"; + }; + + // Close the modal when clicked outside the modal content + window.onclick = (event) => { + if (event.target === document.getElementById("json-modal")) { + document.getElementById("json-modal").style.display = "none"; + } + }; +} diff --git a/resources/.DS_Store b/resources/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..294446ea7e685b7dd90cc6f91ead0da17ba1ff95 GIT binary patch literal 6148 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'); - background-repeat: no-repeat; - background-position: center; - transition: background-color 200ms ease, transform 200ms ease-out; -} -.hljs-copy-button:hover { - border-color: #ffffff44; -} -.hljs-copy-button:active { - border-color: #ffffff66; -} -.hljs-copy-button[data-copied="true"] { - text-indent: 0; - width: auto; - background-image: none; -} -@media (prefers-reduced-motion) { - .hljs-copy-button { - transition: none; - } -} -.hljs-copy-alert { - clip: rect(0 0 0 0); - clip-path: inset(50%); - height: 1px; - overflow: hidden; - position: absolute; - white-space: nowrap; - width: 1px; -} \ No newline at end of file diff --git a/resources/styles.css b/resources/styles.css index 336a917..a16c491 100644 --- a/resources/styles.css +++ b/resources/styles.css @@ -53,9 +53,9 @@ form { .form-group select { padding: 0.5rem; font-size: 1rem; - background-color: #a86969; /* Darker, earthy tone */ - border: 1px solid #f5e6d8; - color: #f5e6d8; + background-color: #f5e6d8; /* Darker, earthy tone #a86969 */ + border: 1px solid #a86969; + color: #a86969; } .form-group input.invalid-server-url { @@ -63,11 +63,12 @@ form { color: #f5e6d8; } -textarea:focus, -input:focus { +textarea, +input { outline: none; - background-color: #b97878; /* Slightly lighter tone for focus */ + background-color: #f5e6d8; /* Slightly lighter tone for focus */ opacity: 1; + resize: none; } .form-group select { @@ -77,14 +78,22 @@ input:focus { .form-row, #parameters-container, .server-container, -.result-card, -.card { +.result-card { background-color: #a86969; border: 2px solid #f5e6d8; /* Thicker border */ padding: 1rem; margin-top: 2rem; } +.card { + background-color: #f5e6d8; + color: #a86969; + padding: 1rem; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + grid-gap: 1rem; +} + .grid-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); @@ -148,15 +157,9 @@ input:focus { color: #f5e6d8; } -.card { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - grid-gap: 1rem; -} - /* Standard syntax */ input::placeholder { - color: #f5e6d8; + color: #a86969; font-family: "Courier New", Courier, monospace; opacity: 0.7; /* Use opacity for lighter color; not all browsers support the 'color' property for placeholders */ } @@ -176,6 +179,22 @@ input::placeholder { background-color: #e5d6c8; } +.button-container { + display: flex; + justify-content: space-between; +} + +.edit-button, .remove-button { + flex: 1; + margin: 0.5em; +} + +#json-editor { + font-family: "Courier New", Courier, monospace; + white-space: pre; + overflow: auto; +} + .result-container { display: grid; grid-template-columns: 1fr;