226 lines
7.1 KiB
JavaScript
Raw Normal View History

2018-07-17 18:09:59 -04:00
import { fromJS } from 'immutable';
import { remove, attempt, isError, take } from 'lodash';
import uuid from 'uuid/v4';
2018-07-16 23:08:16 -04:00
import EditorialWorkflowError from 'netlify-cms-lib-util/EditorialWorkflowError';
2018-07-17 18:09:59 -04:00
import Cursor, { CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util/Cursor'
import AuthenticationPage from './AuthenticationPage';
window.repoFiles = window.repoFiles || {};
window.repoFilesUnpublished = window.repoFilesUnpublished || [];
function getFile(path) {
const segments = path.split('/');
let obj = window.repoFiles;
while (obj && segments.length) {
obj = obj[segments.shift()];
}
return obj || {};
}
const pageSize = 10;
const getCursor = (collection, extension, entries, index) => {
const count = entries.length;
const pageCount = Math.floor(count / pageSize);
return Cursor.create({
actions: [
...(index < pageCount ? ["next", "last"] : []),
...(index > 0 ? ["prev", "first"] : []),
],
meta: { index, count, pageSize, pageCount },
data: { collection, extension, index, pageCount },
});
};
const getFolderEntries = (folder, extension) => {
return Object.keys(window.repoFiles[folder] || {})
.filter(path => path.endsWith(`.${ extension }`))
.map(path => ({
file: { path: `${ folder }/${ path }` },
data: window.repoFiles[folder][path].content,
}))
.reverse();
};
export default class TestRepo {
constructor(config) {
this.config = config;
this.assets = [];
2018-07-17 18:09:59 -04:00
this.initialStatus = config.initialStatus;
}
authComponent() {
return AuthenticationPage;
}
2017-08-29 13:45:05 -06:00
restoreUser(user) {
return this.authenticate(user);
}
2017-08-29 13:45:05 -06:00
WIP - Global UI (#785) * update top bar and collections sidebar UI * update collection entries UI * improve global layout * merge search page into collection page * enable new entry button * search fixup * wip -initial editor update * update editor scrolling and markdown toolbar position * wip * editor toolbar progress * editor toolbar wip * finished basic editor toolbar * add standalone toggle component * improve markdown toolbar spacing * add user avatar placeholder * finish markdown toggle styling * refactor icon setup, add new icons * add new icons to markdown editor toolbar * remove extra app container * add markdown active mark style * relation and text widget styling * widget design updates, basic list/object design update * widget style updates, image widget improvements * refactor widget directory, fix file removal * widget focus styles * finish editor widget focus styles * migrate media library modal to react-modal * wip - migrate editor component form to modal * wip - move editor component form to modal * wip - embed plugin forms in the editor * inline shortcode forms working * disable react hot loading, its breaking things * improve shortcode form styles * make shortcode form collapsible, improve styling * add close functionality to shortcode blocks * improve base media library styling * fix shortcode label * migrate unstyled workflow to new UI * wip - reorganizing everything * more work moving everything * finish more moving and eliminating stuff * restructure, remove react-toolbox * wip - removing old stuff, more restructure * finish restructure * wip - css arch * switch back to test repo * update react-datetime to ^2.11.0 * remove leftover react-toolbox button * more restructuring clean-up * fix UI component directory case * wip -css editor control style * wip - consolidate widget styles * wip - use a single control renderer * fixed object values breaking * wip - editor control active styles * pass control wrapper to widgets * ensure branch name is trimmed * wip - improve widget authoring support * import Map to Widget component * refactor toolbar buttons * wip - more widget active styles * break out editor toggle component * add local scroll sync back * update editor toggle icons * limit editor control pane content width * fix editor control spacing * migrate markdown toolbar stickiness to css * fix markdown toolbar border radius * temporarily use test backend * stop markdown toolbar from going to bottom * restore disabled markdown toolbar buttons for raw * test markdown widget without focus styles * more widget updates * remove card visuals from editor * disable dragging editor split off screen * use editorControl component for shortcode fields * make header site link configurable * add configurable collection descriptions * temporarily add example assets * add basic list view * remove outdated css mixins * add and implement search icon * activate quick add menu * visualize usable space in editor view * fix entry close, other improvements * wip - editorial workflow updates * some dropshadow and other CSS tweaks * workflow ui updates * add worfklow card buttons * fix workflow card button handlers * some dropshadow and other CSS tweaks * make workflow board wider * center workflow and collection views * add basic responsiveness * a bunch of fun UI fixes! a BUNCH! (#875) * give `.nc-entryEditor-toolbar-mainSection` left and right child divs * a bunch of fun UI fixes! a BUNCH! * remove obscure --buttonShadow * revert to test repo * fix not found page styling * allow workflow publishing from any column * disallow publishing from all columns, with feedback * fix new entry button * fix markdown state persisting across entries * enable simple workflow save and new from editor * update slug in address bar when saving new entry * wip - workflow updates, deletion working * add status change functionality to editor * wip - improving status change from editor * editor toolbar back button improvements, loading improvements, cleanup * progress on the media library UI cleanup * remove font smothing css * a quick fix for these buttons * tweaks * progress on media library modal— broken FYI * fix media library functionality, finish migrating footer * remove media library footer files * remove leftover css import * fix media library * editor publishing functionality complete (unstyled) * remove leftover loader var from media library * wip - editor publishing styles * add status dropdown styling * editor toolbar style updates * editor toolbar state improvements * progress on the media library UI cleanup, style improvements * finish editorial workflow editor styling * finish media library styling * fix config * add what-input to optimize focus styling * fix button * fix navigation blocking for simple workflow * improve simple workflow publishing * add avatar dropdown to editor top bar * style github and test-repo auth pages * add git gateway auth page styles * improve editor error styling
2017-12-07 12:37:10 -05:00
authenticate() {
return Promise.resolve();
}
2017-09-06 18:28:20 -07:00
logout() {
return null;
}
2017-01-10 22:23:22 -02:00
getToken() {
return Promise.resolve('');
}
traverseCursor(cursor, action) {
const { collection, extension, index, pageCount } = cursor.data.toObject();
const newIndex = (() => {
if (action === "next") { return index + 1; }
if (action === "prev") { return index - 1; }
if (action === "first") { return 0; }
if (action === "last") { return pageCount; }
})();
// TODO: stop assuming cursors are for collections
const allEntries = getFolderEntries(collection.get('folder'), extension);
const entries = allEntries.slice(newIndex * pageSize, (newIndex * pageSize) + pageSize);
const newCursor = getCursor(collection, extension, allEntries, newIndex);
return Promise.resolve({ entries, cursor: newCursor });
}
2017-04-14 19:19:45 +01:00
entriesByFolder(collection, extension) {
const folder = collection.get('folder');
const entries = folder ? getFolderEntries(folder, extension) : [];
const cursor = getCursor(collection, extension, entries, 0);
const ret = take(entries, pageSize);
ret[CURSOR_COMPATIBILITY_SYMBOL] = cursor;
return Promise.resolve(ret);
}
entriesByFiles(collection) {
const files = collection.get('files').map(collectionFile => ({
path: collectionFile.get('file'),
label: collectionFile.get('label'),
}));
return Promise.all(files.map(file => ({
file,
data: getFile(file.path).content,
})));
}
getEntry(collection, slug, path) {
return Promise.resolve({
file: { path },
2017-01-10 22:23:22 -02:00
data: getFile(path).content,
});
}
unpublishedEntries() {
return Promise.resolve(window.repoFilesUnpublished);
}
unpublishedEntry(collection, slug) {
const entry = window.repoFilesUnpublished.find(e => (
e.metaData.collection === collection.get('name') && e.slug === slug
));
if (!entry) {
return Promise.reject(new EditorialWorkflowError('content is not under editorial workflow', true));
}
return Promise.resolve(entry);
}
deleteUnpublishedEntry(collection, slug) {
const unpubStore = window.repoFilesUnpublished;
const existingEntryIndex = unpubStore.findIndex(e => (
e.metaData.collection === collection && e.slug === slug
));
unpubStore.splice(existingEntryIndex, 1);
return Promise.resolve();
}
persistEntry({ path, raw, slug }, mediaFiles = [], options = {}) {
2018-07-17 18:09:59 -04:00
if (options.useWorkflow) {
const unpubStore = window.repoFilesUnpublished;
const existingEntryIndex = unpubStore.findIndex(e => e.file.path === path);
if (existingEntryIndex >= 0) {
const unpubEntry = { ...unpubStore[existingEntryIndex], data: raw };
unpubEntry.title = options.parsedData && options.parsedData.title;
unpubEntry.description = options.parsedData && options.parsedData.description;
unpubStore.splice(existingEntryIndex, 1, unpubEntry);
} else {
const unpubEntry = {
data: raw,
file: {
path,
},
metaData: {
collection: options.collectionName,
2018-07-17 18:09:59 -04:00
status: this.initialStatus,
title: options.parsedData && options.parsedData.title,
description: options.parsedData && options.parsedData.description,
},
slug,
};
unpubStore.push(unpubEntry);
}
return Promise.resolve();
}
const newEntry = options.newEntry || false;
const folder = path.substring(0, path.lastIndexOf('/'));
const fileName = path.substring(path.lastIndexOf('/') + 1);
window.repoFiles[folder] = window.repoFiles[folder] || {};
window.repoFiles[folder][fileName] = window.repoFiles[folder][fileName] || {};
if (newEntry) {
window.repoFiles[folder][fileName] = { content: raw };
} else {
window.repoFiles[folder][fileName].content = raw;
}
return Promise.resolve();
}
2016-09-06 13:04:17 -03:00
updateUnpublishedEntryStatus(collection, slug, newStatus) {
const unpubStore = window.repoFilesUnpublished;
const entryIndex = unpubStore.findIndex(e => (
e.metaData.collection === collection && e.slug === slug
));
unpubStore[entryIndex].metaData.status = newStatus;
return Promise.resolve();
}
publishUnpublishedEntry(collection, slug) {
const unpubStore = window.repoFilesUnpublished;
const unpubEntryIndex = unpubStore.findIndex(e => (
e.metaData.collection === collection && e.slug === slug
));
const unpubEntry = unpubStore[unpubEntryIndex];
const entry = { raw: unpubEntry.data, slug: unpubEntry.slug, path: unpubEntry.file.path };
unpubStore.splice(unpubEntryIndex, 1);
return this.persistEntry(entry);
}
getMedia() {
return Promise.resolve(this.assets);
}
persistMedia({ fileObj }) {
const { name, size } = fileObj;
const objectUrl = attempt(window.URL.createObjectURL, fileObj);
const url = isError(objectUrl) ? '' : objectUrl;
const normalizedAsset = { id: uuid(), name, size, path: url, url };
this.assets.push(normalizedAsset);
return Promise.resolve(normalizedAsset);
}
deleteFile(path, commitMessage) {
const assetIndex = this.assets.findIndex(asset => asset.path === path);
if (assetIndex > -1) {
this.assets.splice(assetIndex, 1);
}
else {
const folder = path.substring(0, path.lastIndexOf('/'));
const fileName = path.substring(path.lastIndexOf('/') + 1);
delete window.repoFiles[folder][fileName];
}
return Promise.resolve();
}
}