From c00a05262d7ee9c1ffdad8dbf59031bef5dc5842 Mon Sep 17 00:00:00 2001 From: Garrett Mills Date: Wed, 24 Jul 2019 12:05:27 -0500 Subject: [PATCH] finish snippets --- app/MiscUnit.js | 28 ++++-- app/controllers/api/v1.controller.js | 26 ++++-- app/controllers/dash/v1.controller.js | 124 +++++++++++++++++++++----- app/models/v1/Invite.model.js | 1 + app/routing/routers/dash/v1.routes.js | 3 + app/views/dash_v1/accept.pug | 6 +- app/views/dash_v1/main.pug | 28 ++++++ app/views/dash_v1/snippet.pug | 3 +- app/views/dash_v1/template.pug | 3 +- app/views/dash_v1/view.pug | 15 ++++ 10 files changed, 195 insertions(+), 42 deletions(-) diff --git a/app/MiscUnit.js b/app/MiscUnit.js index 2cca64a..6322c14 100644 --- a/app/MiscUnit.js +++ b/app/MiscUnit.js @@ -155,34 +155,46 @@ if ( window ) window.out = out; window.breakpoint = breakpoint; }, permission: { project: { - edit(project, target_user){ + async edit(project, target_user){ if ( project.user_id === target_user.uuid ) return true else if ( project.edit_user_ids.includes(target_user.uuid) ) return true else return false }, - view(project, target_user){ + sync_edit(project, target_user){ + if ( project.user_id === target_user.uuid ) return true + else if ( project.edit_user_ids.includes(target_user.uuid) ) return true + else return false + }, + async view(project, target_user){ if ( project.user_id === target_user.uuid ) return true else if ( project.shared_user_ids.includes(target_user.uuid) ) return true else if ( project.edit_user_ids.includes(target_user.uuid) ) return true else return false }, - owns(project, target_user){ + async owns(project, target_user){ return (project.user_id === target_user.uuid) } }, snippet: { - edit(snippet, target_user){ + async edit(snippet, target_user){ + const project = await _flitter.model('v1:Project').findById(snippet.project_id) if ( snippet.user_id === target_user.uuid ) return true else if ( snippet.edit_user_ids.includes(target_user.uuid) ) return true + else if ( await devbug.permission.project.edit(project, target_user) ) return true else return false }, - view(snippet, target_user){ + async view(snippet, target_user){ + const project = await _flitter.model('v1:Project').findById(snippet.project_id) if ( this.edit(snippet, target_user) ) return true - else if ( project.shared_user_ids.includes(target_user.uuid) ) return true + else if ( snippet.shared_user_ids.includes(target_user.uuid) ) return true + else if ( await devbug.permission.project.view(project, target_user) ) return true else return false }, - owns(snippet, target_user){ - return snippet.user_id === target_user.uuid + async owns(snippet, target_user){ + const project = await _flitter.model('v1:Project').findById(snippet.project_id) + if ( snippet.user_id === target_user.uuid ) return true + else if ( await devbug.permission.project.owns(project, target_user) ) return true + else return false } } }, diff --git a/app/controllers/api/v1.controller.js b/app/controllers/api/v1.controller.js index ca5ca25..63efa13 100644 --- a/app/controllers/api/v1.controller.js +++ b/app/controllers/api/v1.controller.js @@ -6,6 +6,20 @@ const Out = _flitter.model('v1:Out') const Project = _flitter.model('v1:Project') const Invite = _flitter.model('v1:Invite') +const Snippet = _flitter.model('v1:Snippet') +const share_api = { + project: Project, + snippet: Snippet, +} +const share_views = { + project: async function(item){ + return '/dash/v1/project/view/'+item.id + }, + snippet: async function(item){ + const project = await Project.findById(item.project_id); + return '/dash/v1/project/snippet/'+project.id+'/view/'+item.uuid + }, +} class v1 { /* @@ -74,8 +88,9 @@ class v1 { if ( invite.used ) _flitter.error(res, 401, {reason: 'This invitation link has been used or has expired.'}) - const project = await Project.findById(invite.project_id) - if ( !project ) _flitter.error(res, 404, {reason: 'This project no longer exists.'}) + const share_model = share_api[invite.api_type]; + const project = await share_model.findById(invite.project_id) + if ( !project ) _flitter.error(res, 404, {reason: 'This '+invite.api_type+' no longer exists.'}) const user = await _flitter.model('User').findOne({uuid: invite.by_user_id}) if ( !user ) _flitter.error(res, 500, {reason: 'This user no longer exists. Sorry.'}) @@ -89,8 +104,9 @@ class v1 { if ( invite.used ) _flitter.error(res, 401, {reason: 'This invitation link has been used or has expired.'}) - const project = await Project.findById(invite.project_id) - if ( !project ) _flitter.error(res, 404, {reason: 'This project no longer exists.'}) + const share_model = share_api[invite.api_type]; + const project = await share_model.findById(invite.project_id) + if ( !project ) _flitter.error(res, 404, {reason: 'This '+invite.api_type+' no longer exists.'}) const user = await _flitter.model('User').findOne({uuid: invite.by_user_id}) if ( !user ) _flitter.error(res, 500, {reason: 'This user no longer exists. Sorry.'}) @@ -103,7 +119,7 @@ class v1 { } invite.used = true await invite.save() - return res.redirect('/dash/v1') + return res.redirect(await share_views[invite.api_type](project)) } else { req.session.invite = true diff --git a/app/controllers/dash/v1.controller.js b/app/controllers/dash/v1.controller.js index 38134e0..7b0fae1 100644 --- a/app/controllers/dash/v1.controller.js +++ b/app/controllers/dash/v1.controller.js @@ -11,6 +11,15 @@ const share_api = { project: Project, snippet: Snippet, } +const share_views = { + project: async function(item){ + return '/dash/v1/project/view/'+item.id + }, + snippet: async function(item){ + const project = await Project.findById(item.project_id); + return '/dash/v1/project/snippet/'+project.id+'/view/'+item.uuid + }, +} class v1 { /* @@ -41,13 +50,18 @@ class v1 { edit: await Project.find(edit_find), } + const shared_snippets = { + view: await Snippet.find(view_find), + edit: await Snippet.find(edit_find), + } + /* * Return the main view. * It must be passed the response. * View parameters can be passed as an optional third * argument to the view() method. */ - return _flitter.view(res, 'dash_v1:main', { projects, shared_projects, user: req.session.auth.user }) + return _flitter.view(res, 'dash_v1:main', { projects, shared_projects, shared_snippets, user: req.session.auth.user }) } new_project_show(req, res, next){ @@ -61,7 +75,7 @@ class v1 { } // check access perms - if ( !devbug.permission.project.edit(project, req.session.auth.user) ){ + if ( !await devbug.permission.project.edit(project, req.session.auth.user) ){ return _flitter.error(res, 401, {reason: 'You do not have permissions to edit this project.'}) } @@ -79,7 +93,7 @@ class v1 { } // check access perms - if ( !devbug.permission.project.edit(project, req.session.auth.user) ){ + if ( !await devbug.permission.project.edit(project, req.session.auth.user) ){ return _flitter.error(res, 401, {reason: 'You do not have permissions to edit this project.'}) } @@ -117,12 +131,14 @@ class v1 { } const outs = await Out.find({ project_id: project.id }).sort('-created') + + const snippets = await Snippet.find({project_id: project.id}) - if ( !devbug.permission.project.view(project, req.session.auth.user) ){ + if ( !await devbug.permission.project.view(project, req.session.auth.user) ){ return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'}) } - return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, project, outs, show_back: true, title: 'View: '+project.name }) + return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, snippets, project, outs, show_back: true, title: 'View: '+project.name }) } async out_view(req, res, next){ @@ -143,7 +159,7 @@ class v1 { const project = await Project.findById(out.project_id) - if ( !project || (!devbug.permission.project.view(project, req.session.auth.user)) ){ + if ( !project || (!await devbug.permission.project.view(project, req.session.auth.user)) ){ return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'}) } @@ -154,7 +170,7 @@ class v1 { const out = await Out.findById(req.params.id) const project = await Project.findById(req.params.project) - if ( !project || ( !devbug.permission.project.edit(project, req.session.auth.user) ) ){ + if ( !project || ( !await devbug.permission.project.edit(project, req.session.auth.user) ) ){ return _flitter.error(res, 401, {reason: 'You do not have permission to edit this project.'}) } @@ -171,7 +187,7 @@ class v1 { return _flitter.error(res, 404, {reason: 'Project not found with the specified ID.'}) } - if ( !devbug.permission.project.owns(project, req.session.auth.user) ){ + if ( !await devbug.permission.project.owns(project, req.session.auth.user) ){ return _flitter.error(res, 401, {reason: 'You do not have permission to edit this project.'}) } @@ -181,7 +197,7 @@ class v1 { async project_delete_do(req, res, next){ const project = await Project.findById(req.params.id) - if ( project && ( !devbug.permission.project.owns(project, req.session.auth.user) ) ){ + if ( project && ( !await devbug.permission.project.owns(project, req.session.auth.user) ) ){ return _flitter.error(res, 401, {reason: 'You do not have permission to edit this project.'}) } @@ -209,7 +225,7 @@ class v1 { if ( !project ) return _flitter.error(res, 404, {reason: req.params.api+' not found with the specified ID.'}) - if ( !devbug.permission.project.owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this '+req.params.api+'.'}) + if ( !await devbug.permission[req.params.api].owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this '+req.params.api+'.'}) // Find read-only users const read_find = { @@ -258,7 +274,7 @@ class v1 { const target_user = await _flitter.model('User').findOne({uuid: req.params.user}) if ( !target_user ) return _flitter.error(res, 404, {reason: 'User not found with the specified ID.'}) - if ( !devbug.permission.project.owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) + if ( !await devbug.permission[req.params.api].owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) if ( !(project.user_id === target_user.uuid) && !(project.shared_user_ids.includes(target_user.uuid)) ){ project.shared_user_ids.push(target_user.uuid) @@ -277,7 +293,7 @@ class v1 { const target_user = await _flitter.model('User').findOne({uuid: req.params.user}) if ( !target_user ) return _flitter.error(res, 404, {reason: 'User not found with the specified ID.'}) - if ( !devbug.permission.project.owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) + if ( !await devbug.permission[req.params.api].owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) if ( !(project.user_id === target_user.uuid) && !(project.edit_user_ids.includes(target_user.uuid)) ){ // check if read access. If so, revoke. @@ -301,7 +317,7 @@ class v1 { const target_user = await _flitter.model('User').findOne({uuid: req.params.user}) if ( !target_user ) return _flitter.error(res, 404, {reason: 'User not found with the specified ID.'}) - if ( !devbug.permission.project.view(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) + if ( !await devbug.permission[req.params.api].view(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) const to_dash = project.shared_user_ids.includes(req.session.auth.uuid) @@ -324,7 +340,7 @@ class v1 { const target_user = await _flitter.model('User').findOne({uuid: req.params.user}) if ( !target_user ) return _flitter.error(res, 404, {reason: 'User not found with the specified ID.'}) - if ( !devbug.permission.project.view(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) + if ( !await devbug.permission[req.params.api].view(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: "You do not have permission to edit this "+req.params.api+"."}) const to_dash = project.edit_user_ids.includes(req.session.auth.uuid) @@ -347,7 +363,7 @@ class v1 { const target_user = await _flitter.model('User').findOne({uuid: req.params.user}) if ( !target_user ) return _flitter.error(res, 404, {reason: 'User not found with the specified ID.'}) - if ( !devbug.permission.project.owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this '+req.params.api+'.'}) + if ( !await devbug.permission[req.params.api].owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this '+req.params.api+'.'}) project.user_id = target_user.uuid project.shared_user_ids.push(req.session.auth.uuid) @@ -366,13 +382,16 @@ class v1 { } async project_share_invite(req, res, next){ - const project = await Project.findById(req.params.id) - if ( !project ) return _flitter.error(res, 404, {reason: 'Project not found with the specified ID.'}) + const share_model = share_api[req.params.api] + if ( !share_model ) return _flitter.error(res, 400, {reason: 'Invalid Share API endpoint.'}) + const project = await share_model.findById(req.params.id) + if ( !project ) return _flitter.error(res, 404, {reason: req.params.api+' not found with the specified ID.'}) - if ( !devbug.permission.project.owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this project.'}) + if ( !await devbug.permission[req.params.api].owns(project, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this '+req.params.api+'.'}) let share_data = { project_id: project.id, + api_type: req.params.api, by_user_id: req.session.auth.uuid, created_on: Date.now() } @@ -380,7 +399,7 @@ class v1 { const share = new Invite(share_data) await share.save() - return _flitter.view(res, 'dash_v1:invite', {share, project, title: 'Generate Invite Link', show_back: true}) + return _flitter.view(res, 'dash_v1:invite', {share, project, title: 'Sharing link for '+req.params.api, show_back: true}) } async accept_invite(req, res, next){ @@ -389,8 +408,9 @@ class v1 { const invite = await Invite.findById(req.session.invite_data.invite) if ( !invite ) return _flitter.error(res, 404, {reason: 'This invitation is no longer valid. Sorry.'}) - const project = await Project.findById(req.session.invite_data.project) - if ( !project ) return _flitter.error(res, 404, {reason: 'This project no longer exists.'}) + const share_model = share_api[invite.api_type]; + const project = await share_model.findById(req.session.invite_data.project) + if ( !project ) return _flitter.error(res, 404, {reason: 'This '+invite.api_type+' no longer exists.'}) const user = await _flitter.model('User').findById(req.session.invite_data.user) if ( !user ) return _flitter.error(res, 404, {reason: 'This user no longer exists. Sorry.'}) @@ -405,7 +425,7 @@ class v1 { req.session.invite = false req.session.invite_data = false - return res.redirect('/dash/v1/project/view/'+project.id) + return res.redirect(await share_views[invite.api_type](project)) } async project_snippet_new(req, res, next){ @@ -457,10 +477,66 @@ class v1 { const snippet = await Snippet.findOne({uuid: req.params.snippet}) if ( !snippet ) return _flitter.error(res, 404, {reason: 'The specified snippet does not exist.'}) + + if ( !await devbug.permission.snippet.view(snippet, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to view this snippet.'}) + + const is_owner = await devbug.permission.snippet.owns(snippet, req.session.auth.user) + + return _flitter.view(res, 'dash_v1:snippet', {snippet, project, is_owner, user: req.session.auth.user, title: 'Snippet: '+snippet.name, show_back: true, readonly: true}) + } + + async project_snippet_delete(req, res, next){ + const project = await Project.findById(req.params.id) + if ( !project ) return _flitter.error(res, 404, {reason: 'The specified project does not exist.'}) + + const snippet = await Snippet.findOne({uuid: req.params.snippet}) + if ( !snippet ) return _flitter.error(res, 404, {reason: 'The specified snippet does not exist.'}) + + if ( !await devbug.permission.snippet.owns(snippet, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this snippet.'}) - console.log('snippet mode', snippet.mode) + await snippet.delete() + return res.redirect('/dash/v1/project/view/'+project.id) + } + + async project_snippet_edit(req, res, next){ + const project = await Project.findById(req.params.id) + if ( !project ) return _flitter.error(res, 404, {reason: 'The specified project does not exist.'}) + + const snippet = await Snippet.findOne({uuid: req.params.snippet}) + if ( !snippet ) return _flitter.error(res, 404, {reason: 'The specified snippet does not exist.'}) + + if ( !await devbug.permission.snippet.edit(snippet, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this snippet.'}) + + return _flitter.view(res, 'dash_v1:snippet', {project, snippet, user: req.session.auth.user, title: 'Snippet: '+snippet.name, readonly: false, show_back: true}) + } + + async project_snippet_edit_do(req, res, next){ + const project = await Project.findById(req.params.id) + if ( !project ) return _flitter.error(res, 404, {reason: 'The specified project does not exist.'}) + + const snippet = await Snippet.findOne({uuid: req.params.snippet}) + if ( !snippet ) return _flitter.error(res, 404, {reason: 'The specified snippet does not exist.'}) + + if ( !await devbug.permission.snippet.edit(snippet, req.session.auth.user) ) return _flitter.error(res, 401, {reason: 'You do not have permission to edit this snippet.'}) + + // check required fields: title, data, mode + let fail = false + + if ( !req.body.title ) fail = 'Snippet title is required.' + else if ( !req.body.data ) fail = 'Snippet data is required.' + else if ( !req.body.mode ) fail = 'Snippet mode is required.' + + if ( fail ){ + return _flitter.view(res, 'dash_v1:snippet', {snippet, project, user: req.session.auth.user, title: 'Update Snippet', show_back: true, errors:[fail]}) + } + + snippet.name = req.body.title + snippet.data = req.body.data + snippet.mode = req.body.mode + + await snippet.save() - return _flitter.view(res, 'dash_v1:snippet', {snippet, project, user: req.session.auth.user, title: 'Snippet: '+snippet.name, show_back: true, readonly: true}) + return res.redirect('/dash/v1/project/snippet/'+project.id+'/view/'+snippet.uuid) } } diff --git a/app/models/v1/Invite.model.js b/app/models/v1/Invite.model.js index 12e2a16..43f8d06 100644 --- a/app/models/v1/Invite.model.js +++ b/app/models/v1/Invite.model.js @@ -6,6 +6,7 @@ const Invite = { project_id: String, by_user_id: String, + api_type: String, created_on: Date, used: { type: Boolean, default: false } } diff --git a/app/routing/routers/dash/v1.routes.js b/app/routing/routers/dash/v1.routes.js index 5964159..b253291 100644 --- a/app/routing/routers/dash/v1.routes.js +++ b/app/routing/routers/dash/v1.routes.js @@ -50,6 +50,8 @@ const v1 = { '/:api/share/:id/invite': [ _flitter.controller('dash:v1').project_share_invite ], '/project/snippet/:id/new': [ _flitter.controller('dash:v1').project_snippet_new ], '/project/snippet/:id/view/:snippet': [ _flitter.controller('dash:v1').project_snippet_view ], + '/project/snippet/:id/delete/:snippet': [ _flitter.controller('dash:v1').project_snippet_delete ], + '/project/snippet/:id/edit/:snippet': [ _flitter.controller('dash:v1').project_snippet_edit ], '/out/view/:id': [ _flitter.controller('dash:v1').out_view ], '/out/delete/:id/:project': [ _flitter.controller('dash:v1').out_delete ], @@ -73,6 +75,7 @@ const v1 = { '/project/delete/:id': [ _flitter.controller('dash:v1').project_delete_do ], '/project/edit/:id': [ _flitter.controller('dash:v1').project_edit_do ], '/project/snippet/:id/new': [ _flitter.controller('dash:v1').project_snippet_new_do ], + '/project/snippet/:id/edit/:snippet': [ _flitter.controller('dash:v1').project_snippet_edit_do ], }, } diff --git a/app/views/dash_v1/accept.pug b/app/views/dash_v1/accept.pug index 5a0a81d..5921d55 100644 --- a/app/views/dash_v1/accept.pug +++ b/app/views/dash_v1/accept.pug @@ -1,6 +1,6 @@ html head - title Project Invitation | DevBug + title Sharing Invitation | DevBug link(rel='stylesheet' href='/assets/dash_v1.css') script(src='/assets/dash_v1.js') body @@ -11,8 +11,8 @@ html li.navli a.nava(href='/dash/v1') Dashboard Login .spacer - p You've been invited to view the debugging project "#{project.name}" by #{user.username}. - p To accept this invitation, you must have a DevBug account. You will be redirected to the registration portal. + p You've been invited to view the debugging #{invite.api_type} "#{project.name}" by #{user.username}. + p To accept this invitation, you must have a DevBug account. You may be redirected to the registration portal. a.btn(href='/api/v1/invitation/'+invite.id+'/accept') Accept br h3 What's DevBug? diff --git a/app/views/dash_v1/main.pug b/app/views/dash_v1/main.pug index 7714931..de9114a 100644 --- a/app/views/dash_v1/main.pug +++ b/app/views/dash_v1/main.pug @@ -52,3 +52,31 @@ block content a.action(href='/dash/v1/project/view/'+project.id) View 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 + table + thead + tr + th(scope='col' style='min-width: 250px') Name + th(scope='col') Actions + tbody + each snippet in shared_snippets.edit + tr + td #{snippet.name} + td + ul(style='list-style-type: none; margin: 0; padding: 0;') + li + a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/view/'+snippet.uuid) View + li + a.action(href='/dash/v1/snippet/share/'+snippet.id+'/revoke/'+user.uuid+'/edit') Remove + 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 + a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/view/'+snippet.uuid) View + li + a.action(href='/dash/v1/snippet/share/'+snippet.id+'/revoke/'+user.uuid) Remove diff --git a/app/views/dash_v1/snippet.pug b/app/views/dash_v1/snippet.pug index 149c250..46fbe7f 100644 --- a/app/views/dash_v1/snippet.pug +++ b/app/views/dash_v1/snippet.pug @@ -79,8 +79,9 @@ block content option(value='ace/mode/xml') XML option(value='ace/mode/yaml') YAML input#snippet_value(type='hidden' name='data' required) - if snippet && user.uuid === snippet.user_id + if snippet && user && is_owner && readonly a.btn(href='/dash/v1/snippet/share/'+snippet.id style='margin-left: 20px') Share Snippet + 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' } diff --git a/app/views/dash_v1/template.pug b/app/views/dash_v1/template.pug index 4e3128a..6dd791f 100644 --- a/app/views/dash_v1/template.pug +++ b/app/views/dash_v1/template.pug @@ -5,8 +5,9 @@ html script(src='/assets/dash_v1.js') block head body + - var e_project = (user && project && devbug.permission.project.sync_edit(project, user)) .page-header - .devbug-header DevBug | v#{devbug.version} #{(user ? " | User: "+user.username : "")} #{(project ? " | Project: "+project.name+" | API: "+project.uuid : "")} #{((_flitter.config('server.environment') === 'development') ? " | Development" : "" )} + .devbug-header DevBug | v#{devbug.version} #{(user ? " | User: "+user.username : "")} #{(e_project ? " | Project: "+project.name+" | API: "+project.uuid : "")} #{((_flitter.config('server.environment') === 'development') ? " | Development" : "" )} if title_small h3 #{(title ? title : 'Dashboard')} else diff --git a/app/views/dash_v1/view.pug b/app/views/dash_v1/view.pug index 4b4e5bd..5749be2 100644 --- a/app/views/dash_v1/view.pug +++ b/app/views/dash_v1/view.pug @@ -9,6 +9,21 @@ block content tr th(scope='col' style='min-width: 250px') Title th(scope='col') Actions + tbody + each snippet in snippets + tr + td #{snippet.name} + td + ul(style='list-style-type: none; margin: 0; padding: 0;') + li.action-li + a.action(href='/dash/v1/project/snippet/'+project.id+'/view/'+snippet.uuid) View + if ( devbug.permission.snippet.edit(snippet, user) ) + li.action-li + a.action(href='/dash/v1/project/snippet/'+project.id+'/delete/'+snippet.uuid) Delete + li.action-li + a.action(href='/dash/v1/project/snippet/'+project.id+'/edit/'+snippet.uuid) Edit + li.action-li + a.action(href='/dash/v1/snippet/share/'+snippet.id) Share h2 Development Outputs table