Giter Club home page Giter Club logo

cannercms's Introduction

CannerCMS has pivoted to CannerData - The Data Access Layer for Analytics Data Applications.

Canner now provides solution designs for data teams so that data owners, stewards, and consumers can easily collaborate in one interface. It is an ease-of-use, scalable, secure platform for querying and analyzing information across multiple databases, file systems, and other storage formats. Unlike current solutions that data is often manually integrated and transferred across different tools and sources, resulting in time-consuming and error-prone processes.

cannercms's People

Contributors

abz53378 avatar chihsuan avatar chilijung avatar frankyang0529 avatar fredalai avatar gkdoc avatar jinksi avatar wwwy3y3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cannercms's Issues

add authProvider

Overview

We should create AuthProvider component to render login page and deal with the authentication.

Goals

  • check identity
  • render login page
  • pass renderMenu to CMSWrapper (children) .

Proposed Solution

usage

<AuthProvider>
    <CMSWrapper>
        <CMS />
    </CMSWrapper>
</AuthProvider>

current login page
current identity check

Error message improvement

screen shot 2018-07-24 at 11 05 35 am

Now if CMS component is crashing, it will only display a really rough message to users, and crashing the whole CMS.

Errors should catch in CMS component level, we should use componentDidCatch to catch errors from every children component and display errors for within each component

Duplicated keys cause the incorrect data

Problem

The schema below causes Apollo return incorrect data when I use canner script:serve.

Schema

<object keyName="sameKey">
  <object keyName="diffKey">
    <string keyName="sameKey">
  </object>
</object>

Expected
the second sameKey should be a string

{
  "data": {
    "sameKey": {
      "__typename": "SameKeyPayload",
      "diffKey": {
        "__typename": null,
        "sameKey": ""
      }
    }
  }
}

actual

{
  "data": {
    "sameKey": {
      "__typename": "SameKeyPayload",
      "diffKey": {
        "__typename": null,
        "sameKey": {
          "diffKey": {
            "sameKey": "",
            "__typename": null
          },
          "__typename": "sameKey"
        }
      }
    }
  }
}

i18n support on title and description

Proposed Solution

Developers can pass a property dict which stores different languages of title and description
Then in the schema, title and description will be a string with a specific prefix to let canner know this string can be parsed to a key of dict, for examples:

// canner.schema.js
import dict form './dict.js';
<root dict={dict} />
  <object keyName="home" title="${home}">
    <string keyName="info" title="${home.info}" />
  </object> 
</root>
  
// dict.js
export default {
  zh: {
    home: '首頁',
    home.info: '資訊'
  },
  en: {
    home: 'Home Page',
    home.info: 'Information'
  }
}

Field have to be able to add defaultValue from props

Current mechanism directly shows value from source and update value to the source. But sometimes it's not enough.

But in some cases, we might need to insert a defaultValue from Canner schema.

let's say, we need a form to create a product, and the productId should generate while I click the add button and also it should be disabled so users is not allow to change it. So in order to do that I'll add a schema as below.

<string
  keyName="productId"
  disabled
  defaultValue={() => shortId.generate()...}/> // I could use shortId or timestamp to generate a immutable defaultValue.

Better route controller

In the current solution, the framework control the routes of CMS.

For array type component, users can navigate to:

  • /posts: display content of all posts
  • /posts/:id: display one entity of posts
  • /posts?op=create: form to create a new post
  • /posts?op=create&payload=<JSON>: form to create a new post and come with default payload

For object type:

  • /home/header: access header object of home
  • /home/header/title: access home.header.title
  • /home/navs: access navs (array field) of home

For possible customization of route components, we should think of a better architecture of route controller.

Validation feature

Validating fields is really important.
In Prisma (GraphQL) the data is strictly defined in DSL. Such as name must be a string String!, many fields must have values. This will cause errors in database and graphQL and crashing the graphQL server.

I think we should add validation feature in Canner soon.

Error canner init:schema

~/projects/test$ canner init:schema

Error

module.js:549
    throw err;
    ^

Error: Cannot find module 'lodash.mapValues'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/@canner/cli/lib/data.js:15:19)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/@canner/cli/lib/index.js:6:9)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)

Add new tags for dashboard, chart, overview.

Overview

