@proteinjs/db-ui 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/dist/generated/index.d.ts +15 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +53 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/src/form/RecordForm.d.ts +8 -0
- package/dist/src/form/RecordForm.d.ts.map +1 -0
- package/dist/src/form/RecordForm.js +232 -0
- package/dist/src/form/RecordForm.js.map +1 -0
- package/dist/src/form/RecordFormCustomization.d.ts +10 -0
- package/dist/src/form/RecordFormCustomization.d.ts.map +1 -0
- package/dist/src/form/RecordFormCustomization.js +25 -0
- package/dist/src/form/RecordFormCustomization.js.map +1 -0
- package/dist/src/form/customizations/MigrationRecordFormCustomization.d.ts +8 -0
- package/dist/src/form/customizations/MigrationRecordFormCustomization.d.ts.map +1 -0
- package/dist/src/form/customizations/MigrationRecordFormCustomization.js +106 -0
- package/dist/src/form/customizations/MigrationRecordFormCustomization.js.map +1 -0
- package/dist/src/pages/RecordFormPage.d.ts +5 -0
- package/dist/src/pages/RecordFormPage.d.ts.map +1 -0
- package/dist/src/pages/RecordFormPage.js +140 -0
- package/dist/src/pages/RecordFormPage.js.map +1 -0
- package/dist/src/pages/RecordTablePage.d.ts +6 -0
- package/dist/src/pages/RecordTablePage.d.ts.map +1 -0
- package/dist/src/pages/RecordTablePage.js +77 -0
- package/dist/src/pages/RecordTablePage.js.map +1 -0
- package/dist/src/pages/TablesPage.d.ts +3 -0
- package/dist/src/pages/TablesPage.d.ts.map +1 -0
- package/dist/src/pages/TablesPage.js +93 -0
- package/dist/src/pages/TablesPage.js.map +1 -0
- package/dist/src/pages/UuidGeneratorPage.d.ts +3 -0
- package/dist/src/pages/UuidGeneratorPage.d.ts.map +1 -0
- package/dist/src/pages/UuidGeneratorPage.js +93 -0
- package/dist/src/pages/UuidGeneratorPage.js.map +1 -0
- package/dist/src/table/QueryTableLoader.d.ts +10 -0
- package/dist/src/table/QueryTableLoader.d.ts.map +1 -0
- package/dist/src/table/QueryTableLoader.js +71 -0
- package/dist/src/table/QueryTableLoader.js.map +1 -0
- package/dist/src/table/RecordTable.d.ts +15 -0
- package/dist/src/table/RecordTable.d.ts.map +1 -0
- package/dist/src/table/RecordTable.js +138 -0
- package/dist/src/table/RecordTable.js.map +1 -0
- package/generated/index.ts +49 -0
- package/index.ts +4 -0
- package/jest.config.js +18 -0
- package/package.json +51 -0
- package/src/form/RecordForm.tsx +191 -0
- package/src/form/RecordFormCustomization.tsx +20 -0
- package/src/form/customizations/MigrationRecordFormCustomization.tsx +29 -0
- package/src/pages/RecordFormPage.tsx +81 -0
- package/src/pages/RecordTablePage.tsx +56 -0
- package/src/pages/TablesPage.tsx +48 -0
- package/src/pages/UuidGeneratorPage.tsx +37 -0
- package/src/table/QueryTableLoader.ts +23 -0
- package/src/table/RecordTable.tsx +112 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.RecordTable = void 0;
|
|
43
|
+
var react_1 = __importDefault(require("react"));
|
|
44
|
+
var icons_material_1 = require("@mui/icons-material");
|
|
45
|
+
var string_1 = __importDefault(require("string"));
|
|
46
|
+
var ui_1 = require("@proteinjs/ui");
|
|
47
|
+
var db_1 = require("@proteinjs/db");
|
|
48
|
+
var QueryTableLoader_1 = require("./QueryTableLoader");
|
|
49
|
+
var RecordFormPage_1 = require("../pages/RecordFormPage");
|
|
50
|
+
var RecordTablePage_1 = require("../pages/RecordTablePage");
|
|
51
|
+
function deleteButton(table) {
|
|
52
|
+
var _this = this;
|
|
53
|
+
return {
|
|
54
|
+
name: "Delete selected rows",
|
|
55
|
+
icon: icons_material_1.Delete,
|
|
56
|
+
visibility: {
|
|
57
|
+
showWhenRowsSelected: true,
|
|
58
|
+
showWhenNoRowsSelected: false,
|
|
59
|
+
},
|
|
60
|
+
onClick: function (selectedRows, navigate) { return __awaiter(_this, void 0, void 0, function () {
|
|
61
|
+
var qb;
|
|
62
|
+
return __generator(this, function (_a) {
|
|
63
|
+
switch (_a.label) {
|
|
64
|
+
case 0:
|
|
65
|
+
qb = new db_1.QueryBuilderFactory().getQueryBuilder(table)
|
|
66
|
+
.condition({ field: 'id', operator: 'IN', value: selectedRows.map(function (row) { return row.id; }) });
|
|
67
|
+
return [4 /*yield*/, (0, db_1.getDb)().delete(table, qb)];
|
|
68
|
+
case 1:
|
|
69
|
+
_a.sent();
|
|
70
|
+
navigate((0, RecordTablePage_1.recordTableLink)(table));
|
|
71
|
+
return [2 /*return*/];
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}); },
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createButton(table) {
|
|
78
|
+
var _this = this;
|
|
79
|
+
return {
|
|
80
|
+
name: "Create ".concat((0, string_1.default)(table.name).humanize().s),
|
|
81
|
+
icon: icons_material_1.Add,
|
|
82
|
+
visibility: {
|
|
83
|
+
showWhenRowsSelected: false,
|
|
84
|
+
showWhenNoRowsSelected: true,
|
|
85
|
+
},
|
|
86
|
+
onClick: function (selectedRows, navigate) { return __awaiter(_this, void 0, void 0, function () {
|
|
87
|
+
return __generator(this, function (_a) {
|
|
88
|
+
navigate((0, RecordFormPage_1.newRecordFormLink)(table.name));
|
|
89
|
+
return [2 /*return*/];
|
|
90
|
+
});
|
|
91
|
+
}); },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function RecordTable(props) {
|
|
95
|
+
function defaultColumns() {
|
|
96
|
+
var _a, _b;
|
|
97
|
+
var columnProperties = [];
|
|
98
|
+
if (props.table.columns['name'])
|
|
99
|
+
columnProperties.push('name');
|
|
100
|
+
for (var _i = 0, _c = Object.keys(props.table.columns); _i < _c.length; _i++) {
|
|
101
|
+
var columnProperty = _c[_i];
|
|
102
|
+
if (columnProperties.length >= 5)
|
|
103
|
+
break;
|
|
104
|
+
if (columnProperty == 'name' || columnProperty == 'created' || columnProperty == 'updated')
|
|
105
|
+
continue;
|
|
106
|
+
var column = props.table.columns[columnProperty];
|
|
107
|
+
if ((_b = (_a = column.options) === null || _a === void 0 ? void 0 : _a.ui) === null || _b === void 0 ? void 0 : _b.hidden)
|
|
108
|
+
continue;
|
|
109
|
+
if ((column instanceof db_1.StringColumn && column.maxLength === 'MAX') || column instanceof db_1.ReferenceArrayColumn)
|
|
110
|
+
continue;
|
|
111
|
+
columnProperties.push(columnProperty);
|
|
112
|
+
}
|
|
113
|
+
columnProperties.push('created');
|
|
114
|
+
columnProperties.push('updated');
|
|
115
|
+
return columnProperties;
|
|
116
|
+
}
|
|
117
|
+
function defaultTableLoader() {
|
|
118
|
+
return new QueryTableLoader_1.QueryTableLoader(props.table, undefined, [{ field: 'updated', desc: true }]);
|
|
119
|
+
}
|
|
120
|
+
function defaultRowOnClickRedirectUrl(row) {
|
|
121
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
122
|
+
return __generator(this, function (_a) {
|
|
123
|
+
return [2 /*return*/, (0, RecordFormPage_1.recordFormLink)(props.table.name, row.id)];
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function buttons() {
|
|
128
|
+
var buttons = [];
|
|
129
|
+
if (props.buttons)
|
|
130
|
+
buttons.push.apply(buttons, props.buttons);
|
|
131
|
+
buttons.push(deleteButton(props.table));
|
|
132
|
+
buttons.push(createButton(props.table));
|
|
133
|
+
return buttons;
|
|
134
|
+
}
|
|
135
|
+
return (react_1.default.createElement(ui_1.Table, { title: props.title ? props.title : "".concat((0, string_1.default)(props.table.name).humanize().toString(), " Table"), description: props.description, columns: props.columns ? props.columns : defaultColumns(), tableLoader: props.tableLoader ? props.tableLoader : defaultTableLoader(), rowOnClickRedirectUrl: props.rowOnClickRedirectUrl ? props.rowOnClickRedirectUrl : defaultRowOnClickRedirectUrl, defaultRowsPerPage: props.defaultRowsPerPage, buttons: buttons() }));
|
|
136
|
+
}
|
|
137
|
+
exports.RecordTable = RecordTable;
|
|
138
|
+
//# sourceMappingURL=RecordTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordTable.js","sourceRoot":"","sources":["../../../src/table/RecordTable.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Load Dependency Source Graphs */
|
|
2
|
+
|
|
3
|
+
import '@emotion/react';
|
|
4
|
+
import '@emotion/styled';
|
|
5
|
+
import '@mui/icons-material';
|
|
6
|
+
import '@mui/material';
|
|
7
|
+
import '@proteinjs/db';
|
|
8
|
+
import '@proteinjs/reflection';
|
|
9
|
+
import '@proteinjs/ui';
|
|
10
|
+
import '@proteinjs/util';
|
|
11
|
+
import 'moment';
|
|
12
|
+
import 'react';
|
|
13
|
+
import 'string';
|
|
14
|
+
import 'uuid';
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/** Generate Source Graph */
|
|
18
|
+
|
|
19
|
+
const sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/db-ui/QueryTableLoader\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"QueryTableLoader\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/table/QueryTableLoader.ts\",\"qualifiedName\":\"@proteinjs/db-ui/QueryTableLoader\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<T>\",\"filePath\":null,\"qualifiedName\":\"/Table<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"query\",\"type\":{\"packageName\":\"\",\"name\":\"Query<T>\",\"filePath\":null,\"qualifiedName\":\"/Query<T>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"},{\"name\":\"sort\",\"type\":{\"packageName\":\"\",\"name\":\"SortCriteria<T>[]\",\"filePath\":null,\"qualifiedName\":\"/SortCriteria<T>[]\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\"}],\"methods\":[{\"name\":\"load\",\"returnType\":{\"packageName\":\"\",\"name\":\"Promise<RowWindow<T>>\",\"filePath\":null,\"qualifiedName\":\"/Promise<RowWindow<T>>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":true,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"startIndex\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"endIndex\",\"type\":{\"packageName\":\"\",\"name\":\"number\",\"filePath\":null,\"qualifiedName\":\"/number\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[\"/T extends Record\"],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"TableLoader\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/TableLoader\",\"properties\":[],\"methods\":[],\"typeParameters\":[\"/T\"],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/ui/TableLoader\"},{\"v\":\"@proteinjs/db-ui/RecordFormCustomization\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"RecordFormCustomization\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/form/RecordFormCustomization.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/RecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":{\"packageName\":\"\",\"name\":\"Table<any>\",\"filePath\":null,\"qualifiedName\":\"/Table<any>\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getFormButtons\",\"returnType\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"record\",\"type\":{\"packageName\":\"\",\"name\":\"any\",\"filePath\":null,\"qualifiedName\":\"/any\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFormButtons\",\"type\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/reflection\",\"name\":\"Loadable\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/reflection/Loadable\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/reflection/Loadable\"},{\"v\":\"@proteinjs/db-ui/recordFormPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"recordFormPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/RecordFormPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/recordFormPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/ui/Page\"},{\"v\":\"@proteinjs/db-ui/recordTablePage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"recordTablePage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/RecordTablePage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/recordTablePage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/tablesPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"tablesPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/TablesPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/tablesPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"uuidGeneratorPage\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/pages/UuidGeneratorPage.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"value\":{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"MigrationRecordFormCustomization\",\"filePath\":\"/home/runner/work/db/db/packages/ui/src/form/customizations/MigrationRecordFormCustomization.tsx\",\"qualifiedName\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"table\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"getFormButtons\",\"returnType\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"migration\",\"type\":{\"packageName\":\"@proteinjs/db\",\"name\":\"Migration\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db/Migration\",\"typeParameters\":null,\"directParents\":null}},{\"name\":\"defaultFormButtons\",\"type\":{\"packageName\":\"\",\"name\":\"FormButtons<any>\",\"filePath\":null,\"qualifiedName\":\"/FormButtons<any>\",\"typeParameters\":null,\"directParents\":null}}]}],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[{\"packageName\":\"@proteinjs/db-ui\",\"name\":\"RecordFormCustomization\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/db-ui/RecordFormCustomization\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParentInterfaces\":[],\"directParentClasses\":[]}],\"sourceType\":2}}],\"edges\":[{\"v\":\"@proteinjs/db-ui/QueryTableLoader\",\"w\":\"@proteinjs/ui/TableLoader\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/RecordFormCustomization\",\"w\":\"@proteinjs/reflection/Loadable\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/db-ui/recordFormPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/recordTablePage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/tablesPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/uuidGeneratorPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/db-ui/MigrationRecordFormCustomization\",\"w\":\"@proteinjs/db-ui/RecordFormCustomization\",\"value\":\"extends class\"}]}";
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
/** Generate Source Links */
|
|
23
|
+
|
|
24
|
+
import { QueryTableLoader } from '../src/table/QueryTableLoader';
|
|
25
|
+
import { RecordFormCustomization } from '../src/form/RecordFormCustomization';
|
|
26
|
+
import { recordFormPage } from '../src/pages/RecordFormPage';
|
|
27
|
+
import { recordTablePage } from '../src/pages/RecordTablePage';
|
|
28
|
+
import { tablesPage } from '../src/pages/TablesPage';
|
|
29
|
+
import { uuidGeneratorPage } from '../src/pages/UuidGeneratorPage';
|
|
30
|
+
import { MigrationRecordFormCustomization } from '../src/form/customizations/MigrationRecordFormCustomization';
|
|
31
|
+
|
|
32
|
+
const sourceLinks = {
|
|
33
|
+
'@proteinjs/db-ui/QueryTableLoader': QueryTableLoader,
|
|
34
|
+
'@proteinjs/db-ui/RecordFormCustomization': RecordFormCustomization,
|
|
35
|
+
'@proteinjs/db-ui/recordFormPage': recordFormPage,
|
|
36
|
+
'@proteinjs/db-ui/recordTablePage': recordTablePage,
|
|
37
|
+
'@proteinjs/db-ui/tablesPage': tablesPage,
|
|
38
|
+
'@proteinjs/db-ui/uuidGeneratorPage': uuidGeneratorPage,
|
|
39
|
+
'@proteinjs/db-ui/MigrationRecordFormCustomization': MigrationRecordFormCustomization,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
/** Load Source Graph and Links */
|
|
44
|
+
|
|
45
|
+
import { SourceRepository } from '@proteinjs/reflection';
|
|
46
|
+
SourceRepository.merge(sourceGraph, sourceLinks);
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
export * from '../index';
|
package/index.ts
ADDED
package/jest.config.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
"roots": [
|
|
3
|
+
"<rootDir>/test"
|
|
4
|
+
],
|
|
5
|
+
"transform": {
|
|
6
|
+
"^.+\\.tsx?$": "ts-jest"
|
|
7
|
+
},
|
|
8
|
+
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
|
|
9
|
+
"moduleFileExtensions": [
|
|
10
|
+
"ts",
|
|
11
|
+
"tsx",
|
|
12
|
+
"js",
|
|
13
|
+
"jsx",
|
|
14
|
+
"json",
|
|
15
|
+
"node"
|
|
16
|
+
],
|
|
17
|
+
"testEnvironment": "node"
|
|
18
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proteinjs/db-ui",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Db ui components",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/proteinjs/db.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/proteinjs/db/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/proteinjs/db#readme",
|
|
16
|
+
"author": "Brent Bahry",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"clean": "rm -rf dist/ node_modules/ generated/ package-lock.json",
|
|
20
|
+
"build": "reflection-build && tsc",
|
|
21
|
+
"watch": "reflection-watch"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@emotion/react": "11.11.1",
|
|
25
|
+
"@emotion/styled": "11.11.0",
|
|
26
|
+
"@mui/icons-material": "5.14.11",
|
|
27
|
+
"@mui/material": "5.14.11",
|
|
28
|
+
"@proteinjs/db": "1.0.3",
|
|
29
|
+
"@proteinjs/reflection": "1.0.2",
|
|
30
|
+
"@proteinjs/ui": "1.0.1",
|
|
31
|
+
"@proteinjs/util": "1.0.18",
|
|
32
|
+
"moment": "2.29.4",
|
|
33
|
+
"react": "18.2.0",
|
|
34
|
+
"string": "3.3.3",
|
|
35
|
+
"uuid": "8.3.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@proteinjs/reflection-build": "1.0.5",
|
|
39
|
+
"@types/jest": "29.5.5",
|
|
40
|
+
"@types/node": "14.0.27",
|
|
41
|
+
"@types/react": "18.2.23",
|
|
42
|
+
"@types/string": "0.0.33",
|
|
43
|
+
"@types/uuid": "8.3.0",
|
|
44
|
+
"jest": "29.7.0",
|
|
45
|
+
"ts-jest": "29.1.1",
|
|
46
|
+
"typescript": "5.2.2"
|
|
47
|
+
},
|
|
48
|
+
"main": "./dist/generated/index.js",
|
|
49
|
+
"types": "./dist/generated/index.d.ts",
|
|
50
|
+
"gitHead": "d85d27f2ad767c150f9651afe32d2317ba82439c"
|
|
51
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import S from 'string'
|
|
3
|
+
import moment from 'moment'
|
|
4
|
+
import { StringUtil } from '@proteinjs/util'
|
|
5
|
+
import { Form, Fields, textField, FormButtons } from '@proteinjs/ui'
|
|
6
|
+
import { Table, Record, Column, getDbService, DateTimeColumn, ReferenceArrayColumn, BooleanColumn, StringColumn } from '@proteinjs/db'
|
|
7
|
+
import { recordTableLink } from '../pages/RecordTablePage'
|
|
8
|
+
import { recordFormLink } from '../pages/RecordFormPage'
|
|
9
|
+
import { getRecordFormCustomization } from './RecordFormCustomization'
|
|
10
|
+
|
|
11
|
+
export type RecordFormProps<T extends Record> = {
|
|
12
|
+
table: Table<T>,
|
|
13
|
+
record?: T,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function RecordForm<T extends Record>({ table, record }: RecordFormProps<T>) {
|
|
17
|
+
const isNewRecord = typeof record === 'undefined';
|
|
18
|
+
const recordFormCustomization = getRecordFormCustomization(table.name);
|
|
19
|
+
return (
|
|
20
|
+
<Form
|
|
21
|
+
name={S(table.name).humanize().s}
|
|
22
|
+
createFields={createFields()}
|
|
23
|
+
fieldLayout={fieldLayout()}
|
|
24
|
+
buttons={recordFormCustomization?.getFormButtons ? recordFormCustomization.getFormButtons(record, buttons()) : buttons()}
|
|
25
|
+
onLoad={onLoad}
|
|
26
|
+
onLoadProgressMessage={`Loading ${S(table.name).humanize().s}`}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
function getColumns() {
|
|
31
|
+
const columns: {[columnPropertyName: string]: Column<T, any>} = {};
|
|
32
|
+
const nameColumn = (table.columns as any)['name'] as Column<T, any>;
|
|
33
|
+
if (nameColumn)
|
|
34
|
+
columns['name'] = nameColumn;
|
|
35
|
+
|
|
36
|
+
for (let columnPropertyName in table.columns) {
|
|
37
|
+
const column = (table.columns as any)[columnPropertyName] as Column<T, any>;
|
|
38
|
+
if (columnPropertyName == 'name' || columnPropertyName == 'created' || columnPropertyName == 'updated')
|
|
39
|
+
continue;
|
|
40
|
+
|
|
41
|
+
if (column.options?.ui?.hidden)
|
|
42
|
+
continue;
|
|
43
|
+
|
|
44
|
+
if ((column instanceof StringColumn && column.maxLength === 'MAX') || column instanceof ReferenceArrayColumn)
|
|
45
|
+
continue;
|
|
46
|
+
|
|
47
|
+
columns[columnPropertyName] = column;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!isNewRecord) {
|
|
51
|
+
columns['created'] = (table.columns as any)['created'] as Column<T, any>;
|
|
52
|
+
columns['updated'] = (table.columns as any)['updated'] as Column<T, any>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return columns;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createFields(): () => Fields {
|
|
59
|
+
return () => {
|
|
60
|
+
const fields: Fields = {};
|
|
61
|
+
for (let columnPropertyName in getColumns()) {
|
|
62
|
+
fields[columnPropertyName] = textField({
|
|
63
|
+
name: columnPropertyName,
|
|
64
|
+
label: StringUtil.humanizeCamel(columnPropertyName),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return fields;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function fieldLayout(): any {
|
|
73
|
+
const columns = getColumns();
|
|
74
|
+
const layoutColumns = Object.entries(columns).length > 6 ? 2 : 1;
|
|
75
|
+
if (layoutColumns > 1) {
|
|
76
|
+
const layout: (keyof T)[][] = [];
|
|
77
|
+
for (let columnPropertyName in columns) {
|
|
78
|
+
if (layout.length == 0 || layout[layout.length - 1].length >= layoutColumns)
|
|
79
|
+
layout.push([]);
|
|
80
|
+
|
|
81
|
+
layout[layout.length - 1].push(columnPropertyName as keyof T);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return layout;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return Object.keys(columns) as (keyof T)[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function buttons(): FormButtons<any> {
|
|
91
|
+
let newRecord: T;
|
|
92
|
+
return {
|
|
93
|
+
delete: {
|
|
94
|
+
name: 'Delete',
|
|
95
|
+
accessibility: {
|
|
96
|
+
hidden: isNewRecord,
|
|
97
|
+
},
|
|
98
|
+
style: {
|
|
99
|
+
color: 'primary',
|
|
100
|
+
variant: 'text',
|
|
101
|
+
},
|
|
102
|
+
redirect: async (fields: Fields, buttons: FormButtons<Fields>) => {
|
|
103
|
+
return { path: recordTableLink(table) };
|
|
104
|
+
},
|
|
105
|
+
onClick: async (fields: Fields, buttons: FormButtons<Fields>) => {
|
|
106
|
+
if (!record || !record.id)
|
|
107
|
+
throw new Error(`Unable to delete record, record or id undefined`);
|
|
108
|
+
|
|
109
|
+
await getDbService().delete(table, { id: record.id } as any);
|
|
110
|
+
return `Deleted ${S(table.name).humanize().s}`;
|
|
111
|
+
},
|
|
112
|
+
progressMessage: (fields: Fields) => { return `Deleting ${S(table.name).humanize().s}` },
|
|
113
|
+
},
|
|
114
|
+
save: {
|
|
115
|
+
name: 'Save',
|
|
116
|
+
accessibility: {
|
|
117
|
+
hidden: isNewRecord,
|
|
118
|
+
},
|
|
119
|
+
style: {
|
|
120
|
+
color: 'primary',
|
|
121
|
+
variant: 'contained',
|
|
122
|
+
},
|
|
123
|
+
onClick: async (fields: Fields, buttons: FormButtons<Fields>) => {
|
|
124
|
+
if (!record || !record.id)
|
|
125
|
+
throw new Error(`Unable to save record, record or id undefined`);
|
|
126
|
+
|
|
127
|
+
for (let columnPropertyName in fields) {
|
|
128
|
+
const field = fields[columnPropertyName];
|
|
129
|
+
(record as any)[columnPropertyName] = field.field.value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
await getDbService().update(table, record);
|
|
133
|
+
return `Saved ${S(table.name).humanize().s}`;
|
|
134
|
+
},
|
|
135
|
+
progressMessage: (fields: Fields) => { return `Saving ${S(table.name).humanize().s}` },
|
|
136
|
+
},
|
|
137
|
+
create: {
|
|
138
|
+
name: 'Create',
|
|
139
|
+
accessibility: {
|
|
140
|
+
hidden: !isNewRecord,
|
|
141
|
+
},
|
|
142
|
+
style: {
|
|
143
|
+
color: 'primary',
|
|
144
|
+
variant: 'contained',
|
|
145
|
+
},
|
|
146
|
+
redirect: async (fields: Fields, buttons: FormButtons<Fields>) => {
|
|
147
|
+
return { path: recordFormLink(table.name, newRecord.id) };
|
|
148
|
+
},
|
|
149
|
+
onClick: async (fields: Fields, buttons: FormButtons<Fields>) => {
|
|
150
|
+
const record: any = {};
|
|
151
|
+
for (let columnPropertyName in fields) {
|
|
152
|
+
const field = fields[columnPropertyName];
|
|
153
|
+
(record as any)[columnPropertyName] = field.field.value;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
newRecord = await getDbService().insert(table, record);
|
|
157
|
+
return `Created ${S(table.name).humanize().s}`;
|
|
158
|
+
},
|
|
159
|
+
progressMessage: (fields: Fields) => { return `Creating ${S(table.name).humanize().s}` },
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function onLoad(fields: Fields, buttons: FormButtons<Fields>) {
|
|
165
|
+
if (isNewRecord)
|
|
166
|
+
return;
|
|
167
|
+
|
|
168
|
+
for (let columnPropertyName in fields) {
|
|
169
|
+
const column = (table.columns as any)[columnPropertyName] as Column<any, any>;
|
|
170
|
+
const field = fields[columnPropertyName].field;
|
|
171
|
+
let fieldValue = (record as any)[columnPropertyName];
|
|
172
|
+
if (moment.isMoment(fieldValue))
|
|
173
|
+
fieldValue = fieldValue.format('ddd, MMM Do YY, h:mm:ss a');
|
|
174
|
+
else if (column instanceof BooleanColumn)
|
|
175
|
+
fieldValue = fieldValue == true ? 'True' : 'False';
|
|
176
|
+
|
|
177
|
+
field.value = fieldValue;
|
|
178
|
+
if (
|
|
179
|
+
columnPropertyName == 'created' ||
|
|
180
|
+
columnPropertyName == 'updated' ||
|
|
181
|
+
columnPropertyName == 'id' ||
|
|
182
|
+
column instanceof DateTimeColumn
|
|
183
|
+
) {
|
|
184
|
+
if (!field.accessibility)
|
|
185
|
+
field.accessibility = {};
|
|
186
|
+
|
|
187
|
+
field.accessibility.readonly = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Loadable, SourceRepository } from '@proteinjs/reflection'
|
|
2
|
+
import { FormButtons } from '@proteinjs/ui'
|
|
3
|
+
import { Table } from '@proteinjs/db'
|
|
4
|
+
|
|
5
|
+
export const getRecordFormCustomizations = () => SourceRepository.get().objects<RecordFormCustomization>('@proteinjs/db-ui/RecordFormCustomization');
|
|
6
|
+
|
|
7
|
+
export const getRecordFormCustomization = (tableName: string) => {
|
|
8
|
+
const recordFormCustomizations = getRecordFormCustomizations();
|
|
9
|
+
for (let recordFormCustomization of recordFormCustomizations) {
|
|
10
|
+
if (recordFormCustomization.table.name == tableName)
|
|
11
|
+
return recordFormCustomization;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export abstract class RecordFormCustomization implements Loadable {
|
|
16
|
+
abstract table: Table<any>;
|
|
17
|
+
getFormButtons(record: any, defaultFormButtons: FormButtons<any>): FormButtons<any> {
|
|
18
|
+
return defaultFormButtons;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Fields, FormButtons } from '@proteinjs/ui'
|
|
2
|
+
import { Migration, getMigrationRunnerService, tables } from '@proteinjs/db'
|
|
3
|
+
import { RecordFormCustomization } from '../RecordFormCustomization'
|
|
4
|
+
|
|
5
|
+
export class MigrationRecordFormCustomization extends RecordFormCustomization {
|
|
6
|
+
public table = tables.Migration;
|
|
7
|
+
|
|
8
|
+
getFormButtons(migration: Migration, defaultFormButtons: FormButtons<any>): FormButtons<any> {
|
|
9
|
+
const formButtons = { ...defaultFormButtons };
|
|
10
|
+
delete formButtons['create'];
|
|
11
|
+
delete formButtons['delete'];
|
|
12
|
+
formButtons['run'] = {
|
|
13
|
+
name: 'Run',
|
|
14
|
+
accessibility: {
|
|
15
|
+
hidden: !migration || migration.status === 'running',
|
|
16
|
+
},
|
|
17
|
+
style: {
|
|
18
|
+
color: 'primary',
|
|
19
|
+
variant: 'contained',
|
|
20
|
+
},
|
|
21
|
+
onClick: async (fields: Fields, buttons: FormButtons<Fields>) => {
|
|
22
|
+
await getMigrationRunnerService().runMigration(migration.id);
|
|
23
|
+
return `Started migration`;
|
|
24
|
+
},
|
|
25
|
+
progressMessage: (fields: Fields) => { return `Starting migration` },
|
|
26
|
+
};
|
|
27
|
+
return formButtons;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { FormPage, Page, PageComponentProps } from '@proteinjs/ui'
|
|
3
|
+
import { getDbService, tableByName } from '@proteinjs/db'
|
|
4
|
+
import { RecordForm } from '../form/RecordForm'
|
|
5
|
+
|
|
6
|
+
export const recordFormPage: Page = {
|
|
7
|
+
name: 'Record Form',
|
|
8
|
+
path: 'record/form',
|
|
9
|
+
auth: {
|
|
10
|
+
allUsers: true,
|
|
11
|
+
},
|
|
12
|
+
component: ({...props}) => (
|
|
13
|
+
<FormPage>
|
|
14
|
+
<DynamicRecordForm {...props} />
|
|
15
|
+
</FormPage>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const recordFormLink = (tableName: string, recordId: string) => {
|
|
20
|
+
return `/${recordFormPage.path}?table=${tableName}&record=${recordId}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const newRecordFormLink = (tableName: string) => {
|
|
24
|
+
return `/${recordFormPage.path}?table=${tableName}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const DynamicRecordForm = ({ urlParams }: PageComponentProps) => {
|
|
28
|
+
const [record, setRecord] = React.useState();
|
|
29
|
+
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
const fetchData = async () => {
|
|
32
|
+
const { table } = getTable();
|
|
33
|
+
if (!table)
|
|
34
|
+
return;
|
|
35
|
+
|
|
36
|
+
const recordId = urlParams['record'];
|
|
37
|
+
if (!recordId)
|
|
38
|
+
return;
|
|
39
|
+
|
|
40
|
+
const fetchedRecord = await getDbService().get(table, { id: recordId });
|
|
41
|
+
setRecord(fetchedRecord);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
fetchData();
|
|
45
|
+
}, [urlParams.table, urlParams.record]);
|
|
46
|
+
|
|
47
|
+
function getTable() {
|
|
48
|
+
const tableName = urlParams['table'];
|
|
49
|
+
let table;
|
|
50
|
+
let error;
|
|
51
|
+
if (tableName) {
|
|
52
|
+
try {
|
|
53
|
+
table = tableByName(tableName);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
error = `Table not accessible in UI: ${tableName}`;
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
error = `Table name not provided via the 'table' url param`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { table, error };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Form() {
|
|
65
|
+
const { table, error } = getTable();
|
|
66
|
+
if (!table) {
|
|
67
|
+
return <div>{ error }</div>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<RecordForm
|
|
72
|
+
table={table}
|
|
73
|
+
record={record}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<Form />
|
|
80
|
+
);
|
|
81
|
+
}
|