@prisma-cms/front-editor
Version:
429 lines • 20.4 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Editable = void 0;
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable react/forbid-foreign-prop-types */
const react_1 = __importDefault(require("react"));
const prop_types_1 = __importDefault(require("prop-types"));
const EditorComponent_1 = __importDefault(require("../../../EditorComponent"));
const apollo_cms_1 = require("apollo-cms");
const ListView_1 = require("../../Connectors/Connector/ListView");
const context_1 = require("../../../context");
const Query_1 = __importDefault(require("../../Connectors/Query"));
// import { graphql } from 'react-apollo';
const graphql_tag_1 = __importDefault(require("graphql-tag"));
const graphql_1 = require("graphql");
const path_to_regexp_1 = __importDefault(require("path-to-regexp"));
const IconButton_1 = __importDefault(require("material-ui/IconButton"));
const CircularProgress_1 = __importDefault(require("material-ui/Progress/CircularProgress"));
const Delete_1 = __importDefault(require("material-ui-icons/Delete"));
// TODO Fix for new EditableObject
class Editable extends apollo_cms_1.EditableObject {
constructor(props) {
super(props);
this.delete = this.delete.bind(this);
}
updateObject(data) {
for (const i in data) {
const value = data[i];
if (value === '') {
data[i] = null;
}
}
return super.updateObject(data);
}
mutate(props, method) {
const _super = Object.create(null, {
mutate: { get: () => super.mutate }
});
return __awaiter(this, void 0, void 0, function* () {
/**
Prepare Mutation
*/
const { query_components: children, getQueryNameFromQuery, extendQuery, } = this.props;
const queries = {};
const { id: objectId } = this.getObject() || {};
children &&
children.length &&
children
.filter((n) => n)
.map((n) => {
const { type, props } = n;
if (type === Query_1.default) {
const { query } = (props && props.props) || {};
if (query) {
const queryName = getQueryNameFromQuery(query);
if (queryName) {
queries[queryName] = query;
}
}
}
return null;
});
if (!method) {
method = objectId ? 'update' : 'create';
}
let mutation = queries && method ? queries[method] : null;
if (!mutation) {
const error = new Error('Can not get mutation');
return this.addError(error);
}
/**
Eof Prepare Mutation
*/
try {
const extendedQuery = extendQuery(mutation);
mutation = graphql_tag_1.default(extendedQuery);
}
catch (error) {
console.error(error);
}
return _super.mutate.call(this, Object.assign(Object.assign({}, props), { mutation }));
});
}
renderEditableView() {
const { children } = this.props;
return children;
}
renderDefaultView() {
const { children } = this.props;
return children;
}
renderHeader() {
const { show_header } = this.props;
return show_header ? super.renderHeader() : null;
}
getButtons() {
const { id: objectId } = this.getObject() || {};
const buttons = super.getButtons() || [];
if (this.inEditMode() && objectId) {
buttons.push(this.renderDeleteButton());
}
return buttons;
}
renderDeleteButton() {
const { DeleteIcon, deletable_object } = this.props;
const { loading } = this.state;
return deletable_object ? (react_1.default.createElement(IconButton_1.default, { key: "delete", onClick: this.delete, disabled: loading }, loading ? react_1.default.createElement(CircularProgress_1.default, null) : react_1.default.createElement(DeleteIcon, null))) : null;
}
delete() {
const { id: objectId } = this.getObject() || {};
if (objectId) {
if (window.confirm('Удалить данный объект?')) {
return this.mutate({
variables: {
where: {
id: objectId,
},
},
}, 'delete').then((r) => {
const { on_delete_redirect_url } = this.props;
if (on_delete_redirect_url) {
const { router: { history }, } = this.context;
history.push(decodeURIComponent(on_delete_redirect_url));
}
return r;
});
}
}
}
render() {
const _a = this.props, {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_dirty: _dirty_null } = _a, other = __rest(_a, ["_dirty"]);
const { loading, _dirty, errors, notifications } = this.state;
const fieldErrors = {};
if (errors && errors.length) {
errors.map(({ key, message }) => {
fieldErrors[key] = message;
return null;
});
}
const object = this.getObjectWithMutations();
return (react_1.default.createElement(context_1.EditableObjectContext.Provider, { value: Object.assign({
// getCacheKey: this.getCacheKey,
updateObject: this.updateObject, getEditor: this.getEditor, inEditMode: this.inEditMode(), canEdit: this.canEdit(), getObjectWithMutations: this.getObjectWithMutations, getObject: this.getObject, getButtons: this.getButtons, save: this.save, mutate: this.mutate, loading,
_dirty,
errors,
fieldErrors,
notifications }, other) },
react_1.default.createElement(ListView_1.ObjectContext.Provider, { value: {
object: this.getObjectWithMutations(),
} }, super.render())));
}
}
exports.Editable = Editable;
Editable.propTypes = Object.assign(Object.assign({}, apollo_cms_1.EditableObject.propTypes), { show_header: prop_types_1.default.bool.isRequired, extendQuery: prop_types_1.default.func.isRequired, getQueryNameFromQuery: prop_types_1.default.func.isRequired, query_components: prop_types_1.default.array.isRequired, DeleteIcon: prop_types_1.default.func.isRequired, deletable_object: prop_types_1.default.bool.isRequired, on_delete_redirect_url: prop_types_1.default.string, data: prop_types_1.default.object });
Editable.defaultProps = Object.assign(Object.assign({}, apollo_cms_1.EditableObject.defaultProps), { show_header: true, DeleteIcon: Delete_1.default, deletable_object: false });
class EditableObject extends EditorComponent_1.default {
constructor(props) {
super(props);
this.onBeforeDrop = () => {
return;
};
// onUpdateObject(result) {
// return result;
// }
/**
* Расширяем запрос
*/
this.extendQueryBind = (Query) => this.extendQuery(Query);
this.state = Object.assign(Object.assign({}, this.state), { object_key: Math.random() });
this.onCreateObject = this.onCreateObject.bind(this);
this.onSaveObject = this.onSaveObject.bind(this);
}
renderPanelView(content) {
return super.renderPanelView(content || react_1.default.createElement("div", { className: 'panelEditableObject' }, "EditableObject"));
}
getEditableClass() {
return Editable;
}
/**
* Позволяет переопределить редактируемый объект,
* например, чтобы создавать новый внутри имеющегося
*/
prepareEditableObject(object) {
const { create_as_a_child_of } = this.getComponentProps(this);
return create_as_a_child_of ? {} : object;
}
/**
* Этот метод не модифицирует сам редактируемые объект,
* а только формирует параметры для класса Editable
*/
prepareObject(context) {
return {
_dirty: this.getDirty(context),
};
}
getDirty(context) {
let { _dirty } = context;
const { object } = context;
const { create_as_a_child_of } = this.getComponentProps(this);
const { id: objectId } = object || {};
if (create_as_a_child_of) {
_dirty = _dirty
? Object.assign({}, _dirty) : {};
Object.assign(_dirty, {
[create_as_a_child_of]: {
connect: {
id: objectId,
},
},
});
}
return _dirty;
}
onCreateObject(result) {
const { on_create_redirect_url } = this.getComponentProps(this);
if (on_create_redirect_url) {
const { response } = result.data || {};
const { data: object } = response || {};
if (object) {
const toPath = path_to_regexp_1.default.compile(on_create_redirect_url);
try {
const url = toPath(object, { noValidate: true });
if (url) {
const { router: { history }, } = this.context;
history.push(decodeURIComponent(url));
}
}
catch (error) {
console.error(error);
}
}
}
return;
}
onSaveObject(result) {
const { random_key } = this.getComponentProps(this);
if (random_key) {
this.setState({
object_key: Math.random(),
});
}
return this.onCreateObject(result);
}
extendQuery(Query) {
const { schema } = this.context;
if (Query && schema) {
/**
* Проходим запрос на предмет директив в фрагментах
*/
const parsedQuery = graphql_1.parse(Query);
if (parsedQuery && schema) {
const { types } = schema;
const { definitions } = parsedQuery;
if (definitions && definitions.length) {
definitions.reduceRight((current, definition) => {
const { kind, directives, selectionSet: { loc: { end }, }, typeCondition, } = definition;
if (kind === 'FragmentDefinition' && typeCondition) {
const needAutoloadFields = directives &&
directives.find((n) => n && n.name && n.name.value === 'prismaCmsFragmentAllFields')
? true
: false;
if (needAutoloadFields) {
const {
// kind,
name: { value: type }, } = typeCondition;
if (type) {
const field = types.find((n) => {
const { kind, name } = n;
return kind === 'OBJECT' && name === type;
});
if (field) {
let { fields } = field;
fields = fields.filter((n) => {
return n && n.name && this.isScalar(n) ? true : false;
});
/**
* Если были получены скалярные поля,
* добавляем их в запрос
*/
if (fields.length) {
const fieldsList = '\n' + fields.map(({ name }) => name).join('\n') + '\n';
const position = end - 1;
Query = [
Query.slice(0, position),
fieldsList,
Query.slice(position),
].join('');
}
}
}
}
}
return current;
}, []);
}
}
}
return Query;
}
isScalar(field) {
const { type: { kind, ofType }, } = field;
if (kind === 'SCALAR') {
return true;
}
else if (kind === 'ENUM') {
return true;
}
else if ((kind === 'NON_NULL' || kind === 'LIST') && ofType) {
return this.isScalar({
type: ofType,
});
}
else {
return false;
}
}
getQueryNameFromQuery(query) {
try {
const parsedSchema = graphql_1.parse(query);
if (parsedSchema) {
const { definitions } = parsedSchema;
if (definitions) {
const OperationDefinition = definitions.find((n) => n.kind === 'OperationDefinition');
if (OperationDefinition) {
const { value } = OperationDefinition.name || {};
return value;
}
}
}
}
catch (error) {
console.error(error);
}
}
renderChildren() {
// const {
// inEditMode,
// } = this.getEditorContext();
const children = super.renderChildren();
const _a = this.getComponentProps(this), { on_create_redirect_url, props, data, components, style, cache_key, cache_key_prefix, new_object_cache_key, object, random_key } = _a,
// _dirty,
other = __rest(_a, ["on_create_redirect_url", "props", "data", "components", "style", "cache_key", "cache_key_prefix", "new_object_cache_key", "object", "random_key"]);
const { object_key } = this.state;
const Editable = this.getEditableClass();
return (react_1.default.createElement(ListView_1.ObjectContext.Consumer, { key: "editable_object" }, (context) => {
const { object, loading } = context;
/**
Если объекта нет и еще выполняется загрузка,
прерываем рендерер.
Иначе объект будет инициализирован как новый, то есть в режиме редактирования со свойством _dirty
*/
if (!object && loading) {
return null;
}
/**
* Здесь есть возможность переопределить объект
*/
const editableObject = this.prepareEditableObject(object);
const { id: objectId } = editableObject || {};
const cacheKey = cache_key !== undefined
? cache_key
: new_object_cache_key && !objectId
? new_object_cache_key
: undefined;
const cacheKeyPrefix = cache_key_prefix;
return (react_1.default.createElement(Editable, Object.assign({ key: random_key ? object_key : undefined,
// data={{
// object: object || {},
// }}
object: editableObject, extendQuery: this.extendQueryBind,
// extendQuery={(query) => this.extendQuery(query)}
getQueryNameFromQuery: this.getQueryNameFromQuery, query_components: children, onSave: !objectId ? this.onSaveObject : null, cacheKey: cacheKey, cacheKeyPrefix: cacheKeyPrefix }, this.prepareObject(context), other), children));
}));
}
}
EditableObject.propTypes = Object.assign(Object.assign({}, EditorComponent_1.default.propTypes), { deletable_object: prop_types_1.default.bool.isRequired,
/**
* Если новый объект создается как дочерний от другого объекта,
* то можно указать имя родителя, чтобы сформировать конструкцию [parent_name]: {connect: parent_id}.
* Важно! Если выставить это свойство, будет создан именно новый объект,
* даже если это имеющийся уже объект (объект будет перетерт).
*/
create_as_a_child_of: prop_types_1.default.string,
/**
* При рендеринге создает новый ключ для рендеринга Editable.
* Это удобно, когда надо обновить данные
* при сохранении нового объекта без перезагрузки страницы.
* Важно! В режиме редактирования шаблонов передача меняемого key
* ломает вывод элементов, поэтому этот параметр следует использовать очень осторожно.
*/
random_key: prop_types_1.default.bool });
EditableObject.defaultProps = Object.assign(Object.assign({}, EditorComponent_1.default.defaultProps), { style: Object.assign(Object.assign({}, EditorComponent_1.default.defaultProps.style), { flexBasis: '100%' }),
/**
* УРЛ, куда редиректить при создании нового объекта
*/
on_create_redirect_url: undefined,
/**
* Куда редиректить при успешном удалении элемента
*/
on_delete_redirect_url: undefined, cache_key: undefined, cache_key_prefix: undefined, new_object_cache_key: undefined, show_header: true, hide_wrapper_in_default_mode: true, deletable_object: false, create_as_a_child_of: undefined, random_key: false });
EditableObject.Name = 'EditableObject';
EditableObject.help_url = 'https://front-editor.prisma-cms.com/topics/editableobject.html';
exports.default = EditableObject;
//# sourceMappingURL=index.js.map