Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Eugene Shen
erp5
Commits
0d9586e0
Commit
0d9586e0
authored
Mar 31, 2017
by
Eugene Shen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Correctly reload and rewrite entire chat
parent
edcd20f8
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1209 additions
and
1232 deletions
+1209
-1232
bt5/officejs_eyqs/PathTemplateItem/web_page_module/erp5_page_launcher_js.js
...PathTemplateItem/web_page_module/erp5_page_launcher_js.js
+609
-0
bt5/officejs_eyqs/PathTemplateItem/web_page_module/erp5_page_launcher_js.xml
...athTemplateItem/web_page_module/erp5_page_launcher_js.xml
+5
-9
bt5/officejs_eyqs/PathTemplateItem/web_page_module/fast_priority_queue_js.js
...athTemplateItem/web_page_module/fast_priority_queue_js.js
+0
-179
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_box_html.html
...eItem/web_page_module/gadget_erp5_page_chat_box_html.html
+2
-7
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_box_js.js
...plateItem/web_page_module/gadget_erp5_page_chat_box_js.js
+507
-961
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_connect_html.html
...m/web_page_module/gadget_erp5_page_chat_connect_html.html
+6
-6
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_connect_js.js
...eItem/web_page_module/gadget_erp5_page_chat_connect_js.js
+61
-49
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_jio_dav_configurator_js.js
...b_page_module/gadget_erp5_page_jio_dav_configurator_js.js
+7
-7
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_jio_erp5_configurator_js.js
..._page_module/gadget_erp5_page_jio_erp5_configurator_js.js
+12
-13
bt5/officejs_eyqs/bt/template_path_list
bt5/officejs_eyqs/bt/template_path_list
+0
-1
No files found.
bt5/officejs_eyqs/PathTemplateItem/web_page_module/erp5_page_launcher_js.js
0 → 100644
View file @
0d9586e0
/*globals window, document, RSVP, rJS,
URI, location, XMLHttpRequest, console*/
/*jslint indent: 2, maxlen: 80*/
(
function
(
window
,
document
,
RSVP
,
rJS
,
XMLHttpRequest
,
location
,
console
)
{
"
use strict
"
;
/*
if (navigator.hasOwnProperty('serviceWorker')) {
// Check if a ServiceWorker already controls the site on load
if (!navigator.serviceWorker.controller) {
// Register the ServiceWorker
navigator.serviceWorker.register('gadget_erp5_serviceworker.js');
}
}
*/
var
MAIN_SCOPE
=
"
m
"
;
function
renderMainGadget
(
gadget
,
url
,
options
)
{
return
gadget
.
declareGadget
(
url
,
{
scope
:
MAIN_SCOPE
})
.
push
(
function
(
page_gadget
)
{
gadget
.
props
.
m_options_string
=
JSON
.
stringify
(
options
);
if
(
page_gadget
.
render
===
undefined
)
{
return
[
page_gadget
];
}
return
RSVP
.
all
([
page_gadget
,
page_gadget
.
render
(
options
)
]);
})
.
push
(
function
(
all_result
)
{
return
all_result
[
0
];
});
}
function
initHeaderOptions
(
gadget
)
{
gadget
.
props
.
header_argument_list
=
{
panel_action
:
true
,
title
:
gadget
.
props
.
application_title
||
"
OfficeJS
"
};
}
function
route
(
my_root_gadget
,
my_scope
,
my_method
,
argument_list
)
{
return
RSVP
.
Queue
()
.
push
(
function
()
{
return
my_root_gadget
.
getDeclaredGadget
(
my_scope
);
})
.
push
(
function
(
my_gadget
)
{
if
(
argument_list
)
{
return
my_gadget
[
my_method
].
apply
(
my_gadget
,
argument_list
);
}
return
my_gadget
[
my_method
]();
});
}
function
updateHeader
(
gadget
)
{
var
header_gadget
;
return
gadget
.
getDeclaredGadget
(
"
header
"
)
.
push
(
function
(
result
)
{
header_gadget
=
result
;
return
header_gadget
.
notifySubmitted
();
})
.
push
(
function
()
{
return
header_gadget
.
render
(
gadget
.
props
.
header_argument_list
);
});
}
function
increaseLoadingCounter
(
gadget
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
gadget
.
props
.
loading_counter
+=
1
;
if
(
gadget
.
props
.
loading_counter
===
1
)
{
return
gadget
.
getDeclaredGadget
(
"
header
"
)
.
push
(
function
(
header_gadget
)
{
return
header_gadget
.
notifyLoading
();
});
}
});
}
function
decreaseLoadingCounter
(
gadget
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
gadget
.
props
.
loading_counter
-=
1
;
if
(
gadget
.
props
.
loading_counter
<
0
)
{
gadget
.
props
.
loading_counter
=
0
;
// throw new Error("Unexpected negative loading counter");
}
if
(
gadget
.
props
.
loading_counter
===
0
)
{
return
gadget
.
getDeclaredGadget
(
"
header
"
)
.
push
(
function
(
header_gadget
)
{
return
header_gadget
.
notifyLoaded
();
});
}
});
}
function
callJioGadget
(
gadget
,
method
,
param_list
)
{
var
called
=
false
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
called
=
true
;
return
increaseLoadingCounter
(
gadget
);
})
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
"
jio_gadget
"
);
})
.
push
(
function
(
jio_gadget
)
{
return
jio_gadget
[
method
].
apply
(
jio_gadget
,
param_list
);
})
.
push
(
function
(
result
)
{
return
decreaseLoadingCounter
(
gadget
)
.
push
(
function
()
{
return
result
;
});
},
function
(
error
)
{
if
(
called
)
{
return
decreaseLoadingCounter
(
gadget
)
.
push
(
function
()
{
throw
error
;
});
}
throw
error
;
});
}
function
displayErrorContent
(
gadget
,
error
)
{
// Do not break the application in case of errors.
// Display it to the user for now,
// and allow user to go back to the frontpage
var
error_text
=
""
;
if
(
error
.
target
instanceof
XMLHttpRequest
)
{
error_text
=
error
.
target
.
toString
()
+
"
"
+
error
.
target
.
status
+
"
"
+
error
.
target
.
statusText
+
"
\n
"
+
error
.
target
.
responseURL
+
"
\n\n
"
+
error
.
target
.
getAllResponseHeaders
();
}
else
if
(
error
instanceof
Error
)
{
error_text
=
error
.
toString
();
}
else
{
error_text
=
JSON
.
stringify
(
error
);
}
console
.
error
(
error
);
if
(
error
instanceof
Error
)
{
console
.
error
(
error
.
stack
);
}
// XXX Improve error rendering
gadget
.
props
.
content_element
.
innerHTML
=
"
<br/><br/><br/><pre></pre>
"
;
gadget
.
props
.
content_element
.
querySelector
(
'
pre
'
).
textContent
=
"
Error:
"
+
error_text
;
// XXX Notify error
}
function
displayError
(
gadget
,
error
)
{
if
(
error
instanceof
RSVP
.
CancellationError
)
{
return
;
}
displayErrorContent
(
gadget
,
error
);
return
gadget
.
dropGadget
(
MAIN_SCOPE
)
.
push
(
undefined
,
function
()
{
// Do not crash the app if the pg gadget in not defined
// ie, keep the original error on screen
return
;
});
}
//////////////////////////////////////////
// Page rendering
//////////////////////////////////////////
rJS
(
window
)
.
ready
(
function
()
{
var
gadget
=
this
,
setting_gadget
,
setting
;
this
.
props
=
{
loading_counter
:
0
,
content_element
:
this
.
element
.
querySelector
(
'
.gadget-content
'
)
};
// Configure setting storage
return
gadget
.
getDeclaredGadget
(
"
setting_gadget
"
)
.
push
(
function
(
result
)
{
setting_gadget
=
result
;
return
setting_gadget
.
createJio
({
type
:
"
indexeddb
"
,
database
:
"
setting
"
});
})
.
push
(
function
()
{
return
setting_gadget
.
get
(
"
setting
"
)
.
push
(
undefined
,
function
(
error
)
{
if
(
error
.
status_code
===
404
)
{
return
{};
}
throw
error
;
});
})
.
push
(
function
(
result
)
{
setting
=
result
;
// Extract configuration parameters stored in HTML
// XXX Will work only if top gadget...
var
element_list
=
document
.
head
.
querySelectorAll
(
"
script[data-renderjs-configuration]
"
),
len
=
element_list
.
length
,
key
,
value
,
i
;
for
(
i
=
0
;
i
<
len
;
i
+=
1
)
{
key
=
element_list
[
i
].
getAttribute
(
'
data-renderjs-configuration
'
);
value
=
element_list
[
i
].
textContent
;
gadget
.
props
[
key
]
=
value
;
setting
[
key
]
=
value
;
}
// Calculate erp5 hateoas url
setting
.
hateoas_url
=
(
new
URI
(
gadget
.
props
.
hateoas_url
))
.
absoluteTo
(
location
.
href
)
.
toString
();
return
setting_gadget
.
put
(
"
setting
"
,
setting
);
})
.
push
(
function
()
{
// Configure jIO storage
return
gadget
.
getDeclaredGadget
(
"
jio_gadget
"
);
})
.
push
(
function
(
jio_gadget
)
{
if
(
setting
.
jio_storage_description
)
{
return
jio_gadget
.
createJio
(
setting
.
jio_storage_description
);
}
else
{
return
;
}
})
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
'
panel
'
);
})
.
push
(
function
(
panel_gadget
)
{
return
panel_gadget
.
render
();
})
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
'
router
'
);
})
.
push
(
function
(
router_gadget
)
{
return
router_gadget
.
start
();
});
})
//////////////////////////////////////////
// Allow Acquisition
//////////////////////////////////////////
.
allowPublicAcquisition
(
"
getSetting
"
,
function
(
argument_list
)
{
var
gadget
=
this
,
key
=
argument_list
[
0
],
default_value
=
argument_list
[
1
];
return
gadget
.
getDeclaredGadget
(
"
setting_gadget
"
)
.
push
(
function
(
jio_gadget
)
{
return
jio_gadget
.
get
(
"
setting
"
);
})
.
push
(
function
(
doc
)
{
return
doc
[
key
]
||
default_value
;
})
.
push
(
function
(
result
)
{
if
(
!
result
)
{
throw
"
The setting '
"
+
argument_list
[
0
]
+
"
' could not be found!
"
+
"
Please provide a default value to avoid this error,
"
+
"
either in gadget.getSetting('key', 'default_value'),
"
+
"
or in the Layout Configuration of your ERP5 Web Site.
"
+
"
Default values must not be falsy, e.g. null or undefined.
"
;
}
return
result
;
},
function
(
error
)
{
if
(
error
.
status_code
===
404
)
{
return
default_value
;
}
throw
error
;
});
})
.
allowPublicAcquisition
(
"
setSetting
"
,
function
(
argument_list
)
{
var
jio_gadget
,
gadget
=
this
,
key
=
argument_list
[
0
],
value
=
argument_list
[
1
];
return
gadget
.
getDeclaredGadget
(
"
setting_gadget
"
)
.
push
(
function
(
result
)
{
jio_gadget
=
result
;
return
jio_gadget
.
get
(
"
setting
"
);
})
.
push
(
undefined
,
function
(
error
)
{
if
(
error
.
status_code
===
404
)
{
return
{};
}
throw
error
;
})
.
push
(
function
(
doc
)
{
doc
[
key
]
=
value
;
return
jio_gadget
.
put
(
'
setting
'
,
doc
);
});
})
.
allowPublicAcquisition
(
"
translateHtml
"
,
function
(
argument_list
)
{
return
this
.
getDeclaredGadget
(
"
translation_gadget
"
)
.
push
(
function
(
translation_gadget
)
{
return
translation_gadget
.
translateHtml
(
argument_list
[
0
]);
});
})
// XXX Those methods may be directly integrated into the header,
// as it handles the submit triggering
.
allowPublicAcquisition
(
'
notifySubmitting
'
,
function
(
argument_list
)
{
return
RSVP
.
all
([
route
(
this
,
"
header
"
,
'
notifySubmitting
'
),
route
(
this
,
"
notification
"
,
'
notify
'
,
argument_list
)
]);
})
.
allowPublicAcquisition
(
'
notifySubmitted
'
,
function
(
argument_list
)
{
return
RSVP
.
all
([
route
(
this
,
"
header
"
,
'
notifySubmitted
'
),
route
(
this
,
"
notification
"
,
'
notify
'
,
argument_list
)
]);
})
.
allowPublicAcquisition
(
'
notifyChange
'
,
function
(
argument_list
)
{
return
RSVP
.
all
([
route
(
this
,
"
header
"
,
'
notifyChange
'
),
route
(
this
,
"
notification
"
,
'
notify
'
,
argument_list
)
]);
})
.
allowPublicAcquisition
(
'
refresh
'
,
function
()
{
var
gadget
=
this
;
return
gadget
.
getDeclaredGadget
(
MAIN_SCOPE
)
.
push
(
function
(
main
)
{
if
(
main
.
render
!==
undefined
)
{
return
main
.
render
(
JSON
.
parse
(
gadget
.
props
.
m_options_string
));
}
},
function
()
{
return
;
});
})
.
allowPublicAcquisition
(
"
translate
"
,
function
(
argument_list
)
{
return
this
.
getDeclaredGadget
(
"
translation_gadget
"
)
.
push
(
function
(
translation_gadget
)
{
return
translation_gadget
.
translate
(
argument_list
[
0
]);
});
})
.
allowPublicAcquisition
(
"
redirect
"
,
function
(
param_list
)
{
return
this
.
getDeclaredGadget
(
'
router
'
)
.
push
(
function
(
router_gadget
)
{
return
router_gadget
.
redirect
.
apply
(
router_gadget
,
param_list
);
});
})
.
allowPublicAcquisition
(
'
reload
'
,
function
()
{
// XXX does not actually reload the page
return
location
.
reload
();
})
.
allowPublicAcquisition
(
"
getUrlParameter
"
,
function
(
param_list
)
{
return
this
.
getDeclaredGadget
(
'
router
'
)
.
push
(
function
(
router_gadget
)
{
return
router_gadget
.
getUrlParameter
.
apply
(
router_gadget
,
param_list
);
});
})
.
allowPublicAcquisition
(
"
getUrlFor
"
,
function
(
param_list
)
{
return
this
.
getDeclaredGadget
(
'
router
'
)
.
push
(
function
(
router_gadget
)
{
return
router_gadget
.
getCommandUrlFor
.
apply
(
router_gadget
,
param_list
);
});
})
.
allowPublicAcquisition
(
"
updateHeader
"
,
function
(
param_list
)
{
var
gadget
=
this
;
initHeaderOptions
(
gadget
);
return
this
.
getDeclaredGadget
(
"
translation_gadget
"
)
.
push
(
function
(
translation_gadget
)
{
var
promise_list
=
[],
key
;
for
(
key
in
param_list
[
0
])
{
if
(
param_list
[
0
].
hasOwnProperty
(
key
))
{
gadget
.
props
.
header_argument_list
[
key
]
=
param_list
[
0
][
key
];
}
}
promise_list
.
push
(
translation_gadget
.
translate
(
gadget
.
props
.
header_argument_list
.
title
));
if
(
gadget
.
props
.
header_argument_list
.
hasOwnProperty
(
'
right_title
'
))
{
promise_list
.
push
(
translation_gadget
.
translate
(
gadget
.
props
.
header_argument_list
.
right_title
));
}
return
RSVP
.
all
(
promise_list
);
})
.
push
(
function
(
result_list
)
{
gadget
.
props
.
header_argument_list
.
title
=
result_list
[
0
];
if
(
result_list
.
length
===
2
)
{
gadget
.
props
.
header_argument_list
.
right_title
=
result_list
[
1
];
}
// XXX Sven hack: number of _url determine padding for
// subheader on ui-content
var
key
,
count
=
0
;
for
(
key
in
gadget
.
props
.
header_argument_list
)
{
if
(
gadget
.
props
.
header_argument_list
.
hasOwnProperty
(
key
))
{
if
(
key
.
indexOf
(
'
_url
'
)
>
-
1
)
{
count
+=
1
;
}
}
}
if
(
count
>
2
)
{
gadget
.
props
.
sub_header_class
=
"
ui-has-subheader
"
;
}
});
})
.
allowPublicAcquisition
(
'
triggerPanel
'
,
function
()
{
return
route
(
this
,
"
panel
"
,
"
toggle
"
);
})
.
allowPublicAcquisition
(
'
renderEditorPanel
'
,
function
(
param_list
)
{
return
route
(
this
,
"
editor_panel
"
,
'
render
'
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_allDocs
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
allDocs
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_remove
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
remove
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_post
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
post
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_put
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
put
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_get
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
get
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_allAttachments
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
allAttachments
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_getAttachment
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
getAttachment
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_putAttachment
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
putAttachment
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_removeAttachment
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
removeAttachment
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
jio_repair
"
,
function
(
param_list
)
{
return
callJioGadget
(
this
,
"
repair
"
,
param_list
);
})
.
allowPublicAcquisition
(
"
triggerSubmit
"
,
function
(
param_list
)
{
return
this
.
getDeclaredGadget
(
MAIN_SCOPE
)
.
push
(
function
(
main_gadget
)
{
return
main_gadget
.
triggerSubmit
(
param_list
);
});
})
.
allowPublicAcquisition
(
'
requireSetting
'
,
function
(
param_list
)
{
const
setting_key
=
param_list
[
0
];
const
redirect_page
=
param_list
[
1
];
const
success_queue
=
param_list
[
2
];
const
gadget
=
this
;
if
(
!
redirect_page
)
{
return
;
}
else
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
"
setting_gadget
"
);
})
.
push
(
function
(
jio_gadget
)
{
return
jio_gadget
.
get
(
"
setting
"
);
})
.
push
(
function
(
setting
)
{
if
(
!
setting
[
setting_key
])
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
"
router
"
);
})
.
push
(
function
(
router_gadget
)
{
return
router_gadget
.
redirect
({
command
:
'
display
'
,
options
:
{
page
:
redirect_page
},
});
});
}
else
{
return
success_queue
;
}
});
}
})
.
allowPublicAcquisition
(
"
renderApplication
"
,
function
(
param_list
)
{
return
this
.
render
.
apply
(
this
,
param_list
);
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.
onStateChange
(
function
(
modification_dict
)
{
var
gadget
=
this
,
route_result
=
gadget
.
state
;
if
(
modification_dict
.
hasOwnProperty
(
'
url
'
))
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
renderMainGadget
(
gadget
,
route_result
.
url
,
route_result
.
options
);
})
.
push
(
function
(
main_gadget
)
{
// Append loaded gadget in the page
if
(
main_gadget
!==
undefined
)
{
var
element
=
gadget
.
props
.
content_element
,
content_container
=
document
.
createDocumentFragment
();
// content_container.className = "ui-content " +
// (gadget.props.sub_header_class || "");
// reset subheader indicator
delete
gadget
.
props
.
sub_header_class
;
// go to the top of the page
window
.
scrollTo
(
0
,
0
);
// Clear first to DOM, append after to reduce flickering/manip
while
(
element
.
firstChild
)
{
element
.
removeChild
(
element
.
firstChild
);
}
content_container
.
appendChild
(
main_gadget
.
element
);
element
.
appendChild
(
content_container
);
return
updateHeader
(
gadget
);
// XXX Drop notification
// return header_gadget.notifyLoaded();
}
});
}
// Same subgadget
return
gadget
.
getDeclaredGadget
(
MAIN_SCOPE
)
.
push
(
function
(
page_gadget
)
{
return
page_gadget
.
render
(
gadget
.
state
.
options
);
})
.
push
(
function
()
{
return
updateHeader
(
gadget
);
});
})
// Render the page
.
declareMethod
(
'
render
'
,
function
(
route_result
,
keep_message
)
{
var
gadget
=
this
;
// Reinitialize the loading counter
gadget
.
props
.
loading_counter
=
0
;
// By default, init the header options to be empty
// (ERP5 title by default + sidebar)
initHeaderOptions
(
gadget
);
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
increaseLoadingCounter
(
gadget
);
})
.
push
(
function
()
{
var
promise_list
=
[
route
(
gadget
,
'
panel
'
,
'
close
'
),
route
(
gadget
,
'
editor_panel
'
,
'
close
'
)
];
if
(
keep_message
!==
true
)
{
promise_list
.
push
(
route
(
gadget
,
'
notification
'
,
'
close
'
));
}
return
RSVP
.
all
(
promise_list
);
})
.
push
(
function
()
{
return
gadget
.
changeState
({
url
:
route_result
.
url
,
options
:
route_result
.
options
});
})
.
push
(
function
()
{
return
decreaseLoadingCounter
(
gadget
);
},
function
(
error
)
{
return
decreaseLoadingCounter
(
gadget
)
.
push
(
function
()
{
throw
error
;
});
});
})
/////////////////////////////////
// Handle sub gadgets services
/////////////////////////////////
.
allowPublicAcquisition
(
'
reportServiceError
'
,
function
(
param_list
,
gadget_scope
)
{
if
(
gadget_scope
===
undefined
)
{
// don't fail in case of dropped subgadget (like previous page)
return
;
}
return
displayError
(
this
,
param_list
[
0
]);
})
.
onEvent
(
'
submit
'
,
function
()
{
return
displayError
(
this
,
new
Error
(
"
Unexpected form submit
"
));
});
}(
window
,
document
,
RSVP
,
rJS
,
XMLHttpRequest
,
location
,
console
));
\ No newline at end of file
bt5/officejs_eyqs/PathTemplateItem/web_page_module/
fast_priority_queue
_js.xml
→
bt5/officejs_eyqs/PathTemplateItem/web_page_module/
erp5_page_launcher
_js.xml
View file @
0d9586e0
...
...
@@ -79,7 +79,7 @@
</item>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
fast_priority_queue
.js
</string>
</value>
<value>
<string>
erp5_page_launcher
.js
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
...
...
@@ -89,13 +89,11 @@
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
fast_priority_queue
_js
</string>
</value>
<value>
<string>
erp5_page_launcher
_js
</string>
</value>
</item>
<item>
<key>
<string>
language
</string>
</key>
<value>
<none/>
</value>
<value>
<string>
en
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
...
...
@@ -109,13 +107,11 @@
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
Fast Priority Queue
JS
</string>
</value>
<value>
<string>
OfficeJS Launcher
JS
</string>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<none/>
</value>
<value>
<string>
001
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
bt5/officejs_eyqs/PathTemplateItem/web_page_module/fast_priority_queue_js.js
deleted
100644 → 0
View file @
edcd20f8
/**
* FastPriorityQueue.js : a fast heap-based priority queue in JavaScript.
* (c) the authors
* Licensed under the Apache License, Version 2.0.
*
* Speed-optimized heap-based priority queue for modern browsers and JavaScript engines.
*
* Usage :
Installation (in shell, if you use node):
$ npm install fastpriorityqueue
Running test program (in JavaScript):
// var FastPriorityQueue = require("fastpriorityqueue");// in node
var x = new FastPriorityQueue();
x.add(1);
x.add(0);
x.add(5);
x.add(4);
x.add(3);
x.peek(); // should return 0, leaves x unchanged
x.size; // should return 5, leaves x unchanged
while(!x.isEmpty()) {
console.log(x.poll());
} // will print 0 1 3 4 5
x.trim(); // (optional) optimizes memory usage
*/
"
use strict
"
;
var
defaultcomparator
=
function
(
a
,
b
)
{
return
a
<
b
;
};
// the provided comparator function should take a, b and return *true* when a < b
function
FastPriorityQueue
(
comparator
)
{
this
.
array
=
[];
this
.
size
=
0
;
this
.
compare
=
comparator
||
defaultcomparator
;
}
// Add an element the the queue
// runs in O(log n) time
FastPriorityQueue
.
prototype
.
add
=
function
(
myval
)
{
var
i
=
this
.
size
;
this
.
array
[
this
.
size
]
=
myval
;
this
.
size
+=
1
;
var
p
;
var
ap
;
while
(
i
>
0
)
{
p
=
(
i
-
1
)
>>
1
;
ap
=
this
.
array
[
p
];
if
(
!
this
.
compare
(
myval
,
ap
))
{
break
;
}
this
.
array
[
i
]
=
ap
;
i
=
p
;
}
this
.
array
[
i
]
=
myval
;
};
// replace the content of the heap by provided array and "heapifies it"
FastPriorityQueue
.
prototype
.
heapify
=
function
(
arr
)
{
this
.
array
=
arr
;
this
.
size
=
arr
.
length
;
var
i
;
for
(
i
=
(
this
.
size
>>
1
);
i
>=
0
;
i
--
)
{
this
.
_percolateDown
(
i
);
}
};
// for internal use
FastPriorityQueue
.
prototype
.
_percolateUp
=
function
(
i
)
{
var
myval
=
this
.
array
[
i
];
var
p
;
var
ap
;
while
(
i
>
0
)
{
p
=
(
i
-
1
)
>>
1
;
ap
=
this
.
array
[
p
];
if
(
!
this
.
compare
(
myval
,
ap
))
{
break
;
}
this
.
array
[
i
]
=
ap
;
i
=
p
;
}
this
.
array
[
i
]
=
myval
;
};
// for internal use
FastPriorityQueue
.
prototype
.
_percolateDown
=
function
(
i
)
{
var
size
=
this
.
size
;
var
hsize
=
this
.
size
>>>
1
;
var
ai
=
this
.
array
[
i
];
var
l
;
var
r
;
var
bestc
;
while
(
i
<
hsize
)
{
l
=
(
i
<<
1
)
+
1
;
r
=
l
+
1
;
bestc
=
this
.
array
[
l
];
if
(
r
<
size
)
{
if
(
this
.
compare
(
this
.
array
[
r
],
bestc
))
{
l
=
r
;
bestc
=
this
.
array
[
r
];
}
}
if
(
!
this
.
compare
(
bestc
,
ai
))
{
break
;
}
this
.
array
[
i
]
=
bestc
;
i
=
l
;
}
this
.
array
[
i
]
=
ai
;
};
// Look at the top of the queue (a smallest element)
// executes in constant time
//
// This function assumes that the priority queue is
// not empty and the caller is resposible for the check.
// You can use an expression such as
// "isEmpty() ? undefined : peek()"
// if you expect to be calling peek on an empty priority queue.
//
FastPriorityQueue
.
prototype
.
peek
=
function
()
{
return
this
.
array
[
0
];
};
// remove the element on top of the heap (a smallest element)
// runs in logarithmic time
//
//
// This function assumes that the priority queue is
// not empty, and the caller is responsible for the check.
// You can use an expression such as
// "isEmpty() ? undefined : poll()"
// if you expect to be calling poll on an empty priority queue.
//
// For long-running and large priority queues, or priority queues
// storing large objects, you may want to call the trim function
// at strategic times to recover allocated memory.
FastPriorityQueue
.
prototype
.
poll
=
function
()
{
var
ans
=
this
.
array
[
0
];
if
(
this
.
size
>
1
)
{
this
.
array
[
0
]
=
this
.
array
[
--
this
.
size
];
this
.
_percolateDown
(
0
|
0
);
}
else
{
this
.
size
-=
1
;
}
return
ans
;
};
// recover unused memory (for long-running priority queues)
FastPriorityQueue
.
prototype
.
trim
=
function
()
{
this
.
array
=
this
.
array
.
slice
(
0
,
this
.
size
);
};
// Check whether the heap is empty
FastPriorityQueue
.
prototype
.
isEmpty
=
function
()
{
return
this
.
size
===
0
;
};
// just for illustration purposes
var
main
=
function
()
{
// main code
var
x
=
new
FastPriorityQueue
(
function
(
a
,
b
)
{
return
a
<
b
;
});
x
.
add
(
1
);
x
.
add
(
0
);
x
.
add
(
5
);
x
.
add
(
4
);
x
.
add
(
3
);
while
(
!
x
.
isEmpty
())
{
console
.
log
(
x
.
poll
());
}
};
\ No newline at end of file
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_box_html.html
View file @
0d9586e0
...
...
@@ -7,8 +7,7 @@
<script
src=
"rsvp.js"
></script>
<script
src=
"renderjs.js"
></script>
<script
src=
"jiodev.js"
></script>
<script
src=
"gadget_global.js"
></script>
<script
src=
"fast_priority_queue.js"
></script>
<script
src=
"gadget_global.js"
></script>
<script
src=
"gadget_erp5_page_chat_box.js"
></script>
</head>
<body>
...
...
@@ -26,11 +25,7 @@
</form>
<form
class=
"join-form"
>
<input
type=
"text"
name=
"content"
/>
<input
type=
"submit"
value=
"Add new contact (join existing room as guest)!"
/>
</form>
<form
class=
"make-form"
>
<input
type=
"text"
name=
"content"
/>
<input
type=
"submit"
value=
"Add new room (make new room as host)!"
/>
<input
type=
"submit"
value=
"Join room!"
/>
</form>
</div>
</div>
...
...
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_box_js.js
View file @
0d9586e0
/*jslint nomen: true, indent: 2, maxerr: 3
00, maxlen: 80
*/
/*global window, document, RSVP, rJS,
FastPriorityQueue
*/
(
function
(
window
,
document
,
RSVP
,
rJS
,
FastPriorityQueue
)
{
/*jslint nomen: true, indent: 2, maxerr: 3
, maxlen: 80
*/
/*global window, document, RSVP, rJS,
promiseEventListener
*/
(
function
(
window
,
document
,
RSVP
,
rJS
,
promiseEventListener
)
{
"
use strict
"
;
/* Settings required:
* - jio_storage_description, or be redirected
* - user_email
* - user-email
* Settings used:
* - default_jio_type, default: ""
* - default_erp5_url, default: ""
* - default_dav_url, default: ""
*/
/* Abstract Data Types:
* message is a JSON object representing a message with all its metadata.
* chat is messageToChat(message) for displaying an element in the chat log.
* Message Types:
* message is a typical message, with an author and timestamp.
* notification is a system-generated message, with no author.
* bundle is a list of new messages to be added to the local archive.
* request is a dictionary of the times of the last messages of each peer.
/* Check if a string ends with another string.
* Parameters:
* - string: the string that may or may not end with the suffix string
* - suffix: the substring that may or may not be in the end of the string
* Effects: nothing
* Returns: true if string ends with suffix, otherwise false
*/
/* Program Workflow:
* JIO storage (the "archive") can only bepag accessed through two functions:
* - getLocalArchive takes the archive and stores it in the list
* - storeArchive stores a message in the archive
* Local storage (the "list") is always in sorted order and
* can only be accessed through three functions:
* - sendLocalArchive takes the list and sends it over WebRTC
* - storeList stores a message in the list
* - refreshChat sorts the entire list
* The displayed chat log can only be accessed through two functions:
* - appendMessage turns a message into a chat and appends it to the log
* - refreshChat takes the list to overwrite chat log
* Peer interaction via WebRTC can only be accessed through four functions:
* - deployMessage sends a message over WebRTC
* - getMessage gets a message over WebRTC
* - sendLocalArchive sends the list over WebRTC
* - getRemoteArchive gets a list over WebRTC
function
stringEndsWith
(
string
,
suffix
)
{
return
string
.
indexOf
(
suffix
,
string
.
length
-
suffix
.
length
)
!==
-
1
;
}
/* Translate an arbitrary name to a querySelector-safe ID.
* Parameters:
* - name: the name to use as an ID
* Effects: nothing
* Returns: name with all non-alphanumeric characters replaced by hyphens
*/
/* Summary:
* - getLocalArchive takes archive, calls storeList, appendMessage on each
* - sendLocalArchive sends the list to peer
* - getRemoteArchive gets a list from peer, calls storeArchive on each
* - deployMessage sends a message to peer, calls getMessage
* - getMessage gets peer, calls storeArchive, storeList, appendMessage
* - storeArchive stores a message in the archive
* - storeList stores a message in the list
* - appendMessage calls messageToChat, appends it to the chat log
* - refreshChat takes the list, overwrites the chat log
*/
function
logError
(
error
)
{
console
.
log
(
error
);
function
nameToId
(
name
)
{
return
name
.
replace
(
/
\W
/gi
,
"
-
"
);
}
function
logQueue
(
action
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
action
;
})
.
push
(
null
,
logError
);
}
function
styleElementByQuery
(
gadget
,
query
,
style
)
{
gadget
.
element
.
querySelector
(
query
).
style
.
display
=
style
;
}
/* Reset a text input.
* Parameters:
* - element: the text input element to reset
* Effects: set the value of the text input to the empty string
* Returns: the previous value of the text input before resetting it
*/
function
resetInputValue
(
element
)
{
const
value
=
element
.
value
;
var
value
=
element
.
value
;
element
.
value
=
""
;
return
value
;
}
function
getQueryValue
(
query_list
,
query_string
)
{
for
(
let
i
=
0
,
i_len
=
query_list
.
length
;
i
<
i_len
;
i
++
)
{
const
query
=
query_list
[
i
];
if
(
query_string
.
indexOf
(
query
+
"
=
"
)
!==
-
1
)
{
const
start
=
query_string
.
indexOf
(
query
+
"
=
"
)
+
query
.
length
+
1
;
let
end
=
query_string
.
indexOf
(
"
&
"
,
start
);
if
(
end
===
-
1
)
{
end
=
query_string
.
length
;
}
return
query_string
.
slice
(
start
,
end
);
}
}
return
null
;
}
function
setQueryValue
(
query_list
,
query_string
,
element
)
{
const
value
=
getQueryValue
(
query_list
,
query_string
);
if
(
value
)
{
element
.
value
=
value
;
}
}
/* Set the display style of the element given by a query.
* Parameters:
* - query: the query for which to find the element using querySelector
* - style: the display style to set the element to, example: "block"
* Effects: set the display style of the element to the given style
*/
function
pollUntilNotNull
(
gadget
,
delay_ms
,
timeout_ms
,
nullableFunction
,
callbackFunction
)
{
if
(
callbackFunction
===
undefined
)
{
callbackFunction
=
function
()
{};
function
styleElementByQuery
(
gadget
,
query
,
style
)
{
if
(
gadget
.
element
.
querySelector
(
query
))
{
gadget
.
element
.
querySelector
(
query
).
style
.
display
=
style
;
}
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
nullableFunction
();
})
.
push
(
function
(
result
)
{
if
(
result
!==
null
)
{
return
callbackFunction
(
result
);
}
else
{
return
RSVP
.
any
([
RSVP
.
timeout
(
timeout_ms
),
promiseDoWhile
(
function
()
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
RSVP
.
delay
(
delay_ms
);
})
.
push
(
function
()
{
return
nullableFunction
();
})
.
push
(
function
(
result
)
{
if
(
result
===
null
)
{
return
null
;
}
else
{
return
callbackFunction
(
result
);
}
})
.
push
(
function
(
nullable
)
{
return
nullable
===
null
;
})
.
push
(
null
,
logError
);
})
]);
}
});
}
/* Translate an arbitrary name to a querySelector-safe ID.
* Parameters:
* - name: the name to use as an ID
* Returns: name with all non-alphanumeric characters replaced by underscores
* Effects: none
*/
function
nameToRoom
(
name
)
{
return
name
.
replace
(
/
\W
/gi
,
"
_
"
);
}
/*
Check if a string ends with another string
.
/*
Get the element given by a contact
.
* Parameters:
* - string: the string that may or may not end with the suffix string
* - suffix: the substring that may or may not be in the end of the string
* Returns: true if string ends with suffix, otherwise false
* Effects: none
* - contact: the contact for which to find the element
* Effects: nothing
* Returns: the element corresponding to the given contact
*/
function
stringEndsWith
(
string
,
suffix
)
{
return
string
.
indexOf
(
suffix
,
string
.
length
-
suffix
.
length
)
!==
-
1
;
}
/* Get the creation epoch time of a message.
* Parameters:
* - message: the message whose creation time is desired
* Returns: the creation time of the message, in milliseconds since 1970.
* Effects: none
*/
function
getTime
(
message
)
{
return
new
Date
(
message
.
time
).
getTime
();
function
getElementFromContact
(
gadget
,
contact
)
{
return
gadget
.
element
.
querySelector
(
"
#chat-contact-
"
+
nameToId
(
contact
));
}
/* Check if a message is new.
* Parameters:
* - message: the message that may or may not be new
* - last_time: the time in milliseconds since 1970 that splits old from new
* Returns: true if the message was created after last_time, otherwise false
* Effects: none
*/
function
isNewMessage
(
message
,
last_time
)
{
return
last_time
===
undefined
||
last_time
<
getTime
(
message
);
}
/*
Check if two messages are the same
.
/*
Highlight the current contact
.
* Parameters:
* - lhs, rhs: the two messages that may or may not be the same
* Returns: true if both messages exist and have equivalent properties.
* Effects: none
* - contact: the current contact to be highlighted
* - previous_contact: the previously highlighted contact
* Effects:
* - highlight contact by adding the "current" class on its contact element
* - unhighlight previous_contact by removing the "current class"
*/
function
isSameMessage
(
lhs
,
rhs
)
{
return
lhs
!==
undefined
&&
rhs
!==
undefined
&&
lhs
.
name
===
rhs
.
name
&&
lhs
.
content
===
rhs
.
content
&&
lhs
.
room
===
rhs
.
room
&&
getTime
(
lhs
)
===
getTime
(
rhs
);
function
highlightContact
(
gadget
,
contact
)
{
var
contact_element
=
getElementFromContact
(
gadget
,
contact
),
previous_element
=
getElementFromContact
(
gadget
,
gadget
.
state
.
contact
);
contact_element
.
classList
.
add
(
"
current
"
);
if
(
previous_element
)
{
previous_element
.
classList
.
remove
(
"
current
"
);
}
}
/* Keep messages in chronological order, for FastPriorityQueue.
/* Notify the user.
* Parameters:
* - ascending_order: true if the order is ascending, otherwise false
* Returns: a comparator for sorting messages using FastPriorityQueue
* Effects: none
* - room: the room that triggers the notification
* - notify: true to notify, false to remove notification
* Effects:
* - toggle "notify" class on the contact element corresponding to room
* - toggle the favicon between alert and default icons
*/
function
messageTimeCompare
(
ascending_order
)
{
if
(
ascending_order
)
{
return
function
(
lhs
,
rhs
)
{
return
getTime
(
lhs
)
<
getTime
(
rhs
);
};
function
notifyStatus
(
gadget
,
room
,
notify
)
{
var
contact_element
=
getElementFromContact
(
gadget
,
room
),
favicon_element
=
document
.
querySelector
(
"
link[rel*='icon']
"
)
||
document
.
createElement
(
"
link
"
);
if
(
notify
)
{
contact_element
.
classList
.
add
(
"
notify
"
);
favicon_element
.
href
=
gadget
.
state
.
alert_icon_url
;
}
else
{
contact_element
.
classList
.
remove
(
"
notify
"
);
favicon_element
.
href
=
gadget
.
state
.
default_icon_url
;
}
return
function
(
lhs
,
rhs
)
{
return
getTime
(
lhs
)
>
getTime
(
rhs
)
;
}
;
favicon_element
.
type
=
"
image/x-icon
"
;
favicon_element
.
rel
=
"
shortcut icon
"
;
document
.
head
.
appendChild
(
favicon_element
)
;
}
/* Keep messages in chronologically ascending order, for refreshChat.
/* Get the creation epoch time of a message.
* Parameters:
* -
lhs, rhs: two messages to compare during the sorting algorithm
*
Returns: the correct value for sorting messages using sort()
*
Effects: none
* -
message: the message whose creation time is desired
*
Effects: nothing
*
Returns: the creation time of the message, in milliseconds since 1970.
*/
function
messageTimeComparator
(
lhs
,
rhs
)
{
if
(
getTime
(
lhs
)
<
getTime
(
rhs
))
{
return
-
1
;
}
if
(
getTime
(
lhs
)
>
getTime
(
rhs
))
{
return
1
;
}
return
0
;
function
getTime
(
message
)
{
return
new
Date
(
message
.
time
).
getTime
();
}
/* Translate a JSON message to an HTML chat element.
* Parameters:
* - message: the JavaScript object to display in HTML
* Effects: nothing
* Returns: a HTML representation of the given message
* Effects: none
*/
function
messageToChat
(
message
)
{
var
matches
,
i
,
i_len
,
j
,
j_len
,
image
,
link
,
var
i
,
j
,
matches
,
image
,
link
,
link_string
,
dot_count
,
is_image
,
absolute_url
,
chat
=
document
.
createElement
(
"
li
"
),
image_extensions
=
[
"
.jpg
"
,
"
.png
"
,
"
.gif
"
,
"
.bmp
"
,
"
.tif
"
,
"
.svg
"
],
url_regex
=
/
((?:
https
?
:
\/\/)?(?:[\-
a-zA-Z0-9_~
\/]
+
\.)
+
[\-
a-zA-Z0-9_~#?&=
\/]
+
)
/g
;
switch
(
message
.
type
)
{
case
"
bundle
"
:
break
;
case
"
notification
"
:
/
((?:
https
?
:
\/\/)?(?:[\-
a-zA-Z0-9_~
\/
@
]
+
\.)
+
[\-
a-zA-Z0-9_~#?&=
\/]
+
)
/g
;
if
(
message
.
type
===
"
notification
"
)
{
chat
.
appendChild
(
document
.
createTextNode
(
message
.
content
));
chat
.
style
.
color
=
message
.
colo
u
r
;
return
chat
;
case
"
message
"
:
chat
.
style
.
color
=
message
.
color
;
}
else
if
(
message
.
type
===
"
message
"
)
{
// Put message in the format "[3/24/2017, 11:30:52 AM] user: message"
chat
.
appendChild
(
document
.
createTextNode
(
"
[
"
+
new
Date
(
message
.
time
).
toLocaleString
()
+
"
]
"
+
message
.
name
+
"
:
"
));
// Loop through all potential URLs in the message
// matches[i] is the non-link content, matches[i + 1] is the actual link
matches
=
message
.
content
.
split
(
url_regex
);
for
(
i
=
0
,
i_len
=
matches
.
length
-
1
;
i
<
i_len
;
i
+=
2
)
{
for
(
i
=
0
;
i
<
matches
.
length
-
1
;
i
+=
2
)
{
chat
.
appendChild
(
document
.
createTextNode
(
matches
[
i
]));
link_string
=
matches
[
i
+
1
];
dot_count
=
link_string
.
match
(
/
\.
/g
).
length
;
// If 2d + 1 >= L, then the potential URL has only single letters,
// so ignore it to eliminate acronyms like e.g., i.e., U.S.A., etc.
link_string
=
matches
[
i
+
1
];
dot_count
=
link_string
.
match
(
/
\.
/g
).
length
;
if
(
2
*
dot_count
+
1
>=
link_string
.
length
)
{
chat
.
appendChild
(
document
.
createTextNode
(
link_string
));
}
else
{
is_image
=
false
;
// Add a protocol to transform relative URLs into absolute URLs
if
(
link_string
.
indexOf
(
"
:
"
)
!==
-
1
)
{
absolute_url
=
link_string
;
}
else
{
absolute_url
=
"
http://
"
+
link_string
;
}
// Create an image if the URL ends with one of the image extensions
for
(
j
=
0
,
j_len
=
image_extensions
.
length
;
j
<
j_len
;
j
+=
1
)
{
for
(
j
=
0
;
j
<
image_extensions
.
length
;
j
+=
1
)
{
if
(
stringEndsWith
(
link_string
,
image_extensions
[
j
]))
{
image
=
document
.
createElement
(
"
img
"
);
image
.
src
=
absolute_url
;
...
...
@@ -275,6 +191,7 @@
break
;
}
}
// Otherwise, create a link
if
(
!
is_image
)
{
link
=
document
.
createElement
(
"
a
"
);
...
...
@@ -284,93 +201,75 @@
}
}
}
// Add the last non-link content and return the resulting chat element
chat
.
appendChild
(
document
.
createTextNode
(
matches
[
matches
.
length
-
1
]));
chat
.
style
.
color
=
message
.
colour
;
return
chat
;
chat
.
style
.
color
=
message
.
color
;
}
return
chat
;
}
rJS
(
window
)
.
setState
({
name
:
null
,
auth
:
null
,
dropbox_folder
:
null
,
erp5_url
:
null
,
room
:
null
,
element
:
null
,
initialized
:
false
,
// A set of names of current rooms; as a guest, only notify that
// you have joined once you have received the host's remote archive,
// so that your notification doesn't override all previous messages
// room_set["room"] = false if joined, true if also notified
contact
:
null
,
room_set
:
{},
// A dictionary of messages based on the current room, e.g.
// message_list_dict["room"] = [message1, message2, ...]
message_list_dict
:
{},
// A dictionary of epoch times of the last messages received, e.g.
// last_message_dict["room"]["name"] = 1234567890
last_message_dict
:
{},
alert_icon
:
"
https://pricespy.co.nz/favicon.ico
"
,
default_icon
:
"
https://softinst75770.host.vifib.net/
"
alert_icon_url
:
"
https://pricespy.co.nz/favicon.ico
"
,
default_icon_url
:
"
https://softinst75770.host.vifib.net/
"
+
"
erp5/web_site_module/web_chat/favicon.ico
"
})
.
declareService
(
function
()
{
var
gadget
=
this
;
return
gadget
.
render
();
})
// The following functions are all acquired from erp5_page_launcher.
// The following functions are all acquired from erp5_launcher_nojqm.js
.
declareAcquiredMethod
(
"
updateHeader
"
,
"
updateHeader
"
)
.
declareAcquiredMethod
(
"
getSetting
"
,
"
getSetting
"
)
.
declareAcquiredMethod
(
"
requireSetting
"
,
"
requireSetting
"
)
.
declareAcquiredMethod
(
"
jio_allDocs
"
,
"
jio_allDocs
"
)
.
declareAcquiredMethod
(
"
jio_put
"
,
"
jio_put
"
)
.
declareAcquiredMethod
(
"
jio_repair
"
,
"
jio_repair
"
)
.
declareAcquiredMethod
(
"
getSetting
"
,
"
getSetting
"
)
/* Get the contact's jIO ID from their email address.
* Parameters:
* - param_list[0]: the email address of the contact
* Returns: the ID of the contact if found in jIO storage, otherwise null
* Effects: none
*/
.
allowPublicAcquisition
(
"
getContactByEmail
"
,
function
(
param_list
)
{
var
gadget
=
this
,
email
=
param_list
[
0
],
i
,
i_len
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
jio_allDocs
({
limit
:
[
0
,
1000000
],
query
:
'
portal_type: "Person"
'
,
sort_on
:
[[
"
last_modified
"
,
"
descending
"
]],
select_list
:
[
"
default_email_coordinate_text
"
],
});
})
.
push
(
function
(
person_list
)
{
for
(
i
=
0
,
i_len
=
person_list
.
data
.
total_rows
;
i
<
i_len
;
i
+=
1
)
{
if
(
person_list
.
data
.
rows
[
i
].
value
.
default_email_coordinate_text
===
email
)
{
return
person_list
.
data
.
rows
[
i
].
id
;
}
}
return
null
;
})
.
push
(
null
,
logError
);
// The following function is acquired by gadget_erp5_chat_room.
.
allowPublicAcquisition
(
"
changeRoom
"
,
function
(
param_list
)
{
var
gadget
=
this
;
return
gadget
.
changeRoom
.
apply
(
gadget
,
param_list
);
})
/* Render the gadget
// Set the chat title when the current room changes.
.
onStateChange
(
function
(
modification_dict
)
{
var
gadget
=
this
;
if
(
modification_dict
.
hasOwnProperty
(
"
room
"
))
{
styleElementByQuery
(
gadget
,
"
#room-gadget-
"
+
nameToId
(
gadget
.
state
.
contact
),
"
none
"
);
styleElementByQuery
(
gadget
,
"
.chat-right-panel-chat
"
,
"
flex
"
);
gadget
.
element
.
querySelector
(
"
.chat-title
"
)
.
textContent
=
"
Room:
"
+
modification_dict
.
room
;
}
else
if
(
modification_dict
.
hasOwnProperty
(
"
contact
"
))
{
styleElementByQuery
(
gadget
,
"
#room-gadget-
"
+
nameToId
(
gadget
.
state
.
contact
),
"
none
"
);
styleElementByQuery
(
gadget
,
"
#room-gadget-
"
+
nameToId
(
modification_dict
.
contact
),
"
block
"
);
styleElementByQuery
(
gadget
,
"
.chat-right-panel-chat
"
,
"
none
"
);
gadget
.
element
.
querySelector
(
"
.chat-title
"
)
.
textContent
=
"
Contact:
"
+
modification_dict
.
contact
;
}
})
/* Render the gadget.
* Parameters:
* - get setting: jio_storage_description, user_email
* - getSetting: user_email, jio_storage_description,
* default_jio_type, default_erp5_url, default_dav_url
* Effects:
* - update header, page_title to "OfficeJS Chat"
* - redirect if no jIO storage available
* -
join the user home room
whose name is the user name
* -
create the user contact,
whose name is the user name
*/
.
declareMethod
(
"
render
"
,
function
()
{
var
gadget
=
this
;
return
gadget
.
requireSetting
(
...
...
@@ -379,779 +278,432 @@
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
updateHeader
({
page_title
:
"
OfficeJS Chat
"
,
page_title
:
"
OfficeJS Chat
"
});
})
.
push
(
function
()
{
return
gadget
.
getSetting
(
"
user_email
"
);
return
RSVP
.
all
([
gadget
.
getSetting
(
"
user_email
"
),
gadget
.
getSetting
(
"
jio_storage_description
"
),
gadget
.
getSetting
(
"
default_jio_type
"
,
"
none
"
),
gadget
.
getSetting
(
"
default_erp5_url
"
,
"
none
"
),
gadget
.
getSetting
(
"
default_dav_url
"
,
"
none
"
)
]);
})
.
push
(
function
(
email
)
{
gadget
.
state
.
room
=
email
.
replace
(
/
[^
0-9a-z
\-]
/gi
,
"
-
"
);
gadget
.
state
.
name
=
gadget
.
state
.
room
;
gadget
.
element
.
querySelector
(
"
.send-form input[type='text']
"
).
onfocus
=
function
()
{
return
logQueue
(
gadget
.
notifyStatus
(
gadget
.
state
.
room
,
false
));
};
.
push
(
function
(
setting_list
)
{
return
gadget
.
changeState
({
name
:
setting_list
[
0
],
contact
:
setting_list
[
0
],
local_sub_storage
:
setting_list
[
1
],
default_jio_type
:
setting_list
[
2
]
===
"
none
"
?
null
:
setting_list
[
2
],
default_erp5_url
:
setting_list
[
3
]
===
"
none
"
?
null
:
setting_list
[
3
],
default_dav_url
:
setting_list
[
4
]
===
"
none
"
?
null
:
setting_list
[
4
]
});
})
.
push
(
function
()
{
return
gadget
.
createContact
({
room
:
gadget
.
state
.
room
,
role
:
"
host
"
});
gadget
.
element
.
querySelector
(
"
.send-form input[type='text']
"
)
.
onfocus
=
function
()
{
return
notifyStatus
(
gadget
,
gadget
.
state
.
room
,
false
);
};
return
gadget
.
createContact
(
gadget
.
state
.
contact
);
})
);
})
/* Send a message via the appropriate WebRTC channel.
/* Create a new contact.
* Parameters:
* - message: the message to send, whose room is the selected WebRTC room
* - source: the WebRTC data channel that sent the original message
* Returns: nothing
* Effects: calls sendMessage on the WebRTC gadget
* - contact: the name of the contact
* Effects:
* - append a new contact to the contact list
* - create a new room gadget
* - show the chat box
*/
.
declareMethod
(
"
sendMessage
"
,
function
(
message
,
source
)
{
.
declareMethod
(
"
createContact
"
,
function
(
contact
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
(
)
return
gadget
.
appendContact
(
contact
)
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
"
webrtc_gadget_
"
+
message
.
room
);
})
.
push
(
function
(
webrtc_gadget
)
{
return
webrtc_gadget
.
sendMessage
.
apply
(
webrtc_gadget
,
[
message
,
source
]);
return
gadget
.
createRoom
(
contact
);
})
.
push
(
null
,
logError
);
})
.
declareMethod
(
"
chooseRoom
"
,
function
(
param_dict
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
declareGadget
(
"
gadget_erp5_chat_webrtc.html
"
,
{
scope
:
"
webrtc_gadget_
"
+
param_dict
.
room
});
})
.
push
(
function
(
webrtc_gadget
)
{
var
fields
=
webrtc_gadget
.
element
.
querySelector
(
"
.contact-form
"
).
elements
;
fields
.
dropbox_folder
.
value
=
param_dict
.
dropbox_folder
||
gadget
.
state
.
dropbox_folder
;
fields
.
erp5_url
.
value
=
param_dict
.
erp5_url
||
gadget
.
state
.
erp5_url
;
webrtc_gadget
.
element
.
querySelector
(
"
.auth-form
"
)
.
auth
.
value
=
param_dict
.
auth
||
gadget
.
state
.
auth
;
gadget
.
element
.
querySelector
(
"
.chat-right-panel
"
).
insertBefore
(
webrtc_gadget
.
element
,
gadget
.
element
.
querySelector
(
"
.chat-max-height-wrapper
"
));
webrtc_gadget
.
state
.
login_dict
=
{
room
:
param_dict
.
room
,
name
:
gadget
.
state
.
name
,
role
:
param_dict
.
role
,
};
webrtc_gadget
.
state
.
dataChannelOnopen
=
function
()
{
return
gadget
.
changeRoom
(
param_dict
.
room
);
};
webrtc_gadget
.
state
.
dataChannelOnmessage
=
function
(
event
)
{
var
message
=
JSON
.
parse
(
event
.
data
);
var
source
=
event
.
srcElement
;
if
(
message
.
type
===
"
notification
"
||
message
.
type
===
"
message
"
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
getMessage
(
message
);
})
.
push
(
function
()
{
if
(
param_dict
.
role
===
"
host
"
)
{
return
webrtc_gadget
.
sendMessage
(
message
,
source
);
}
else
{
return
;
}
})
.
push
(
null
,
logError
);
}
else
if
(
message
.
type
===
"
bundle
"
)
{
if
(
param_dict
.
role
===
"
host
"
)
{
webrtc_gadget
.
state
.
archive_amount
+=
1
;
if
(
webrtc_gadget
.
state
.
archive_amount
>=
webrtc_gadget
.
state
.
guest_amount
)
{
webrtc_gadget
.
state
.
archive_amount
=
0
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
getRemoteArchive
(
message
);
})
.
push
(
function
()
{
return
gadget
.
requestRequest
();
})
.
push
(
null
,
logError
);
}
}
else
{
return
gadget
.
getRemoteArchive
(
message
);
}
}
else
if
(
message
.
type
===
"
request
"
)
{
return
gadget
.
sendLocalArchive
(
message
,
source
);
}
else
if
(
message
.
type
===
"
doubler
"
)
{
return
gadget
.
sendRequest
();
}
};
return
webrtc_gadget
.
render
();
})
.
push
(
null
,
logError
);
return
gadget
.
changeState
({
contact
:
contact
});
});
})
/*
return gadget.createJio({
remote: fields.remote.value,
dropbox_folder: fields.remote_dropbox_folder.value,
erp5_url: fields.remote_erp5_url.value,
dav_url: fields.remote_dav_url.value,
dav_user: fields.remote_dav_user.value,
dav_pass: fields.remote_dav_pass.value,
/* Append a new contact element to the contact list.
* Parameters:
* - contact: the name of the contact
* Effects:
* - if the contact is not blank and not a duplicate, then:
* - create and append a new contact element to the contact list
* - set its ID to a querySelector-safe translation of its name
* - highlight it and add an event listener to highlight it on click
* and either change to the room or the contact
*/
.
declareMethod
(
"
appendContact
"
,
function
(
contact
)
{
var
gadget
=
this
,
contact_element
;
if
(
!
contact
.
trim
())
{
throw
"
An invisible name is not allowed! You couldn't click on it!
"
;
}
if
(
getElementFromContact
(
gadget
,
contact
))
{
throw
"
A contact with the same name already exists!
"
;
}
contact_element
=
document
.
createElement
(
"
li
"
);
contact_element
.
appendChild
(
document
.
createTextNode
(
contact
));
contact_element
.
setAttribute
(
"
id
"
,
"
chat-contact-
"
+
nameToId
(
contact
));
gadget
.
element
.
querySelector
(
"
.contact-list
"
)
.
appendChild
(
contact_element
);
highlightContact
(
gadget
,
contact
);
contact_element
.
addEventListener
(
"
click
"
,
function
()
{
return
notifyStatus
(
gadget
,
contact
,
false
)
.
push
(
function
()
{
highlightContact
(
gadget
,
contact
);
if
(
gadget
.
state
.
room_set
[
contact
])
{
return
gadget
.
changeRoom
(
contact
);
}
return
gadget
.
changeState
({
contact
:
contact
});
});
})
.push(function () {
return gadget.jio_repair();
})
*/
/*
},
false
);
})
.declareMethod("createJio", function (param_dict) {
var gadget = this;
return new RSVP.Queue()
.push(function () {
var remote_config = {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs-chat",
},
},
};
var remote_post = true;
// We want the remote ERP5 storage to be canonical, so true for ERP5.
// Post is not implemented in drivetojiomapping, so false for others.
switch (param_dict.remote) {
case "dropbox":
var start = document.URL.indexOf("access_token=") + 13;
var end = document.URL.indexOf("&", start);
var token = document.URL.slice(start, end);
remote_config = {
type: "query",
sub_storage: {
type: "drivetojiomapping",
sub_storage: {
type: "dropbox",
access_token: token,
root: "dropbox",
},
},
};
remote_post = false;
break;
case "dav":
remote_config = {
type: "query",
sub_storage: {
type: "drivetojiomapping",
sub_storage: {
type: "dav",
url: param_dict.dav_url,
basic_login: btoa(param_dict.dav_user
+ ":" + param_dict.dav_pass),
with_credentials: true,
},
},
};
remote_post = false;
break;
case "erp5":
remote_config = {
type: "erp5",
url: (new URI("hateoas"))
.absoluteTo(param_dict.erp5_url).toString(),
default_view_reference: "view",
};
remote_post = true;
break;
}
return gadget.createJio({
type: "replicate",
use_remote_post: remote_post,
conflict_handling: 2,
/* Create a new room gadget.
* Parameters:
* - room: the name of the room
* Effects:
* - declare a new gadget with scope "room-gadget-" + room
* - set its ID to a querySelector-safe translation of its scope
* - initialize its state and render the room gadget
*/
.
declareMethod
(
"
createRoom
"
,
function
(
room
)
{
var
gadget
=
this
,
room_gadget
;
return
gadget
.
declareGadget
(
"
gadget_erp5_chat_room.html
"
,
{
scope
:
"
room-gadget-
"
+
room
})
.
push
(
function
(
sub_gadget
)
{
room_gadget
=
sub_gadget
;
room_gadget
.
element
.
setAttribute
(
"
id
"
,
"
room-gadget-
"
+
nameToId
(
room
));
gadget
.
element
.
querySelector
(
"
.chat-right-panel
"
).
insertBefore
(
room_gadget
.
element
,
gadget
.
element
.
querySelector
(
"
.chat-max-height-wrapper
"
)
);
return
room_gadget
.
changeState
({
room
:
room
,
local_sub_storage
:
gadget
.
state
.
local_sub_storage
,
default_jio_type
:
gadget
.
state
.
default_jio_type
,
default_erp5_url
:
gadget
.
state
.
default_erp5_url
,
default_dav_url
:
gadget
.
state
.
default_dav_url
,
query
:
{
limit
:
[
0
,
1000000000
],
query: "portal_type: "Person" OR portal_type: "Text Post"",
},
local_sub_storage: {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs-chat",
},
},
},
remote_sub_storage: remote_config,
query
:
'
portal_type: "Text Post"
'
// AND room: "' + room + '"'
}
});
})
.push(null, logError);
})
*/
// Get all messages stored in archive and add them to the list in order,
// using storeList because the messages are already in the archive
.
declareMethod
(
"
getLocalArchive
"
,
function
()
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
jio_allDocs
({
limit
:
[
0
,
1000000
],
query
:
'
portal_type: "Text Post"
'
,
sort_on
:
[[
"
last_modified
"
,
"
descending
"
]],
select_list
:
[
"
content
"
],
});
})
.
push
(
function
(
message_list
)
{
var
message_queue
=
new
FastPriorityQueue
(
messageTimeCompare
(
true
)),
i
,
i_len
;
for
(
i
=
0
,
i_len
=
message_list
.
data
.
total_rows
;
i
<
i_len
;
i
+=
1
)
{
try
{
var
message
=
JSON
.
parse
(
list
[
i
]);
if
(
message
&&
typeof
message
===
"
object
"
)
{
message_queue
.
add
(
message
);
}
}
catch
(
error
)
{}
}
var
promise_list
=
[];
var
message_dict
=
gadget
.
state
.
last_message_dict
;
while
(
!
message_queue
.
isEmpty
())
{
var
message
=
message_queue
.
poll
();
if
(
message
.
room
in
gadget
.
state
.
room_set
)
{
promise_list
.
push
(
gadget
.
storeList
(
message
));
promise_list
.
push
(
gadget
.
appendMessage
(
message
));
}
}
gadget
.
state
.
initialized
=
true
;
return
RSVP
.
all
(
promise_list
);
})
.
push
(
null
,
logError
);
return
room_gadget
.
render
();
});
})
// Send all requested messages in the list, in sorted order, to peer
.
declareMethod
(
"
sendLocalArchive
"
,
function
(
request
,
source
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
request_dict
=
{};
var
room
;
for
(
room
in
request
.
content
.
room_set
)
{
if
(
request
.
content
.
room_set
.
hasOwnProperty
(
room
)
&&
gadget
.
state
.
message_list_dict
[
room
])
{
request_dict
[
room
]
=
[];
var
list
=
gadget
.
state
.
message_list_dict
[
room
],
i
,
i_len
;
for
(
i
=
0
,
i_len
=
list
.
length
;
i
<
i_len
;
i
+=
1
)
{
if
(
isNewMessage
(
list
[
i
],
request
.
content
.
dict
[
room
][
list
[
i
].
name
]))
{
request_dict
[
room
].
push
(
list
[
i
]);
}
}
}
}
return
gadget
.
createMessage
({
type
:
"
bundle
"
,
content
:
request_dict
});
})
.
push
(
function
(
message
)
{
return
gadget
.
sendMessage
(
message
,
source
);
})
.
push
(
null
,
logError
);
})
// Get all new messages from the sorted list of peer,
// add them to both the archive and list using storeArchive,
// and refresh, dedupe, and resort the list using refreshChat
.
declareMethod
(
"
getRemoteArchive
"
,
function
(
bundle
)
{
/* Change to a different room.
* Parameters:
* - room: the name of the room to change to
* Effects:
* - changeState: room, room_set[room]
* - hide the room gadget contact panel
* - show the chat box
* - overwrite the chat box with chats from the jIO storage
*/
.
declareMethod
(
"
changeRoom
"
,
function
(
room
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
promise_list
=
[],
room
;
for
(
room
in
bundle
.
content
)
{
if
(
bundle
.
content
.
hasOwnProperty
(
room
))
{
var
list
=
gadget
.
state
.
message_list_dict
[
room
];
var
remote_list
=
bundle
.
content
[
room
],
i
,
i_len
;
for
(
i
=
0
,
i_len
=
remote_list
.
length
;
i
<
i_len
;
i
+=
1
)
{
promise_list
.
push
(
gadget
.
storeList
(
remote_list
[
i
]));
promise_list
.
push
(
gadget
.
storeArchive
(
remote_list
[
i
]));
}
}
}
return
RSVP
.
all
(
promise_list
);
})
return
gadget
.
changeState
({
room
:
room
})
.
push
(
function
()
{
if
(
!
gadget
.
state
.
room_set
[
gadget
.
state
.
room
])
{
gadget
.
state
.
room_set
[
gadget
.
state
.
room
]
=
true
;
return
gadget
.
deployMessage
({
type
:
"
notification
"
,
content
:
gadget
.
state
.
name
+
"
has joined.
"
,
colour
:
"
orange
"
,
});
}
else
{
return
;
if
(
!
gadget
.
state
.
room_set
[
room
])
{
gadget
.
state
.
room_set
[
room
]
=
true
;
}
})
.
push
(
function
()
{
return
gadget
.
refreshChat
();
})
.
push
(
null
,
logError
);
});
})
// Ask a peer to send over a request
.
declareMethod
(
"
requestRequest
"
,
function
()
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
createMessage
({
type
:
"
doubler
"
});
})
.
push
(
function
(
message
)
{
return
gadget
.
sendMessage
(
message
);
})
.
push
(
null
,
logError
);
})
// Send a request to update the local archive
.
declareMethod
(
"
sendRequest
"
,
function
()
{
var
gadget
=
this
;
return
pollUntilNotNull
(
gadget
,
1000
,
30000
,
function
()
{
return
gadget
.
state
.
initialized
;
},
function
()
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
createMessage
({
type
:
"
request
"
,
content
:
{
room_set
:
gadget
.
state
.
room_set
,
dict
:
gadget
.
state
.
last_message_dict
,
},
});
})
.
push
(
function
(
message
)
{
return
gadget
.
sendMessage
(
message
);
})
.
push
(
null
,
logError
);
});
})
// Create new message from its parameters
.
declareMethod
(
"
createMessage
"
,
function
(
param_dict
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
{
type
:
param_dict
.
type
||
"
message
"
,
name
:
param_dict
.
name
||
gadget
.
state
.
name
,
room
:
param_dict
.
room
||
gadget
.
state
.
room
,
time
:
param_dict
.
time
||
new
Date
(),
content
:
param_dict
.
content
||
""
,
colour
:
param_dict
.
colour
||
"
black
"
,
};
})
.
push
(
null
,
logError
);
})
/* Deploy a new message.
* Parameters:
* - param_dict: the parameters to pass to createMessage
* Effects:
* - create a new message
* - append the message to the chat
* - store the message in jIO storage
*/
// Create new message and send it to peer
.
declareMethod
(
"
deployMessage
"
,
function
(
param_dict
)
{
var
gadget
=
this
;
var
message
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
createMessage
(
param_dict
);
})
var
gadget
=
this
,
message
;
return
gadget
.
createMessage
(
param_dict
)
.
push
(
function
(
result
)
{
message
=
result
;
return
gadget
.
storeList
(
message
);
})
.
push
(
function
()
{
return
gadget
.
appendMessage
(
message
);
})
.
push
(
function
()
{
return
gadget
.
storeArchive
(
message
);
})
.
push
(
function
()
{
return
gadget
.
sendMessage
(
message
);
})
.
push
(
null
,
logError
);
});
})
// Create new notification and keep it on own machine
/* Deploy a new notification.
* Parameters:
* - param_dict: the parameters to pass to createMessage
* Effects:
* - create a new message
* - append the message to the chat
*/
.
declareMethod
(
"
deployNotification
"
,
function
(
param_dict
)
{
var
gadget
=
this
;
var
notification
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
param_dict
.
type
=
"
notification
"
;
return
gadget
.
createMessage
(
param_dict
);
})
param_dict
.
type
=
"
notification
"
;
return
gadget
.
createMessage
(
param_dict
)
.
push
(
function
(
result
)
{
notification
=
result
;
return
gadget
.
storeList
(
notification
);
})
.
push
(
function
()
{
return
gadget
.
appendMessage
(
notification
);
})
.
push
(
null
,
logError
);
return
gadget
.
appendMessage
(
result
);
});
})
// Get message from peer, store it in archive and list
.
declareMethod
(
"
getMessage
"
,
function
(
message
)
{
/* Create a new message.
* Parameters:
* - name: the name of the sender of the message
* - room: the room from where the message is sent
* - time: the epoch time at which the message is sent
* - content: the content of the message
* - color: the colour of the message in the chat
* Effects: nothing
* Returns: a message object corresponding to the parameters
*/
.
declareMethod
(
"
createMessage
"
,
function
(
param_dict
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
notifyStatus
(
message
.
room
,
true
);
})
.
push
(
function
()
{
return
gadget
.
storeList
(
message
);
})
.
push
(
function
()
{
return
gadget
.
appendMessage
(
message
);
})
.
push
(
function
()
{
return
gadget
.
storeArchive
(
message
);
})
.
push
(
null
,
logError
);
return
{
type
:
param_dict
.
type
||
"
message
"
,
name
:
param_dict
.
name
||
gadget
.
state
.
name
,
room
:
param_dict
.
room
||
gadget
.
state
.
room
,
time
:
param_dict
.
time
||
new
Date
(),
content
:
param_dict
.
content
||
""
,
color
:
param_dict
.
color
||
"
black
"
};
})
// Store message in the archive
/* Append a message to the chat.
* Parameters:
* - message: the message object to append to the chat
* Effects:
* - create a HTML chat element from the message
* - append the chat element to the chat list
* - scroll the chat list down to show the chat element
*/
.
declareMethod
(
"
appendMessage
"
,
function
(
message
)
{
var
gadget
=
this
,
container
=
gadget
.
element
.
querySelector
(
"
.chat-list
"
);
container
.
appendChild
(
messageToChat
(
message
));
container
.
scrollTop
=
container
.
scrollHeight
;
})
/* Store a message in jIO storage.
* Parameters:
* - message: the message object to store in jIO storage
* Effects: store the message with all necessary properties into jIO
*/
.
declareMethod
(
"
storeArchive
"
,
function
(
message
)
{
var
gadget
=
this
;
var
id
=
message
.
room
+
"
_
"
+
message
.
name
+
"
_
"
+
getTime
(
message
).
toString
();
return
new
RSVP
.
Queue
(
)
.
push
(
function
()
{
return
gadget
.
jio_put
(
id
,
{
var
gadget
=
this
,
id
=
message
.
room
+
"
_
"
+
message
.
name
+
"
_
"
+
getTime
(
message
).
toString
();
return
gadget
.
getDeclaredGadget
(
"
room-gadget-
"
+
gadget
.
state
.
room
)
.
push
(
function
(
room_gadget
)
{
return
room_gadget
.
wrapJioCall
(
"
put
"
,
[
id
,
{
portal_type
:
"
Text Post
"
,
parent_relative_url
:
"
post_text_module
"
,
reference
:
id
,
author
:
message
.
name
,
date_ms
:
getTime
(
message
),
content
:
JSON
.
stringify
(
message
)
,
});
})
.
push
(
null
,
logError
);
room
:
message
.
room
,
content
:
JSON
.
stringify
(
message
)
}]);
}
);
})
// Add message to the list
.
declareMethod
(
"
storeList
"
,
function
(
message
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
if
(
isNewMessage
(
message
,
gadget
.
state
.
last_message_dict
[
message
.
room
][
message
.
name
]))
{
gadget
.
state
.
last_message_dict
[
message
.
room
][
message
.
name
]
=
getTime
(
message
);
}
gadget
.
state
.
message_list_dict
[
message
.
room
].
push
(
message
);
})
.
push
(
null
,
logError
);
})
// Appends a message to the chat box
.
declareMethod
(
"
appendMessage
"
,
function
(
message
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
if
(
message
.
room
===
gadget
.
state
.
room
)
{
var
container
=
gadget
.
element
.
querySelector
(
"
.chat-list
"
);
container
.
appendChild
(
messageToChat
(
message
));
container
.
scrollTop
=
container
.
scrollHeight
;
/*
gadget.element
.querySelector(".chat-right-panel").style.height =
gadget.element
.querySelector(".chat-left-panel").style.height;
*/
}
})
.
push
(
null
,
logError
);
})
/* Overwrite the chat box with chats from the jIO storage.
* Parameters: nothing
* Effects:
* - get a sorted list of all chats in the current room from jIO storage
* - remove the entire chat box and append all chats from jIO storage
* - scroll the chat list down to show the chat element
*/
// Sort the list, dedupe, and overwrite the chat box,
// efficient because the archive is originally sorted
.
declareMethod
(
"
refreshChat
"
,
function
()
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
container
=
gadget
.
element
.
querySelector
(
"
.chat-list
"
);
return
gadget
.
getDeclaredGadget
(
"
room-gadget-
"
+
gadget
.
state
.
room
)
.
push
(
function
(
room_gadget
)
{
return
room_gadget
.
wrapJioCall
(
"
allDocs
"
,
[{
query
:
'
portal_type: "Text Post" AND room: "
'
+
gadget
.
state
.
room
+
'
"
'
,
limit
:
[
0
,
1000000
],
sort_on
:
[[
"
date_ms
"
,
"
ascending
"
]],
select_list
:
[
"
content
"
]
}]);
})
.
push
(
function
(
result_list
)
{
var
i
,
message
,
message_list
=
[],
container
=
gadget
.
element
.
querySelector
(
"
.chat-list
"
);
for
(
i
=
0
;
i
<
result_list
.
data
.
total_rows
;
i
+=
1
)
{
try
{
message
=
JSON
.
parse
(
result_list
.
data
.
rows
[
i
].
value
.
content
);
if
(
message
&&
typeof
message
===
"
object
"
)
{
message_list
.
push
(
message
);
}
}
catch
(
ignore
)
{}
}
while
(
container
.
firstChild
)
{
container
.
removeChild
(
container
.
firstChild
);
}
var
old_list
=
gadget
.
state
.
message_list_dict
[
gadget
.
state
.
room
];
old_list
.
sort
(
messageTimeComparator
);
var
new_list
=
[];
var
last_message
,
i
,
i_len
;
for
(
i
=
0
,
i_len
=
old_list
.
length
;
i
<
i_len
;
i
+=
1
)
{
var
message
=
old_list
[
i
];
if
(
isSameMessage
(
last_message
,
message
))
{
continue
;
}
last_message
=
message
;
new_list
.
push
(
message
);
container
.
appendChild
(
messageToChat
(
message
));
for
(
i
=
0
;
i
<
message_list
.
length
;
i
+=
1
)
{
container
.
appendChild
(
messageToChat
(
message_list
[
i
]));
}
gadget
.
state
.
message_list_dict
[
gadget
.
state
.
room
]
=
new_list
;
container
.
scrollTop
=
container
.
scrollHeight
;
/*
gadget.element
.querySelector(".chat-right-panel").style.height =
gadget.element
.querySelector(".chat-left-panel").style.height;
*/
})
.
push
(
null
,
logError
);
});
})
// Notify when a new message appears and denotify when it is seen
.
declareMethod
(
"
notifyStatus
"
,
function
(
room
,
notify
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
favicon_url
;
var
class_name
;
if
(
notify
)
{
favicon_url
=
gadget
.
state
.
alert_icon
;
class_name
=
"
notify
"
;
}
else
{
favicon_url
=
gadget
.
state
.
default_icon
;
class_name
=
"
current
"
;
}
var
link
=
document
.
querySelector
(
"
link[rel*='icon']
"
)
||
document
.
createElement
(
"
link
"
);
link
.
type
=
"
image/x-icon
"
;
link
.
rel
=
"
shortcut icon
"
;
link
.
href
=
favicon_url
;
document
.
head
.
appendChild
(
link
);
var
contact
=
gadget
.
element
.
querySelector
(
"
#chat-contact-
"
+
room
);
contact
.
className
=
class_name
;
})
.
push
(
null
,
logError
);
})
// Join a different room
.
declareMethod
(
"
changeRoom
"
,
function
(
room
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
styleElementByQuery
(
gadget
,
"
#webrtc-gadget-
"
+
gadget
.
state
.
room
,
"
none
"
);
styleElementByQuery
(
gadget
,
"
.chat-right-panel-chat
"
,
"
flex
"
);
gadget
.
element
.
querySelector
(
"
.chat-title
"
)
.
textContent
=
"
Room:
"
+
room
;
gadget
.
state
.
room
=
room
;
if
(
!
(
room
in
gadget
.
state
.
room_set
))
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
gadget
.
state
.
room_set
[
room
]
=
false
;
gadget
.
state
.
message_list_dict
[
room
]
=
[];
gadget
.
state
.
last_message_dict
[
room
]
=
{};
})
.
push
(
function
()
{
return
gadget
.
getLocalArchive
();
})
.
push
(
function
()
{
return
gadget
.
requestRequest
();
})
.
push
(
null
,
logError
);
}
})
.
push
(
function
()
{
return
gadget
.
refreshChat
();
})
.
push
(
null
,
logError
);
})
/* Parse chat commands.
* Parameters:
* - chat: the plaintext chat message, which starts with "/"
* Effects: parses the command in the chat message and responds accordingly
*/
// Create a new contact
.
declareMethod
(
"
createContact
"
,
function
(
param_dict
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
appendContact
(
param_dict
.
room
);
})
.
push
(
function
()
{
return
gadget
.
chooseRoom
(
param_dict
);
})
.
push
(
function
()
{
return
gadget
.
editContact
(
param_dict
.
room
);
})
.
push
(
null
,
logError
);
})
.
declareMethod
(
"
parseCommand
"
,
function
(
chat
)
{
var
gadget
=
this
,
i
,
split
=
chat
.
slice
(
1
).
split
(
"
"
),
command
=
split
.
shift
(),
argument
=
split
.
join
(
"
"
),
promise_list
=
[],
help_list
=
[
"
Available commands:
"
,
"
/join [room]: connects you to [room]
"
,
"
/help: displays this help box
"
,
"
/leave: disconnects you from the current room
"
,
"
/quit: disconnects from the chat and refreshes the page
"
];
switch
(
command
)
{
// change to a room that has already been joined
case
"
join
"
:
if
(
gadget
.
state
.
room_set
[
argument
])
{
return
gadget
.
changeRoom
(
argument
);
}
return
gadget
.
deployNotification
({
content
:
"
You must first be connected to room '
"
+
argument
+
"
' via a shared jIO storage to join it!
"
,
color
:
"
red
"
});
// Add a contact as some HTML element
.
declareMethod
(
"
appendContact
"
,
function
(
room
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
if
(
!
room
.
trim
())
{
throw
"
An invisible name is not allowed! You couldn't click on it!
"
;
}
if
(
gadget
.
element
.
querySelector
(
"
#chat-contact-
"
+
room
))
{
throw
"
A contact with the same name already exists!
"
;
}
var
contact
=
document
.
createElement
(
"
li
"
);
contact
.
appendChild
(
document
.
createTextNode
(
room
));
contact
.
setAttribute
(
"
id
"
,
"
chat-contact-
"
+
room
);
gadget
.
element
.
querySelector
(
"
.contact-list
"
).
appendChild
(
contact
);
gadget
.
element
.
querySelector
(
"
#chat-contact-
"
+
gadget
.
state
.
room
).
className
=
""
;
contact
.
className
=
"
current
"
;
contact
.
addEventListener
(
"
click
"
,
function
(
event
)
{
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
notifyStatus
(
room
,
false
);
})
.
push
(
function
()
{
gadget
.
element
.
querySelector
(
"
#chat-contact-
"
+
gadget
.
state
.
room
).
className
=
""
;
gadget
.
element
.
querySelector
(
"
#chat-contact-
"
+
room
).
className
=
"
current
"
;
})
.
push
(
function
()
{
if
(
gadget
.
state
.
room_set
[
room
])
{
return
gadget
.
changeRoom
(
room
);
}
else
{
return
gadget
.
editContact
(
room
);
}
})
.
push
(
null
,
logError
);
},
false
);
return
;
})
})
// leave the current room
case
"
leave
"
:
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
if
(
gadget
.
state
.
room
===
gadget
.
state
.
name
)
{
return
gadget
.
deployNotification
({
content
:
"
You cannot leave your own room!
"
,
color
:
"
red
"
});
}
gadget
.
state
.
room_set
[
gadget
.
state
.
room
]
=
false
;
return
gadget
.
deployMessage
({
content
:
gadget
.
state
.
name
+
"
has quit.
"
,
color
:
"
orange
"
});
})
.
push
(
function
()
{
return
gadget
.
changeRoom
(
gadget
.
state
.
name
);
});
// Edit a contact in the right panel
.
declareMethod
(
"
editContact
"
,
function
(
room
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
styleElementByQuery
(
gadget
,
"
.chat-right-panel-chat
"
,
"
none
"
);
styleElementByQuery
(
gadget
,
"
#webrtc-gadget-
"
+
gadget
.
state
.
room
,
"
none
"
);
styleElementByQuery
(
gadget
,
"
#webrtc-gadget-
"
+
room
,
"
block
"
);
gadget
.
state
.
room
=
room
;
gadget
.
element
.
querySelector
(
"
.chat-title
"
)
.
textContent
=
"
Contact:
"
+
room
;
})
.
push
(
null
,
logError
);
// quit the entire chat
case
"
quit
"
:
return
window
.
location
.
reload
()
;
// print a list of available commands
case
"
help
"
:
for
(
i
=
0
;
i
<
help_list
.
length
;
i
+=
1
)
{
promise_list
.
push
(
gadget
.
deployNotification
({
content
:
help_list
[
i
],
color
:
"
green
"
}));
}
return
RSVP
.
all
(
promise_list
);
}
})
// Parse chat commands
.
declareMethod
(
"
parseCommand
"
,
function
(
chat
)
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
split
=
chat
.
slice
(
1
).
split
(
"
"
);
var
command
=
split
.
shift
();
var
argument
=
split
.
join
(
"
"
);
switch
(
command
)
{
case
"
join
"
:
if
(
gadget
.
state
.
room_set
[
argument
])
{
return
gadget
.
changeRoom
(
argument
);
}
else
{
return
gadget
.
deployNotification
({
content
:
"
You must first be connected to room '
"
+
argument
+
"
' via WebRTC to join it!
"
,
colour
:
"
red
"
,
});
}
case
"
leave
"
:
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
if
(
gadget
.
state
.
room
===
gadget
.
state
.
name
)
{
return
gadget
.
deployNotification
({
content
:
"
You cannot leave your own room!
"
,
colour
:
"
red
"
});
}
else
{
delete
gadget
.
state
.
room_set
[
gadget
.
state
.
room
];
return
gadget
.
deployMessage
({
type
:
"
notification
"
,
content
:
gadget
.
state
.
name
+
"
has quit.
"
,
colour
:
"
orange
"
,
});
}
})
.
push
(
function
()
{
return
gadget
.
changeRoom
(
gadget
.
state
.
name
);
})
.
push
(
null
,
logError
);
case
"
quit
"
:
window
.
location
.
reload
();
break
;
case
"
help
"
:
var
help_list
=
[
"
Available commands:
"
,
"
/join [room]: connects you to [room]
"
,
"
/help: displays this help box
"
,
"
/leave: disconnects you from the current room
"
,
"
/quit: disconnects from the chat and refreshes the page
"
,
];
var
promise_list
=
[];
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
i
,
i_len
;
for
(
i
=
0
,
i_len
=
help_list
.
length
;
i
<
i_len
;
i
+=
1
)
{
promise_list
.
push
(
gadget
.
deployNotification
({
content
:
help_list
[
i
],
colour
:
"
green
"
,
}));
}
return
RSVP
.
all
(
promise_list
);
})
.
push
(
null
,
logError
);
}
});
})
// Call the appropriate function based on the form submitted.
.
onEvent
(
"
submit
"
,
function
(
event
)
{
var
gadget
=
this
;
var
gadget
=
this
,
content
;
switch
(
event
.
target
.
className
)
{
case
"
sync-form
"
:
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
gadget
.
jio_repair
();
})
.
push
(
function
()
{
return
gadget
.
getLocalArchive
();
})
.
push
(
function
()
{
return
gadget
.
requestRequest
();
})
.
push
(
null
,
logError
);
case
"
edit-form
"
:
return
gadget
.
editContact
(
gadget
.
state
.
room
);
case
"
join-form
"
:
var
contact
=
resetInputValue
(
event
.
target
.
elements
.
content
);
return
gadget
.
createContact
({
room
:
contact
,
role
:
"
guest
"
});
case
"
make-form
"
:
var
room
=
resetInputValue
(
event
.
target
.
elements
.
content
);
return
gadget
.
createContact
({
room
:
room
,
role
:
"
host
"
});
case
"
send-form
"
:
var
content
=
resetInputValue
(
event
.
target
.
elements
.
content
);
if
(
content
.
indexOf
(
"
/
"
)
===
0
)
{
return
gadget
.
parseCommand
(
content
);
}
else
{
return
gadget
.
deployMessage
({
content
:
content
});
}
case
"
sync-form
"
:
return
gadget
.
getDeclaredGadget
(
"
room-gadget-
"
+
gadget
.
state
.
room
)
.
push
(
function
(
room_gadget
)
{
return
room_gadget
.
wrapJioCall
(
"
repair
"
);
})
.
push
(
function
()
{
return
gadget
.
refreshChat
();
});
case
"
edit-form
"
:
content
=
resetInputValue
(
event
.
target
.
elements
.
content
);
return
gadget
.
changeState
({
contact
:
content
});
case
"
join-form
"
:
content
=
resetInputValue
(
event
.
target
.
elements
.
content
);
return
gadget
.
createContact
(
content
);
case
"
send-form
"
:
content
=
resetInputValue
(
event
.
target
.
elements
.
content
);
if
(
content
.
indexOf
(
"
/
"
)
===
0
)
{
return
gadget
.
parseCommand
(
content
);
}
return
gadget
.
deployMessage
({
content
:
content
})
.
push
(
function
()
{
return
gadget
.
getDeclaredGadget
(
"
room-gadget-
"
+
gadget
.
state
.
room
);
})
.
push
(
function
(
room_gadget
)
{
return
room_gadget
.
wrapJioCall
(
"
repair
"
);
})
.
push
(
function
()
{
return
gadget
.
refreshChat
();
})
}
})
/* Send a farewell message when chat is closed.
* Parameters: nothing
* Effects: send a message when chat is closed
*/
.
declareService
(
function
()
{
var
gadget
=
this
;
return
new
RSVP
.
Queue
()
...
...
@@ -1159,25 +711,19 @@
return
promiseEventListener
(
window
,
"
beforeunload
"
,
true
);
})
.
push
(
function
()
{
if
(
gadget
.
state
.
initialized
)
{
var
promise_list
=
[],
room
;
for
(
room
in
gadget
.
state
.
room_set
)
{
if
(
gadget
.
state
.
room_set
.
hasOwnProperty
(
room
)
var
promise_list
=
[],
room
;
for
(
room
in
gadget
.
state
.
room_set
)
{
if
(
gadget
.
state
.
room_set
.
hasOwnProperty
(
room
)
&&
gadget
.
state
.
room_set
[
room
])
{
promise_list
.
push
(
gadget
.
deployMessage
({
type
:
"
notification
"
,
content
:
gadget
.
state
.
name
+
"
has quit.
"
,
room
:
room
,
colour
:
"
orange
"
,
}));
}
promise_list
.
push
(
gadget
.
deployMessage
({
content
:
gadget
.
state
.
name
+
"
has quit.
"
,
room
:
room
,
color
:
"
orange
"
}));
}
return
RSVP
.
all
(
promise_list
);
}
else
{
return
;
}
})
.
push
(
null
,
logError
);
return
RSVP
.
all
(
promise_list
);
}
);
});
}(
window
,
document
,
RSVP
,
rJS
,
FastPriorityQueue
));
\ No newline at end of file
}(
window
,
document
,
RSVP
,
rJS
,
promiseEventListener
));
\ No newline at end of file
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_connect_html.html
View file @
0d9586e0
...
...
@@ -12,15 +12,15 @@
<form
class=
"connect-form"
>
<label>
E-mail Address:
</label>
<input
type=
"email"
name=
"user_email"
required=
"required"
/>
<label>
Default
WebRTC Authentication Method
:
</label>
<label>
Default
Shared Storage Type
:
</label>
<br
/>
<input
type=
"radio"
name=
"default_
webrtc_storag
e"
value=
"erp5"
>
ERP5
</input>
<input
type=
"radio"
name=
"default_
webrtc_storage"
value=
"dropbox"
>
Dropbox
</input>
<input
type=
"radio"
name=
"default_
jio_typ
e"
value=
"erp5"
>
ERP5
</input>
<input
type=
"radio"
name=
"default_
jio_type"
value=
"dav"
>
WebDAV
</input>
<br
/>
<label>
Default Dropbox Folder:
</label>
<input
type=
"text"
name=
"default_dropbox_folder"
placeholder=
"/Apps/OfficeJS Chat/"
/>
<label>
Default ERP5 URL:
</label>
<input
type=
"text"
name=
"default_erp5_url"
,
placeholder=
"https://softinst75770.host.vifib.net/erp5/webrtc_rooms_module/"
/>
<input
type=
"text"
name=
"default_erp5_url"
,
placeholder=
"https://softinst75770.host.vifib.net/erp5/web_site_module/hateoas"
/>
<label>
Default WebDAV URL:
</label>
<input
type=
"text"
name=
"default_dav_url"
,
placeholder=
"https://softinst75722.host.vifib.net/share"
/>
<input
type=
"submit"
/>
</form>
</body>
...
...
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_chat_connect_js.js
View file @
0d9586e0
/*
global window, RSVP, rJS
*/
/*
jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80
*/
/*
jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80
*/
/*
global window, RSVP, rJS
*/
(
function
(
window
,
RSVP
,
rJS
)
{
'
use strict
'
;
"
use strict
"
;
/* Settings modified:
* - user_email
* - default_webrtc_storage
* - default_dropbox_folder
* - default_jio_type
* - default_erp5_url
* - default_dav_url
*/
/* Store the given connection settings
/* Store the given connection settings.
* Parameters: all from the connect form,
* - user_email: an email, which acts as a username, example: eugene@abc.xyz
* - default_
webrtc_storag
e: the type of storage to select by default
* for sharing
WebRTC negotiations, example: dropbox
* - default_
dropbox_folder: the Dropbox folder to select by default
*
for sharing WebRTC negotiations, example: /Apps/OfficeJS Chat/
* - default_
erp5_url: the ERP5
URL to select by default for sharing,
* example: https://softinst757
70.host.vifib.net/erp5/web_site_module/
* - default_
jio_typ
e: the type of storage to select by default
* for sharing
chat messages, example: erp5
* - default_
erp5_url: the ERP5 URL to select by default, example:
*
https://softinst75770.host.vifib.net/erp5/web_site_module/hateoas
* - default_
dav_url: the WebDAV
URL to select by default for sharing,
* example: https://softinst757
22.host.vifib.net/share
* Effects:
* - set
setting: user_email, default_webrtc_storag
e,
* default_
dropbox_folder, default_erp5
_url
* - set
Setting: user_email, default_jio_typ
e,
* default_
erp5_url, default_dav
_url
* - redirect to the front page
*/
function
setConnectConfiguration
(
gadget
,
event
)
{
const
fields
=
[
'
user_email
'
,
'
default_webrtc_storage
'
,
'
default_dropbox_folder
'
,
'
default_erp5_url
'
];
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
const
queue
=
new
RSVP
.
Queue
();
for
(
let
i
=
0
,
i_len
=
fields
.
length
;
i
<
i_len
;
i
++
)
{
const
field
=
fields
[
i
];
if
(
event
.
target
.
hasOwnProperty
(
field
)
&&
event
.
target
[
field
].
value
)
{
queue
.
push
(
function
()
{
return
gadget
.
setSetting
(
field
,
event
.
target
[
field
].
value
);
});
}
}
return
queue
;
})
var
i
,
field
,
queue
=
new
RSVP
.
Queue
(),
fields
=
[
"
user_email
"
,
"
default_jio_type
"
,
"
default_erp5_url
"
,
"
default_dav_url
"
],
callSetting
=
function
(
setting
)
{
return
function
()
{
return
gadget
.
setSetting
(
setting
,
event
.
target
[
setting
].
value
);
};
};
// must call setSetting synchronously; RSVP.all causes race conditions
for
(
i
=
0
;
i
<
fields
.
length
;
i
+=
1
)
{
field
=
fields
[
i
];
if
(
event
.
target
.
hasOwnProperty
(
field
)
&&
event
.
target
[
field
].
value
)
{
queue
.
push
(
callSetting
(
field
));
}
}
return
queue
.
push
(
function
()
{
return
gadget
.
redirect
();
});
}
rJS
(
window
)
// Neither state to set nor ready to initialize
// The following functions are all acquired from erp5_launcher_nojqm.js
.
declareAcquiredMethod
(
'
updateHeader
'
,
'
updateHeader
'
)
.
declareAcquiredMethod
(
'
redirect
'
,
'
redirect
'
)
.
declareAcquiredMethod
(
'
setSetting
'
,
'
setSetting
'
)
/* Render the gadget
// Neither state to set nor ready to initialize.
// The following functions are all acquired from erp5_page_launcher.
.
declareAcquiredMethod
(
"
updateHeader
"
,
"
updateHeader
"
)
.
declareAcquiredMethod
(
"
redirect
"
,
"
redirect
"
)
.
declareAcquiredMethod
(
"
setSetting
"
,
"
setSetting
"
)
/* Render the gadget.
* Parameters: nothing
* Effects:
* - update header, page_title to 'Connect to Chat'
* Effects: update header, page_title to "Connect to Chat"
*/
.
declareMethod
(
'
render
'
,
function
()
{
.
declareMethod
(
"
render
"
,
function
()
{
var
gadget
=
this
;
return
gadget
.
updateHeader
({
page_title
:
'
Connect to Chat
'
,
page_title
:
"
Connect to Chat
"
,
submit_action
:
true
});
})
/* Manually click submit button when the right button is clicked,
* so that HTML5 form validation is automatically used
* so that HTML5 form validation is automatically used
.
*/
.
declareMethod
(
'
triggerSubmit
'
,
function
(
event
)
{
this
.
element
.
querySelector
(
'
input[type="submit"]
'
).
click
();
.
declareMethod
(
"
triggerSubmit
"
,
function
()
{
this
.
element
.
querySelector
(
"
input[type='submit']
"
).
click
();
})
// Call setConnectionConfiguration when either proceed button is clicked
.
onEvent
(
'
submit
'
,
function
(
event
)
{
const
gadget
=
this
;
// Call setConnectionConfiguration when either proceed button is clicked.
.
onEvent
(
"
submit
"
,
function
(
event
)
{
var
gadget
=
this
;
return
setConnectConfiguration
(
gadget
,
event
);
});
...
...
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_jio_dav_configurator_js.js
View file @
0d9586e0
...
...
@@ -74,13 +74,13 @@
},
},
};
return
RSVP
.
all
([
gadget
.
setSetting
(
'
jio_storage_description
'
,
configuration
),
gadget
.
setSetting
(
'
redirect_after_reload
'
,
{
command
:
'
display
'
,
options
:
{
page
:
'
sync
'
}
,
})
]
);
return
gadget
.
setSetting
(
'
jio_storage_description
'
,
configuration
);
})
.
push
(
function
()
{
return
gadget
.
setSetting
(
'
redirect_after_reload
'
,
{
command
:
'
display
'
,
options
:
{
page
:
'
sync
'
},
}
);
})
.
push
(
function
()
{
return
gadget
.
reload
();
...
...
bt5/officejs_eyqs/PathTemplateItem/web_page_module/gadget_erp5_page_jio_erp5_configurator_js.js
View file @
0d9586e0
/* global window, RSVP, rJS
, URI
*/
/* global window, RSVP, rJS */
/* jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80 */
(
function
(
window
,
RSVP
,
rJS
,
URI
)
{
(
function
(
window
,
RSVP
,
rJS
)
{
'
use strict
'
;
/* Settings required:
...
...
@@ -65,18 +65,17 @@
},
remote_sub_storage
:
{
type
:
'
erp5
'
,
erp5_url
:
erp5_url
,
url
:
(
new
URI
(
'
hateoas
'
)).
absoluteTo
(
erp5_url
).
toString
(),
url
:
erp5_url
,
default_view_reference
:
'
jio_view
'
,
},
};
return
RSVP
.
all
([
gadget
.
setSetting
(
'
jio_storage_description
'
,
configuration
),
gadget
.
setSetting
(
'
redirect_after_reload
'
,
{
command
:
'
display
'
,
options
:
{
page
:
'
sync
'
}
,
})
]
);
return
gadget
.
setSetting
(
'
jio_storage_description
'
,
configuration
);
})
.
push
(
function
()
{
return
gadget
.
setSetting
(
'
redirect_after_reload
'
,
{
command
:
'
display
'
,
options
:
{
page
:
'
sync
'
},
}
);
})
.
push
(
function
()
{
return
gadget
.
reload
();
...
...
@@ -131,7 +130,7 @@
})
.
push
(
function
(
configuration
)
{
gadget
.
element
.
querySelector
(
'
input[name="erp5_url"]
'
)
.
value
=
configuration
.
remote_sub_storage
.
erp5_
url
;
.
value
=
configuration
.
remote_sub_storage
.
url
;
return
;
});
}
else
{
...
...
@@ -150,4 +149,4 @@
return
setErp5Configuration
(
gadget
,
event
);
});
}(
window
,
RSVP
,
rJS
,
URI
));
\ No newline at end of file
}(
window
,
RSVP
,
rJS
));
\ No newline at end of file
bt5/officejs_eyqs/bt/template_path_list
View file @
0d9586e0
web_page_module/adapter_js
web_page_module/erp5_page_launcher*
web_page_module/fast_priority_queue_js
web_page_module/gadget_erp5_chat_panel_*
web_page_module/gadget_erp5_chat_webrtc_*
web_page_module/gadget_erp5_nojquery_css
...
...
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