Prepare website for domain substitution #135
12
README.md
@ -12,12 +12,14 @@ Clone the project:
|
||||
|
||||
Install Zola.
|
||||
|
||||
Start:
|
||||
Start with targeting `m-labs.hk` domain:
|
||||
|
||||
```
|
||||
zola serve
|
||||
|
||||
```
|
||||
|
||||
Environmental variable `DOMAINNAME` can be specified to [substitute links on the website](#domain-handling).
|
||||
|
||||
To build the .bundle.js from .jsx files:
|
||||
|
||||
```
|
||||
@ -28,3 +30,11 @@ To build the .bundle.js from .jsx files:
|
||||
|
||||
Development builds are also available. `npm run build-dev` to re/build once, or `npm run start-dev` for incremental
|
||||
continuous builds as source files change.
|
||||
|
||||
## Domain handling
|
||||
|
||||
Environmental variable `DOMAINNAME` controls only the following links on the website:
|
||||
* email `mailto:` links
|
||||
* hook for the RFQ server (`window.API_RFQ`) variable
|
||||
|
||||
If absent, `DOMAINNAME` defaults to `m-labs.hk`.
|
||||
|
@ -18,4 +18,4 @@ Selling drinks is not our main business and only a service we do to other Club M
|
||||
* In case of any dispute, the seller is always right.
|
||||
|
||||
|
||||
Contact: [sb@m-labs.hk](mailto:sb@m-labs.hk)
|
||||
Contact: {{ email(address="sb") }}
|
||||
|
@ -83,5 +83,5 @@ Now is your chance to work on top-notch science and technology projects that get
|
||||
|
||||
|
||||
{% layout_centered_content() %}
|
||||
##### Contact us at [jobs@m-labs.hk](mailto:jobs@m-labs.hk) or [jobs@m-labs.ph](mailto:jobs@m-labs.ph)!
|
||||
##### Contact us at {{ email(address="jobs") }} or [jobs@m-labs.ph](mailto:jobs@m-labs.ph)!
|
||||
{% end %}
|
||||
|
@ -62,7 +62,7 @@ The <a href="https://github.com/quartiq/stabilizer" target="_blank" rel="noopene
|
||||
|
||||
<div class="col-12 col-md-4">
|
||||
<p>
|
||||
To purchase this controller, email <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a>. We also offer firmware customizations and development of new features. Note that features that are not implemented in the open source code above (e.g. control from Kasli) are not supported unless purchased separately.
|
||||
To purchase this controller, email {{ email(address="sales") }}. We also offer firmware customizations and development of new features. Note that features that are not implemented in the open source code above (e.g. control from Kasli) are not supported unless purchased separately.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
@ -19,7 +19,7 @@ ARTIQ and the related components that we are developing ([Migen/MiSoC](/gateware
|
||||
|
||||
{% layout_funding(position="center", title="Sponsors") %}
|
||||
|
||||
We acknowledge support from our partners below. Please get in touch ([sales@m-labs.hk](mailto:sales@m-labs.hk)) if you also want to move ARTIQ forward!
|
||||
We acknowledge support from our partners below. Please get in touch ({{ email(address="sales") }}) if you also want to move ARTIQ forward!
|
||||
|
||||
{% end %}
|
||||
|
||||
|
@ -114,7 +114,7 @@ template = "page.html"
|
||||
|
||||
**Sinara hardware purchases, ports to your hardware, feature development, technical support, bugfixing**
|
||||
|
||||
contact [sales@m-labs.hk](mailto:sales@m-labs.hk)
|
||||
contact {{ email(address="sales") }}
|
||||
|
||||
We welcome inquiries from research groups of all sizes.<br>[See what has been funded before](/experiment-control/funding)
|
||||
|
||||
@ -237,6 +237,6 @@ We welcome inquiries from research groups of all sizes.<br>[See what has been fu
|
||||
</div>
|
||||
|
||||
{% layout_div(css="col-12 text-center") %}
|
||||
Want your project listed here? Write to [sb@m-labs.hk](mailto:sb@m-labs.hk).
|
||||
Want your project listed here? Write to {{ email(address="sb") }}.
|
||||
|
||||
{% end %}
|
||||
|
@ -14,7 +14,7 @@ The first ARTIQ core devices used hardware built in-house by physicists (based o
|
||||
|
||||
The Sinara hardware is in active development, and the latest information is available <a href="https://github.com/sinara-hw" target="_blank" rel="noopener noreferrer">on the wiki of each project's page</a>. Most of the hardware engineering is done at the <a href="https://www.ise.pw.edu.pl/" target="_blank" rel="noopener noreferrer">Institute for Electronics Systems</a> at the Warsaw University of Technology.
|
||||
|
||||
Kasli and EEMs can be ordered now. We can deliver a rack-mountable crate that contains all the cards, is fully tested, and is ready to be connected to your experiment and computer network. Use our [web-based configuration and ordering tool](../place-order), or contact <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a> with your requirements, and we will establish a quote.
|
||||
Kasli and EEMs can be ordered now. We can deliver a rack-mountable crate that contains all the cards, is fully tested, and is ready to be connected to your experiment and computer network. Use our [web-based configuration and ordering tool](../place-order), or contact {{ email(address="sales") }} with your requirements, and we will establish a quote.
|
||||
|
||||
{% end %}
|
||||
|
||||
@ -297,7 +297,7 @@ The 4624 AWG "Phaser" is a quad channel 1.25 GS/s RF generator card with dual IQ
|
||||
|
||||
We can deliver a rack-mountable crate that contains all the cards, is fully tested, and is ready to be connected to your experiment and computer network. The lead time can be as short as a few working days and we will provide assistance to help you set up your new equipment with ARTIQ via the online helpdesk. Using our AFWS tool, you can keep the firmware of your M-Labs devices up-to-date easily, and benefit from the new features we continuously develop into ARTIQ.
|
||||
|
||||
Use our [web-based configuration and ordering tool](../place-order), or contact <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a> with your requirements, and we will establish a quote.
|
||||
Use our [web-based configuration and ordering tool](../place-order), or contact <{{ email(address="sales") }} with your requirements, and we will establish a quote.
|
||||
|
||||
{% end %}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Built on the <a href="/gateware/migen/">MiSoC and Migen</a> technologies that or
|
||||
|
||||
The Mixxeo supported mixing from two DVI or HDMI sources up to 720p60, with crossfade, fade to black and potentially other effects with a latency of less than two frames.
|
||||
|
||||
<b>Status (Aug 2014)</b> - Main board and gateware have been <a href="/images/mixxeo_result.jpg">mostly functional</a> for a while, mechanical design and manufacturing for the case/mechatronics are progressing slowly. If you have the skills and would like to help out, email [sb@m-labs.hk](mailto:sb@m-labs.hk) or the mailing list.
|
||||
<b>Status (Aug 2014)</b> - Main board and gateware have been <a href="/images/mixxeo_result.jpg">mostly functional</a> for a while, mechanical design and manufacturing for the case/mechatronics are progressing slowly. If you have the skills and would like to help out, email {{ email(address="sb") }} or the mailing list.
|
||||
|
||||
<center><img src="/images/mixxeo_menu.png"><br /><br /><img src="/images/mixxeo_board.jpg" class="picimg"></center>
|
||||
|
||||
|
@ -26,6 +26,6 @@ smoltcp achieves <a href="https://github.com/smoltcp-rs/smoltcp#examplesbenchmar
|
||||
|
||||
The source code is available <a href="https://github.com/smoltcp-rs/smoltcp" rel="noopener noreferrer">on GitHub</a>.
|
||||
|
||||
**Commercial support for smoltcp is available.** Email [sales@m-labs.hk](mailto:sales@m-labs.hk).
|
||||
**Commercial support for smoltcp is available.** Email {{ email(address="sales") }}.
|
||||
|
||||
{% end %}
|
||||
|
13
static/js/shop/Domained.jsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import {DOMAIN} from "./utils";
|
||||
|
||||
|
||||
export function DomainedEmail({address}) {
|
||||
const target = `${address}@${DOMAIN}`;
|
||||
return <a href={"mailto:" + target}>{target}</a>
|
||||
}
|
||||
|
||||
export const DomainedRFQMessages = {
|
||||
OK: <>We've received your request and will be in contact soon.</>,
|
||||
ERROR: <>We cannot receive your request. Try using the export by coping the configuration and send it to us at <DomainedEmail address="sales"/></>
|
||||
}
|
@ -9,6 +9,7 @@ import {Layout} from "./Layout";
|
||||
import {Catalog} from "./Catalog";
|
||||
import {OrderPanel} from "./OrderPanel";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {DomainedEmail} from "./Domained";
|
||||
|
||||
/**
|
||||
* Component that renders the entire shop
|
||||
@ -61,7 +62,7 @@ export function Shop() {
|
||||
the combination would look like. Configure the card settings by tapping on the top of
|
||||
the card; many of the options can be adjusted even after the card has been shipped.
|
||||
If you have any issues with this ordering system, or if you need other configurations,
|
||||
email us directly anytime at <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a>.
|
||||
email us directly anytime at <DomainedEmail address="sales"/>.
|
||||
The price excludes shipping, is estimated, and must be confirmed by a quote.
|
||||
</p>
|
||||
)}
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import {createWithEqualityFn} from "zustand/traditional";
|
||||
import {data as shared_data, itemsUnfoldedList} from "./utils";
|
||||
import {DATA as shared_data, itemsUnfoldedList, API_RFQ} from "./utils";
|
||||
import {FillExtCrateData, FillExtOrderData, true_type_of} from "./options/utils";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import {FillResources} from "./count_resources";
|
||||
@ -10,6 +10,7 @@ import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
|
||||
import {Validation, validateEmail, validateNote, validateJSONInput} from "./validate";
|
||||
import {CratesToJSON, JSONToCrates} from "./json_porter";
|
||||
import {ProcessOptionsToData} from "./options/Options";
|
||||
import {DomainedRFQMessages} from "./Domained";
|
||||
sb10q
commented
Is it really necessary to split the messages into this other file? Is it really necessary to split the messages into this other file?
esavkin
commented
Well, the loader is the same for both JS and JSX, and it works fine if you move RFQMessages object into shop_store and import React, but pure JS files do not permit JSX (unless you import react) and it would be quite unexpected for developers to see JSX code in JS file. Also, the shop_store.js is already quite big and better be split in future. So both reasons are styling and best practices thing. Well, the loader is the same for both JS and JSX, and it works fine if you move RFQMessages object into shop_store and import React, but pure JS files do not permit JSX (unless you import react) and it would be quite unexpected for developers to see JSX code in JS file.
Also, the shop_store.js is already quite big and better be split in future.
So both reasons are styling and best practices thing.
sb10q
commented
A few-lines file with a couple strings is not good style and not best practice. A few-lines file with a couple strings is not good style and not best practice.
sb10q
commented
And it does not help with the size of shop_store.js either. And it does not help with the size of shop_store.js either.
esavkin
commented
It's not a couple of strings - it's a JSX code, one of the fields of which contains an actual link Also since we substitute domains, it is better to use some unified method of doing it, i.e. utilize I'll merge It's not a couple of strings - it's a JSX code, one of the fields of which contains an actual link `mailto:`. If it was just a string-only solution, it would appear in the page as `<a href="....">email</a>`, or without mailto links, which makes it less convenient.
Also since we substitute domains, it is better to use some unified method of doing it, i.e. utilize `DomainedEmail` component, that's why I added a link in this message.
I'll merge `RFQMessages` into `DomainedEmail`, though it is not exactly good for component hierarchy.
sb10q
commented
Cannot just access window.DOMAIN here, as you do in JS in other places? Cannot just access window.DOMAIN here, as you do in JS in other places?
esavkin
commented
Of course it can, just I don't want to populate external variables in the code. Of course it can, just I don't want to populate external variables in the code.
sb10q
commented
Then I don't see what the problem is. Splitting some random "RFQ" strings into Domained.jsx does not make any sense to me. Then I don't see what the problem is. Splitting some random "RFQ" strings into Domained.jsx does not make any sense to me.
esavkin
commented
I'm now not sure what do you want from this. If you want it to remain in shop_store, then I explained earlier why it is not suitable here. I'm now not sure what do you want from this. If you want it to remain in shop_store, then I explained earlier why it is not suitable here.
sb10q
commented
What's the issue if you access window.DOMAIN in shop_store.js and keep the strings there? What's the issue if you access window.DOMAIN in shop_store.js and keep the strings there?
esavkin
commented
For what purpose? Of course it is possible to make something like template string and leave the email unclickable, but it is a regress relative to this PR in usability and in code quality relative to before this PR. For what purpose?
With this PR the email in RFQ error case becomes clickable, which is an usability improvement.
These "strings" are JSX elements now, i.e. rendered as HTML, and not as a text. If they would remain strings, the clickable email wouldn't be possible, because it would be rendered as text (i.e. user would see the html itself).
Since normally JS doesn't contain JSX elements, it would be a weird practice to make shop_store.js depend on React to add such elements. Also, I introduced shop_store.js in earlier refactoring to keep data/logic away from rendering as much as possible, which is a standard practice. So putting the "strings" (actually elements) back to shop_store would be a regress.
Also spreading dependencies on external variables across code is not a good practice either. I admit it is not in ideal state right now, but it was far worse before.
Of course it is possible to make something like template string and leave the email unclickable, but it is a regress relative to this PR in usability and in code quality relative to before this PR.
|
||||
|
||||
|
||||
const cards_to_pn_map = (cards) => {
|
||||
@ -228,7 +229,7 @@ const useSubmitForm = ((set, get) => ({
|
||||
status: Validation.OK,
|
||||
message: ""
|
||||
},
|
||||
API_RFQ: shared_data.API_RFQ,
|
||||
API_RFQ: API_RFQ,
|
||||
email: {
|
||||
value: "",
|
||||
error: null
|
||||
@ -306,18 +307,18 @@ const useSubmitForm = ((set, get) => ({
|
||||
if (response.status !== 200) {
|
||||
throw Error("Response status is not OK: " + response.status + ".\n" + response);
|
||||
}
|
||||
get().finishSubmitForm({status: Validation.OK, message: "We've received your request and will be in contact soon."})
|
||||
get().finishSubmitForm({status: Validation.OK, message: DomainedRFQMessages.OK})
|
||||
}, reason => {
|
||||
console.error("Request rejected, reason:", reason)
|
||||
get().finishSubmitForm({
|
||||
status: Validation.Invalid,
|
||||
message: "We cannot receive your request. Try using the export by coping the configuration and send it to us at sales@m-labs.hk"
|
||||
message: DomainedRFQMessages.ERROR
|
||||
})
|
||||
}).catch(err => {
|
||||
console.error("Request failed, reason:", err)
|
||||
get().finishSubmitForm({
|
||||
status: Validation.Invalid,
|
||||
message: "We cannot receive your request. Try using the export by coping the configuration and send it to us at sales@m-labs.hk"
|
||||
message: DomainedRFQMessages.ERROR
|
||||
})
|
||||
})
|
||||
},
|
||||
|
@ -1,7 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
export const data = window.shop_data;
|
||||
export const itemsUnfoldedList = Array.from(data.columns.catalog.categories.map(groupId => groupId.itemIds).flat());
|
||||
export const DATA = window.shop_data;
|
||||
export const DOMAIN = window.DOMAIN;
|
||||
export const API_RFQ = window.API_RFQ;
|
||||
export const itemsUnfoldedList = Array.from(DATA.columns.catalog.categories.map(groupId => groupId.itemIds).flat());
|
||||
|
||||
export const productStyle = (style, snapshot, removeAnim, hovered, selected, cart=false) => {
|
||||
const custom = {
|
||||
|
@ -1,6 +1,4 @@
|
||||
const shop_data = {
|
||||
|
||||
API_RFQ: 'https://hooks.m-labs.hk/rfq',
|
||||
currency: 'USD',
|
||||
|
||||
crateModes: {
|
||||
sb10q
commented
Just define SHOP_API_RFQ in a generated config.js together with DOMAIN. Just define SHOP_API_RFQ in a generated config.js together with DOMAIN.
|
||||
|
@ -43,6 +43,7 @@
|
||||
<link href="{{ get_url(path='favicon.ico', cachebust=true) }}" rel="icon" type="image/x-icon">
|
||||
|
||||
{% block styles %}{% endblock %}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<h5 class="pb-3">Sales inquiries</h5>
|
||||
|
||||
<p>
|
||||
To purchase ARTIQ Sinara hardware, software and gateware development services, or to enter a technical support agreement, write to <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a>.
|
||||
To purchase ARTIQ Sinara hardware, software and gateware development services, or to enter a technical support agreement, write to <a href="mailto:sales@{{get_env(name="DOMAINNAME", default="m-labs.hk")}}">sales@{{get_env(name="DOMAINNAME", default="m-labs.hk")}}</a>.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
@ -15,7 +15,7 @@
|
||||
<h5 class="pb-3">Commercial technical support</h5>
|
||||
|
||||
<p>
|
||||
If you need help setting up ARTIQ hardware purchased from us, or if you have a commercial technical support agreement with us, email us anytime at <a href="mailto:helpdesk@m-labs.hk">helpdesk@m-labs.hk</a>.
|
||||
If you need help setting up ARTIQ hardware purchased from us, or if you have a commercial technical support agreement with us, email us anytime at <a href="mailto:helpdesk@{{get_env(name="DOMAINNAME", default="m-labs.hk")}}">helpdesk@{{get_env(name="DOMAINNAME", default="m-labs.hk")}}</a>.
|
||||
</p>
|
||||
|
||||
<h5 class="pb-3">Community support</h5>
|
||||
|
@ -46,6 +46,11 @@
|
||||
<!-- Load Data -->
|
||||
<script src="{{ get_url(path='js/shop_data.js', cachebust=true) }}"></script>
|
||||
|
||||
<script>
|
||||
window.DOMAIN = "{{get_env(name="DOMAINNAME", default="m-labs.hk")}}";
|
||||
window.API_RFQ = `https://hooks.${window.DOMAIN}/rfq`;
|
||||
</script>
|
||||
sb10q
commented
``window.DOMAIN = get_env(name="DOMAINNAME", default="m-labs.hk")`` ?
|
||||
|
||||
<!-- Load our React component. -->
|
||||
<!-- <script type="text/babel" src="{{ get_url(path='js/shop.jsx', cachebust=true) }}"></script> -->
|
||||
<script src="{{ get_url(path='js/shop.bundle.js', cachebust=true) }}"></script>
|
||||
|
1
templates/shortcodes/email.html
Normal file
@ -0,0 +1 @@
|
||||
<a href="mailto:{{address}}@{{get_env(name="DOMAINNAME", default="m-labs.hk")}}">{{address}}@{{get_env(name="DOMAINNAME", default="m-labs.hk")}}</a>
|
||||
sb10q
commented
What is that? What is that?
esavkin
commented
Template to generate email link, obviously Template to generate email link, obviously
sb10q
commented
Considering your constant rate of mistakes I better double-check instead of assuming it's "obvious". So this is what gets called when you use Considering your constant rate of mistakes I better double-check instead of assuming it's "obvious". So this is what gets called when you use ``{{ email(address="sb") }}``?
esavkin
commented
Yes Yes
sb10q
commented
Ok. This is fine then. Ok. This is fine then.
|
Just make it a default?
It's default, but updated docs for less confusion.
Just say you can set the DOMAINNAME environment variable to something else. It doesn't need to feature prominently.