We will support few tags for overview, chart, dashboard features:

  • <page>
  • <chart> tags
    • <chart ui="line">
    • <chart ui="pie">
    • <chart ui="scatter">
    • <chart ui="bar">
  • <display> tags
  • layout tags
    • <Row>
    • <Col>

Usage

export default (
  <root>
    <page keyName="overview"> {/* keyName of page will be used as the route */}
      <Row>
        <Col>
          <display ui="amount" graphql={``} />
        </Col>
        <Col>
          <display ui="list" graphql={``} />
        </Col>
      </Row>
      <Col><chart ui="bar" uiParams={vegaConfig} graphql={``}/></Col>
    </page>
  </root>
);

Implementation

For now, canner-script actually generate an object contains several required information for canner:
source

{
  schema: CannerSchema,
  visitors: Array<Object>,
  connectors: {[string]: any},
  resolvers: {[string]: any},
  graphqlClient: any,
  storages: {[key: string]: any}
};

To implement these tags, we can just add a pageSchema key in the object, and its value is a JSON object, same as CannerSchema.

{
    pageSchema: PageSchema
    schema: CannerSchema,
    visitors: Array<Object>,
    connectors: {[string]: any},
    resolvers: {[string]: any},
    graphqlClient: any,
    storages: {[key: string]: any}
};

The example of pageSchema:

pageSchema: {
    keyName: 'overview',
    type: 'page',
    items: {
        KEY2: {
            type: 'display',
            ui: 'amount',
            keyName: 'KEY2'
        },
        KEY3: {
            type: 'display',
            ui: 'amount',
            keyName: 'KEY3'
        },
        KEY4: {
            type: 'chart',
            ui: 'bar',
            keyName: 'KEY4'
        }
    }
}

Notes

  • The keyName of <page /> is required because canner will take it as the route of this page.
  • If there is no keyName passing to <display /> and <chart />, we should randomly generate one for it.

Discussion

  1. Any better names of new tags?
  2. Any different design of tags?

Add cache property to indicate regeneration of cacheTree when receive new schema

In the current solution, when schema is passed to canner, it will be processed to componentTree and not going to regenerate if canner recieve new schema. It's a best for performance, but under some situations, for example live demo, we'll want canner to regenerate the componentTree.

Thus, IMO, we should add a cache property to decide whether to cache the componentTree or not.

override css in CMSWrapper

Overview

<CMSWrapper /> should have an API to let developers override our CMS style easily

Possible Solution

  • css string
<CMSWrapper
  style={`
      .antd-menu-item: {
         background: #333;
      }     
  `}
>
</CMSWrapper>

sidebar/navbar in CMSWrapper

See #39 if you have no idea what's CMSWrapper.

Overview

We can pass sidebarConfig and navbarConfig to <CMSWrapper /> to render sidebar and navbar easily.

<CMSWrapper
  sidebarConfig={SidebarConfig}
  navbarConfig={NavbarConfig}
  schema={schema}
>
  <CMS />
</CMSWrapper>

1

Details

There should be two components <Sidebar /> and <Navbar />, and then <CMSWrapper /> can just pass their config to them like below.

render() {
  const {sidebarConfig, navbarConfig, children} = this.props;
  return (<Layout>
    {...}
    <Navbar {...navbarConfig} />
    {...}
    <Sidebar {...sidebarConfig} />
    {...}
  </ Layout>)
}

<Sidebar />

Implement sidebar with antd Sider and Menu

sidebarConfig interface

interface MenuItemConfig = {
  title: string,
  pathname: string,
  params?: {
    operation?: 'create' | 'update',
    defaultPayload?: JSONString,
    filter?: JSONString
  }
}

interface SubmenuConfig = {
  title: string,
  items: Array<MenuItemConfig>
}

interface SidebarConfig = {
  menuConfig: Array<SubmenuConfig | MenuItemConfig>
}

<Sidebar /> will use menuConfig to generate the antd menu. When <MenuItem> is clicked, it should call the goTo method with argument {pathname, params}.

goTo is a method of RouterAdaptor

menuConfig examples

[{
  title: 'Posts',
  pathname: '/posts',
  params: {
    operation: 'create'
  }
  items: [...]
}]

current implement in CMS

render with schema

