<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Plugin Archives - Blog IT</title>
	<atom:link href="https://blogit.create.pt/tag/plugin/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogit.create.pt/tag/plugin/</link>
	<description>Create IT blogger community</description>
	<lastBuildDate>Tue, 19 Nov 2019 12:10:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>How to modify and compile a mobile plugin using OutSystems</title>
		<link>https://blogit.create.pt/marisabarradas/2019/11/18/how-to-modify-and-compile-a-mobile-plugin-using-outsystems/</link>
					<comments>https://blogit.create.pt/marisabarradas/2019/11/18/how-to-modify-and-compile-a-mobile-plugin-using-outsystems/#respond</comments>
		
		<dc:creator><![CDATA[Marisa Barradas]]></dc:creator>
		<pubDate>Mon, 18 Nov 2019 15:05:12 +0000</pubDate>
				<category><![CDATA[OutSystems]]></category>
		<category><![CDATA[Misc]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[compile]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[OutSystems 10]]></category>
		<category><![CDATA[Plugin]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=11691</guid>

					<description><![CDATA[<p>As an OutSystems developer, I had the need to use a QR Code plugin reader. First step? Started by creating a test project to be able to choose the best plugin that suited my needs. However…In the moment that I had to install it in the final app, I ran into… “Element uses-permission#android.permission.CAMERA at AndroidManifest.xml:30:5-90 [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/marisabarradas/2019/11/18/how-to-modify-and-compile-a-mobile-plugin-using-outsystems/">How to modify and compile a mobile plugin using OutSystems</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>As an OutSystems developer, I had the need to use a QR Code plugin reader. <br> </p>



<p>First step? Started by creating a test project to be able to choose the best plugin that suited my needs.<br></p>



<p>However…In the moment that I had to install it in the final app, I ran into… “Element uses-permission#android.permission.CAMERA at AndroidManifest.xml:30:5-90 duplicated with element declared at AndroidManifest.xml” error!</p>



<p>The plugin was: <a href="https://www.outsystems.com/forge/component-versions/1403">https://www.outsystems.com/forge/component-versions/1403</a> , and by extensibility configurations, I reached the project URL, as in the image bellow.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="393" height="512" src="https://blogit.create.pt////wp-content/uploads/2019/11/image.png" alt="" class="wp-image-11692" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image.png 393w, https://blogit.create.pt/wp-content/uploads/2019/11/image-230x300.png 230w, https://blogit.create.pt/wp-content/uploads/2019/11/image-322x420.png 322w" sizes="(max-width: 393px) 100vw, 393px" /></figure>



<p>So, after a brief research, I found out that what I had to do was a minor change in plugin.xml file, instead of having </p>



<figure class="wp-block-image size-large"><img decoding="async" width="624" height="126" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-1.png" alt="" class="wp-image-11693" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image-1.png 624w, https://blogit.create.pt/wp-content/uploads/2019/11/image-1-300x61.png 300w" sizes="(max-width: 624px) 100vw, 624px" /></figure>



<p>I had to have:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="624" height="137" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-2.png" alt="" class="wp-image-11694" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image-2.png 624w, https://blogit.create.pt/wp-content/uploads/2019/11/image-2-300x66.png 300w" sizes="(max-width: 624px) 100vw, 624px" /></figure>



<p>So all I needed to do, was to change this
snippet and compile it into the OutSystems project.</p>



<p>So, how can we do it without native
software?</p>



<p><strong>1<sup>st</sup> step: </strong>create a git account at <a href="https://github.com/">https://github.com/</a> and install git &nbsp;<a href="https://gitforwindows.org/">https://gitforwindows.org/</a></p>



<p><strong>2nd step: </strong>Fork the project.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="843" height="178" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-3.png" alt="" class="wp-image-11695" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image-3.png 843w, https://blogit.create.pt/wp-content/uploads/2019/11/image-3-300x63.png 300w, https://blogit.create.pt/wp-content/uploads/2019/11/image-3-768x162.png 768w, https://blogit.create.pt/wp-content/uploads/2019/11/image-3-696x147.png 696w" sizes="(max-width: 843px) 100vw, 843px" /></figure>



<p>Then, in your computer, open git bash in the project folder that you want the project:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="192" height="287" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-4.png" alt="" class="wp-image-11696" /></figure>



<p>Config your account on git bash.</p>



<p><strong>&nbsp;git config &#8211;global user.name &#8220;your username&#8221;</strong></p>



<p><strong>&nbsp;git config &#8211;global user.password &#8220;your password&#8221;</strong></p>



<p>or</p>



<p><strong>git config user.name &#8220;your username&#8221;</strong></p>



<p><strong>git config user.password &#8220;your password&#8221;</strong></p>



<p></p>



<p>And clone the project, as showed in the image bellow.</p>



<p>After cloning the project into your computer, make your code changes
using any editor, and then, follow the steps:</p>



<ol class="wp-block-list"><li>Check modified files: git status</li><li>Add modified files into the list of the next commit:
git add -u</li><li>Commit your changes: git commit -m “description”</li><li>Create a tag: git tag <em>v1.0_1.0</em> -a</li><li>Push your changes into the server: git push origin –tags</li></ol>



<figure class="wp-block-image size-large"><img decoding="async" width="599" height="861" src="https://blogit.create.pt////wp-content/uploads/2019/11/postblog1.png" alt="" class="wp-image-11698" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/postblog1.png 599w, https://blogit.create.pt/wp-content/uploads/2019/11/postblog1-209x300.png 209w, https://blogit.create.pt/wp-content/uploads/2019/11/postblog1-292x420.png 292w" sizes="(max-width: 599px) 100vw, 599px" /></figure>



<p>The project is now ready to be compiled in OutSystems project!! </p>



<p>Open your plugin in OutSystems, and change the URL to your repository#yourtag </p>



<figure class="wp-block-image size-large"><img decoding="async" width="315" height="498" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-6.png" alt="" class="wp-image-11699" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image-6.png 315w, https://blogit.create.pt/wp-content/uploads/2019/11/image-6-190x300.png 190w, https://blogit.create.pt/wp-content/uploads/2019/11/image-6-266x420.png 266w" sizes="(max-width: 315px) 100vw, 315px" /></figure>



<figure class="wp-block-image size-large is-resized"><img decoding="async" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-7.png" alt="" class="wp-image-11700" width="316" height="195" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image-7.png 544w, https://blogit.create.pt/wp-content/uploads/2019/11/image-7-300x185.png 300w, https://blogit.create.pt/wp-content/uploads/2019/11/image-7-356x220.png 356w" sizes="(max-width: 316px) 100vw, 316px" /></figure>



<p>1 &#8211; Publish the changes<br>2 &#8211; Generate App – this will compile your plugin changes</p>



<figure class="wp-block-image size-large"><img decoding="async" width="501" height="609" src="https://blogit.create.pt////wp-content/uploads/2019/11/image-8.png" alt="" class="wp-image-11701" srcset="https://blogit.create.pt/wp-content/uploads/2019/11/image-8.png 501w, https://blogit.create.pt/wp-content/uploads/2019/11/image-8-247x300.png 247w, https://blogit.create.pt/wp-content/uploads/2019/11/image-8-346x420.png 346w" sizes="(max-width: 501px) 100vw, 501px" /></figure>



<p>Reinstall the app in your device, and test it! 🙂</p>



<p>References:</p>



<p><a href="https://www.outsystems.com/forums/discussion/44842/box-camera-overlay/">https://www.outsystems.com/forums/discussion/44842/box-camera-overlay/</a></p>



<p><a href="https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/418">https://github.com/phonegap/phonegap-plugin-barcodescanner/issues/418</a></p>



<p></p>
<p>The post <a href="https://blogit.create.pt/marisabarradas/2019/11/18/how-to-modify-and-compile-a-mobile-plugin-using-outsystems/">How to modify and compile a mobile plugin using OutSystems</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/marisabarradas/2019/11/18/how-to-modify-and-compile-a-mobile-plugin-using-outsystems/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Automatic generation of Umbraco packages with Grunt</title>
		<link>https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/</link>
					<comments>https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/#comments</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 07 Mar 2016 16:03:50 +0000</pubDate>
				<category><![CDATA[Umbraco]]></category>
		<category><![CDATA[automatization]]></category>
		<category><![CDATA[Backoffice extension]]></category>
		<category><![CDATA[grunt]]></category>
		<category><![CDATA[npm]]></category>
		<category><![CDATA[NPM Scripts Task Runner]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Section]]></category>
		<category><![CDATA[visual studio]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/andresantos/?p=1161</guid>

					<description><![CDATA[<p>Manually creating Umbraco packages can be tiresome. If you&#8217;re continuously building upon the same package, doing it manually is wasting time that can be more useful developing new features. This problem presented itself to me when improving Approve It. In order to create the Umbraco package I need several things: The main assembly The new dashboard [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/">Automatic generation of Umbraco packages with Grunt</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Manually creating Umbraco packages can be tiresome.</p>
<p>If you&#8217;re continuously building upon the same package, doing it manually is wasting time that can be more useful developing new features.</p>
<p>This problem presented itself to me when improving <a href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">Approve It</a>. In order to create the Umbraco package I need several things:</p>
<ul>
<li>The main assembly</li>
<li>The new dashboard section html file</li>
<li>The App_Plugins folder which contains every angular controller and views, javascript frameworks and custom css</li>
<li>The <a href="http://packageactioncontrib.codeplex.com/" target="_blank" rel="noopener">Package Actions Contrib</a> assembly and its respective actions that enable me to bundle some translations in the package</li>
</ul>
<p>I decided to go with <a href="http://gruntjs.com/getting-started" target="_blank" rel="noopener">Grunt</a> and the <a href="https://www.npmjs.com/package/grunt-umbraco-package" target="_blank" rel="noopener">Grunt Umbraco Package</a> task. A grunt file is a script that typically automates the process of executing some tasks. These scripts can be executed on top of <a href="https://www.npmjs.com/" target="_blank" rel="noopener">NPM</a>, a package manager for javscript that provides a command line tool to run its packages. To streamline even more the package creation, I installed a Visual Studio extension called <a href="https://visualstudiogallery.msdn.microsoft.com/8f2f2cbc-4da5-43ba-9de2-c9d08ade4941" target="_blank" rel="noopener">NPM Scripts Task Runner</a>, that detects the grunt file and provides a simples UI to handle its tasks.</p>
<p><span id="more-6479"></span></p>
<h3>Step 1 &#8211; Install NPM</h3>
<p>With NPM installed we are able to execute a Grunt file.</p>
<h3>Step 2 &#8211; Install NPM Scripts Task Runner</h3>
<p>The Visual Studio extension:</p>
<p><figure id="attachment_1241" aria-describedby="caption-attachment-1241" style="width: 471px" class="wp-caption alignnone"><a href="http://blogit-create.com/wp-content/uploads/2016/03/npmscriptsvs.png" rel="attachment wp-att-1241"><img decoding="async" class="wp-image-1241 size-full" src="http://blogit-create.com/wp-content/uploads/2016/03/npmscriptsvs.png" alt="NPM Scripts Task Runner Visual Studio extension" width="471" height="235" /></a><figcaption id="caption-attachment-1241" class="wp-caption-text">NPM Scripts Task Runner Visual Studio extension</figcaption></figure></p>
<h3>Step 3 &#8211; Create a Grunt file</h3>
<p>And place it in your project:</p>
<pre class="brush: jscript; title: Gruntfile.js; notranslate">
module.exports = function (grunt) {

    // Setup
    var pkg = grunt.file.readJSON('package.json');
    var projectRoot = 'C:/path/to/project/ApproveIt/';
    var packageNamespace = &quot;Create.Plugin&quot;;

    // Grunt Configuration
    grunt.initConfig({
        pkg: pkg,
        clean: {
            files: &#x5B;
                'bld/App_Plugins',
                'bld/bin',
                'bld/Umbraco'
            ]
        },
        copy: {
            release: {
                files: &#x5B;
                    {
                        expand: true,
                        cwd: projectRoot + 'bin/',
                        src: &#x5B;
                            packageNamespace + '.' + pkg.name + '.dll',
                            'PackageActionsContrib.dll'
                        ],
                        dest: 'bld/bin/'
                    },
                    {
                        expand: true,
                        cwd: projectRoot + 'App_Plugins/',
                        src: &#x5B;'**'],
                        dest: 'bld/App_Plugins/'
                    },
                    {
                        expand: true,
                        cwd: projectRoot + 'Dashboard/Views/dashboard/approveIt/',
                        src: &#x5B;'approveItdashboardintro.html'],
                        dest: &quot;bld/Umbraco/Views/dashboard/approveIt/&quot;
                    }
                ]
            }
        },
        umbracoPackage: {
            release: {
                src: 'bld/',
                dest: 'bin/umbraco',
                options: {
                    name: pkg.name,
                    version: pkg.version,
                    url: pkg.url,
                    license: pkg.license.name,
                    licenseUrl: pkg.license.url,
                    author: pkg.author.name,
                    authorUrl: pkg.author.url,
                    readme: pkg.readme,
                    outputName: pkg.name + '.v' + pkg.version + '.zip',
                    manifest: 'package.xml'
                }
            }
        }
    });

    // Loading of Grunt Tasks
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-umbraco-package');
};
</pre>
<p>This file has three sections, which I&#8217;ll explain in a different order:</p>
<ol>
<li>Setup</li>
<li>Grunt configuration</li>
<li>Loading of grunt tasks</li>
</ol>
<h4>Loading of Grunt Tasks</h4>
<p>Most actions we need a grunt file to execute are simplified by the use of existing Grunt tasks. In my case, I only need 3:</p>
<ol>
<li><em>grunt-contrib-clean</em>: deletes files and folders</li>
<li><em>grunt-contrib-copy</em>: copies files and folders</li>
<li><em>grunt-umbraco-package</em>: generates an umbraco package</li>
</ol>
<h4>Grunt File Setup</h4>
<p>Here I define a set of variables and load an external configuration file that contains project properties I use later on:</p>
<pre class="brush: jscript; title: package.json; notranslate">
{
  &quot;author&quot;: {
    &quot;name&quot;: &quot;André Santos&quot;,
    &quot;url&quot;: &quot;http://www.create.pt&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;grunt&quot;: &quot;~0.4.5&quot;,
    &quot;grunt-contrib-clean&quot;: &quot;^0.6.0&quot;,
    &quot;grunt-contrib-copy&quot;: &quot;~0.4.1&quot;,
    &quot;grunt-umbraco-package&quot;: &quot;1.0.0&quot;
  },
  &quot;license&quot;: {
    &quot;name&quot;: &quot;MIT&quot;,
    &quot;url&quot;: &quot;http://opensource.org/licenses/MIT&quot;
  },
  &quot;name&quot;: &quot;ApproveIt&quot;,
  &quot;readme&quot;: &quot;Umbraco Plugin that creates a section that shows all the content that is waiting approval for publishing.&quot;,
  &quot;url&quot;: &quot;https://our.umbraco.org/projects/backoffice-extensions/approve-it/&quot;,
  &quot;version&quot;: &quot;1.0.1&quot;
}
</pre>
<h4>Grunt Configuration</h4>
<p>This section is where everything comes together. The <em>package.json</em> configuration file is loaded and the three aforementioned grunt tasks are implemented:</p>
<h5>Clean</h5>
<p>In here, the directories used as the source for the umbraco package creation, are configured so that when we can empty them at will</p>
<h5>Copy</h5>
<p>This task copies every file needed by the plugin to a centralized location, creating a snapshot of our plugin. We copy full directories and hand picked files as needed.</p>
<h5>Umbraco Package</h5>
<p>Finally, this task picks up every file we have copied and creates the final Umbraco package. It uses the configuration properties set in <em>package.json</em> and uses a custom <em>package.xml</em> file so that I can include my custom post umbraco package install actions (using Package Actions Contrib):</p>
<pre class="brush: xml; title: package.xml; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
&lt;umbPackage&gt;
  &lt;info&gt;
    &lt;package&gt;
      &lt;name&gt;&lt;%= name %&gt;&lt;/name&gt;
      &lt;version&gt;&lt;%= version %&gt;&lt;/version&gt;
      &lt;license url=&quot;&lt;%= licenseUrl %&gt;&quot;&gt;&lt;%= license %&gt;&lt;/license&gt;
      &lt;url&gt;&lt;%= url %&gt;&lt;/url&gt;
      &lt;requirements&gt;
        &lt;major&gt;3&lt;/major&gt;
        &lt;minor&gt;0&lt;/minor&gt;
        &lt;patch&gt;0&lt;/patch&gt;
      &lt;/requirements&gt;
    &lt;/package&gt;
    &lt;author&gt;
      &lt;name&gt;&lt;%= author %&gt;&lt;/name&gt;
      &lt;website&gt;&lt;%= authorUrl %&gt;&lt;/website&gt;
    &lt;/author&gt;
    &lt;readme&gt;&lt;!&#x5B;CDATA&#x5B;&lt;%= readme %&gt;]]&gt;&lt;/readme&gt;
  &lt;/info&gt;
  &lt;DocumentTypes /&gt;
  &lt;Templates /&gt;
  &lt;Stylesheets /&gt;
  &lt;Macros /&gt;
  &lt;DictionaryItems /&gt;
  &lt;Languages /&gt;
  &lt;DataTypes /&gt;
  &lt;control /&gt;
  &lt;Actions&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;addDashboardSection&quot; dashboardAlias=&quot;StartupApproveItDashboardSection&quot;&gt;
      &lt;section&gt;
        &lt;areas&gt;
          &lt;area&gt;approveIt&lt;/area&gt;
        &lt;/areas&gt;
        &lt;tab caption=&quot;Get Started&quot;&gt;
          &lt;control showOnce=&quot;true&quot; addPanel=&quot;true&quot; panelCaption=&quot;&quot;&gt;
            views/dashboard/approveIt/approveItdashboardintro.html
          &lt;/control&gt;
        &lt;/tab&gt;
      &lt;/section&gt;
    &lt;/Action&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pt&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;cs&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;da&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en_us&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;es&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;fr&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;he&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;it&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ja&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ko&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;nl&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;no&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pl&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ru&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;sv&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;zh&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pt&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Editador por&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;cs&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;da&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en_us&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;es&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;fr&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;he&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;it&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ja&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ko&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;nl&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;no&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pl&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ru&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;sv&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;zh&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
  &lt;/Actions&gt;
  &lt;files&gt;
  	&lt;% files.forEach(function(file) { %&gt;
  	&lt;file&gt;
      &lt;guid&gt;&lt;%= file.guid %&gt;&lt;/guid&gt;
      &lt;orgPath&gt;&lt;%= file.dir %&gt;&lt;/orgPath&gt;
      &lt;orgName&gt;&lt;%= file.name %&gt;&lt;/orgName&gt;
    &lt;/file&gt;
	&lt;% }); %&gt;
  &lt;/files&gt;
&lt;/umbPackage&gt;
</pre>
<p>This file uses the Grunt templating engine so that, not only can I include the Package Action Contrib custom actions, but also some custom variables, such as:</p>
<ul>
<li>The mandatory list of files that is automatically updated when a new file is added to the project output</li>
<li>The <em>package.json</em> variables</li>
</ul>
<p>That&#8217;s it! We can now create new versions of Approve It without having to go into the Umbraco backoffice and doing it manually every time we need a new package version.</p>
<p><em>You can find the complete source code in my GitHub: <a href="https://github.com/ViGiLnT/ApproveIt" target="_blank" rel="noopener">https://github.com/ViGiLnT/ApproveIt</a>. You can download the Approve It package here: <a href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">https://our.umbraco.org/projects/backoffice-extensions/approve-it/</a>.</em></p>
<p>The post <a href="https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/">Automatic generation of Umbraco packages with Grunt</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Building an Umbraco 7 backoffice extension – Part III</title>
		<link>https://blogit.create.pt/andresantos/2015/11/30/building-an-umbraco-7-backoffice-extension-part-iii/</link>
					<comments>https://blogit.create.pt/andresantos/2015/11/30/building-an-umbraco-7-backoffice-extension-part-iii/#comments</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 30 Nov 2015 15:02:06 +0000</pubDate>
				<category><![CDATA[Umbraco]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[Backoffice extension]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Section]]></category>
		<category><![CDATA[WebMatrix]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/andresantos/?p=841</guid>

					<description><![CDATA[<p>The previous post (Part II) showed how to populate the content tree of a custom Umbraco backoffice section. This one presents a way for content managers to quickly handle each post pending approval, which means we&#8217;re going to create our own AngularJS controller and view. AngularJS is a MVC javascript framework mainly mantained by Google which [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2015/11/30/building-an-umbraco-7-backoffice-extension-part-iii/">Building an Umbraco 7 backoffice extension – Part III</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span class="dropcap dropcap3">T</span>he previous post (<a title="Building an Umbraco 7 backoffice extension - Part II" href="http://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii" target="_blank" rel="noopener">Part II</a>) showed how to populate the content tree of a custom Umbraco backoffice section. This one presents a way for content managers to quickly handle each post pending approval, which means we&#8217;re going to create our own AngularJS controller and view.</p>
<p><a title="Angular.JS" href="https://angularjs.org/" target="_blank" rel="noopener">AngularJS</a> is a MVC javascript framework mainly mantained by Google which primary goal is to aid in the development of single-page applications. It&#8217;s use on the Umbraco backoffice was the most notable change when Umbraco 7 was first released.</p>
<p>When the content manager selects one node pending approval we want him to be able to take three quick actions:</p>
<ul>
<li>get some information about that node;</li>
<li>quickly access it in the content section;</li>
<li>quickly publish it.</li>
</ul>
<p><span id="more-6478"></span></p>
<p>New Angular controllers and views must be placed in a specific Umbraco directory, following a specific directory structure:</p>
<ul>
<li>the main directory must reside at ~\App_Plugins\ApproveIt &#8211; the plugin name</li>
<li>the views and controllers must reside at App_Plugins\ApproveIt\backoffice\approvalTree\ &#8211; the tree controller name</li>
</ul>
<p>First things first:</p>
<p>Create a package manifest so that Umbraco knows there are new javascript files available, and place it in the root of App_Plugins\ApproveIt directory.</p>
<pre class="brush: plain; title: package.manifest; notranslate">

{
	javascript: &#x5B;
		'~/App_Plugins/ApproveIt/backoffice/approvalTree/edit.controller.js',
		'~/App_Plugins/ApproveIt/approval.resource.js'
	]
}

</pre>
<p>Then we must create the javascript files referenced by the manifest and the respective angular view.</p>
<pre class="brush: jscript; title: approval.resource.js; notranslate">

angular.module(&quot;umbraco.resources&quot;)
	.factory(&quot;approvalResource&quot;, function ($http) {
	    return {
	        getById: function (id) {
	            return $http.get(&quot;backoffice/ApproveIt/ApprovalApi/GetById?id=&quot; + id);
	        },
	        publish: function (id) {
	            return $http.post(&quot;backoffice/ApproveIt/ApprovalApi/PostPublish?id=&quot; + id);
	        }
	    };
	});
</pre>
<p>This javascript file provides a new <a title="Angular Service" href="https://docs.angularjs.org/guide/services">Angular Service</a> that can then be used by Angular controllers. This service is no more than a facade for the ApprovalApiController created on <a title="Building an Umbraco 7 backoffice extension - Part II" href="http://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii" target="_blank" rel="noopener">Part II</a>. The methods it connects to are created further on.</p>
<pre class="brush: jscript; title: edit.controller.js; notranslate">

angular.module(&quot;umbraco&quot;).controller(&quot;Approval.ApprovalEditController&quot;,
	function ($scope, $routeParams, approvalResource, notificationsService, navigationService) {

	    $scope.loaded = false;

	    if ($routeParams.id == -1) {
	        $scope.node = {};
	        $scope.loaded = true;
	    }
	    else {
	        approvalResource.getById($routeParams.id).then(function (response) {
	            $scope.node = response.data;
	            $scope.loaded = true;
	        });
	    }

	    $scope.publish = function (node) {
	        approvalResource.publish(node.Id).then(function (response) {
	            $scope.node = response.data;
	            $scope.contentForm.$dirty = false;
	            navigationService.syncTree({ tree: 'approvalTree', path: &#x5B;-1, -1], forceReload: true });
	            notificationsService.success(&quot;Success&quot;, node.Name + &quot; has been published&quot;);
	        });
	    };

	});

</pre>
<p>This Angular controller is called when the Approve It section is being used:</p>
<ul>
<li>If no node is selected (for instance, when we access this section for the first time) we do nothing;</li>
<li>If a node is selected (<em>$routeParams.id != -1</em>) we request the node details through our approval.resource service facade</li>
<li>Finally, the quick publish method is also implemented here. This methods calls the ApprovalResource service which then invokes the publish method of the ApprovalApiController.</li>
</ul>
<pre class="brush: xml; title: edit.html; notranslate">

&lt;form name=&quot;contentForm&quot;
      ng-controller=&quot;Approval.ApprovalEditController&quot;
      ng-show=&quot;loaded&quot;
      ng-submit=&quot;publish(node)&quot;
      val-form-manager&gt;
    &lt;umb-panel&gt;
        &lt;umb-header&gt;
            &lt;div class=&quot;span7&quot;&gt;
                &lt;umb-content-name placeholder=&quot;@placeholders_entername&quot;
                                  ng-model=&quot;node.Name&quot; /&gt;
            &lt;/div&gt;
            &lt;div class=&quot;span5&quot;&gt;
                &lt;div class=&quot;btn-toolbar pull-right umb-btn-toolbar&quot;&gt;
                    &lt;umb-options-menu ng-show=&quot;currentNode&quot;
                                      current-node=&quot;currentNode&quot;
                                      current-section=&quot;{{currentSection}}&quot;&gt;
                    &lt;/umb-options-menu&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/umb-header&gt;
        &lt;div class=&quot;umb-panel-body umb-scrollable row-fluid&quot;&gt;
            &lt;div class=&quot;tab-content form-horizontal&quot; style=&quot;padding-bottom: 90px&quot;&gt;
                &lt;div class=&quot;umb-pane&quot;&gt;

                    &lt;umb-control-group label=&quot;Name&quot; description=&quot;Content's name&quot;&gt;
                        &lt;input type=&quot;text&quot; class=&quot;umb-editor umb-textstring&quot; ng-model=&quot;node.Name&quot; required /&gt;
                    &lt;/umb-control-group&gt;

                    &lt;div class=&quot;umb-tab-buttons&quot; detect-fold&gt;
                        &lt;div class=&quot;btn-group&quot;&gt;
                            &lt;a class=&quot;btn&quot; ng-href=&quot;#/content/content/edit/{{node.Id}}&quot;&gt;
                                Show
                            &lt;/a&gt;
                        &lt;/div&gt;
                        &lt;div class=&quot;btn-group&quot;&gt;
                            &lt;button type=&quot;submit&quot; data-hotkey=&quot;ctrl+s&quot; class=&quot;btn btn-success&quot;&gt;
                                Publish
                            &lt;/button&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/umb-panel&gt;
&lt;/form&gt;
</pre>
<p>The node view presents the waiting approval page name and two buttons: one to quickly navigate to it&#8217;s details and another to publish it.</p>
<p>Finally, we need to update the ApprovalApiController.cs to include two new methods:</p>
<pre class="brush: csharp; title: ; notranslate">

public IContent GetById(int id)
{
    IContent content = ApplicationContext.Services.ContentService.GetById(id);
    return content;
}

public IContent PostPublish(int id)
{
    IContent node = ApplicationContext.Services.ContentService.GetById(id);
    ApplicationContext.Services.ContentService.Publish(node);

    return node;
}
</pre>
<ul>
<li>GetById: returns the node details to the angular view</li>
<li>PostPublish: publishes the node being viewed</li>
</ul>
<p>By following these steps we are able to create a complete new Umbraco backoffice section that provides us with a way to manage every site content waiting approval for publishing:</p>
<p><a href="http://blogit-create.com/wp-content/uploads/2015/11/approveit1.0.png"><img decoding="async" class="aligncenter wp-image-1031" src="http://blogit-create.com/wp-content/uploads/2015/11/approveit1.0.png" alt="approveit1.0" width="600" height="410" /></a></p>
<p><em>If you want to see how this plugin as been evolving, you can check its source code in github: <a title="https://github.com/ViGiLnT/ApproveIt" href="https://github.com/ViGiLnT/ApproveIt" target="_blank" rel="noopener">https://github.com/ViGiLnT/ApproveIt</a>. You can also download the plugin ready to be installed at Umbraco&#8217;s extensions repository: <a title="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">https://our.umbraco.org/projects/backoffice-extensions/approve-it/</a>. Other Umbraco 7 tutorials and information can be found here: <a title="http://umbraco.github.io/Belle" href="http://umbraco.github.io/Belle" target="_blank" rel="noopener">http://umbraco.github.io/Belle</a>.</em></p>
<p>The post <a href="https://blogit.create.pt/andresantos/2015/11/30/building-an-umbraco-7-backoffice-extension-part-iii/">Building an Umbraco 7 backoffice extension – Part III</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2015/11/30/building-an-umbraco-7-backoffice-extension-part-iii/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>Building an Umbraco 7 backoffice extension – Part II</title>
		<link>https://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii/</link>
					<comments>https://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii/#respond</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 23 Nov 2015 10:00:56 +0000</pubDate>
				<category><![CDATA[Umbraco]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[Backoffice extension]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Section]]></category>
		<category><![CDATA[WebMatrix]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/andresantos/?p=721</guid>

					<description><![CDATA[<p>The previous post (Building an Umbraco 7 backoffice extension – Part I), demonstrated how easy it is to create a new section in Umbraco&#8217;s backoffice. This post will show how we can populate this new section with meaningful content coming directly from the backoffice. To begin with, we must reference a few more assemblies (also [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii/">Building an Umbraco 7 backoffice extension – Part II</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span class="dropcap dropcap3">T</span>he previous post (<a title="Building an Umbraco 7 backoffice extension – Part I" href="http://blogit.create.pt/andresantos/2015/11/16/building-an-umbraco-7-backoffice-extension-part-i/" target="_blank" rel="noopener">Building an Umbraco 7 backoffice extension – Part I</a>), demonstrated how easy it is to create a new section in Umbraco&#8217;s backoffice. This post will show how we can populate this new section with meaningful content coming directly from the backoffice.</p>
<p>To begin with, we must reference a few more assemblies (also available at the Umbraco&#8217;s installation <em>bin</em> directory):</p>
<ul>
<li>umbraco.dll</li>
<li>cms.dll</li>
<li>Umbraco.Core.dll</li>
<li>System.Web.Http</li>
<li>System.Net.Http.Formatting</li>
</ul>
<p>Then we can populate our section with a tree containing content awaiting approval. To accomplish this we must extend an Umbraco class named TreeController and decorate it with information about our <strong>Approve It</strong> plugin:</p>
<p><span id="more-6471"></span></p>
<pre class="brush: csharp; title: ; notranslate">

&#x5B;Tree(&quot;approveIt&quot;, &quot;approvalTree&quot;, &quot;Content for Approval&quot;)]
&#x5B;PluginController(&quot;ApproveIt&quot;)]
public class ApprovalTreeController : TreeController
{
   protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
   {
       var ctrl = new ApprovalApiController();
       var nodes = new TreeNodeCollection();

       IUser user = UmbracoContext.Security.CurrentUser;

       //check if we're rendering the root node's children
       if (id == Constants.System.Root.ToInvariantString())
       {
           foreach (IContent content in ctrl.GetAll(user))
           {
                var node = CreateTreeNode(
                    content.Id.ToString(),
                    &quot;-1&quot;,
                    queryStrings,
                    content.Name,
                    &quot;icon-document&quot;,
                    false);

               nodes.Add(node);
            }
       }

        return nodes;
    }

    protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
    {
        var menu = new MenuItemCollection();

        if (id == Constants.System.Root.ToInvariantString())
        {
            // root actions
            menu.Items.Add&lt;RefreshNode, ActionRefresh&gt;(
                ApplicationContext.Services.TextService.Localize(ActionRefresh.Instance.Alias));
        }

        return menu;
    }
}
</pre>
<p>To create a tree we must implement two methods:</p>
<ol>
<li>GetTreeNodes: in here we call the GetAll method of the ApprovalApiController that we&#8217;ll create in the following. This GetAll method returns a list of content waiting approval and we just iterate through it all and create tree nodes;</li>
<li>GetMenuForNode: presents a dropdown menu when we right click the root node to refresh the list.</li>
</ol>
<p>Next we create our custom WebAPI and name it ApprovalApiController. For it to be available in our site, we need only extend the UmbracoAuthorizedJsonController.</p>
<pre class="brush: csharp; title: ; notranslate">

&#x5B;PluginController(&quot;ApproveIt&quot;)]
public class ApprovalApiController : UmbracoAuthorizedJsonController
{
    public IList&lt;IContent&gt; UnpublishedContent { get; set; }

    public IEnumerable&lt;IContent&gt; GetAll(IUser user)
    {
        UnpublishedContent = new List&lt;IContent&gt;();

        IList&lt;IContent&gt; root = ApplicationContext.Services.ContentService.GetRootContent().ToList();

        foreach (IContent content in root)
        {
            GetNode(content);
        }

        return UnpublishedContent;
    }

    private void GetNode(IContent node)
    {
        if (!node.Published)
        {
            UnpublishedContent.Add(node);
        }

        foreach (IContent child in ApplicationContext.Services.ContentService.GetChildren(node.Id))
        {
            GetNode(child);
        }
    }
}

</pre>
<p>The GetAll method, iterates through all the nodes in the content section and finds the ones that are not published, that is, that are waiting approval.</p>
<p>With these two classes we are able to populate our section with a tree containing the content nodes that are waiting approval:</p>
<p><a href="http://blogit-create.com/wp-content/uploads/2015/11/approveit2.png"><img decoding="async" class="alignnone size-medium wp-image-791" src="http://blogit-create.com/wp-content/uploads/2015/11/approveit2-167x300.png" alt="approveit2" width="167" height="300" /></a></p>
<p>The next post in the series will show how to create the Angular view and controller that will enable content managers to actually manage the content waiting approval.</p>
<p><em>The Approve It extension can be found here: <a title="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">https://our.umbraco.org/projects/backoffice-extensions/approve-it/</a>. The complete source code can be found here: <a title="https://github.com/ViGiLnT/ApproveIt" href="https://github.com/ViGiLnT/ApproveIt" target="_blank" rel="noopener">https://github.com/ViGiLnT/ApproveIt</a>.</em></p>
<p>The post <a href="https://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii/">Building an Umbraco 7 backoffice extension – Part II</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2015/11/23/building-an-umbraco-7-backoffice-extension-part-ii/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Building an Umbraco 7 backoffice extension &#8211; Part I</title>
		<link>https://blogit.create.pt/andresantos/2015/11/16/building-an-umbraco-7-backoffice-extension-part-i/</link>
					<comments>https://blogit.create.pt/andresantos/2015/11/16/building-an-umbraco-7-backoffice-extension-part-i/#comments</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 16 Nov 2015 15:34:25 +0000</pubDate>
				<category><![CDATA[Umbraco]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[Backoffice extension]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[WebMatrix]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/andresantos/?p=461</guid>

					<description><![CDATA[<p>Umbraco (https://umbraco.com/) is a lean and powerful CMS built on top of current .NET technologies and Javascript frameworks. It provides developers with a varied and simple to use collection of APIs, it is easy to customize and doesn&#8217;t get in the way between the coded markup and the HTML that is actually rendered. The next series [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2015/11/16/building-an-umbraco-7-backoffice-extension-part-i/">Building an Umbraco 7 backoffice extension &#8211; Part I</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span class="dropcap dropcap3">U</span>mbraco (<a href="https://umbraco.com/">https://umbraco.com/</a>) is a lean and powerful CMS built on top of current .NET technologies and Javascript frameworks. It provides developers with a varied and simple to use collection of APIs, it is easy to customize and doesn&#8217;t get in the way between the coded markup and the HTML that is actually rendered.</p>
<p>The next series of posts will show how to build plugins that extend the default Umbraco backoffice capabilities.</p>
<p><span id="more-6467"></span></p>
<h2>How is it built?</h2>
<p>The release of Umbraco&#8217;s version 7 presented a completely redesigned backoffice. It went from a  typical MVC website to a single page application built using <a title="AngularJS" href="https://angularjs.org/" target="_blank" rel="noopener">AngularJS</a>. Umbraco custom WebAPIs are used by Angular controllers in order to read information from the backoffice.</p>
<h2>How can we change it?</h2>
<p>A typical Umbraco 7 backoffice extension requires:</p>
<ol>
<li>Creation of Angular controllers, views and probably models;</li>
<li>Umbraco WebAPI extensions in order to access Umbraco&#8217;s backoffice and for custom server side development;</li>
<li>Extension of some Umbraco classes to customize common backoffice functionalities.</li>
</ol>
<h2>What to do?</h2>
<p>These series of posts will gradually present a way to build a new backoffice section, that will provide content managers with a centralized area where they can approve changes made to content. This backoffice extension was named<strong> Approve It</strong>. Natively, Umbraco sends an email to each content approver when changes are made to content nodes but, if an approver wants to see what nodes were updated just by visiting the backoffice, he must traverse every node to see which ones present a change waiting approval. This gets harder as the number of content nodes increase, and the changed nodes can be difficult to spot as we can see from the image below:</p>
<p><figure id="attachment_541" aria-describedby="caption-attachment-541" style="width: 285px" class="wp-caption aligncenter"><a href="http://blogit-create.com/wp-content/uploads/2015/11/changedcontent.png"><img decoding="async" class="wp-image-541 size-medium" src="http://blogit-create.com/wp-content/uploads/2015/11/changedcontent-285x300.png" alt="changedcontent" width="285" height="300" /></a><figcaption id="caption-attachment-541" class="wp-caption-text">The red arrows point to changed content &#8211; we can&#8217;t tell by the parent node if one of its children has changed</figcaption></figure></p>
<h2>Preparing the development environment</h2>
<ol>
<li>Download the latest and greatest version of Umbraco 7 (currently at v7.3.1): <a title="https://our.umbraco.org/contribute/releases/731/" href="https://our.umbraco.org/contribute/releases/731/ " target="_blank" rel="noopener">https://our.umbraco.org/contribute/releases/731/ </a></li>
<li>Download and setup WebMatrix: <a title="http://www.microsoft.com/web/webmatrix/" href="http://www.microsoft.com/web/webmatrix/" target="_blank" rel="noopener">http://www.microsoft.com/web/webmatrix/</a></li>
<li>Create a new web site in WebMatrix selecting the folder which contains Umbraco&#8217;s downloaded .zip file contents and go through the Setup
<ol>
<li>Select customize</li>
<li>Use a SQL CE database</li>
<li>Choose any starter kit (I chose Txt Starter Kit)</li>
</ol>
</li>
<li>Create a new Empty ASP.NET project in Visual Studio (I&#8217;m using VS2015) and add folders and core references for MVC</li>
</ol>
<h2>Creating a new backoffice section</h2>
<p>Creating a new section in Umbraco is easy:</p>
<ol>
<li>Add references to the following three assemblies available in the <em>bin</em> Umbraco directory:
<ul>
<li>businesslogic.dll</li>
<li>interfaces.dll</li>
<li>System.Web.Mvc.dll (need to replace the one Visual Studio automatically referenced)</li>
</ul>
</li>
<li>Create a new .cs file in the project with the following code:</li>
</ol>
<pre class="brush: csharp; title: ; notranslate">

&#x5B;Application(&quot;approveIt&quot;, &quot;ApproveIt&quot;, &quot;icon-people&quot;, 15)]
public class Section : IApplication
{
}

</pre>
<p>Simply implementing the IApplication interface, creates a new Umbraco backoffice section with the properties defined above.</p>
<p>The next step is translating the section name. If we don&#8217;t translate it, it will show up as [approveIt]. So, we must edit the file<em> \Umbraco\Config\Lang\en.xml</em> (for the UK version), and append the &#8220;approveIt&#8221; line in the &#8220;sections&#8221; area:</p>
<pre class="brush: xml; title: ; notranslate">

&amp;amp;amp;lt;area alias=&quot;sections&quot;&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;concierge&quot;&amp;amp;amp;gt;Concierge&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;content&quot;&amp;amp;amp;gt;Content&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;courier&quot;&amp;amp;amp;gt;Courier&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;developer&quot;&amp;amp;amp;gt;Developer&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;installer&quot;&amp;amp;amp;gt;Umbraco Configuration Wizard&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;media&quot;&amp;amp;amp;gt;Media&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;member&quot;&amp;amp;amp;gt;Members&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;newsletters&quot;&amp;amp;amp;gt;Newsletters&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;settings&quot;&amp;amp;amp;gt;Settings&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;statistics&quot;&amp;amp;amp;gt;Statistics&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;translation&quot;&amp;amp;amp;gt;Translation&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;users&quot;&amp;amp;amp;gt;Users&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;help&quot; version=&quot;7.0&quot;&amp;amp;amp;gt;Help&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;forms&quot;&amp;amp;amp;gt;Forms&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;analytics&quot;&amp;amp;amp;gt;Analytics&amp;amp;amp;lt;/key&amp;amp;amp;gt;
  &amp;amp;amp;lt;key alias=&quot;approveIt&quot;&amp;amp;amp;gt;Approve It&amp;amp;amp;lt;/key&amp;amp;amp;gt;
&amp;amp;amp;lt;/area&amp;amp;amp;gt;

</pre>
<p><strong>Note</strong>: for the new section to appear you must add it to the available sections your user can see. Furthermore, because of caching, you probably need to restart the website and open a browser window in private mode in order to see the new section.</p>
<p>This is how it looks:<br />
<a href="http://blogit-create.com/wp-content/uploads/2015/11/approveit.png"><img decoding="async" class="alignnone size-full wp-image-681" src="http://blogit-create.com/wp-content/uploads/2015/11/approveit.png" alt="approveit" width="112" height="271" /></a></p>
<p>So, we have a new section, but there&#8217;s nothing we can do with it. The next post in the series will show how we can add some content to this newly created Umbraco backoffice area.</p>
<p><em>The Approve It extension can be found here: <a title="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">https://our.umbraco.org/projects/backoffice-extensions/approve-it/</a>. The complete source code can be found here: <a title="https://github.com/ViGiLnT/ApproveIt" href="https://github.com/ViGiLnT/ApproveIt" target="_blank" rel="noopener">https://github.com/ViGiLnT/ApproveIt</a>.</em></p>
<p>The post <a href="https://blogit.create.pt/andresantos/2015/11/16/building-an-umbraco-7-backoffice-extension-part-i/">Building an Umbraco 7 backoffice extension &#8211; Part I</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2015/11/16/building-an-umbraco-7-backoffice-extension-part-i/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
	</channel>
</rss>
