Skip to content

Commit

Permalink
Merged branch master into issue_33
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaslabbe committed Feb 1, 2017
2 parents 6d597f4 + 460688c commit 9a88a6e
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 14 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,16 @@

## [2.15.0] - 2017-1-31
* [[`0f4acd56b1`](https://github.com/abecms/abecms/commit/0f4acd56b1)] - **enhancement**: New HBS Helper eachGroup. This helper divide a json array of objects into groups of objects. Useful to create a set of different layouts to display the list of json objects (gregorybesson)
* [[`a36ba3fed1`](https://github.com/abecms/abecms/commit/a36ba3fed1)] - **enhancement**: It's now possible to import the same partial (containing Abe tags with keys) several times. (we update the keys id dynamically) (gregorybesson)
* [[`155df3760e`](https://github.com/abecms/abecms/commit/155df3760e)] - Update README.md (Greg Besson)
* [[`9531436f5c`](https://github.com/abecms/abecms/commit/9531436f5c)] - Merge pull request #125 from nicolaslabbe/issue_124 (Greg Besson)
* [[`e7e34de8bb`](https://github.com/abecms/abecms/commit/e7e34de8bb)] - **fix**: update code for nodemailer 2.x (nicolaslabbe)
* [[`68b5321841`](https://github.com/abecms/abecms/commit/68b5321841)] - **fix**: update code for nodemailer 2.x (nicolaslabbe)
* [[`b5f172f48c`](https://github.com/abecms/abecms/commit/b5f172f48c)] - **qa**: removing console.logs... (gregorybesson)
* [[`8c6a973c37`](https://github.com/abecms/abecms/commit/8c6a973c37)] - **qa**: updating dev dependency (gregorybesson)
* [[`01d1a4ed1d`](https://github.com/abecms/abecms/commit/01d1a4ed1d)] - **fix**: updating fields where precontrib='' (gregorybesson)
* [[`47598359c7`](https://github.com/abecms/abecms/commit/47598359c7)] - **qa**: update handlebars-helpers version (gregorybesson)
* [[`093af59abd`](https://github.com/abecms/abecms/commit/093af59abd)] - **doc**: CHANGELOG (gregorybesson)
* [[`6e372c4e3e`](https://github.com/abecms/abecms/commit/6e372c4e3e)] - Merge branch 'master' of https://github.com/abecms/abecms (gregorybesson)
* [[`5f010c1ca4`](https://github.com/abecms/abecms/commit/5f010c1ca4)] - **qa**: Updating dependencies versions (gregorybesson)
* [[`78a4038780`](https://github.com/abecms/abecms/commit/78a4038780)] - Update README.md (Greg Besson)
Expand Down
20 changes: 18 additions & 2 deletions README.md
Expand Up @@ -36,11 +36,9 @@ The documentation will be rewritten and included in the modules
As a major new feature, it will be possible to create a template from partials.

## Roadmap of the next 2.x releases
- the stateful manager of Abe has to become responsible of pagination of articles (huge performance boost)
- A homepage will arrive (at last !) on the frontend
- It will be possible to create filtered views on the manager frontend
- Refactoring the editor has to be done
- The load testing scenarii will be open sourced (based on Locust)
- Precompiling of templates has to be fully tested
- since Abe has become stateful, clustering has been removed. Implement a solution to permit clusters of Abe
- Add template creation from partials
Expand All @@ -57,6 +55,24 @@ As a major new feature, it will be possible to create a template from partials.
## Changelog
See the complete [changelog](./CHANGELOG.md)

### 2.15.*
- The order by statement in abe type="data" is now fully usable on any property of the json post. usage of order by date ASC is deprecated. Please use order by abe_meta.date ASC instead. And you can now limit a set of record without having to use the 'where' statement
- abe type="import" are not usable in a {{#each}} statement for technical reasons. But you can reproduce this behavior by using the array notation in an import. ie. {{abe type="import" file="myPartial/{{list[].id}}"}} This is particularly useful when you propose a contributor to select several partials in a list (with the {{#each}} notation + type="data). You can then display these selected partials with this iarray style notation.

### 2.14.*
- Abe type="data" are now usable in {{#each x}} statements. This was a long awaited feature.

### 2.13.*
- The manager has been fully ajaxified ; A dedicated REST route is available making the performance on frontend much more performant. the stateful manager of Abe has become responsible of pagination of articles (huge performance boost)
- New core features for the array class (facet + nested sort)

### 2.12.*
- 150 handlebars helpers are now available for template designers
- The engine now detects abe tags with more accuracy and more performance
- The abe type="file" is available (your users will be able to upload files
- The "hint" attribute (which produces a comment under the fields in the editor) are now part of the core
- The load testing scenarii have been open sourced (based on Locust)

### 2.11.*
- Abe type="import": Can now include variables
- Abe admin: Role Workflow management has been improved
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "abecms",
"version": "2.14.7",
"version": "2.15.0",
"description": "Abe: The lightning fast CMS",
"main": "src/server/app.js",
"repository": {
Expand Down
91 changes: 91 additions & 0 deletions src/cli/cms/templates/handlebars/eachGroup.js
@@ -0,0 +1,91 @@
import extend from 'extend'

/**
* This helper divide an array into groups of objects and repeat the structure
* Usage :
*
*{{#eachgroup products '[{"group":"my","qty":"1"},{"group":"ty","qty":"3"}]'}}
* {{my.0.title}} <img src="{{my.0.cover_273x273}}" width="40"><br/>
* {{ty.0.title}} <img src="{{ty.0.cover_273x273}}" width="40"><br/>
* {{ty.1.title}} <img src="{{ty.1.cover_273x273}}" width="40"><br/>
* {{ty.2.title}} <img src="{{ty.2.cover_273x273}}" width="40"><br/>
*{{/eachgroup}}
*
* @param {[type]} context The array to parse
* @param {[type]} id the groups of groups and qty
* @param {[type]} options
* @return {[type]} html
*/
export default function eachGroup(context, groups, options) {
var fn = options.fn, inverse = options.inverse;
var ret = ''
var group = []
function getLeaf(node) {
if (node.group && node.qty) {
return node
} else {
try{
return getLeaf(node[Object.keys(node)[0]]);
} catch (e){
return null
}
}
}

if(typeof groups !== 'undefined'){
if(typeof groups === 'string'){
groups = JSON.parse(groups)
}
if(context && context.length > 0) {
for(var i=0, newCount=0, j=context.length, distribIndex=0, k=0, iteration=0; i<j; i++,newCount++) {
var o = getLeaf(groups[Object.keys(groups)[distribIndex]])
if(o == null) break
var first = newCount % o['qty'] === 0;

// Adding index, isFirst, isLast, isNewGroup to each record
context[i] = extend(true, {
index: i,
isFirst: first,
isNewGroup: first && newCount > 0,
isLast: i === context.length - 1
}, context[i])

if(first){
if(newCount > 0){
// if the last group has been reached, I reinit the distribIndex
// and iterate on the result array
if(distribIndex === Object.keys(groups).length - 1) {
distribIndex = 0
var ar = []
} else {
distribIndex++
}
iteration++
newCount = 0
k++
}

o = getLeaf(groups[Object.keys(groups)[distribIndex]])
var key = o['group']
if(group[iteration] == null)
group.push([])
if(group[iteration][key] == null){
group[iteration][key] = []
}
}
group[iteration][key].push(context[i])
}
context = group
}

if(context) {
for(var i=0, j=context.length, k=0; i<j; i++) {
ret += fn(context[i]);
}
} else {
ret = inverse(this);
}
}

return ret;
}
3 changes: 3 additions & 0 deletions src/cli/cms/templates/index.js
Expand Up @@ -10,6 +10,7 @@ import cleanTab from './handlebars/cleanTab'
import ifCond from './handlebars/ifCond'
import ifIn from './handlebars/ifIn'
import isTrue from './handlebars/isTrue'
import eachGroup from './handlebars/eachGroup'
import math from './handlebars/math'
import moduloIf from './handlebars/moduloIf'
import notEmpty from './handlebars/notEmpty'
Expand Down Expand Up @@ -40,6 +41,7 @@ Handlebars.registerHelper('slugify', handlebarsHelperSlugify({Handlebars: Hand
Handlebars.registerHelper('ifCond', ifCond)
Handlebars.registerHelper('ifIn', ifIn)
Handlebars.registerHelper('isTrue', isTrue)
Handlebars.registerHelper('eachGroup', eachGroup)
Handlebars.registerHelper('math', math)
Handlebars.registerHelper('moduloIf', moduloIf)
Handlebars.registerHelper('notEmpty', notEmpty)
Expand Down Expand Up @@ -69,6 +71,7 @@ export {
ifCond,
ifIn,
isTrue,
eachGroup,
truncate,
lowercase,
uppercase,
Expand Down
39 changes: 36 additions & 3 deletions src/cli/cms/templates/template.js
Expand Up @@ -70,6 +70,7 @@ export function getAbeImport(text) {
*/
export function includePartials(text, json) {
var abeImports = cmsTemplates.template.getAbeImport(text)
var duplicateImports = duplicateImports || []

Array.prototype.forEach.call(abeImports, (abeImport) => {
var obj = cmsData.attributes.getAll(abeImport, {})
Expand All @@ -82,15 +83,47 @@ export function includePartials(text, json) {
if(Object.prototype.toString.call(file) === '[object Array]' ) {
Array.prototype.forEach.call(file, (f) => {
if(coreUtils.file.exist(f)) {
partial += cmsTemplates.template.includePartials(fse.readFileSync(f, 'utf8'), json)
if(duplicateImports[f] != null){
var tmpFile = fse.readFileSync(f, 'utf8')
var regAbe = /{{abe .*key=[\'|\"](.*?)[\'|\"].*}}/g
var matches = tmpFile.match(regAbe)
var match
while ((match = regAbe.exec(tmpFile)) !== null) {
if (match[1] != null) {
tmpFile = tmpFile.replace(match[0], match[0].replace(match[1], match[1] + '_' + duplicateImports[f]))
tmpFile = tmpFile.replace(new RegExp(`\{\{${match[1]}`, 'g'), '{{' + match[1] + '_' + duplicateImports[f])
}
}
duplicateImports[f] += 1
partial += cmsTemplates.template.includePartials(tmpFile, json)
} else{
duplicateImports[f] = 1
partial += cmsTemplates.template.includePartials(fse.readFileSync(f, 'utf8'), json)
}
}
})
} else {
if(coreUtils.file.exist(file)) {
partial = cmsTemplates.template.includePartials(fse.readFileSync(file, 'utf8'), json)
if(duplicateImports[file] != null){
var tmpFile = fse.readFileSync(file, 'utf8')
var regAbe = /{{abe .*key=[\'|\"](.*?)[\'|\"].*}}/g
var match
while ((match = regAbe.exec(tmpFile)) !== null) {
if (match[1] != null) {
tmpFile = tmpFile.replace(match[0], match[0].replace(match[1], match[1] + '_' + duplicateImports[file]))
tmpFile = tmpFile.replace(new RegExp(`\{\{${match[1]}`, 'g'), '{{' + match[1] + '_' + duplicateImports[file])
}
}

duplicateImports[file] += 1
partial = cmsTemplates.template.includePartials(tmpFile, json)
} else {
duplicateImports[file] = 1
partial = cmsTemplates.template.includePartials(fse.readFileSync(file, 'utf8'), json)
}
}
}
text = text.replace(cmsData.regex.escapeTextToRegex(abeImport, 'g'), partial)
text = text.replace(cmsData.regex.escapeTextToRegex(abeImport), partial)
})

return text
Expand Down
10 changes: 6 additions & 4 deletions src/server/routes/users/get/forgot.js
Expand Up @@ -53,7 +53,7 @@ var route = function route(req, res) {

var requestedUrl = req.protocol + '://' + req.get('Host') + '/abe/users/reset?token=' + resetPasswordToken

var smtp = config.smtp
var smtp = config.users.smtp
var emailConf = config.users.email
html = emailConf.html || ''

Expand All @@ -77,7 +77,10 @@ var route = function route(req, res) {
})

if(typeof smtp === 'undefined' || smtp === null) {
var transport = nodemailer.createTransport('direct', {})
var transport = nodemailer.createTransport({
name: 'localhost',
direct: true
})
transport.sendMail({
from: emailConf.from, // sender address
to: user.email, // list of receivers
Expand All @@ -89,7 +92,7 @@ var route = function route(req, res) {
showHtml(res, req, 'Check your inbox')
}else if(typeof smtp !== 'string') {
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport('SMTP', smtp)
var transporter = nodemailer.createTransport(smtp)

// setup e-mail data with unicode symbols
var mailOptions = {
Expand All @@ -107,7 +110,6 @@ var route = function route(req, res) {
}

showHtml(res, req, 'Check your inbox')
console.log('Message sent: ' + info.response)
})
}
})
Expand Down
2 changes: 1 addition & 1 deletion src/server/views/users/forgot.html
Expand Up @@ -11,7 +11,7 @@
<div class="panel panel-default panel-login">
<div class="panel-body">
{{#if info}}
<span class="text-danger">{{info}}</span>
<span class="text-danger">{{@root.info}}</span>
<br /><br />
<a href="/abe/users/login">Login</a>
{{else}}
Expand Down
2 changes: 1 addition & 1 deletion src/server/views/users/login.html
Expand Up @@ -11,7 +11,7 @@
<div class="panel panel-default panel-login">
<div class="panel-body">
{{#if info}}
<span class="text-danger">{{info}}</span>
<span class="text-danger">{{@root.info}}</span>
<br /><br />
{{/if}}
<form action="/abe/users/login" method="post">
Expand Down
4 changes: 2 additions & 2 deletions src/server/views/users/reset.html
Expand Up @@ -12,7 +12,7 @@
<div class="panel panel-default panel-login">
<div class="panel-body">
{{#if info}}
<span class="text-danger">{{info}}</span>
<span class="text-danger">{{@root.info}}</span>
<br /><br />
{{/if}}
<form action="/abe/users/reset" method="post">
Expand All @@ -25,7 +25,7 @@
<label for="repeat-password">Repeat password</label>
<input type="password" class="form-control" name="repeat-password" placeholder="">
</div>
<input type="hidden" class="form-control" name="token" value="{{token}}">
<input type="hidden" class="form-control" name="token" value="{{@root.token}}">
<button type="submit" class="btn btn-default">Submit</button>
</form>

Expand Down

0 comments on commit 9a88a6e

Please sign in to comment.