Skip to content

Commit 291ba12

Browse files
committed
added frontend setup
1 parent cbc6ae1 commit 291ba12

35 files changed

+929
-0
lines changed

gulpfile.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2013, Divio AG
3+
* Licensed under BSD
4+
* http://github.com/divio/djangocms-boilerplate-webpack
5+
*/
6+
7+
// INFO:
8+
// - The minimatch/graceful-fs warnings are from gulp, needs upgrade to 4.0 once released.
9+
10+
// #############################################################################
11+
// IMPORTS
12+
const argv = require('minimist')(process.argv.slice(2));
13+
const gulp = require('gulp');
14+
15+
// #############################################################################
16+
// SETTINGS
17+
const PROJECT_ROOT = __dirname;
18+
const PROJECT_STATIC = '/djangocms_bootstrap4/static/djangocms_bootstrap4/'
19+
const PROJECT_PATH = {
20+
css: PROJECT_ROOT + PROJECT_STATIC + '/css',
21+
js: PROJECT_ROOT + PROJECT_STATIC + '/js',
22+
sprites: PROJECT_ROOT + PROJECT_STATIC + '/sprites',
23+
sass: PROJECT_ROOT + '/private/sass',
24+
webpack: PROJECT_ROOT + '/private/js',
25+
svg: PROJECT_ROOT + '/private/svg',
26+
};
27+
const PROJECT_PATTERNS = {
28+
css: [
29+
PROJECT_PATH.css + '/*base*.css',
30+
],
31+
js: [
32+
'*.js',
33+
'./tools/tasks/**/*.js',
34+
PROJECT_PATH.webpack + '*.config.js',
35+
PROJECT_PATH.webpack + '/**/*.js',
36+
'!' + PROJECT_PATH.webpack + '/*.min.js',
37+
'!' + PROJECT_PATH.webpack + '/**/*.min.js',
38+
],
39+
sass: [
40+
PROJECT_PATH.sass + '/**/*.{scss,sass}',
41+
'!' + PROJECT_PATH.sass + '/libs/_svgsprite.scss',
42+
],
43+
svg: {
44+
icons: [PROJECT_PATH.svg + '/**/*.svg'],
45+
},
46+
};
47+
48+
/**
49+
* Generic utility to import gulp tasks and pass options to them
50+
*
51+
* @param {String} id - task name
52+
* @param {Object} [extra] - optional options to pass
53+
* @returns {Function} - task definition
54+
*/
55+
function task(id, extra) {
56+
return require('./tools/tasks/' + id)(
57+
gulp,
58+
Object.assign(
59+
{
60+
PROJECT_ROOT: PROJECT_ROOT,
61+
PROJECT_PATH: PROJECT_PATH,
62+
PROJECT_PATTERNS: PROJECT_PATTERNS,
63+
argv: argv,
64+
},
65+
extra
66+
)
67+
);
68+
}
69+
70+
71+
// #############################################################################
72+
// TASKS
73+
gulp.task('sass', task('sass'));
74+
gulp.task('webpack', task('webpack', { watch: true }));
75+
gulp.task('lint', task('lint'));
76+
gulp.task('icons', task('svg', { svg: 'icons' }));
77+
78+
gulp.task('default', ['sass', 'webpack', 'watch']);
79+
80+
gulp.task('watch', function () {
81+
gulp.start('webpack');
82+
gulp.watch(PROJECT_PATTERNS.sass, ['sass']);
83+
gulp.watch(PROJECT_PATTERNS.js, ['lint']);
84+
});

private/js/.babelrc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"presets": [
3+
["env", {
4+
"modules": false
5+
}]
6+
],
7+
"plugins": ["transform-runtime"],
8+
"env": {
9+
"production": {
10+
"plugins": [
11+
"lodash"
12+
]
13+
}
14+
}
15+
}

private/js/base.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright (c) 2013, Divio AG
3+
* Licensed under BSD
4+
* http://github.com/divio/djangocms-boilerplate-webpack
5+
*/
6+
7+
// import 'bootstrap/js/dist/alert'

