Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • maspect/amiv-admintool
  • emustafa/amiv-admintool
  • dvruette/amiv-admintool
  • amiv/amiv-admintool
4 results
Show changes
import m from 'mithril';
import infinite from 'mithril-infinite';
import { List, ListTile, Toolbar, Search, Button } from 'polythene-mithril';
import { List, ListTile, Toolbar, Search, Button, Icon } from 'polythene-mithril';
import 'polythene-css';
import { styler } from 'polythene-core-css';
import { chip, icons } from './elements';
import { FilterChip, icons } from './elements';
const tableStyles = [
{
......@@ -21,22 +21,6 @@ const tableStyles = [
styler.add('tableview', tableStyles);
class FilterChip {
view({ attrs: { selected = false, onclick = () => {} }, children }) {
return m(chip, {
'margin-left': '5px',
'margin-right': '5px',
background: selected ? '#aaaaaa' : '#dddddd',
svgBackground: '#aaaaaa',
textColor: selected ? '#000000' : '#999999',
svgColor: '#000000',
svg: selected ? icons.checked : null,
onclick,
}, children);
}
}
export default class TableView {
/* Shows a table of objects for a given API resource.
*
......@@ -56,19 +40,24 @@ export default class TableView {
constructor({
attrs: {
keys,
titles,
tileContent,
filters = null,
clickOnRows = (data) => { m.route.set(`/${data._links.self.href}`); },
clickOnTitles = (controller, title) => { controller.setSort([[title, 1]]); },
},
}) {
this.search = '';
this.tableKeys = keys || [];
this.tableTitles = titles;
this.tileContent = tileContent;
this.clickOnRows = clickOnRows;
this.clickOnTitles = clickOnTitles;
this.searchValue = '';
// make a copy of filters so we can toggle the selected status
this.filters = filters ? filters.map(filterGroup =>
filterGroup.map(filter => Object.assign({}, filter))) : null;
this.filters = filters ? filters.map(
filterGroup => filterGroup.map(filter => Object.assign({}, filter)),
) : null;
}
/*
......@@ -117,18 +106,32 @@ export default class TableView {
getSelectedFilterQuery() {
// produce a list of queries from the filters that are currently selected
const selectedFilters = [].concat(...this.filters.map(filterGroup =>
filterGroup.filter(filter => filter.selected === true).map(filter => filter.query)));
const selectedFilters = [].concat(...this.filters.map(filterGroup => filterGroup.filter(
filter => filter.selected === true,
).map(filter => filter.query)));
// now merge all queries into one new object
return Object.assign({}, ...selectedFilters);
}
// Display an arrow at the table title that allows sorting
arrowOrNot(controller, title) {
const titleText = title.width ? title.text : title;
if (!controller.sort) return false;
let i;
for (i = 0; i < this.tableTitles.length; i += 1) {
const tableTitlei = this.tableTitles[i].width
? this.tableTitles[i].text : this.tableTitles[i];
if (tableTitlei === titleText) break;
}
return this.tableKeys[i] === controller.sort[0][0];
}
view({
attrs: {
controller,
titles,
onAdd = false,
buttons = [],
tableHeight = false,
},
}) {
......@@ -136,8 +139,8 @@ export default class TableView {
style: {
display: 'grid',
height: '100%',
'grid-template-rows': this.filters ?
'48px 40px calc(100% - 78px)' : '48px calc(100% - 78px)',
'grid-template-rows': this.filters
? '48px 40px calc(100% - 120px)' : '48px calc(100% - 80px)',
'background-color': 'white',
},
}, [
......@@ -158,6 +161,16 @@ export default class TableView {
},
fullWidth: false,
}),
...buttons.map(b => m(Button, {
className: 'blue-button',
style: {
'margin-right': '5px',
},
events: {
onclick: b.onclick,
},
label: b.text,
})),
onAdd ? m(Button, {
className: 'blue-button',
borders: true,
......@@ -172,19 +185,20 @@ export default class TableView {
// ones in this group will be deselected)
this.filters && m('div', {
style: {
height: '40px',
height: '50px',
'overflow-x': 'auto',
'overflow-y': 'hidden',
'white-space': 'nowrap',
padding: '0px 5px',
},
}, [].concat(['Filters: '], ...[...this.filters.keys()].map(filterGroupIdx =>
[...this.filters[filterGroupIdx].keys()].map((filterIdx) => {
}, [].concat(['Filters: '], ...[...this.filters.keys()].map(
filterGroupIdx => [...this.filters[filterGroupIdx].keys()].map((filterIdx) => {
const thisFilter = this.filters[filterGroupIdx][filterIdx];
return m(FilterChip, {
selected: thisFilter.selected,
onclick: () => {
if (!thisFilter.selected) {
// set all filters in this group to false
// set all filters in this group to false
[...this.filters[filterGroupIdx].keys()].forEach((i) => {
this.filters[filterGroupIdx][i].selected = false;
});
......@@ -197,7 +211,8 @@ export default class TableView {
controller.setFilter(this.getSelectedFilterQuery());
},
}, thisFilter.name);
})))),
}),
))),
m(List, {
className: 'scrollTable',
style: {
......@@ -207,14 +222,25 @@ export default class TableView {
tiles: [
m(ListTile, {
className: 'tableTile',
hoverable: this.clickOnTitles,
content: m(
'div',
{ style: { width: '100%', display: 'flex' } },
// Either titles is a list of titles that are distributed equally,
// or it is a list of objects with text and width
titles.map(title => m('div', {
style: { width: title.width || `${98 / this.tableKeys.length}%` },
}, title.width ? title.text : title)),
titles.map((title, i) => m(
'div', {
onclick: () => {
if (this.clickOnTitles && this.tableKeys[i]) {
this.clickOnTitles(controller, this.tableKeys[i]);
}
},
style: { width: title.width || `${98 / this.tableKeys.length}%` },
},
[title.width ? title.text : title,
this.arrowOrNot(controller, title)
? m(Icon, { svg: { content: m.trust(icons.sortingArrow) } }) : ''],
)),
),
}),
m(infinite, controller.infiniteScrollParams(this.item())),
......@@ -223,4 +249,3 @@ export default class TableView {
]);
}
}
// Start with prod config
const config = require('./webpack.config.prod.js');
// Replace development with production config
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// Start with dev config
const config = require('./webpack.config.js');
// Remove local server and code map
config.devServer = undefined;
//config.devtool = '';
config.mode = 'production';
config.optimization = {
usedExports: true,
sideEffects: true,
splitChunks: {
chunks: 'async', // TODO possibly set to all
automaticNameDelimiter: '-',
name: true,
},
};
// Add optimization plugins
config.plugins.push(
new CompressionPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
);
// Replace local with development server config
config.resolve.alias.networkConfig = `${__dirname}/src/networkConfig.dev.json`;
module.exports = config;
......@@ -38,12 +38,12 @@ const config = {
rules: [
{
test: /\.js$/,
enforce: "pre",
enforce: 'pre',
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
emitWarning: true // don't fail the build for linting errors
}
emitWarning: true, // don't fail the build for linting errors
},
},
{
test: /\.js$/, // Check for all js files
......@@ -52,13 +52,19 @@ const config = {
path.resolve(__dirname, 'node_modules/@material'),
path.resolve(__dirname, 'node_modules/amiv-web-ui-components'),
],
use: [{
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: ['transform-object-rest-spread'],
use: [
{
loader: 'babel-loader',
options: {
//presets: [['@babel/preset-env', { targets: 'last 2 years' }]],
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-proposal-object-rest-spread',
//'@babel/plugin-syntax-dynamic-import',
],
},
},
}],
],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
......
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// Start with dev config
const config = require('./webpack.config.js');
// Remove development server and code map
config.devServer = undefined;
config.devtool = '';
config.mode = 'production';
config.optimization = {
usedExports: true,
sideEffects: true,
splitChunks: {
chunks: 'async', // TODO possibly set to all
automaticNameDelimiter: '-',
name: true,
},
};
// Add optimization plugins
config.plugins.push(
new CompressionPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
);
// Replace development with production config
config.resolve.alias.networkConfig = `${__dirname}/src/networkConfig.local.json`;
module.exports = config;
......@@ -7,22 +7,31 @@ const config = require('./webpack.config.js');
// Remove development server and code map
config.devServer = undefined;
config.devtool = '';
config.mode = 'production';
config.optimization = {
usedExports: true,
sideEffects: true,
splitChunks: {
chunks: 'async', // TODO possibly set to all
automaticNameDelimiter: '-',
name: true,
},
};
// Add optimization plugins
config.plugins = [
new webpack.optimize.UglifyJsPlugin(),
new webpack.optimize.AggressiveMergingPlugin(),
config.plugins.push(
new CompressionPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
];
);
// Replace development with production config
config.resolve.alias.networkConfig = `${__dirname}/src/networkConfig.prod.json`;
module.exports = config;
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
// Start with dev config
const config = require('./webpack.config.js');
// Remove local server and code map
config.devServer = undefined;
//config.devtool = '';
config.mode = 'production';
config.optimization = {
usedExports: true,
sideEffects: true,
splitChunks: {
chunks: 'async', // TODO possibly set to all
automaticNameDelimiter: '-',
name: true,
},
};
// Add optimization plugins
config.plugins.push(
new CompressionPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
}),
);
// Replace local with staging server config
config.resolve.alias.networkConfig = `${__dirname}/src/networkConfig.staging.json`;
module.exports = config;