UNPKG

graft-react

Version:

react admin and helper components for graft-db

435 lines (434 loc) 22.5 kB
"use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t; return { next: verb(0), "throw": verb(1), "return": verb(2) }; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var React = require("react"); var react_dom_1 = require("react-dom"); var react_dnd_1 = require("react-dnd"); var Toolbars_1 = require("react-md/lib/Toolbars"); var List_1 = require("react-md/lib/Lists/List"); var ListItem_1 = require("react-md/lib/Lists/ListItem"); var Button_1 = require("react-md/lib/Buttons/Button"); var Avatars_1 = require("react-md/lib/Avatars"); var FontIcons_1 = require("react-md/lib/FontIcons"); var SelectionControl_1 = require("react-md/lib/SelectionControls/SelectionControl"); var TextFields_1 = require("react-md/lib/TextFields"); var PublishButton_1 = require("./PublishButton"); var modal_1 = require("../modal"); var Scroll_1 = require("./Scroll"); var debounce = require("lodash.debounce"); var graft_db_1 = require("graft-db"); var shortid = require("shortid"); var utils_1 = require("../utils"); var Router_1 = require("./Router"); var WithClient_1 = require("./WithClient"); var utils_2 = require("../utils"); var fragments = require("../fragments"); var Drawers_1 = require("react-md/lib/Drawers"); var PropertyEdit_1 = require("./PropertyEdit"); var WithQuery_1 = require("./WithQuery"); var validName = /^[a-z][a-zA-Z0-9]*$/; var TypeEdit = (function (_super) { __extends(TypeEdit, _super); function TypeEdit() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var _this = _super.apply(this, args) || this; _this.add = function () { return __awaiter(_this, void 0, void 0, function () { var client, type, name_1, id_1, owner_1, fieldType_1, pos_1, e_1; return __generator(this, function (_a) { switch (_a.label) { case 0: client = this.context.client; type = this.props.type; _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); if (!type) { throw new Error('no type'); } return [4 /*yield*/, modal_1.prompt('Enter a name for the new property')]; case 2: name_1 = _a.sent(); if (!name_1) { throw new Error('you must give a valid name'); } if (!validName.test(name_1)) { throw new Error('name must start with a lowercase, should be in camelCase form and must not contain any whitespace'); } id_1 = shortid.generate(); owner_1 = type.id; fieldType_1 = graft_db_1.PropertyType.Label; pos_1 = type.properties.length; return [4 /*yield*/, client.update(function (b) { return b.set(id_1, graft_db_1.Entities.property(owner_1, name_1, fieldType_1, { pos: pos_1 })); })]; case 3: _a.sent(); this.select({ id: id_1 }); return [3 /*break*/, 5]; case 4: e_1 = _a.sent(); modal_1.alert(e_1.toString()); return [3 /*break*/, 5]; case 5: return [2 /*return*/]; } }); }); }; _this.remove = function (p) { return __awaiter(_this, void 0, void 0, function () { var client, ok, g, values, ok_1, ids_1, e_2; return __generator(this, function (_a) { switch (_a.label) { case 0: client = this.context.client; return [4 /*yield*/, modal_1.confirm("Are you sure you want to remove '" + p.name + "' property?", { okLabel: 'Yes, Continue', cancelLabel: 'No, Cancel' })]; case 1: ok = _a.sent(); if (!ok) { return [2 /*return*/]; } _a.label = 2; case 2: _a.trys.push([2, 7, , 8]); return [4 /*yield*/, client.work.toGraph()]; case 3: g = _a.sent(); values = g.all.filter(function (o) { return o.property === p.id; }).toArray(); if (!values.length) return [3 /*break*/, 5]; return [4 /*yield*/, modal_1.confirm("Property " + p.name + " has been used, if you continue you will also remove " + values.length + " " + p.name + " values", { okLabel: 'I understand, delete the values', cancelLabel: 'Abort' })]; case 4: ok_1 = _a.sent(); if (!ok_1) { return [2 /*return*/]; } _a.label = 5; case 5: ids_1 = values.length > 0 ? values.map(function (v) { return v.id; }) : []; ids_1.push(p.id); return [4 /*yield*/, client.update(function (b) { return b.delete.apply(b, ids_1); })]; case 6: _a.sent(); return [3 /*break*/, 8]; case 7: e_2 = _a.sent(); modal_1.alert(e_2.toString()); return [3 /*break*/, 8]; case 8: return [2 /*return*/]; } }); }); }; _this.select = function (_a) { var id = _a.id; var navigator = _this.context.navigator; navigator.update({ propertyId: id }); }; _this.setSingleton = function (singleton) { _this.setState({ singleton: singleton }, _this.save); }; _this.setName = function (name) { _this.setState({ name: name }, _this.save); }; _this.save = debounce(function () { return __awaiter(_this, void 0, void 0, function () { var _this = this; var type_1, name_2, singleton_1, client, e_3; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); type_1 = this.props.type; if (!type_1) { throw new Error('cannot save, no type'); } name_2 = this.getName(); if (!name_2) { throw new Error('no name'); } singleton_1 = this.getSingleton(); client = this.context.client; return [4 /*yield*/, client.update(function (b) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, b.set(type_1.id, graft_db_1.Entities.type(name_2, { singleton: singleton_1 }))]; }); }); })]; case 1: _a.sent(); this.setState({ name: null, singleton: null, }); return [3 /*break*/, 3]; case 2: e_3 = _a.sent(); modal_1.alert(e_3.toString()); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }, 250); _this.showSidebar = function () { var navigator = _this.context.navigator; navigator.update({ sidebar: true }); }; _this.sort = function (fromIndex, toIndex) { var ps = (_this.getProperties()).slice(); ps.splice(toIndex, 0, ps.splice(fromIndex, 1)[0]); var orderedProperties = ps.map(function (v, idx) { return (__assign({}, v, { pos: idx })); }); _this.setState({ orderedProperties: orderedProperties }); }; _this.doneSorting = function (droppedInList) { if (!droppedInList) { _this.setState({ orderedProperties: null }); } else { _this.saveOrderedProperties(); } }; _this.saveOrderedProperties = function () { return __awaiter(_this, void 0, void 0, function () { var _this = this; var orderedProperties, client; return __generator(this, function (_a) { switch (_a.label) { case 0: orderedProperties = this.state.orderedProperties; if (!orderedProperties) { return [2 /*return*/]; } client = this.context.client; return [4 /*yield*/, client.update(function (b) { return __awaiter(_this, void 0, void 0, function () { var i, p; return __generator(this, function (_a) { switch (_a.label) { case 0: i = 0; _a.label = 1; case 1: if (!(i < orderedProperties.length)) return [3 /*break*/, 4]; p = orderedProperties[i]; return [4 /*yield*/, b.set(p.id, { kind: graft_db_1.Kind.Property, type: graft_db_1.PropertyType[p.type], name: p.name, owner: p.owner.id, nullable: p.nullable, list: p.list, maxLength: p.maxLength, edge: p.edge, edgeTypes: p.edgeTypes, pos: i, })]; case 2: b = _a.sent(); _a.label = 3; case 3: i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/, b]; } }); }); })]; case 1: _a.sent(); this.setState({ orderedProperties: null }); return [2 /*return*/]; } }); }); }; _this.state = { name: null, singleton: null, }; return _this; } TypeEdit.prototype.getSingleton = function () { if (this.state.singleton !== null) { return this.state.singleton; } var type = this.props.type; return type ? !!type.singleton : false; }; TypeEdit.prototype.getName = function () { if (this.state.name !== null) { return this.state.name; } var type = this.props.type; return type ? type.name || '' : ''; }; TypeEdit.prototype.getProperties = function () { var orderedProperties = this.state.orderedProperties; if (orderedProperties) { return orderedProperties; } var type = this.props.type; if (!type) { return []; } return type.properties.sort(function (a, b) { return a.pos > b.pos ? 1 : b.pos > a.pos ? -1 : 0; }); }; TypeEdit.prototype.render = function () { var _this = this; var navigator = this.context.navigator; var _a = navigator.data(), propertyId = _a.propertyId, sidebar = _a.sidebar; var _b = this.props, type = _b.type, types = _b.types; var properties = this.getProperties(); if (!type) { return React.createElement("div", null, "NO_TYPE"); } var drawer; var p = propertyId && utils_2.find(type.properties, function (p) { return p.id === propertyId; }); if (p) { drawer = (React.createElement(Drawers_1.default, { defaultVisible: true, className: 'md-toolbar-relative', key: p.id, position: 'right', type: Drawers_1.default.DrawerTypes.PERMANANT, style: { zIndex: 100, width: 400, overflowY: 'auto' } }, React.createElement(PropertyEdit_1.PropertyEdit, { key: p.id, property: p, types: types || [] }))); } var right = drawer ? 400 : 0; var btnRight = right + 18; return (React.createElement("div", { key: type.id }, React.createElement(Toolbars_1.default, { colored: true, title: type.name + " Type", nav: sidebar ? undefined : React.createElement(Button_1.default, { key: "nav", icon: true, onClick: this.showSidebar }, "menu"), actions: React.createElement(PublishButton_1.PublishButton, null) }), React.createElement(Scroll_1.Scroll, { className: 'md-toolbar-relative', style: { right: right, transition: 'right 250ms ease-in' } }, React.createElement("div", { className: 'md-grid' }, React.createElement(TextFields_1.default, { className: 'md-cell md-cell--12 md-cell--top', id: 'name', label: 'Name', placeholder: 'Type Name', value: this.getName(), onChange: this.setName, helpText: 'The name of the type will be used to generate the API' }), React.createElement(SelectionControl_1.default, { className: 'md-cell md-cell--12 md-cell--top', id: 'singleton', name: 'singleton', type: 'switch', label: 'Singleton', checked: this.getSingleton(), onChange: this.setSingleton }), React.createElement("p", { className: 'md-caption' }, "If type is a singleton, then only ONE instance of this type can be created")), React.createElement(List_1.default, null, properties.map(function (p, idx) { return React.createElement(PropertyItem, { index: idx, key: p.id, property: p, active: p.id === propertyId, onClick: _this.select, onRemove: _this.remove, onReorder: _this.sort, onDoneReordering: _this.doneSorting }); })), React.createElement(Button_1.default, { floating: true, fixed: true, primary: true, onClick: this.add, style: { right: btnRight } }, "add")), drawer)); }; return TypeEdit; }(React.Component)); TypeEdit.contextTypes = __assign({}, WithClient_1.clientContextTypes, Router_1.navigatorContextTypes); TypeEdit = __decorate([ WithQuery_1.WithQuery("\n query args($id: ID!) {\n type:node(id: $id) {\n ...on Type {\n " + fragments.type + "\n }\n }\n types:types {\n id:_id\n name\n }\n }\n") ], TypeEdit); exports.TypeEdit = TypeEdit; var itemDragSource = { beginDrag: function (props) { var property = props.property, index = props.index; return { property: property, index: index }; }, endDrag: function (props, monitor, _component) { var onDoneReordering = props.onDoneReordering; if (!monitor.didDrop()) { onDoneReordering(false); return; } onDoneReordering(true); } }; var itemTarget = { hover: function (props, monitor, component) { var dragIndex = monitor.getItem().index; var hoverIndex = props.index; if (dragIndex === hoverIndex) { return; } var hoverBoundingRect = react_dom_1.findDOMNode(component).getBoundingClientRect(); var hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; var clientOffset = monitor.getClientOffset(); var hoverClientY = clientOffset.y - hoverBoundingRect.top; if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) { return; } if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) { return; } var onReorder = props.onReorder; onReorder(dragIndex, hoverIndex); monitor.getItem().index = hoverIndex; } }; var PropertyItem = (function (_super) { __extends(PropertyItem, _super); function PropertyItem() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.remove = function (e) { e.stopPropagation(); var _a = _this.props, onRemove = _a.onRemove, property = _a.property; if (onRemove) { onRemove(property); } }; _this.click = function (e) { e.stopPropagation(); var _a = _this.props, onClick = _a.onClick, property = _a.property; if (onClick) { onClick(property); } }; return _this; } PropertyItem.prototype.render = function () { var _a = this.props, property = _a.property, active = _a.active, isDragging = _a.isDragging, dragSource = _a.dragSource, dropTarget = _a.dropTarget; var icon = dragSource(React.createElement("div", null, React.createElement(Avatars_1.default, { icon: utils_1.propertyIcon(graft_db_1.PropertyType[property.type]) }))); var border = isDragging ? '5px dashed #eee' : 0; var opacity = isDragging ? 0 : 1; return dropTarget(React.createElement("div", { style: { border: border } }, React.createElement(ListItem_1.default, { primaryText: property.name, onClick: this.click, active: active, secondaryText: "" + (property.list ? 'List of ' : '') + property.type, leftAvatar: icon, rightIcon: React.createElement(FontIcons_1.default, { onClick: this.remove }, "delete"), style: { opacity: opacity } }))); }; return PropertyItem; }(React.Component)); PropertyItem = __decorate([ react_dnd_1.DropTarget('property', itemTarget, function (connect) { return ({ dropTarget: connect.dropTarget() }); }), react_dnd_1.DragSource('property', itemDragSource, function (connect, monitor) { return ({ dragSource: connect.dragSource(), isDragging: monitor.isDragging() }); }) ], PropertyItem);