524 lines
21 KiB
JavaScript
524 lines
21 KiB
JavaScript
function newEducationDocSpace() {
|
|
const MODULE_NAME = 'Doc Space'
|
|
let thisObject = {
|
|
isVisible: undefined,
|
|
sidePanelTab: undefined,
|
|
container: undefined,
|
|
searchEngine: undefined,
|
|
mainSearchPage: undefined,
|
|
searchResultsPage: undefined,
|
|
footer: undefined,
|
|
documentPage: undefined,
|
|
commandInterface: undefined,
|
|
contextMenu: undefined,
|
|
language: undefined,
|
|
currentBranch: undefined,
|
|
contributionsBranch: undefined,
|
|
menuLabelsMap: undefined,
|
|
currentDocumentBeingRendered: undefined,
|
|
previousDocumentBeingRendered: undefined,
|
|
currentBookBeingRendered: undefined,
|
|
paragraphMap: undefined, // Here we will store a map of paragraphs from the Docs Node, Concept, Topics, Tutorials, Reviews or Books Schema in order to find it when we need to update them.
|
|
textArea: undefined,
|
|
sharePage: sharePage,
|
|
changeLanguage: changeLanguage,
|
|
changeCurrentBranch: changeCurrentBranch,
|
|
changeContributionsBranch: changeContributionsBranch,
|
|
enterEditMode: enterEditMode,
|
|
exitEditMode: exitEditMode,
|
|
openSpaceAreaAndNavigateTo: openSpaceAreaAndNavigateTo,
|
|
navigateTo: navigateTo,
|
|
searchPage: searchPage,
|
|
scrollToElement: scrollToElement,
|
|
physics: physics,
|
|
draw: draw,
|
|
getContainer: getContainer,
|
|
initialize: initialize,
|
|
finalize: finalize,
|
|
reset: reset
|
|
}
|
|
|
|
let isInitialized = false
|
|
|
|
thisObject.container = newContainer()
|
|
thisObject.container.name = MODULE_NAME
|
|
thisObject.container.initialize()
|
|
thisObject.container.isClickeable = true
|
|
thisObject.container.isDraggeable = false
|
|
thisObject.container.detectMouseOver = true
|
|
thisObject.container.status = 'hidden'
|
|
|
|
resize()
|
|
|
|
let browserResizedEventSubscriptionId
|
|
let openingEventSubscriptionId
|
|
let closingEventSubscriptionId
|
|
|
|
return thisObject
|
|
|
|
async function initialize() {
|
|
let promise = new Promise((resolve, reject) => {
|
|
|
|
thisObject.menuLabelsMap = new Map()
|
|
|
|
setupSidePanelTab()
|
|
setUpMenuItemsMap()
|
|
setupUserLanguage()
|
|
|
|
thisObject.searchEngine = newFoundationsDocsSearchEngine()
|
|
thisObject.mainSearchPage = newFoundationsDocsMainSearchPage()
|
|
thisObject.searchResultsPage = newFoundationsDocsSearchResultsPage()
|
|
thisObject.documentPage = newFoundationsDocsDocumentPage()
|
|
thisObject.footer = newFoundationsDocsFooter()
|
|
thisObject.commandInterface = newFoundationsDocsCommmandInterface()
|
|
thisObject.contextMenu = newFoundationsDocsContextMenu()
|
|
|
|
thisObject.searchEngine.initialize()
|
|
thisObject.mainSearchPage.initialize()
|
|
thisObject.searchResultsPage.initialize()
|
|
thisObject.documentPage.initialize()
|
|
thisObject.footer.initialize()
|
|
thisObject.commandInterface.initialize()
|
|
thisObject.contextMenu.initialize()
|
|
|
|
setupCurrentBranch()
|
|
setupContributionsBranch()
|
|
|
|
isInitialized = true
|
|
|
|
UI.projects.foundations.utilities.statusBar.changeStatus("Setting up Docs Search Engine...")
|
|
setTimeout(setUpSearchEngine, 100)
|
|
|
|
function setUpSearchEngine() {
|
|
thisObject.searchEngine.setUpSearchEngine(whenFinished)
|
|
function whenFinished() {
|
|
resolve()
|
|
}
|
|
}
|
|
|
|
function setupCurrentBranch() {
|
|
/*
|
|
Getting the currentBranch
|
|
*/
|
|
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
|
let currentBranch = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(workspace.payload, 'currentBranch')
|
|
|
|
if (currentBranch === undefined) {
|
|
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(workspace.payload, 'currentBranch', UI.projects.education.globals.docs.DEFAULT_CURRENT_BRANCH)
|
|
UI.projects.education.spaces.docsSpace.currentBranch = UI.projects.education.globals.docs.DEFAULT_CURRENT_BRANCH
|
|
} else {
|
|
UI.projects.education.spaces.docsSpace.currentBranch = currentBranch
|
|
}
|
|
/*
|
|
Every time this setup occurs, we will automatically change to the currentBranch of the workspace.
|
|
*/
|
|
changeCurrentBranch(UI.projects.education.spaces.docsSpace.currentBranch, true)
|
|
/*
|
|
Deleting what was is here because is not longer used...
|
|
*/
|
|
window.localStorage.removeItem('Current Branch')
|
|
}
|
|
|
|
function setupContributionsBranch() {
|
|
/*
|
|
Getting the contributionsBranch
|
|
*/
|
|
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
|
let contributionsBranch = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(workspace.payload, 'contributionsBranch')
|
|
|
|
if (contributionsBranch === undefined) {
|
|
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(workspace.payload, 'contributionsBranch', UI.projects.education.globals.docs.DEFAULT_CONTRIBUTIONS_BRANCH)
|
|
UI.projects.education.spaces.docsSpace.contributionsBranch = UI.projects.education.globals.docs.DEFAULT_CONTRIBUTIONS_BRANCH
|
|
} else {
|
|
UI.projects.education.spaces.docsSpace.contributionsBranch = contributionsBranch
|
|
}
|
|
/*
|
|
Every time this setup occurs, we will automatically change to the contributionsBranch of the workspace.
|
|
*/
|
|
changeContributionsBranch(UI.projects.education.spaces.docsSpace.contributionsBranch, true)
|
|
/*
|
|
Deleting what was is here because is not longer used...
|
|
*/
|
|
window.localStorage.removeItem('Contributions Branch')
|
|
}
|
|
|
|
function setupUserLanguage() {
|
|
/*
|
|
Getting the used preferred languague
|
|
*/
|
|
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
|
let docsLanguage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(workspace.payload, 'docsLanguage')
|
|
|
|
if (docsLanguage === undefined) {
|
|
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(workspace.payload, 'docsLanguage', UI.projects.education.globals.docs.DEFAULT_LANGUAGE)
|
|
UI.projects.education.spaces.docsSpace.language = UI.projects.education.globals.docs.DEFAULT_LANGUAGE
|
|
} else {
|
|
UI.projects.education.spaces.docsSpace.language = docsLanguage
|
|
}
|
|
/*
|
|
Deleting what was is here because is not longer used...
|
|
*/
|
|
window.localStorage.removeItem('Docs Language')
|
|
}
|
|
|
|
function setupSidePanelTab() {
|
|
thisObject.sidePanelTab = newSidePanelTab()
|
|
thisObject.sidePanelTab.container.connectToParent(thisObject.container, false, false)
|
|
thisObject.sidePanelTab.initialize('right')
|
|
openingEventSubscriptionId = thisObject.sidePanelTab.container.eventHandler.listenToEvent('opening', onOpening)
|
|
closingEventSubscriptionId = thisObject.sidePanelTab.container.eventHandler.listenToEvent('closing', onClosing)
|
|
|
|
browserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
|
}
|
|
|
|
function setUpMenuItemsMap() {
|
|
/*
|
|
Here we will put put all the menu item labels of all nodes at all
|
|
app schemas into a single map, that will allow us to know when a phrase
|
|
is a label of a menu and then change its style.
|
|
*/
|
|
for (let i = 0; i < PROJECTS_SCHEMA.length; i++) {
|
|
let project = PROJECTS_SCHEMA[i].name
|
|
let appSchemaArray = SCHEMAS_BY_PROJECT.get(project).array.appSchema
|
|
|
|
for (let j = 0; j < appSchemaArray.length; j++) {
|
|
let docsSchemaDocument = appSchemaArray[j]
|
|
|
|
if (docsSchemaDocument.menuItems === undefined) { continue }
|
|
for (let k = 0; k < docsSchemaDocument.menuItems.length; k++) {
|
|
let menuItem = docsSchemaDocument.menuItems[k]
|
|
thisObject.menuLabelsMap.set(menuItem.label, true)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
return promise
|
|
}
|
|
|
|
function finalize() {
|
|
canvas.eventHandler.stopListening(browserResizedEventSubscriptionId)
|
|
thisObject.sidePanelTab.container.eventHandler.stopListening(openingEventSubscriptionId)
|
|
thisObject.sidePanelTab.container.eventHandler.stopListening(closingEventSubscriptionId)
|
|
|
|
thisObject.searchEngine.finalize()
|
|
thisObject.mainSearchPage.finalize()
|
|
thisObject.searchResultsPage.finalize()
|
|
thisObject.documentPage.finalize()
|
|
thisObject.footer.finalize()
|
|
thisObject.commandInterface.finalize()
|
|
thisObject.contextMenu.finalize()
|
|
|
|
thisObject.searchEngine = undefined
|
|
thisObject.mainSearchPage = undefined
|
|
thisObject.searchResultsPage = undefined
|
|
thisObject.documentPage = undefined
|
|
thisObject.footer = undefined
|
|
thisObject.commandInterface = undefined
|
|
thisObject.contextMenu = undefined
|
|
|
|
thisObject.currentDocumentBeingRendered = undefined
|
|
thisObject.previousDocumentBeingRendered = undefined
|
|
thisObject.paragraphMap = undefined
|
|
thisObject.menuLabelsMap = undefined
|
|
isInitialized = false
|
|
}
|
|
|
|
async function reset() {
|
|
finalize()
|
|
await initialize()
|
|
}
|
|
|
|
function changeCurrentBranch(branch, doNotNavigate) {
|
|
httpRequest(undefined, 'App/Checkout/' + branch, onResponse)
|
|
if (doNotNavigate !== true) {
|
|
UI.projects.education.spaces.docsSpace.navigateTo('Foundations', 'Topic', 'Switching Branches - Changing Current Branch')
|
|
}
|
|
|
|
function onResponse(err, data) {
|
|
/* Lets check the result of the call through the http interface */
|
|
data = JSON.parse(data)
|
|
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result && data.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
|
UI.projects.education.spaces.docsSpace.currentBranch = branch
|
|
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
|
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(workspace.payload, 'currentBranch', branch)
|
|
|
|
if (doNotNavigate === true) { return }
|
|
UI.projects.education.spaces.docsSpace.navigateTo('Foundations', 'Topic', 'Switching Branches - Current Branch Changed')
|
|
} else {
|
|
UI.projects.education.spaces.docsSpace.navigateTo(
|
|
data.docs.project,
|
|
data.docs.category,
|
|
data.docs.type,
|
|
data.docs.anchor,
|
|
undefined,
|
|
data.docs.placeholder
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
function changeContributionsBranch(branch, doNotNavigate) {
|
|
UI.projects.education.spaces.docsSpace.contributionsBranch = branch
|
|
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
|
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(workspace.payload, 'contributionsBranch', branch)
|
|
|
|
if (doNotNavigate !== true) {
|
|
UI.projects.education.spaces.docsSpace.navigateTo('Foundations', 'Topic', 'Switching Branches - Contributions Branch Changed')
|
|
}
|
|
}
|
|
|
|
function changeLanguage(pLanguage) {
|
|
UI.projects.education.spaces.docsSpace.language = pLanguage
|
|
let languageLabel = UI.projects.education.utilities.languages.getLaguageLabel(UI.projects.education.spaces.docsSpace.language)
|
|
UI.projects.education.spaces.docsSpace.navigateTo('Foundations', 'Topic', 'Docs In ' + languageLabel)
|
|
|
|
let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode
|
|
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(workspace.payload, 'docsLanguage', UI.projects.education.spaces.docsSpace.language)
|
|
}
|
|
|
|
function sharePage() {
|
|
let clipboard = "docs.goto " + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.project + '->' + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.category + '->' + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type
|
|
UI.projects.foundations.utilities.clipboard.copyTextToClipboard(clipboard)
|
|
}
|
|
|
|
function onKeyDown(event) {
|
|
/*
|
|
When an editor is on focus we will only
|
|
take care of a few combinations of key strokes
|
|
so as to tell the editor container when the user
|
|
would like to close the editor. ESC key exits edit mode.
|
|
*/
|
|
if (event.key === 'Escape') {
|
|
UI.projects.education.spaces.docsSpace.exitEditMode()
|
|
}
|
|
}
|
|
|
|
function enterEditMode() {
|
|
EDITOR_ON_FOCUS = true
|
|
window.editorController = {
|
|
onKeyDown: onKeyDown
|
|
}
|
|
}
|
|
|
|
function exitEditMode() {
|
|
if (EDITOR_ON_FOCUS === true) {
|
|
thisObject.documentPage.exitEditMode()
|
|
UI.projects.education.spaces.docsSpace.documentPage.render()
|
|
EDITOR_ON_FOCUS = false
|
|
}
|
|
}
|
|
|
|
function onOpening() {
|
|
thisObject.isVisible = true
|
|
if (UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered === undefined) {
|
|
thisObject.mainSearchPage.render()
|
|
|
|
} else {
|
|
UI.projects.education.spaces.docsSpace.navigateTo(
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.project,
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.category,
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.type,
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.anchor,
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.nodeId,
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.placeholder
|
|
)
|
|
}
|
|
}
|
|
|
|
function onClosing() {
|
|
thisObject.contextMenu.removeContextMenuFromScreen()
|
|
thisObject.isVisible = false
|
|
}
|
|
|
|
function scrollToElement(htmlElementId) {
|
|
let myElement = document.getElementById(htmlElementId)
|
|
if (myElement) {
|
|
let topPos = myElement.offsetTop
|
|
let scrollingDiv = document.getElementById('docs-space-div')
|
|
scrollingDiv.scrollTop = topPos
|
|
}
|
|
}
|
|
|
|
function openSpaceAreaAndNavigateTo(project, category, type, anchor, nodeId, placeholder) {
|
|
|
|
getReadyToNavigate(project, category, type, anchor, nodeId, placeholder)
|
|
|
|
thisObject.sidePanelTab.open()
|
|
}
|
|
|
|
function searchPage() {
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered = undefined
|
|
thisObject.mainSearchPage.render()
|
|
}
|
|
|
|
function navigateTo(project, category, type, anchor, nodeId, placeholder) {
|
|
|
|
EDITOR_ON_FOCUS = false // forced exit
|
|
UI.projects.education.spaces.docsSpace.paragraphMap = new Map()
|
|
|
|
getReadyToNavigate(project, category, type, anchor, nodeId, placeholder)
|
|
|
|
UI.projects.education.spaces.docsSpace.documentPage.render()
|
|
|
|
/*
|
|
Here we will check if we need to position the page at a particular anchor or at the top.
|
|
*/
|
|
if (UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.anchor !== undefined) {
|
|
scrollToElement('docs-anchor-' + UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.anchor.toLowerCase().replaceAll(' ', '-'))
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered.anchor = undefined
|
|
} else {
|
|
scrollToElement('docs-space-div')
|
|
}
|
|
}
|
|
|
|
function getReadyToNavigate(project, category, type, anchor, nodeId, placeholder) {
|
|
/* Replace the current object with this */
|
|
if (UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered !== undefined) {
|
|
UI.projects.education.spaces.docsSpace.previousDocumentBeingRendered = JSON.parse(JSON.stringify(UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered))
|
|
}
|
|
|
|
if (category === 'Book') {
|
|
UI.projects.education.spaces.docsSpace.currentBookBeingRendered = {
|
|
project: project,
|
|
category: category,
|
|
type: type.replace('AMPERSAND', '\''),
|
|
anchor: anchor,
|
|
nodeId: nodeId,
|
|
placeholder: placeholder
|
|
}
|
|
}
|
|
|
|
UI.projects.education.spaces.docsSpace.currentDocumentBeingRendered = {
|
|
project: project,
|
|
category: category,
|
|
type: type.replace('AMPERSAND', '\''),
|
|
anchor: anchor,
|
|
nodeId: nodeId,
|
|
placeholder: placeholder
|
|
}
|
|
}
|
|
|
|
function resize() {
|
|
thisObject.container.frame.width = UI.projects.education.globals.docs.DOCS_SPACE_WIDTH
|
|
thisObject.container.frame.height = browserCanvas.height // - TOP_SPACE_HEIGHT
|
|
thisObject.container.frame.position.x = browserCanvas.width
|
|
thisObject.container.frame.position.y = 0 // TOP_SPACE_HEIGHT
|
|
|
|
if (thisObject.sidePanelTab !== undefined) {
|
|
thisObject.sidePanelTab.resize()
|
|
}
|
|
}
|
|
|
|
function getContainer(point, purpose) {
|
|
if (thisObject.sidePanelTab === undefined) { return }
|
|
let container
|
|
|
|
container = thisObject.sidePanelTab.getContainer(point, purpose)
|
|
if (container !== undefined) { return container }
|
|
|
|
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
|
return thisObject.container
|
|
} else {
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
function physics() {
|
|
thisObject.sidePanelTab.physics()
|
|
docsAppDivPhysics()
|
|
|
|
function docsAppDivPhysics() {
|
|
let docsSpaceDiv = document.getElementById('docs-space-div')
|
|
docsAppDivPosition = {
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
docsAppDivPosition = thisObject.container.frame.frameThisPoint(docsAppDivPosition)
|
|
docsSpaceDiv.style = ' ' +
|
|
'overflow-y: scroll;' +
|
|
'overflow-x: hidden;' +
|
|
'position:fixed; top:' + docsAppDivPosition.y + 'px; ' +
|
|
'left:' + docsAppDivPosition.x + 'px; z-index:1; ' +
|
|
'width: ' + thisObject.container.frame.width + 'px;' +
|
|
'height: ' + thisObject.container.frame.height + 'px'
|
|
}
|
|
}
|
|
|
|
function draw() {
|
|
if (CAN_SPACES_DRAW === false) { return }
|
|
if (isInitialized === false) { return }
|
|
borders()
|
|
thisObject.sidePanelTab.draw()
|
|
}
|
|
|
|
function borders() {
|
|
let point1
|
|
let point2
|
|
let point3
|
|
let point4
|
|
|
|
point1 = {
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
|
|
point2 = {
|
|
x: thisObject.container.frame.width,
|
|
y: 0
|
|
}
|
|
|
|
point3 = {
|
|
x: thisObject.container.frame.width,
|
|
y: thisObject.container.frame.height
|
|
}
|
|
|
|
point4 = {
|
|
x: 0,
|
|
y: thisObject.container.frame.height
|
|
}
|
|
|
|
point1 = thisObject.container.frame.frameThisPoint(point1)
|
|
point2 = thisObject.container.frame.frameThisPoint(point2)
|
|
point3 = thisObject.container.frame.frameThisPoint(point3)
|
|
point4 = thisObject.container.frame.frameThisPoint(point4)
|
|
|
|
browserCanvasContext.setLineDash([]) // Resets Line Dash
|
|
browserCanvasContext.beginPath()
|
|
browserCanvasContext.moveTo(point1.x, point1.y)
|
|
browserCanvasContext.lineTo(point2.x, point2.y)
|
|
browserCanvasContext.lineTo(point3.x, point3.y)
|
|
browserCanvasContext.lineTo(point4.x, point4.y)
|
|
browserCanvasContext.lineTo(point1.x, point1.y)
|
|
browserCanvasContext.closePath()
|
|
|
|
let opacity = 1
|
|
|
|
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + opacity + ''
|
|
browserCanvasContext.fill()
|
|
|
|
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREY + ', ' + opacity + ''
|
|
browserCanvasContext.lineWidth = 0.3
|
|
browserCanvasContext.stroke()
|
|
|
|
/* Shadow */
|
|
|
|
if (thisObject.container.status !== 'hidden') {
|
|
for (let i = 0; i <= 30; i++) {
|
|
opacity = 1 - (i / 300) - 0.95
|
|
|
|
browserCanvasContext.setLineDash([]) // Resets Line Dash
|
|
browserCanvasContext.beginPath()
|
|
browserCanvasContext.moveTo(point2.x + i, point2.y)
|
|
browserCanvasContext.lineTo(point3.x + i, point3.y)
|
|
browserCanvasContext.closePath()
|
|
|
|
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.BLACK + ', ' + opacity + ''
|
|
browserCanvasContext.lineWidth = 1
|
|
browserCanvasContext.stroke()
|
|
}
|
|
}
|
|
}
|
|
}
|