Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions 404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="refresh" content="0; url=/?page=">
<script>
// Extract the path from URL (e.g., /cms) and redirect
(function () {
const repoName = "codejson-generator"; // change if needed
const pages = ["gov", "cms"];
const path = window.location.pathname.replace(`/${repoName}`, "").replace(/^\/+/, "").replace(/\/$/, "");
const redirectPage = pages.includes(path);
if (redirectPage) {
var newUrl = `/${repoName ? repoName + "/" : ""}?page=${encodeURIComponent(path)}`;
window.location.replace(newUrl);
}
})();
</script>
</head>

<body>
<p>Page not found.</p>
</body>

</html>
163 changes: 72 additions & 91 deletions js/formDataToJson.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ async function retrieveFile(filePath) {

function isMultiSelect(obj) {
for (const key in obj) {
if (typeof obj[key] !== 'boolean') {
return false;
}
if (typeof obj[key] !== 'boolean') {
return false;
}
}
return true; // Returns true if all values are booleans
}

// Convert from dictionary to array
function getSelectedOptions(options) {
let selectedOptions = [];

for (let key in options) {
if(options[key]) {
selectedOptions.push(key);
}
}
return selectedOptions;
let selectedOptions = [];

for (let key in options) {
if (options[key]) {
selectedOptions.push(key);
}
}
return selectedOptions;
}

// Populates fields with form data
Expand All @@ -46,7 +46,7 @@ function populateObject(data, schema) {
let value = data[key];

// Adjusts value accordingly if multi-select field
if((typeof value === "object" && isMultiSelect(value))) {
if ((typeof value === "object" && isMultiSelect(value))) {
value = getSelectedOptions(value);
}

Expand All @@ -57,7 +57,10 @@ function populateObject(data, schema) {
}

async function populateCodeJson(data) {
const filePath = "schemas/schema.json";
// Fetching schema based on search params
const params = new URLSearchParams(window.location.search);
const page = params.get("page") || "gov";
const filePath = `schemas/${page}/schema.json`;

// Retrieves schema with fields in correct order
const schema = await retrieveFile(filePath);
Expand Down Expand Up @@ -87,37 +90,33 @@ async function createCodeJson(data) {
}

// Copies code.json to clipboard
async function copyToClipboard(event){
async function copyToClipboard(event) {
event.preventDefault();

var textArea = document.getElementById("json-result");
textArea.select();
textArea.select();
document.execCommand("copy")
}

const NEW_BRANCH = 'code-json-branch' + Math.random().toString(36).substring(2, 10);

function getOrgAndRepoArgsGitHub(url)
{
function getOrgAndRepoArgsGitHub(url) {
const pattern = /https:\/\/github\.com\/([^\/]+)\/([^\/]+)/;
const match = url.match(pattern);
const match = url.match(pattern);

if(match)
{
if (match) {
const owner = match[1];
const repo = match[2];
return {owner,repo};
return { owner, repo };
}
else
{
else {
throw new Error('Invalid URL!');
}
}


async function createBranchOnProject(projectURL, token)
{
const {owner, repo} = getOrgAndRepoArgsGitHub(projectURL);
async function createBranchOnProject(projectURL, token) {
const { owner, repo } = getOrgAndRepoArgsGitHub(projectURL);

const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/git/refs/heads/main`,
{
Expand All @@ -130,58 +129,53 @@ async function createBranchOnProject(projectURL, token)

const data = await response.json();

if (response.ok)
{
if (response.ok) {
const sha = data.object.sha;

const createBranchApiUrl = `https://api.github.com/repos/${owner}/${repo}/git/refs`;

// Create the new branch from the base branch
const newBranchResponse = await fetch(createBranchApiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `token ${token}`,
'Content-Type': 'application/json',
'Authorization': `token ${token}`,
},
body: JSON.stringify({
ref: `refs/heads/${NEW_BRANCH}`, // Name of the new branch
sha: sha, // SHA of the base branch (main)
ref: `refs/heads/${NEW_BRANCH}`, // Name of the new branch
sha: sha, // SHA of the base branch (main)
}),
});

const newBranchData = await newBranchResponse.json();

if ( newBranchResponse.ok )
{
if (newBranchResponse.ok) {
console.log('New branch created successfully: ', newBranchData);
return true;
}
else
{
else {
console.error('Error creating new branch: ', newBranchData);
alert("Failed to create branch on project! Error code: " + newBranchResponse.status + ". Please check API Key permissions and try again.")
return false;
}
}
else
{
else {
console.error('Error fetching base branch info:', data);
alert('Error fetching base branch info:', data);
return false;
}
}


async function addFileToBranch(projectURL, token, codeJSONObj)
{
const {owner, repo} = getOrgAndRepoArgsGitHub(projectURL);
async function addFileToBranch(projectURL, token, codeJSONObj) {
const { owner, repo } = getOrgAndRepoArgsGitHub(projectURL);
const FILE_PATH = 'code.json'
const createFileApiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${FILE_PATH}`;
const encodedContent = btoa(codeJSONObj);
console.log("Content: ", encodedContent);
console.log("Branch: ", NEW_BRANCH);

const response = await fetch(createFileApiUrl,
const response = await fetch(createFileApiUrl,
{
method: 'PUT',
headers: {
Expand All @@ -203,24 +197,21 @@ async function addFileToBranch(projectURL, token, codeJSONObj)

const data = await response.json()

if ( response.ok )
{
if (response.ok) {
console.log('File added successfully: ', data);
return true;
}
else
{
else {
console.error('Error adding file: ', data);
alert("Failed to add file on project! Error code: " + response.status + ". Please check API Key permissions and try again.")
return false;
}
}

async function createPR(projectURL, token)
{
const {owner, repo} = getOrgAndRepoArgsGitHub(projectURL);
async function createPR(projectURL, token) {
const { owner, repo } = getOrgAndRepoArgsGitHub(projectURL);
const createPrApiUrl = `https://api.github.com/repos/${owner}/${repo}/pulls`;
const response = await fetch(createPrApiUrl,
const response = await fetch(createPrApiUrl,
{
method: 'POST',
headers: {
Expand All @@ -240,64 +231,54 @@ async function createPR(projectURL, token)

const data = await response.json();

if (response.ok)
{
if (response.ok) {
console.log('Pull request created successfully: ', data);
return true;
}
else
{
else {
console.error("Error creating PR!: ", data);
alert("Failed to create PR on project! Error code: " + response.status + ". Please check API Key permissions and try again.")
return false;
}
}

// Creates PR on requested project
async function createProjectPR(event){
async function createProjectPR(event) {
event.preventDefault();

var textArea = document.getElementById("json-result");//Step 1
var codeJSONObj = JSON.parse(textArea.value)

if('gh_api_key' in window)
{

if ('gh_api_key' in window) {
var apiKey = window.gh_api_key;

if ('repositoryURL' in codeJSONObj)
{

if ('repositoryURL' in codeJSONObj) {
var prCreated = false;
//Step 1
const branchCreated = await createBranchOnProject(codeJSONObj.repositoryURL,apiKey);
if (branchCreated)
{
const branchCreated = await createBranchOnProject(codeJSONObj.repositoryURL, apiKey);
if (branchCreated) {
const fileAdded = await addFileToBranch(codeJSONObj.repositoryURL, apiKey, textArea.value);

if (fileAdded)
{
if (fileAdded) {
prCreated = await createPR(codeJSONObj.repositoryURL, apiKey);
if(prCreated)
{
if (prCreated) {
console.log("PR successfully created!");
alert("PR has been created!");
}
}
}
else
{
else {
console.error("Could not create branch on requested repository with the requested API key!");
alert("Could not create branch on requested repository with the requested API key!");
}
}
else
{
else {
console.error("No URL found!");
alert("No URL given for project! Please provide project URL in repositoryURL text box");
}

}
else
{
else {
console.error("No API key found!");
alert("No API Key in submitted data! Please provide an API key");
}
Expand Down Expand Up @@ -328,27 +309,27 @@ async function emailFile(event) {

const codeJson = document.getElementById("json-result").value
const jsonObject = JSON.parse(codeJson);

try {
const cleanData = {...jsonObject};
delete cleanData.submit;

const jsonString = JSON.stringify(cleanData, null, 2);
try {
const cleanData = { ...jsonObject };
delete cleanData.submit;

const jsonString = JSON.stringify(cleanData, null, 2);

const subject = "Code.json generator Results";
const body = `Hello,\n\nHere are the code.json results:\n\n${jsonString}\n\nThank you!`;
const subject = "Code.json generator Results";
const body = `Hello,\n\nHere are the code.json results:\n\n${jsonString}\n\nThank you!`;

const recipients = ["opensource@cms.hhs.gov"];
const recipients = ["opensource@cms.hhs.gov"];

const mailtoLink = `mailto:${recipients}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
const mailtoLink = `mailto:${recipients}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;

window.location.href = mailtoLink;
window.location.href = mailtoLink;

console.log("Email client opened");
} catch {
console.error("Error preparing email:", error);
showNotificationModal("Error preparing email. Please try again or copy the data manually.", 'error');
}
console.log("Email client opened");
} catch {
console.error("Error preparing email:", error);
showNotificationModal("Error preparing email. Please try again or copy the data manually.", 'error');
}
}

window.createCodeJson = createCodeJson;
Expand Down
Loading
Loading