Browse code
Update web interface
fiddlerwoaroof authored on 05/04/2017 00:51:11
Showing 3 changed files
Showing 3 changed files
... | ... |
@@ -1,60 +1,91 @@ |
1 | 1 |
<!DOCTYPE html> |
2 | 2 |
<html lang="en"> |
3 |
- <head> |
|
4 |
- <meta charset="UTF-8"> |
|
5 |
- <title></title> |
|
6 |
- <base href="<XXX: YOUR BASE URL HERE>" /> |
|
7 |
- <link rel="stylesheet" href="style.css" /> |
|
8 |
- </head> |
|
9 |
- <body> |
|
10 |
- <div id="container" v-cloak> |
|
11 |
- <div :class="{left: true, collapsed: collapsed}"> |
|
12 |
- <div class="feeds"> |
|
13 |
- <span class="pull-time">{{pull_time}}</span> |
|
14 |
- <!--<div v-for="url in feed_urls">{{url}}</div>--> |
|
15 |
- <div v-for="feed in feeds"> |
|
16 |
- <a class="feed-link" v-on:click="get_feed(feed.path)" v-if="has_items(feed)"> |
|
17 |
- <div class="title">{{feed.title}}</div> |
|
18 |
- <div class="url"> |
|
19 |
- <{{feed.url}}> |
|
20 |
- </div> |
|
21 |
- </a> |
|
22 |
- </div> |
|
23 |
- </div> |
|
3 |
+ <head> |
|
4 |
+ <meta charset="UTF-8"> |
|
5 |
+ <title></title> |
|
6 |
+ <base href="//<URL>/feed_archive/" /> |
|
7 |
+ <link rel="stylesheet" href="style.css" /> |
|
8 |
+ <link rel="stylesheet" href="prism.css" /> |
|
9 |
+ </head> |
|
10 |
+ <body> |
|
11 |
+ <div id="container" v-cloak> |
|
12 |
+ <header :class="{'v-collapse': collapsed}"> |
|
13 |
+ <div :class="{'general-info':true, collapsed: collapsed}"> |
|
14 |
+ <span class="pull-time">{{pull_time}}</span> |
|
15 |
+ </div> |
|
16 |
+ <div class="feed-info"> |
|
17 |
+ <h2>{{current_feed.metadata.title}}</h2> |
|
18 |
+ <h3>{{current_feed.metadata.link}}</h3> |
|
19 |
+ <div class="description">{{current_feed.metadata.description}}</div> |
|
20 |
+ <button @click="toggleCollapse" class="collapse-toggle">(Un)Collapse</button> |
|
21 |
+ </div> |
|
22 |
+ </header> |
|
23 |
+ <div :class="{left: true, collapsed: collapsed}"> |
|
24 |
+ <div class="feeds"> |
|
25 |
+ <!--<div v-for="url in feed_urls">{{url}}</div>--> |
|
26 |
+ <div> |
|
27 |
+ <a :class="{'feed-link': true, 'current': show_likes}" |
|
28 |
+ @click="list_likes()" |
|
29 |
+ > |
|
30 |
+ <div :class="title">Likes</div> |
|
31 |
+ </a> |
|
32 |
+ </div> |
|
24 | 33 |
|
25 |
- <div v-if="current_feed.metadata.title !== null && current_feed.items.length > 0" class="current_feed"> |
|
26 |
- <h2>{{current_feed.metadata.title}}</h2> |
|
27 |
- <h3>{{current_feed.metadata.link}}</h3> |
|
28 |
- <div>{{current_feed.metadata.description}}</div> |
|
29 |
- <ul> |
|
30 |
- <li v-for="item in current_feed.items | orderBy 'path' -1"> |
|
31 |
- <a v-on:click="get_item(item.path)"> |
|
32 |
- <span class="feed_url">{{item.title}}</span> |
|
33 |
- </a> |
|
34 |
- </li> |
|
35 |
- </ul> |
|
36 |
- </div> |
|
37 |
- </div> |
|
38 |
- <div class="right"> |
|
39 |
- <button @click="toggleCollapse" class="collapse-toggle">(Un)Collapse</button> |
|
40 |
- <div v-if="current_item.title !== null" class="article-container"> |
|
41 |
- <h2> |
|
42 |
- <a href="{{current_item.link}}">{{current_item.title}}</a> |
|
43 |
- <button @click="like(current_item, current_feed)"><3</button> |
|
44 |
- </h2> |
|
45 |
- <h3>{{current_item.author}}</h3> |
|
46 |
- <div>{{{ item_content }}}</div> |
|
34 |
+ <div v-for="feed in feeds"> |
|
35 |
+ <a :class="{'feed-link': true, |
|
36 |
+ 'current': (!show_likes) && |
|
37 |
+ current_feed.base_path === feed.path}" |
|
38 |
+ @click="get_feed(feed.path)" v-if="has_items(feed)"> |
|
39 |
+ <div class="title">{{feed.title}}</div> |
|
40 |
+ <div class="url"> |
|
41 |
+ <{{feed.url}}> |
|
42 |
+ </div> |
|
43 |
+ </a> |
|
44 |
+ </div> |
|
45 |
+ </div> |
|
46 |
+ |
|
47 |
+ <div v-if="feed_visible" class="current_feed"> |
|
48 |
+ <ul> |
|
49 |
+ <li v-for="item in current_feed.items | orderBy 'path' -1"> |
|
50 |
+ <a v-on:click="get_item(item.path)"> |
|
51 |
+ <span class="feed_url">{{item.title}}</span> |
|
52 |
+ </a> |
|
53 |
+ </li> |
|
54 |
+ </ul> |
|
55 |
+ </div> |
|
56 |
+ |
|
57 |
+ <div v-if="show_likes" class="current_feed"> |
|
58 |
+ <ul> |
|
59 |
+ <li v-for="item in likes"> |
|
60 |
+ <a href="{{item.item}}"> |
|
61 |
+ <span class="feed_url">{{item.title}}</span> |
|
62 |
+ </a> |
|
63 |
+ </li> |
|
64 |
+ </ul> |
|
65 |
+ </div> |
|
66 |
+ </div> |
|
67 |
+ |
|
68 |
+ <div :class="{'right':true, 'v-expand': collapsed}" > |
|
69 |
+ <h2 v-if="current_item.title !== null" class="article-title"> |
|
70 |
+ <a href="{{current_item.link}}">{{current_item.title}}</a> |
|
71 |
+ <button @click="like(current_item, current_feed)"><3</button> |
|
72 |
+ </h2> |
|
73 |
+ <div v-if="current_item.title !== null" class="article-container"> |
|
74 |
+ <h3>{{current_item.author}}</h3> |
|
75 |
+ <div>{{{ item_content }}}</div> |
|
76 |
+ </div> |
|
77 |
+ </div> |
|
47 | 78 |
</div> |
48 |
- </div> |
|
49 |
- </div> |
|
50 | 79 |
|
51 |
- <script> |
|
52 |
- baseUrl = 'current' |
|
53 |
- </script> |
|
54 |
- <script src="vue.js"></script> |
|
55 |
- <script src="purify.js"></script> |
|
56 |
- <script src="es6-promise.min.js"></script> |
|
57 |
- <script src="fetch.js"></script> |
|
58 |
- <script src="run.js"></script> |
|
59 |
- </body> |
|
80 |
+ <script> |
|
81 |
+ baseUrl = 'current' |
|
82 |
+ </script> |
|
83 |
+ <script src="vue.js"></script> |
|
84 |
+ <script src="purify.js"></script> |
|
85 |
+ <script src="es6-promise.min.js"></script> |
|
86 |
+ <script src="fetch.js"></script> |
|
87 |
+ <script src="prism.js"></script> |
|
88 |
+ <script src="oboe-browser.js"></script> |
|
89 |
+ <script src="run.js"></script> |
|
90 |
+ </body> |
|
60 | 91 |
</html> |
... | ... |
@@ -1,142 +1,171 @@ |
1 | 1 |
root = new Vue({ |
2 | 2 |
el: '#container', |
3 | 3 |
data: { |
4 |
- "pull_time": null, |
|
5 |
- "feed_urls": [], |
|
6 |
- feeds: { |
|
7 |
- feeds: [] |
|
8 |
- }, |
|
9 |
- collapsed: false, |
|
10 |
- |
|
11 |
- current_feed: { |
|
12 |
- metadata: { |
|
13 |
- description: null, |
|
14 |
- fetch_url: null, |
|
15 |
- link: null, |
|
16 |
- title: null, |
|
17 |
- }, |
|
18 |
- base_path: null, |
|
19 |
- items: [], |
|
20 |
- }, |
|
21 |
- |
|
22 |
- current_item: { |
|
23 |
- title: null, |
|
24 |
- date: null, |
|
25 |
- author: null, |
|
26 |
- id: null, |
|
27 |
- link: null, |
|
28 |
- content: null, |
|
29 |
- }, |
|
30 |
- |
|
31 |
- feed_item_counts: {}, |
|
4 |
+ "pull_time": null, |
|
5 |
+ "feed_urls": [], |
|
6 |
+ feeds: { |
|
7 |
+ feeds: [] |
|
8 |
+ }, |
|
9 |
+ collapsed: false, |
|
10 |
+ |
|
11 |
+ current_feed: { |
|
12 |
+ metadata: { |
|
13 |
+ description: null, |
|
14 |
+ fetch_url: null, |
|
15 |
+ link: null, |
|
16 |
+ title: null, |
|
17 |
+ }, |
|
18 |
+ base_path: null, |
|
19 |
+ items: [], |
|
20 |
+ }, |
|
21 |
+ |
|
22 |
+ current_item: { |
|
23 |
+ title: null, |
|
24 |
+ date: null, |
|
25 |
+ author: null, |
|
26 |
+ id: null, |
|
27 |
+ link: null, |
|
28 |
+ content: null, |
|
29 |
+ }, |
|
30 |
+ |
|
31 |
+ feed_item_counts: {}, |
|
32 |
+ |
|
33 |
+ likes: [], |
|
34 |
+ show_likes: true, |
|
32 | 35 |
}, |
33 | 36 |
|
34 | 37 |
computed: { |
35 |
- item_content() { |
|
36 |
- let result = null; |
|
37 |
- if (this.current_item.content !== null) { |
|
38 |
- result = DOMPurify.sanitize(this.current_item.content, { |
|
39 |
- FORBID_TAG: ['style'], |
|
40 |
- FORBID_ATTR: ['style'], |
|
41 |
- }); |
|
42 |
- } |
|
43 |
- return result; |
|
38 |
+ feed_visible() { |
|
39 |
+ return (!this.show_likes) && |
|
40 |
+ this.current_feed.metadata.title !== null && |
|
41 |
+ this.current_feed.items.length > 0; |
|
44 | 42 |
}, |
43 |
+ |
|
44 |
+ item_content() { |
|
45 |
+ let result = null; |
|
46 |
+ if (this.current_item.content !== null) { |
|
47 |
+ result = DOMPurify.sanitize(this.current_item.content, { |
|
48 |
+ FORBID_TAG: ['style'], |
|
49 |
+ FORBID_ATTR: ['style'], |
|
50 |
+ }); |
|
51 |
+ } |
|
52 |
+ return result; |
|
53 |
+ }, |
|
45 | 54 |
}, |
46 | 55 |
|
47 | 56 |
methods: { |
48 |
- toggleCollapse() { |
|
49 |
- this.collapsed = !this.collapsed; |
|
57 |
+ list_likes() { |
|
58 |
+ this.likes = [] |
|
59 |
+ oboe('events.json') |
|
60 |
+ .node('*', (ev) => { |
|
61 |
+ let {event} = ev; |
|
62 |
+ if (event === 'like-item') { |
|
63 |
+ this.likes.push(ev); |
|
64 |
+ } |
|
65 |
+ }); |
|
66 |
+ this.show_likes = !this.show_likes; |
|
50 | 67 |
}, |
51 | 68 |
|
52 |
- sanitize(html) { |
|
53 |
- return DOMPurify.sanitize(html, { |
|
54 |
- FORBID_TAG: ['style'], |
|
55 |
- FORBID_ATTR: ['style'], |
|
56 |
- }); |
|
57 |
- }, |
|
58 |
- |
|
59 |
- get_remote_feed: function (path) { |
|
60 |
- var promise = new Promise((resolve, reject) => { |
|
61 |
- window.fetch(path+'index.json').then((resp) => resp.json()) |
|
62 |
- .then((data) => { |
|
63 |
- var result = Object.assign({}, data); |
|
64 |
- result.fetch_url = data['fetch-url']; |
|
65 |
- result.base_path = path; |
|
66 |
- window.history.pushState({ |
|
67 |
- 'current_feed': result |
|
68 |
- }, "", window.location.pathname); |
|
69 |
- resolve(result); |
|
70 |
- return promise; |
|
71 |
- }, reject.bind(promise)); |
|
72 |
- }); |
|
73 |
- return promise; |
|
69 |
+ toggleCollapse() { |
|
70 |
+ this.collapsed = !this.collapsed; |
|
71 |
+ }, |
|
72 |
+ |
|
73 |
+ sanitize(html) { |
|
74 |
+ return DOMPurify.sanitize(html, { |
|
75 |
+ FORBID_TAG: ['style'], |
|
76 |
+ FORBID_ATTR: ['style'], |
|
77 |
+ }); |
|
78 |
+ }, |
|
79 |
+ |
|
80 |
+ get_remote_feed: function (path) { |
|
81 |
+ var promise = new Promise((resolve, reject) => { |
|
82 |
+ window.fetch(path+'index.json').then((resp) => resp.json()) |
|
83 |
+ .then((data) => { |
|
84 |
+ var result = Object.assign({}, data); |
|
85 |
+ result.fetch_url = data['fetch-url']; |
|
86 |
+ result.base_path = path; |
|
87 |
+ window.history.pushState({ |
|
88 |
+ 'current_feed': result |
|
89 |
+ }, "", window.location.pathname); |
|
90 |
+ resolve(result); |
|
91 |
+ return promise; |
|
92 |
+ }, reject.bind(promise)); |
|
93 |
+ }); |
|
94 |
+ return promise; |
|
95 |
+ }, |
|
96 |
+ |
|
97 |
+ get_feed: function (path) { |
|
98 |
+ this.get_remote_feed(path) |
|
99 |
+ .then((result) => Vue.set(this, 'current_feed', result)) |
|
100 |
+ .then(() => this.show_likes = false); |
|
74 | 101 |
}, |
75 | 102 |
|
76 |
- get_feed: function (path) { |
|
77 |
- this.get_remote_feed(path) |
|
78 |
- .then((result) => |
|
79 |
- Object.assign(root.current_feed, result)); |
|
80 |
- }, |
|
81 |
- |
|
82 |
- like(item, feed) { |
|
83 |
- fetch('<<< LIKE WEBHOOK >>>', { |
|
84 |
- method: 'POST', |
|
85 |
- body: JSON.stringify({ |
|
86 |
- 'event': 'like-item', |
|
87 |
- 'item': item.link, |
|
88 |
- 'title': item.title, |
|
89 |
- 'author': item.author, |
|
90 |
- 'feed-title': feed.metadata.title, |
|
91 |
- 'feed-link': feed.metadata.link, |
|
92 |
- }), |
|
93 |
- }); |
|
94 |
- }, |
|
95 |
- |
|
96 |
- get_item(path) { |
|
97 |
- window.fetch(this.current_feed.base_path + path).then((resp) => resp.json()) |
|
98 |
- .then((data) => { |
|
99 |
- fetch('<<< READ WEBHOOK >>>', { |
|
100 |
- method: 'POST', |
|
101 |
- body: JSON.stringify({ |
|
102 |
- 'event': 'read-item', |
|
103 |
- 'item': data.link, |
|
104 |
- 'title': data.title, |
|
105 |
- 'author': data.author, |
|
106 |
- 'feed-title': this.current_feed.metadata.title, |
|
107 |
- 'feed-link': this.current_feed.metadata.link, |
|
108 |
- }), |
|
109 |
- }); |
|
110 |
- window.history.pushState({ |
|
111 |
- 'current_feed': root.current_feed, |
|
112 |
- 'current_item': data |
|
113 |
- }, "", window.location.pathname); |
|
114 |
- Object.assign(this.current_item, data); |
|
115 |
- }); |
|
116 |
- }, |
|
117 |
- |
|
118 |
- has_items(feed) { |
|
119 |
- var count = this.feed_item_counts[feed.path]; |
|
120 |
- return count === undefined || (count > 0); |
|
121 |
- }, |
|
103 |
+ like(item, feed) { |
|
104 |
+ fetch('https://<URL>/hub/feed_archive', { |
|
105 |
+ method: 'POST', |
|
106 |
+ body: JSON.stringify({ |
|
107 |
+ 'event': 'like-item', |
|
108 |
+ 'item': item.link, |
|
109 |
+ 'title': item.title, |
|
110 |
+ 'author': item.author, |
|
111 |
+ 'feed-title': feed.metadata.title, |
|
112 |
+ 'feed-link': feed.metadata.link, |
|
113 |
+ }), |
|
114 |
+ }); |
|
115 |
+ }, |
|
116 |
+ |
|
117 |
+ get_item(path) { |
|
118 |
+ window.fetch(this.current_feed.base_path + path).then((resp) => resp.json()) |
|
119 |
+ .then((data) => { |
|
120 |
+ fetch('https://<URL>/hub/feed_archive', { |
|
121 |
+ method: 'POST', |
|
122 |
+ body: JSON.stringify({ |
|
123 |
+ 'event': 'read-item', |
|
124 |
+ 'item': data.link, |
|
125 |
+ 'title': data.title, |
|
126 |
+ 'author': data.author, |
|
127 |
+ 'feed-title': this.current_feed.metadata.title, |
|
128 |
+ 'feed-link': this.current_feed.metadata.link, |
|
129 |
+ }), |
|
130 |
+ }); |
|
131 |
+ window.history.pushState({ |
|
132 |
+ 'current_feed': root.current_feed, |
|
133 |
+ 'current_item': data |
|
134 |
+ }, "", window.location.pathname); |
|
135 |
+ Object.assign(this.current_item, data); |
|
136 |
+ }); |
|
137 |
+ }, |
|
138 |
+ |
|
139 |
+ has_items(feed) { |
|
140 |
+ var count = this.feed_item_counts[feed.path]; |
|
141 |
+ return count === undefined || (count > 0); |
|
142 |
+ }, |
|
122 | 143 |
|
123 | 144 |
}, |
124 | 145 |
|
125 | 146 |
ready() { |
126 |
- window.fetch(baseUrl+'/index.json').then((resp) => resp.json()) |
|
127 |
- .then(function (data) { |
|
128 |
- root.pull_time = data['pull-time']; |
|
129 |
- root.feed_urls = data['feed-urls']; |
|
130 |
- root.feeds = data.feeds; |
|
131 |
- return data; |
|
132 |
- }) |
|
133 |
- .then((data) => { |
|
134 |
- root.feeds.forEach((feed) => { |
|
135 |
- // console.log(feed); |
|
136 |
- this.get_remote_feed(feed.path) |
|
137 |
- .then((feed_index) => Vue.set(this.feed_item_counts, feed.path, feed_index.items.length)); |
|
138 |
- }); |
|
147 |
+ oboe('events.json') |
|
148 |
+ .node('*', (ev) => { |
|
149 |
+ let {event} = ev; |
|
150 |
+ if (event === 'like-item') { |
|
151 |
+ this.likes.push(ev); |
|
152 |
+ } |
|
139 | 153 |
}); |
154 |
+ |
|
155 |
+ window.fetch(baseUrl+'/index.json').then((resp) => resp.json()) |
|
156 |
+ .then(function (data) { |
|
157 |
+ root.pull_time = data['pull-time']; |
|
158 |
+ root.feed_urls = data['feed-urls']; |
|
159 |
+ root.feeds = data.feeds; |
|
160 |
+ return data; |
|
161 |
+ }) |
|
162 |
+ .then((data) => { |
|
163 |
+ root.feeds.forEach((feed) => { |
|
164 |
+ // console.log(feed); |
|
165 |
+ this.get_remote_feed(feed.path) |
|
166 |
+ .then((feed_index) => Vue.set(this.feed_item_counts, feed.path, feed_index.items.length)); |
|
167 |
+ }); |
|
168 |
+ }); |
|
140 | 169 |
|
141 | 170 |
}, |
142 | 171 |
|
... | ... |
@@ -149,15 +178,15 @@ window.onpopstate = function (ev) { |
149 | 178 |
Object.assign(root.current_feed, current_feed); |
150 | 179 |
|
151 | 180 |
if (current_item !== undefined) { |
152 |
- Object.assign(root.current_item, current_item); |
|
181 |
+ Object.assign(root.current_item, current_item); |
|
153 | 182 |
} |
154 | 183 |
}; |
155 | 184 |
|
156 | 185 |
document.addEventListener('DOMContentLoaded', function (ev) { |
157 | 186 |
if (window.history.state !== null) { |
158 |
- Object.assign(root.current_feed, window.history.state.current_feed); |
|
159 |
- if (window.history.state.current_item !== undefined) { |
|
160 |
- Object.assign(root.current_item, window.history.state.current_item); |
|
161 |
- } |
|
187 |
+ Object.assign(root.current_feed, window.history.state.current_feed); |
|
188 |
+ if (window.history.state.current_item !== undefined) { |
|
189 |
+ Object.assign(root.current_item, window.history.state.current_item); |
|
190 |
+ } |
|
162 | 191 |
} |
163 | 192 |
}); |
... | ... |
@@ -1,92 +1,217 @@ |
1 | 1 |
* { |
2 | 2 |
box-sizing: border-box; |
3 |
+ transition: font-size 0.2s ease; |
|
3 | 4 |
} |
4 | 5 |
|
5 | 6 |
body { |
6 |
- margin: 0px; |
|
7 |
- font-family: 'Lato', 'Alegreya Sans', sans-serif; |
|
8 |
- background: #002834; |
|
9 |
- color: #cce5dd; |
|
7 |
+ margin: 0px; |
|
8 |
+ font-family: 'Lato', 'Alegreya Sans', sans-serif; |
|
9 |
+ background: #002b36; |
|
10 |
+ color: #fdf6e3; |
|
11 |
+ font-weight: 300; |
|
12 |
+} |
|
13 |
+ |
|
14 |
+.current { |
|
15 |
+ background-color: #073642; |
|
16 |
+ color: #93a1a1; |
|
10 | 17 |
} |
11 | 18 |
|
12 | 19 |
|
13 | 20 |
#container { |
14 |
- opacity: 1; |
|
15 |
- transition: 0.1s ease opacity; |
|
21 |
+ opacity: 1; |
|
22 |
+ transition: 0.1s ease opacity; |
|
16 | 23 |
} |
17 | 24 |
|
18 | 25 |
#container[v-cloak] { |
19 |
- opacity: 0; |
|
26 |
+ opacity: 0; |
|
20 | 27 |
} |
21 | 28 |
|
22 | 29 |
a { |
23 |
- color: #28b0b1; |
|
24 |
- border: thin solid transparent; |
|
30 |
+ color: #28b0b1; |
|
31 |
+ border: thin solid transparent; |
|
25 | 32 |
} |
26 | 33 |
|
27 | 34 |
.current_feed a, .feeds a { |
28 |
- display: inline-block; |
|
29 |
- vertical-align: middle; |
|
30 |
- text-decoration: none; |
|
31 |
- cursor: pointer; |
|
32 |
- margin-right: 1em; |
|
35 |
+ display: inline-block; |
|
36 |
+ vertical-align: middle; |
|
37 |
+ text-decoration: none; |
|
38 |
+ cursor: pointer; |
|
39 |
+ margin-right: 1em; |
|
40 |
+ width: 100%; |
|
33 | 41 |
} |
34 | 42 |
|
35 | 43 |
a:hover { |
36 |
- border-color: #28b0b1; |
|
44 |
+ border-color: #28b0b1; |
|
45 |
+ background-color: #073642; |
|
37 | 46 |
} |
38 | 47 |
|
39 | 48 |
a:focus { |
40 |
- text-decoration: underline; |
|
49 |
+ text-decoration: underline; |
|
50 |
+} |
|
51 |
+ |
|
52 |
+header * { |
|
53 |
+ padding: 0; |
|
54 |
+ margin: 0; |
|
41 | 55 |
} |
42 | 56 |
|
57 |
+#container > .left, |
|
43 | 58 |
#container > .right { |
44 |
- overflow-y: auto; |
|
59 |
+ top: 7em; |
|
60 |
+} |
|
61 |
+ |
|
62 |
+#container > .left.collapsed, |
|
63 |
+#container > .right.v-expand { |
|
64 |
+ top: 3em; |
|
65 |
+} |
|
66 |
+ |
|
67 |
+#container > .right.v-expand .article-title { |
|
68 |
+ font-size: 0.75rem; |
|
69 |
+ |
|
70 |
+} |
|
71 |
+ |
|
72 |
+#container > header { |
|
73 |
+ height: 7em; |
|
74 |
+} |
|
75 |
+ |
|
76 |
+#container > header.v-collapse { |
|
77 |
+ height: 3em; |
|
78 |
+} |
|
79 |
+ |
|
80 |
+#container > header.v-collapse .general-info { |
|
81 |
+ line-height: 3em; |
|
82 |
+} |
|
83 |
+ |
|
84 |
+#container > header { |
|
85 |
+ width: 100vw; |
|
86 |
+ background: #073642; |
|
87 |
+ border-bottom: 4px double #6c71c4; |
|
88 |
+ box-sizing: border-box; |
|
89 |
+ position: absolute; |
|
90 |
+ display: block; |
|
91 |
+ right: 0; |
|
92 |
+ font-size: 16px; |
|
93 |
+ line-height: 1.25; |
|
94 |
+ transition: height 0.2s ease, line-height 0.2s ease; |
|
95 |
+ overflow: hidden; |
|
96 |
+ z-index: 1000; |
|
97 |
+} |
|
98 |
+ |
|
99 |
+#container > header > * { |
|
100 |
+ vertical-align: middle; |
|
101 |
+} |
|
102 |
+ |
|
103 |
+#container > header > .general-info { |
|
104 |
+ width: 24vw; |
|
105 |
+ height: 100%; |
|
106 |
+ line-height: 6rem; |
|
107 |
+ display: block; |
|
108 |
+ float: left; |
|
109 |
+ text-align: right; |
|
110 |
+ padding-right: 1em; |
|
111 |
+ border-right: 3px #28b0b1 double; |
|
112 |
+ transition: width 0.2s ease, padding 0.2s ease; |
|
113 |
+ overflow: hidden; |
|
114 |
+} |
|
115 |
+ |
|
116 |
+.collapsed + .right > .article-container { |
|
117 |
+ width: 38em; |
|
118 |
+} |
|
119 |
+ |
|
120 |
+#container > header > .general-info.collapsed { |
|
121 |
+ padding-right: 0em; |
|
122 |
+} |
|
123 |
+ |
|
124 |
+#container > header > .feed-info { |
|
125 |
+ width: 75vw; |
|
126 |
+ height: 100%; |
|
127 |
+ line-height: 2rem; |
|
128 |
+ display: block; |
|
129 |
+ float: right; |
|
130 |
+} |
|
131 |
+ |
|
132 |
+header h1, header h2, header h3, header h4, header h5, header h6 { |
|
133 |
+ max-height: 1.2em; |
|
134 |
+ width: auto; |
|
135 |
+ border: none; |
|
136 |
+ margin: 0.1em 0; |
|
137 |
+} |
|
138 |
+ |
|
139 |
+#container > header > .general-info.collapsed + .feed-info .description { |
|
140 |
+ display: none; |
|
141 |
+} |
|
142 |
+ |
|
143 |
+#container > header.v-collapse > .feed-info h2, |
|
144 |
+#container > header.v-collapse > .feed-info h3 { |
|
145 |
+ display: inline-block; |
|
146 |
+ font-size: 1rem; |
|
45 | 147 |
} |
46 | 148 |
|
47 | 149 |
#container > .right { |
48 |
- width: 50vw; |
|
49 |
- height: 100vh; |
|
50 |
- box-sizing: border-box; |
|
51 |
- position: absolute; |
|
52 |
- padding: 1em; |
|
53 |
- display: block; |
|
54 |
- right: 0; |
|
55 |
- font-size: 16px; |
|
56 |
- line-height: 1.25; |
|
150 |
+ overflow-y: auto; |
|
151 |
+ width: 50vw; |
|
152 |
+ box-sizing: border-box; |
|
153 |
+ position: absolute; |
|
154 |
+ display: block; |
|
155 |
+ bottom: 0; |
|
156 |
+ right: 0; |
|
157 |
+ font-size: 16px; |
|
158 |
+ line-height: 1.25; |
|
57 | 159 |
} |
58 | 160 |
|
59 | 161 |
h1, h2, h3, h4, h5, h6 { |
60 |
- border-bottom: 3px #28b0b1 double; |
|
162 |
+ border-bottom: 3px #28b0b1 double; |
|
61 | 163 |
} |
62 | 164 |
|
165 |
+ |
|
63 | 166 |
#container > *, #container > .left > * { |
64 |
- transition: width 2s ease; |
|
167 |
+ transition: width 0.2s ease, top 0.2s ease; |
|
65 | 168 |
} |
66 | 169 |
|
67 | 170 |
.article-container { |
68 | 171 |
width: 30em; |
69 | 172 |
margin: auto; |
173 |
+ transition: width 0.2s ease; |
|
174 |
+ letter-spacing: +0.25px; |
|
175 |
+ line-height: 1.5; |
|
176 |
+} |
|
177 |
+ |
|
178 |
+.article-title { |
|
179 |
+ padding: 0.5em 1em; |
|
180 |
+ position: relative; |
|
181 |
+} |
|
182 |
+ |
|
183 |
+.article-title a { |
|
184 |
+ display: block; |
|
185 |
+} |
|
186 |
+ |
|
187 |
+.article-title button { |
|
188 |
+ font-family: 'Source Code Pro', 'Courier New', monospace; |
|
189 |
+ position: absolute; |
|
190 |
+ right: 1em; |
|
191 |
+ bottom: 0.5em; |
|
70 | 192 |
} |
71 | 193 |
|
72 | 194 |
#container > .left { |
73 |
- border-right: 4px #28b0b1 double; |
|
74 |
- box-shadow: 0px 0px 1em #28b0b1; |
|
75 |
- width: 50vw; |
|
76 |
- height: 100vh; |
|
77 |
- overflow: hidden; |
|
78 |
- box-sizing: border-box; |
|
79 |
- position: absolute; |
|
80 |
- display: block; |
|
81 |
- left: 0; |
|
195 |
+ border-right: 4px #28b0b1 double; |
|
196 |
+ width: 50vw; |
|
197 |
+ overflow: hidden; |
|
198 |
+ box-sizing: border-box; |
|
199 |
+ position: absolute; |
|
200 |
+ display: block; |
|
201 |
+ left: 0; |
|
202 |
+ bottom: 0; |
|
82 | 203 |
} |
83 | 204 |
|
205 |
+div.description { |
|
206 |
+ line-height: 1em; |
|
207 |
+ margin-top: 0.5em; |
|
208 |
+} |
|
84 | 209 |
|
85 | 210 |
#container > .right img { |
86 | 211 |
max-width: 95%; |
87 | 212 |
height: auto; |
88 |
- display: block; |
|
89 |
- margin: auto; |
|
213 |
+ display: block; |
|
214 |
+ margin: auto; |
|
90 | 215 |
} |
91 | 216 |
|
92 | 217 |
.current_feed, .feeds { |
... | ... |
@@ -95,18 +220,17 @@ h1, h2, h3, h4, h5, h6 { |
95 | 220 |
} |
96 | 221 |
|
97 | 222 |
.current_feed { |
98 |
- height: 100vh; |
|
223 |
+ height: 100%; |
|
99 | 224 |
width: 25vw; |
100 | 225 |
float: right; |
101 | 226 |
} |
102 | 227 |
|
103 | 228 |
.feeds { |
104 |
- height: 100vh; |
|
229 |
+ height: 100%; |
|
105 | 230 |
width: 24vw; |
106 | 231 |
float: left; |
107 | 232 |
padding: 1em; |
108 |
- border-bottom: 5px #28b0b1 double; |
|
109 |
- box-shadow: 0px 0px 1em #28b0b1; |
|
233 |
+ border-right: 3px #28b0b1 double; |
|
110 | 234 |
} |
111 | 235 |
|
112 | 236 |
.feeds .title, .feeds .url { |
... | ... |
@@ -133,14 +257,15 @@ h1, h2, h3, h4, h5, h6 { |
133 | 257 |
overflow: hidden; |
134 | 258 |
} |
135 | 259 |
|
136 |
-.collapsed + * { |
|
260 |
+.collapsed + .right, .collapsed + .top { |
|
137 | 261 |
width: 100vw !important; |
138 |
- padding-left: 25vw; |
|
139 |
- padding-right: 25vw; |
|
140 | 262 |
} |
141 | 263 |
|
142 | 264 |
.collapse-toggle { |
143 |
- position: fixed; |
|
265 |
+ position: absolute; |
|
266 |
+ right: 1em; |
|
267 |
+ top: 50%; |
|
268 |
+ transform: translateY(-50%); |
|
144 | 269 |
} |
145 | 270 |
|
146 | 271 |
|
... | ... |
@@ -161,3 +286,15 @@ h1, h2, h3, h4, h5, h6 { |
161 | 286 |
padding: 0; |
162 | 287 |
border: none; |
163 | 288 |
} |
289 |
+ |
|
290 |
+.current_feed ul { |
|
291 |
+ padding: 0; |
|
292 |
+ list-style: none; |
|
293 |
+} |
|
294 |
+ |
|
295 |
+.current_feed ul > li { |
|
296 |
+ padding: 0.25em 0.25em; |
|
297 |
+} |
|
298 |
+.current_feed ul a { |
|
299 |
+ padding: 0.1em 0.25em; |
|
300 |
+} |