@seanox/aspect-js
Version:
full stack JavaScript framework for SPAs incl. reactivity rendering, mvc / mvvm, models, expression language, datasource, virtual paths, unit test and some more
250 lines (229 loc) • 9.16 kB
JavaScript
(()=> {
// Imports the connector with the #import macro. Since the connector in turn
// uses the #export macro, it can then be used in the global scope.
#import benchmark/connector;
// Imports the mock-up tools with which the application behaves more realistic
#import benchmark/mockup;
const API_HOST_URL = window.location.pathcontext + "/api/" + DataSource.locale;
const API_LIST_MARKET_URL = API_HOST_URL + "/listMarket";
const API_LIST_DATATYPES_URL = API_HOST_URL + "/listDatatype";
const API_SEARCH_NEWS_URL = API_HOST_URL + "/searchNews";
const API_SEND_NEWSLETTER_URL = window.location.pathcontext + "/api/sendNewsletter";
const API_MEDIA_IMAGES_URL = window.location.pathcontext + "/api/media/";
const PIAAS_URL = window.location.pathcontext + "/";
const DATATYPE_BRANDS_ID = 1;
const DATATYPE_PRODUCT_GROUPS = 2;
const DATATYPE_PRODUCTS_ID = 3;
const DATATYPE_TECHNICAL_DATA_ID = 4;
const DATATYPE_EQUIPMENTS_ID = 5;
const DATATYPE_IMAGES_ID = 6;
const DATATYPE_ACCESSORIES_ID = 7;
const DATATYPE_MARKETING_TEXTS_ID = 8;
const DATATYPE_SERVICES_ID = 9;
const DATATYPE_MEDIA_ID = 10;
const FUNCTION_PREVIEW_YOU = 1;
const FUNCTION_PREVIEW_EMAIL = 2;
const FUNCTION_RECIPIENTS = 3;
const FUNCTION_PUBLISH = 4;
#export FUNCTION_PREVIEW_YOU FUNCTION_PREVIEW_EMAIL FUNCTION_RECIPIENTS FUNCTION_PUBLISH;
const news = Reactive({
market: {
list: null,
value: "",
get text() {
if (this.value
&& this.list)
return this.list.find(record => record.id === this.value).text;
return "";
},
get disabled() {
return this.list && this.list.length ? undefined : true;
},
onChange() {
if (this.value) {
connector.call("GET", API_LIST_DATATYPES_URL + "/" + this.value, null, (status, json) => {
if (status instanceof Error)
throw status;
news.datatype.list = json;
news.datatype.value = "";
});
}
}
},
datatype: {
list: null,
value: "",
get text() {
if (this.value
&& this.list)
return this.list.find(record => record.id === this.value).text;
return "";
},
get disabled() {
if (!this.list
|| !this.list.length)
return true;
return news.market.value ? undefined : true;
}
},
search: {
get disabled() {
return news.market.value && news.datatype.value
? undefined : true;
},
onClick() {
news.recipients.list = null;
connector.call("GET", API_SEARCH_NEWS_URL + "/" + news.market.value + "/" + news.datatype.value, null, (status, json) => {
if (status instanceof Error)
throw status;
news.list.marketId = parseInt(news.market.value);
news.list.market = news.market.text;
news.list.datatypeId = parseInt(news.datatype.value);
news.list.datatype = news.datatype.text;
json = Mockup.filterRecords(news.list.datatypeId, json);
// target url of the record must be set qualified
// images must be made market related
json.forEach((record, index) => {
record.targetUrl = PIAAS_URL
+ news.datatype.text.replaceAll(/\s+/g, "-").toLowerCase()
+ "/" + record.id;
if (record.images)
record.images = record.images.map(image =>
API_MEDIA_IMAGES_URL + news.market.value + "/" + image);
});
// additional fields for the view must be added before rendering
// if they are to be used reactive, because during rendering the
// consumers of the fields are detected
json.forEach((record, index) => {
record.selected = false;
record.active = true;
});
news.list.records = json;
});
}
},
list: {
marketId: null,
market: null,
datatypeId: null,
datatype: null,
records: null,
get exists() {
return this.market && this.datatype;
},
get empty() {
return this.length <= 0;
},
get length() {
return this.filter().length;
},
isProductGroup(record) {
return record
&& record.datatype === DATATYPE_PRODUCT_GROUPS
&& this.datatypeId !== DATATYPE_PRODUCT_GROUPS;
},
filter() {
return (this.records || []).filter(record =>
!news.list.isProductGroup(record));
}
},
selection: {
get status() {
// status knows three states of selection:
// not (undefined), partial, all
const records = news.list.filter();
const active = records.filter(record =>
record.active).length;
const selectable = records.filter(record =>
record.active && !record.selected).length;
if (records.length <= 0
|| active <= 0
|| active === selectable)
return undefined;
return selectable === 0 ? "all" : "partial";
},
get records() {
return news.list.filter().filter(record =>
record.active && record.selected);
},
onClick(event) {
const unique = String(event.target.id.match(/[^#]+$/));
if (unique === "toggle") {
const selected = this.status !== "all";
news.list.filter()
.filter(record =>
record.active)
.forEach(record =>
record.selected = selected);
event.target.checked = !!this.status;
} else news.list.records[unique].selected = !news.list.records[unique].selected;
}
},
function: {
value: "",
recipients: {
value: "",
error: ""
},
apply: {
get disabled() {
// simple condition, because string and number are compared
const disabled = !news.selection.status
|| !news.function.value
|| (news.function.value == FUNCTION_PREVIEW_EMAIL
&& (!news.function.recipients.value || news.function.recipients.error))
return disabled ? true : undefined;
},
onClick() {
if (this.disabled)
return;
// In the tutorial only a GET request, otherwise POST + payload
// of the data for sending mail.
connector.call("GET", API_SEND_NEWSLETTER_URL, null, (status, json) => {
if (status instanceof Error)
throw status;
// The response is a JSON file containing the echo of the
// called function and a detailed list of recipients. This
// is simulated in the tutorial with JavaScript.
// To reflect the low implementation effort, mockup was
// outsourced to an extra module.
news.recipients.list = Mockup.sendNewsletter(parseInt(news.function.value),
news.function.recipients.value.split(/\s+/),
news.selection.records.map(record => record.id)).recipients;
if (news.function.value != FUNCTION_PUBLISH)
return;
news.selection.records.forEach(record => {
record.active = false;
record.selected = false;
});
});
}
}
},
recipients: {
list: null,
get exists() {
return this.list !== null;
},
get empty() {
return this.length <= 0;
},
get length() {
return (this.list || []).length;
}
}
});
// Object news was declared as const in the current scope. To make it globally
// usable, it is made public with the #export macro.
#export news;
// Test of invalid macros #import !!!
console.log("#import !!!");
console.log('#import !!!');
console.log(`#import !!!`);
/* #import !!! */
// Test of invalid macros #export !!!
console.log("#export !!!");
console.log('#export !!!');
console.log(`#export !!!`);
/* #export !!! */
});