Skip to content

Commit 95b8cea

Browse files
DEP Upgrade frontend build stack (#88)
1 parent ab0bf06 commit 95b8cea

20 files changed

+6468
-105
lines changed

.editorconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ indent_style = space
1010
insert_final_newline = true
1111
trim_trailing_whitespace = true
1212

13-
[{*.yml,package.json}]
13+
[{*.yml,*.js,*.scss,package.json}]
1414
indent_size = 2
15+
indent_style = space
1516

1617
# The indent size used in the package.json file cannot be changed:
1718
# https://github.com/npm/npm/pull/3180#issuecomment-16336516

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('@silverstripe/eslint-config/.eslintrc');

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
/**/*.js.map
3+
/**/*.css.map
4+
/vendor/

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18

VERSION

Lines changed: 0 additions & 1 deletion
This file was deleted.

babel.config.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"presets": [
3+
"@babel/preset-env",
4+
"@babel/preset-react"
5+
]
6+
}

client/css/multivaluefield.css

Lines changed: 0 additions & 13 deletions
This file was deleted.

client/dist/js/multivaluefield.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/dist/styles/multivaluefield.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/javascript/multivaluefield.js

Lines changed: 0 additions & 69 deletions
This file was deleted.

client/src/js/multivaluefield.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/* global jQuery */
2+
jQuery(($) => {
3+
function addNewField() {
4+
const self = $(this);
5+
const val = self.val();
6+
const keySep = '__';
7+
8+
// check to see if the one after us is there already - if so, we don't need a new one
9+
const li = $(this).closest('li').next('li');
10+
11+
if (!val) {
12+
// lets also clean up if need be
13+
const nextText = li.find('input.mventryfield');
14+
let detach = true;
15+
16+
nextText.each(function () {
17+
if ($(this) && $(this).val() && $(this).val().length > 0) {
18+
detach = false;
19+
}
20+
});
21+
22+
if (detach) {
23+
li.detach();
24+
}
25+
} else {
26+
if (li.length) {
27+
return;
28+
}
29+
30+
const append = self.closest('li')
31+
.clone()
32+
.find('.has-chzn')
33+
.show()
34+
.removeClass('')
35+
.data('chosen', null)
36+
.end()
37+
.find('.chzn-container')
38+
.remove()
39+
.end();
40+
41+
// Assign the new inputs a unique ID, so that chosen picks up
42+
// the correct container.
43+
append.find('input, select, textarea').val('').each(function () {
44+
let pos = this.id.lastIndexOf(keySep);
45+
if (pos !== -1) {
46+
pos += keySep.length;
47+
48+
const maxId = parseInt(this.id.substr(pos), 10);
49+
const nextId = maxId + 1;
50+
51+
this.id = this.id.substr(0, pos) + nextId; // nextId auto-converted to string here
52+
}
53+
});
54+
55+
append.appendTo(self.parents('ul.multivaluefieldlist'));
56+
}
57+
58+
$(this).trigger('multiValueFieldAdded');
59+
}
60+
61+
$(document).on('keyup', '.mventryfield', addNewField);
62+
$(document).on('change', '.mventryfield:not(input)', addNewField);
63+
64+
if ($.fn.sortable) {
65+
if ($.entwine) {
66+
$('ul.multivaluefieldlist').entwine({
67+
onmatch() {
68+
$(this).sortable();
69+
}
70+
});
71+
} else {
72+
$('ul.multivaluefieldlist').sortable();
73+
}
74+
}
75+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
ul.multivaluefieldlist {
2+
margin: 0px;
3+
padding: 0px;
4+
}
5+
6+
.multivaluefieldlist > li {
7+
margin-bottom: 4px;
8+
min-width: 250px;
9+
list-style-type: none;
10+
}
11+
12+
.multivaluefieldlist > li::after {
13+
content: '';
14+
cursor: pointer;
15+
}
16+
17+
.multivaluefieldlist > li:last-child {
18+
margin-bottom: 0;
19+
}
20+
21+
.mventryfield {
22+
max-width: 200px !important;
23+
display: inline;
24+
}
25+
26+
textarea.mventryfield {
27+
max-width: none !important;
28+
vertical-align: top;
29+
}
30+
31+
.multivaluefieldlist .chosen-container {
32+
max-width: 90% !important;
33+
}
34+
35+
.field .multivaluefieldlist input.text, .field .multivaluefieldlist select {
36+
display: inline;
37+
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
},
2525
"extra": {
2626
"expose": [
27-
"client"
27+
"client/dist"
2828
],
2929
"installer-name": "multivaluefield"
3030
},

package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "multivaluefield",
3+
"engines": {
4+
"node": ">=18.x"
5+
},
6+
"scripts": {
7+
"build": "yarn && yarn lint && rm -rf client/dist/* && NODE_ENV=production webpack --mode production --bail --progress",
8+
"dev": "NODE_ENV=development webpack --progress",
9+
"watch": "NODE_ENV=development webpack --watch --progress",
10+
"lint": "eslint client/src && sass-lint client/src"
11+
},
12+
"dependencies": {
13+
},
14+
"devDependencies": {
15+
"@silverstripe/eslint-config": "^1.0.0-alpha6",
16+
"@silverstripe/webpack-config": "^2.0.0-alpha5",
17+
"webpack": "^5.74.0",
18+
"webpack-cli": "^5.0.0"
19+
},
20+
"resolutions": {
21+
"colors": "1.4.0"
22+
},
23+
"browserslist": [
24+
"defaults"
25+
]
26+
}

src/Fields/KeyValueField.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,8 @@ public function __construct($name, $title = null, $sourceKeys = [], $sourceValue
8080

8181
public function Field($properties = [])
8282
{
83-
if (Controller::curr() instanceof ContentController) {
84-
Requirements::javascript('silverstripe/admin: thirdparty/jquery/jquery.js');
85-
}
86-
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/javascript/multivaluefield.js');
87-
Requirements::css('symbiote/silverstripe-multivaluefield: client/css/multivaluefield.css');
83+
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/dist/js/multivaluefield.js');
84+
Requirements::css('symbiote/silverstripe-multivaluefield: client/dist/styles/multivaluefield.css');
8885

8986
$nameKey = $this->name.'[key][]';
9087
$nameVal = $this->name.'[val][]';

src/Fields/MultiValueDropdownField.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,8 @@ public function setSource(array $source)
4545

4646
public function Field($properties = [])
4747
{
48-
if (Controller::curr() instanceof ContentController) {
49-
Requirements::javascript('silverstripe/admin: thirdparty/jquery/jquery.js');
50-
}
51-
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/javascript/multivaluefield.js');
52-
Requirements::css('symbiote/silverstripe-multivaluefield: client/css/multivaluefield.css');
48+
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/dist/js/multivaluefield.js');
49+
Requirements::css('symbiote/silverstripe-multivaluefield: client/dist/styles/multivaluefield.css');
5350

5451
$name = $this->name.'[]';
5552
$fields = [];

src/Fields/MultiValueListField.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ public function __construct($name, $title = null, $source = [], $value = null)
2727

2828
public function Field($properties = [])
2929
{
30-
if (Controller::curr() instanceof ContentController) {
31-
Requirements::javascript('silverstripe/admin: thirdparty/jquery/jquery.js');
32-
}
33-
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/javascript/multivaluefield.js');
34-
Requirements::css('symbiote/silverstripe-multivaluefield: client/css/multivaluefield.css');
30+
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/dist/js/multivaluefield.js');
31+
Requirements::css('symbiote/silverstripe-multivaluefield: client/dist/styles/multivaluefield.css');
3532

3633
$name = $this->name.'[]';
3734

src/Fields/MultiValueTextField.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,8 @@ class MultiValueTextField extends FormField
2424

2525
public function Field($properties = [])
2626
{
27-
if (Controller::curr() instanceof ContentController) {
28-
Requirements::javascript('silverstripe/admin: thirdparty/jquery/jquery.js');
29-
}
30-
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/javascript/multivaluefield.js');
31-
Requirements::css('symbiote/silverstripe-multivaluefield: client/css/multivaluefield.css');
27+
Requirements::javascript('symbiote/silverstripe-multivaluefield: client/dist/js/multivaluefield.js');
28+
Requirements::css('symbiote/silverstripe-multivaluefield: client/dist/styles/multivaluefield.css');
3229

3330
$name = $this->name.'[]';
3431
$fields = [];

webpack.config.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const Path = require('path');
2+
const { JavascriptWebpackConfig, CssWebpackConfig } = require('@silverstripe/webpack-config');
3+
4+
const PATHS = {
5+
ROOT: Path.resolve(),
6+
SRC: Path.resolve('client/src'),
7+
DIST: Path.resolve('client/dist'),
8+
};
9+
10+
// Main JS bundle
11+
const jsConfig = new JavascriptWebpackConfig('js', PATHS, 'symbiote/silverstripe-multivaluefield')
12+
.setEntry({
13+
multivaluefield: `${PATHS.SRC}/js/multivaluefield.js`
14+
})
15+
.getConfig();
16+
// Tell webpack that jquery is externally accessible, but don't include default externals as this can be used on the frontend
17+
jsConfig.externals = {
18+
jquery: 'jQuery'
19+
};
20+
21+
const config = [
22+
jsConfig,
23+
// sass to css
24+
new CssWebpackConfig('css', PATHS)
25+
.setEntry({
26+
multivaluefield: `${PATHS.SRC}/styles/multivaluefield.scss`
27+
})
28+
.getConfig(),
29+
];
30+
31+
// Use WEBPACK_CHILD=js or WEBPACK_CHILD=css env var to run a single config
32+
module.exports = (process.env.WEBPACK_CHILD)
33+
? config.find((entry) => entry.name === process.env.WEBPACK_CHILD)
34+
: config;

0 commit comments

Comments
 (0)