if sidebarConfig.menuConfig is passed as a true means user wants to render menu with schema, for examples:

import schema from 'canner.schema.js', we will actually get a object like below,

{
  connector: Connector,
  visitors: Vistors,
  schema: DataSchema
}

We can get the data schema and transform it to menu.

console.log(schema.schema);
/*
{
  info: {type: 'object', title: 'My Info', keyName: 'info',...},
  posts: {type: 'array', title: 'Posts', keyName: 'posts',...},
  users: {type: 'array', title: 'Authors', keyName: 'authors',...}
}
*/

const menuConfig = transformSchemaToMenuConfig(schema.schema);
console.log(menuConfig);

/*
[{
  title: 'My Info',
  pathname: '/info'
}, {
  title: 'Posts',
  pathname: '/posts'
}, {
  title: 'Authors',
  pathname: '/authors'
}]
*/

<Navbar />

important with antd Header and Menu

A navbar can be divided to three parts from left to right: logo, menu, save button:
navbar

And there are three properties correspond to the three parts on navbar.
navbarConfig interface

{
  logo: string, // img url
  renderMenu: () => React.Node,
  showSaveButton: boolean
}

ChangedData

Both Sidebar and Navbar should have different behavior when there are unsaved change:

  • when user clicks another menu item, it should pop a confirm modal.
  • the saveButton on navbar should have dot badge.

See current implementation

add CMSWrapper

Overview

Canner is a component that renders the CMS with our canner schema

For examples, the code below will ONLY generate the form, no sidebar, navbar or anything a complete CMS should have.

examples

