mobile frontend WIP, removing extra dependencies

This commit is contained in:
azivner 2018-12-24 10:10:36 +01:00
parent a32645cdeb
commit e0028ab6f1
10 changed files with 134 additions and 70 deletions

View File

@ -33,6 +33,9 @@ import bundle from "./bundle.js";
import treeCache from "./tree_cache.js";
import libraryLoader from "./library_loader.js";
import hoistedNoteService from './hoisted_note.js';
import noteTypeService from './note_type.js';
import linkService from './link.js';
import noteAutocompleteService from './note_autocomplete.js';
// required for CKEditor image upload plugin
window.glob.getCurrentNode = treeService.getCurrentNode;
@ -144,3 +147,9 @@ entrypoints.registerEntrypoints();
noteTooltipService.setupGlobalTooltip();
bundle.executeStartupBundles();
noteTypeService.init();
linkService.init();
noteAutocompleteService.init();

View File

@ -88,17 +88,19 @@ function addTextToEditor(text) {
});
}
ko.bindingHandlers.noteLink = {
init: async function(element, valueAccessor, allBindings, viewModel, bindingContext) {
const noteId = ko.unwrap(valueAccessor());
function init() {
ko.bindingHandlers.noteLink = {
init: async function(element, valueAccessor, allBindings, viewModel, bindingContext) {
const noteId = ko.unwrap(valueAccessor());
if (noteId) {
const link = await createNoteLink(noteId);
if (noteId) {
const link = await createNoteLink(noteId);
$(element).append(link);
$(element).append(link);
}
}
}
};
};
}
// when click on link popup, in case of internal link, just go the the referenced note instead of default behavior
// of opening the link in new window/tab
@ -124,5 +126,6 @@ export default {
getNotePathFromUrl,
createNoteLink,
addLinkToEditor,
addTextToEditor
addTextToEditor,
init
};

View File

@ -1,3 +1,43 @@
import treeService from "./tree.js";
import noteDetailService from "./note_detail.js";
import dragAndDropSetup from "./drag_and_drop.js";
import treeCache from "./tree_cache.js";
import treeBuilder from "./tree_builder.js";
treeService.showTree();
const $tree = $("#tree");
async function showTree() {
const tree = await treeService.loadTree();
$tree.fancytree({
autoScroll: true,
keyboard: false, // we takover keyboard handling in the hotkeys plugin
extensions: ["dnd5", "clones"],
source: tree,
scrollParent: $tree,
minExpandLevel: 2, // root can't be collapsed
activate: (event, data) => {
const node = data.node;
const noteId = node.data.noteId;
treeService.setCurrentNotePathToHash(node);
noteDetailService.switchToNote(noteId, true);
},
expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true),
collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false),
init: (event, data) => treeService.treeInitialized(), // don't collapse to short form
dnd5: dragAndDropSetup,
lazyLoad: function(event, data) {
const noteId = data.node.data.noteId;
data.result = treeCache.getNote(noteId).then(note => treeBuilder.prepareBranch(note));
},
clones: {
highlightActiveClones: true
}
});
}
showTree();

View File

@ -101,40 +101,42 @@ function initNoteAutocomplete($el, options) {
return $el;
}
$.fn.getSelectedPath = function() {
if (!$(this).val().trim()) {
return "";
}
else {
return $(this).attr(SELECTED_PATH_KEY);
}
};
function init() {
$.fn.getSelectedPath = function () {
if (!$(this).val().trim()) {
return "";
} else {
return $(this).attr(SELECTED_PATH_KEY);
}
};
$.fn.setSelectedPath = function(path) {
path = path || "";
$.fn.setSelectedPath = function (path) {
path = path || "";
$(this).attr(SELECTED_PATH_KEY, path);
$(this).attr(SELECTED_PATH_KEY, path);
$(this)
.closest(".input-group")
.find(".go-to-selected-note-button")
.toggleClass("disabled", !path.trim())
.attr(SELECTED_PATH_KEY, path); // we also set attr here so tooltip can be displayed
};
$(this)
.closest(".input-group")
.find(".go-to-selected-note-button")
.toggleClass("disabled", !path.trim())
.attr(SELECTED_PATH_KEY, path); // we also set attr here so tooltip can be displayed
};
ko.bindingHandlers.noteAutocomplete = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
initNoteAutocomplete($(element));
ko.bindingHandlers.noteAutocomplete = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
initNoteAutocomplete($(element));
$(element).setSelectedPath(bindingContext.$data.selectedPath);
$(element).setSelectedPath(bindingContext.$data.selectedPath);
$(element).on('autocomplete:selected', function(event, suggestion, dataset) {
bindingContext.$data.selectedPath = $(element).val().trim() ? suggestion.path : '';
});
}
};
$(element).on('autocomplete:selected', function (event, suggestion, dataset) {
bindingContext.$data.selectedPath = $(element).val().trim() ? suggestion.path : '';
});
}
};
}
export default {
initNoteAutocomplete,
showRecentNotes
showRecentNotes,
init
}

View File

