From 8ee9b0b7b5d947e95358c60f4867519512b874c0 Mon Sep 17 00:00:00 2001 From: CherrelleTucker <106271365+CherrelleTucker@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:50:28 -0600 Subject: [PATCH] resolve #79 --- DynamicDocToGitHubIssue/QuickGit__index.html | 302 --- QuickGit/QuickGit__index.html | 2146 ++++++++++++++++++ 2 files changed, 2146 insertions(+), 302 deletions(-) delete mode 100644 DynamicDocToGitHubIssue/QuickGit__index.html create mode 100644 QuickGit/QuickGit__index.html diff --git a/DynamicDocToGitHubIssue/QuickGit__index.html b/DynamicDocToGitHubIssue/QuickGit__index.html deleted file mode 100644 index 98d6b0a..0000000 --- a/DynamicDocToGitHubIssue/QuickGit__index.html +++ /dev/null @@ -1,302 +0,0 @@ -/** Contains web app specific functions (doGet, handling web requests) - - Contains doGet function for serving the web app - - Has endpoint functions called directly by the frontend - - Handles web-specific error reporting - - Acts as a bridge between the frontend and core functionality -**/ - -/** - * Handles web app requests and OAuth flow - * @param {Object} e - Event object from web app - * @returns {HtmlOutput} The HTML page - */ -function doGet(e) { - // Handle OAuth callback - if (e.parameter.code) { - const result = handleOAuthCallback(e.parameter.code, e.parameter.state); - if (!result.success) { - return HtmlService.createHtmlOutput( - `

Authentication Failed

-

Error: ${result.error}

-

Please close this window and try again.

` - ); - } - return HtmlService.createHtmlOutput( - `

Authentication Successful!

-

You can close this window and return to QuickGit Refresh the page to access the tool.