private/js/components/button-group.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { iconTemplate } from 'components/templates'
2+
3+
/**
4+
* @class ButtonGroup
5+
* @public
6+
*/
7+
export default class ButtonGroup {
8+
/**
9+
* @method constructor
10+
* @param {Object} options
11+
* @param {String} options.select
12+
* @param {String} options.static
13+
* @param {String[]} [options.icons]
14+
*/
15+
constructor(options) {
16+
this.options = options;
17+
this.templates = {
18+
wrapper: (cls = '', buttons = '') => `
19+
<div class="bootstrap4-button-group${cls}">
20+
<div class="btn-group" role="group" aria-label="">
21+
${buttons}
22+
</div>
23+
</div>`,
24+
button: (icon = '', text = '') => `
25+
<button type="button" class="btn" title="${text}">
26+
${icon}<span class="sr-only">${text}</span>
27+
</button>`,
28+
};
29+
this.select = $(this.options.select);
30+
this.selectOptions = this.select.find('option');
31+
32+
// initialize
33+
this.select.after(
34+
this.setEvents($(this.getTemplate()))
35+
);
36+
}
37+
38+
/**
39+
* @method setEvents
40+
* @param {jQuery} template
41+
* @return {jQuery} template
42+
*/
43+
setEvents(template) {
44+
let buttons = template.find('button');
45+
let select = this.select;
46+
let options = this.select.find('option');
47+
let index = options.index(options.filter(':selected'));
48+
49+
buttons.on('click', function (event) {
50+
event.preventDefault();
51+
// set the value on the select
52+
select.find('option')
53+
.prop('selected', false)
54+
.eq(buttons.index(this))
55+
.prop('selected', true);
56+
// set icon color
57+
buttons.find('.icon').removeClass('icon-white');
58+
$(this).find('.icon').addClass('icon-white');
59+
// set active state of the button
60+
buttons.removeClass('btn-primary');
61+
$(this).addClass('btn-primary');
62+
});
63+
64+
// set initial active item
65+
buttons.eq(index).trigger('click');
66+
67+
return template;
68+
}
69+
70+
/**
71+
* @method getTemplate
72+
* @return {String} template
73+
*/
74+
getTemplate() {
75+
let cls = '';
76+
77+
this.select.addClass('hidden');
78+
79+
if (this.options.icons &&
80+
this.options.icons.length !== this.selectOptions.length) {
81+
throw new Error('Provided icons do not match options.');
82+
} else if (this.options.icons) {
83+
cls = ' bootstrap4-button-group-icons';
84+
}
85+
86+
const buttons = this.selectOptions.toArray().reduce((btns, selectOption, index) => {
87+
let text = $(selectOption).text();
88+
let icon;
89+
90+
// prepare icon
91+
if (this.options.icons) {
92+
icon = iconTemplate(
93+
this.options.icons[index],
94+
this.options.static,
95+
$(selectOption).text(),
96+
);
97+
} else {
98+
icon = text;
99+
}
100+
// add button
101+
btns += this.templates.button(icon, text);
102+
103+
return btns;
104+
}, '');
105+
106+
return this.templates.wrapper(cls, buttons);
107+
}
108+
109+
}

