Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
18
Merge Requests
18
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
jio
Commits
31e65d17
Commit
31e65d17
authored
Dec 14, 2012
by
Sven Franck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added revision management, POST working, PUT partially
parent
2c7d952d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
808 additions
and
143 deletions
+808
-143
examples/complex_example.html
examples/complex_example.html
+1
-0
src/jio.dummystorages.js
src/jio.dummystorages.js
+39
-3
src/jio.storage/localstorage.js
src/jio.storage/localstorage.js
+472
-84
src/jio/commands/command.js
src/jio/commands/command.js
+7
-3
src/jio/commands/putAttachmentCommand.js
src/jio/commands/putAttachmentCommand.js
+1
-1
src/jio/jio.outro.js
src/jio/jio.outro.js
+8
-2
test/jiotests.js
test/jiotests.js
+280
-50
No files found.
examples/complex_example.html
View file @
31e65d17
...
@@ -238,6 +238,7 @@ var command = function (method) {
...
@@ -238,6 +238,7 @@ var command = function (method) {
log
(
'
revision:
'
+
other
.
revision
);
log
(
'
revision:
'
+
other
.
revision
);
log
(
'
content:
'
+
other
.
content
);
log
(
'
content:
'
+
other
.
content
);
log
(
'
mimetype:
'
+
other
.
mimetype
);
log
(
'
mimetype:
'
+
other
.
mimetype
);
break
;
case
'
post
'
:
case
'
post
'
:
case
'
put
'
:
case
'
put
'
:
doc
=
JSON
.
parse
(
$
(
'
#metadata
'
).
attr
(
'
value
'
));
doc
=
JSON
.
parse
(
$
(
'
#metadata
'
).
attr
(
'
value
'
));
...
...
src/jio.dummystorages.js
View file @
31e65d17
...
@@ -18,12 +18,47 @@
...
@@ -18,12 +18,47 @@
return
o
;
return
o
;
};
};
// Fake revisions
var
fakeCount
=
0
;
var
generateRevision
=
function
(
command
,
action
,
reset
){
var
that
=
{},
priv
=
{},
fakeRevision
=
""
,
fakeCount
=
reset
===
true
?
0
:
fakeCount
,
now
=
Date
.
now
();
that
.
makeHash
=
function
(){
return
that
.
hashCode
(
''
+
command
.
getDocId
()
+
'
'
+
now
+
''
);
};
that
.
hashCode
=
function
(
string
)
{
return
hex_sha256
(
string
);
};
that
.
generateNextRev
=
function
(
previous_revision
,
string
)
{
return
(
parseInt
(
previous_revision
.
split
(
'
-
'
)[
0
],
10
)
+
1
)
+
'
-
'
+
priv
.
hashCode
(
previous_revision
+
string
);
};
if
(
fakeRevision
===
""
&&
fakeCount
===
0
){
fakeRevision
=
'
1-
'
+
that
.
makeHash
();
}
else
{
if
(
action
!==
"
post
"
){
fakeRevision
=
that
.
generateNextRev
(
fakeRev
,
that
.
makeHash
);
}
}
return
fakeRevision
;
};
that
.
post
=
function
(
command
)
{
that
.
post
=
function
(
command
)
{
setTimeout
(
function
()
{
setTimeout
(
function
()
{
that
.
success
({
that
.
success
({
ok
:
true
,
ok
:
true
,
id
:
command
.
getDocId
()
id
:
command
.
getDocId
(),
rev
:
generateRevision
(
command
,
"
post
"
,
true
)
});
});
},
100
);
},
100
);
};
// end post
};
// end post
...
@@ -32,7 +67,8 @@
...
@@ -32,7 +67,8 @@
setTimeout
(
function
()
{
setTimeout
(
function
()
{
that
.
success
({
that
.
success
({
ok
:
true
,
ok
:
true
,
id
:
command
.
getDocId
()
id
:
command
.
getDocId
(),
rev
:
generateRevision
(
command
,
"
put
"
,
true
)
});
});
},
100
);
// 100 ms, for jiotests simple job waiting
},
100
);
// 100 ms, for jiotests simple job waiting
};
// end put
};
// end put
...
...
src/jio.storage/localstorage.js
View file @
31e65d17
...
@@ -235,131 +235,464 @@ var newLocalStorage = function ( spec, my ) {
...
@@ -235,131 +235,464 @@ var newLocalStorage = function ( spec, my ) {
};
};
/**
/**
* Create a document in the local storage.
* @method throwError - Creates the error object for all errors
* It will store the file in 'jio/local/USR/APP/FILE_NAME'.
*
* The command may have some options:
* @param {code} string - the error code.
* - {boolean} conflicts Add a conflicts object to the response
* @param {reason} string - the error reason
* - {boolean} revs Add the revisions history of the document
*/
* - {boolean} revs_info Add revisions informations
priv
.
throwError
=
function
(
code
,
reason
)
{
var
statusText
,
error
,
message
,
e
;
switch
(
code
){
case
409
:
statusText
=
'
Conflict
'
;
error
=
'
conflict
'
;
message
=
'
Document update conflict.
'
;
break
;
case
403
:
statusText
=
'
Forbidden
'
;
error
=
'
forbidden
'
;
message
=
'
Forbidden
'
;
break
;
case
404
:
statusText
=
'
Not found
'
;
error
=
'
not_found
'
;
message
=
'
Document not found.
'
;
break
;
}
// create object
e
=
({
status
:
code
,
statusText
:
statusText
,
error
:
error
,
message
:
message
,
reason
:
reason
});
return
e
;
};
/**
* @method createDocument - Creates a new document
*
* docid will be "" for POST and a string for PUT
*
* @param {docid} string - id for the new document
* @param {docpath} string - the path where to store the document
*
* @stored 'jio/local/USR/APP/FILE_NAME'
*/
priv
.
createDocument
=
function
(
docId
,
docPath
)
{
var
now
=
Date
.
now
(),
doc
=
{},
hash
=
priv
.
hashCode
(
''
+
doc
+
'
'
+
now
+
''
),
docPathRev
;
doc
.
_id
=
docId
;
doc
.
_rev
=
'
1-
'
+
hash
;
doc
.
_revisions
=
{
start
:
1
,
ids
:
[
hash
]
};
doc
.
_revs_info
=
[{
rev
:
'
1-
'
+
hash
,
status
:
'
available
'
}];
// allow to store multiple versions of a document by including rev
docPathRev
=
docPath
+
'
/
'
+
doc
.
_rev
;
// store
localstorage
.
setItem
(
docPathRev
,
doc
);
return
doc
;
};
/**
* @method updateDocument - updates a document
*
* called from PUT or PUTATTACHMENT (or REMOVE?)
*
* @param {docid} string - id for the new document
* @param {docpath} string - the path where to store the document
* @param {prev_rev} string- the previous revision
*
*/
priv
.
updateDocument
=
function
(
doc
,
docPath
,
prev_rev
)
{
var
now
=
Date
.
now
(),
rev
=
priv
.
generateNextRev
(
prev_rev
,
''
+
doc
+
'
'
+
now
+
''
);
// update document
doc
.
_rev
=
rev
.
join
(
'
-
'
);
doc
.
_revisions
.
ids
.
unshift
(
rev
[
1
]);
doc
.
_revisions
.
start
=
rev
[
0
];
doc
.
_revs_info
[
0
].
status
=
'
deleted
'
;
doc
.
_revs_info
.
unshift
({
"
rev
"
:
rev
.
join
(
'
-
'
),
"
status
"
:
"
available
"
});
// store
localstorage
.
setItem
(
docPath
,
doc
);
return
doc
;
};
/**
* @method createDocumentTree - Creates a new document.tree
*
* @param {docId} string - id for the new document
* @param {doc } object - the document object
* @param {docPath} string - the path where to store the document
*
* the tree will include
* @key {type} string - branch or leaf
* @key {status} string - available or deleted
* @key {rev} string - revision string of this node
* @key {spawns} object - child branches/leaves
*
* @stored 'jio/local/USR/APP/FILE_NAME/TREE_revision'.
*
* the tree is maintained as long as more than one leaf exists(!)
* a leaf set to status "deleted" implies a deleted document version
* When all leaves have been set to "deleted", the tree is also deleted.
*
*/
priv
.
createDocumentTree
=
function
(
doc
,
docId
,
docPath
){
var
tree
=
{
type
:
'
leaf
'
,
status
:
'
available
'
,
rev
:
doc
.
_rev
,
kids
:{}
},
treePath
=
docPath
+
'
/revision_tree
'
;
// store
localstorage
.
setItem
(
treePath
,
tree
);
};
/**
* @method updateDocumentTree - update a document tree
*
* @param {docId} string - id for the new document
* @param {doc } object - the document object
* @param {docPath} string - the path where to store the document
*
* a tree can be grown (update a document) or split (when creating
* a new version). Growing the tree means changing a leaf into
* a branch and creating a new leaf. This is done here.
*
*/
priv
.
updateDocumentTree
=
function
(
){
};
/**
* @method getLastTreeRevision - find a leaf
*
* @param {docTree} string - the tree for this document
*
* this method should get the last leaf on the tree.
* If there are multiple leaves that come into question
* we select same as COUCHDB, highest rev counter, than
* compare ASCII. We will return only a single document
*
*/
priv
.
getLastTreeRevision
=
function
(
docTree
){
};
/**
* @method post
* @method post
*
* Create a document in local storage.
*
* Available options:
* - {boolean} conflicts - Add a conflicts object to the response
* - {boolean} revs - Add the revisions history of the document
* - {boolean} revs_info - Add revisions informations
*
*/
*/
that
.
post
=
function
(
command
)
{
that
.
post
=
function
(
command
)
{
var
now
=
Date
.
now
();
// wait a little in order to simulate asynchronous saving
setTimeout
(
function
()
{
setTimeout
(
function
()
{
var
docid
,
hash
,
doc
,
ret
,
path
;
var
docId
=
command
.
getDocId
(),
docPath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docId
,
treePath
=
docPath
+
'
/revision_tree
'
,
docTree
=
localstorage
.
getItem
(
treePath
),
doc
=
localstorage
.
getItem
(
docPath
),
reg
;
// no attachments allowed
if
(
command
.
getAttachmentId
())
{
if
(
command
.
getAttachmentId
())
{
that
.
error
({
that
.
error
(
priv
.
throwError
(
403
,
status
:
403
,
statusText
:
'
Forbidden
'
,
error
:
'
forbidden
'
,
'
Attachment cannot be added with a POST request
'
)
message
:
'
Cannot add an attachment with post request.
'
,
);
reason
:
'
attachment cannot be added with a post request
'
});
return
;
return
;
}
}
docid
=
command
.
getDocId
();
// check for UUID
path
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
reg
=
/^
[
0-9a-f
]{8}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{12}
$/i
.
test
(
docId
);
priv
.
secured_applicationname
+
'
/
'
+
docid
;
// reading
if
(
reg
!==
true
)
{
doc
=
localstorage
.
getItem
(
path
);
if
(
!
doc
)
{
// id was supplied, use PUT
hash
=
priv
.
hashCode
(
''
+
doc
+
'
'
+
now
+
''
);
that
.
error
(
priv
.
throwError
(
403
,
// create document
'
ID cannot be supplied with a POST request. Please use PUT
'
)
doc
=
{};
);
doc
.
_id
=
docid
;
return
;
doc
.
_rev
=
'
1-
'
+
hash
;
doc
.
_revisions
=
{
}
else
{
start
:
1
,
// create and store new document
ids
:
[
hash
]
doc
=
priv
.
createDocument
(
docId
,
docPath
);
};
doc
.
_revs_info
=
[{
// create and store new document.tree
rev
:
'
1-
'
+
hash
,
priv
.
createDocumentTree
(
doc
,
docId
,
docPath
);
// status can be 'available', 'deleted' or 'missing'
status
:
'
available
'
// add user
}];
if
(
!
priv
.
doesUserExist
(
priv
.
secured_username
))
{
if
(
!
priv
.
doesUserExist
(
priv
.
secured_username
))
{
priv
.
addUser
(
priv
.
secured_username
);
priv
.
addUser
(
priv
.
secured_username
);
}
}
priv
.
addFileName
(
docid
);
}
else
{
// add fileName
// cannot overwrite
priv
.
addFileName
(
docId
);
that
.
error
({
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
that
.
success
(
message
:
'
Document already exists.
'
,
priv
.
manageOptions
(
reason
:
'
the document already exists
'
{
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
});
command
,
return
;
doc
)
);
}
}
localstorage
.
setItem
(
path
,
doc
);
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docid
,
rev
:
doc
.
_rev
},
command
,
doc
)
);
});
});
};
};
// end post
/**
/**
* Saves a document in the local storage.
* It will store the file in 'jio/local/USR/APP/FILE_NAME'.
* @method put
* @method put
*
* Create or Update a document in local storage.
*
* Available options:
* - {boolean} conflicts - Add a conflicts object to the response
* - {boolean} revs - Add the revisions history of the document
* - {boolean} revs_info - Add revisions informations
*/
*/
that
.
put
=
function
(
command
)
{
that
.
put
=
function
(
command
)
{
setTimeout
(
function
()
{
var
docId
=
command
.
getDocId
(),
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
),
docPath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docId
,
docPathRev
=
docPath
+
'
/
'
+
prev_rev
,
treePath
=
docPath
+
'
/revision_tree
'
,
docTree
=
localstorage
.
getItem
(
treePath
),
doc
,
reg
;
// no tree = create document or error
if
(
!
docTree
)
{
// check UUID
reg
=
/^
[
0-9a-f
]{8}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{4}
-
[
0-9a-f
]{12}
$/i
.
test
(
docId
);
// id/revision provided = update, revision must be incorrect
if
(
prev_rev
!==
undefined
&&
reg
===
false
){
that
.
error
(
priv
.
throwError
(
409
,
'
Incorrect Revision or ID
'
)
);
return
;
}
// revision provided = update, wrong revision or missing id
if
(
prev_rev
!==
undefined
){
that
.
error
(
priv
.
throwError
(
404
,
'
Document not found, please check revision and/or ID
'
)
);
return
;
}
// no revision and UUID = create, no id provided
if
(
prev_rev
===
undefined
&&
reg
===
true
){
that
.
error
(
priv
.
throwError
(
409
,
'
Missing Document ID and or Revision
'
)
);
return
;
}
// if passed here, we create.
// it could be create (id+content) or update (without revision)
// but since no tree was found and the tree includes id only
// we only end here with a NEW id, so update sans revision cannot
// be the case.
// create and store new document
doc
=
priv
.
createDocument
(
docId
,
docPath
);
// create and store new document.tree
priv
.
createDocumentTree
(
doc
,
docId
,
docPath
);
// add user
if
(
!
priv
.
doesUserExist
(
priv
.
secured_username
))
{
priv
.
addUser
(
priv
.
secured_username
);
}
// add fileName
priv
.
addFileName
(
docId
);
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
)
);
}
else
{
// we found a tree
/*
console.log( docTree );
console.log( prev_rev );
console.log( docId );
console.log( docPath );
console.log( docPathRev );
*/
doc
=
localstorage
.
getItem
(
docPathRev
);
console
.
log
(
doc
);
// check if rev_supplied is on the tree
// check if last node
// check if multiple leaves or one (do I need to???)
// if on tree and only leaf = expand
// if on tree and multiple leaves = ???
// if on tree, but not a leaf = error
// if not on tree, can be error or new version
// get revs_info from new document
// not available = error on PUT
// available = compare revs_info current and supplied
// start @root
// if nodes are the same and BRANCH, make sure they are branch and deleted if not the last nodes
// if nodes are not the same STOP
// add new kid to last branch
// continue with supplied revs_info to last version and add all the nodes on supplied revs_info
// this should "copy" the tree from supplied revs_info into the current document tree
// we have a tree, we know the last revision
//priv.getLastTreeRevision( docTree );
if
(
!
doc
)
{
}
if
(
doc
.
_rev
!==
prev_rev
)
{
that
.
error
(
priv
.
throwError
(
409
,
'
Revision supplied is not the latest revision
'
)
);
return
;
}
// update ...?
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
// update document (and get it back)
doc
=
priv
.
updateDocument
(
doc
,
docPath
,
prev_rev
);
// update document tree
priv
.
updateDocumentTree
();
that
.
success
(
priv
.
manageOptions
(
{
ok
:
true
,
id
:
docId
,
rev
:
doc
.
_rev
},
command
,
doc
)
);
}
});
};
// end put
/**
* Saves/updates an attachment of a specified document.
* attachment will be stored @ 'jio/local/USR/APP/FILE_NAME/ATTACHMENTID'.
* @method putAttachment
*/
that
.
putAttachment
=
function
(
command
)
{
var
now
=
Date
.
now
();
var
now
=
Date
.
now
();
// wait a little in order to simulate asynchronous saving
// wait a little in order to simulate asynchronous saving
setTimeout
(
function
()
{
setTimeout
(
function
()
{
var
docid
,
doc
,
docpath
,
attmtid
,
attmt
,
attmtpath
,
prev_rev
,
rev
;
var
docid
,
doc
,
docpath
,
attmtid
,
attmt
,
attmtpath
,
prev_rev
,
rev
;
docid
=
command
.
getDocId
();
docid
=
command
.
getDocId
();
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
);
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
);
docpath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
docpath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docid
;
priv
.
secured_applicationname
+
'
/
'
+
docid
;
// reading
// 404
doc
=
localstorage
.
getItem
(
docpath
);
doc
=
localstorage
.
getItem
(
docpath
);
if
(
!
doc
)
{
if
(
!
doc
)
{
that
.
error
({
that
.
error
({
status
:
404
,
statusText
:
'
Not found
'
,
error
:
'
not_found
'
,
status
:
404
,
statusText
:
'
Not found
'
,
error
:
'
not_found
'
,
message
:
'
Document not found.
'
,
message
:
'
Document not found.
'
,
reason
:
'
document not found
'
reason
:
'
Document with specified id does not exist
'
});
});
return
;
return
;
}
}
// 409
if
(
doc
.
_rev
!==
prev_rev
)
{
if
(
doc
.
_rev
!==
prev_rev
)
{
// want to update an older document
// want to update an older document
that
.
error
({
that
.
error
({
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
message
:
'
Document update conflict.
'
,
message
:
'
Document update conflict.
'
,
reason
:
'
document update conflict.
'
reason
:
'
Trying to update a previous document version
'
});
});
return
;
return
;
}
}
// it is the good document
// check attachment id
attmtid
=
command
.
getAttachmentId
();
attmtid
=
command
.
getAttachmentId
();
if
(
attmtid
)
{
if
(
attmtid
)
{
attmtpath
=
docpath
+
'
/
'
+
attmtid
;
attmtpath
=
docpath
+
'
/
'
+
attmtid
;
// this is an attachment
attmt
=
localstorage
.
getItem
(
attmtpath
);
attmt
=
localstorage
.
getItem
(
attmtpath
);
if
(
!
attmt
)
{
// there is no attachment to update
// create _attachments
that
.
error
({
if
(
doc
.
_attachments
===
undefined
){
status
:
404
,
statusText
:
'
Not found
'
,
error
:
'
not_found
'
,
doc
.
_attachments
=
{};
message
:
'
Document is missing attachment.
'
,
}
reason
:
'
document is missing attachment
'
});
// create _attachments object for this attachment
return
;
if
(
doc
.
_attachments
[
attmtid
]
===
undefined
){
doc
.
_attachments
[
attmtid
]
=
{};
}
}
// updating attachment
// set revpos
doc
.
_attachments
[
attmtid
].
revpos
=
doc
.
_attachments
[
attmtid
].
revpos
=
parseInt
(
doc
.
_rev
.
split
(
'
-
'
)[
0
],
10
);
parseInt
(
doc
.
_rev
.
split
(
'
-
'
)[
0
],
10
);
// store/update attachment
localstorage
.
setItem
(
attmtpath
,
command
.
getContent
());
localstorage
.
setItem
(
attmtpath
,
command
.
getContent
());
}
else
{
}
else
{
// update document metadata
// no attachment id specified
priv
.
documentObjectUpdate
(
doc
,
command
.
cloneDoc
());
that
.
error
({
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
message
:
'
Document update conflict.
'
,
reason
:
'
No attachment id specified
'
});
return
;
}
}
// rev = [number, hash]
// rev = [number, hash]
rev
=
priv
.
generateNextRev
(
prev_rev
,
''
+
doc
+
'
'
+
now
+
''
);
rev
=
priv
.
generateNextRev
(
prev_rev
,
''
+
doc
+
'
'
+
now
+
''
);
doc
.
_rev
=
rev
.
join
(
'
-
'
);
doc
.
_rev
=
rev
.
join
(
'
-
'
);
...
@@ -379,7 +712,7 @@ var newLocalStorage = function ( spec, my ) {
...
@@ -379,7 +712,7 @@ var newLocalStorage = function ( spec, my ) {
)
)
);
);
});
});
};
// end put
};
// end put
Attachment
/**
/**
* Loads a document from the local storage.
* Loads a document from the local storage.
...
@@ -441,6 +774,7 @@ var newLocalStorage = function ( spec, my ) {
...
@@ -441,6 +774,7 @@ var newLocalStorage = function ( spec, my ) {
* the user.
* the user.
* @method allDocs
* @method allDocs
*/
*/
// ============== NOT MODIFIED YET ===============
that
.
allDocs
=
function
(
command
)
{
that
.
allDocs
=
function
(
command
)
{
setTimeout
(
function
()
{
setTimeout
(
function
()
{
...
@@ -472,23 +806,77 @@ var newLocalStorage = function ( spec, my ) {
...
@@ -472,23 +806,77 @@ var newLocalStorage = function ( spec, my ) {
};
// end allDocs
};
// end allDocs
/**
/**
* Removes a document from the local storage.
* Removes a document
or attachment
from the local storage.
* It will also remove the path from the local file array.
* It will also remove the path from the local file array.
* @method remove
* @method remove
*/
*/
// ============== FILES WON'T BE DELETED YET ===============
that
.
remove
=
function
(
command
)
{
that
.
remove
=
function
(
command
)
{
// wait a little in order to simulate asynchronous saving
setTimeout
(
function
()
{
setTimeout
(
function
()
{
var
secured_docid
=
priv
.
secureDocId
(
command
.
getDocId
()),
var
docid
,
doc
,
docpath
,
prev_rev
,
attmtid
,
attmt
,
attpath
;
path
=
'
jio/local/
'
+
docid
=
command
.
getDocId
();
priv
.
secured_username
+
'
/
'
+
docpath
=
'
jio/local/
'
+
priv
.
secured_username
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
priv
.
secured_applicationname
+
'
/
'
+
docid
;
secured_docid
;
prev_rev
=
command
.
getDocInfo
(
'
_rev
'
);
if
(
!
priv
.
checkSecuredDocId
(
attmtid
=
command
.
getAttachmentId
();
secured_docid
,
command
.
getDocId
(),
'
remove
'
))
{
return
;}
// deleting
// xxx remove attachment if exists
localstorage
.
deleteItem
(
path
);
if
(
attmtid
){
priv
.
removeFileName
(
secured_docid
);
attpath
=
docpath
+
'
/
'
+
attmtid
;
that
.
success
({
ok
:
true
,
id
:
command
.
getDocId
()});
attmt
=
localstorage
.
getItem
(
attpath
);
if
(
attmt
){
// deleting
localstorage
.
deleteItem
(
attpath
);
priv
.
removeFileName
(
attpath
);
// xxx add new revision to tree here
that
.
success
({
ok
:
true
,
id
:
command
.
getDocId
()});
}
else
{
// the document does not exist
that
.
error
({
status
:
404
,
statusText
:
'
Not Found.
'
,
error
:
'
not_found
'
,
message
:
'
Document "
'
+
docid
+
'
" not found.
'
,
reason
:
'
missing
'
});
}
// xxx remove document if exists
}
else
{
doc
=
localstorage
.
getItem
(
docpath
);
// document exists
if
(
doc
){
// check for wrong revision
if
(
doc
.
_rev
===
prev_rev
){
localstorage
.
deleteItem
(
docpath
);
priv
.
removeFileName
(
docid
);
// xxx add new revision to tree here
that
.
success
({
ok
:
true
,
id
:
command
.
getDocId
()});
}
else
{
// the document does not exist
that
.
error
({
status
:
409
,
statusText
:
'
Conflict
'
,
error
:
'
conflict
'
,
message
:
'
Document update conflict.
'
,
reason
:
'
Trying to update an outdated revision
'
});
}
}
else
{
// the document does not exist
that
.
error
({
status
:
404
,
statusText
:
'
Not Found.
'
,
error
:
'
not_found
'
,
message
:
'
Document "
'
+
docid
+
'
" not found.
'
,
reason
:
'
missing
'
});
}
}
});
});
};
// end remove
};
// end remove
...
...
src/jio/commands/command.js
View file @
31e65d17
...
@@ -23,9 +23,13 @@ var command = function(spec, my) {
...
@@ -23,9 +23,13 @@ var command = function(spec, my) {
priv
.
doc
=
spec
.
doc
||
{};
priv
.
doc
=
spec
.
doc
||
{};
priv
.
doc
.
_id
=
priv
.
doc
.
_id
||
generateUuid
();
priv
.
doc
.
_id
=
priv
.
doc
.
_id
||
generateUuid
();
priv
.
docid
=
spec
.
docid
||
''
;
priv
.
docid
=
spec
.
docid
||
''
;
priv
.
content
=
typeof
spec
.
content
===
'
string
'
?
spec
.
content
:
// xxx fixed spec.content to spec.doc.content for PUTATTACHMENT
undefined
;
// xxx need extra check for GET, otherwise spec.doc is undefined
priv
.
content
=
spec
.
doc
===
undefined
?
undefined
:
typeof
spec
.
doc
.
content
===
'
string
'
?
spec
.
doc
.
content
:
undefined
;
priv
.
option
=
spec
.
options
||
{};
priv
.
option
=
spec
.
options
||
{};
priv
.
callbacks
=
spec
.
callbacks
||
{};
priv
.
callbacks
=
spec
.
callbacks
||
{};
priv
.
success
=
priv
.
callbacks
.
success
||
function
(){};
priv
.
success
=
priv
.
callbacks
.
success
||
function
(){};
...
...
src/jio/commands/putAttachmentCommand.js
View file @
31e65d17
...
@@ -11,7 +11,7 @@ var putAttachmentCommand = function(spec, my) {
...
@@ -11,7 +11,7 @@ var putAttachmentCommand = function(spec, my) {
that
.
executeOn
=
function
(
storage
)
{
that
.
executeOn
=
function
(
storage
)
{
storage
.
putAttachment
(
that
);
storage
.
putAttachment
(
that
);
};
};
that
.
validateState
=
function
()
{
that
.
validateState
=
function
()
{
if
(
typeof
that
.
getContent
()
!==
'
string
'
)
{
if
(
typeof
that
.
getContent
()
!==
'
string
'
)
{
that
.
error
({
that
.
error
({
...
...
src/jio/jio.outro.js
View file @
31e65d17
...
@@ -194,6 +194,7 @@
...
@@ -194,6 +194,7 @@
[
options
,
success
,
error
],
[
options
,
success
,
error
],
{
max_retry
:
0
}
{
max_retry
:
0
}
);
);
priv
.
addJob
(
postCommand
,{
priv
.
addJob
(
postCommand
,{
doc
:
doc
,
doc
:
doc
,
options
:
param
.
options
,
options
:
param
.
options
,
...
@@ -223,6 +224,7 @@
...
@@ -223,6 +224,7 @@
[
options
,
success
,
error
],
[
options
,
success
,
error
],
{
max_retry
:
0
}
{
max_retry
:
0
}
);
);
priv
.
addJob
(
putCommand
,{
priv
.
addJob
(
putCommand
,{
doc
:
doc
,
doc
:
doc
,
options
:
param
.
options
,
options
:
param
.
options
,
...
@@ -253,6 +255,7 @@
...
@@ -253,6 +255,7 @@
[
options
,
success
,
error
],
[
options
,
success
,
error
],
{
max_retry
:
3
}
{
max_retry
:
3
}
);
);
priv
.
addJob
(
getCommand
,{
priv
.
addJob
(
getCommand
,{
docid
:
id
,
docid
:
id
,
options
:
param
.
options
,
options
:
param
.
options
,
...
@@ -282,6 +285,7 @@
...
@@ -282,6 +285,7 @@
[
options
,
success
,
callback
],
[
options
,
success
,
callback
],
{
max_retry
:
0
}
{
max_retry
:
0
}
);
);
priv
.
addJob
(
removeCommand
,{
priv
.
addJob
(
removeCommand
,{
doc
:
doc
,
doc
:
doc
,
options
:
param
.
options
,
options
:
param
.
options
,
...
@@ -311,6 +315,7 @@
...
@@ -311,6 +315,7 @@
[
options
,
success
.
error
],
[
options
,
success
.
error
],
{
max_retry
:
3
}
{
max_retry
:
3
}
);
);
priv
.
addJob
(
allDocsCommand
,{
priv
.
addJob
(
allDocsCommand
,{
options
:
param
.
options
,
options
:
param
.
options
,
callbacks
:{
success
:
param
.
success
,
error
:
param
.
error
}
callbacks
:{
success
:
param
.
success
,
error
:
param
.
error
}
...
@@ -342,8 +347,9 @@
...
@@ -342,8 +347,9 @@
[
options
,
success
,
error
],
[
options
,
success
,
error
],
{
max_retry
:
0
}
{
max_retry
:
0
}
);
);
priv
.
addJob
(
putAttachmentCommand
,{
doc
:{
_id
:
id
,
content
:
doc
},
priv
.
addJob
(
putAttachmentCommand
,{
doc
:{
_id
:
id
,
content
:
doc
,
_rev
:
rev
,
mimetype
:
mimetype
},
options
:
param
.
options
,
options
:
param
.
options
,
callbacks
:{
success
:
param
.
success
,
error
:
param
.
error
}
callbacks
:{
success
:
param
.
success
,
error
:
param
.
error
}
});
});
...
...
test/jiotests.js
View file @
31e65d17
...
@@ -5,21 +5,6 @@
...
@@ -5,21 +5,6 @@
Base64
=
loader
.
Base64
,
Base64
=
loader
.
Base64
,
$
=
loader
.
jQuery
;
$
=
loader
.
jQuery
;
//// clear jio localstorage
(
function
()
{
var
k
,
storageObject
=
LocalOrCookieStorage
.
getAll
();
for
(
k
in
storageObject
)
{
var
splitk
=
k
.
split
(
'
/
'
);
if
(
splitk
[
0
]
===
'
jio
'
)
{
LocalOrCookieStorage
.
deleteItem
(
k
);
}
}
var
d
=
document
.
createElement
(
'
div
'
);
d
.
setAttribute
(
'
id
'
,
'
log
'
);
document
.
querySelector
(
'
body
'
).
appendChild
(
d
);
}());
//// end clear jio localstorage
//// Tools
//// Tools
var
empty_fun
=
function
(){},
var
empty_fun
=
function
(){},
contains
=
function
(
array
,
content
)
{
contains
=
function
(
array
,
content
)
{
...
@@ -34,10 +19,27 @@ contains = function (array,content) {
...
@@ -34,10 +19,27 @@ contains = function (array,content) {
}
}
return
false
;
return
false
;
},
},
clean_up_local_storage_function
=
function
(){
var
k
,
storageObject
=
LocalOrCookieStorage
.
getAll
();
for
(
k
in
storageObject
)
{
var
splitk
=
k
.
split
(
'
/
'
);
if
(
splitk
[
0
]
===
'
jio
'
)
{
LocalOrCookieStorage
.
deleteItem
(
k
);
}
}
var
d
=
document
.
createElement
(
'
div
'
);
d
.
setAttribute
(
'
id
'
,
'
log
'
);
document
.
querySelector
(
'
body
'
).
appendChild
(
d
);
// remove everything
localStorage
.
clear
();
},
base_tick
=
30000
,
base_tick
=
30000
,
basic_test_function_generator
=
function
(
o
,
res
,
value
,
message
)
{
basic_test_function_generator
=
function
(
o
,
res
,
value
,
message
)
{
return
function
(
err
,
val
)
{
return
function
(
err
,
val
)
{
var
jobstatus
=
(
err
?
'
fail
'
:
'
done
'
);
var
jobstatus
=
(
err
?
'
fail
'
:
'
done
'
),
val
=
(
isEmptyObject
(
value
)
&&
isUUID
(
val
.
_id
)
)
?
{}
:
val
;
switch
(
res
)
{
switch
(
res
)
{
case
'
status
'
:
case
'
status
'
:
err
=
err
||
{};
val
=
err
.
status
;
err
=
err
||
{};
val
=
err
.
status
;
...
@@ -187,6 +189,31 @@ revs_infoContains = function (revs_info, rev) {
...
@@ -187,6 +189,31 @@ revs_infoContains = function (revs_info, rev) {
}
}
}
}
return
false
;
return
false
;
},
isUUID
=
function
(
_id
){
var
re
=
/^
[
0-9a-f
]{8}(
-
[
0-9a-f
]{4}){3}
-
[
0-9a-f
]{12}
$/
;
if
(
re
.
test
(
_id
)
){
return
true
;
}
else
{
return
false
;
}
},
isEmptyObject
=
function
(
obj
)
{
var
key
;
if
(
obj
.
length
&&
obj
.
length
>
0
){
return
false
;
}
if
(
obj
.
length
&&
obj
.
length
===
0
){
return
true
;
}
for
(
key
in
obj
)
{
if
(
hasOwnProperty
.
call
(
obj
,
key
)){
return
false
;
}
}
return
true
;
};
};
//// end tools
//// end tools
...
@@ -256,12 +283,36 @@ test ('All tests', function () {
...
@@ -256,12 +283,36 @@ test ('All tests', function () {
o
.
clock
.
tick
(
base_tick
);
o
.
clock
.
tick
(
base_tick
);
o
.
spy
=
basic_spy_function
;
o
.
spy
=
basic_spy_function
;
o
.
tick
=
basic_tick_function
;
o
.
tick
=
basic_tick_function
;
// All Ok Dummy Storage
// All Ok Dummy Storage
o
.
jio
=
JIO
.
newJio
({
'
type
'
:
'
dummyallok
'
});
o
.
jio
=
JIO
.
newJio
({
'
type
'
:
'
dummyallok
'
});
// save
o
.
spy
(
o
,
'
value
'
,{
ok
:
true
,
id
:
'
file
'
},
'
dummyallok saving
'
);
// post empty
o
.
jio
.
put
({
_id
:
'
file
'
,
content
:
'
content
'
},
o
.
f
);
o
.
jio
.
post
({},
function
(
err
,
response
)
{
o
.
spy
(
o
,
'
value
'
,{
"
ok
"
:
true
,
"
id
"
:
response
.
id
,
"
rev
"
:
response
.
rev
},
'
dummyallok post/create empty object
'
);
o
.
f
(
response
);
});
o
.
tick
(
o
);
o
.
tick
(
o
);
// post
o
.
jio
.
post
({
"
content
"
:
"
basic_content
"
},
function
(
err
,
response
)
{
o
.
spy
(
o
,
'
value
'
,{
"
ok
"
:
true
,
"
id
"
:
response
.
id
,
"
rev
"
:
response
.
rev
},
'
dummyallok post/create object
'
);
o
.
f
(
response
);
});
o
.
tick
(
o
);
// put
o
.
jio
.
put
({
"
_id
"
:
"
file
"
,
"
content
"
:
"
basic_content
"
},
function
(
err
,
response
)
{
o
.
spy
(
o
,
'
value
'
,{
"
ok
"
:
true
,
"
id
"
:
"
file
"
,
"
rev
"
:
response
.
rev
},
'
dummyallok put create object
'
);
o
.
f
(
response
);
});
o
.
tick
(
o
);
/*
// load
// load
o.spy(o,'value',{_id:'file',content:'content',_last_modified:15000,
o.spy(o,'value',{_id:'file',content:'content',_last_modified:15000,
_creation_date:10000},'dummyallok loading');
_creation_date:10000},'dummyallok loading');
...
@@ -348,8 +399,10 @@ test ('All tests', function () {
...
@@ -348,8 +399,10 @@ test ('All tests', function () {
o.jio.allDocs (o.f);
o.jio.allDocs (o.f);
o.tick(o);
o.tick(o);
o.jio.stop();
o.jio.stop();
*/
});
});
/*
module ( 'Jio Job Managing' );
module ( 'Jio Job Managing' );
test ('Simple Job Elimination', function () {
test ('Simple Job Elimination', function () {
...
@@ -533,45 +586,221 @@ test ('Restore old Jio', function() {
...
@@ -533,45 +586,221 @@ test ('Restore old Jio', function() {
o.jio.stop();
o.jio.stop();
});
});
module
(
'
Jio LocalStorage
'
);
*/
test
(
'
Document save
'
,
function
()
{
module
(
'
Jio LocalStorage
'
);
// Test if LocalStorage can save documents.
// We launch a saving to localstorage and we check if the file is
// realy saved. Then save again and check if
var
o
=
{};
o
.
t
=
this
;
o
.
clock
=
o
.
t
.
sandbox
.
useFakeTimers
();
// ============================== POST ==========================
test
(
'
Post
'
,
function
(){
// runs following assertions
// a) POST with id - should be an error
// b) POST with attachment - should be an error
// c) POST with content
// d) check that document is created with UUID.revision
// e) check that document revision tree is created
var
o
=
{};
o
.
t
=
this
;
o
.
clock
=
o
.
t
.
sandbox
.
useFakeTimers
(),
localstorage
=
{
getItem
:
function
(
item
)
{
return
JSON
.
parse
(
localStorage
.
getItem
(
item
));
},
setItem
:
function
(
item
,
value
)
{
return
localStorage
.
setItem
(
item
,
JSON
.
stringify
(
value
));
},
deleteItem
:
function
(
item
)
{
delete
localStorage
[
item
];
}
};
o
.
clock
.
tick
(
base_tick
);
o
.
clock
.
tick
(
base_tick
);
o
.
spy
=
basic_spy_function
;
o
.
spy
=
basic_spy_function
;
o
.
tick
=
function
(
o
,
tick
,
value
,
fun
)
{
o
.
clean
=
clean_up_local_storage_function
();
basic_tick_function
(
o
,
tick
,
fun
);
o
.
tmp
=
// test functions
LocalOrCookieStorage
.
getItem
(
'
jio/local/MrSaveName/jiotests/file
'
);
o
.
checkReply
=
function
(
o
,
tick
,
fun
){
basic_tick_function
(
o
,
tick
,
fun
);
};
o
.
checkFile
=
function
(
response
,
o
,
tick
,
value
,
fun
)
{
o
.
tmp
=
localstorage
.
getItem
(
'
jio/local/MrPost/jiotests/
'
+
response
.
id
+
'
/
'
+
response
.
rev
);
// fake it
o
.
tmp
.
ok
=
true
;
delete
o
.
tmp
.
_revisions
;
delete
o
.
tmp
.
_revs_info
;
if
(
o
.
tmp
)
{
if
(
o
.
tmp
)
{
o
.
tmp
.
lmcd
=
(
o
.
tmp
.
_last_modified
===
o
.
tmp
.
_creation_date
);
deepEqual
(
o
.
tmp
,{
delete
o
.
tmp
.
_last_modified
;
"
ok
"
:
response
.
ok
,
delete
o
.
tmp
.
_creation_date
;
"
_id
"
:
response
.
id
,
deepEqual
(
o
.
tmp
,{
_id
:
'
file
'
,
content
:
'
content
'
,
lmcd
:
value
}
,
"
_rev
"
:
response
.
rev
,
'
check saved document
'
);
},
'
document was created
'
);
}
else
{
}
else
{
ok
(
false
,
'
document is not saved!
'
);
ok
(
false
,
'
document was not created
'
);
}
};
o
.
checkTree
=
function
(
response
,
o
,
tick
,
value
,
fun
)
{
o
.
tmp
=
localstorage
.
getItem
(
'
jio/local/MrPost/jiotests/
'
+
response
.
id
+
'
/revision_tree
'
);
if
(
o
.
tmp
)
{
deepEqual
(
o
.
tmp
,{
"
type
"
:
'
leaf
'
,
"
status
"
:
'
available
'
,
"
rev
"
:
response
.
rev
,
"
kids
"
:{}
},
'
document tree was created
'
);
}
else
{
ok
(
false
,
'
document tree was not created
'
);
}
}
};
};
o
.
jio
=
JIO
.
newJio
({
type
:
'
local
'
,
username
:
'
MrSaveName
'
,
// let's go
applicationname
:
'
jiotests
'
});
o
.
jio
=
JIO
.
newJio
({
type
:
'
local
'
,
username
:
'
MrPost
'
,
// save and check document existence
applicationname
:
'
jiotests
'
});
o
.
spy
(
o
,
'
value
'
,{
ok
:
true
,
id
:
'
file
'
},
'
saving document
'
);
o
.
spy
(
o
,
'
value
'
,{
o
.
jio
.
put
({
_id
:
'
file
'
,
content
:
'
content
'
},
o
.
f
);
"
error
"
:
'
forbidden
'
,
o
.
tick
(
o
,
null
,
true
);
"
message
"
:
'
Forbidden
'
,
"
reason
"
:
'
ID cannot be supplied with a POST request. Please use PUT
'
,
o
.
spy
(
o
,
'
value
'
,{
ok
:
true
,
id
:
'
file
'
},
'
saving document
'
);
"
status
"
:
403
,
o
.
jio
.
put
({
_id
:
'
file
'
,
content
:
'
content
'
},
o
.
f
);
"
statusText
"
:
'
Forbidden
'
o
.
tick
(
o
,
null
,
false
);
},
'
POST with id = 403 forbidden
'
);
o
.
jio
.
post
({
"
_id
"
:
'
file
'
,
"
content
"
:
'
content
'
},
o
.
f
);
// TEST a) POST with id
o
.
checkReply
(
o
,
null
,
true
);
o
.
spy
(
o
,
'
value
'
,{
"
error
"
:
'
forbidden
'
,
"
message
"
:
'
Forbidden
'
,
"
reason
"
:
'
Attachment cannot be added with a POST request
'
,
"
status
"
:
403
,
"
statusText
"
:
'
Forbidden
'
},
'
POST attachment = 403 forbidden
'
);
o
.
jio
.
post
({
"
_id
"
:
'
file/ABC
'
,
"
mimetype
"
:
'
text/html
'
,
"
content
"
:
'
<b>hello</b>
'
},
o
.
f
);
// TEST b) POST attachment
o
.
checkReply
(
o
,
null
,
true
);
o
.
jio
.
post
({
"
content
"
:
'
content
'
},
function
(
err
,
response
)
{
o
.
spy
(
o
,
'
value
'
,{
"
ok
"
:
true
,
"
id
"
:
response
.
id
,
"
rev
"
:
response
.
rev
},
'
POST content = ok
'
);
o
.
f
(
response
);
// TEST d) check if document is created and correct
o
.
checkFile
(
response
,
o
,
null
,
true
);
// TEST e) check if document tree is created and correct
o
.
checkTree
(
response
,
o
,
null
,
true
);
});
// c) TEST POST content
o
.
checkReply
(
o
,
null
,
true
);
o
.
jio
.
stop
();
o
.
clean
;
});
// ============================== PUT ==========================
/*
test ('Put', function(){
// runs following assertions
// a)
var o = {};
o.t = this;
o.clock = o.t.sandbox.useFakeTimers(),
localstorage = {
getItem: function (item) {
return JSON.parse (localStorage.getItem(item));
},
setItem: function (item,value) {
return localStorage.setItem(item,JSON.stringify (value));
},
deleteItem: function (item) {
delete localStorage[item];
}
};
o.clock.tick(base_tick);
o.spy = basic_spy_function;
o.clean = clean_up_local_storage_function();
// test functions
o.checkReply = function(o,tick,fun){
basic_tick_function(o,tick,fun);
};
o.checkFile = function (response, o, tick, value, fun) {
o.tmp =
localstorage.getItem('jio/local/MrSaveName/jiotests/'+ response.id+'/'+response.rev );
// fake it
o.tmp.ok = true;
delete o.tmp._revisions;
delete o.tmp._revs_info;
if (o.tmp) {
deepEqual (o.tmp,{
"ok":response.ok,
"_id":response.id,
"_rev":response.rev,
},'document was created');
} else {
ok (false, 'document was not created');
}
};
o.checkTree = function ( response, o, tick, value, fun) {
o.tmp =
localstorage.getItem('jio/local/MrPut/jiotests/'+ response.id+'/revision_tree' );
if (o.tmp) {
deepEqual (o.tmp,{
"type":'leaf',
"status":'available',
"rev":response.rev,
"kids":{}
},'document tree was created');
} else {
ok (false, 'document tree was not created');
}
};
// let's go
o.jio = JIO.newJio({ type:'local', username:'MrPut',
applicationname:'jiotests' });
o.spy (o,'value',{ },'');
o.jio.post({"_id":'file',"content":'content'},o.f);
// a) TEST
o.checkReply(o,null,true);
o.jio.post({"content":'content'},
function(err, response) {
o.spy(o,'value',{"ok":true,"id":response.id,"rev":response.rev},
'POST content = ok');
o.f(response);
// d) check document is created and correct
o.checkFile(response, o, null, true);
// e) check document tree is created and correct
o.checkTree(response, o, null, true);
});
// c) POST content - o.spy must be in callback to access response
o.checkReply(o,null,true);
o.jio.stop();
o.jio.stop();
o.clean;
});
});
*/
/*
test ('Document load', function () {
test ('Document load', function () {
// Test if LocalStorage can load documents.
// Test if LocalStorage can load documents.
// We launch a loading from localstorage and we check if the file is
// We launch a loading from localstorage and we check if the file is
...
@@ -599,7 +828,7 @@ test ('Document load', function () {
...
@@ -599,7 +828,7 @@ test ('Document load', function () {
o.jio.stop();
o.jio.stop();
});
});
*//*
test ('Get document list', function () {
test ('Get document list', function () {
// Test if LocalStorage can get a list of documents.
// Test if LocalStorage can get a list of documents.
// We create 2 documents inside localStorage to check them.
// We create 2 documents inside localStorage to check them.
...
@@ -650,7 +879,7 @@ test ('Get document list', function () {
...
@@ -650,7 +879,7 @@ test ('Get document list', function () {
o.jio.stop();
o.jio.stop();
});
});
*//*
test ('Document remove', function () {
test ('Document remove', function () {
// Test if LocalStorage can remove documents.
// Test if LocalStorage can remove documents.
// We launch a remove from localstorage and we check if the file is
// We launch a remove from localstorage and we check if the file is
...
@@ -677,7 +906,8 @@ test ('Document remove', function () {
...
@@ -677,7 +906,8 @@ test ('Document remove', function () {
o.jio.stop();
o.jio.stop();
});
});
*/
/*
module ('Jio DAVStorage');
module ('Jio DAVStorage');
test ('Document load', function () {
test ('Document load', function () {
...
@@ -2264,7 +2494,7 @@ test ('Get revision List', function () {
...
@@ -2264,7 +2494,7 @@ test ('Get revision List', function () {
o.jio.stop();
o.jio.stop();
});
});
*/
};
// end thisfun
};
// end thisfun
if
(
window
.
requirejs
)
{
if
(
window
.
requirejs
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment