UNPKG

graft-react

Version:

react admin and helper components for graft-db

430 lines (429 loc) 20.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 graft_db_1 = require("graft-db"); var Buttons_1 = require("react-md/lib/Buttons"); var Toolbars_1 = require("react-md/lib/Toolbars"); var Media_1 = require("react-md/lib/Media/Media"); var SelectionControl_1 = require("react-md/lib/SelectionControls/SelectionControl"); var utils_1 = require("../utils"); var utils_2 = require("../utils"); var react_dnd_html5_backend_1 = require("react-dnd-html5-backend"); var react_dnd_1 = require("react-dnd"); var WithClient_1 = require("./WithClient"); var edgeItemDragSource = { beginDrag: function (props) { var id = props.id, index = props.index; return { id: id, index: index }; }, endDrag: function (props, monitor, _component) { var onDoneReordering = props.onDoneReordering; if (!monitor.didDrop()) { onDoneReordering(false); return; } onDoneReordering(true); } }; var edgeItemTarget = { 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 placeholder = 'https://placeholdit.imgix.net/~text?txtsize=38&txt=loading&w=400&h=250&txttrack=0'; var ImageItem = (function (_super) { __extends(ImageItem, _super); function ImageItem() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var _this = _super.apply(this, args) || this; _this.loadError = function (err) { console.error('failed to load image', _this.props.srcKey, err); }; _this.remove = function (e) { e.preventDefault(); var _a = _this.props, id = _a.id, onRemove = _a.onRemove; onRemove(id); }; _this.select = function (selected) { _this.props.onSelect(selected); }; _this.state = { url: null }; _this.load(_this.props.srcKey).catch(_this.loadError); return _this; } ImageItem.prototype.componentDidMount = function () { this.mounted = true; }; ImageItem.prototype.componentWillUnmount = function () { this.mounted = false; }; ImageItem.prototype.componentWillReceiveProps = function (nextProps) { if (this.props.srcKey != nextProps.srcKey) { this.load(nextProps.srcKey).catch(this.loadError); } }; ImageItem.prototype.load = function (key) { return __awaiter(this, void 0, void 0, function () { var client, bytes, blob, url; return __generator(this, function (_a) { switch (_a.label) { case 0: client = this.context.client; return [4 /*yield*/, client.store.getBuffer(key)]; case 1: bytes = _a.sent(); blob = new Blob([bytes]); return [4 /*yield*/, utils_2.blobToDataURL(blob)]; case 2: url = _a.sent(); if (this.mounted) { this.setState({ url: url }); } return [2 /*return*/]; } }); }); }; ImageItem.prototype.render = function () { var _a = this.props, isDragging = _a.isDragging, dragSource = _a.dragSource, dropTarget = _a.dropTarget, selected = _a.selected, id = _a.id; var url = this.state.url; var mediaStyle = { backgroundImage: "url(" + (url || placeholder) + ")", backgroundSize: 'cover', backgroundPosition: 'center center', opacity: isDragging ? 0 : 1, }; var wrapperStyle = { border: isDragging ? '5px dashed #eee' : 0, }; return dragSource(dropTarget(React.createElement("div", { className: 'md-cell md-cell--4' }, React.createElement("div", { style: wrapperStyle }, React.createElement(Media_1.default, { aspectRatio: '16-9', style: mediaStyle }, React.createElement(SelectionControl_1.default, { id: "select-" + id, name: 'select', type: 'checkbox', style: { position: 'absolute', top: 0, left: 0 }, checked: selected, onChange: this.select })))))); }; return ImageItem; }(React.Component)); ImageItem.contextTypes = WithClient_1.clientContextTypes; ImageItem = __decorate([ react_dnd_1.DropTarget('image', edgeItemTarget, function (connect) { return ({ dropTarget: connect.dropTarget() }); }), react_dnd_1.DragSource('image', edgeItemDragSource, function (connect, monitor) { return ({ dragSource: connect.dragSource(), isDragging: monitor.isDragging() }); }) ], ImageItem); exports.ImageItem = ImageItem; var ImageProperty = (function (_super) { __extends(ImageProperty, _super); function ImageProperty() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var _this = _super.apply(this, args) || this; _this.remove = function (id) { var client = _this.context.client; client.update(function (b) { return b.delete(id); }); }; _this.move = function (fromIndex, toIndex) { var values = _this.getValues(); var vs = values.slice(); vs.splice(toIndex, 0, vs.splice(fromIndex, 1)[0]); var orderedValues = vs.map(function (v, idx) { return (__assign({}, v, { pos: idx })); }); _this.setState({ orderedValues: orderedValues }); }; _this.moved = function (droppedInList) { return __awaiter(_this, void 0, void 0, function () { var _this = this; var client, orderedValues, _a, object_1, property_1; return __generator(this, function (_b) { switch (_b.label) { case 0: client = this.context.client; orderedValues = this.state.orderedValues; if (!(droppedInList && orderedValues)) return [3 /*break*/, 2]; _a = this.props, object_1 = _a.object, property_1 = _a.property; return [4 /*yield*/, client.update(function (b) { return __awaiter(_this, void 0, void 0, function () { var _i, orderedValues_1, v; return __generator(this, function (_a) { switch (_a.label) { case 0: _i = 0, orderedValues_1 = orderedValues; _a.label = 1; case 1: if (!(_i < orderedValues_1.length)) return [3 /*break*/, 4]; v = orderedValues_1[_i]; return [4 /*yield*/, b.set(v.id, { kind: graft_db_1.Kind.Value, owner: object_1.id, property: property_1.id, type: graft_db_1.ValueType.Image, key: v.key, edge: property_1.edge, pos: v.pos, })]; case 2: b = _a.sent(); _a.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/, b]; } }); }); })]; case 1: _b.sent(); _b.label = 2; case 2: this.setState({ orderedValues: null }); return [2 /*return*/]; } }); }); }; _this.addFile = function (f) { return __awaiter(_this, void 0, void 0, function () { var client, buf, key_1, _a, object_2, property_2, values_1, id_1, err_1; return __generator(this, function (_b) { switch (_b.label) { case 0: client = this.context.client; _b.label = 1; case 1: _b.trys.push([1, 5, , 6]); return [4 /*yield*/, utils_2.blobToUint8Array(f)]; case 2: buf = _b.sent(); return [4 /*yield*/, client.store.setBuffer(client.newImageKey(), buf)]; case 3: key_1 = _b.sent(); _a = this.props, object_2 = _a.object, property_2 = _a.property; values_1 = this.getValues(); id_1 = client.generateId(); return [4 /*yield*/, client.update(function (b) { return b.set(id_1, { kind: graft_db_1.Kind.Value, owner: object_2.id, property: property_2.id, type: graft_db_1.ValueType.Image, key: key_1, edge: property_2.edge, pos: values_1.length - 1, }); })]; case 4: _b.sent(); return [3 /*break*/, 6]; case 5: err_1 = _b.sent(); console.error(f.filename, err_1); return [3 /*break*/, 6]; case 6: return [2 /*return*/]; } }); }); }; _this.addFiles = function (files) { return __awaiter(_this, void 0, void 0, function () { var _i, files_1, f; return __generator(this, function (_a) { switch (_a.label) { case 0: _i = 0, files_1 = files; _a.label = 1; case 1: if (!(_i < files_1.length)) return [3 /*break*/, 4]; f = files_1[_i]; return [4 /*yield*/, this.addFile(f)]; case 2: _a.sent(); _a.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/]; } }); }); }; _this.select = function (id, on) { var selection = _this.state.selection; _this.setState({ selection: __assign({}, selection, (_a = {}, _a[id] = on, _a)) }); var _a; }; _this.removeSelection = function () { return __awaiter(_this, void 0, void 0, function () { var client, selection, ids; return __generator(this, function (_a) { switch (_a.label) { case 0: client = this.context.client; selection = this.state.selection; if (!selection) { return [2 /*return*/]; } ids = Object.keys(selection).filter(function (k) { return selection[k]; }); return [4 /*yield*/, client.update(function (b) { return b.delete.apply(b, ids); })]; case 1: _a.sent(); this.setState({ selection: {} }); return [2 /*return*/]; } }); }); }; _this.state = { orderedValues: null, add: [], remove: [], selection: {}, }; return _this; } ImageProperty.prototype.getValues = function () { var _a = this.state, add = _a.add, remove = _a.remove, orderedValues = _a.orderedValues; if (orderedValues) { return orderedValues; } var values = this.props.values; var vs = (add || []).concat(values); if (remove && remove.length > 0) { vs = vs.filter(function (v) { return remove.indexOf(v.id) === -1; }); } return vs.sort(function (a, b) { return a.pos > b.pos ? 1 : b.pos > a.pos ? -1 : 0; }); }; ImageProperty.prototype.hasSelection = function () { var selection = this.state.selection; if (!selection) { return false; } var ids = Object.keys(selection).filter(function (k) { return selection[k]; }); return ids.length > 0; }; ImageProperty.prototype.render = function () { var _this = this; var property = this.props.property; var selection = this.state.selection; var values = this.getValues(); var items = values.map(function (v, idx) { return (React.createElement(ImageItem, { key: v.id, id: v.id, index: idx, name: v.imageValue.name, srcKey: v.key, selected: selection !== undefined && !!selection[v.id], onSelect: function (on) { return _this.select(v.id, on); }, onRemove: _this.remove, onReorder: _this.move, onDoneReordering: _this.moved })); }); var nav = React.createElement(Buttons_1.default, { icon: true, disabled: true }, utils_1.propertyIconName(graft_db_1.PropertyType.Image)); var actions = []; if (this.hasSelection()) { actions.push(React.createElement(Buttons_1.default, { key: 'remove', icon: true, onClick: this.removeSelection }, "delete")); } actions.push(React.createElement(Buttons_1.default, { icon: true, tooltipLabel: property.hint, tooltipPosition: 'left' }, "help")); return (React.createElement("div", { className: 'md-cell md-cell--12 md-cell--top' }, React.createElement(Toolbars_1.default, { singleColor: true, themed: true, nav: nav, actions: actions, title: property.name, className: 'property-toolbar' }), React.createElement(FileDropZone, { onDrop: this.addFiles }, items))); }; return ImageProperty; }(React.Component)); ImageProperty.contextTypes = WithClient_1.clientContextTypes; exports.ImageProperty = ImageProperty; var fileTarget = { drop: function (props, monitor) { var onDrop = props.onDrop; onDrop(monitor.getItem().files); } }; var FileDropZone = (function (_super) { __extends(FileDropZone, _super); function FileDropZone() { return _super !== null && _super.apply(this, arguments) || this; } FileDropZone.prototype.render = function () { var _a = this.props, dropTarget = _a.dropTarget, isOver = _a.isOver, canDrop = _a.canDrop, children = _a.children; var cs = ['md-grid', 'file-drop-zone']; if (isOver) { cs.push('file-over'); } else if (canDrop) { cs.push('file-over-hint'); } return dropTarget(React.createElement("div", { className: cs.join(' ') }, children, React.createElement("div", { className: 'md-cell md-cell--12 file-drop-placeholder' }, !isOver && !canDrop && 'Drag & Drop Images Here', !isOver && canDrop && 'Over here! Over here!', isOver && "Yes! Drop' um!"))); }; return FileDropZone; }(React.Component)); FileDropZone = __decorate([ react_dnd_1.DropTarget(react_dnd_html5_backend_1.NativeTypes.FILE, fileTarget, function (connect, monitor) { return ({ dropTarget: connect.dropTarget(), isOver: monitor.isOver(), canDrop: monitor.canDrop() }); }) ], FileDropZone); exports.FileDropZone = FileDropZone;