Skip to content

Instantly share code, notes, and snippets.

Avatar

Johannes Brodwall jhannes

View GitHub Profile
@jhannes
jhannes / ApplicationTexts.en.ts
Created Oct 29, 2020
Localization with TypeScript and React context
View ApplicationTexts.en.ts
const english: ApplicationTexts = {
standardTexts: {
submit: "Submit",
},
personTexts: {
givenName: "First name",
familyName: "Last name",
title: "Title",
header: "Enter your details"
}
@jhannes
jhannes / ApplicationTexts.ts
Last active Oct 29, 2020
Localization with TypeScript and React context
View ApplicationTexts.ts
interface ApplicationTexts {
standardTexts: {
submit: string;
};
personTexts: {
givenName: string;
familyName: string;
title: string;
header: string;
};
@jhannes
jhannes / App.tsx
Last active Oct 29, 2020
Localization with TypeScript and React context
View App.tsx
export default function App() {
const [language, setLanguage] = useState(english);
return (
<ApplicationTextsContext.Provider value={language}>
<div className="App">
<MainPage />
<SelectLanguage onChangeLanguage={setLanguage} />
</div>
</ApplicationTextsContext.Provider>
);
@jhannes
jhannes / MainPage.tsx
Last active Oct 29, 2020
Localization with TypeScript and React context
View MainPage.tsx
function MainPage() {
const { standardTexts, personTexts: texts } = useContext(
ApplicationTextsContext
);
return (
<div>
<h2>{texts.header}</h2>
<div>
<label>{texts.givenName}:</label>
<input />
@jhannes
jhannes / useLoader.ts
Created Oct 24, 2020
Zombie spinner killer
View useLoader.ts
function useLoader<T>(
loadingFunction: () => Promise<T>,
deps: DependencyList[] = []
) {
const [data, setData] = useState<T | undefined>();
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | undefined>();
async function reload() {
setData(undefined);
@jhannes
jhannes / TodoList.tsx
Last active Oct 24, 2020
React Zombie spinner killer
View TodoList.tsx
function TodoList({ list }: { list: string }) {
const { data, error, loading, reload } = useLoader(
async () => listTodos(list),
[list]
);
return (
<>
<h2>Items in {list}</h2>
{loading && <Spinner />}
{error && <ErrorView error={error} reload={reload} />}
@jhannes
jhannes / GoogleForms-to-Trello.gs
Last active Aug 27, 2019
Google Forms to Trello
View GoogleForms-to-Trello.gs
var authentication = "key=a...&token=9...";
var idBoard = "592....";
var inboxList = "592...";
var updatedLabel = "592....";
function getField(itemResponses, fieldName) {
var titles = [];
for (var i in itemResponses) {
if (itemResponses[i].getItem().getTitle() === fieldName && itemResponses[i].getResponse().length > 0) {
@jhannes
jhannes / AnnotationScanner.java
Created Jan 16, 2015
Jetty 9 embedded Servlet 3.0 annotations without war file
View AnnotationScanner.java
public class AnnotationScanner {
protected void scanForAnnotations(final String javaPackage, WebAppContext webapp) throws Exception {
Set<AnnotationParser.Handler> handlers = new HashSet<>();
handlers.add(new WebServletAnnotationHandler(webapp));
handlers.add(new WebFilterAnnotationHandler(webapp));
handlers.add(new WebListenerAnnotationHandler(webapp));
AnnotationParser annotationParser = new AnnotationParser();
for (URL url : ((URLClassLoader) getClass().getClassLoader()).getURLs()) {
@jhannes
jhannes / package.json
Last active Aug 29, 2015
Promises you can trust
View package.json
{
"name": "promises",
"scripts": {
"test": "node node_modules/mocha/bin/mocha --watch --growl"
},
"devDependencies": {
"chai": "^1.10.0",
"mocha": "^2.0.1"
},
"dependencies": {
@jhannes
jhannes / AppConfiguration.java
Last active Oct 19, 2016
Dead simple configuration
View AppConfiguration.java
package com.johannesbrodwall.infrastructure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;