@ -17,6 +17,7 @@ import noteDetailRender from './note_detail_render.js';
import noteDetailRelationMap from './note_detail_relation_map.js';
import bundleService from "./bundle.js";
import attributeService from "./attributes.js";
import utils from "./utils.js";
const $noteTitle = $("#note-title");
@ -89,11 +90,11 @@ async function reload() {
await loadNoteDetail(getCurrentNoteId());
}
async function switchToNote(noteId) {
async function switchToNote(noteId, mobile) {
if (getCurrentNoteId() !== noteId) {
await saveNoteIfChanged();
await loadNoteDetail(noteId);
await loadNoteDetail(noteId, mobile);
}
}
@ -177,8 +178,10 @@ async function loadNoteDetail(noteId) {
// only now that we're in sync with tree active node we will switch currentNote
currentNote = loadedNote;
// needs to happend after loading the note itself because it references current noteId
attributeService.refreshAttributes();
if (utils.isDesktop()) {
// needs to happen after loading the note itself because it references current noteId
attributeService.refreshAttributes();
}
if (isNewNoteCreated) {
isNewNoteCreated = false;
@ -197,8 +200,10 @@ async function loadNoteDetail(noteId) {
try {
$noteTitle.val(currentNote.title);
noteTypeService.setNoteType(currentNote.type);
noteTypeService.setNoteMime(currentNote.mime);
if (utils.isDesktop()) {
noteTypeService.setNoteType(currentNote.type);
noteTypeService.setNoteMime(currentNote.mime);
}
for (const componentType in components) {
if (componentType !== currentNote.type) {
@ -225,13 +230,15 @@ async function loadNoteDetail(noteId) {
// after loading new note make sure editor is scrolled to the top
getComponent(currentNote.type).scrollToTop();
$scriptArea.empty();
if (utils.isDesktop()) {
$scriptArea.empty();
await bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteView');
await bundleService.executeRelationBundles(getCurrentNote(), 'runOnNoteView');
await attributeService.showAttributes();
await attributeService.showAttributes();
await showChildrenOverview();
await showChildrenOverview();
}
}
async function showChildrenOverview() {

View File

@ -44,7 +44,7 @@ const DEFAULT_MIME_TYPES = [
{ mime: 'text/x-yaml', title: 'YAML' }
];
const noteTypeModel = new NoteTypeModel();
let noteTypeModel;
function NoteTypeModel() {
const self = this;
@ -153,7 +153,11 @@ function NoteTypeModel() {
}
}
ko.applyBindings(noteTypeModel, document.getElementById('note-type-wrapper'));
function init() {
noteTypeModel = new NoteTypeModel();
ko.applyBindings(noteTypeModel, document.getElementById('note-type-wrapper'));
}
export default {
getNoteType: () => noteTypeModel.type(),
@ -168,5 +172,6 @@ export default {
getDefaultCodeMimeTypes: () => DEFAULT_MIME_TYPES.slice(),
getCodeMimeTypes: () => noteTypeModel.codeMimeTypes(),
setCodeMimeTypes: types => noteTypeModel.codeMimeTypes(types)
setCodeMimeTypes: types => noteTypeModel.codeMimeTypes(types),
init
};

View File

@ -359,7 +359,7 @@ function initFancyTree(tree) {
$tree.fancytree({
autoScroll: true,
keyboard: false, // we takover keyboard handling in the hotkeys plugin
extensions: ["hotkeys", "filter", "dnd5", "clones"],
extensions: ["hotkeys", "dnd5", "clones"],
source: tree,
scrollParent: $tree,
minExpandLevel: 2, // root can't be collapsed
@ -397,18 +397,6 @@ function initFancyTree(tree) {
hotkeys: {
keydown: treeKeyBindings
},
filter: {
autoApply: true, // Re-apply last filter if lazy data is loaded
autoExpand: true, // Expand all branches that contain matches while filtered
counter: false, // Show a badge with number of matching child nodes near parent icons
fuzzy: false, // Match single characters in order, e.g. 'fb' will match 'FooBar'
hideExpandedCounter: true, // Hide counter badge if parent is expanded
hideExpanders: false, // Hide expanders if all child nodes are hidden by filter
highlight: true, // Highlight matches by wrapping inside <mark> tags
leavesOnly: false, // Match end nodes only
nodata: true, // Display a 'no data' status node if result is empty
mode: "hide" // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
},
dnd5: dragAndDropSetup,
lazyLoad: function(event, data) {
const noteId = data.node.data.noteId;
@ -696,5 +684,8 @@ export default {
getSelectedNodes,
clearSelectedNodes,
sortAlphabetically,
showTree
showTree,
loadTree,
treeInitialized,
setExpandedToServer
};

View File

@ -143,6 +143,14 @@ function bindShortcut(keyboardShortcut, handler) {
});
}
function isMobile() {
return window.device === "mobile";
}
function isDesktop() {
return window.device === "desktop";
}
export default {
reloadApp,
parseDate,
@ -166,5 +174,7 @@ export default {
download,
toObject,
randomString,
bindShortcut
bindShortcut,
isMobile,
isDesktop
};

View File

@ -205,6 +205,7 @@
<script type="text/javascript">
window.baseApiUrl = 'api/';
window.device = "desktop";
window.glob = {
activeDialog: null,
sourceId: '<%= sourceId %>',

View File

@ -10,6 +10,7 @@
<script type="text/javascript">
window.baseApiUrl = 'api/';
window.device = "mobile";
window.glob = {
activeDialog: null,
sourceId: '<%= sourceId %>',
@ -26,11 +27,6 @@
<link href="libraries/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<script src="javascripts/services/mobile.js" crossorigin type="module"></script>
<script src="libraries/jquery.hotkeys.js"></script>
<script src="libraries/jquery.fancytree.hotkeys.js"></script>
<script src="libraries/knockout.min.js"></script>
<link href="stylesheets/style.css" rel="stylesheet">
<link href="stylesheets/mobile.css" rel="stylesheet">