feat: add Redux Grid app
This commit is contained in:
Родитель
8544ffa5d2
Коммит
775143feb9
|
@ -1,2 +1,2 @@
|
|||
# react-redux-grid
|
||||
React Redux Grid application
|
||||
Kendo UI Grid wrapper component for React using the Redux Pattern
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "redux-grid-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@progress/kendo-ui": "2017.3.1018",
|
||||
"@progress/kendo-grid-react-wrapper": "latest",
|
||||
"@progress/kendo-data-query": "^1.0.6",
|
||||
"react": "^16.0.0",
|
||||
"react-dom": "^16.0.0",
|
||||
"react-scripts-ts": "2.8.0",
|
||||
"@progress/kendo-theme-default": "latest",
|
||||
"react-redux": "^5.0.6",
|
||||
"redux": "^3.7.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts-ts start",
|
||||
"build": "react-scripts-ts build",
|
||||
"test": "react-scripts-ts test --env=jsdom",
|
||||
"eject": "react-scripts-ts eject"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^21.1.4",
|
||||
"@types/node": "^8.0.44",
|
||||
"@types/react": "^16.0.13",
|
||||
"@types/react-dom": "^16.0.1"
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.8 KiB |
|
@ -0,0 +1,42 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { Grid, GridColumn } from '@progress/kendo-grid-react-wrapper';
|
||||
|
||||
|
||||
export default class ReduxGrid extends React.Component<any, any> {
|
||||
private widgetInstance: kendo.ui.Grid = null;
|
||||
private options: any = null;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.widgetRef = this.widgetRef.bind(this);
|
||||
|
||||
this.options = {
|
||||
selectable: true,
|
||||
filterable: true,
|
||||
groupable: true,
|
||||
sortable: {
|
||||
mode: 'multiple',
|
||||
allowUnsort: true,
|
||||
showIndexes: true
|
||||
},
|
||||
pageable: true,
|
||||
widgetRef: this.widgetRef,
|
||||
sort: this.props.onSort,
|
||||
group: this.props.onGroup,
|
||||
page: this.props.onPage,
|
||||
editable: 'popup',
|
||||
toolbar: ['create'],
|
||||
save: this.props.onSave,
|
||||
remove: this.props.onRemove,
|
||||
filter: this.props.onFilter
|
||||
};
|
||||
}
|
||||
|
||||
widgetRef(widget: kendo.ui.Grid) {
|
||||
this.widgetInstance = widget;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { products, sort, group, page, filter, pageSize } = this.props;
|
||||
const serverSorting = true;
|
||||
const serverGrouping = true;
|
||||
const serverPaging = true;
|
||||
const serverFiltering = true;
|
||||
|
||||
const dataSource = new kendo.data.DataSource({
|
||||
data: products,
|
||||
sort, group, page, filter,
|
||||
serverSorting, serverGrouping, serverPaging, serverFiltering, pageSize,
|
||||
schema: {
|
||||
model: {
|
||||
id: 'ProductID',
|
||||
fields: {
|
||||
ProductID: { editable: false, nullable: true },
|
||||
ProductName: { validation: { required: true } },
|
||||
UnitPrice: { type: 'number', validation: { required: true, min: 1 } },
|
||||
UnitsInStock: { type: 'number', validation: { min: 0, required: true } },
|
||||
Discontinued: { type: 'boolean' }
|
||||
}
|
||||
},
|
||||
total: 'total'
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{ 'marginBottom': '30px' }}>
|
||||
<Grid dataSource={dataSource} {...this.options}>
|
||||
<GridColumn field="ProductID" title="ID" filterable={false} key={1} />
|
||||
<GridColumn field="ProductName" title="Product Name" key={2} />
|
||||
<GridColumn field="UnitPrice" title="Unit Price" format="{0:c}" width="130px" key={3} />
|
||||
<GridColumn field="UnitsInStock" title="Units In Stock" width="130px" key={4} />
|
||||
<GridColumn field="Discontinued" width="130px" key={5} />
|
||||
<GridColumn command={[{"name": "edit", "text": "Edit"}, {"name": "destroy", "text": "Delete"}]} title=" " width="250px" key={6}/>
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { sort, group, page, filter, remove, add, update } from './actions';
|
||||
import ReduxGrid from './ReduxGrid';
|
||||
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
products: state.products,
|
||||
sort: state.sort,
|
||||
group: state.group,
|
||||
filter: state.filter,
|
||||
page: state.page,
|
||||
pageSize: state.pageSize
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSort: (event: any) => {
|
||||
event.preventDefault();
|
||||
dispatch(sort(event.sort));
|
||||
},
|
||||
onGroup: (event: any) => {
|
||||
event.preventDefault();
|
||||
dispatch(group(event.groups));
|
||||
|
||||
},
|
||||
onPage: (event: any) => {
|
||||
event.preventDefault();
|
||||
dispatch(page(event.page));
|
||||
},
|
||||
onRemove: (event: any) => {
|
||||
event.preventDefault();
|
||||
dispatch(remove(event.model.ProductID));
|
||||
},
|
||||
onSave: (event: any) => {
|
||||
event.preventDefault();
|
||||
dispatch(event.model.id ? update(event.model) : add(event.model));
|
||||
},
|
||||
onFilter: (event: any) => {
|
||||
event.preventDefault();
|
||||
dispatch(filter(event.filter));
|
||||
}
|
||||
});
|
||||
|
||||
const ReduxGridCont = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ReduxGrid);
|
||||
|
||||
export default ReduxGridCont;
|
|
@ -0,0 +1,51 @@
|
|||
import { SortDescriptor, CompositeFilterDescriptor, FilterDescriptor } from '@progress/kendo-data-query';
|
||||
import * as n from './names';
|
||||
|
||||
export const sort = function (sortDesc: SortDescriptor) {
|
||||
return {
|
||||
type: n.SORT,
|
||||
sort: sortDesc
|
||||
};
|
||||
};
|
||||
|
||||
export const group = function (groupDesc: [SortDescriptor]) {
|
||||
return {
|
||||
type: n.GROUP,
|
||||
group: groupDesc
|
||||
};
|
||||
};
|
||||
|
||||
export const page = function (pageNumber: number) {
|
||||
return {
|
||||
type: n.PAGE,
|
||||
page: pageNumber
|
||||
};
|
||||
};
|
||||
|
||||
export const remove = function (productID: number) {
|
||||
return {
|
||||
type: n.REMOVE,
|
||||
ProductID: productID
|
||||
};
|
||||
};
|
||||
|
||||
export const add = function (model: any) {
|
||||
return {
|
||||
type: n.ADD,
|
||||
model
|
||||
};
|
||||
};
|
||||
|
||||
export const update = function (model: any) {
|
||||
return {
|
||||
type: n.UPDATE,
|
||||
model
|
||||
};
|
||||
};
|
||||
|
||||
export const filter = function (filterDesc: CompositeFilterDescriptor | FilterDescriptor) {
|
||||
return {
|
||||
type: n.FILTER,
|
||||
filter: filterDesc
|
||||
};
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
export const SORT = 'SORT';
|
||||
export const GROUP = 'GROUP';
|
||||
export const PAGE = 'PAGE';
|
||||
export const REMOVE = 'REMOVE';
|
||||
export const ADD = 'ADD';
|
||||
export const UPDATE = 'UPDATE';
|
||||
export const FILTER = 'FILTER';
|
|
@ -0,0 +1,16 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import '@progress/kendo-ui';
|
||||
import ReduxGrid from './ReduxGridCont';
|
||||
import { Provider } from 'react-redux';
|
||||
import { products } from './products';
|
||||
import { createStoreHelper } from './reduxUtils/createStoreHelper';
|
||||
|
||||
import '@progress/kendo-theme-default/dist/all.css';
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={createStoreHelper(products)}>
|
||||
<ReduxGrid />
|
||||
</Provider>,
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,98 @@
|
|||
import { CompositeFilterDescriptor } from '@progress/kendo-data-query';
|
||||
import * as actionNames from '../actions/names';
|
||||
import createState from '../reduxUtils/createState';
|
||||
|
||||
function mergeSortDescriptors(sourceDescriptors: any, newDesciptor: any) {
|
||||
let result = [];
|
||||
let matchFound = false;
|
||||
|
||||
sourceDescriptors.forEach(element => {
|
||||
if (element.field === newDesciptor.field) {
|
||||
// If the field was already sorted
|
||||
matchFound = true;
|
||||
if (newDesciptor.dir !== undefined) {
|
||||
// and the sorting is not removed, add the new descriptor.
|
||||
result.push(newDesciptor);
|
||||
}
|
||||
} else {
|
||||
// Preserve the not affected desciptors.
|
||||
result.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
if (!matchFound) {
|
||||
// If the field was not already sorted, add the new descriptor.
|
||||
result.push(newDesciptor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mergeFilters(sourceFilters: any, newFilter: any): CompositeFilterDescriptor {
|
||||
let result: CompositeFilterDescriptor = { logic: 'and', filters: [] };
|
||||
// If a filter is presented
|
||||
if (sourceFilters.length || (sourceFilters.filters && sourceFilters.filters.length && newFilter)) {
|
||||
let isNewFilterInserted = false;
|
||||
// If a filter with the same target exists
|
||||
sourceFilters.filters.forEach((currentFilter) => {
|
||||
// If the current filter doesnt have nested filters and has the same target
|
||||
if (currentFilter.field === newFilter.filters[0].field) {
|
||||
let tmp: CompositeFilterDescriptor = { logic: newFilter.logic, filters: [] };
|
||||
newFilter.filters.forEach((fltr) => {
|
||||
// Insert all new filters
|
||||
tmp.filters.push(fltr);
|
||||
});
|
||||
result.filters.push(tmp);
|
||||
} else {
|
||||
// If the current filter DOES have nested filters and those filter has the same target
|
||||
if (currentFilter.filters && currentFilter.filters[0].field === newFilter.filters[0].field) {
|
||||
result.filters.push.apply(result.filters, newFilter);
|
||||
} else {
|
||||
// Copy all filters that does not have the same target into result
|
||||
result.filters.push(currentFilter);
|
||||
}
|
||||
}
|
||||
});
|
||||
// If the new filter hasnt been inserted into result
|
||||
if (!isNewFilterInserted) {
|
||||
result.filters.push(newFilter);
|
||||
}
|
||||
} else {
|
||||
// If the new filter is null, return empty array
|
||||
if (newFilter) {
|
||||
result.filters.push(newFilter);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export default (state, action) => {
|
||||
switch (action.type) {
|
||||
case actionNames.SORT:
|
||||
return createState(
|
||||
action.allProducts,
|
||||
state.page,
|
||||
mergeSortDescriptors(state.sort, action.sort),
|
||||
state.group,
|
||||
state.filter);
|
||||
case actionNames.GROUP:
|
||||
return createState(action.allProducts, state.page, state.sort, action.group, state.filter);
|
||||
case actionNames.PAGE:
|
||||
return createState(action.allProducts, action.page, state.sort, state.group, state.filter);
|
||||
case actionNames.FILTER:
|
||||
return createState(
|
||||
action.allProducts,
|
||||
state.page,
|
||||
state.sort,
|
||||
state.group,
|
||||
mergeFilters(state.filter, action.filter));
|
||||
case actionNames.REMOVE:
|
||||
case actionNames.ADD:
|
||||
case actionNames.UPDATE:
|
||||
return createState(action.allProducts, state.page, state.sort, state.group, state.filter);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const pageSize = 10;
|
|
@ -0,0 +1,16 @@
|
|||
import queryItems from './queryItems';
|
||||
|
||||
export default function createState(products: any, page: number, sort: any, group: any, filter: any) {
|
||||
return {
|
||||
products: queryItems(products, page, 10, sort, group, filter),
|
||||
sort,
|
||||
group,
|
||||
filter,
|
||||
page,
|
||||
pageSize: 10
|
||||
};
|
||||
}
|
||||
|
||||
export function createInitialState(products: any) {
|
||||
return createState(products, 1, [], [], []);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import { createStore, applyMiddleware } from 'redux';
|
||||
|
||||
import reducer from './../reducers';
|
||||
import { createInitialState } from './createState';
|
||||
import * as actionNames from './../actions/names';
|
||||
|
||||
// The ProductsMiddleware:
|
||||
// - handles CUD operations
|
||||
// - assigns all available products to each action
|
||||
function createProductsMiddleware(products: any) {
|
||||
return store => next => action => {
|
||||
switch (action.type) {
|
||||
case actionNames.REMOVE:
|
||||
products.splice(products.findIndex(pr => pr.ProductID === action.ProductID), 1);
|
||||
break;
|
||||
case actionNames.ADD:
|
||||
let product = action.model.toJSON();
|
||||
product.ProductID = Math.max(...products.map(pr => pr.ProductID));
|
||||
product.ProductID++;
|
||||
products.unshift(product);
|
||||
break;
|
||||
case actionNames.UPDATE:
|
||||
products[products.findIndex(el => el.ProductID === action.model.ProductID)] = action.model.toJSON();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
action.allProducts = products;
|
||||
|
||||
return next(action);
|
||||
};
|
||||
}
|
||||
|
||||
export function createStoreHelper(products: any): any {
|
||||
return createStore(
|
||||
reducer,
|
||||
createInitialState(products),
|
||||
applyMiddleware(createProductsMiddleware(products)));
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import { groupBy, orderBy, filterBy } from '@progress/kendo-data-query';
|
||||
|
||||
function getItemsPerPage(items: any, page: number, pageSize: number) {
|
||||
return items.slice((page - 1) * pageSize, page * pageSize);
|
||||
}
|
||||
|
||||
function parseDiscontinued(filter: any) {
|
||||
if (filter.filters) {
|
||||
filter.filters = filter.filters.map((fltr) => {
|
||||
return parseDiscontinued(fltr);
|
||||
});
|
||||
} else {
|
||||
if (filter.field === 'Discontinued') {
|
||||
filter.value = filter.value === 'true' || filter.value === true;
|
||||
}
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
export default function (
|
||||
items: any,
|
||||
page: number,
|
||||
pageSize: number,
|
||||
sortDescriptors: any,
|
||||
groupDescriptors: any,
|
||||
filter: any) {
|
||||
if (filter) {
|
||||
filter = parseDiscontinued(filter);
|
||||
}
|
||||
|
||||
let result: any = filterBy(items, filter);
|
||||
result = orderBy(result, groupDescriptors.concat(sortDescriptors));
|
||||
result = getItemsPerPage(result, page, pageSize);
|
||||
result = groupBy(result, groupDescriptors);
|
||||
result = toGroupable(result);
|
||||
result.total = items.length;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toGroupable(data: any) {
|
||||
if (Array.isArray(data)) {
|
||||
data = data.map(tmp => {
|
||||
if (tmp.items) {
|
||||
tmp.items = tmp.items.map((item) => {
|
||||
if (item.items) {
|
||||
tmp.hasSubgroups = true;
|
||||
}
|
||||
return toGroupable(item);
|
||||
});
|
||||
}
|
||||
return tmp;
|
||||
});
|
||||
} else {
|
||||
if (data.items) {
|
||||
data.items = data.items.map(item => {
|
||||
if (item.items) {
|
||||
data.hasSubgroups = true;
|
||||
}
|
||||
return toGroupable(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"noImplicitAny": false,
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"jsx": "react",
|
||||
"lib": ["es2015", "es2017", "dom"],
|
||||
"declaration": false,
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"awesomeTypescriptLoaderOptions": {
|
||||
"useTranspileModule": true,
|
||||
"transpileOnly": true,
|
||||
"useCache": true
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"extends": ["tslint-react"],
|
||||
"rules": {
|
||||
"align": [
|
||||
true,
|
||||
"parameters",
|
||||
"arguments",
|
||||
"statements"
|
||||
],
|
||||
"ban": false,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
true,
|
||||
"check-space"
|
||||
],
|
||||
"curly": true,
|
||||
"eofline": false,
|
||||
"forin": true,
|
||||
"indent": [ true, "spaces" ],
|
||||
"interface-name": [true, "never-prefix"],
|
||||
"jsdoc-format": true,
|
||||
"jsx-no-lambda": false,
|
||||
"jsx-no-multiline-js": false,
|
||||
"label-position": true,
|
||||
"max-line-length": [ true, 120 ],
|
||||
"member-ordering": [
|
||||
true,
|
||||
"public-before-private",
|
||||
"static-before-instance",
|
||||
"variables-before-functions"
|
||||
],
|
||||
"no-any": true,
|
||||
"no-arg": true,
|
||||
"no-bitwise": true,
|
||||
"no-console": [
|
||||
true,
|
||||
"log",
|
||||
"error",
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-consecutive-blank-lines": true,
|
||||
"no-construct": true,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-empty": true,
|
||||
"no-eval": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-string-literal": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-trailing-whitespace": false,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": true,
|
||||
"one-line": [
|
||||
true,
|
||||
"check-catch",
|
||||
"check-else",
|
||||
"check-open-brace",
|
||||
"check-whitespace"
|
||||
],
|
||||
"quotemark": [true, "single", "jsx-double"],
|
||||
"radix": true,
|
||||
"semicolon": [true, "always"],
|
||||
"switch-default": true,
|
||||
|
||||
"trailing-comma": [false],
|
||||
|
||||
"triple-equals": [ true, "allow-null-check" ],
|
||||
"typedef": [
|
||||
true,
|
||||
"parameter",
|
||||
"property-declaration"
|
||||
],
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
}
|
||||
],
|
||||
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-module",
|
||||
"check-operator",
|
||||
"check-separator",
|
||||
"check-type",
|
||||
"check-typecast"
|
||||
]
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче