Info |
---|
Excerpt |
---|
This tutorial demonstrates advanced capabilities of ConfiForms app and it's APIs and shows you how to build a "non boring" forms for collecting user's feedback |
|
We at Vertuna LLC, live, eat and breath data entry forms, we just love to build forms to quickly collect user opinions and feedback. And we love Atlassian products, so we have built, and continue to build, the best forms add-on for app for Confluence available on Atlassian Marketplace called - ConfiForms, Data entry forms and workflows.
...
We want something more sexy and user engaging. So, we will build a user macro with icons and a little bit of scripting to glue the things together.
When a form is used by an authenticated user then this information is stored in the createdBy field, as ConfiForms has some metadata fields stored with each record (even when you have defined just one field, as we did in this example)
When a form is used by anonymous users the createdBy field is left blank
Each image has a custom "onClick" handler and invokes ConfiForms REST API to create new record in the form
The code, the handler invokes, looks something like this:
Code Block |
---|
// mychoice is the value (ID) for each option in "choice" field
function leaveFeedback(mychoice) {
AJS.$.ajax({
url: 'https://wiki.vertuna.com |
Expand |
---|
title | User macro source code |
---|
|
Code Block |
---|
|
|
## @param FormName:title=Form name|type=string|required=true|desc=ConfiForms Form name
## @param Page:title=Page|type=confluence-content|required=true|desc=Select a page where ConfiForms Form is located
#set( $cfPageId = $content.id)
#if(${paramPage})
#set( $spaceAndPageTitle = $paramPage.split(":"))
#set( $pageTitle = $paramPage)
#set( $spaceKey = $content.spaceKey)
#set( $temp = '')
#set( $count = 1 )
#foreach( $e in $spaceAndPageTitle)
#if ($count == 1)
#set( $spaceKey = $e)
#end
#if ($count == 2)
#set( $pageTitle = $e)
#end
#set( $count = $count + 1 )
#end
#if ($count == 1)
#set( $spaceKey = $content.spaceKey)
#end
#set( $cfPageId = $pageManager.getPage($spaceKey, $pageTitle).getId())
#end
<table class="wrapped cf_quickfeedback_$!{paramFormName}" style="border: 0;">
<colgroup> <col/> <col/> <col/> <col/> </colgroup>
<tbody>
<tr style="border: 0;">
<td style="border: 0;">
<div class="content-wrapper user-choice-cf">
<p>
<img alt="Awesome" title="Awesome" style="cursor: pointer" data-choice="1" width="50px" src="data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDQ3My45MzEgNDczLjkzMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDczLjkzMSA0NzMuOTMxOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiNGRkMxMEU7IiBjeD0iMjM2Ljk2NiIgY3k9IjIzNi45NjYiIHI9IjIzNi45NjYiLz4NCjxwYXRoIHN0eWxlPSJmaWxsOiNGRkZGRkY7IiBkPSJNODEuMzkxLDIzNy4xMjNjMCw4NS45MTEsNjkuNjQ5LDE1NS41NiwxNTUuNTYsMTU1LjU2Yzg1LjkxNSwwLDE1NS41NjQtNjkuNjQ5LDE1NS41NjQtMTU1LjU2DQoJTDgxLjM5MSwyMzcuMTIzTDgxLjM5MSwyMzcuMTIzeiIvPg0KPGc+DQoJPHBhdGggc3R5bGU9ImZpbGw6I0NDQ0JDQjsiIGQ9Ik0xNjcuNzI4LDIzNy4xMjNjMCw0Ni40MzUsMCw5Mi44NywwLDEzOS4zMDZjNi4wMjQsMy4wMDEsMTIuMjczLDUuNjA5LDE4LjcwOSw3LjgyDQoJCWMwLTQ5LjA0MywwLTk4LjA4MywwLTE0Ny4xMjZIMTY3LjcyOHoiLz4NCgk8cGF0aCBzdHlsZT0iZmlsbDojQ0NDQkNCOyIgZD0iTTI4My4zMTksMjM3LjEyM2MwLDQ5LjUxMSwwLDk5LjAxOCwwLDE0OC41MjljNi40MzItMi4wMDYsMTIuNjY2LTQuNDUzLDE4LjcwOS03LjI0DQoJCWMwLTQ3LjA5OCwwLTk0LjE5MSwwLTE0MS4yODlMMjgzLjMxOSwyMzcuMTIzTDI4My4zMTksMjM3LjEyM3oiLz4NCjwvZz4NCjxnPg0KCTxwYXRoIHN0eWxlPSJmaWxsOiMzMzMzMzM7IiBkPSJNMjE5LjE4MSwxNTguNzkzYy0xLjY4NC0zMS4yNTUtMjMuOTkyLTUzLjU2LTU1LjI0My01NS4yNDMNCgkJYy0zMS4xODQtMS42OC01My42OTgsMjYuNTIyLTU1LjI0Myw1NS4yNDNjLTAuNjUxLDEyLjA2MywxOC4wNjEsMTIsMTguNzA5LDBjMi41MzctNDcuMDksNzAuNTM2LTQ3LjA5LDczLjA2OSwwDQoJCUMyMDEuMTIsMTcwLjc5MywyMTkuODMyLDE3MC44NTYsMjE5LjE4MSwxNTguNzkzTDIxOS4xODEsMTU4Ljc5M3oiLz4NCgk8cGF0aCBzdHlsZT0iZmlsbDojMzMzMzMzOyIgZD0iTTM1My45ODUsMTU4Ljc5M2MtMS42ODQtMzEuMjU1LTIzLjk5Mi01My41Ni01NS4yNDMtNTUuMjQzDQoJCWMtMzEuMTg0LTEuNjgtNTMuNjk0LDI2LjUyMi01NS4yNDMsNTUuMjQzYy0wLjY1MSwxMi4wNjMsMTguMDYxLDEyLDE4LjcwOSwwYzIuNTM3LTQ3LjA5LDcwLjUzMi00Ny4wOSw3My4wNjksMA0KCQlDMzM1LjkyNCwxNzAuNzkzLDM1NC42MzcsMTcwLjg1NiwzNTMuOTg1LDE1OC43OTNMMzUzLjk4NSwxNTguNzkzeiIvPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=" />
</p>
</div>
</td>
<td style="border: 0;">
<div class="content-wrapper user-choice-cf">
<p>
<img alt="Good" title="Good" style="cursor: pointer" data-choice="2" width="50px" src="data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDQ3My45MzUgNDczLjkzNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDczLjkzNSA0NzMuOTM1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiNGRkMxMEU7IiBjeD0iMjM2Ljk2NyIgY3k9IjIzNi45NjciIHI9IjIzNi45NjciLz4NCjxnPg0KCTxjaXJjbGUgc3R5bGU9ImZpbGw6IzMzMzMzMzsiIGN4PSIxNjQuOTM4IiBjeT0iMTU1LjIzMiIgcj0iMzcuMjE2Ii8+DQoJPGNpcmNsZSBzdHlsZT0iZmlsbDojMzMzMzMzOyIgY3g9IjMwNS42NjciIGN5PSIxNTUuMjMyIiByPSIzNy4yMTYiLz4NCgk8cGF0aCBzdHlsZT0iZmlsbDojMzMzMzMzOyIgZD0iTTM0My4yNTcsMzE2Ljg2MmMtNTkuMjgxLDYwLjMyOS0xNTQuNjYzLDU5Ljg1NC0yMTMuNDUtMC44OTgNCgkJYy04LjQtOC42ODUtMjEuNjE2LDQuNTYxLTEzLjIyNywxMy4yMjdjNjUuNzY5LDY3Ljk3LDE3My42NDUsNjguMzQsMjM5LjkwNSwwLjg5OA0KCQlDMzY0Ljk0NCwzMjEuNDc5LDM1MS43MjEsMzA4LjI0NSwzNDMuMjU3LDMxNi44NjJMMzQzLjI1NywzMTYuODYyeiIvPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=" />
</p>
</div>
</td>
<td style="border: 0;">
<div class="content-wrapper user-choice-cf">
<p>
<img alt="Could be better" title="Could be better" style="cursor: pointer" data-choice="3" width="50px" src="data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDQ3My45MzUgNDczLjkzNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDczLjkzNSA0NzMuOTM1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiNGRkMxMEU7IiBjeD0iMjM2Ljk2NyIgY3k9IjIzNi45NjciIHI9IjIzNi45NjciLz4NCjxnPg0KCTxwYXRoIHN0eWxlPSJmaWxsOiMzMzMzMzM7IiBkPSJNMzU2LjY3MSwzNTQuMWMtNjYuMjI2LTY3LjYxOC0xNzQuMjU1LTY3LjMzNy0yNDAuMDk2LDAuNzAzDQoJCWMtOC4zODksOC42NjYsNC44MjcsMjEuOTEyLDEzLjIyNywxMy4yMjdjNTguODctNjAuODMsMTU0LjM4Ni02MS4yMDQsMjEzLjY0MS0wLjcwM0MzNTEuODk2LDM3NS45NiwzNjUuMTE2LDM2Mi43MjEsMzU2LjY3MSwzNTQuMQ0KCQlMMzU2LjY3MSwzNTQuMXoiLz4NCgk8Y2lyY2xlIHN0eWxlPSJmaWxsOiMzMzMzMzM7IiBjeD0iMTY0LjkzOCIgY3k9IjE1NS4yMzIiIHI9IjM3LjIxNiIvPg0KCTxjaXJjbGUgc3R5bGU9ImZpbGw6IzMzMzMzMzsiIGN4PSIzMDUuNjY3IiBjeT0iMTU1LjIzMiIgcj0iMzcuMjE2Ii8+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==" />
</p>
</div>
</td>
<td style="border: 0;">
<div class="content-wrapper user-choice-cf">
<p>
<img alt="WTF!?" title="WTF!?" style="cursor: pointer" data-choice="4" width="50px" src="data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDQ3My45MzUgNDczLjkzNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDczLjkzNSA0NzMuOTM1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiNGRkMxMEU7IiBjeD0iMjM2Ljk2NyIgY3k9IjIzNi45NjciIHI9IjIzNi45NjciLz4NCjxnPg0KCTxwYXRoIHN0eWxlPSJmaWxsOiMzMzMzMzM7IiBkPSJNMzU3LjMxOCwzNTQuOGMtNjYuMDg0LTY4LjI5MS0xNzQuNjYzLTY4LjI4OC0yNDAuNzQzLDAuMDA3DQoJCWMtOC4zODksOC42NjYsNC44MjcsMjEuOTEyLDEzLjIyNywxMy4yMjdjNTkuMTM5LTYxLjExOCwxNTUuMTQ2LTYxLjEyMiwyMTQuMjg4LTAuMDA3DQoJCUMzNTIuNDkxLDM3Ni43MDgsMzY1LjcxMSwzNjMuNDY2LDM1Ny4zMTgsMzU0LjhMMzU3LjMxOCwzNTQuOHoiLz4NCgk8Y2lyY2xlIHN0eWxlPSJmaWxsOiMzMzMzMzM7IiBjeD0iMTY0LjkzOCIgY3k9IjE5Mi42NjUiIHI9IjM3LjIxNiIvPg0KCTxjaXJjbGUgc3R5bGU9ImZpbGw6IzMzMzMzMzsiIGN4PSIzMDUuNjY3IiBjeT0iMTkyLjY2NSIgcj0iMzcuMjE2Ii8+DQoJPHBhdGggc3R5bGU9ImZpbGw6IzMzMzMzMzsiIGQ9Ik0zMTYuMzY0LDY4LjM4OWMtMjguNjc3LDI4LjY3My01Ny4zNSw1Ny4zNS04Ni4wMjQsODYuMDI0YzQuNDA4LDAsOC44MTksMCwxMy4yMjcsMA0KCQljLTI4LjY3My0yOC42NzctNTcuMzQ3LTU3LjM1LTg2LjAyLTg2LjAyNGMtOC41MzktOC41MzktMjEuNzY2LDQuNjg4LTEzLjIyNywxMy4yMjdjMjguNjczLDI4LjY3Nyw1Ny4zNDcsNTcuMzUsODYuMDIsODYuMDI0DQoJCWMzLjYwMywzLjYwMyw5LjYyNCwzLjYwMywxMy4yMjcsMGMyOC42NzctMjguNjczLDU3LjM1LTU3LjM1LDg2LjAyNC04Ni4wMjRDMzM4LjEzLDczLjA3NywzMjQuODk5LDU5Ljg0NiwzMTYuMzY0LDY4LjM4OQ0KCQlMMzE2LjM2NCw2OC4zODl6Ii8+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==" />
</p>
</div>
</td>
</tr>
</tbody>
</table>
<div id="thankumsg_$!{paramFormName}" style=" display:none">
<div class="aui-message aui-message-info closeable shadowed success">
<p>Thank you for your feedback</p>
</div>
</div>
#set( $D = '$' )
#set( $serverUrl = 'AJS.params.contextPath' )
#set( $ajaxCall = 'AJS.$.ajax({url: AJS.params.contextPath + "/ajax/confiforms/rest/save.action?pageId=
'+${cfPageId}+'16646199&f=
'+$!{paramFormName}+'f&choice=
"' +
dcmychoice,
type:
"GET",success:
function()
{
AJS.$("#thankumsg_'+$!{paramFormName}+'").show(); window.setTimeout(function () { AJS.$("#thankumsg_'+$!{paramFormName}+'").fadeOut("slow");}, 2000);}});')
<script type="text/javascript">
AJS.toInit(function() {
AJS.$D('.cf_quickfeedback_$!{paramFormName}').find('img').click(function() {
var dc = AJS.$D(this).attr('data-choice');
${ajaxCall}
});
});
</script>
<style type="text/css">
.user-choice-cf p img {
opacity: .7;
}
.user-choice-cf p:hover img {
opacity: 1;
-webkit-transition: .3s ease-in-out;
transition: .3s ease-in-out;
}
</style>
When a form is used by an authenticated user then this information is stored in the createdBy field, as ConfiForms has some metadata fields stored with each record (even when you have defined just one field, as we did in this example)
type: "GET",
success: function (data) {
// here we need to tell we received the feedback
}
});
}
|
See more complete example on how to setup the handlers with scripting here: Custom feedback form with ConfiForms and some JavaScript
You can also see the form in action and user macro created for you
When a form is used by anonymous users the createdBy field is left blank
What is good about ConfiForms is that you can use and re-use the defined form on multiple pages, as well as build the "views" around the stored data where you want. Let's build the table over the stored data, we will show the metadata field created with the feedback given
...