{"id":253,"date":"2017-03-30T11:36:19","date_gmt":"2017-03-30T09:36:19","guid":{"rendered":"https:\/\/bluemind.purpl-web.com\/?p=253"},"modified":"2022-09-06T09:33:01","modified_gmt":"2022-09-06T07:33:01","slug":"tutorial-writing-a-bluemind-add-on","status":"publish","type":"post","link":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/","title":{"rendered":"Tutorial: writing a BlueMind add-on"},"content":{"rendered":"<p>So here you are with\u00a0your shiny BlueMind setup. You&#8217;ve heard about our grand architecture plans,\u00a0extension points, p2 platform, REST API, but you find it hard to get started. Rejoice! This article has been\u00a0written just for you.<\/p>\n<p>You need to know some java, and be more or less familiar with maven.<\/p>\n<h3>Your goal: a dummy scheduled job<\/h3>\n<p>Let&#8217;s say your BlueMind add-on will be a scheduled job. You can view the <a href=\"https:\/\/forge.bluemind.net\/confluence\/display\/BM35\/Les+taches+planifiees\">BlueMind scheduler<\/a> as an internal CRON that will execute jobs when planned, which is pretty handy to assist you in administrating your server.<\/p>\n<p>This scheduled job\u00a0will log some dummy stats &#8211; basically what we&#8217;ll do is just a placeholder to demonstrate how to\u00a0glue\u00a0the REST API bricks together. Doing something more meaningful will be left as an exercise to the reader \ud83d\ude42<\/p>\n<p>Your scheduled job will list all mobile devices for all users for all domains of your BlueMind server. Just because you can. We&#8217;ll call it <em>MobileDevicesListingJob<\/em>.<\/p>\n<h3>A word of caution<\/h3>\n<p>Don&#8217;t forget that when you&#8217;re using the REST API with a BlueMind server, you&#8217;re dealing with real users data and it&#8217;s pretty easy to make mistakes, since everything you can do in BlueMind can be done using the REST API. There won&#8217;t be a confirmation screen like we do in the Administration Console: when in doubt, just don&#8217;t. Or better: do your API tests on a sandbox server. We won&#8217;t be modifying data in this tutorial, so you should be safe, but you&#8217;ve been warned.<\/p>\n<h3>Bootstrapping a maven project<\/h3>\n<p>If you take a peep into BlueMind internals, it&#8217;s <a href=\"https:\/\/en.wikipedia.org\/wiki\/OSGi\">OSGi<\/a> bundles all over the place. Since we want to build a BlueMind add-on, we depend on BlueMind target platform.<\/p>\n<p>This target platform is published as\u00a0a p2 repository, and you can find it at\u00a0<a href=\"http:\/\/pkg.blue-mind.net\/p2\/latest\/\">http:\/\/pkg.blue-mind.net\/p2\/latest\/<\/a><\/p>\n<p>As the URL implies, this is the latest and greatest BlueMind target platform. It will get updated every time we publish a new BlueMind release &#8211; and hopefully upgrading won&#8217;t break your work.<\/p>\n<p>We&#8217;ll be using <a href=\"https:\/\/eclipse.org\/tycho\/\">Tycho<\/a>, which makes it easy to build your bundles with maven. Here is the simplest\u00a0<a href=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/project_structure.zip\">project_structure<\/a>. Download it and extract it somewhere.<\/p>\n<p>This project is restricted to the bare minimum. I won&#8217;t delve into the details of the configuration files since they are not BlueMind specific, but I want to emphasize\u00a0two points:<\/p>\n<ul>\n<li>pom.xml declares where to find the BlueMind target platform<\/li>\n<li>plugin.xml declares what extension point we&#8217;ll be using, namely <em>scheduledjob_provider<\/em>, along with the name of our soon-to-be-written java\u00a0class:\u00a0<em>org.example.mobiledeviceslistingjob.MobileDevicesListingJob<\/em><\/li>\n<\/ul>\n<p>The rest is just boilerplate configuration.<\/p>\n<p>Alternatively, you could also use our <a href=\"https:\/\/forge.bluemind.net\/confluence\/display\/BM35\/BlueMind+plugin+Maven+Archetype\">maven archetype<\/a> to bootstrap your project. Or clone <a href=\"https:\/\/forge.bluemind.net\/stash\/projects\/BA\/repos\/bluemind-samples\">bluemind-samples<\/a> to find an existing add-on to adapt. There are more than one way to skin a cat. Or a duck. Well&#8230;<\/p>\n<p>In the project directory, you can run:<\/p>\n<pre>mvn install<\/pre>\n<p>Et\u00a0voil\u00e0! You&#8217;ve built your project, but it won&#8217;t work yet: there&#8217;s no code.<\/p>\n<h3>Eclipse to the rescue<\/h3>\n<p>You may just go ahead and write the java code using your favorite editor, but here is how you&#8217;ll do with <a href=\"https:\/\/eclipse.org\/\">Eclipse<\/a>:<\/p>\n<ol>\n<li>Import your maven project into your workspace<\/li>\n<li>Tell eclipse about the BlueMind target platform: go to Preferences, search for &#8220;Target Platform&#8221;, and add a new target platform definition. You need to start with an empty target definition, pick up some name (for instance &#8220;BM target platform&#8221;), then add the URL above as a new Software Site location:<\/li>\n<\/ol>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"alignnone size-full wp-image-260\" src=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-29-17-43-39.png\" alt=\"screenshot-from-2017-03-29-17-43-39\" width=\"515\" height=\"493\" srcset=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-29-17-43-39.png 515w, https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-29-17-43-39-150x144.png 150w, https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-29-17-43-39-300x287.png 300w\" sizes=\"(max-width: 515px) 100vw, 515px\" \/><\/p>\n<p>Select all (the &#8220;Uncategorized&#8221; checkbox in the previous screenshot), click on Finish and you&#8217;re done. Careful, you need to select the target platform we&#8217;ve just defined before you\u00a0close the Preferences window.<\/p>\n<h3>Setting up the dependencies<\/h3>\n<p>We need to declare what parts of the BlueMind target platform we&#8217;ll\u00a0actually use in the MANIFEST.MF. Our <a href=\"https:\/\/forge.bluemind.net\/apidoc\/\">REST API online documentation<\/a>\u00a0for will help you to cherry-pick the parts you&#8217;ll need. If you&#8217;ve installed the optional <em>bm-docs<\/em> package and given the\u00a0<em>Api docs<\/em> permission to your user, this documentation should be available right in the BlueMind UI:<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-262\" src=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-30-09-36-52.png\" alt=\"screenshot-from-2017-03-30-09-36-52\" width=\"605\" height=\"153\" srcset=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-30-09-36-52.png 605w, https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-30-09-36-52-150x38.png 150w, https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/screenshot-from-2017-03-30-09-36-52-300x76.png 300w\" sizes=\"(max-width: 605px) 100vw, 605px\" \/><\/p>\n<p>Icing on the cake: this inline documentation is interactive, so you can execute calls using the javascript client. Beware, the previous\u00a0caution notes also apply! (the harm you&#8217;ll be able to do depends on your logged-in user&#8217;s rights)<\/p>\n<p>The <a href=\"http:\/\/git.blue-mind.net\/bluemind\/\">BlueMind source code<\/a>\u00a0is\u00a0also be a good place to find inspiration.<\/p>\n<p>Here are the dependencies\u00a0we&#8217;ll need, just add these lines at the end of the MANIFEST.MF:<\/p>\n<pre>Require-Bundle: net.bluemind.domain.api,\n net.bluemind.user.api,\n net.bluemind.device.api,\n net.bluemind.scheduledjob.scheduler,\n\u00a0net.bluemind.core.rest,\n net.bluemind.slf4j<\/pre>\n<ul>\n<li>net.bluemind.*.api : the REST apis we&#8217;ll need to explore domains, users and mobile devices<\/li>\n<li>net.bluemind.scheduledjob.scheduler: to make use of the extension point<\/li>\n<li>net.bluemind.core.rest: to setup authentication to the REST API<\/li>\n<li>net.bluemind.slf4j: logging classes\u00a0&#8211; since we won&#8217;t do much more than log some information at the end of the day<\/li>\n<\/ul>\n<h3>Have fun with the REST API<\/h3>\n<p>So go ahead and create the class we&#8217;ve declared in plugin.xml:\u00a0<em>org.example.mobiledeviceslistingjob.MobileDevicesListingJob<\/em>. It has to implement <em>IScheduledJob<\/em>\u00a0for\u00a0<em>scheduledjob_provider<\/em> to be able to plug\u00a0it in. Here is\u00a0the complete <a href=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/code.zip\">code<\/a>. I will only include here the actual\u00a0business logic:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-linenumbers=\"false\">\/\/ logger will write in bm core logs (\/var\/log\/bm\/core.log)\nlogger.info(\"Executing MobileDevicesListingJob\");\n\/\/ sched will write in the execution report, that you can send by mail in the Job setup UI\nsched.info(slot, \"en\", \"Collecting mobile devices data for all users...\\n\");\n\/\/ write header row for the data to come\nsched.info(slot, \"en\", \"device; isWipe; lastSync; user; domain\");\n\/\/ initialize client for domain service\nIDomains domainService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)\n    .instance(IDomains.class);\n\/\/ loop on all domains\ndomainService.all().stream().forEach(domain -&gt; {\n  \/\/ initialize client for user service\n  IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)\n      .instance(IUser.class, domain.uid);\n  \/\/ loop on all users\n  userService.allUids().stream().forEach(userUID -&gt; {\n    \/\/ grab full details for user\n    ItemValue&lt;User&gt; user = userService.getComplete(userUID);\t\t\t\t\n    \/\/ initialize device service for each user\n    try {\n      IDevice deviceService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)\n          .instance(IDevice.class, userUID);\n      \/\/ loop on all devices\n      deviceService.list().values.stream().forEach(device -&gt; {\n        \/\/ collect info for this device\n        List&lt;String&gt; deviceInfo = new ArrayList&lt;&gt;();\n        deviceInfo.add(device.displayName);\n        deviceInfo.add(Boolean.toString(device.value.isWipe));\n        deviceInfo.add(device.value.lastSync.toString());\n        deviceInfo.add(user.displayName);\n        deviceInfo.add(domain.displayName);\n        \/\/ write a line in the report\t\t\t\t\t\n        sched.info(slot, \"en\", String.join(\"; \", deviceInfo));\n      });;\n    } catch (ServerFault exception){\n      \/\/ Skipping this user since she doesn't have a \"device\" container\n    }\n  });\n});<\/pre>\n<h3>Deploy to your BlueMind server<\/h3>\n<p>You can compile this code with<\/p>\n<pre>mvn clean install<\/pre>\n<p>Then drop the resulting jar (target\/org.example.mobiledeviceslistingjob-1.0.0-SNAPSHOT.jar) in the folder\u00a0\/usr\/share\/bm-core\/extensions of your BlueMind server. Then you can restart bm-core<\/p>\n<pre>\/etc\/init.d\/bm-core restart<\/pre>\n<p>And your job should appear among the Scheduled Jobs in the Administration console. You can then execute it, schedule it, send the report to your best friend, it&#8217;s all yours.<\/p>\n<p><strong>Caveat<\/strong>: if you need to recompile\/redeploy your extension, you may need to delete bm-core&#8217;s cache to be sure the fresh jar is picked up:<\/p>\n<pre>rm -Rf \/var\/lib\/bm-core<\/pre>\n<h3>Talking REST from the outside world<\/h3>\n<p>You&#8217;ve noticed we&#8217;ve used a ServerSideServiceProvider to initialize the REST API services, but you can of course <a href=\"https:\/\/forge.bluemind.net\/confluence\/display\/BM35\/API+BlueMind+3.5\">talk\u00a0REST<\/a> from the outside world, for instance by using our python client.\u00a0You need a BlueMind <a href=\"https:\/\/forge.bluemind.net\/confluence\/display\/BM35\/Parametres+utilisateurs#Parametresutilisateurs-APIkeys\">API key<\/a> to do so.<\/p>\n<h3>Share\u00a0your work!<\/h3>\n<p>Don&#8217;t bother sharing your\u00a0<em>MobileDevicesListingJob<\/em>, but once you&#8217;ve done something\u00a0useful you may want to share it on <a href=\"https:\/\/marketplace.bluemind.net\/\">BlueMind Marketplace<\/a>. We&#8217;ll be looking forward to your contributions!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So here you are with\u00a0your shiny BlueMind setup. You&#8217;ve heard about our grand architecture plans,\u00a0extension points, p2 platform, REST API, but you find it hard to get started. Rejoice! This article has been\u00a0written just for you. You need to know some java, and be more or less familiar with maven. Your goal: a dummy scheduled [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":2037,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[179],"tags":[],"class_list":["post-253","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-solution-en"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tutorial: writing a BlueMind add-on - Bluemind<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial: writing a BlueMind add-on - Bluemind\" \/>\n<meta property=\"og:description\" content=\"So here you are with\u00a0your shiny BlueMind setup. You&#8217;ve heard about our grand architecture plans,\u00a0extension points, p2 platform, REST API, but you find it hard to get started. Rejoice! This article has been\u00a0written just for you. You need to know some java, and be more or less familiar with maven. Your goal: a dummy scheduled [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\" \/>\n<meta property=\"og:site_name\" content=\"Bluemind\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-30T09:36:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-09-06T07:33:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"626\" \/>\n\t<meta property=\"og:image:height\" content=\"417\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Tutorial: writing a BlueMind add-on\",\"datePublished\":\"2017-03-30T09:36:19+00:00\",\"dateModified\":\"2022-09-06T07:33:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\"},\"wordCount\":1063,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg\",\"articleSection\":[\"BlueMind's Solution\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\",\"url\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\",\"name\":\"Tutorial: writing a BlueMind add-on - Bluemind\",\"isPartOf\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg\",\"datePublished\":\"2017-03-30T09:36:19+00:00\",\"dateModified\":\"2022-09-06T07:33:01+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage\",\"url\":\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg\",\"contentUrl\":\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg\",\"width\":\"626\",\"height\":\"417\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/bluemind.purpl-web.com\/en\/homepage\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial: writing a BlueMind add-on\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#website\",\"url\":\"https:\/\/bluemind.purpl-web.com\/en\/\",\"name\":\"Bluemind\",\"description\":\"Collaborative messaging\",\"publisher\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/bluemind.purpl-web.com\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#organization\",\"name\":\"BlueMind\",\"url\":\"https:\/\/bluemind.purpl-web.com\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/06\/logobm_300.png\",\"contentUrl\":\"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/06\/logobm_300.png\",\"width\":300,\"height\":100,\"caption\":\"BlueMind\"},\"image\":{\"@id\":\"https:\/\/bluemind.purpl-web.com\/en\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial: writing a BlueMind add-on - Bluemind","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial: writing a BlueMind add-on - Bluemind","og_description":"So here you are with\u00a0your shiny BlueMind setup. You&#8217;ve heard about our grand architecture plans,\u00a0extension points, p2 platform, REST API, but you find it hard to get started. Rejoice! This article has been\u00a0written just for you. You need to know some java, and be more or less familiar with maven. Your goal: a dummy scheduled [&hellip;]","og_url":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/","og_site_name":"Bluemind","article_published_time":"2017-03-30T09:36:19+00:00","article_modified_time":"2022-09-06T07:33:01+00:00","og_image":[{"width":626,"height":417,"url":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Written by":"","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#article","isPartOf":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/"},"author":{"name":"","@id":""},"headline":"Tutorial: writing a BlueMind add-on","datePublished":"2017-03-30T09:36:19+00:00","dateModified":"2022-09-06T07:33:01+00:00","mainEntityOfPage":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/"},"wordCount":1063,"commentCount":0,"publisher":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/#organization"},"image":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage"},"thumbnailUrl":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg","articleSection":["BlueMind's Solution"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/","url":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/","name":"Tutorial: writing a BlueMind add-on - Bluemind","isPartOf":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage"},"image":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage"},"thumbnailUrl":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg","datePublished":"2017-03-30T09:36:19+00:00","dateModified":"2022-09-06T07:33:01+00:00","breadcrumb":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#primaryimage","url":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg","contentUrl":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/03\/homme-utilisant-ordinateur-portable_23-2147961542.jpg","width":"626","height":"417"},{"@type":"BreadcrumbList","@id":"https:\/\/bluemind.purpl-web.com\/en\/tutorial-writing-a-bluemind-add-on\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/bluemind.purpl-web.com\/en\/homepage\/"},{"@type":"ListItem","position":2,"name":"Tutorial: writing a BlueMind add-on"}]},{"@type":"WebSite","@id":"https:\/\/bluemind.purpl-web.com\/en\/#website","url":"https:\/\/bluemind.purpl-web.com\/en\/","name":"Bluemind","description":"Collaborative messaging","publisher":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/bluemind.purpl-web.com\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/bluemind.purpl-web.com\/en\/#organization","name":"BlueMind","url":"https:\/\/bluemind.purpl-web.com\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/bluemind.purpl-web.com\/en\/#\/schema\/logo\/image\/","url":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/06\/logobm_300.png","contentUrl":"https:\/\/bluemind.purpl-web.com\/wp-content\/uploads\/2017\/06\/logobm_300.png","width":300,"height":100,"caption":"BlueMind"},"image":{"@id":"https:\/\/bluemind.purpl-web.com\/en\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"_links":{"self":[{"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/posts\/253","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/comments?post=253"}],"version-history":[{"count":3,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/posts\/253\/revisions"}],"predecessor-version":[{"id":4008,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/posts\/253\/revisions\/4008"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/media\/2037"}],"wp:attachment":[{"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/media?parent=253"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/categories?post=253"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bluemind.purpl-web.com\/en\/wp-json\/wp\/v2\/tags?post=253"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}