- ` - ); - } - - // Check if user is authenticated - const userProperties = PropertiesService.getUserProperties(); - const isAuthenticated = Boolean(userProperties.getProperty('github_access_token')); - - // Create template and add authentication state - const template = HtmlService.createTemplateFromFile('index'); - template.isAuthenticated = isAuthenticated; - - // Log authentication state for debugging - console.log('User authentication state:', isAuthenticated); - - return template.evaluate() - .setTitle('QuickGit') - .setFaviconUrl('https://raw.githubusercontent.com/CherrelleTucker/snwg-automation/348c5c6f451c951c6a4558fec69e75809886aa45/DocToGitHubTransferToolIcon.png') - .addMetaTag('viewport', 'width=device-width, initial-scale=1'); -} - -/** - * Checks if user is authenticated - * @returns {boolean} Authentication status - */ -function checkAuthStatus() { - const userProperties = PropertiesService.getUserProperties(); - return Boolean(userProperties.getProperty('github_access_token')); -} - -function processDocument(docUrl) { - try { - const doc = DocumentApp.openByUrl(docUrl); - if (!doc) { - return { error: 'Invalid document URL or no access to document' }; - } - - // Get document metadata - const docMetadata = { - title: doc.getName(), - url: docUrl - }; - - // First use the working parser to get the basic structure - const content = doc.getBody().getText(); - const basicParsed = parseDocContent(content, docMetadata); - - // Now use parseDocContentWithFormatting to get formatted versions - const formattedParsed = parseDocContentWithFormatting(doc.getBody(), docMetadata); - - // Merge the results, preserving the working issue recognition from basicParsed - // but using the formatted content from formattedParsed - const mergedResults = { - newIssues: basicParsed.newIssues.map((issue, index) => ({ - ...issue, - body: formattedParsed.newIssues[index]?.body || issue.body - })), - updateIssues: basicParsed.updateIssues.map((issue, index) => ({ - ...issue, - comment: formattedParsed.updateIssues[index]?.body || issue.comment - })) - }; - - // Validate parsed content - if (!mergedResults.newIssues.length && !mergedResults.updateIssues.length) { - return { error: 'No new issues or updates found in document' }; - } - - return mergedResults; - } catch (error) { - console.error('Error processing document:', error); - return { error: error.message || 'Failed to process document' }; - } -} - -/** - * Processes issues based on UI data - * @param {Object} data - Data object containing issue information - * @param {Array} data.newIssues - Array of new issues to create - * @param {Array} data.updateIssues - Array of issues to update - * @returns {Object} Results of processing containing created, updated, and error information - * @throws {Error} If data validation fails - */ -function processIssues(data) { - try { - // Input validation - if (!data) { - throw new Error('No data provided for processing'); - } - - // Initialize results object - const results = { - created: [], - updated: [], - errors: [], - links: [] // Array to store URLs and metadata - }; - - // Process new issues if they exist - if (data.newIssues && Array.isArray(data.newIssues)) { - for (const issue of data.newIssues) { - try { - // Validate required fields - if (!issue.repo || !issue.title || !issue.body) { - throw new Error(`Missing required fields for new issue: ${issue.title}`); - } - - // Create the issue - const createdIssue = createIssue(issue.repo, { - title: issue.title, - body: issue.body, - assignees: issue.assignee ? [issue.assignee] : [] - }); - - // Store issue number and URL - results.created.push(createdIssue.number); - results.links.push({ - type: 'issue', - number: createdIssue.number, - url: createdIssue.html_url, - repo: issue.repo, - title: issue.title - }); - - } catch (error) { - results.errors.push(`Failed to create issue "${issue.title}": ${error.message}`); - } - } - } - - // Process update issues if they exist - if (data.updateIssues && Array.isArray(data.updateIssues)) { - for (const update of data.updateIssues) { - try { - // Validate required fields - if (!update.repo || !update.issueNumber || !update.comment) { - throw new Error(`Missing required fields for update issue #${update.issueNumber}`); - } - - // add the comment - const updatedIssue = updateIssue(update.repo, update.issueNumber, update.comment); - - // Store issue number and comment url - results.updated.push(update.issueNumber); - results.links.push({ - type: 'comment', - number: update.issueNumber, - url: updatedIssue.html_url, - repo: update.repo - }); - - } catch (error) { - results.errors.push(`Failed to update issue #${update.issueNumber}: ${error.message}`); - } - } - } - - return results; - - } catch (error) { - throw new Error(`Failed to process issues: ${error.message}`); - } -} - -/** - * Validates an individual issue object - * @param {Object} issue - Issue object to validate - * @param {string} type - Type of issue ('new' or 'update') - * @returns {boolean} True if valid, false otherwise - */ -function validateIssue(issue, type) { - if (type === 'new') { - return issue && issue.repo && issue.title && issue.body; - } else if (type === 'update') { - return issue && issue.repo && issue.issueNumber && issue.comment; - } - return false; -} - -/** - * Gets repositories for frontend display - * @returns {Array} List of repositories - */ -function getRepos() { - try { - Logger.log('WebApp: Fetching repositories for frontend'); - const allRepos = fetchOrgRepos(); - Logger.log(`WebApp: Returning ${allRepos.length} repositories to frontend`); - return allRepos.map(repo => ({ - name: repo.name - })); - } catch (error) { - Logger.log('WebApp: Error in getRepos: ' + error.message); - throw new Error('Failed to fetch repositories: ' + error.message); - } -} - -/** - * Gets the list of organization members for the frontend - * @returns {Array} List of members - */ -function getMembers() { - try { - return fetchOrgMembers(); - } catch (error) { - Logger.log('Error in getMembers: ' + error.message); - throw new Error('Failed to fetch members: ' + error.message); - } -} - -/** - * Fetches open issues for a repository with recursion protection - * @param {string} repoName - Repository name - * @returns {Array} List of open issues - */ -function fetchRepoIssues(repoName) { - // Add guard for recursive calls - if (!repoName) { - throw new Error('Repository name is required'); - } - - try { - const client = createGitHubClient(); - const url = `${client.baseUrl}/repos/${CONFIG.ORG_NAME}/${repoName}/issues?state=open&per_page=100`; - - // Make a single API call with proper error handling - const response = UrlFetchApp.fetch(url, { - headers: client.headers, - muteHttpExceptions: true - }); - - // Check response code first - const responseCode = response.getResponseCode(); - if (responseCode !== 200) { - console.error('Error response:', response.getContentText()); - throw new Error(`GitHub API returned status ${responseCode}`); - } - - // Parse response once - const issues = JSON.parse(response.getContentText()); - - // Return simplified issue objects - return issues.map(issue => ({ - number: issue.number, - title: issue.title, - state: issue.state, - url: issue.html_url - })); - - } catch (error) { - console.error('Error in fetchRepoIssues:', error); - throw new Error(`Failed to fetch issues: ${error.message}`); - } -} - -/** - * Parses the document and returns structured content - * Called by the frontend when processing a document - * @param {string} docUrl - The URL of the document to process - * @returns {Object} Parsed document content - */ -function parseDocument(docUrl) { - try { - Logger.log('WebApp: Starting to parse document: ' + docUrl); - const results = processGoogleDoc(docUrl); - Logger.log('WebApp: Processing results: ' + JSON.stringify(results)); - return results; - } catch (error) { - Logger.log('WebApp: Error in parseDocument: ' + error.message); - throw new Error(error.message); - } -} - - - - diff --git a/QuickGit/QuickGit__index.html b/QuickGit/QuickGit__index.html new file mode 100644 index 0000000..adae4a2 --- /dev/null +++ b/QuickGit/QuickGit__index.html @@ -0,0 +1,2146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+

QuickGit

+ +
+ + +
+ + +
+ + + +
+
+ + +
+ +
+ + +
+
+ + +
+
+

New Issues

+
+
+

Update Issues

+
+ +
+
+ + + + + + + + + + + + + + +