Skip to content

Commit 17807b2

Browse files
committed
Add a gallery, deploy to Firebase.
1 parent 6befd94 commit 17807b2

9 files changed

+149
-27
lines changed

.firebaserc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "emrg-pcg"
4+
}
5+
}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.DS_Store
2+
*.log

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ The app runs as a single-page application, so we use [serve](https://www.npmjs.c
1515

1616
## Deploy
1717

18-
surge -d pcg .
18+
npm install -g firebase-tools
19+
firebase login
20+
firebase init
21+
firebase deploy

css/style.css

+50-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
box-sizing: border-box;
55
}
66

7+
img {
8+
max-width: 100%;
9+
}
10+
711
html,
812
body {
913
width: 100%;
@@ -89,19 +93,63 @@ a {
8993
justify-self: flex-end;
9094
}
9195

96+
.header__nav .button.unsaved {
97+
background: #6a6;
98+
}
99+
92100
/* Page */
93101

94102
.page {
95103
flex: 1;
96-
xbackground: radial-gradient(circle farthest-corner at 50%, #444, #000);
97104
background: linear-gradient(0deg, #000, #222);
98-
99105
display: flex;
106+
flex-direction: column;
100107
justify-content: center;
101108
align-items: center;
102109
color: white;
103110
}
104111

112+
.page h1 {
113+
font-weight: 200;
114+
margin-bottom: 1rem;
115+
}
116+
117+
.page a {
118+
padding-bottom: 2px;
119+
border-bottom: 1px solid rgba(255, 255, 255, 0.5);
120+
}
121+
122+
.page a:hover {
123+
border-bottom-color: rgba(255, 255, 255, 0.9);
124+
}
125+
126+
/* Gallery */
127+
128+
.gallery {
129+
display: flex;
130+
flex-wrap: wrap;
131+
}
132+
133+
.gallery__thumb {
134+
width: 250px;
135+
height: 250px;
136+
margin: 10px;
137+
}
138+
139+
.gallery__img {
140+
border-radius: 3px;
141+
}
142+
143+
.gallery__link {
144+
display: inline-block;
145+
border: 0 !important;
146+
}
147+
148+
.gallery__link:active {
149+
transform: translateY(2px);
150+
}
151+
152+
105153
/* Editor */
106154

107155
.editor {

firebase.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"hosting": {
3+
"public": ".",
4+
"ignore": [
5+
"firebase.json",
6+
"**/.*"
7+
],
8+
"rewrites": [{
9+
"source": "**",
10+
"destination": "/index.html"
11+
}]
12+
}
13+
}

gallery/-L0iXXTIHpU3fd0hXiEo.png

27.4 KB
Loading

gallery/-L0ibWrnaptySlFrOniw.png

106 KB
Loading

index.html

+13-13
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
<head>
44
<meta charset="UTF-8">
55
<title>PCG</title>
6-
<link rel="stylesheet" href="css/style.css">
6+
<link rel="stylesheet" href="/css/style.css">
77
</head>
88
<body>
9-
<!-- <script src="https://www.gstatic.com/firebasejs/4.6.2/firebase.js"></script>
9+
<script src="https://www.gstatic.com/firebasejs/4.6.2/firebase.js"></script>
1010
<script>
1111
const config = {
12-
apiKey: "AIzaSyAN0gHQS-9LpMozdRCHKFqcyZ2x6b17o9I",
13-
authDomain: "emrgpcg.firebaseapp.com",
14-
databaseURL: "https://emrgpcg.firebaseio.com",
15-
projectId: "emrgpcg",
16-
storageBucket: "emrgpcg.appspot.com",
17-
messagingSenderId: "670989392506"
12+
apiKey: "AIzaSyCplihRW4j3gUo7uvpndnyXAYfQgPRtTn4",
13+
authDomain: "emrg-pcg.firebaseapp.com",
14+
databaseURL: "https://emrg-pcg.firebaseio.com",
15+
projectId: "emrg-pcg",
16+
storageBucket: "emrg-pcg.appspot.com",
17+
messagingSenderId: "972956794987"
1818
};
1919
firebase.initializeApp(config);
20-
</script> -->
21-
<script src="third_party/preact.min.js"></script>
22-
<script src="third_party/preact-router.min.js"></script>
23-
<script src="js/pcg.js"></script>
24-
<script src="js/editor.js"></script>
20+
</script>
21+
<script src="/third_party/preact.min.js"></script>
22+
<script src="/third_party/preact-router.min.js"></script>
23+
<script src="/js/pcg.js"></script>
24+
<script src="/js/editor.js"></script>
2525
</body>
2626
</html>

js/editor.js

+63-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { h, render, Component } = preact;
2-
const { Router, Link } = preactRouter;
2+
const { route, Router, Link } = preactRouter;
33

44
const INITIAL_TEXT = `root:
55
- Dear {{ giver }}, thank you for the {{ object }}.
@@ -16,6 +16,11 @@ object:
1616
- dishwasher
1717
`;
1818

19+
const GALLERY = [
20+
'-L0iXXTIHpU3fd0hXiEo',
21+
'-L0ibWrnaptySlFrOniw'
22+
];
23+
1924
let gApp;
2025

2126
class Header extends Component {
@@ -29,21 +34,38 @@ class Header extends Component {
2934

3035
class Home extends Component {
3136
render(props, state) {
37+
const thumbs = GALLERY.map(id => this.renderThumb(id));
38+
console.log(thumbs);
3239
return h('div', {class: 'app'},
3340
h(Header, {},
3441
h(Link, {class: 'button', href: '/sketch'}, 'Create')
3542
),
3643
h('div', {class: 'page'},
37-
h('h1', {}, 'Click the "create" button to create a new sketch.')
44+
h('h1', {}, 'Gallery'),
45+
h('div', {class: 'gallery'},
46+
thumbs
47+
)
48+
)
49+
);
50+
}
51+
52+
renderThumb(id) {
53+
return h('div', {class: 'gallery__thumb'},
54+
h(Link, {class: 'gallery__link', href: `/sketch/${id}`},
55+
h('img', {class: 'gallery__img', src: `/gallery/${id}.png`})
3856
)
3957
);
4058
}
4159
}
4260

4361
class Sketch extends Component {
44-
constructor() {
45-
super();
46-
this.state = { source: INITIAL_TEXT, debug: true, debugOutput: '', result: '' };
62+
constructor(props) {
63+
super(props);
64+
if (!props.id) {
65+
this.state = { source: INITIAL_TEXT, debug: true, debugOutput: '', result: '', unsaved: false };
66+
} else {
67+
this.state = { loading: true, source: '', debug: true, debugOutput: '', result: '', unsaved: false };
68+
}
4769
gApp = this;
4870
}
4971

@@ -59,30 +81,58 @@ class Sketch extends Component {
5981
}
6082

6183
componentDidMount() {
62-
this.generate();
84+
if (!this.props.id) {
85+
this.generate();
86+
} else {
87+
console.log('loading from database', this.props.id);
88+
firebase.database().ref(`sketch/${this.props.id}`).once('value', snap => {
89+
const sketch = { key: this.props.id, ...snap.val() };
90+
this.setState({ loading: false, source: sketch.source });
91+
this.generate();
92+
});
93+
}
94+
95+
window.addEventListener('beforeunload', (e) => {
96+
let confirm = null;
97+
if (this.state.unsaved) {
98+
confirm = 'You have unsaved changes.';
99+
(e || window.event).returnValue = confirm;
100+
}
101+
return confirm;
102+
});
63103
}
64104

65105
onInput(e) {
66106
const source = e.target.value;
67-
this.setState({ source: e.target.value });
107+
this.setState({ unsaved: true, source });
68108
this.generate();
69109
}
70110

71111
onSave() {
72-
// FIXME: save the content
112+
if (this.state.saving) return;
113+
this.setState({ saving: true });
114+
const ref = firebase.database().ref('sketch').push();
115+
ref.set({
116+
source: this.state.source
117+
}, () => {
118+
this.setState({ saving: false, unsaved: false });
119+
route(`/sketch/${ref.key}`);
120+
});
73121
}
74122

75123
render(props, state) {
76124
const debugView = h('pre', { className: 'debug' }, this.state.debugOutput);
125+
const source = state.loading ? 'Loading...' : state.source;
126+
let saveLabel = state.saving ? 'Saving...' : 'Save';
77127
return h('div', {class: 'app'},
78128
h(Header, {},
79-
h('button', {class: 'button', onClick: this.onSave.bind(this)}, 'Save')
129+
h('button', {class: 'button' + (state.unsaved ? ' unsaved' : ''), onClick: this.onSave.bind(this), disabled: state.saving}, saveLabel)
80130
),
81131
h('div', { className: 'editor' },
82132
h('div', { className: 'editor__toolbar' }, h('button', { class: 'button', onClick: this.generate.bind(this) }, 'Generate')),
83133
h('div', { className: 'editor__panels'},
84134
h('div', { className: 'editor__source' },
85-
h('textarea', { className: 'editor__area', value: state.source, onInput: this.onInput.bind(this) }),
135+
h('textarea', { className: 'editor__area', value: source, onInput: this.onInput.bind(this), readonly: state.loading }),
86136
debugView
87137
),
88138
h('div', { className: 'editor__viewer' },
@@ -99,7 +149,8 @@ class NotFound extends Component {
99149
return h('div', {class: 'app'},
100150
h(Header, {}),
101151
h('div', {class: 'page'},
102-
h('h1', {}, 'Page not found.')
152+
h('h1', {}, 'Page not found.'),
153+
h(Link, {href: '/'}, 'Go Back Home')
103154
)
104155
);
105156
}
@@ -110,6 +161,7 @@ class App extends Component {
110161
return h(Router, {},
111162
h(Home, { path: '/' }),
112163
h(Sketch, { path: '/sketch' }),
164+
h(Sketch, { path: '/sketch/:id' }),
113165
h(NotFound, { type: '404', default: true })
114166
);
115167
}

0 commit comments

Comments
 (0)