Jira-Servlet-Plugin using TemplateRenderer - plugins

I'm trying to develop a simple HTTP-Servlet, to render a Velocity Template.
My Servlet:
Map<String, Object> context = Maps.newHashMap();
resp.setContentType("text/html;charset=utf-8");
templateRenderer.render("/templates/test/input.vm", context, httpRespnse.getWriter());
atlassian-plugin.xml
<webwork1 key="newactions1" name="New actions1" class="java.lang.Object">
<actions>
<action name="test.ActionAlpha" alias="FirstNewAction">
<view name="success">/templates/test/input.vm</view>
<view name="error">/templates/test/input.vm</view>
<view name="input">/templates/test/input.vm</view>
</action>
</actions>
</webwork1>
(See: https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Internationalising+Your+Plugin)
Everything works fine so far, but after the page is rendered the menu-bar on the left is missing (The other Menu-webitems in the websection)
If I call the URL in my browser by hand, with "!default" behind the action-name, the sidebar is displayed.
http://host:port/jira/secure/FirstNewAction!default.jspa
But if I call the URL without "!default" the output is the same as the servlet produces. Is there a possibility for the TemplateRenderer to add the "!default" term?

I guess
Map<String, Object> context = Maps.newHashMap();
templateRenderer.render("/templates/test/input.vm", context, httpRespnse.getWriter());
passes an empty map to the render method, if you omit the context parameter the default context should be passed which includes the webResources. Another idea is to add something like
meta name="decorator" content="atl.admin"
to the heads section

Related

How to synchronize control values within different views

I would like to know how to get the content of TextArea, assign the value to a variable, set it to a model, and then set the variable to another TextArea in another view. I have coded some examples and it works, but not on TextArea.
Here is the example code:
// In init of the Component.js
this.setModel(new JSONModel(), "TransportModel"); // JSONModel required from "sap/ui/model/json/JSONModel"
// In *.controller.js
this.getView().getModel("TransportModel").setProperty("/", {
"Serial": this.byId("mat_serial").getValue() // "mat_serial" == id of the Input box in XML view
});
In the last step, I set the Text from a different View (also XML and Input Box) with the Value of the Model Element.
<Text text="{TransportModel>/Serial}" />
That worked pretty well.
But how to do the same with the TextArea? How can I do it based on this model? The value that I want to use from the first TextArea should also be on a TextArea in another view.
UI5 supports two-way data binding. I.e. if the user changes something in the UI (e.g. user types something in the text area), that change will be reflected automatically in other bindings that listen to the change.
<!-- In view 1 -->
<TextArea value="{TransportModel>/Serial}" />
<!-- In view 2 -->
<Text text="{TransportModel>/Serial}" />
No need to get input values by hand. Simply let the framework synchronize the value.
How to use a local json model:
Create
initItemViewModel: function () {
return new JSONModel({
Serial: ""
});
}
this._oViewModel = this.initItemViewModel();
this.setModel(this._oViewModel, "TransportModel");
Using
this.getView().getModel("TransportModel").setProperty("/Serial", serial);
<Text text="{TransportModel>/Serial}" width="auto" maxLines="1"/>

Preact-Router - Handle routes from sub directory

I'm currently creating a SPA that can be included and run from any route.
Currently any <Link /> component I create redirects the client back to the root of the domain it's on plus the intended path.
In react-router there's a property to set a starting base path; basename.
This doesn't seem to be present in preact-router and I'd really rather not switch to react-router as it's significantly larger and I won't be using many of the additional features.
A simple example of the routes:
<Router>
<Route
path="/"
component={Home}
/>
<Route
path="/:slug"
component={Merchant}
/>
</Router>
I've seen a couple of post around the internet implying this is possible but with such little documentation it's a little tricky to piece together.
Any help is much appreciated.
Thanks.
I've ended up wrapping the preact-router Link and Router with my own components. From there I can prefix the path property value with my apps base route, e.g:
<MyRoute
path="/"
component={Home}
/>
Then somewhere within <MyRoute />:
const route = 'my/app/base/path';
let result = (route || '') + this.props.path;
result = result.replace(/([^:]\/)\/+/g, '$1');
Then render the preact-router default component with the result value, <Route path={result} />
If you're looking for hash routing, here it is: https://github.com/developit/preact-router#custom-history.
jhdevuk's Answer pointed me to the right direction.
The following Router class will do the trick (this is in TypeScript):
class SubfolderRouter extends preactRouter.Router {
render(props: preactRouter.RouterProps, state: any) {
if (state.url.indexOf(MY_FOLDER) == 0) {
state = {
...state,
url: state.url.substr(MY_FOLDER.length),
};
}
return super.render(props, state);
}
}
If your app lives in the folder const MY_FOLDER = "/myfolder", then this Router will ignore the folder of the URL. If the user navigates to
/myfolder/home/index
then the Router will look up the URL /home/index, because this is the actual route.