import {CMS} from 'canner';
import schema from 'canner.schema.js';
// ...
render() {
    return (
      <Router>
        <Route path="/cms" render={({history}) => {
          return (
              <CMS
                history={history}
                baseUrl="/cms"
                schema={schema}
              />
          );
        }}/>
      </Router>
    );

2018-08-01 2 13 22

So, we need a component help developers to generate these components and deal with other logic that Canner shouldn't do.

2018-08-01 2 32 50

Definition:

  • CMSWrapper: should render sidebar, navbar and pass some properties to CMS
  • CMS: should only render the form.

usage

<CMSWrapper
   style={style}  // ref to #42
   sidebarConfig={SidebarConfig} // ref to #41
   navbarConfig={{navbarConfig}} // ref to #41
   routerAdapter={new RouterAdaptor({})} // ref to #40
   >
  <CMS />
</CMSWrapper>

Problem

sidebar props: the missing components sidebar and navbar:

Detail implementation: #41
Our CMS deals with the form of a CMS page, but there are some components we have to render for developers to make the development more easy and quick, such as Sidebar and Navbar.

override style:

Detail implementation: #42

Canner style is based on ant-design. In build stage we set the antd as external in webpack (example) and include the antd.css from CDN in html (example).

In this case, if developers want to override style in open source version, they have to build their own antd.css like the examples below:

And it's impossible for now if they want to override the style in platform version because the bundle.js they deploy to our platform is just the canner schema but not the whole CMS.

routes

Detail implementation: #40

current usage

import {CMS} from 'canner';
import schema from 'canner.schema.js';
// ...
render() {
    return (
      <Router>
        <Route path="/cms" render={({history}) => {
          return (
              <CMS
                history={history}
                baseUrl="/cms"
                schema={schema}
              />
          );
        }}/>
      </Router>
    );

The CMS component use routes, params to decide which components should be rendered, and use goTo method to change the route. For now, we ask developers to pass a history-like object and CMS will get routes, params, goTo from the object. But in most cases, there is no a history object can be passed redirect unless using react-router.

So we need a interface RouterAdaptor to handle different router and CMSWrapper can easily get params, routes, goTo from this interface.

Goals

  • Users can give a sidebar configuration to CMSWrapper to render a sidebar.
  • Users can give a navbar configuration to CMSWrapper to render a navbar.
  • Users can give a style to CMSWrapper to override the style in CMS.
  • Users can give a routerAdaptor to CMSWrapper to parse the routes and params and pass goTo method to CMS

Table could render differently when in create & edit mode

Currently our popup table, no matter it is create or edit it shows with the same CMS UI, this could cause some severe limits, such as a common situation if I have a field called createDate. When user creates it should be editable, and in edit mode it should be disabled.

We have to think of a general interface for these kinds of usage.

types in Canner

  • naming type
    All package name should be ${prefix}-${type}-${name}, and type only can be string, number, boolean, array, object

  • package.json

    type CannerDataType = 'string' | 'boolean' | 'number' | 'array' | 'object' | 'geoPoint' | 'date' | 'file' | 'relation'
    // package.json
    {
      canner: {
        cannerDataType: CannerDataType
      }
    }

Canner script should validate the types above.

proposal: run tests on CI

Currently there is no CI and I think it makes sense to enable Travis CI for testing commits and PR.

Multiple select relationship broken

Now we must put ui="multipleSelect" in the first prop to make multiple select work

<relation
        ui="multipleSelect" // must put in the first prop
        keyName="unSupportShipment"
        uiParams={{
          textCol: "name",
          columns: [
            {
              title: "名稱",
              dataIndex: "name"
            }
          ]
        }}
        relation={{
          type: "toMany",
          to: "shipments"
        }}
        title="不支援的運送方式"
      />

Canner SSR + support Next.js

In the past few days, we were trying to support Canner with Next.js in order to provide SSR in CMS. We encountered a problem that when Next.js builds production code, it also handles how chunks should store. More information from Next.js handle-import.js: https://github.com/zeit/next.js/blob/canary/build/babel/plugins/handle-import.js#L37-L44.

After several days of investigation, here's our solution to accomplish SSR in CMS.

The last issue we need to solve is dynamic import, which Next.js have it's own dynamic import function, and dynamic() in nextjs will transpile through it's own babel plugin ( https://github.com/zeit/next.js/blob/canary/build/babel/plugins/handle-import.js). I've tried to add nextjs's babel plugin to compile it's dynamic() function, which won't work because dynamic import won't work with dynamic variables.

So in order to support it,

  1. We need to transpile our code to https://github.com/zeit/next.js/blob/canary/build/babel/plugins/handle-import.js, while js files are going through canner-schema-loader

  2. Export a variable such as nextLoader that we can use directly in canner/canner, just like how we support dynamic import using React-loadable (we export a variable called copyNode.loader) https://github.com/Canner/canner/blob/master/src/components/Generator.js#L162

  3. Assign component in canner to that variable such as component = copyNode.nextLoader

This implementation will support SSR in Canner using Next.js

Use apolloclient

Fetch Data

In Provider Component

  • Use ApolloProvider
  • change the method query to use client.query
  • add the method updateQuery
  • Use Query to manage all fetch query
// init with schema
const query = new Query({
  schema: schema
});

// update query
query.update('path/to/', 'field', 'value')

// get query value
query.get('path/to/', 'field')

// to gql, return gql query
query.toGql('path')

In HOC

  • Every Component will call fetch in withQuery HOC with the key
  • In array node can have toolbar component to manage the variable

Write Data

In Provider Component

  • Handle the mutates actions like before
  • add actionToMutationQuery()

In HOC

  • generateAction should concern the relation type connect disconnect delete create

Render title & order not correctly

I use schema like this

export default () => (
  <object keyName="orderPage" title="訂單 - 頁面">
    <array keyName="bannerBg" ui="gallery" title="背景輪播圖" />
    <object keyName="hintText" ui="editor" title="提醒文字" />
    <object keyName="thanksText" ui="editor" title="感謝文字" />
  </object>
);

The order & title is not displayed correctly.

screen shot 2018-08-14 at 10 36 29 am

Does not compile on fresh install after setup

paolo:canner-neo4j/ (master*) $ nvm version                                                                                                                                                      [15:53:45]
v8.11.2
paolo:canner-neo4j/ (master*) $ canner init:schema                                                                                                                                               [15:48:55]
  Initializing schema...
? What template do you want to create? Company
? What data source do you want to use? Firebase admin
? '/Users/paolo/DEV/repos/canner-neo4j/cert/firebase' is already existed. Do you want to remove it? Yes
? '/Users/paolo/DEV/repos/canner-neo4j/canner.schema.js' is already existed. Do you want to remove it? Yes
? '/Users/paolo/DEV/repos/canner-neo4j/schema' is already existed. Do you want to remove it? Yes
✔ Initialized

Next Steps:

  - Serve your CMS: canner script:serve

  - Or follow the docs below to connect your data source:
      Firebase Admin: https://www.canner.io/docs/start-quick-firebase.html
      Prisma: https://www.canner.io/docs/start-quick-prisma.html

paolo:canner-neo4j/ (master*) $ canner script:serve                                                                                                                                              [15:49:11]
ℹ Starting CMS server on http://localhost:9090
✖ 「wdm」: Hash: a02b6628f01631b71c0c
Version: webpack 4.16.4
Time: 539ms
Built at: 2018-08-03 15:49:19
         Asset      Size  Chunks             Chunk Names
    index.html  1.17 KiB          [emitted]
main.bundle.js  29.3 KiB    main  [emitted]  main
Entrypoint main = main.bundle.js
[0] multi (webpack)-dev-server/client?http://localhost /var/folders/6c/m2phtvt9277d44jb0bkxtj5h0000gn/T/_cnr-428641MR91DQu8Tmn.js 40 bytes {main} [built]

ERROR in multi (webpack)-dev-server/client?http://localhost /var/folders/6c/m2phtvt9277d44jb0bkxtj5h0000gn/T/_cnr-428641MR91DQu8Tmn.js
Module not found: Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j'
 @ multi (webpack)-dev-server/client?http://localhost /var/folders/6c/m2phtvt9277d44jb0bkxtj5h0000gn/T/_cnr-428641MR91DQu8Tmn.js main[0]

ERROR in multi (webpack)-dev-server/client?http://localhost /var/folders/6c/m2phtvt9277d44jb0bkxtj5h0000gn/T/_cnr-428641MR91DQu8Tmn.js
Module not found: Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j'
 @ multi (webpack)-dev-server/client?http://localhost /var/folders/6c/m2phtvt9277d44jb0bkxtj5h0000gn/T/_cnr-428641MR91DQu8Tmn.js main[1]

ERROR in   Error: Child compilation failed:
  Module not found: Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j':
  Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j'
  Module not found: Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j':
  Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j'

  - compiler.js:79 childCompiler.runAsChild
    [global]/[html-webpack-plugin]/lib/compiler.js:79:16

  - Compiler.js:296 compile
    [global]/[webpack]/lib/Compiler.js:296:11

  - Compiler.js:553 hooks.afterCompile.callAsync.err
    [global]/[webpack]/lib/Compiler.js:553:14


  - Hook.js:35 AsyncSeriesHook.lazyCompileHook [as _callAsync]
    [global]/[tapable]/lib/Hook.js:35:21

  - Compiler.js:550 compilation.seal.err
    [global]/[webpack]/lib/Compiler.js:550:30


  - Hook.js:35 AsyncSeriesHook.lazyCompileHook [as _callAsync]
    [global]/[tapable]/lib/Hook.js:35:21

  - Compilation.js:1284 hooks.optimizeAssets.callAsync.err
    [global]/[webpack]/lib/Compilation.js:1284:35



Child html-webpack-plugin for "index.html":
         Asset      Size  Chunks  Chunk Names
    index.html  1.38 MiB       0
    Entrypoint undefined = index.html
    [../../../.config/yarn/global/node_modules/html-webpack-plugin/lib/loader.js!../../../.config/yarn/global/node_modules/@canner/cli/lib/serve/template.html] /Users/paolo/.config/yarn/global/node_modules/html-webpack-plugin/lib/loader.js!/Users/paolo/.config/yarn/global/node_modules/@canner/cli/lib/serve/template.html 2.01 KiB {0} [built]
    [../../../.config/yarn/global/node_modules/lodash/lodash.js] /Users/paolo/.config/yarn/global/node_modules/lodash/lodash.js 527 KiB {0} [built]

    ERROR in /Users/paolo/.config/yarn/global/node_modules/lodash/lodash.js
    Module not found: Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j'
     @ /Users/paolo/.config/yarn/global/node_modules/lodash/lodash.js 1:0-41
     @ /Users/paolo/.config/yarn/global/node_modules/html-webpack-plugin/lib/loader.js!/Users/paolo/.config/yarn/global/node_modules/@canner/cli/lib/serve/template.html

    ERROR in /Users/paolo/.config/yarn/global/node_modules/lodash/lodash.js
    Module not found: Error: Can't resolve 'babel-loader' in '/Users/paolo/DEV/repos/canner-neo4j'
     @ /Users/paolo/.config/yarn/global/node_modules/lodash/lodash.js 1:0-41
     @ /Users/paolo/.config/yarn/global/node_modules/html-webpack-plugin/lib/loader.js!/Users/paolo/.config/yarn/global/node_modules/@canner/cli/lib/serve/template.html
ℹ 「wdm」: Failed to compile.
ℹ Shutting down CMS server.

Also noticed theres no package.json file created, is this by design?

components, def.js, uiParams problem

  • broken components
- <array keyName="slider" ui="slider" title="Slider">
    <string keyName="children" title="Children" />
   </array>
- <array keyName="tag" ui="tag" title="Tag" />
- <array keyName="gallery" ui="gallery" title="Gallery" />
  • table and table-route default uiParams.columns
  • select, card, radio default uiParams.options
  • map, variants, options def.js
  • map broken but don't know why
  • tabs component should render buttons only at first key
  • table component has expandedRowRender, but don't know why
  • nested table-route should fix

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

canner script:serve error msg

OS: win10

when i command

canner script:serve

it run the error message.

ERROR in C:/Users/Shawn/AppData/Local/Temp/_cnr-9364lk4C3Pztejr6.js
Module not found: Error: Can't resolve 'C:UsersShawnAppDataRoaming
pm
ode_modules@cannerclilibserveapp' in 'C:\Users\Shawn\AppData\Local\Temp'
 @ C:/Users/Shawn/AppData/Local/Temp/_cnr-9364lk4C3Pztejr6.js 15:65-140
 @ multi (webpack)-dev-server/client?http://localhost C:/Users/Shawn/AppData/Local/Temp/_cnr-9364lk4C3Pztejr6.js

ERROR in C:/Users/Shawn/AppData/Local/Temp/_cnr-9364lk4C3Pztejr6.js
Module not found: Error: Can't resolve 'C:UsersShawnDesktopcanner-demo
extjs-ecommerce-with-firebasecanner.schema.js' in 'C:\Users\Shawn\AppData\Local\Temp'
 @ C:/Users/Shawn/AppData/Local/Temp/_cnr-9364lk4C3Pztejr6.js 11:73-161
 @ multi (webpack)-dev-server/client?http://localhost C:/Users/Shawn/AppData/Local/Temp/_cnr-9364lk4C3Pztejr6.js

RouterAdaptor in CMSWrapper

Overview

Use RouterAdaptor to parse routes, params and generate the goTo method to CMS component.

Why

different router implementation

For now, canner ask developers to pass a history object to let CMS get the routes, params and gotTo which are used to deal with the routing in CMS.

For examples:

history = {
  location: {
    pathname: '/posts/postId',
    search: '?operation=create'
  },
  push: string => void
}
// can get value 
{
  routes: ['posts', 'postId'],
  params: {
    operation: 'create'
  },
  goTo: path => push(`${baseUrl}/${path}`);
}

But there is maybe no history object if developers is not using react-router.

So, we need provide a interface RouterAdapter to deal with different router usage.

Goals

  • Users can pass a ReactRouterAdaptor to CMSWrapper to deal with the routing with react-router

Proposed solution

interface

interface RouterAdaptor {
   getRoutes = () => Array<string>
   getParams = () => Object
   goTo = ({pathname: string, params: Object}) => void
}

usage example

//  history from react-router props
//  {
//    location: {
//      pathname: '/posts/postId1',
//      search: '?op=create&payload={"title":"Default title"}'
//    },
//    push: () => ()
// };
const {history} = this.props;
const routerAdaptor = new ReactRouterAdaptor({history});
// in render 
<CMSWrapper routeAdaptor={routeAdaptor}
    <CMS />
</CMSWrapper>
// ...
...

console.log(routerAdaptor.getRoutes()); // ['posts', 'postId1']
console.log(routerAdaptor.getParams()); // {op: 'create', payload: {title: 'Default title"}}
routerAdaptor.goTo({
  pathname: '/';
  params: {}
})

current implement

AWS AppSync

This feature request serves as a central place to discuss development and progress for the support for AWS AppSync. Please contribute in the comments below. I will update the top comment as consensus forms.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.