AstroJS/botanjs/src/Astro/Blog/AstroEdit/Article.js

542 lines
13 KiB
JavaScript

(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMObject} */
var IDOMObject = __import( "Dandelion.IDOMObject" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {Astro.Blog.Components.Bubble} */
var Bubble = __import( "Astro.Blog.Components.Bubble" );
var opostData = __import( "System.Net.postData" );
var prettyDate = __import( "Astro.utils.Date.pretty" );
var Visualizer = ns[ NS_INVOKE ]( "Visualizer" );
var Flag = ns[ NS_INVOKE ]( "Flag" );
// Editor Override
var postData = function( processor, data, success, failed )
{
data[ "editor" ] = 1;
opostData( processor, data, success, failed );
};
// Wrappers for every plugins
var PluginBundles = function( article, plugins )
{
this.plugins = plugins;
for( var i in this.plugins )
{
/* @type {Astro.Blog.AstroEdit.IPlugins} */
var g = this.plugins[i];
g.bindArticle = article;
}
};
PluginBundles.prototype.setForView = function( pluginId, data )
{
for( var i in this.plugins )
{
var p = this.plugins[i];
if( p.id == pluginId )
{
p.setForView( data );
}
}
};
PluginBundles.prototype.getData = function( pluginId, data )
{
for( var i in this.plugins )
{
var p = this.plugins[i];
if( p.id == pluginId )
{
return p.getData( data );
}
}
};
var Article = function( processorSet, plugins )
{
var pBubble = new Bubble();
var Draft = ns[ NS_INVOKE ]( "Draft" );
var _title = "";
var _content = "";
//// Classes & obj
var _visualizer = null;
var timestamp = new Date();
/** @type {_AstJson_.AJaxGetArticle.entry} */
var ArticleModel = {
title: ""
, slug: ""
, content: ""
, date_modified: timestamp
, date_published: timestamp
, date_created: timestamp
, archived: false
, tags: null
, section: null
, draft: true
, article_id: false
};
var ae_content = Dand.id( "ae_content" );
var ae_title = Dand.id( "ae_title" );
// Article info
var ae_cdate = Dand.id( "ae_cdate" );
var ae_mdate = Dand.id( "ae_mdate" );
var ae_pdate = Dand.id( "ae_pdate" );
var ae_status = Dand.id( "ae_status" );
var ae_backup = Dand.id( "ae_backup_btn" );
var ae_publish = Dand.id( "ae_publish_btn" );
var ae_preview = Dand.id( "ae_preview" );
/** @type {_AstConf_.AstroEdit} */
var a_conf = Config.get( "AstroEdit" );
var base_path = Config.get( "BasePath" );
/*{{{ preview fields */
var ae_p_fields = {
mtime: set_field_name( Dand.wrap( "input" ), "date_modified" )
, ptime: set_field_name( Dand.wrap( "input" ), "date_published" )
, title: set_field_name( Dand.wrap( "input" ), "title" )
, content: set_field_name( Dand.wrap( "input" ), "content" )
, tags: set_field_name( Dand.wrap( "input" ), "tags" )
, section: set_field_name( Dand.wrap( "input" ), "section" )
};
// Initialize id
var __article_id = false;
var canSave = false;
var temp;
for ( var i in ae_p_fields ) ae_preview.appendChild( ae_p_fields[i] );
/* End preview fields }}}*/
/*{{{ Button sections */
var ae_stitles = Dand.glass( "ae_stitle", true );
var ae_panel_section = Dand.glass( "ae_panel_section", true );
var l = ae_stitles.length;
for( var i = 0; i < l; i ++ )
{
var t = ae_stitles[i];
var p = ae_panel_section[i];
t.addEventListener( "Click", function( e )
{
var p = this.p;
if( this.t.expanded = !this.t.expanded )
{
p.style.height = "auto";
Cycle.next(
function(){
p.style.height = this.h + "px";
}.bind({ h: p.element.clientHeight })
);
p.style.height = 0;
}
else
{
p.style.height = 0;
}
}.bind({ t: t, p: p }) );
}
ae_stitles[0].element.click();
/* End Button sections }}}*/
// Install plugins
plugins = new PluginBundles( this, plugins );
var enableSaveFunction = function ()
{
ae_backup.className = "ae_iValue ae_dodgerblue flsf";
canSave = true;
}
, disableSaveFunction = function ()
{
ae_backup.className = "ae_iValue ae_disabled flsf";
canSave = false;
}
, contentUpdate = function ()
{
if( !canSave ) enableSaveFunction();
// (_visualizer.saveRaw() != _content) ? enableSaveFunction() : disableSaveFunction();
}
//// private methods
////// Handlers ///////
, saveSuccess = function ( obj )
{
disableSaveFunction();
ae_mdate.innerHTML = prettyDate( new Date( obj.date_modified ) );
// Replace state of the content and title
ArticleModel.title = _title;
ArticleModel.content = _content;
ArticleModel.date_modified = obj.date_modified;
// If this is a published article
// we need to set the ref_id for ArticleModel
// then set current id to draft's id
if( ArticleModel.article_id != obj.article_id )
{
ArticleModel.draft = true;
ArticleModel.ref_id = __article_id;
ArticleModel.article_id = obj.article_id;
}
// Set article id if this is a new document
if ( obj.article_id )
ArticleModel.article_id = __article_id = obj.article_id;
window.history.replaceState( ArticleModel, "", base_path + "astroedit/" + __article_id + "/" );
}
, publishSuccess = function ( obj )
{
ae_publish.innerHTML = "Done edit";
ae_backup.innerHTML = "Backup(Ctrl + s)";
ArticleModel.date_published = obj.date_published;
ae_pdate.innerHTML = prettyDate( new Date( obj.date_published ) );
this.contentUpdate && saveSuccess( obj );
new MessageBox(
"AstroEdit"
, "You have successfully published your article!"
, "Stay here", "Exit and goto article"
, publishAction
).show();
}
, publishAction = function ( stay )
{
if ( !stay )
{
window.open( base_path + "article/view/" + ArticleModel.slug + "/") && window.close();
}
}
, restoreArticle = function( obj )
{
debug.Info("[Document] Looking for stored data");
if ( obj )
{
debug.Info("[Document] .. data found");
// Set stored article id
__article_id = obj.article_id;
setArticle( obj );
}
else
{
if (!( ArticleModel && 0 < ArticleModel.article_id ))
{
debug.Info("[Document] .. data not found");
// This is a state of new article
var d = Math.floor(new Date().getTime()/1000);
__article_id = false;
setArticle({
title:""
, content:""
, date_modified: d
, date_published: 0
, date_created: d
, archived: false
, tags: null
, draft: true
, article_id: false
});
window.history.replaceState( ArticleModel, "", base_path + "astroedit/new/" );
}
}
}
/** @param {_AstJson_.AJaxGetArticle} */
, showArticle = function( obj )
{
if ( obj && obj.entry )
{
debug.Info( "[Document] Article Loaded" );
if ( obj.entry.ref_id )
{
// This is a backup item
__article_id = obj.article_id;
pBubble.setColor( "royalblue" );
pBubble.pop( "Using backup entry" );
Cycle.delay( function () { pBubble.blurp() }, 3000 );
}
setArticle( obj.entry );
__statePusher( obj.entry, __article_id );
}
else
{
debug.Info( "[Document] Article: " + String( __article_id ) + " not found on server." );
__article_id = false;
}
}
, setArticle = function ( entry )
{
ArticleModel = entry;
ae_title.value = _title = ArticleModel.title;
_visualizer.visualizeData( _content = ArticleModel.content );
ae_mdate.innerHTML = prettyDate( new Date( ArticleModel.date_modified ) );
ae_cdate.innerHTML = prettyDate( new Date( ArticleModel.date_created ) );
ae_pdate.innerHTML = ArticleModel.date_published
? prettyDate( new Date( ArticleModel.date_published ) )
: "Not published."
;
ae_status.innerHTML =
( ArticleModel.archived ? "Archived. " : "" )
+ ( ArticleModel.draft ? "In draft" : "Published" )
;
ae_publish.innerHTML = ArticleModel.draft ? "Publish" : "Done edit";
ae_backup.innerHTML = ( ArticleModel.draft ? "Save" : "Backup" ) + "(Ctrl + s)";
plugins.setForView( "tags", ArticleModel.tags );
plugins.setForView( "section", ArticleModel.section );
}
, deleteDraft = function ( confirmed )
{
if ( confirmed )
{
var _data = {
"draft": ArticleModel.draft ? 1 : 0
, "article_id": __article_id
, "del": 1
};
postData( processorSet, _data, deleteSuccess, serverFailed );
}
}
, deleteSuccess = function ( obj )
{
var loc = window.location;
loc.replace(
loc.href.replace(
"/" + ArticleModel.article_id
, ArticleModel.ref_id ? ( "/" + ArticleModel.ref_id ) : ""
)
);
}
, serverFailed = function ( obj )
{
pBubble.setColor( "red" );
pBubble.pop( obj ? obj["mesg"] : "Server Error" );
Cycle.delay( function () { pBubble.blurp() }, 3000 );
}
, contentEmpty = function ()
{
return !Boolean( ae_content.hasChildNodes() );
}
;
// Bind properties
this.saveOrBackup = function ()
{
if ( canSave )
{
// Store current content and title
_title = ae_title.value.trim();
_content = _visualizer.saveRaw();
/** @type {_AstJson_.AJaxGetArticle.entry} */
var _data =
{
article_id: __article_id ? __article_id : ""
, title: _title
, content: _content
, draft: 1
, tags: plugins.getData( "tags" )
, section: plugins.getData( "section" )
};
postData( processorSet, _data, saveSuccess, serverFailed );
}
};
this.load = function ( aid, statePusher )
{
if( aid && __article_id != aid )
{
debug.Info( "[Document] Loading article: " + aid );
__statePusher = statePusher;
postData(
a_conf.paths.get_article
, { article_id: __article_id = aid }
, showArticle
, serverFailed
);
}
};
this.getArticleId = function () { return __article_id; }
this.preview = function ()
{
ae_p_fields.title.value = ae_title.value;
ae_p_fields.content.value = _visualizer.saveRaw();
ae_p_fields.mtime.value = ArticleModel.date_modified;
ae_p_fields.ptime.value = Number( ArticleModel.date_published )
? ArticleModel.date_published
: Math.floor( 0.001*( new Date().getTime() ) )
;
ae_p_fields.tags.value = plugins.getData( "tags" );
ae_p_fields.section.value = plugins.getData( "section" );
ae_preview.submit();
};
this.invoke = function (_class)
{
if ( _class instanceof Draft ) _ae_draft = _class;
if ( _class instanceof Visualizer )
{
_visualizer = _class;
_visualizer.setContentDiv( ae_content );
}
};
this.saveAndPublish = function ()
{
if ( contentEmpty() ) return;
/** @type {_AstJson_.AJaxGetArticle.entry} */
var _data = {
article_id: __article_id ? __article_id : ""
, draft: 0
};
if ( !ArticleModel.draft )
{
// This is a published article
canSave = true;
}
if ( canSave )
{
// Store current content and title
_title = ae_title.value.trim();
_content = _visualizer.saveRaw();
_data.title = _title;
_data.content = _content;
_data.tags = plugins.getData( "tags" );
_data.section = plugins.getData( "section" );
postData( processorSet, _data, publishSuccess.bind({ contentUpdate: true }), serverFailed );
}
else
{
// Do not submit uneccessary data!
postData( processorSet, _data, publishSuccess, serverFailed );
}
};
this.drop = function ()
{
if( ArticleModel.draft )
{
new MessageBox(
"Delete draft"
, "Are you sure you want to delete this draft? (Published article will only remove backup draft.)"
, "Delete", "No"
, deleteDraft
).show();
}
else
{
new MessageBox(
"Delete Draft"
, "There is no draft to delete"
).show();
}
};
this.updateContent = contentUpdate;
// Setting Ctrl+s functions
new IDOMObject(document).addEventListener(
new EventKey("KeyDown", function(e)
{
// key Ctrl(17)
if(e.ctrlKey == true && e.which == 83)
{
// key s (83)
this.saveOrBackup();
e.preventDefault();
}
}.bind(this))
);
IDOMElement( ae_backup ).addEventListener( "Click", this.saveOrBackup );
window.addEventListener(
"popstate"
, function( event )
{
debug.Info( "[Document] Pop State fired" );
restoreArticle( event.state );
}
);
ae_title.oninput = function ()
{
( ae_title.value != _title ) ? enableSaveFunction() : disableSaveFunction();
}
temp = IDOMElement(ae_content);
temp.addEventListener( "Input", function() { enableSaveFunction(); } );
document.body.appendChild( pBubble.init() );
return this;
};
var set_field_name = function ( elem, value )
{
elem.name = value;
elem.type = "hidden";
return elem;
};
ns[ NS_EXPORT ]( EX_CLASS, "Article", Article );
})();