private/js/components/grid-layout.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @class GridLayout
3+
* @public
4+
*/
5+
export default class GridLayout {
6+
/**
7+
* @method constructor
8+
* @param {Object} options
9+
* @param {Array} options.sizes
10+
* @param {Array} options.row
11+
* @param {String} options.reset
12+
* @param {String} options.static
13+
*/
14+
constructor(options) {
15+
this.options = options;
16+
17+
this.setHeader();
18+
this.setColumn();
19+
this.setReset();
20+
}
21+
22+
/**
23+
* @method setHeader
24+
*/
25+
setHeader() {
26+
let container = $('.form-row.field-xs_col .field-box');
27+
let sizes = ['size-xs', 'size-sm', 'size-md', 'size-lg', 'size-xl'];
28+
let wrapper = (wrapper) => `<div class="icon-thead">${wrapper}</div>`;
29+
let icons = (icon, title = '', staticPath = this.options.static) => `
30+
<span class="icon icon-${icon}" title="${title}">
31+
<svg role="presentation">
32+
<use xlink:href="${staticPath}djangocms_bootstrap4/sprites/icons.svg#${icon}"></use>
33+
</svg>
34+
</span>
35+
<span class="icon-title">${title}</span>`;
36+
let tmp = '';
37+
38+
sizes.forEach(function (item, index) {
39+
tmp = icons(item, this.options.sizes[index]);
40+
41+
container.eq(index).prepend(
42+
wrapper(tmp)
43+
);
44+
}, this);
45+
}
46+
47+
/**
48+
* @method setColumn
49+
*/
50+
setColumn() {
51+
let container = $(`
52+
.form-row.field-xs_col,
53+
.form-row.field-xs_order,
54+
.form-row.field-xs_ml,
55+
.form-row.field-xs_mr
56+
`);
57+
let template = (text = '', link = '#', staticPath = this.options.static) => `
58+
<div class="field-box field-box-label">
59+
<a href="${link}" target="_blank" class="d-inline-block text-right">
60+
${text}
61+
<span class="icon icon-info icon-primary">
62+
<svg role="presentation">
63+
<use xlink:href="${staticPath}djangocms_bootstrap4/sprites/icons.svg#info"></use>
64+
</svg>
65+
</span>
66+
</a>
67+
</div>
68+
`;
69+
let links = [
70+
'https://getbootstrap.com/docs/4.0/layout/grid/#grid-options',
71+
'https://getbootstrap.com/docs/4.0/layout/grid/#reordering',
72+
'https://getbootstrap.com/docs/4.0/layout/grid/#offsetting-columns',
73+
'https://getbootstrap.com/docs/4.0/layout/grid/#offsetting-columns',
74+
];
75+
76+
container.toArray().forEach(function (item, index) {
77+
$(item).prepend(template(this.options.rows[index], links[index]));
78+
}, this);
79+
}
80+
81+
/**
82+
* @method setReset
83+
*/
84+
setReset() {
85+
let container = $('.form-row.field-xs_col');
86+
let wrapper = container.closest('fieldset');
87+
let template = (text = this.options.reset) => `
88+
<a href="#" class="btn grid-reset">${text}</a>
89+
`;
90+
let button = $(template());
91+
92+
button.on('click', function (event) {
93+
event.preventDefault();
94+
wrapper.find('input').val('');
95+
wrapper.find('input[type="checkbox"]').prop('checked', false);
96+
});
97+
98+
container.append(button);
99+
}
100+
101+
}

private/js/components/templates.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Templates
3+
*/
4+
export const iconTemplate = (icon, staticPath = '/static/', title = '') => `
5+
<span class="icon icon-${icon}" title="${title}">
6+
<svg role="presentation">
7+
<use xlink:href="${staticPath}djangocms_bootstrap4/sprites/icons.svg#${icon}"></use>
8+
</svg>
9+
</span>`;

private/js/grid.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2013, Divio AG
3+
* Licensed under BSD
4+
* http://github.com/divio/djangocms-boilerplate-webpack
5+
*/
6+
7+
// import 'bootstrap/js/dist/alert'
8+
import ButtonGroup from 'components/button-group';
9+
import GridLayout from 'components/grid-layout'
10+
import { iconTemplate } from 'components/templates'
11+
12+
13+
$(() => {
14+
// Row plugin
15+
if ($('.djangocms-bootstrap4-row').length) {
16+
let static_url = $('.djangocms-bootstrap4-row').data().static;
17+
18+
// Bootstrap 4 Grid Row - Vertical Alignment
19+
new ButtonGroup({
20+
static: static_url,
21+
select: '#id_vertical_alignment',
22+
icons: ['align-reset', 'flex-align-start', 'flex-align-center', 'flex-align-end'],
23+
});
24+
// Bootstrap 4 Grid Row - Horizontal Alignment
25+
new ButtonGroup({
26+
static: static_url,
27+
select: '#id_horizontal_alignment',
28+
icons: ['align-reset', 'flex-content-start', 'flex-content-center', 'flex-content-end',
29+
'flex-content-around', 'flex-content-between'],
30+
});
31+
32+
$('.form-row.field-create > div').before(
33+
iconTemplate('columns', static_url)
34+
);
35+
}
36+
37+
// Column plugin
38+
let column = $('.djangocms-bootstrap4-column');
39+
if (column.length) {
40+
let static_url = $('.djangocms-bootstrap4-column').data().static;
41+
42+
// Bootstrap 4 Grid Column - Alignment
43+
new ButtonGroup({
44+
select: '#id_column_alignment',
45+
icons: ['align-reset', 'flex-self-start', 'flex-self-center', 'flex-self-end'],
46+
static: static_url,
47+
});
48+
// Bootstrap 4 Grid Column - Reponsive Settings
49+
new GridLayout({
50+
sizes: column.data().sizes,
51+
rows: column.data().rows,
52+
reset: column.data().reset,
53+
static: static_url,
54+
});
55+
}
56+
});

0 commit comments

Comments
 (0)