I am working on an Aikau Share Page where I a side bar that is using the Alfresco Share document library tree picker. The picker allows me to publish the nodeRef to another widget which will display information. I would like to use the tree view but i'm having trouble showing the documents and it is only showing the containers/folders. Anyone have any idea on what I need to do in order to solve this?
Here is the Aikua code i am using:
{
align: "sidebar",
name: "alfresco/layout/Twister",
config: {
label: "twister.library.label",
additionalCssClasses: "no-borders",
widgets: [
{
name: "alfresco/navigation/PathTree",
config: {
showRoot: true,
rootLabel: "Repository",
rootNode: "/app:company_home",
publishTopic: "ALF_ITEM_SELECTED"
}
}
]
}
}
I am wondering if I need to write an extension to the CoreXhr or what the steps would be in order to make this work.
Any help would be appreciated
I was able to figure this out. The problem comes from the repository script in the alfresco explorer side "treenode.get.js". The solution was to do the following
Create a new webscript in alfresco explorer and copy treenode.get.js code into the new webscript. I ended up calling mine customtreenode.get.js.
Remove the logic check for IsContainer in the newly created webscript
Create new Aikau file that extends PathTree. Here is the code below
define(["dojo/_base/declare",
"alfresco/navigation/PathTree",
"alfresco/documentlibrary/_AlfDocumentListTopicMixin",
"service/constants/Default",
"dojo/_base/lang",
"dojo/_base/array",
"dojo/dom-class",
"dojo/query",
"dojo/NodeList-dom"],
function(declare, PathTree, _AlfDocumentListTopicMixin, AlfConstants, lang, array, domClass, query) {
return declare([PathTree, _AlfDocumentListTopicMixin], {
useHash: true,
getTargetUrl: function alfresco_navigation_Tree__getTargetUrl() {
var url = null;
if (this.siteId && this.containerId)
{
url = AlfConstants.PROXY_URI + "slingshot/doclib/treenodeCustom/site/" + this.siteId + "/documentlibrary";
}
else if (this.rootNode)
{
url = AlfConstants.PROXY_URI + "slingshot/doclib/treenodeCustom/node/alfresco/company/home";
}
else if (!this.childRequestPublishTopic)
{
this.alfLog("error", "Cannot create a tree without 'siteId' and 'containerId' or 'rootNode' attributes", this);
}
return url;
}
});
});
Change your code to use the new CustomPathTree
{
align: "sidebar",
name: "alfresco/layout/Twister",
config: {
label: "twister.library.label",
additionalCssClasses: "no-borders",
widgets: [
{
name: "CustomWidgets/widgets/CustomTreeNode",
config: {
showRoot: true,
rootLabel: "Repository",
rootNode: "/app:company_home",
publishTopic: "ALF_ITEM_SELECTED"
}
}
]
}
}
It works after that. I still need to change the icons from folders to documents.
Related
I am working on creating a Polymer app for a pet project, using the Polymer Starter Kit, and modifying it to add horizontal toolbar, background images, etc. So far, everything has worked fine except the links in the app-toolbar do not update the "view" when I click on them.
All my debugging so far points me in the direction of the "page" property. I believe this is not getting updated or is null, causing the view to default to "about" (which is View-2 as per the starter kit) as specified in the _routePageChanged observer method.
I tried using the debugger on DevTools on Chrome, but being new to this, I'm not very clear if I did it correctly. I just kept going in and out of hundred of function calls.
I am copying relevant parts of the app-shell.
Please help or at least point me in the right direction; I've been trying to fix this since 2 days. Thank you!
<app-location
route="{{route}}">
</app-location>
<app-route
route="{{route}}"
pattern=":view"
data="{{routeData}}"
tail="{{subroute}}">
</app-route>
<!-- Main content -->
<app-header-layout has-scrolling-region>
<app-header slot="header" class="main-header" condenses effects="waterfall">
<app-toolbar class="logo"></app-toolbar>
<app-toolbar class="tabs-bar" hidden$="{{!wideLayout}}">
<paper-tabs selected="[[selected]]" attr-for-selected="name">
<paper-tab>Home</paper-tab>
<paper-tab>About Us</paper-tab>
<paper-tab>Pricing</paper-tab>
</paper-tabs>
</app-toolbar>
</app-header>
<iron-pages
selected="[[page]]"
attr-for-selected="name"
fallback-selection="view404"
role="main">
<my-view1 name="home"></my-view1>
<my-view2 name="about"></my-view2>
<my-view3 name="pricing"></my-view3>
<my-view404 name="view404"></my-view404>
</iron-pages>
</app-header-layout>
</app-drawer-layout>
<script>
class MyApp extends Polymer.Element {
static get is() { return 'my-app'; }
static get properties() {
return {
page: {
type: String,
reflectToAttribute: true,
observer: '_pageChanged'
},
wideLayout: {
type: Boolean,
value: false,
observer: 'onLayoutChange'
},
items: {
type: Array,
value: function() {
return ['Home', 'About', 'Pricing', 'Adults', 'Contact'];
}
},
routeData: Object,
subroute: String,
// This shouldn't be neccessary, but the Analyzer isn't picking up
// Polymer.Element#rootPath
// rootPath: String,
};
}
static get observers() {
return [
'_routePageChanged(routeData.page)',
];
}
_routePageChanged(page) {
// If no page was found in the route data, page will be an empty string.
// Default to 'view1' in that case.
this.page = page || 'about';
console.log('_routePageChange');
// Close a non-persistent drawer when the page & route are changed.
if (!this.$.drawer.persistent) {
this.$.drawer.close();
}
}
_pageChanged(page) {
// Load page import on demand. Show 404 page if fails
var resolvedPageUrl = this.resolveUrl(page + '.html');
Polymer.importHref(
resolvedPageUrl,
null,
this._showPage404.bind(this),
true);
}
_showPage404() {
this.page = 'view404';
}
_onLayoutChange(wide) {
var drawer = this.$.drawer;
if (wide && drawer.opened){
drawer.opened = false;
}
}
}
window.customElements.define(MyApp.is, MyApp);
</script>
Here's a snapshot of the page when I click on the "Home" link.
Snapshot of the page
I have fixed the same issue on my app, page observed functions like:
static get properties() { return {
page:{
type:String,
reflectToAttribute:true,
observer: '_pageChanged'},
...
_pageChanged(page, oldPage) {
if (page != null) {
if (page === "home" ) {
this.set('routeData.page', "");
} else {
this.set('routeData.page', page);
}
.......
}
}
Honestly, I am still trying to find the better solution. Because I have users page and I could not manage to able to indexed at google search results. This only keeps synchronized the iron-pages and address link.
This is my main.js file in a Durandal project.
What I'm trying to do is set things up so that the name 'upload-item' resolves to either 'upload-item' or 'upload-item-prehtml5' depending on whether File is defined.
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal': '../lib/durandal/js',
'plugins': '../lib/durandal/js/plugins',
'transitions': '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-2.3.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1.min',
'jquery-ui': '../lib/jquery-ui/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.min',
'moment': '../lib/moment/moment',
'knockout-jqueryui': '../lib/knockout/knockout-jqueryui.min',
'file-size-formatting': '../lib/wone/file-size-formatting'
},
shim: {
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
}
}
});
define(['durandal/system', 'durandal/app', 'durandal/viewLocator'], function (system, app, viewLocator) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");
var filetype = typeof(File);
if (filetype == 'undefined') {
//apply pre-html5 fixups
require.config({
map: {
'*': {
'upload-item': 'upload-item-prehtml5'
}
}
});
}
app.title = 'Jumbo File Transfer';
//specify which plugins to install and their configuration
app.configurePlugins({
router: true,
dialog: true,
widget: {
kinds: ['expander']
}
});
app.start().then(function () {
//Replace 'viewmodels' in the moduleId with 'views' to locate the view.
//Look for partial views in a 'views' folder in the root.
viewLocator.useConvention();
//Show the app by setting the root view model for our application.
app.setRoot('shell');
});
});
Testing on IE8 shows that the call to require.config occurs and the mapping is added, but it doesn't seem to have the effect I expected: upload-item.js and upload-item.html are loaded when I expected upload-item-prehtml5.js and upload-item-prehtml5.html to be loaded.
If this is the wrong way to go about this, then what is the right way to perform this kind of conditional resolution?
It's not quite what I originally wanted, but I found you can do this:
var prehtml5 = (typeof (File) == 'undefined');
requirejs.config({
paths: {
...
'upload-item': prehtml5 ? 'upload-item-prehtml5' : 'upload-item'
},
shim: {
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
}
}
});
Path remapping seems to extend into the file name. Normally you wouldn't list siblings of main.js but you can and if you do then you can remap them, including the file name.
I'm trying to get the item disclosure to work in a list item in Sencha Touch using a controller ref. But the event never seems to fire/receive inside controller. All of the examples I've seen have the list item using a listener but I thought that wasn't very MVC so I'm trying to do it this way (is there any reason why they use listeners instead of a controller?)
In my view, the list is an item inside the EnquiryIndex view.
When I do this in a console window it returns the list correctly so I know the ref is working ok:
Ext.ComponentQuery.query("enquiryindexview list")[0]
See below example:
Ext.define('MyApp.controller.EnquiryIndex', {
extend: 'Ext.app.Controller',
requires: [
],
config: {
refs: {
enquiryIndexViewRef: 'enquiryindexview list'
},
control: {
'enquiryIndexViewRef': {
disclose: 'onDiscloseEnquiryIndex'
}
}
},
onDiscloseEnquiryIndex: function (rec) {
// never gets here!
}
});
Try this
config: {
control: {
'enquiryindexview list': {
disclose: 'onDiscloseEnquiryIndex'
}
}
or this
config: {
refs: {
enquiryIndexViewRef: 'enquiryindexview list'
},
control: {
enquiryIndexViewRef: {
disclose: 'onDiscloseEnquiryIndex'
}
}
Hope this helps
What you might have missed doing is adding this line in the app.js
controllers: ['EnquiryIndex'],
Try this out, it should work now.
I'm just getting started with Sencha Touch 2 and I have never worked with Sencha Touch 1.x before. I've just finished this tutorial (which is the best starter tutorial I have found so far) http://miamicoder.com/2012/how-to-create-a-sencha-touch-2-app-part-1/ and now I want to go ahead and extend this Notes App.
I have a controller and 2 views, a list view and an edit view. In the edit view I want to be able to delete the current record. The delete function is in the controller. After tapping the delete button, I want to show a confirmation dialog ("Are you sure you want to delete...?"). After the user presses yes, the delete function should be called.
Now my problem is: How do I call the controllers delete function from within Ext.Msg.confirm?
Here are the relevant snippets of my code. Please let me know if something important is missing.
Please see the "onDeleteNoteCommand" function. "this.someFunction" obviously doesn't work since "this" is a DOMWindow.
Ext.define('TestApp2.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
noteEditorView: 'noteeditorview'
},
control: {
noteEditorView: {
deleteNoteCommand: 'onDeleteNoteCommand',
}
}
},
onDeleteNoteCommand: function() {
console.log('onDeleteNoteCommand');
var noteEditor = this.getNoteEditorView();
var currentNote = noteEditor.getRecord();
Ext.Msg.confirm(
"Delete note?",
"Do you reall want to delete the note <i>"+currentNote.data.title+"</i>?",
function(buttonId) {
if(buttonId === 'yes') {
//controller functions!! how to call them?
this.deleteNote(currentNote);
this.activateNotesList();
}
}
);
},
deleteNote: function(record) {
var notesStore = Ext.getStore('Notes');
notesStore.remove(record);
notesStore.sync();
},
activateNotesList: function() {
Ext.Viewport.animateActiveItem(this.getNotesListView(), this.slideRightTransition);
},
slideLeftTransition: { type: 'slide', direction: 'left' },
slideRightTransition: { type: 'slide', direction: 'right' },
launch: function() {
this.callParent();
Ext.getStore('Notes').load();
console.log('launch main controller');
},
init: function() {
this.callParent();
console.log('init main controller');
}
});
When you enter callback function of Ext.Msg the scope changes from controller scope to global scope (window), so you must set up it as parameter of confirm method:
Ext.Msg.confirm(
"Delete note?",
"Do you reall want to delete the note <i>"+currentNote.data.title+"</i>?",
function(buttonId) {
if(buttonId === 'yes') {
this.deleteNote(currentNote);
this.activateNotesList();
}
},
this // scope of the controller
);
For more info please check sencha docs: http://docs.sencha.com/touch/2-0/#!/api/Ext.MessageBox-method-confirm
In the standard "Pull to Refresh" plugin, the list store gets updated. However, I have two lists and I need to update a different store for my detail list. How can I override the update event and reload my other store? I tried adding a simple listener but it's not firing.
[Update]
I got this snippet from the Sencha site to work:
plugins: [
{
xclass: 'Ext.plugin.PullRefresh',
pullRefreshText: 'Pull down for more new Events!',
refreshFn: function(plugin) {
console.log( "I'm pulled" );
}
}
]
Original code:
Ext.define('SenchaFiddle.view.ListView', {
extend: 'Ext.dataview.List',
xtype: 'main-list',
config: {
plugins: [
'pullrefresh',
{
pullRefreshText: 'Do it!',
type: 'listpaging',
// Don't offer "Load More" msg
autoPaging: false,
refreshFn: function() {
console.log("Boom");
},
listeners: {
'updatedata': function(plugin, list) {
console.log("Getting the data");
}
}
}
],
layout: 'fit',
width: 300,
itemTpl: '{text}'
}
});
In Sencha Touch 2.2, they have removed the refreshFn config from Ext.util.PullRefresh. I have successfully implemented a custom refreshFn with the new version of Sencha Touch by overriding the fetchLatest function inside Ext.util.PullRefresh like so...
Ext.define('MyApp.overrides.PullRefreshOverride', {
override: 'Ext.plugin.PullRefresh',
fetchLatest: function() {
var list = this.getList();
switch(list.getItemId()) {
case "list1":
this.updateStore1();
break;
case "list2":
this.updateStore2();
break;
}
this.callParent(arguments);
},
//My own custom function to add to the plugin
updateStore1: function() {
//Code to update store 1
},
//My own custom function to add to the plugin
updateStore2: function {
//Code to update store 2
}
});
Having a look at Ext.plugin.PullRefresh definition in sencha-touch-all-debug, I see this config:
/*
* #cfg {Function} refreshFn The function that will be called to refresh the list.
* If this is not defined, the store's load function will be called.
* The refresh function gets called with a reference to this plugin instance.
* #accessor
*/
refreshFn: null,
It might be a good idea that you can achieve what you need through refreshFn config.
For those who need the refreshFn back, there is a PullRefreshFn extension for PullRefresh.
I needed PullRefresh to get triggered by a Panel, rather than a List or Dataview and I also needed to manually load and set data to my Dataview upon user triggering the PullRefresh.
For this I needed the refreshFn config function that existed prior to Sencha 2.2, so here is my implementation.
PullRefreshFn (Modified)
Ext.define('Ext.plugin.PullRefreshFn', {
extend: 'Ext.plugin.PullRefresh',
alias: 'plugin.pullrefreshfn',
requires: ['Ext.DateExtras'],
config: {
/**
* #cfg {Function} refreshFn The function that will be called to refresh the list.
* If this is not defined, the store's load function will be called.
*/
refreshFn: null
},
fetchLatest: function() {
if (this.getRefreshFn()) {
this.getRefreshFn().call();
} else {
var store = this.getList().getStore(),
proxy = store.getProxy(),
operation;
operation = Ext.create('Ext.data.Operation', {
page: 1,
start: 0,
model: store.getModel(),
limit: store.getPageSize(),
action: 'read',
sorters: store.getSorters(),
filters: store.getRemoteFilter() ? store.getFilters() : []
});
proxy.read(operation, this.onLatestFetched, this);
}
}
});
My Controller
Ext.define('myApp.controller.MyController', {
extend: 'Ext.app.Controller',
requires: ['Ext.plugin.PullRefreshFn'],
...
// More code
...
// Binds the Pull Refresh to myPanel view item.
// myPanel is a panel. Not list nor dataview.
setPullRefresh: function () {
var me = this;
// We get reference to myPanel and
// we set PullRefreshFn
this.getMyPanel().setPlugins([{
xclass: 'Ext.plugin.PullRefreshFn',
docked: 'top',
// We set autoSnapBack to false,
// as we are going to trigger this manually
autoSnapBack: false,
// refreshFn will be called upon user releasing for refresh.
refreshFn: function() {
// This is a custom function that sets data to our dataview list.
// When it's done setting data, we trigger the snapBack.
me.populateMylist(function () {
me.getMyPanel().getPlugins()[0].snapBack(true);
});
}
}]);
}
});