Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • oss/minerva/grapesjs-project-manager
1 result
Show changes
import indexeddb from './indexeddb';
import remote from './remote';
import firestore from './firestore';
export default (editor, opts = {}) => {
// Load indexeddb storage
indexeddb(editor, opts);
// Load remote storage
remote(editor, opts);
// Load firestore storage
firestore(editor, opts);
}
\ No newline at end of file
import { storageIDB } from '../consts';
export default (editor, opts = {}) => {
let db;
const sm = editor.StorageManager;
const storageName = storageIDB;
const objsName = opts.objectStoreName;
// Functions for DB retrieving
const getDb = () => db;
const getAsyncDb = (clb) => {
if (db) {
clb(db);
} else {
const indexedDB = window.indexedDB || window.mozIndexedDB ||
window.webkitIndexedDB || window.msIndexedDB;
const request = indexedDB.open(opts.dbName, opts.indexeddbVersion);
const onError = () => sm.onError(storageName, request.errorCode);
request.onerror = onError;
request.onsuccess = () => {
db = request.result;
db.onerror = onError;
clb(db);
};
request.onupgradeneeded = e => {
const objs = e.currentTarget.result.createObjectStore(objsName, { keyPath: 'id' });
objs.createIndex('name', 'name', { unique: false });
};
}
};
// Functions for object store retrieving
const getObjectStore = () => {
return db.transaction([objsName], 'readwrite').objectStore(objsName);
};
const getAsyncObjectStore = clb => {
if (db) {
clb(getObjectStore());
} else {
getAsyncDb(db => clb(getObjectStore()))
}
};
// Add custom storage to the editor
sm.add(storageName, {
currentName: 'Default',
currentId: 'uuidv4',
currentThumbnail: '',
isTemplate: false,
description: 'No description',
getDb,
getObjectStore,
setId(id) {
this.currentId = id;
},
setName(name) {
this.currentName = name;
},
setThumbnail(thumbnail) {
this.currentThumbnail = thumbnail;
},
setIsTemplate(isTemplate) {
this.isTemplate = !!isTemplate;
},
setDescription(description) {
this.description = description;
},
load(keys, clb, clbErr) {
getAsyncObjectStore(objs => {
const request = objs.get(this.currentId);
request.onerror = clbErr;
request.onsuccess = () => {
clb && clb(request.result);
};
});
},
loadAll(clb, clbErr) {
getAsyncObjectStore(objs => {
const request = objs.getAll();
request.onerror = clbErr;
request.onsuccess = () => {
clb && clb(request.result);
};
});
},
store(data, clb, clbErr) {
getAsyncObjectStore(objs => {
const request = objs.put({
id: this.currentId,
name: this.currentName,
template: this.isTemplate,
thumbnail: this.currentThumbnail,
description: this.description,
updated_at: Date(),
...data
});
request.onerror = clbErr;
request.onsuccess = clb;
});
},
update(data, clb, clbErr) {
const { id, ..._data } = data;
getAsyncObjectStore(objs => {
const request = objs.get(id);
request.onerror = clbErr;
request.onsuccess = () => {
objs.put({ id, ...request.result, ..._data });
clb && clb(request.result);
};
});
},
delete(clb, clbErr, index) {
getAsyncObjectStore(objs => {
const request = objs.delete(index || this.currentId);
request.onerror = clbErr;
request.onsuccess = clb;
});
}
});
}
\ No newline at end of file
import { storageRemote } from '../consts';
export default (editor, opts = {}) => {
const sm = editor.StorageManager;
const storageName = storageRemote;
const remote = sm.get('remote');
// Add custom storage to the editor
sm.add(storageName, {
currentName: 'Default',
currentId: 'uuidv4',
currentThumbnail: '',
isTemplate: false,
description: 'No description',
setId(id) {
this.currentId = id;
},
setName(name) {
this.currentName = name;
},
setThumbnail(thumbnail) {
this.currentThumbnail = thumbnail;
},
setIsTemplate(isTemplate) {
this.isTemplate = !!isTemplate;
},
setDescription(description) {
this.description = description;
},
load(keys, clb, clbErr) {
const urlLoad = remote.get('urlLoad');
const id = urlLoad.endsWith('/') ? this.currentId : `/${this.currentId}`;
remote.set({ urlLoad: urlLoad + id });
remote.load(keys, clb, clbErr);
remote.set({ urlLoad });
},
loadAll(clb, clbErr) {
remote.load({}, clb, clbErr);
},
store(data, clb, clbErr) {
const urlStore = remote.get('urlStore');
const id = urlStore.endsWith('/') ? this.currentId : `/${this.currentId}`;
opts.uuidInPath && remote.set({ urlStore: urlStore + id });
remote.store({
id: this.currentId,
name: this.currentName,
template: this.isTemplate,
thumbnail: this.currentThumbnail,
description: this.description,
updated_at: Date(),
...data
}, clb, clbErr);
remote.set({ urlStore });
},
update(data, clb, clbErr) {
const urlLoad = remote.get('urlLoad');
let { id } = data;
id = urlLoad.endsWith('/') ? id : `/${id}`;
remote.set({ urlLoad: urlLoad + id });
remote.load({}, res => {
const body = { ...res, ...data };
const method = 'post';
const urlUpdate = remote.get('urlStore');
id = data.id;
id = urlUpdate.endsWith('/') ? id : `/${id}`;
remote.request(urlUpdate + id, { method, body }, clb, clbErr);
}, clbErr);
remote.set({ urlLoad });
},
delete(clb, clbErr, index) {
const urlDelete = remote.get('urlDelete');
let id = index || this.currentId;
id = urlDelete.endsWith('/') ? id : `/${id}`;
remote.request(urlDelete + id, { method: 'delete' }, clb, clbErr);
}
});
}
\ No newline at end of file
/* Class names prefixes */
$prefix: 'gjs-' !default;
/* Main color */
$mainColor: #936a9b;
:root {
--border-color: rgba(0, 0, 0, 0.15);
--background-color: #3c4a49;
--background-box-title: #263332;
}
.app {
margin: 20px;
margin-top: 30px;
animation: fadein .3s;
a {
text-decoration: none;
color: $mainColor;
}
h1 {
margin-bottom: 30px;
}
h2 {
color: $mainColor;
}
button {
cursor: pointer;
background-color: #424242;
font-family: inherit;
color: #fff;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 15px;
border: 1px solid #e9ebeb;
border-bottom-color: #e1e3e3;
border-radius: 4px;
background-color: #fff;
color: rgba(14, 30, 37, .87);
box-shadow: 0 2px 4px 0 rgba(14, 30, 37, .12);
transition: all .2s ease;
transition-property: background-color, color, border, box-shadow;
outline: 0;
font-weight: 500;
background: $mainColor;
color: #fff;
border-color: transparent;
}
}
.title-inner {
display: flex;
align-items: center;
button {
margin-left: 20px;
}
}
.primary-button {
padding: 13px 18px;
&:hover {
background: #73308d;
}
}
.flex-row {
display: flex;
justify-content: space-between;
align-items: center;
button {
height: 45px;
}
}
.tm-input {
border-radius: 2px;
font-size: 16px;
padding: 11px 15px;
min-width: 300px;
display: inline-block;
box-shadow: 0 0 0 2px rgba(120, 130, 152, .25);
border: none;
outline: none;
transition: all .3s ease;
margin: 20px 0;
color: white;
background-color: rgba(0, 0, 0, 0.2);
&:active,
&:focus,
&:hover {
box-shadow: 0 0 0 2px $mainColor;
}
&.sm {
width: 100%;
min-width: 0;
font-size: 12px;
margin: 10px 0;
padding: 8px 10px;
}
}
.header {
cursor: pointer;
font-weight: bold;
font-size: 16px !important;
}
.item {
text-align: center;
}
#site-list {
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
}
.site-wrapper,
.site-wrapper-header {
display: flex;
align-items: center;
padding: 10px 0;
padding-left: 20px;
font-size: 14px;
transition: .3s;
}
.site-wrapper.selected {
border: 2px solid $mainColor;
}
.site-wrapper.open,
.site-wrapper:nth-child(even).open {
background-color: rgba(147, 106, 155, .2);
}
.site-wrapper-header {
padding-left: 15px;
border-bottom: 2px solid rgba(14, 30, 37, .2);
}
.site-wrapper:hover,
.site-wrapper:nth-child(even):hover {
background: rgba(255, 255, 255, .1);
}
.site-wrapper-header,
.site-wrapper:nth-child(even) {
background-color: rgba(0, 0, 0, .1);
}
.site-screenshot,
.site-screenshot-header {
height: 64px;
margin: 0 24px 0 0;
min-width: 102.4px;
position: relative;
overflow: hidden;
}
.site-screenshot-header {
height: 30px;
}
.site-screenshot:before {
background: #dadcdd;
bottom: 0;
content: " ";
left: 0;
position: absolute;
right: 0;
top: 0;
}
.site-screenshot a {
display: block;
position: relative;
z-index: 9;
height: 100%;
}
.site-screenshot img {
position: relative;
width: 100%;
width: 102.4px;
border: none;
}
.site-screenshot img[alt]:after {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #dadcdd;
font-weight: 300;
line-height: 2;
text-align: center;
content: '';
}
.site-info {
min-width: 250px;
max-width: 250px;
h2 {
margin: 0px;
margin-bottom: 5px;
}
a {
text-decoration: none;
}
}
.site-meta a {
font-size: 14px;
color: rgba(165, 210, 230, 0.8);
}
.site-update-time {
min-width: 150px;
}
.site-create-time {
min-width: 130px;
}
.site-pages,
.site-size {
min-width: 80px;
}
.site-actions {
min-width: 200px;
i {
color: $mainColor;
background-color: rgba(0, 0, 0, 0.1);
border: 1px solid $mainColor;
border-radius: 2px;
padding: 5px;
cursor: pointer;
&:hover {
background-color: $mainColor;
color: white;
}
}
}
.#{$prefix}templates-overlay {
position: absolute;
pointer-events: none;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.05);
}
.#{$prefix}mdl-dialog-tml {
max-width: 1000px;
margin-top: 45px;
}
.#{$prefix}mdl-dialog-md {
max-width: 400px;
margin-top: 45px;
}
.#{$prefix}tip-about {
padding: 10px;
font-size: .9rem;
border: 1px solid rgba(0, 0, 0, 0.2);
border-left: 3px solid $mainColor;
background-color: rgba(0, 0, 0, 0.1);
margin-bottom: 10px;
}
.#{$prefix}tab {
overflow: hidden;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
margin-bottom: 10px;
button {
background-color: inherit;
color: inherit;
float: left;
border: 1px solid rgba(0, 0, 0, 0.1);
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: .3s;
&:hover {
background-color: rgba(0, 0, 0, 0.1);
}
&.active {
background-color: rgba(0, 0, 0, 0.2);
}
}
}
.pages-wrp,
.pages {
display: flex;
flex-direction: column;
}
.pages-wrp {
padding: 5px;
}
.pages-title {
padding: 5px;
margin: 0;
border-bottom: 1px solid rgba(0, 0, 0, .1);
}
.add-page {
background: $mainColor;
color: white;
font-size: 12px;
padding: 8px 5px;
border-radius: 2px;
cursor: pointer;
white-space: nowrap;
margin-bottom: 10px;
}
.page {
font-size: 12px;
text-align: left;
padding: 5px;
margin-bottom: 5px;
border-radius: 2px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 1px 0 0 rgb(0, 0, 0, .15);
transition: all .2s ease 0s;
transition-property: box-shadow, color;
cursor: pointer;
&:hover {
color: $mainColor;
box-shadow: 0 3px 4px 0 rgb(0, 0, 0, .15);
}
&.selected {
color: $mainColor;
border: 1px solid $mainColor;
background-color: rgba(0, 0, 0, .1);
}
}
.page-edit,
.page-close {
opacity: .5;
float: right;
background-color: rgba(0, 0, 0, .1);
border: 1px solid rgba(0, 0, 0, .2);
height: 17px;
width: 17px;
text-align: center;
border-radius: 3px;
&:hover {
opacity: 1;
}
}
.page-edit {
margin-right: 5px;
}
.group {
margin-bottom: 15px;
input {
padding: 0;
height: initial;
width: initial;
margin-bottom: 0;
display: none;
cursor: pointer;
&:checked+label:after {
content: '';
display: block;
position: absolute;
top: 2px;
left: 9px;
width: 6px;
height: 14px;
border: solid $mainColor;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
}
label {
position: relative;
cursor: pointer;
&:before {
content: '';
-webkit-appearance: none;
background-color: transparent;
border: 2px solid $mainColor;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0px -15px 10px -12px rgba(0, 0, 0, 0.05);
padding: 10px;
display: inline-block;
position: relative;
vertical-align: middle;
cursor: pointer;
margin-right: 5px;
}
}
}
@keyframes fadein {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
\ No newline at end of file
export function objSizeMegaBytes(obj) {
return objSizeBytes(obj) / (1024 * 1024);
}
export default function objSizeKiloBytes(obj) {
return objSizeBytes(obj) / 1024;
}
export function objSizeBytes(obj) {
return new TextEncoder().encode(JSON.stringify(obj)).length;
}
\ No newline at end of file
// https://github.com/netlify-labs/oauth-example/blob/master/source/utils/sort.js
// License MIT
import objSize from './objsize';
export function matchText(search, text) {
if (!text || !search) {
return false
}
return text.toLowerCase().indexOf(search.toLowerCase()) > -1
}
export function sortByDate(dateType, order) {
return function (a, b) {
const timeA = new Date(a[dateType]).getTime()
const timeB = new Date(b[dateType]).getTime()
if (order === 'asc') {
return timeA - timeB
}
// default 'desc' descending order
return timeB - timeA
}
}
export function sortByName(key, order) {
return function (a, b) {
if (order === 'asc') {
if (a[key] < b[key]) return -1
if (a[key] > b[key]) return 1
}
if (a[key] > b[key]) return -1
if (a[key] < b[key]) return 1
return 0
}
}
export function sortByPages(key, order) {
return function (a, b) {
const pagesA = JSON.parse(a[key]);
const pagesB = JSON.parse(b[key]);
if (order === 'desc') {
if (pagesA.length < pagesB.length) return -1
if (pagesA.length > pagesB.length) return 1
}
if (pagesA.length > pagesB.length) return -1
if (pagesA.length < pagesB.length) return 1
return 0
}
}
export function sortBySize(order) {
return function (a, b) {
const sizeA = objSize(a);
const sizeB = objSize(b);
if (order === 'asc') {
if (sizeA < sizeB) return -1
if (sizeA > sizeB) return 1
}
if (sizeA > sizeB) return -1
if (sizeA < sizeB) return 1
return 0
}
}
\ No newline at end of file
export default function timeago(date, short) {
const obj = {
second: 1000,
minute: 60 * 1000,
hour: 60 * 1000 * 60,
day: 24 * 60 * 1000 * 60,
week: 7 * 24 * 60 * 1000 * 60,
month: 30 * 24 * 60 * 1000 * 60,
year: 365 * 24 * 60 * 1000 * 60,
}
const { round } = Math,
dir = ' ago',
pl = function (v, n) {
return (short === undefined) ? `${n} ${v + (n > 1 ? 's' : '') + dir}` : n + v.substring(0, 1)
},
ts = Date.now() - new Date(date).getTime();
let ii;
if (ts < 0) {
ts *= -1;
dir = ' from now';
}
for (var i in obj) {
if (round(ts) < obj[i]) return pl(ii || 'm', round(ts / (obj[ii] || 1)))
ii = i;
}
return pl(i, round(ts / obj[i]));
}
\ No newline at end of file
export default class UI {
constructor(editor, opts = {}) {
this.editor = editor;
this.$ = editor.$;
this.pfx = editor.getConfig('stylePrefix');
this.id = editor.Storage.getConfig().id;
this.opts = opts;
this.setState = this.setState.bind(this);
this.setStateSilent = this.setStateSilent.bind(this);
this.onRender = this.onRender.bind(this);
this.handleTabs = this.handleTabs.bind(this);
}
setState(state) {
this.state = { ...this.state, ...state };
this.update();
}
setStateSilent(state) {
this.state = { ...this.state, ...state };
}
get sm() {
return this.editor.Storage;
}
get cs() {
return this.editor.Storage.getCurrentStorage();
}
get pm() {
return this.editor.Pages;
}
onRender() { }
handleTabs() { }
}
\ No newline at end of file
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const pkg = require('./package.json');
const webpack = require('webpack');
const fs = require('fs');
const name = pkg.name;
let plugins = [];
let optimization = {};
module.exports = (env = {}) => {
if (env.production) {
optimization.minimizer = [
new TerserPlugin({
parallel: true,
})
];
plugins = [
new webpack.BannerPlugin(`${name} - ${pkg.version}`),
]
} else {
const index = 'index.html';
const indexDev = '_' + index;
plugins.push(new HtmlWebpackPlugin({
template: fs.existsSync(indexDev) ? indexDev : index
}));
}
return {
mode: env.production ? 'production' : 'development',
entry: './source',
output: {
filename: `./${name}.min.js`,
library: name,
libraryTarget: 'umd',
},
module: {
rules: [
{
test: /\.js$/,
include: /source/,
use: {
loader: 'babel-loader',
}
},
],
},
externals: {'grapesjs': 'grapesjs'},
optimization: optimization,
plugins: plugins,
watchOptions: {
ignored: /node_modules/
}
};
};