...
 
Commits (3)
/* global document, m, System */
import m from "./static/vendor/mithril/1.1.6/mithril.min";
import EmailSvc from "./services/email.js";
import MainLayout from "./components/main-layout";
import WithRouteTriggeredLoader from "./components/with-route-triggered-loader";
import InboxMail from "./components/inbox-mail";
let StarredMail;
// Set up the app
m.route(document.body, "/inbox", {
"/inbox": {
render: function() {
return m(MainLayout, m(WithRouteTriggeredLoader, {
title: "Loading inbox...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: function(data) { return m(InboxMail, {emails: data}); }
}));
}
},
"/starred": {
onmatch: function() {
// Load starred mail *when we need it*
return import("./components/starred-mail")
.then((mod) => StarredMail = mod.default);
},
},
"/draft": {
onmatch: function() {
return import("./components/draft-mail")
.then(({default: DraftMail}) => DraftMail);
}
},
"/important": {
onmatch: function() {
return import("./components/important-mail")
.then(({default: ImportantMail}) => ImportantMail);
}
},
System.register([
"./services/email.js",
"./components/main-layout.js",
"./components/with-route-triggered-loader.js",
"./components/inbox-mail.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
Promise.all([
moduleCtx.import("./services/email.js"),
moduleCtx.import("./components/main-layout.js"),
moduleCtx.import("./components/with-route-triggered-loader.js"),
moduleCtx.import("./components/inbox-mail.js"),
])
.then(function(deps) {
var EmailSvc = deps.shift().service;
var MainLayout = deps.shift().component;
var WithRouteTriggeredLoader = deps.shift().component;
var InboxMail = deps.shift().component;
// Set up the app
m.route(document.body, "/inbox", {
"/inbox": {
render: function() {
return m(MainLayout, m(WithRouteTriggeredLoader, {
title: "Loading inbox...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: function(data) { return m(InboxMail, {emails: data}); }
}));
}
},
"/starred": {
render: function() {
// Load starred mail *when we need it*
return moduleCtx
.import("./components/starred-mail.js")
.then(function(StarredMailModule) {
var StarredMail = StarredMailModule.component;
return m(MainLayout, m(WithRouteTriggeredLoader, {
title: "Loading starred emails...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: function(data) { return m(StarredMail, {emails: data}); }
}));
});
}
},
"/draft": {
render: function() {
return moduleCtx
.import("./components/draft-mail.js")
.then(function(DraftMailModule) {
DraftMail = DraftMailModule.component;
return m(MainLayout, m(WithRouteTriggeredLoader, {
title: "Loading draft emails...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: function(data) { return m(DraftMail, {emails: data}); }
}));
});
}
},
"/important": {
render: function() {
return moduleCtx
.import("./components/important-mail.js")
.then(function(ImportantMailModule) {
var ImportantMail = ImportantMailModule.component;
return m(MainLayout, m(WithRouteTriggeredLoader, {
title: "Loading important emails...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: function(data) { return m(ImportantMail, {emails: data}); }
}));
});
}
},
});
// This module exports nothing, just runs once
exportModule({});
});
}, // /execute
};
});
/* global System */
System.register([
"./rhs-header.js",
"./mail-page-subnav.js",
"./email-list.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
import m from "../static/vendor/mithril/1.1.6/mithril.min";
Promise.all([
moduleCtx.import("./rhs-header.js"),
moduleCtx.import("./mail-page-subnav.js"),
moduleCtx.import("./email-list.js"),
])
.then(function(deps) {
var RHSHeader = deps.shift().component;
var MailPageSubNav = deps.shift().component;
var EmailList = deps.shift().component;
import EmailSvc from "../services/email";
var DraftMail = {
view: function(vnode) {
var newCount = vnode.attrs.newCount;
import RHSHeader from "./rhs-header";
import MailPageSubNav from "./mail-page-subnav";
import EmailList from "./email-list";
import MainLayout from "./main-layout";
import WithRouteTriggeredLoader from "./with-route-triggered-loader";
return m(".component.draft-rhs", [
// Colored header
m(RHSHeader, {class: "draft-gray-bg white-fg", title: "Draft", newCount: newCount}),
const DraftMail = {
view: function(vnode) {
const newCount = vnode.attrs.newCount;
// Container with buttons
m(MailPageSubNav),
return m(MainLayout,
m(WithRouteTriggeredLoader, {
title: "Loading draft emails...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: (data) => m(".component.draft-rhs", [
// Colored header
m(RHSHeader, {class: "draft-gray-bg white-fg", title: "Draft", newCount: newCount}),
// EmailList
m(EmailList, {emails: vnode.attrs.emails}),
]);
}
};
// Container with buttons
m(MailPageSubNav),
exportModule({component: DraftMail});
});
// EmailList
m(EmailList, {emails: data}),
])
})
);
},
};
},
};
});
export default DraftMail;
/* global System */
System.register([
"../services/email.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
Promise.all([
moduleCtx.import("../services/email.js",)
]).then(function(deps) {
var EmailSvc = deps.shift().service;
import m from "../static/vendor/mithril/1.1.6/mithril.min.js";
import EmailSvc from "../services/email.js";
var ELLIPSIS_CHAR_LIMIT = 60;
const ELLIPSIS_CHAR_LIMIT = 60;
var EmailListItem = {
view: function(vnode) {
var email = vnode.attrs.email;
var textContent = email.text || "";
var formattedSendDate = email.sendDate.toLocaleString();
const EmailListItem = {
view: function(vnode) {
const email = vnode.attrs.email;
const textContent = email.text || "";
const formattedSendDate = email.sendDate.toLocaleString();
var isSelected = EmailSvc.getEmailSelectedStatusById(email.id);
var isChecked = EmailSvc.getEmailCheckedStatusById(email.id);
const isSelected = EmailSvc.getEmailSelectedStatusById(email.id);
const isChecked = EmailSvc.getEmailCheckedStatusById(email.id);
var additionalClasses = [];
if (isSelected) { additionalClasses.push("selected"); }
let additionalClasses = [];
if (isSelected) { additionalClasses.push("selected"); }
return m(
".component.email-list-item.clickable",
{
class: additionalClasses.join(" "),
onclick: function() { EmailSvc.toggleSelectionStatusById(email.id); }
},
[
m(".header", [
m(".lhs", [
m("input[type=checkbox]", {
checked: isChecked,
onclick: function() { EmailSvc.toggleCheckedStatusById(email.id); }
}),
m("span.sm-margin-left.sender", email.from.name),
m("span.sm-margin-left.tag", email.label),
]),
return m(
".component.email-list-item.clickable",
{
class: additionalClasses.join(" "),
onclick: () => EmailSvc.toggleSelectionStatusById(email.id),
},
[
m(".header", [
m(".lhs", [
m("input[type=checkbox]", {
checked: isChecked,
onclick: () => EmailSvc.toggleCheckedStatusById(email.id),
}),
m("span.sm-margin-left.sender", email.from.name),
m("span.sm-margin-left.tag", email.label),
]),
m(".rhs", [
m(".date", formattedSendDate)
])
]),
m(".rhs", [
m(".date", formattedSendDate)
])
]),
m(".blurb.md-margin-top", [
m("p.subject", email.subject),
// This is not a great way to do ellipsis but... it'll work for the demo.
m("p.body-preview", textContent.substring(0, ELLIPSIS_CHAR_LIMIT) + "..."),
]),
m(".blurb.md-margin-top", [
m("p.subject", email.subject),
// This is not a great way to do ellipsis but... it'll work for the demo.
m("p.body-preview", textContent.substring(0, ELLIPSIS_CHAR_LIMIT) + "..."),
]),
]);
}
};
]);
}
};
var EmailList = {
oninit: function() {
this.selectedEmails = {};
},
const EmailList = {
oninit: function() {
this.selectedEmails = {};
},
view: function(vnode) {
var emails = vnode.attrs.emails || [];
return m(".component.email-list", emails.map(function(email) {
return m(EmailListItem, {
email: email,
onEmailSelect: function(email) { this.selectedEmails[email.id] = true; },
});
}));
}
};
exportModule({component: EmailList});
view: function(vnode) {
const emails = vnode.attrs.emails || [];
return m(".component.email-list", emails.map(function(email) {
return m(EmailListItem, {
email: email,
onEmailSelect: (email) => this.selectedEmails[email.id] = true,
});
}));
}
};
},
};
});
export default EmailList;
/* global System */
System.register([
"./rhs-header.js",
"./mail-page-subnav.js",
"./email-list.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
import m from "../static/vendor/mithril/1.1.6/mithril.min";
Promise.all([
moduleCtx.import("./rhs-header.js"),
moduleCtx.import("./mail-page-subnav.js"),
moduleCtx.import("./email-list.js"),
])
.then(function(deps) {
var RHSHeader = deps.shift().component;
var MailPageSubNav = deps.shift().component;
var EmailList = deps.shift().component;
import EmailSvc from "../services/email";
var ImportantMail = {
view: function(vnode) {
var newCount = vnode.attrs.newCount;
import RHSHeader from "./rhs-header";
import MailPageSubNav from "./mail-page-subnav";
import EmailList from "./email-list";
import MainLayout from "./main-layout";
import WithRouteTriggeredLoader from "./with-route-triggered-loader";
return m(".component.important-rhs", [
// Colored header
m(RHSHeader, {class: "important-red-bg white-fg", title: "Important", newCount: newCount}),
const ImportantMail = {
view: function(vnode) {
const newCount = vnode.attrs.newCount;
// Container with buttons
m(MailPageSubNav),
return m(MainLayout,
m(WithRouteTriggeredLoader, {
title: "Loading important emails...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: (data) => m(".component.important-rhs", [
// Colored header
m(RHSHeader, {class: "important-red-bg white-fg", title: "Important", newCount: newCount}),
// EmailList
m(EmailList, {emails: vnode.attrs.emails}),
]);
}
};
// Container with buttons
m(MailPageSubNav),
exportModule({component: ImportantMail});
});
// EmailList
m(EmailList, {emails: data}),
])
})
);
}
};
},
};
});
export default ImportantMail;
/* global System */
System.register([
"./rhs-header.js",
"./mail-page-subnav.js",
"./email-list.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
import m from "../static/vendor/mithril/1.1.6/mithril.min";
import RHSHeader from "./rhs-header";
import MailPageSubNav from "./mail-page-subnav";
import EmailList from "./email-list";
Promise.all([
moduleCtx.import("./rhs-header.js"),
moduleCtx.import("./mail-page-subnav.js"),
moduleCtx.import("./email-list.js"),
])
.then(function(deps) {
var RHSHeader = deps.shift().component;
var MailPageSubNav = deps.shift().component;
var EmailList = deps.shift().component;
const InboxMail = {
view: function(vnode) {
const newCount = vnode.attrs.newCount;
const emails = vnode.attrs.emails;
var InboxMail = {
view: function(vnode) {
var newCount = vnode.attrs.newCount;
var emails = vnode.attrs.emails;
return m(".component.inbox-rhs", [
// Colored header
m(RHSHeader, {class: "inbox-blue-bg white-fg", title: "Inbox", newCount: newCount}),
return m(".component.inbox-rhs", [
// Colored header
m(RHSHeader, {class: "inbox-blue-bg white-fg", title: "Inbox", newCount: newCount}),
// Container with buttons
m(MailPageSubNav),
// Container with buttons
m(MailPageSubNav),
// EmailList
m(EmailList, {emails: vnode.attrs.emails}),
]);
}
};
// EmailList
m(EmailList, {emails: vnode.attrs.emails}),
]);
}
};
exportModule({component: InboxMail});
});
},
};
});
export default InboxMail;
This diff is collapsed.
System.register([
"../services/email.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
Promise.all([
moduleCtx.import("../services/email.js",)
]).then(function(deps) {
var EmailSvc = deps.shift().service;
var MultiSelectCheckbox = {
view: function(vnode) {
var allEmailsChecked = vnode.attrs.allEmailsChecked;
var oneOrMoreEmailsChecked = vnode.attrs.oneOrMoreEmailsChecked;
var dropdownContentClasses = [];
var dropdownContentHidden = "dropdownContentHidden" in vnode.attrs ? vnode.attrs.dropdownContentHidden : true;
if (dropdownContentHidden) { dropdownContentClasses.push("hidden"); }
var selectionIconSrc = "static/images/icons/square.svg";
if (oneOrMoreEmailsChecked) { selectionIconSrc = "static/images/icons/minus-square.svg"; }
if (allEmailsChecked) { selectionIconSrc = "static/images/icons/check-square.svg"; }
var selectionText = "Select All";
if (oneOrMoreEmailsChecked) { selectionText = "Clear Selection"; }
if (allEmailsChecked) { selectionText = "Unselect All"; }
var clickHandler = function() { EmailSvc.checkAllEmails(); };
if (allEmailsChecked || oneOrMoreEmailsChecked) { clickHandler = function() { EmailSvc.clearCheckedEmails(); }; }
return m(
"span.component.multi-select-checkbox.gray-boxed.clickable",
{onclick: clickHandler},
[
m("span", [
m("img.icon", {src: selectionIconSrc}),
m("span.xs-margin-left", selectionText),
]),
]);
}
};
var ButtonGroup = {
view: function(vnode) {
return m("span.component.button-group", {class: vnode.attrs.class}, vnode.children);
}
};
var DropDownButton = {
view: function(vnode) {
var title = vnode.attrs.title || "Button";
return m("button.component.drop-down-button.gray-boxed.clickable", [
m("span", title),
m("img.xs-margin-left.icon", {src: "static/images/icons/chevron-down.svg"}),
]);
}
};
var PaginationControls = {
view: function(vnode) {
var title = vnode.attrs.title || "Button";
var lowerBound = 0;
var upperBound = 50;
var boundStatement = lowerBound + " - " + upperBound;
var total = 100;
return m(".component.pagination-controls", [
m("strong", boundStatement),
m("span", " of "),
m("strong", total),
m("img.xs-margin-left.icon-lg.gray-boxed.valign-mid", {src: "static/images/icons/chevron-left.svg"}),
m("img.xs-margin-left.icon-lg.gray-boxed.valign-mid", {src: "static/images/icons/chevron-right.svg"}),
]);
}
};
var MailPageSubNav = {
view: function(vnode) {
var allEmailsChecked = EmailSvc.allEmailsChecked();
var oneOrMoreEmailsChecked = EmailSvc.oneOrMoreEmailsChecked();
// Container with buttons
return m(".component.mail-page-subnav", [
m(".lhs", [
m(MultiSelectCheckbox, {
allEmailsChecked: allEmailsChecked,
oneOrMoreEmailsChecked: oneOrMoreEmailsChecked,
}),
m(ButtonGroup, {class: "sm-margin-left"}, [
m("button.clickable", "Archive"),
m("button.clickable", "Spam"),
m("button.clickable", "Delete"),
]),
m(ButtonGroup, {class: "sm-margin-left"}, [
m(DropDownButton, {title: "Move to"}),
m(DropDownButton, {title: "Label"}),
]),
]),
m(".rhs", [
m(PaginationControls)
]),
]);
},
};
exportModule({component: MailPageSubNav});
});
},
};
});
import m from "../static/vendor/mithril/1.1.6/mithril.min.js";
import EmailSvc from "../services/email.js";
import SquareIcon from "../static/images/icons/square.svg";
import MinusSquareIcon from "../static/images/icons/minus-square.svg";
import CheckSquareIcon from "../static/images/icons/check-square.svg";
import ChevronDownIcon from "../static/images/icons/chevron-down.svg";
import ChevronLeftIcon from "../static/images/icons/chevron-left.svg";
import ChevronRightIcon from "../static/images/icons/chevron-right.svg";
const MultiSelectCheckbox = {
view: function(vnode) {
const allEmailsChecked = vnode.attrs.allEmailsChecked;
const oneOrMoreEmailsChecked = vnode.attrs.oneOrMoreEmailsChecked;
const dropdownContentClasses = [];
const dropdownContentHidden = "dropdownContentHidden" in vnode.attrs ? vnode.attrs.dropdownContentHidden : true;
if (dropdownContentHidden) { dropdownContentClasses.push("hidden"); }
let selectionIconSrc = SquareIcon;
if (oneOrMoreEmailsChecked) { selectionIconSrc = MinusSquareIcon; }
if (allEmailsChecked) { selectionIconSrc = CheckSquareIcon; }
let selectionText = "Select All";
if (oneOrMoreEmailsChecked) { selectionText = "Clear Selection"; }
if (allEmailsChecked) { selectionText = "Unselect All"; }
let clickHandler = function() { EmailSvc.checkAllEmails(); };
if (allEmailsChecked || oneOrMoreEmailsChecked) { clickHandler = function() { EmailSvc.clearCheckedEmails(); }; }
return m(
"span.component.multi-select-checkbox.gray-boxed.clickable",
{onclick: clickHandler},
[
m("span", [
m("img.icon", {src: selectionIconSrc}),
m("span.xs-margin-left", selectionText),
]),
]);
}
};
const ButtonGroup = {
view: function(vnode) {
return m("span.component.button-group", {class: vnode.attrs.class}, vnode.children);
}
};
const DropDownButton = {
view: function(vnode) {
const title = vnode.attrs.title || "Button";
return m("button.component.drop-down-button.gray-boxed.clickable", [
m("span", title),
m("img.xs-margin-left.icon", {src: ChevronDownIcon}),
]);
}
};
const PaginationControls = {
view: function(vnode) {
const title = vnode.attrs.title || "Button";
const lowerBound = 0;
const upperBound = 50;
const boundStatement = lowerBound + " - " + upperBound;
const total = 100;
return m(".component.pagination-controls", [
m("strong", boundStatement),
m("span", " of "),
m("strong", total),
m("img.xs-margin-left.icon-lg.gray-boxed.valign-mid", {src: ChevronLeftIcon}),
m("img.xs-margin-left.icon-lg.gray-boxed.valign-mid", {src: ChevronRightIcon}),
]);
}
};
const MailPageSubNav = {
view: function(vnode) {
const allEmailsChecked = EmailSvc.allEmailsChecked();
const oneOrMoreEmailsChecked = EmailSvc.oneOrMoreEmailsChecked();
// Container with buttons
return m(".component.mail-page-subnav", [
m(".lhs", [
m(MultiSelectCheckbox, {
allEmailsChecked: allEmailsChecked,
oneOrMoreEmailsChecked: oneOrMoreEmailsChecked,
}),
m(ButtonGroup, {class: "sm-margin-left"}, [
m("button.clickable", "Archive"),
m("button.clickable", "Spam"),
m("button.clickable", "Delete"),
]),
m(ButtonGroup, {class: "sm-margin-left"}, [
m(DropDownButton, {title: "Move to"}),
m(DropDownButton, {title: "Label"}),
]),
]),
m(".rhs", [
m(PaginationControls)
]),
]);
},
};
export default MailPageSubNav;
/* global System */
System.register([
// Declare dependencies
"./lhs-nav.js"
], function(exportModule, moduleCtx) {
return {
execute: function() {
// Import the module from this module's context
moduleCtx
.import("./lhs-nav.js")
.then(function(LHSNavModule) {
var LHSNav = LHSNavModule.component;
// Use all the imports to actualy do work
var MainLayout = {
view: function(vnode) {
return m(".component.app-page.important-page", [
m(LHSNav),
vnode.children,
]);
},
};
// SystemJS export
exportModule({component: MainLayout});
return Promise.resolve();
});
},
};
});
import m from "../static/vendor/mithril/1.1.6/mithril.min.js";
import LHSNav from "./lhs-nav.js";
// Use all the imports to actualy do work
const MainLayout = {
view: function(vnode) {
return m(".component.app-page", [
m(LHSNav),
vnode.children,
]);
},
};
export default MainLayout;
/* global System */
System.register([], function(exportModule) {
return {
execute: function() {
import m from "../static/vendor/mithril/1.1.6/mithril.min.js";
var RHSHeader = {
view: function(vnode) {
var title = vnode.attrs.title || "Title";
var bgColor = vnode.attrs.bgColor || "#2285c6";
var newCount = vnode.attrs.newCount;
import SettingsWhiteIcon from "../static/images/icons/settings-white.svg";
import ExampleAvatar from "../static/images/example-avatar.jpg";
return m("div.component.rhs-header.flex", {class: vnode.attrs.class}, [
m(".title-container", [
m("span.title", title),
newCount ? m("span.new-count", "(" + newCount + ")"): undefined,
]),
const RHSHeader = {
view: function(vnode) {
const title = vnode.attrs.title || "Title";
const bgColor = vnode.attrs.bgColor || "#2285c6";
const newCount = vnode.attrs.newCount;
m(".controls", [
m("input.search-box[type='text'][placeholder='Search']"),
m("img.sm-margin-left.icon", {src: "static/images/icons/settings-white.svg"}),
m("img.sm-margin-left.avatar", {src: "static/images/example-avatar.jpg"}),
])
]);
}
};
return m("div.component.rhs-header.flex", {class: vnode.attrs.class}, [
m(".title-container", [
m("span.title", title),
newCount ? m("span.new-count", "(" + newCount + ")"): undefined,
]),
exportModule({component: RHSHeader});
},
};
});
m(".controls", [
m("input.search-box[type='text'][placeholder='Search']"),
m("img.sm-margin-left.icon", {src: SettingsWhiteIcon}),
m("img.sm-margin-left.avatar", {src: ExampleAvatar}),
])
]);
}
};
export default RHSHeader;
/* global System */
System.register([
"./rhs-header.js",
"./mail-page-subnav.js",
"./email-list.js",
], function(exportModule, moduleCtx) {
return {
execute: function() {
import m from "../static/vendor/mithril/1.1.6/mithril.min";
Promise.all([
moduleCtx.import("./rhs-header.js"),
moduleCtx.import("./mail-page-subnav.js"),
moduleCtx.import("./email-list.js"),
])
.then(function(deps) {
var RHSHeader = deps.shift().component;
var MailPageSubNav = deps.shift().component;
var EmailList = deps.shift().component;
import EmailSvc from "../services/email";
var StarredMail = {
view: function(vnode) {
var newCount = vnode.attrs.newCount;
import RHSHeader from "./rhs-header";
import MailPageSubNav from "./mail-page-subnav";
import EmailList from "./email-list";
import MainLayout from "./main-layout";
import WithRouteTriggeredLoader from "./with-route-triggered-loader";
return m(".component.starred-rhs", [
// Colored header
m(RHSHeader, {class: "starred-orange-bg white-fg", title: "Starred", newCount: newCount}),
const StarredMail = {
view: function(vnode) {
const newCount = vnode.attrs.newCount;
// Container with buttons
m(MailPageSubNav),
return m(MainLayout,
m(WithRouteTriggeredLoader, {
title: "Loading starred emails...",
// This function provides the data
loadFn: function() { return EmailSvc.getEmails(); },
// This function provides the component to WithRouteTriggeredLoader
childFn: (data) => m(".component.starred-rhs", [
// Colored header
m(RHSHeader, {class: "starred-orange-bg white-fg", title: "Starred", newCount: newCount}),
// EmailList
m(EmailList, {emails: vnode.attrs.emails}),
]);
}
};
// Container with buttons
m(MailPageSubNav),
exportModule({component: StarredMail});
});
},
};
});
// EmailList
m(EmailList, {emails: data})
]),
})
);
},
};
export default StarredMail;
/* global System */
System.register([], function(exportModule, moduleCtx) {
return {
execute: function() {
import m from "../static/vendor/mithril/1.1.6/mithril.min.js";
var LoadingIndicator = {
view: function(vnode) {
var title = vnode.attrs.title || "Loading...";
import LoaderGrayIcon from "../static/images/icons/loader-gray.svg";
return m(".component.loading-indicator", [
m("img.icon.loading-icon", {src: "static/images/icons/loader-gray.svg"}),
m(".title", title),
]);
},
};
const LoadingIndicator = {
view: function(vnode) {
const title = vnode.attrs.title || "Loading...";
return m(".component.loading-indicator", [
m("img.icon.loading-icon", {src: LoaderGrayIcon}),
m(".title", title),
]);
},
};
var WithRouteTriggeredLoader = {
oninit: function(vnode) {
this.loadFn = vnode.attrs.loadFn;
this.requestInFlight = false;
this.refetchOnUpdate = true;
if ("refetchOnUpdate" in vnode.attrs) { this.refetchOnUpdate = vnode.attrs.refetchOnUpdate; }
const WithRouteTriggeredLoader = {
oninit: function(vnode) {
this.loadFn = vnode.attrs.loadFn;
this.requestInFlight = false;
// Trigger initial fetch
this.fetchAndRedraw();
},
this.refetchOnUpdate = true;
if ("refetchOnUpdate" in vnode.attrs) { this.refetchOnUpdate = vnode.attrs.refetchOnUpdate; }
fetchAndRedraw: function() {
this.loaded = false;
this.loadedData = null;
// Trigger redraw with emptied data
m.redraw();
// Trigger initial fetch
this.fetchAndRedraw();
},
this.requestInFlight = true;
(this.loadFn ? this.loadFn() : Promise.resolve())
.then(data => {
this.requestInFlight = false;
this.loadedData = data;
this.loaded = true;
this.currentRoute = m.route.get();
m.redraw();
});
},
fetchAndRedraw: function() {
this.loaded = false;
this.loadedData = null;
// Trigger redraw with emptied data
// NOTE: this redraw doesn't work with onmatch (since we're code splitting) versus `render`
// It will render two components on the page instead of one
// m.redraw();
onupdate: function(vnode) {
var newRoute = m.route.get();
var currentRoute = this.currentRoute;
this.requestInFlight = true;
(this.loadFn ? this.loadFn() : Promise.resolve())
.then(data => {
this.requestInFlight = false;
this.loadedData = data;
this.loaded = true;
this.currentRoute = m.route.get();
m.redraw();
});
},
// If the route has been updated & refetching on update is turned on then re load
if (newRoute != currentRoute && this.refetchOnUpdate && !this.requestInFlight) {
this.fetchAndRedraw();
}
},
onupdate: function(vnode) {
const newRoute = m.route.get();
const currentRoute = this.currentRoute;
view: function(vnode) {
var loader = m(LoadingIndicator, {title: vnode.attrs.title});
// If the route has been updated & refetching on update is turned on then re load
if (newRoute != currentRoute && this.refetchOnUpdate && !this.requestInFlight) {
this.fetchAndRedraw();
}
},
return m(".component.with-loader", [
this.loaded ? vnode.attrs.childFn(this.loadedData) : loader
]);
},
};
view: function(vnode) {
const loader = m(LoadingIndicator, {title: vnode.attrs.title});
// SystemJS export
exportModule({component: WithRouteTriggeredLoader});
},
};
});
return m(".component.with-loader", [
this.loaded ? vnode.attrs.childFn(this.loadedData) : loader
]);
},
};
export default WithRouteTriggeredLoader;
......@@ -8,11 +8,6 @@
<link rel="stylesheet" href="static/css/app.css"/>
</head>
<body>
<script src="static/vendor/mithril/1.1.6/mithril.min.js"></script>
<script src="static/vendor/s.min.js"></script>
<script type="text/javascript">
System.import("./app.js");
</script>
<script src="./app.js"></script>
</body>
</html>
This diff is collapsed.
......@@ -14,9 +14,14 @@
"build-static": "mkdir -p dist && cp -r static dist/",
"build-watch": "ls index.html app.js static/css/app.css components/* services/* | entr -rc npm run build",
"serve": "./node_modules/.bin/http-server dist/",
"serve-watch": "ls index.html app.js static/css/app.css | entr -rc bash -c 'npm run build && npm run serve'"
"serve-watch": "ls index.html app.js static/css/app.css | entr -rc bash -c 'npm run build && npm run serve'",
"parcel": "parcel index.html"
},
"devDependencies": {
"http-server": "^0.11.1"
"http-server": "^0.11.1",
"parcel-bundler": "^1.11.0"
},
"dependencies": {
"static": "^2.0.0"
}
}
This diff is collapsed.
This diff is collapsed.