diff --git a/app/MiscUnit.js b/app/MiscUnit.js index 6322c14..0672d68 100644 --- a/app/MiscUnit.js +++ b/app/MiscUnit.js @@ -35,23 +35,24 @@ class MiscUnit extends Unit { // do stuff here global.devbug = { - version: '0.2.0', + version: '0.5.1', code: { node: `require("devbugjs") dbsetup({ \tserver: "https://CHANGEME:8000/", // DevBug Server URL \tproject: "CHANGEME", // Project API Key })`, - api: `Send a multipart/form-data POST request to: -http(s):///api/v1/out/ + api: `// Send a multipart/form-data POST request to: +// http://#{_flitter.config('server.url')}/api/v1/out/ -The form should have a single field with the name "data". -This field should contain a valid JSON string with the following structure: +// The form should have a single field with the name "data". +// This field should contain a valid JSON string with the following structure: { "brief": "Some preview text to be displayed. Whatever you want.", "data": { - // the output data (key-pairs) goes here - } + // the output data (key-pairs) goes here: + "some name": "some data", + }, }`, php: ` $what ]; -\t\t} -\t\telse { -\t\t\t$dev_outs[$group][$key] = $what; -\t\t} -\t} -\telse { -\t\t$dev_outs[$key] = $what; -\t} + global $dev_outs; + if ( $group ){ + if ( !array_key_exists($group, $dev_outs) ){ + $dev_outs[$group] = [ $key => $what ]; + } + else { + $dev_outs[$group][$key] = $what; + } + } + else { + $dev_outs[$key] = $what; + } } -function breakpoint($html = false, $name = null){ -\tglobal $dev_outs; -\t$devbug = "http://CHANGEME:8000/"; -\t$project_api_key = "CHANGEME"; -\t$bt = debug_backtrace(); -\t$caller = array_shift($bt); +function breakpoint($continue = false, $name = null){ + global $dev_outs; + $devbug = "http://localhost:8000/"; + $project_api_key = "CHANGEME"; + $bt = debug_backtrace(); + $caller = array_shift($bt); -\tif ( !$html ){ -\t\tvar_dump([($item ? $item : $caller), 'outs' => $dev_outs]); -\t} -\telse { -\t\techo "
";
-\t\tvar_dump([($item ? $item : $caller), 'outs' => $dev_outs]);
-\t\techo "
"; -\t} + // Send to devbug server + $ch = curl_init(); + $url = $devbug.'api/v1/out/'.$project_api_key; + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, [ + 'data' => json_encode([ + 'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'], + 'data' => $dev_outs, + ]) + ]); -\t// Send to devbug server -\t$ch = curl_init(); -\t$url = $devbug.'api/v1/out/'.$project_api_key; -\tvar_dump($url); -\tcurl_setopt($ch, CURLOPT_URL, $url); -\tcurl_setopt($ch, CURLOPT_POST, 1); -\tcurl_setopt($ch, CURLOPT_POSTFIELDS, [ -\t 'data' => json_encode([ -\t 'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'], -\t 'data' => $dev_outs, -\t ]) -\t]); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -\tcurl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -\t -\t$odata = curl_exec($ch); + $odata = curl_exec($ch); -\texit(); + if ( !$continue ) { exit(); } } // ===========================================================`, - js: `// =========================================================== -// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER -// TODO: REMOVE BEFORE COMMITTING -let outs = {} -const devbug_url = 'http://CHANGEME:8000/' -const project_api_key = 'CHANGEME' -const out = (key, what, group=false) => { - if ( group ){ - if ( Object.keys(outs).includes(group) ) outs[group][key] = what - else outs[group] = {}; outs[group][key] = where - } - else { - outs[key] = what - } -} -const breakpoint = (html = false, name = null) => { - var e = new Error(); - (function() { - // Load the script - var script = document.createElement("SCRIPT"); - script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js'; - script.type = 'text/javascript'; - script.onload = () => { - var $ = window.jQuery; - $(() => { - e = e.stack.split('at'); var caller = ''; - if ( e.length < 3 ) e = e.stack.split('@') - if ( e.length > 2 ) caller = e[2].trim() - else if ( e.length > 1 ) caller = e[1] - else caller = 'Unable to determine stacktrace' - var data = new FormData(); - data.append('data', JSON.stringify({brief: (name ? name : 'Breakpoint: ')+caller,data: outs})) - $.ajax({ - url: devbug_url+'api/v1/out/'+project_api_key, - data: data, cache: false, contentType: false, processData: false, method: 'POST', type: 'POST', - success: (res) => { console.log('DevBug POST Completed'); console.log(res) } - }) - }); - }; - document.getElementsByTagName("head")[0].appendChild(script); - })(); -} -if ( window ) window.out = out; window.breakpoint = breakpoint; -// ===========================================================` }, permission: { project: { diff --git a/app/assets/dash_v1.css b/app/assets/dash_v1.css index 06c54b0..795b112 100644 --- a/app/assets/dash_v1.css +++ b/app/assets/dash_v1.css @@ -88,7 +88,7 @@ a { color: #eee; } -.btn { +.btn, .action { margin: 5; margin-bottom: 20; padding: 5; @@ -101,7 +101,13 @@ a { transition: all 0.5s ease; } -.btn:hover { +.action { + padding: 0; + padding-left: 5; + padding-right: 5; +} + +.btn:hover, .action:hover { background: #eee; color: #307d7d; } @@ -115,7 +121,7 @@ pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; } .action-li { display: inline; - margin-right: 15px; + /*margin-right: 15px;*/ } #editor { diff --git a/app/controllers/dash/v1.controller.js b/app/controllers/dash/v1.controller.js index 7b0fae1..cfc15e5 100644 --- a/app/controllers/dash/v1.controller.js +++ b/app/controllers/dash/v1.controller.js @@ -538,6 +538,20 @@ class v1 { return res.redirect('/dash/v1/project/snippet/'+project.id+'/view/'+snippet.uuid) } + + async show_usage_page(req, res, next){ + const valid_pages = ['main', 'node', 'php', 'ecma', 'api']; + + if ( !valid_pages.includes(req.params.page) ) return _flitter.error(res, 404, {reason: 'The page could not be found.'}) + + const title = req.params.page.charAt(0).toUpperCase() + req.params.page.slice(1); + + return _flitter.view(res, 'dash_v1:use:'+req.params.page.replace(/\W/g, ''), { + show_back: true, + title: 'Using DevBug - '+title, + user: req.session.auth.user, + }) + } } module.exports = exports = v1 diff --git a/app/routing/routers/dash/v1.routes.js b/app/routing/routers/dash/v1.routes.js index b253291..7f6c527 100644 --- a/app/routing/routers/dash/v1.routes.js +++ b/app/routing/routers/dash/v1.routes.js @@ -53,6 +53,8 @@ const v1 = { '/project/snippet/:id/delete/:snippet': [ _flitter.controller('dash:v1').project_snippet_delete ], '/project/snippet/:id/edit/:snippet': [ _flitter.controller('dash:v1').project_snippet_edit ], + '/using_devbug/:page': [ _flitter.controller('dash:v1').show_usage_page ], + '/out/view/:id': [ _flitter.controller('dash:v1').out_view ], '/out/delete/:id/:project': [ _flitter.controller('dash:v1').out_delete ], diff --git a/app/views/dash_v1/main.pug b/app/views/dash_v1/main.pug index de9114a..81e9591 100644 --- a/app/views/dash_v1/main.pug +++ b/app/views/dash_v1/main.pug @@ -1,9 +1,7 @@ extends ./template block content h3 My Projects - ul(style='list-style-type: none;') - li - a(href='/dash/v1/project/new') Create New Project + a.btn(href='/dash/v1/project/new') + table thead tr @@ -37,20 +35,20 @@ block content td #{project.name} td ul(style='list-style-type: none; margin: 0; padding: 0;') - li + li.action-li a.action(href='/dash/v1/project/view/'+project.id) View - li + li.action-li a.action(href='/dash/v1/project/share/'+project.id+'/revoke/'+user.uuid+'/edit') Remove - li + li.action-li a.action(href='/dash/v1/project/edit/'+project.id) Edit each project in shared_projects.view tr td #{project.name} td ul(style='list-style-type: none; margin: 0; padding: 0;') - li + li.action-li a.action(href='/dash/v1/project/view/'+project.id) View - li + li.action-li a.action(href='/dash/v1/project/share/'+project.id+'/revoke/'+user.uuid) Remove if shared_snippets.view || shared_snippets.edit h3 Snippets Shared With Me @@ -65,18 +63,18 @@ block content td #{snippet.name} td ul(style='list-style-type: none; margin: 0; padding: 0;') - li + li.action-li a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/view/'+snippet.uuid) View - li + li.action-li a.action(href='/dash/v1/snippet/share/'+snippet.id+'/revoke/'+user.uuid+'/edit') Remove - li + li.action-li a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/edit/'+snippet.uuid) Edit each snippet in shared_snippets.view tr td #{snippet.name} td ul(style='list-style-type: none; margin: 0; padding: 0;') - li + li.action-li a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/view/'+snippet.uuid) View - li + li.action-li a.action(href='/dash/v1/snippet/share/'+snippet.id+'/revoke/'+user.uuid) Remove diff --git a/app/views/dash_v1/out.pug b/app/views/dash_v1/out.pug index f3af085..382b1d9 100644 --- a/app/views/dash_v1/out.pug +++ b/app/views/dash_v1/out.pug @@ -1,4 +1,12 @@ extends ./template block content + pre#editor(style="height: 75%;") #{prettyd} script(src='/assets/dash_v1.js') - script output(syntaxHighlight(`#{prettyd}`)); + +block scripts + script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js") + script. + const editor = ace.edit('editor'); + editor.setTheme('ace/theme/cobalt'); + editor.session.setMode('ace/mode/json'); + editor.setOption('readOnly', true); diff --git a/app/views/dash_v1/project.pug b/app/views/dash_v1/project.pug index e7cfda7..642ab4f 100644 --- a/app/views/dash_v1/project.pug +++ b/app/views/dash_v1/project.pug @@ -8,4 +8,4 @@ block content input#project_name(type='text', name='name' value=(project_name ? project_name : '') required autofocus) br br - button(type='submit') #{project_name ? 'Update Project' : 'Create Project'} \ No newline at end of file + button.btn(type='submit') #{project_name ? 'Update Project' : 'Create Project'} \ No newline at end of file diff --git a/app/views/dash_v1/share.pug b/app/views/dash_v1/share.pug index 8115cef..56c6917 100644 --- a/app/views/dash_v1/share.pug +++ b/app/views/dash_v1/share.pug @@ -26,7 +26,7 @@ block content if !(user.uuid === item.user_id) li.action-li a.action(href='/dash/v1/'+api+'/share/'+item.id+'/revoke/'+user.uuid) Revoke - li + li.action-li a.action(href='/dash/v1/'+api+'/share/'+item.id+'/transfer/'+user.uuid) Transfer Ownership else li.action-li @@ -51,7 +51,7 @@ block content if !(user.uuid === item.user_id) li.action-li a.action(href='/dash/v1/'+api+'/share/'+item.id+'/revoke/'+user.uuid+'/edit') Revoke - li + li.action-li a.action(href='/dash/v1/'+api+'/share/'+item.id+'/transfer/'+user.uuid) Transfer Ownership else li.action-li diff --git a/app/views/dash_v1/snippet.pug b/app/views/dash_v1/snippet.pug index 46fbe7f..4981ce6 100644 --- a/app/views/dash_v1/snippet.pug +++ b/app/views/dash_v1/snippet.pug @@ -84,7 +84,7 @@ block content a.btn(href='/dash/v1/project/snippet/'+project.id+'/edit/'+snippet.uuid style='margin-left: 10px') Edit pre#editor #{ snippet ? snippet.data : '' } if (!readonly) - button(onclick='submitSnippet()') #{ snippet ? 'Update Snippet' : 'Create Snippet' } + button.btn(onclick='submitSnippet()') #{ snippet ? 'Update Snippet' : 'Create Snippet' } input#preset_mode(type='hidden' value=snippet ? snippet.mode : 'ace/mode/javascript') block scripts diff --git a/app/views/dash_v1/template.pug b/app/views/dash_v1/template.pug index 6dd791f..aa22b85 100644 --- a/app/views/dash_v1/template.pug +++ b/app/views/dash_v1/template.pug @@ -16,7 +16,7 @@ html li.navli a.nava(href='/dash/v1') Home li.navli - a.nava(href='/dash/v1/code') Using DevBug + a.nava(href='/dash/v1/using_devbug/main') Using DevBug li.navli a.nava(href='/auth/logout') Logout if show_back diff --git a/app/views/dash_v1/use/api.pug b/app/views/dash_v1/use/api.pug new file mode 100644 index 0000000..0987ecc --- /dev/null +++ b/app/views/dash_v1/use/api.pug @@ -0,0 +1,13 @@ +extends ../template +block content + h3 DevBug supports anywhere within the reach of your network. + p You can use DevBug in any language that supports sending multipart/form-data POST requests. This is accomplished via the DevBug API. This is the same procedure the native DevBug clients use. The API is fairly simple to use and contains a single endpoint. The snippet below details how to use it: + pre#editor #{devbug.code.api} + +block scripts + script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js") + script. + const editor = ace.edit('editor'); + editor.setTheme('ace/theme/cobalt'); + editor.session.setMode('ace/mode/javascript'); + editor.setOption('readOnly', true); diff --git a/app/views/dash_v1/use/ecma.pug b/app/views/dash_v1/use/ecma.pug new file mode 100644 index 0000000..b3b2286 --- /dev/null +++ b/app/views/dash_v1/use/ecma.pug @@ -0,0 +1,17 @@ +extends ../template +block content + h3 DevBug supports ECMAscript on the web. + p To use the client, include the ECMAscript client file in your application, as early as possible. This file is hosted by your local DevBug server, and is available here. Then, set the project API key and server addresses (see the code snippet below). This gives you access to the global out() and breakpoint() functions. Here's how to use them: + h4 out(info, data) - output data to DevBug + p This function is similar to logging data. It stores data to be outputted to DevBug. The first parameter should be a string with a brief description of the data, and the second is the data to be outputted. Note that the info string should be unique and multiple outputs with the same name will overwrite their predecessors. It's important to note that calling this function doesn't actually send any data to DevBug. Instead, it stores it to be sent. + h4 breakpoint(continue = false, name = "") - send the outputted data to DevBug + p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The continue parameter determines whether or not program execution continues, or if the interpreter's exit method is called. The name parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. Note that the continuation parameter is non-functional in browser-based ECMAscript. + pre#editor // Run the following as early in your application as your can: devbug_url="http://localhost:8000/"; project_api_key="CHANGEME"; + +block scripts + script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js") + script. + const editor = ace.edit('editor'); + editor.setTheme('ace/theme/cobalt'); + editor.session.setMode('ace/mode/javascript'); + editor.setOption('readOnly', true); diff --git a/app/views/dash_v1/use/main.pug b/app/views/dash_v1/use/main.pug new file mode 100644 index 0000000..fb9561d --- /dev/null +++ b/app/views/dash_v1/use/main.pug @@ -0,0 +1,51 @@ +extends ../template +block content + h2 Welcome to DevBug! + p DevBug is a development helper tool designed to make it easy to collect program output and code snippets for your projects. + | The basic principle here is that you include DevBug's inline-helper scripts which provide helper functions. + | You can call these helper functions from your code to output data. When a breakpoint is reached, that data is sent to + | the DevBug server as JSON, where it is logged in a project along with some other information about the breakpoint. + | You can then view the outputs through the DevBug console. DevBug is designed to be hosted on the local network of the + | developers who use it. This alleviates some worries about code and development output being sent over the open web. + p Because output data is sent over HTTP, DevBug is helpful for debugging software that may run in an environment where the direct output is not easily accessible. + p Inline helper functions are included with DevBug for the following languages (however, the DevBug api is easy to use, even if your favorite language isn't supported): + br + ul(style='list-style-type: none; margin: 0; padding: 0;') + li.action-li + a.btn(href='./node') Node.js + li.action-li + a.btn(href='./ecma') JavaScript (Web) + li.action-li + a.btn(href='./php') PHP + li.action-li + a.btn(href='./api') DevBug API + br + h3 Changelog + h4 v0.5.1 - Use Ace.js for Outputs + ul + li Switched over to use Ace.js to view development output. Might make this a user preference in the future. + + h4 v0.5.0 - Better Documentation and UI + ul + li Improved the "Using DevBug" section to be more readable and accessible. + li Added individual pages for each of the supported languages with details on the client functions. + li Use a consistent button theme throughtout the application. + + h4 v0.4.0 - Snippets + ul + li Projects can now contain various code snippets. + li These snippets can be shared individually with view/edit/transfer/invite support. + li Users with view/edit access to the parent project automatically inherit these permissions. + li Snippets make use of the Ace.js embedded editor, which provides syntax highlighting. + + h4 v0.3.0 - Sharing! + ul + li DevBug now supports sharing project with other users. + li This includes view/edit mode, as well as the ability to transfer ownership of a project to that user. + li Projects can also be shared via invitation URL. If the recipient doesn't have an account on this DevBug server, they will be prompted to create one. + + h3 About + p Copyright (C) 2019 Garrett L Mills. + p + | DevBug is licensed under the GNU Affero GPL Version 3. Read more about what that means + a(href="https://choosealicense.com/licenses/agpl-3.0/" target="_blank") here. \ No newline at end of file diff --git a/app/views/dash_v1/use/node.pug b/app/views/dash_v1/use/node.pug new file mode 100644 index 0000000..15c5673 --- /dev/null +++ b/app/views/dash_v1/use/node.pug @@ -0,0 +1,17 @@ +extends ../template +block content + h3 Node.js has a first-class DevBug client. + p To use the client, install the devbugjs package from NPM. Probably best to include this in your development dependencies. Then, run the following code as early in your application initialization as you can. This gives you access to the global out() and breakpoint() functions. Here's how to use them: + h4 out(info, data) - output data to DevBug + p This function is similar to logging data. It stores data to be outputted to DevBug. The first parameter should be a string with a brief description of the data, and the second is the data to be outputted. Note that the info string should be unique and multiple outputs with the same name will overwrite their predecessors. It's important to note that calling this function doesn't actually send any data to DevBug. Instead, it stores it to be sent. + h4 breakpoint(continue = false, name = "") - send the outputted data to DevBug + p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The continue parameter determines whether or not program execution continues, or if the Node.js exit method is called. The name parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. + pre#editor #{ devbug.code.node } + +block scripts + script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js") + script. + const editor = ace.edit('editor'); + editor.setTheme('ace/theme/cobalt'); + editor.session.setMode('ace/mode/javascript'); + editor.setOption('readOnly', true); diff --git a/app/views/dash_v1/use/php.pug b/app/views/dash_v1/use/php.pug new file mode 100644 index 0000000..4bdadc5 --- /dev/null +++ b/app/views/dash_v1/use/php.pug @@ -0,0 +1,17 @@ +extends ../template +block content + h3 DevBug supports the code behind the web. + p To use the client, include the code snippet in your PHP application as early as you can. You'll need to go to the breakpoint() function and customize the DevBug server URL and project API key. It's best to do this in a global namespace. That way the functions defined by DevBug are available everywhere in your program. This gives you access to the global out() and breakpoint() functions. Here's how to use them: + h4 out(info, data) - output data to DevBug + p This function is similar to logging data. It stores data to be outputted to DevBug. The first parameter should be a string with a brief description of the data, and the second is the data to be outputted. Note that the info string should be unique and multiple outputs with the same name will overwrite their predecessors. It's important to note that calling this function doesn't actually send any data to DevBug. Instead, it stores it to be sent. + h4 breakpoint(continue = false, name = "") - send the outputted data to DevBug + p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The continue parameter determines whether or not program execution continues, or if the PHP exit method is called. The name parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. + pre#editor #{devbug.code.php} + +block scripts + script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js") + script. + const editor = ace.edit('editor'); + editor.setTheme('ace/theme/cobalt'); + editor.session.setMode('ace/mode/php'); + editor.setOption('readOnly', true);