IMPORTANT: Currently works only with the default theme (e.g. Material design theme not supported) IMPORTANT: Previous CSON configuration needs to be rewritten in YAML
main.js
of the mantra appMantra plugin settings are kept in the mantra.json file
Context menu was disabled in mantra pane, as this led to problems with file deletion, which often led to unexpected deletes.
Plugin can be easily customised by creating a mantra.yaml file in the project root. In the configuration, you first define the structure of the panes that will be displayed, then you define following parameters:
For each template you define following parameters:
Checkout extra configuration in the project repository. Following is an exemplary configuration for the "Classic Mantra Javascript" project.
root: ''panes:- name: Modulestructure:- directory: actionsstructure:- file: index.tstemplate: actionIndex- directory: componentsstructure:- file: stories/index.tstemplate: storiesIndex- directory: containers- file: routes.tsxtemplate: route- file: index.tstemplate: module- name: Serverstructure:- directory: server/publicationsstructure:- file: index.tstemplate: publicationIndex- directory: server/methodsstructure:- file: index.tstemplate: methodIndex- file: server/index.tstemplate: server- name: Configsstructure:- directory: client/configs- directory: lib- file: client/configs/context.tstemplate: context- file: client/index.tstemplate: clienttemplates:# Module action template- name: actionstext: |class Actions {create({Meteor, LocalState}, myParam) {},};let actions = new Actions();export default actions;placeholders:actions:- type: replacepath: index.tswhat: const actions = {replace: import $name from "./$name";\nconst actions = {- type: replacepath: index.tswhat: const actions = {replace: const actions = {\n $name,- type: createpath: tests/$name_test.tstext: |const {describe, it} = global;import {expect} from 'chai';import {spy, stub} from 'sinon';import actions from '../posts';describe('module.actions.actionSet', () => {describe('create', () => {it('should reject if title is not there', () => {const LocalState = {set: spy()};actions.create({LocalState}, null, 'content');const args = LocalState.set.args[0];expect(args[0]).to.be.equal('SAVING_ERROR');expect(args[1]).to.match(/required/);});});});- name: actionIndexcreate: truetext: |const actions = {// ACTION};export default actions;# Module component template- name: storiesIndexcreate: truetext: |// imports- name: componentstext: |import React from "react";interface IProps {}export default class $1 extends React.Component {render() {return (<div></div>);}}placeholders:- Component Nameactions:- type: createpath: tests/$name_test.tstext: |const {describe, it} = global;import {expect} from 'chai';import {shallow} from 'enzyme';import Component from '../$name';describe('test', () => {it('should display the post title', () => {const el = shallow(<Component />);expect(el).not.to.be.null;});});- type: createpath: stories/$name_stories.tstext: |import React from 'react';import { storiesOf, action } from '@kadira/storybook';import Component from '../$name';storiesOf('module.$name', module).add('default view', () => {return (<Component />);})- type: replacepath: stories/index.tswhat: // importsreplace: |// importsimport $name from "./$name_stories";# Module container template- name: containerstext: |import { useDeps, composeWithTracker, composeAll } from "../../../configs/context";import Component from "../components/$1";interface IProps {context?: () => IContext;clearErrors: Function;}export const composer = ({context, clearErrors}, onData) => {const { Meteor, Collections } = context();if (Meteor.subscribe("$3", postId).ready()) {const options = {sort: {createdAt: -1}};const data = {Collections.$2.find({$2}, options).fetch()};onData(null, {data});} else {onData();}return clearErrors;};export const depsMapper = (context, actions) => ({create: actions.schedule.create,handleSearch: actions.schedule.handleSearch,context: () => context});export default composeAll(composeWithTracker(composer),useDeps(depsMapper))(Component);placeholders:- Component Name- Collection Name- Subscriptionactions:- type: createpath: tests/$name_test.tstext: |const { describe, it } = global;import {expect} from 'chai';import {spy, stub} from 'sinon';import {composer, depsMapper} from '../newpost';describe('component', () => {describe('composer', () => {it('should get SAVING_ERROR from local state', () => {const LocalState = {get: spy()};const context = () => ({LocalState});composer({context}, spy());const args = LocalState.get.args[0];expect(args).to.have.length(1);expect(args[0]).to.be.equal('SAVING_ERROR');});});});# Module route template- name: routeshow: truecreate: truetext: |import React from "react";import { mount } from "mantra-core";export default function (injectDeps) {//const MainLayoutCtx = injectDeps(MainLayout);// Move these as a module and call this from a main file// FlowRouter.route("/", {// name: "ei.list",// action() {// mount(MainLayoutCtx, {// content: () => (<EiList />)// });// }// });}# Module index template- name: moduleshow: truecreate: truetext: |import actions from "./actions";import routes from "./routes";export default {actions,routes};# Server publication template- name: server/publicationstext: |import {Meteor} from 'meteor/meteor';import {check} from 'meteor/check';export default function () {Meteor.publish("$1", function () {const selector = {};const options = {// fields: {_id: 1, title: 1},// sort: {createdAt: -1},// limit: 10};return $2.find(selector, options);});}placeholders:- Publication Name- Collectionactions:- type: replacepath: index.tswhat: export default function () {replace: |import $name from "./$name";export default function () {- type: replacepath: index.tswhat: export default function () {replace: |export default function () {$name();# Method template- name: server/methodstext: |import {Meteor} from 'meteor/meteor';import {check} from 'meteor/check';export default function () {Meteor.methods({'$1'($2) {check($2, String);}});}placeholders:- Method Name- Parametersactions:- type: replacepath: index.tswhat: export default function () {replace: >import $name from "./$name";export default function () {- type: replacepath: index.tswhat: export default function () {replace: >export default function () {$name();- name: servercreate: trueshow: truetext: |import publications from "./publications/index";import methods from "./methods/index";// import addInitialData from "./configs/initial_adds";publications();methods();// addInitialData();- name: publicationIndexcreate: truetext: |export default function () {}- name: methodIndexcreate: truetext: |export default function () {}# context template- name: contextcreate: truetext: |import * as Collections from "../../lib/collections";import {Meteor} from 'meteor/meteor';import {FlowRouter} from 'meteor/kadira:flow-router';import {ReactiveDict} from 'meteor/reactive-dict';import {Tracker} from 'meteor/tracker';export default function () {return {Meteor,FlowRouter,Collections,LocalState: new ReactiveDict(),};}# client index template- name: clientcreate: trueshow: truetext: |import "./configs/config";import {createApp} from 'mantra-core';import coreModule from "./modules/core/index";import initContext from "./configs/context";// init contextconst context = initContext();// create appconst app = createApp(context);app.loadModule(coreModule);app.init();actions:- type: replacepath: ../index.tswhat: import {createApp} from 'mantra-core';replace: |import {createApp} from 'mantra-core';import $nameModule from "./modules/$name";- type: replacepath: ../index.tswhat: app.init();replace: |app.loadModule($nameModule);app.init()
Good catch. Let us know what about this package looks wrong to you, and we'll investigate right away.