Multiple properties from cq-dialog to dom template AEM

I am dependent on getting a json-structure (or something similar) from an AEM cq-dialog to the DOM of the rendered page, where i pick it up by the rendered page's JS.
The sightly page template looks something like the below, here the data-labels are a json-containing the fields of the dialog. As you see I have manually typed all fields/properties:
<div id="myApp"
data-service="${properties.applicationService}"
data-labels="{"title":"${properties.title}","sub1":"${properties.sub1}","number":"${properties.number}"}"></div>
I rather like to be able to pick up all labels more dynamically: data-labels = ${properties.labels}
Can I get all the "label" properties from the cq-dialog to the template as one property?
My dialog has a couple of fields like below, all the properties on tab1 are considered "label" properties (and hence should be added to the #myApp element's data-labels attribute).
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Dialog"
title="my Application"
xtype="dialog">
<items jcr:primaryType="cq:WidgetCollection">
<tabs jcr:primaryType="cq:TabPanel">
<items jcr:primaryType="cq:WidgetCollection">
<tab1
jcr:primaryType="cq:Widget"
title="Texts and Labels"
xtype="panel">
<items jcr:primaryType="cq:WidgetCollection">
<title
jcr:primaryType="cq:Widget"
fieldDescription="The title of the page."
fieldLabel="blablabla"
name="./title"
defaultValue="default value..."
xtype="textfield"/>
<sub1
jcr:primaryType="cq:Widget"
fieldDescription="First subtitle"
fieldLabel="blablba"
name="./subtitle1"
defaultValue="default value..."
xtype="textfield"/>
<number
jcr:primaryType="cq:Widget"
fieldDescription="The textfield label for number."
fieldLabel="number"
name="./number"
defaultValue="number"
xtype="textfield"/>
</items>
</tab1>
...
You could either write a custom ExtJs widget to store the data in the JCR as a JSON string or write a piece of backend (Java or JavaScript) code to read the properties and put them in a JSON object. Personally, I favour the latter approach.
Here's an example using Sling Models:
package com.mycompany.myproject.blah;
//imports, whatever
#Model(adaptables = Resource.class)
public class ItemsModel {
// Properties will be injected by Sling Models from the current resource
#Inject
private String title;
#Inject
private String subtitle1;
#Inject
private String number;
public String getJson() {
// use String concatenation to build a JSON document
// or create a JSON object using Gson or a similar library
// and serailize it to String
}
}
Then in your Sightly file, you can call the model
<div id="myApp" data-sly-use.model="com.mycompany.myproject.blah.ItemsModel"
data-service="${properties.applicationService}"
data-labels="${model.json}"></div>
If you don't want to or cannot use Sling Models, you could write a use class or use the JavaScript Use-API to achieve a similar result.
In your component folder, create a JS file, let's call it items.js, it could look like this:
"use strict";
use(function () {
var items= {};
items.title = "" + properties.get("title");
items.sub1 = "" + properties.get("sub1");
items.number = "" + properties.get("number");
return JSON.stringify(items);
});
To use it in your Sightly script, call it via data-sly-use:
<div id="myApp" data-sly-use.items="items.js"
data-service="${properties.applicationService}"
data-labels="${items}"></div>
If you want to retrieve a number of properties in a more dynamic manner (without specifying each key in your Java/JS code), you can just iterate over all properties and filter them while building the JSON object.
Here's a somewhat crude example in JavaScript that reads all properties of the current resource and puts them in a JSON string:
"use strict";
use(function () {
var result = {},
i,
keys,
key;
keys = properties.keySet().toArray();
for (i = 0 ; i < keys.length ; i ++) {
key = keys[i];
result["" + key] = "" + properties.get(key);
}
return JSON.stringify(result);
});
I'm afraid there's no explicit documentation for the JavaScript API because you're effectively using the same APIs as you would in the Java code. Sorry about the weird type conversions but for some reason, stringify complained about the objects retrieved unless I did the trick with prepending an empty string to enforce the type "" +
I tend not to use JS in my back-end code so I'm not very familiar with this particular style.
If you want to figure out what you can do with the properties object, take a look at the ValueMap javadoc

Titanium Alloy ListView XML Uncaught TypeError: Object #<UI> has no method 'createTemplates'

I am new to Titanium, so excuse my lack of understanding.
Even though I am using sdk version 3.2 (have sdk-version: 3.2.0.v20130801162445 in my tiapp.xml) when I try and have a view that uses the xml above I get this error:
[ERROR][V8Exception( 615)] Exception occurred at alloy/controllers/feed.js:22: Uncaught TypeError: Object # has no method 'createTemplates'
I cut down all my code so that the feed.js file is just:
function loadMoreBtnClicked(_event) {
alert('not implemented yet');
}
function createListView(_data) {
// this is pretty straight forward, assigning the values to the specific
// properties in the template we defined above
var items = [];
for (var i in _data) {
// add items to an array
items.push({
template : "template1", // set the template
textLabel : {
text : _data[i].name // assign the values from the data
},
pic : {
image : _data[i].pic_square // assign the values from the data
}
});
}
// add the array, items, to the section defined in the feed.xml file
$.section.setItems(items);
}
alert('feed loaded');
The XML is in feed.xml and looks like this:
<Alloy>
<Window class="container" formFactor="handheld">
<ListView id="list" defaultItemTemplate="template1">
<Templates>
<ItemTemplate name="buttonItem" height="Ti.UI.SIZE">
<!-- will use this in the next blog post -->
<Button id="loadMoreBtn" onClick="loadMoreBtnClicked">Load More</Button>
</ItemTemplate>
<!-- main template for displaying the list items -->
<ItemTemplate id="template1" name="template1" class="template1">
<ImageView id="pic" bindId="pic" class="imageThumb"/>
<View id="textContainer">
<Label id="textLabel" bindId="textLabel" class="title"/>
</View>
</ItemTemplate>
</Templates>
<!-- we only have one section and the items are contstucted using template1 -->
<ListSection id="section" >
<ListItem template="template1" />
</ListSection>
</ListView>
</Window>
</Alloy>
I still get the error (just using the XML with no actual controller code other than the alert running). If I pull the ListView XML out of the feed.xml file the alert fires, when I put the ListView XML back in I get the Error above.
I am trying to use code from this example:
https://gist.github.com/aaronksaunders/5896390
but cant really tell what I am missing?
Thanks!
-James
found out what the issue was, my problem had to do with not having the updated version of alloy that is needed to support the ListView Templates in XML. I needed to run this at the command line in Windows: "npm install -g alloy#1.2.0-alpha" (without quotes). After that I was able to use ListView templates in XML as shown above.

How to set different localized string in different visual states in WP7 using Blend?

How do I set different localized strings in different visual states in WP7 using Blend without any code behind?
I can set different non-localized strings in different visual states (although it flickers). That works, but how about localized strings?
If I change the string using data binding in Blend, Blend just overrides the data binding in Base state and not the actual state where I'm recording.
EDIT:
This is how I localize my strings:
I have a resources file named AppPresources.resx. Then I would do this in code:
// setting localized button title
mainButton.Content = AppResources.MainButtonText;
Then I have a GlobalViewModelLocator from MVVM Light Toolkit with the following Property for Databinding.
private static AppResources _localizedStrings;
public AppResources LocalizedStrings
{
get
{
if (_localizedStrings == null)
{
_localizedStrings = new AppResources();
}
return _localizedStrings;
}
}
And in xaml file:
<Button x:Name="mainButton" Content="{Binding LocalizedStrings.MainButtonText, Mode=OneWay, Source={StaticResource Locator}}" ... />
What you need to do, is very close to what you're already doing. First, define a class named Resources.cs with following content
public class Resources
{
private static AppResources resources = new AppResources();
public AppResources LocalizedStrings
{
get
{
return resources;
}
}
}
This allows us to create a instance of your Resource File in XAML. To do this, open App.xaml and add following
<Application.Resources>
<local:Resources x:Key="Resources" />
</Application.Resources>
Now when you need to do bindings in your XAML, you do it like this:
<Button Content="{Binding LocalizedStrings.MainButtonText,
Source={StaticResource Resources}}" />
What you'll notice is that it doesn't work in Blend, yet. To make it work in Expression Blend,
add the following file: DesignTimeResources.xaml in the Properties Folder, and add following content
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YourNameSpace">
<local:Resources x:Key="Resources" />
</ResourceDictionary>
Now, you press F6 in Visual Studio to recompile, and voila, your localized strings are available in Expression Blend!
A real-world example from one of my projects:
AppResources.cs
DesignTimeResources.xaml
App.xaml