diff --git a/.circleci/config.yml b/.circleci/config.yml
index ae06455..b82b5ff 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,17 +1,19 @@
version: 2
defaults: &defaults
docker:
- - image: circleci/python:2.7-stretch-browsers
+ - image: cimg/python:3.11.0-browsers
install_dependency: &install_dependency
name: Installation of build and deployment dependencies.
command: |
+ sudo apt update
sudo apt install jq
- sudo pip install awscli --upgrade
- sudo pip install docker-compose
+ sudo apt install python3-pip
+ sudo pip3 install awscli --upgrade
+ sudo pip3 install docker-compose
install_deploysuite: &install_deploysuite
name: Installation of install_deploysuite.
command: |
- git clone --branch v1.4.2 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript
+ git clone --branch v1.4.15 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript
cp ./../buildscript/master_deploy.sh .
cp ./../buildscript/buildenv.sh .
cp ./../buildscript/awsconfiguration.sh .
@@ -56,7 +58,15 @@ jobs:
environment:
DEPLOY_ENV: "DEV"
LOGICAL_ENV: "dev"
- APPNAME: "micro-frontends-taas-admin-app"
+ APPNAME: "micro-frontends-forums-app"
+ steps: *builddeploy_steps
+
+ "build-qa":
+ <<: *defaults
+ environment:
+ DEPLOY_ENV: "QA"
+ LOGICAL_ENV: "qa"
+ APPNAME: "micro-frontends-forums-app"
steps: *builddeploy_steps
"build-prod":
@@ -64,7 +74,7 @@ jobs:
environment:
DEPLOY_ENV: "PROD"
LOGICAL_ENV: "prod"
- APPNAME: "micro-frontends-taas-admin-app"
+ APPNAME: "micro-frontends-forums-app"
steps: *builddeploy_steps
workflows:
@@ -77,8 +87,16 @@ workflows:
filters:
branches:
only:
- - dev
+ - develop
+ # Development builds are executed on "develop" branch only.
+ - "build-qa":
+ context: org-global
+ filters:
+ branches:
+ only:
+ - qa
+
# Production builds are exectuted only on tagged commits to the
# master branch.
- "build-prod":
diff --git a/README.md b/README.md
index 294170a..7db5a7c 100644
--- a/README.md
+++ b/README.md
@@ -103,21 +103,21 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t
2. Run **Navbar** micro-app:
```sh
- git clone https://github.com/topcoder-platform/micro-frontends-navbar-app.git
- cd micro-frontends-navbar-app
+ git clone https://github.com/topcoder-platform/mfe-header.git
+ cd mfe-header
```
- Update in file `micro-frontends-navbar-app/config/dev.js` values for `ACCOUNTS_APP_CONNECTOR` and `AUTH` to `http://localhost:5000` so Navbar app which handles authentication uses our local Authentication service.
+ Update in file `mfe-header/config/dev.js` values for `ACCOUNTS_APP_CONNECTOR` and `AUTH` to `http://localhost:5000` so Navbar app which handles authentication uses our local Authentication service.
```sh
- # inside folder "micro-frontends-navbar-app" run:
+ # inside folder "mfe-header" run:
nvm use # or make sure to use Node 10
npm i # to install dependencies
npm run dev
- # this host navbar app as http://localhost:3001/navbar/topcoder-micro-frontends-navbar-app.js
+ # this host navbar app as http://localhost:3001/navbar/topcoder-mfe-header.js
```
3. Run **Forums** micro-app:
@@ -147,4 +147,4 @@ Some config files are using domain `local.topcoder-dev.com`. You can change it t
- If you are not logged-in yet, you should be redirected to the login page.
- If you cannot see the application and redirect doesn't happen, make sure that file "http://local.topcoder-dev.com:8602/forums-app/topcoder-micro-frontends--app.js" is loaded successfully in the Network tab.
-Congratulations, you successfully run the project. If you had some issue, please, try to go through README of https://github.com/topcoder-platform/micro-frontends-frame and https://github.com/topcoder-platform/micro-frontends-navbar-app.
+Congratulations, you successfully run the project. If you had some issue, please, try to go through README of https://github.com/topcoder-platform/micro-frontends-frame and https://github.com/topcoder-platform/mfe-header.
diff --git a/config/index.js b/config/index.js
index ba0ff0d..167f29b 100644
--- a/config/index.js
+++ b/config/index.js
@@ -1,6 +1,14 @@
/* global process */
module.exports = (() => {
- const appEnv = process.env.APPENV === "prod" ? "prod" : "dev";
- return require(`./${appEnv}`);
-})();
+ const env = process.env.APPENV || "dev";
+
+ console.log(`APPENV: "${env}"`);
+
+ // for security reason don't let to require any arbitrary file defined in process.env
+ if (["prod", "dev", "qa"].indexOf(env) < 0) {
+ return require("./dev");
+ }
+
+ return require("./" + env);
+})();
\ No newline at end of file
diff --git a/config/qa.js b/config/qa.js
new file mode 100644
index 0000000..b992998
--- /dev/null
+++ b/config/qa.js
@@ -0,0 +1,7 @@
+module.exports = {
+ API: {
+ V3: "https://api.topcoder-qa.com/v3",
+ V5: "https://api.topcoder-qa.com/v5",
+ },
+ VANILLA_EMBED_JS: "https://vanilla.topcoder-qa.com/js/embed.js",
+};
diff --git a/package.json b/package.json
index ef4a7df..9143e16 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"start": "node server.js",
"dev": "cross-env APPMODE=development webpack-dev-server --port 8602 --host 0.0.0.0",
"dev-https": "cross-env APPMODE=development webpack-dev-server --https --port 8602 --host 0.0.0.0",
+ "qa": "cross-env APPMODE=development webpack-dev-server --port 8602 --host 0.0.0.0",
"build": "webpack --mode=${APPMODE:-production} --env.config=${APPENV:-prod}",
"analyze": "webpack --mode=production --env.analyze=true",
"lint": "eslint ./src --ext .js,.jsx",
diff --git a/src/embed-test.js b/src/embed-test.js
new file mode 100644
index 0000000..061e847
--- /dev/null
+++ b/src/embed-test.js
@@ -0,0 +1,397 @@
+/* eslint-disable */
+export default () => {
+ if (window.vanilla == undefined) window.vanilla = {};
+ window.vanilla_lazy_load = undefined
+
+ if (window.vanilla.embeds == undefined) window.vanilla.embeds = {};
+
+ window.vanilla.embed = function (host) {
+ var scripts = document.getElementsByTagName("script"),
+ id = Math.floor(Math.random() * 100000).toString(),
+ embedUrl = window.location.href.split("#")[0],
+ jsPath = "/js/embed.js",
+ currentPath = window.location.hash.substr(1),
+ disablePath = window != top;
+
+ var optStr = function (name, defaultValue, definedValue) {
+ if (window["vanilla_" + name]) {
+ if (definedValue == undefined) return window["vanilla_" + name];
+ else return definedValue.replace("%s", window["vanilla_" + name]);
+ }
+ return defaultValue;
+ };
+
+ if (!currentPath || disablePath) currentPath = "/";
+
+ if (currentPath.substr(0, 1) != "/") currentPath = "/" + currentPath;
+
+ if (window.gadgets) embedUrl = "";
+
+ if (typeof host == "undefined") {
+ host = "";
+ window.host_base_url = "";
+ for (var i = 0; i < scripts.length; i++) {
+ if (scripts[i].src.indexOf(jsPath) > 0) {
+ host = scripts[i].src;
+ host = host.replace("http://", "").replace("https://", "");
+ host = host.substr(0, host.indexOf(jsPath));
+
+ host_base_url = scripts[i].src;
+ host_base_url = host_base_url.substr(
+ 0,
+ host_base_url.indexOf(jsPath)
+ );
+ if (host_base_url.substring(host_base_url.length - 1) != "/")
+ host_base_url += "/";
+ }
+ }
+ }
+
+ window.vanilla.embeds[id] = this;
+ if (window.postMessage) {
+ var onMessage = function (e) {
+ console.log("---- message ----", e);
+
+ // Check that we're getting a vanilla message
+ if (typeof e.data === "string") {
+ var message = e.data.split(":");
+ var frame = document.getElementById("vanilla" + id);
+
+ // Unload event's source is undefined
+ var isUnload = message[0] == "unload";
+ if (!frame || (!isUnload && frame.contentWindow != e.source)) {
+ return;
+ }
+ processMessage(message);
+ }
+ };
+ if (window.addEventListener) {
+ window.addEventListener("message", onMessage, false);
+ } else {
+ window.attachEvent("onmessage", onMessage);
+ }
+ } else {
+ var messageId = null;
+ setInterval(function () {
+ try {
+ var vid = "vanilla" + id;
+ var hash = window.frames[vid].frames["messageFrame"].location.hash;
+ hash = hash.substr(6);
+ } catch (e) {
+ return;
+ }
+
+ var message = hash.split(":");
+ var newMessageId = message[0];
+ if (newMessageId == messageId) {
+ return;
+ }
+
+ messageId = newMessageId;
+ message.splice(0, 1);
+ processMessage(message);
+ }, 200);
+ }
+
+ const checkHash = function () {
+ debugger;
+ var path = window.location.hash.substr(1) || "/";
+ if (path != currentPath) {
+ currentPath = path;
+ window.frames["vanilla" + id].location.replace(vanillaUrl(path));
+ }
+ };
+
+ if (!window.gadgets) {
+ if (!disablePath) {
+ if ("onhashchange" in window) {
+ if (window.addEventListener)
+ window.addEventListener("hashchange", checkHash, false);
+ else window.attachEvent("onhashchange", checkHash);
+ } else {
+ setInterval(checkHash, 300);
+ }
+ }
+ }
+
+ // Strip param out of str if it exists
+ const stripParam = function (str, param) {
+ var pIndex = str.indexOf(param);
+ if (pIndex > -1) {
+ var pStr = str.substr(pIndex);
+ var tIndex = pStr.indexOf("&");
+ var trail = tIndex > -1 ? pStr.substr(tIndex + 1) : "";
+ var pre = currentPath.substr(pIndex - 1, 1);
+ if (pre == "&" || pre == "?") pIndex--;
+
+ return str.substr(0, pIndex) + (trail.length > 0 ? pre : "") + trail;
+ }
+ return str;
+ };
+
+ const processMessage = function (message) {
+ var iframe = document.getElementById("vanilla" + id);
+
+ if (message[0] == "height") {
+ setHeight(message[1]);
+
+ if (message[1] > 0) {
+ iframe.style.visibility = "visible";
+ }
+ } else if (message[0] == "location") {
+ if (message[1] != "") {
+ iframe.style.visibility = "visible";
+ }
+
+ if (disablePath) {
+ //currentPath = cmd[1];
+ } else {
+ currentPath = window.location.hash.substr(1);
+ if (currentPath != message[1]) {
+ currentPath = message[1];
+ // Strip off the values that this script added
+ currentPath = stripParam(currentPath, "remote="); // 1
+ currentPath = stripParam(currentPath, "locale="); // 2
+ //window.location.hash = currentPath;
+ }
+ }
+ } else if (message[0] == "unload") {
+ // Scroll to the top of the IFRAME if the top position is not in the view.
+ var currentScrollAmount =
+ window.pageYOffset || document.documentElement.scrollTop;
+ var offsetTop = offsetFromTop("vanilla" + id);
+ if (offsetTop - currentScrollAmount < 0) {
+ window.scrollTo(0, offsetTop);
+ }
+
+ iframe.style.visibility = "hidden";
+ } else if (message[0] == "scrolltop") {
+ window.scrollTo(0, document.getElementById("vanilla" + id).offsetTop);
+ } else if (message[0] == "scrollto") {
+ window.scrollTo(
+ 0,
+ document.getElementById("vanilla" + id).offsetTop -
+ 40 +
+ message[1] * 1
+ );
+ } else if (message[0] == "unembed") {
+ document.location = "http://" + host + window.location.hash.substr(1);
+ }
+ };
+
+ const offsetFromTop = function (id) {
+ var node = document.getElementById(id),
+ top = 0,
+ topScroll = 0;
+ if (node.offsetParent) {
+ do {
+ top += node.offsetTop;
+ topScroll += node.offsetParent ? node.offsetParent.scrollTop : 0;
+ } while ((node = node.offsetParent));
+ return top - topScroll;
+ }
+ return -1;
+ };
+
+ const setHeight = function (height) {
+ if (optStr("height")) return;
+ // if (document.getElementById("vanilla" + id).style["height"] === ( height - 21 ) + 'px') {
+ // return
+ // }
+
+ // document.getElementById("vanilla" + id).style["height"] = height + "px";
+ document.getElementById("vanilla" + id).style["height"] = 'calc(100vh - 76px)'
+ if (window.gadgets && gadgets.window && gadgets.window.adjustHeight) {
+ try {
+ gadgets.window.adjustHeight();
+ } catch (ex) {
+ // Do nothing...
+ }
+ }
+ };
+
+ const vanillaUrl = function (path) {
+ // What type of embed are we performing?
+ var embed_type =
+ typeof vanilla_embed_type == "undefined"
+ ? "standard"
+ : vanilla_embed_type;
+ // Are we loading a particular discussion based on discussion_id?
+ var discussion_id =
+ typeof vanilla_discussion_id == "undefined" ? 0 : vanilla_discussion_id;
+ // Are we loading a particular discussion based on foreign_id?
+ var foreign_id =
+ typeof vanilla_identifier == "undefined" ? "" : vanilla_identifier;
+ // Is there a foreign type defined? Possibly used to render the discussion
+ // body a certain way in the forum? Also used to filter down to foreign
+ // types so that matching foreign_id's across type don't clash.
+ var foreign_type =
+ typeof vanilla_type == "undefined" ? "page" : vanilla_type;
+ // If embedding comments, should the newly created discussion be placed in a specific category?
+ var category_id =
+ typeof vanilla_category_id == "undefined" ? "" : vanilla_category_id;
+ // If embedding comments, this value will be used to reference the foreign content. Defaults to the url of the page this file is included in.
+ var foreign_url =
+ typeof vanilla_url == "undefined"
+ ? document.URL.split("#")[0]
+ : vanilla_url;
+ // Are we forcing a locale via Multilingual plugin?
+ var embed_locale =
+ typeof vanilla_embed_locale == "undefined" ? "" : vanilla_embed_locale;
+ if (typeof vanilla_lazy_load == "undefined") vanilla_lazy_load = true;
+
+ // If path was defined, and we're sitting at app root, use the defined path instead.
+ if (typeof vanilla_path != "undefined" && path == "/")
+ path = vanilla_path;
+
+ // Force type based on incoming variables
+ if (discussion_id != "" || foreign_id != "") embed_type = "comments";
+
+ var result = "";
+
+ if (embed_type == "comments") {
+ result =
+ "//" +
+ host +
+ "/discussion/embed/" +
+ // Break the cache. /embed/ gets cached, looks like you are not logged in.
+ "&c=" +
+ new Date().getTime() +
+ "&vanilla_identifier=" +
+ encodeURIComponent(foreign_id) +
+ "&vanilla_url=" +
+ encodeURIComponent(foreign_url);
+
+ if (typeof vanilla_type != "undefined")
+ result += "&vanilla_type=" + encodeURIComponent(vanilla_type);
+
+ if (typeof vanilla_discussion_id != "undefined")
+ result +=
+ "&vanilla_discussion_id=" +
+ encodeURIComponent(vanilla_discussion_id);
+
+ if (typeof vanilla_category_id != "undefined")
+ result +=
+ "&vanilla_category_id=" + encodeURIComponent(vanilla_category_id);
+
+ if (typeof vanilla_title != "undefined")
+ result += "&title=" + encodeURIComponent(vanilla_title);
+ } else {
+ result =
+ "//" +
+ host +
+ path +
+ "&remote=" +
+ encodeURIComponent(embedUrl) +
+ "&locale=" +
+ encodeURIComponent(embed_locale);
+ }
+
+ if (window.vanilla_sso) {
+ result += "&sso=" + encodeURIComponent(vanilla_sso);
+ }
+
+ return result.replace(/\?/g, "&").replace("&", "?"); // Replace the first occurrence of amp with question.
+ };
+ var vanillaIframe = document.createElement("iframe");
+ vanillaIframe.id = "vanilla" + id;
+ vanillaIframe.name = "vanilla" + id;
+ vanillaUrl(currentPath);
+ vanillaIframe.src =
+ "https://vanilla.topcoder-dev.com/?remote=https://local.topcoder-dev.com/forums&locale=";
+ vanillaIframe.scrolling = "yes";
+ vanillaIframe.frameBorder = "0";
+ vanillaIframe.allowTransparency = true;
+ vanillaIframe.border = "0";
+ vanillaIframe.width = "100%";
+ vanillaIframe.style.width = "100%";
+ vanillaIframe.style.border = "0";
+ vanillaIframe.style.display = "block"; // must be block
+
+ if (window.postMessage) {
+ vanillaIframe.height = "0";
+ vanillaIframe.style.height = "0";
+ } else {
+ vanillaIframe.height = "300";
+ vanillaIframe.style.height = "300px";
+ }
+
+ var img = document.createElement("div");
+ img.className = "vn-loading";
+ img.style.textAlign = "center";
+ img.innerHTML = window.vanilla_loadinghtml
+ ? vanilla_loadinghtml
+ : '';
+
+ var container = document.getElementById("vanilla-comments");
+ // Couldn't find the container, so dump it out and try again.
+ if (!container) document.write('