I'm creating a Docusaurus v2 project that will host documentation for a number of tools. They're all related, so it makes sense for them to be hosted in one place - but they're distinct enough that the docs for each should be separate.
As there are potentially a lot of these tools, I wanted to put the nav links in a dropdown, rather than having them fill up the entire width of the header. I'm trying the following:
themeConfig: {
navbar: {
...
items: [
{
to: '/about',
position: 'left',
label: 'About',
},
{
position: 'left',
label: 'Tools',
items: [
{
type: 'doc',
docId: 'intro',
label: 'Tool 1',
docsPluginId: 'tool1',
},
{
type: 'doc',
docId: 'intro',
label: 'Tool 2',
docsPluginId: 'tool2',
},
...
]
},
...
],
},
}
This partly works, in that a drop down menu appears with the correct labels (Tool 1 and Tool 2) - but the links aren't clickable and aren't highlighted if the active page is one of the documentation tools.
Is this a bug, or am I doing something wrong?
You need href for navigating outside of the website
Or, you need to for avigating within the website, which is client side routing.
{
type: 'doc',
docId: 'intro',
label: 'Tool 1',
docsPluginId: 'tool1',
href: "https://tool1.com"
},
{
type: 'doc',
docId: 'intro',
label: 'Tool 1',
docsPluginId: 'tool1',
to: "/tool1"
},
Related
I'm trying to add add a new page in Docusaurus v2, so I added a new item in the navbar:
module.exports = {
...
themeConfig: {
navbar: {
title: 'My Site: API Documentation',
logo: {
alt: 'My Site Logo',
src: 'img/logo.png',
},
items: [
{
to: 'docs/',
activeBasePath: 'docs',
label: 'Docs',
position: 'left',
},
{
to: 'references/',
activeBasePath: 'references',
label: 'References',
position: 'left',
},
],
},
...
},
presets: [
[
'#docusaurus/preset-classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
// Please change this to your repo.
editUrl:
'https://github.com/facebook/docusaurus/edit/master/website/',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
};
Problem is that when I click the References link, I am redirected to http://localhost:3000/references/ which gives me a Page Not Found page:
Does anybody know where exactly I need to put my *.mds or what I should do to be able add a page inside /references and to access e.g. http://localhost:3000/references/dymmy_page?
There are a couple options, things to check out. The first page you want showing up for /references, you can add the following to the frontmatter of that markdown file: slug: /
Or you can change to use docId (which I love). It's easier for using an ID and not remembering what file has a slug added to the frontmatter. The docid is the id from your markdown file, formatted just like the id in your sidebars.js (folder/id).
For example:
{
type: 'doc',
docId: 'folder-if-any/id-of-markdown-file',
label: 'References',
position: 'left',
},
If you add references in a dropdown menu, then it would be something like:
{
label: 'Docs',
position: 'left',
items: [
{
type: 'doc',
to: 'docs/folder-if-any/id-of-markdown-file',
label: 'References',
},
{
type: 'doc',
to: 'docs/some-other-folder/id-of-markdown-file',
label: 'Guide',
},
]
},
I'm searching for a database concept for managing a dynamic multilevel menu as JSON Object. Because we have different customers, and the menu is depending on the customer. I'm searching for a database structure to store the following JSON String so that I can edit the structure and create again a json object from the data. How would you realize that? I don't need a complete answer, just an approach.
[
{
name: 'Dashboard',
url: '/dashboard',
writeble: true,
icon: 'icon-speedometer'
},
{
name: 'Menu1',
url: '/menu1',
writeble: true,
icon: 'icon-puzzle',
children: [
{
name: 'Item1.1',
url: '/item/item1.1',
icon: 'icon-puzzle'
subitem: [
{
name: 'Subitem 1',
url: '/item/item1.1',
icon: 'icon-puzzle'
}
},
{
name: 'Item1.2',
url: '/item/item1.2',
icon: 'icon-puzzle'
},
{
name: 'Settings',
url: '/settings',
icon: 'icon-settings'
}
]
}
]
If I understand correctly your question, I would use a NoSql DB where every document is your JSON object and the key is the customer Id.
I designing edit form using fieldset. For example,
items: [
{
xtype: 'textfield',
name: 'nameEn',
label: 'Name (English)',
placeholder: '',
autoCapitalize: false,
required: true,
clearIcon: true
},
{
xtype: 'textareafield',
name: 'descriptionEn',
label: 'Description (English)'
},
{
xtype: 'togglefield',
name: 'verified',
label: 'Verified'
}
]
And now I need photos (for view, but upload/remove is possible in future). I have no idea what to do.
Well, for display you can use the xtype:image (documentation here), and for upload you can use the xtype:textfield with an inputType:'file' property. However, you should note that on iOS you may not be able to do file upload without packaging an app (as mentioned in this forum post). If you want users to be able to take a picture with the camera you can use a button, and in the handler use the Ext.device.Camera component.
If you want multiple photos you may want to use an hbox layout around your image components.
Good luck!
EDIT: Here's an example of a panel with an hbox layout and horizontal scrolling. Basically, the simplest image gallery you can make in Sencha Touch (I think):
{
xtype: 'panel',
layout: 'hbox',
scrollable: { direction: 'horizontal' },
items: [
{
xtype: 'image',
src: 'path/to/image.png'
},
{
xtype: 'image',
src: 'path/to/another/image.jpg'
},
...
]
}
I am trying to use third party extension on this link for only time field. How can I use it in sencha touch 2.1?
Edit
I added the extension in ux\picker and then I used following code
Ext.define('HB.view.Search', {
extend: 'Ext.form.Panel',
xtype: 'search',
Ext.require(['Ext.ux.picker.DateTimePicker']),
config: {
title: 'Search',
layout: 'fit',
scrollable: true,
styleHtmlContent: true,
styleHtmlCls: 'searchpage',
//html: ['<h1>Welcome to MyApp</h1>'].join(''),
items: [
{
xtype: 'titlebar',
title: 'Search Page',
docked: 'top'
},
{
xtype: 'textfield',
name: 'from',
placeHolder: 'From'
},
{
xtype: 'textfield',
name: 'to',
placeHolder: 'To'
},
{
xtype: 'datepickerfield',
name: 'date',
value: new Date()
},
{
xtype: 'datetimepickerfield',
name: 'time',
value: new Date()
}
]
},
//style: 'height:' + (Ext.getBody().getHeight()) + 'px;'
height: Ext.getBody().getHeight()
});
But it gives me this error
GET http://localhost/HelsinkiBus/touch/src/DateTimePicker.js?_dc=1357800622746 404 (Not Found)
Uncaught Error: [Ext.Loader] Failed loading 'touch/src/DateTimePicker.js', please verify that the file exists
It is Ext.require(['Ext.ux.field.DateTimePicker']);.
DateTimePicker -> ux/field/DateTimePicker
DateTime -> ux/picker/DateTime
I wasted 6 hours to find this issue.
Just place the files from the ux folder in ux\picker folder in your project and use xtype: 'datetimepickerfield'.
Before you can use this component you need to load the files needed first. You can do this with Ext.require
I'm trying to create a tabpanel view that contains a splitview controller on the first tab. Think "kitchen sink" demo placed into one tab of a tabpanel.
The others do not contain the nestedlist.
http://dev.sencha.com/deploy/touch/examples/production/kitchensink/
I've tried placing the nestedlist into a container, which you can see in some of the commented code shown below.
At the moment, this working code only shows the nestlist taking up the entire section on the first tab:
Ext.application({
name: 'Test',
requires: [
'Ext.dataview.NestedList',
'Ext.navigation.Bar'
],
launch: function() {
Ext.create("Ext.TabPanel", {
fullscreen: true,
tabBarPosition: 'bottom',
items: [{
id: 'tab4',
title: 'Tab4',
iconCls: 'star',
xtype: 'container',
items: [{
xtype: 'nestedlist',
displayField: 'text',
docked: 'left',
store: store
}, {
html: 'Detail View'
}]
}, {
id: 'tab2',
title: 'Tab2',
iconCls: 'star',
html: 'No nav bar?'
}, {
id: 'tab3',
title: 'Tab3',
iconCls: 'star',
html: 'Screen3'
}]
}).setActiveItem(0);
}
});
Store setup:
Ext.Loader.setConfig({ enabled: true });
var data = {
text: 'Groceries',
items: [{
text: 'Drinks',
items: [{
text: 'Water',
items: [{
text: 'Sparkling',
leaf: true
},{
text: 'Still',
leaf: true
}]
},{
text: 'Coffee',
leaf: true
},{
text: 'Espresso',
leaf: true
},{
text: 'Redbull',
leaf: true
},{
text: 'Coke',
leaf: true
},{
text: 'Diet Coke',
leaf: true
}]
},{
text: 'Fruit',
items: [{
text: 'Bananas',
leaf: true
},{
text: 'Lemon',
leaf: true
}]
},{
text: 'Snacks',
items: [{
text: 'Nuts',
leaf: true
},{
text: 'Pretzels',
leaf: true
}, {
text: 'Wasabi Peas',
leaf: true
}]
}
]};
Ext.define('ListItem', {
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'text',
type: 'string'
}]
}
});
var store = Ext.create('Ext.data.TreeStore', {
model: 'ListItem',
defaultRootProperty: 'items',
root: data
});
Okay. I have created this example for you: http://www.senchafiddle.com/#ynn40
You can also download the whole source from here: http://rwd.me/FG5s (quite large as it includes the SDK)
Be sure to look through all the files as I have added lots of documentation.
Some notes:
I created a new component called Sencha.view.SplitView. This obviously can be called anything. It has a xtype of splitview so we can simply just require it and include it into our Main.js file (which is a Ext.tab.Panel.
{
xtype: 'splitview',
title: 'SplitView',
store: 'Items'
}
Because this is an item inside a tabPanel, we need to give it the title configuration too. Of course we could include this Splitview component anywhere.
As you can see it has a store configuration which is defined in SplitView:
config: {
/**
* We create a custom config called store here so we can pass the store from this component
* (SplitView) down into the nested list when it updates. Checkout {#link #updateStore}
* #type {Ext.data.Store}
*/
store: null
}
This is used to pass the store from the splitview to the nested list (we will get to that in a second). Of course that configuration will do nothing unless we add the appropriate methods to update the nested list:
/**
* This is called when the {#link #store} config has been updated.
* We simply check if the nested list has been created, and if it has, set the store
* on it with the new value.
*/
updateStore: function(newStore) {
if (this.nestedList) {
this.nestedList.setStore(newStore);
}
}
As you can see, we are simply updating the nestedList (if it exists) store with the new value of the SplitView store.
Inside the initialize method of SplitView, we created both the detailContainer (where the detail card of the nested list should go) and the nestedList and then add them to the SplitView. Make sure you look at some of the configurations that we give nestedList as they are important. The store configuration:
// Set the store of this nested list to the store config of this component (Splitview)
store: this.getStore()
The detailCard and detailContainer configurations:
// Tell the nested list to have a detail card and put it inside our new detailContinaer
detailCard: true,
detailContainer: this.detailContainer
And of course the listeners so we know when things get changed:
// And finally add a listener so we know when to update the detail card
listeners: {
scope: this,
leafitemtap: this.onLeafItemTap
}
Finally we add the onLeadItemTap method into the Splitview (we added the listener above) which should update the detail card with new information:
/**
* This is called when a leaf item is tapped in the nested list, or when the detail card
* should be updated. In here, we just get the record which was tapped and then set the HTML
* of the detail card.
*/
onLeafItemTap: function(nestedList, list, index, node, record, e) {
var detailCard = nestedList.getDetailCard();
detailCard.setHtml(record.get('text'));
}
Hopefully this makes sense and helps you. If not, let me know.