302 Commits

Author SHA1 Message Date
Bogdan Lyashenko
64a1cb27c2 feat: migrate file code fetching to sockets 2019-01-25 17:15:57 +01:00
Bogdan Lyashenko
c03248de48 feat: migrate download upload 2019-01-24 19:00:56 +01:00
Bogdan Lyashenko
17cb1075cf feat: migrate explorer bar 2019-01-24 18:42:30 +01:00
Bogdan Lyashenko
787560916b feat: migrate subpanel 2019-01-24 18:37:19 +01:00
Bogdan Lyashenko
06828c2d8b feat: migrate sidebar to namepsacw logic 2019-01-24 18:22:10 +01:00
Bogdan Lyashenko
baf6fbbb2b feat: show flowselect for single project only 2019-01-22 20:27:15 +01:00
Bogdan Lyashenko
5b26f6b203 feat: finish migrating view switches to nampespaces 2019-01-22 20:11:48 +01:00
Bogdan Lyashenko
423eb1ed7b feat: finish migrating tree diagram components 2019-01-21 20:02:08 +01:00
Bogdan Lyashenko
0142f55f09 Merge branch 'master' into multy-server 2019-01-21 19:14:59 +01:00
Bohdan Liashenko
8fd467b1d0 Merge pull request #11 from andrewmherren/line_endings
fix(#3): support consecutive codecrumbs
2019-01-21 19:09:14 +01:00
Bogdan Lyashenko
198632f94f feat: fix multy server for actions 2019-01-21 18:52:49 +01:00
andrewmherren
7c885ae2e6 fix(#3): support consecutive codecrumbs
removed babelTraverse and instead used ast.comments returned by babylon.parse()
2019-01-20 16:38:31 -08:00
Bogdan Lyashenko
36284e507d feat: add support of multiple servers 2019-01-19 19:43:53 +01:00
Bogdan Lyashenko
e6e4969695 Merge branch 'master' into multy-server 2019-01-19 11:26:05 +01:00
Bohdan Liashenko
370a8622c3 Merge pull request #9 from ghsamm/commitlint
feat: enable commitlint setup
2019-01-19 11:22:27 +01:00
Bogdan Lyashenko
93e0346538 Change gitignore props 2019-01-19 10:58:41 +01:00
Bogdan Lyashenko
d657a08d94 first 2019-01-19 10:44:16 +01:00
ghsamm
9eab89a72b feat: configure commitlint for husky 2019-01-19 08:52:25 +01:00
ghsamm
32267b766a install and config commitlint 2019-01-19 08:49:54 +01:00
ghsamm
b80ca1d852 install husky 2019-01-19 08:44:05 +01:00
Bohdan Liashenko
5cb179b055 Update README.md 2019-01-19 08:35:55 +01:00
Bohdan Liashenko
70ebc7b2ce Merge pull request #8 from ghsamm/ignore-dist
gitignore src/public/dist
2019-01-18 21:18:49 +01:00
Bohdan Liashenko
25eb5c845d Update README.md 2019-01-18 20:55:30 +01:00
ghsamm
d3d4e95a19 delete and gitignore src/public/dist 2019-01-18 02:53:23 +01:00
Bohdan Liashenko
357cf192ac Update package.json 2019-01-16 11:19:04 +01:00
Bohdan Liashenko
40aacdd809 Create LICENSE 2019-01-16 11:17:15 +01:00
Bohdan Liashenko
251a894262 Delete LICENSE 2019-01-16 11:16:22 +01:00
Bohdan Liashenko
bec6434f73 Merge pull request #4 from AGCB/master
grammar fixes for documentation
2019-01-16 09:14:38 +01:00
AGCB
b294c09e1a grammar fixes for documentation 2019-01-15 17:04:04 -08:00
Bogdan Lyashenko
62ec4aae1f Fix comment starting from space 2019-01-15 18:56:10 +01:00
Bogdan Lyashenko
8f20d6e43c Update readme 2019-01-14 20:18:27 +01:00
Bogdan Lyashenko
4cc8cc225c Update readme 2019-01-14 20:14:51 +01:00
Bohdan Liashenko
508a60ab2a Update README.md 2019-01-14 14:57:00 +01:00
Bohdan Liashenko
92f1389680 Update README.md 2019-01-14 14:56:02 +01:00
Bohdan Liashenko
5368193ad0 Update README.md 2019-01-14 13:57:28 +01:00
Bogdan Lyashenko
fd7fff3fb6 Layout fixes 2019-01-12 20:43:31 +01:00
Bogdan Lyashenko
b0056b66b8 Fix names in json 2019-01-06 13:21:56 +01:00
Bogdan Lyashenko
a2b9b065d0 Fix cc names 2019-01-06 13:19:17 +01:00
Bogdan Lyashenko
fb414b02d8 Add chunks for tabs in sidebar 2019-01-06 13:02:46 +01:00
Bogdan Lyashenko
946459a104 Fix link 2019-01-06 12:49:13 +01:00
Bogdan Lyashenko
415bd3b091 Add lines to cc 2019-01-06 12:45:54 +01:00
Bogdan Lyashenko
05a3f37a6e Fix standalone file loading 2019-01-05 16:35:40 +01:00
Bogdan Lyashenko
ef6fa75486 Update version 2019-01-05 12:51:02 +01:00
Bogdan Lyashenko
d755218f5f Fix icons resources 2019-01-05 12:17:22 +01:00
Bogdan Lyashenko
f61fbcc44f Fix public path for prod 2019-01-01 19:02:41 +01:00
Bogdan Lyashenko
ded7785170 Fix public path for prod 2019-01-01 18:57:16 +01:00
Bogdan Lyashenko
eb084c8a8c Fix public path for prod 2019-01-01 18:53:32 +01:00
Bogdan Lyashenko
66bcef28c6 Fix public path for prod 2019-01-01 18:48:15 +01:00
Bogdan Lyashenko
bfa0c4d9eb Fix public path for prod 2019-01-01 18:38:48 +01:00
Bogdan Lyashenko
2ed1c99435 Fix public path for prod 2019-01-01 18:26:52 +01:00
Bogdan Lyashenko
3aa171aef8 Fix public path for prod 2019-01-01 18:21:52 +01:00
Bohdan Liashenko
1312ff142c Set theme jekyll-theme-cayman 2018-12-31 17:36:23 +01:00
Bogdan Lyashenko
4d26b88153 Add standalone fixes 2018-12-31 17:34:05 +01:00
Bogdan Lyashenko
4bbc210ef1 Add dynamic loading 2018-12-31 15:14:31 +01:00
Bogdan Lyashenko
6b8e921cc4 Update react 2018-12-31 12:46:32 +01:00
Bogdan Lyashenko
09c663b11c Split webpack configs 2018-12-31 12:41:33 +01:00
Bogdan Lyashenko
8036ffc595 Add setup to app init 2018-12-31 12:06:22 +01:00
Bogdan Lyashenko
446e2e5970 Moving files around 2018-12-30 20:34:15 +01:00
Bogdan Lyashenko
d69598bd56 Moving files around 2018-12-30 20:27:57 +01:00
Bogdan Lyashenko
af18b825fe Add props param to selector 2018-12-30 19:38:36 +01:00
Bogdan Lyashenko
f5ccd6e4b7 Fix storing dep entry name 2018-12-30 19:24:10 +01:00
Bogdan Lyashenko
fd1561de07 Refactor state selectors 2018-12-30 17:01:00 +01:00
Bogdan Lyashenko
1e28ed8f25 Add store upload 2018-12-28 19:59:01 +01:00
Bogdan Lyashenko
f90dae3f96 Remove ast nodes from payload 2018-12-27 20:10:42 +01:00
Bogdan Lyashenko
08098584b3 Refactor actions 2018-12-27 19:46:19 +01:00
Bogdan Lyashenko
efef5f932f Add download setup feature 2018-12-26 20:09:20 +01:00
Bogdan Lyashenko
fe5fa2eecd Update version 2018-12-26 12:34:05 +01:00
Bogdan Lyashenko
c03a5cc434 Fix dep edges 2018-12-26 12:33:20 +01:00
Bogdan Lyashenko
49ee30bcf1 Fix dep edge 2018-12-10 20:49:19 +01:00
Bogdan Lyashenko
1b86bd7912 Add no trail selet 2018-12-08 20:14:38 +01:00
Bogdan Lyashenko
cd89395cf1 Fix cc flow sorting 2018-12-08 19:11:19 +01:00
Bogdan Lyashenko
b129dc5cc6 Refactor trees 2018-12-06 20:26:08 +01:00
Bogdan Lyashenko
58b81e6cf4 Add file code loading on connection select 2018-12-05 20:44:07 +01:00
Bogdan Lyashenko
38ec23f4fa Add file code for files with cc 2018-12-05 19:56:00 +01:00
Bogdan Lyashenko
b767fb4aca Move nodes data usage to filesMap 2018-12-05 19:51:40 +01:00
Bogdan Lyashenko
9c60f4d228 Fix client port 2018-12-04 19:30:43 +01:00
Bogdan Lyashenko
2e9d82bc31 Fix path in cli 2018-12-02 20:13:08 +01:00
Bogdan Lyashenko
413dc91a48 Add cli 2018-12-02 19:56:46 +01:00
Bogdan Lyashenko
184578fcc4 Add npm ignore 2018-12-01 18:11:27 +01:00
Bogdan Lyashenko
405ac1c0bd Add cli placeholder 2018-12-01 18:07:36 +01:00
Bogdan Lyashenko
acd8ddb7bb package json fixes 2018-12-01 12:55:50 +01:00
Bogdan Lyashenko
e8b8a195bc Refactor dependencies to parse file on select 2018-12-01 12:49:52 +01:00
Bogdan Lyashenko
d384ef2d59 Remove file code fetch if sidebar closed 2018-11-26 20:19:01 +01:00
Bogdan Lyashenko
f7a38f55b9 Fix broken dep tab 2018-11-26 19:57:52 +01:00
Bogdan Lyashenko
afae0ea8fb Add file code fetch 2018-11-26 19:51:32 +01:00
Bogdan Lyashenko
dd727b3fac Add api endpoint 2018-11-25 19:10:46 +01:00
Bogdan Lyashenko
2a2067cd0f Enable cc 2018-11-25 17:56:09 +01:00
Bogdan Lyashenko
f533eb0b05 Remove custom static server 2018-11-25 17:46:48 +01:00
Bogdan Lyashenko
36a628e5de Dependencies connections fixes 2018-11-25 16:49:35 +01:00
Bogdan Lyashenko
096bf67079 remove zoom 2018-11-15 17:14:33 +01:00
Bogdan Lyashenko
9254a6d1da Move cc 2018-11-10 14:35:06 +01:00
Bogdan Lyashenko
dfddb2b3af Update readme 2018-11-10 12:46:55 +01:00
Bogdan Lyashenko
fcd385b2b0 Fix rendering of steps 2018-11-08 20:52:59 +01:00
Bogdan Lyashenko
5b2e59ed55 Add cc paths 2018-11-03 14:18:38 +01:00
Bogdan Lyashenko
ee3e5ac150 Move font ssze to constant 2018-11-03 12:43:16 +01:00
Bogdan Lyashenko
e74c33a88b Add zoom 2018-11-03 09:40:19 +01:00
Bogdan Lyashenko
2f28609cd5 Add cover for folder namve 2018-10-28 11:16:18 +01:00
Bogdan Lyashenko
055d97075d Fix font size for Code 2018-10-28 11:08:58 +01:00
Bogdan Lyashenko
ab9cc5aab3 Fix folder index path 2018-10-28 11:06:11 +01:00
Bogdan Lyashenko
0e83ea4dd1 Add cc flow filter 2018-10-28 10:50:46 +01:00
Bogdan Lyashenko
e8e5b06a91 Remove aliases for example proj 2018-10-27 19:58:58 +02:00
Bogdan Lyashenko
9fca36b281 Move example proj dir 2018-10-27 19:41:09 +02:00
Bogdan Lyashenko
0e735102ff Fix smart folders 2018-10-27 18:24:30 +02:00
Bogdan Lyashenko
44fe38a5d9 Fix dep edges layout 2018-10-27 11:41:03 +02:00
Bogdan Lyashenko
80d24021ef Fix dep edges layout 2018-10-27 11:35:51 +02:00
Bogdan Lyashenko
ce2cf6d7a8 Fix cc line 2018-10-27 10:04:22 +02:00
Bogdan Lyashenko
f30aeb1d20 Fix cc 2018-10-25 20:25:27 +02:00
Bogdan Lyashenko
de8720ee60 Remove first level of opened folders 2018-10-25 20:20:19 +02:00
Bogdan Lyashenko
4c1b0b3e1f Clean up test files 2018-10-25 19:53:36 +02:00
Bogdan Lyashenko
545626a94e Add redux example project 2018-10-25 19:48:13 +02:00
Bogdan Lyashenko
b54c72c074 Move out ast config 2018-10-25 19:13:43 +02:00
Bogdan Lyashenko
d0a66c605e Add side bar explorer 2018-10-23 20:42:27 +02:00
Bogdan Lyashenko
44833471da Update readme 2018-10-23 19:23:30 +02:00
Bogdan Lyashenko
8fc0b33189 Update styling fc 2018-10-23 19:12:22 +02:00
Bogdan Lyashenko
35fad3ef5c Add flow chart 2018-10-22 21:44:34 +02:00
Bogdan Lyashenko
fb26280a78 Update git ignore with example project 2018-10-22 20:14:30 +02:00
Bogdan Lyashenko
e115ebc208 Fixes for example project 2018-10-22 20:12:45 +02:00
Bogdan Lyashenko
5ad9c7e4fc Fix tr-catch, folders closing 2018-10-22 19:14:42 +02:00
Bogdan Lyashenko
ae21729bd7 Dep edge fixes 2018-10-21 19:34:09 +02:00
Bogdan Lyashenko
6e750ff63b Dep edge fixes 2018-10-21 19:11:00 +02:00
Bogdan Lyashenko
26f45e7602 Icons fixes 2018-10-21 17:44:40 +02:00
Bogdan Lyashenko
4f87a5c2cd Add constants for opened state 2018-10-21 17:08:50 +02:00
Bogdan Lyashenko
311edd0dce Add smart folders open 2018-10-21 12:33:59 +02:00
Bogdan Lyashenko
7c18fa9002 Update config for AST parser 2018-10-20 18:09:14 +02:00
Bogdan Lyashenko
86ee569794 Improvments 2018-10-17 20:30:49 +02:00
Bogdan Lyashenko
2e71f596c1 Move entry point config to BE 2018-10-17 19:21:54 +02:00
Bogdan Lyashenko
5b367b61c9 Add grab cursor 2018-10-15 20:47:02 +02:00
Bogdan Lyashenko
aebd647d35 Fix file nodes map 2018-10-15 20:40:30 +02:00
Bogdan Lyashenko
cd5c5af94f Add crumbs tab 2018-10-15 20:34:19 +02:00
Bogdan Lyashenko
b897b513b8 Visual fixes 2018-10-15 19:12:33 +02:00
Bogdan Lyashenko
2cb1888f8d Add animations, key fixes 2018-10-14 19:07:36 +02:00
Bogdan Lyashenko
fa4e08c8e2 Add folders close on entry point change 2018-10-14 12:18:04 +02:00
Bogdan Lyashenko
84bc94538f Add folder closing logc 2018-10-14 11:03:15 +02:00
Bogdan Lyashenko
faac196af7 Move to opened foleds 2018-10-14 09:33:24 +02:00
Bogdan Lyashenko
3be0520b60 Add folder closing smart feature 2018-10-13 20:09:04 +02:00
Bogdan Lyashenko
8945082220 Add scroll 2018-10-11 20:39:58 +02:00
Bogdan Lyashenko
ada458bac6 Add sidebar selected tab key 2018-10-10 18:37:53 +02:00
Bogdan Lyashenko
e479093746 Add dep code pane 2018-10-09 17:48:09 +02:00
Bogdan Lyashenko
92adf9c8d5 Refacor code tab 2018-10-07 11:42:32 +02:00
Bogdan Lyashenko
641577665f Change minimize behaviou 2018-10-04 21:05:03 +02:00
Bogdan Lyashenko
e5de0b5f45 Higlight crum line, not next one 2018-10-04 20:48:24 +02:00
Bogdan Lyashenko
43b29fbecc Refactor redux connect 2018-10-04 20:40:49 +02:00
Bogdan Lyashenko
c50eee237c Fix for close all folders 2018-10-03 21:04:32 +02:00
Bogdan Lyashenko
2fa2ed62ba Add files map, clean up unused lists 2018-10-03 21:02:08 +02:00
Bogdan Lyashenko
205f1bef51 Add babel 7 2018-10-02 19:27:54 +02:00
Bogdan Lyashenko
7af202a198 Fix cc flow edges 2018-10-01 20:20:12 +02:00
Bogdan Lyashenko
03b4318c7a Add multi cc in one file 2018-09-30 20:47:19 +02:00
Bogdan Lyashenko
b2a3fe4ce8 Add flow selectors 2018-09-30 12:02:17 +02:00
Bogdan Lyashenko
648a6062a9 Move cc flow edges back under file names 2018-09-30 10:34:02 +02:00
Bogdan Lyashenko
5047a0ddbf Add cc edges 2018-09-29 19:01:04 +02:00
Bogdan Lyashenko
60269f2ada Fix purple for cc 2018-09-29 17:44:29 +02:00
Bogdan Lyashenko
3d0daa6d60 Add path title 2018-09-29 17:31:01 +02:00
Bogdan Lyashenko
063b147448 Add flow connections steps on tree 2018-09-29 14:55:58 +02:00
Bogdan Lyashenko
6094a6c2fd Add cc flow parsing to BE 2018-09-28 20:31:07 +02:00
Bogdan Lyashenko
976a1260b2 Add ui image 2018-09-28 20:02:40 +02:00
Bogdan Lyashenko
09b685ca86 Add show lines control 2018-09-28 19:48:24 +02:00
Bogdan Lyashenko
99a1812b35 Add config persistance to local storage 2018-09-26 20:48:39 +02:00
Bogdan Lyashenko
73861d6a18 Add dep sync 2018-09-26 20:31:07 +02:00
Bogdan Lyashenko
b7e775f854 Fix height for tree diagram containe 2018-09-26 20:15:23 +02:00
Bogdan Lyashenko
9468a589fc Add file watcher 2018-09-26 20:05:18 +02:00
Bogdan Lyashenko
af028923e5 rm yarn lock 2018-09-24 19:26:51 +02:00
Bogdan Lyashenko
9d46b7c195 rm yarn lock 2018-09-24 19:26:18 +02:00
Bogdan Lyashenko
b42975ac30 Test 2018-09-24 19:24:28 +02:00
Bogdan Lyashenko
91ff195ab8 fix 2018-09-24 19:04:03 +02:00
Bogdan Lyashenko
855835af53 fix 2018-09-24 19:02:26 +02:00
Bogdan Lyashenko
0c272532b3 Merge branch 'master' of https://github.com/Bogdan-Lyashenko/codecrumbs 2018-09-24 18:54:27 +02:00
Bogdan Lyashenko
74c823edeb ant update 2018-09-24 18:54:16 +02:00
Bogdan Lyashenko
8e624fdb49 ant update 2018-09-24 18:39:06 +02:00
Bogdan Lyashenko
cb66cdff20 ant update 2018-09-24 18:37:53 +02:00
Bogdan Lyashenko
abcc81649c Merge branch 'master' of https://github.com/Bogdan-Lyashenko/codecrumbs 2018-09-24 18:35:37 +02:00
Bogdan Lyashenko
737ade5c46 ant u[date 2018-09-24 18:29:14 +02:00
Bogdan Lyashenko
0be99d845d ant u[date 2018-09-24 18:29:14 +02:00
Bohdan Liashenko
4298b90a6f Add drag and drop 2018-09-23 13:10:02 +02:00
Bohdan Liashenko
23162bb324 Add drag and drop 2018-09-23 13:10:02 +02:00
Bohdan Liashenko
24d7f83394 Add layout calc 2018-09-23 10:24:27 +02:00
Bohdan Liashenko
c722103b39 Add layout calc 2018-09-23 10:24:27 +02:00
Bohdan Liashenko
ea00b664a3 Add side bar switch 2018-09-22 16:00:44 +02:00
Bohdan Liashenko
12facb0ecd Add side bar switch 2018-09-22 16:00:44 +02:00
Bogdan Lyashenko
6afc119adf Add copy to clipboard icon 2018-09-19 20:50:44 +02:00
Bogdan Lyashenko
88aac37021 Add copy to clipboard icon 2018-09-19 20:50:44 +02:00
Bogdan Lyashenko
b9319e801b Add under layer for unselect 2018-09-19 20:25:27 +02:00
Bogdan Lyashenko
25aa59c067 Add under layer for unselect 2018-09-19 20:25:27 +02:00
Bogdan Lyashenko
6d943da96e Unite icon and text dependency tree click 2018-09-19 20:05:14 +02:00
Bogdan Lyashenko
174525550c Unite icon and text dependency tree click 2018-09-19 20:05:14 +02:00
Bogdan Lyashenko
e37d73c7ac Add select of import on dep edge click 2018-09-18 21:08:42 +02:00
Bogdan Lyashenko
5168520efb Add select of import on dep edge click 2018-09-18 21:08:42 +02:00
Bogdan Lyashenko
5caf77d0c3 Fix code highlighting 2018-09-17 20:23:49 +02:00
Bogdan Lyashenko
15d181a415 Fix code highlighting 2018-09-17 20:23:49 +02:00
Bogdan Lyashenko
81aca317fc Fix selected entry point svg 2018-09-17 19:35:39 +02:00
Bogdan Lyashenko
0b9ac1206d Fix selected entry point svg 2018-09-17 19:35:39 +02:00
Bogdan Lyashenko
c95361d0f0 Add dependencies style fixes 2018-09-16 19:56:39 +02:00
Bogdan Lyashenko
d2a439c04e Add dependencies style fixes 2018-09-16 19:56:39 +02:00
Bogdan Lyashenko
b50417f1a0 Add dependencies style fixes 2018-09-16 19:40:44 +02:00
Bogdan Lyashenko
ae1f934b39 Add dependencies style fixes 2018-09-16 19:40:44 +02:00
Bogdan Lyashenko
df20030b9f Perf fixes for file nodes 2018-09-16 11:26:22 +02:00
Bogdan Lyashenko
091bffcb52 Perf fixes for file nodes 2018-09-16 11:26:22 +02:00
Bogdan Lyashenko
11d81a212e Perf fixes for file nodes 2018-09-16 10:20:44 +02:00
Bogdan Lyashenko
5b5239d18d Perf fixes for file nodes 2018-09-16 10:20:44 +02:00
Bogdan Lyashenko
f48f59d1a7 Add redux dev tools 2018-09-16 09:45:38 +02:00
Bogdan Lyashenko
8f6c48ad0a Add redux dev tools 2018-09-16 09:45:38 +02:00
Bogdan Lyashenko
3921ee099c Rename folders to camel case 2018-09-16 09:29:33 +02:00
Bogdan Lyashenko
8d6ad16498 Rename folders to camel case 2018-09-16 09:29:33 +02:00
Bogdan Lyashenko
0b397ac36a Update react, fix dep switch 2018-09-15 13:31:20 +02:00
Bogdan Lyashenko
d472987c2c Update react, fix dep switch 2018-09-15 13:31:20 +02:00
Bogdan Lyashenko
45b597d9ff Add dep tree edge selection 2018-09-15 13:24:47 +02:00
Bogdan Lyashenko
59cdb70f9e Add dep tree edge selection 2018-09-15 13:24:47 +02:00
Bogdan Lyashenko
09f17d60f8 Add dep edge select 2018-09-13 21:13:33 +02:00
Bogdan Lyashenko
5b45f88281 Add dep edge select 2018-09-13 21:13:33 +02:00
Bogdan Lyashenko
8802b797d1 Add source edge select 2018-09-12 20:30:39 +02:00
Bogdan Lyashenko
b5814cdb1f Add source edge select 2018-09-12 20:30:39 +02:00
Bogdan Lyashenko
f08e1bce8e Add file names for dep tree when source is off 2018-09-11 19:56:18 +02:00
Bogdan Lyashenko
224f2bfd51 Add file names for dep tree when source is off 2018-09-11 19:56:18 +02:00
Bogdan Lyashenko
18b9b8d0e2 Fix icons for code crumb and dep tree 2018-09-11 19:46:22 +02:00
Bogdan Lyashenko
f045304019 Fix icons for code crumb and dep tree 2018-09-11 19:46:22 +02:00
Bogdan Lyashenko
30cc932ef9 Fix dependencies tree bug 2018-09-10 21:15:35 +02:00
Bogdan Lyashenko
a49eab3955 Fix dependencies tree bug 2018-09-10 21:15:35 +02:00
Bogdan Lyashenko
5326bab255 Add scss loader and clean up css 2018-08-28 20:16:44 +02:00
Bogdan Lyashenko
684f9c791c Add scss loader and clean up css 2018-08-28 20:16:44 +02:00
Bogdan Lyashenko
683c53838b Move dim feature to source 2018-08-27 21:04:28 +02:00
Bogdan Lyashenko
e136eb090c Move dim feature to source 2018-08-27 21:04:28 +02:00
Bogdan Lyashenko
133963766a Add dim feature for source 2018-08-27 20:57:52 +02:00
Bogdan Lyashenko
77082119cc Add dim feature for source 2018-08-27 20:57:52 +02:00
Bogdan Lyashenko
31f4a4a37e Fix styles for top container 2018-08-27 20:42:22 +02:00
Bogdan Lyashenko
357a957afd Fix styles for top container 2018-08-27 20:42:22 +02:00
Bogdan Lyashenko
fdc2c8a554 Add dropdown menu 2018-08-27 20:22:01 +02:00
Bogdan Lyashenko
f5c87c1aeb Add dropdown menu 2018-08-27 20:22:01 +02:00
Bogdan Lyashenko
317cf4cb11 Add top bar for path breadcrumbs 2018-08-26 19:07:55 +02:00
Bogdan Lyashenko
0f3e71300f Add top bar for path breadcrumbs 2018-08-26 19:07:55 +02:00
Bogdan Lyashenko
5db767254c Add v shift for mapping dep edges 2018-08-25 19:18:12 +02:00
Bogdan Lyashenko
e5503fcff6 Add v shift for mapping dep edges 2018-08-25 19:18:12 +02:00
Bogdan Lyashenko
0b0e420a5a Refactor dep edges directions 2018-08-25 18:48:04 +02:00
Bogdan Lyashenko
70e24b3d0e Refactor dep edges directions 2018-08-25 18:48:04 +02:00
Bogdan Lyashenko
3b48625597 Dep edges 2018-08-19 19:26:59 +02:00
Bogdan Lyashenko
f499c818da Dep edges 2018-08-19 19:26:59 +02:00
Bogdan Lyashenko
4610f14394 Clean up wepback path 2018-08-18 19:40:13 +02:00
Bogdan Lyashenko
313526207f Clean up wepback path 2018-08-18 19:40:13 +02:00
Bohdan Liashenko
03d1fca234 Merge pull request #1 from Bogdan-Lyashenko/react-svg
React svg
2018-08-18 18:59:11 +02:00
Bohdan Liashenko
3c4acae3bd Merge pull request #1 from Bogdan-Lyashenko/react-svg
React svg
2018-08-18 18:59:11 +02:00
Bogdan Lyashenko
10c38506fa Finish cc tree 2018-08-18 18:35:35 +02:00
Bogdan Lyashenko
0a5e13dc04 Add few moew edges 2018-08-16 19:53:04 +02:00
Bogdan Lyashenko
9672e6b7f0 CC tree 2018-08-16 19:28:13 +02:00
Bogdan Lyashenko
a036070a33 Start moving codecrumbs 2018-08-15 21:00:40 +02:00
Bogdan Lyashenko
02a7dfdde7 Finish dep tree 2018-08-14 19:53:52 +02:00
Bogdan Lyashenko
739756e553 Move dep tree 2018-08-11 21:06:13 +02:00
Bogdan Lyashenko
d633557d30 Migrate source tree 2018-08-11 18:45:01 +02:00
Bogdan Lyashenko
b017014c60 Start refactoring 2018-08-09 19:16:55 +02:00
Bogdan Lyashenko
15a86e4830 Update formatting 2018-08-06 20:54:28 +02:00
Bogdan Lyashenko
86b3cec1e7 Change back test project 2018-08-06 20:24:56 +02:00
Bogdan Lyashenko
e38c6b4916 Layout changes 2018-06-10 16:26:21 +02:00
Bogdan Lyashenko
3acdfa09ae Remove recursion 2018-06-07 21:23:55 +02:00
Bogdan Lyashenko
1f5324a975 Refactoring 2018-06-07 21:12:48 +02:00
Bogdan Lyashenko
10d1ea5983 Fix m statte 2018-06-05 21:31:38 +02:00
Bogdan Lyashenko
a7605b589c Add hidden buttons 2018-06-05 19:56:25 +02:00
Bogdan Lyashenko
e5945e48dd Add show all depencdencies button 2018-06-04 21:24:03 +02:00
Bogdan Lyashenko
313c3b577b Add depencdencies limiter 2018-06-04 20:58:49 +02:00
Bogdan Lyashenko
d2e1866582 Add collapse expand actions 2018-06-03 19:01:31 +02:00
Bogdan Lyashenko
277bcd2759 Add close buttons 2018-06-02 21:10:52 +02:00
Bogdan Lyashenko
3223dcad66 Add sort of folders 2018-06-02 18:28:15 +02:00
Bogdan Lyashenko
cb93fded6c Update icon 2018-06-02 17:46:05 +02:00
Bogdan Lyashenko
2ef0ad78e1 Add sagas, closed folders 2018-06-02 11:48:20 +02:00
Bogdan Lyashenko
a88446478e Add all details check 2018-05-31 21:37:45 +02:00
Bogdan Lyashenko
fdcf280630 Fix popover 2018-05-31 20:02:57 +02:00
Bogdan Lyashenko
617d809569 Refactor tree diagram props 2018-05-31 19:38:06 +02:00
Bogdan Lyashenko
fa317e6518 Add sub switches 2018-05-30 21:53:06 +02:00
Bogdan Lyashenko
97cf0b346e Fix layout 2018-05-30 20:28:04 +02:00
Bogdan Lyashenko
beb34935a2 Add hjs 2018-05-29 22:07:09 +02:00
Bogdan Lyashenko
268687f6c3 Add hjs 2018-05-29 22:04:43 +02:00
Bogdan Lyashenko
12f5742c59 Add pop over 2018-05-27 20:54:04 +02:00
Bogdan Lyashenko
dac52c2b8b Add side bar 2018-05-27 20:37:19 +02:00
Bogdan Lyashenko
7c742dc880 Add shared set util 2018-05-27 18:45:43 +02:00
Bogdan Lyashenko
d66136e7bf Add sets 2018-05-27 15:19:22 +02:00
Bogdan Lyashenko
69fe1fd412 Add should update for cc 2018-05-27 13:19:21 +02:00
Bogdan Lyashenko
a943e4f946 Add names rednering for disabled source 2018-05-26 11:29:21 +02:00
Bogdan Lyashenko
5924cad2db Add data bus component 2018-05-26 11:03:44 +02:00
Bogdan Lyashenko
e12e658b56 Add redux 2018-05-25 22:01:35 +02:00
Bogdan Lyashenko
b8f03fd2ac Improve edge rendering for single nodes 2018-05-24 21:20:46 +02:00
Bogdan Lyashenko
9be8790052 Refactor diagram trees 2018-05-24 20:27:41 +02:00
Bogdan Lyashenko
fb8efe91aa Add loc displaying in codecrumbs 2018-05-22 21:26:58 +02:00
Bogdan Lyashenko
4437d60cf8 Add code crumbs tree 2018-05-21 21:10:01 +02:00
Bogdan Lyashenko
697282f6ef Add dependencies style fixes 2018-05-20 20:07:09 +02:00
Bogdan Lyashenko
5b0c720c4f Add dependencies fraph 2018-05-20 17:29:24 +02:00
Bogdan Lyashenko
a97a132320 Add Dependencies tree switch 2018-05-19 11:50:31 +02:00
Bogdan Lyashenko
2be239d1fe Add opacity fix for text 2018-05-17 21:37:31 +02:00
Bogdan Lyashenko
96ea6c0a92 Add svg layers. Dependencies graph 2018-05-17 21:23:50 +02:00
Bogdan Lyashenko
417b291f1f Fix folder icon size 2018-05-15 21:22:19 +02:00
Bogdan Lyashenko
f66af6c706 Refactired source graph 2018-05-15 21:19:02 +02:00
Bogdan Lyashenko
8b83889659 Align graph 2018-05-14 20:45:33 +02:00
Bogdan Lyashenko
aba076cf36 Add files watch 2018-05-12 20:52:19 +02:00
Bogdan Lyashenko
1838d3c26f Add tralling comment support 2018-05-10 14:20:17 +02:00
Bogdan Lyashenko
37a7901f5d Add webpack dependencies tree 2018-05-10 12:37:49 +02:00
Bogdan Lyashenko
2fef514437 Add switchers 2018-05-08 21:40:26 +02:00
Bogdan Lyashenko
437a32cb2b Refactoring: added dsit for ui, moved statics to fs in server 2018-05-08 20:40:33 +02:00
Bogdan Lyashenko
d66b71d0a1 Add UI lib 2018-05-07 20:39:50 +02:00
Bogdan Lyashenko
63516582cc Add react 2018-05-06 20:52:28 +02:00
Bogdan Lyashenko
cc30bd0a08 Add tree layout builder and svg 2018-05-06 14:12:10 +02:00
Bogdan Lyashenko
50af09ba70 Add codecrumbs parsing 2018-05-03 19:54:01 +02:00
Bogdan Lyashenko
11bcc10137 Remove debugger 2018-05-02 21:07:57 +02:00
Bogdan Lyashenko
dfc54b7b00 Add parsing 2018-05-02 21:05:07 +02:00
Bogdan Lyashenko
58bfbf0703 Add files structure reading 2018-05-01 21:07:11 +02:00
Bogdan Lyashenko
c22fe03bf3 Merge branch 'master' of https://github.com/Bogdan-Lyashenko/codecrumbs 2018-05-01 17:06:33 +02:00
Bogdan Lyashenko
caae675135 First commit 2018-05-01 17:04:23 +02:00
Bohdan Liashenko
bc0eff5c55 Initial commit 2018-05-01 17:00:36 +02:00
245 changed files with 56187 additions and 91576 deletions

9
.gitignore vendored
View File

@@ -1,6 +1,15 @@
# Dependency directory # Dependency directory
node_modules node_modules
# Build directories
src/public/dist/local/bundle/
src/public/dist/standalone/bundle/
# example for dev
# example-project
# Remove some common IDE working directories # Remove some common IDE working directories
.idea .idea
.DS_STORE .DS_STORE
yarn.lock

3
.npmignore Normal file
View File

@@ -0,0 +1,3 @@
.idea
example-project
docs

42
LICENSE
View File

@@ -1,21 +1,29 @@
MIT License BSD 3-Clause License
Copyright (c) 2018 Bohdan Liashenko Copyright (c) 2019, Bohdan Liashenko
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy Redistribution and use in source and binary forms, with or without
of this software and associated documentation files (the "Software"), to deal modification, are permitted provided that the following conditions are met:
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all * Redistributions of source code must retain the above copyright notice, this
copies or substantial portions of the Software. list of conditions and the following disclaimer.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * Redistributions in binary form must reproduce the above copyright notice,
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, this list of conditions and the following disclaimer in the documentation
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE and/or other materials provided with the distribution.
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * Neither the name of the copyright holder nor the names of its
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE contributors may be used to endorse or promote products derived from
SOFTWARE. this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,2 +1,48 @@
# codecrumbs # codecrumbs [active development phase, stay tuned!] [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Leave%20breadcrumbs%20in%20source%20code%20with%20codecrumbs%20tool%20&url=https://github.com/Bogdan-Lyashenko/codecrumbs&via=bliashenko&hashtags=javascript,code)
Leave "breadcrumbs" in source code via comments to find your way out from code maze
[![npm version](https://badge.fury.io/js/codecrumbs.svg)](https://badge.fury.io/js/codecrumbs)
Leave "breadcrumbs" in source code via comments to find your way out from code maze.
> Still much work to do, but the basic features are already implemented and are ready to use. Give it a try while I am finishing a few more big features. Ideas and improvements are welcome. Thanks.
## [Demo](https://codecrumbs.io/)
Check out [**standalone version here**](https://codecrumbs.io/) with defined trail of codecrumbs.
[<img src="/docs/codecrumbs-ui.png" width="800">](https://codecrumbs.io/)
## Get started
Install ```codecrumbs``` globally or in ```devDependencies```:
```yarn add codecrumbs -D```
Add command with **entry file** and **source directory** to ```scripts``` section in your ```package.json```. Change ```-e``` (entry point file), ```-d``` (directory) params to match paths inside your project.
```javascript
// package.json
...
"scripts": {
"start:cc": "codecrumbs -e src/index.js -d src"
}
```
Run ```yarn start:cc``` from the terminal. Go to [http://localhost:2018/#](http://localhost:2018/#) in the browser to check it out.
## Breadcrumbs
> Leave breadcrumbs by simply putting a comment in code, diagram wil be updated on the fly!
Write ```//cc:here is breadcrumb``` to put a simple breadcrumb in the code. ```cc``` (stands for "codecrumb") is the prefix which used by the parser, and ```here is breadcrumb``` is a title of our first breadcrumb.
Also, you can create “trail of breadcrumbs”basically, a sequence of codecrumbs which follow some data flow (e.g. user login, or form submit, etc.).
To create a codecrumb as part of a trail you write: ```//cc:signin#3;enable route``` where ```signin``` is the **trail ID**, ```#3``` is order **number of step**, ```enable route``` is a title describing the step.
<img src="/docs/live-changes.gif" width="800">
Check out [the introduction article here](https://itnext.io/how-to-navigate-the-maze-of-javascript-code-541250447cbb) for more details.
## Learn and share your knowledge
So lets say you put together some trail of codecrumbs describing some important flow inside the project. How you can share it with others? Simply download the json file of codecrumbs store, send it to the friend, he/she uploads it to the codecrumbs and can see same you just saw!
<img src="/docs/share-knowledge.gif" width="800">
## Support
If you like this project and believe it makes sense, please, put a :star: or tweet about it - it will show your support and motivate me :punch:. Thanks!

1
_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

36
cli/index.cli.js Normal file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env node
const program = require('commander');
const colors = require('colors');
const server = require('../src/server');
program
.option('-e, --entry [entryFile]', 'Specify path to entry point file. E.g. `./src/app.js`')
.option('-d, --dir [projectDir]', 'Specify path to project source code directory. E.g. `./src`')
.option(
'-w, --webpack [webpackConfigFile]',
'Specify path to webpack config file. E.g. ./webpack.config.js'
)
.option('-p, --port [defaultPort]', 'Specify port for Codecrumbs client. E.g. 3333', 2018)
.parse(process.argv);
if (!program.entry && !program.dir) {
console.log(
colors.magenta(
'Please specify `entry` and `dir` params. E.g. `codecrumbs -e src/app.js -d src`'
)
);
process.exit();
}
server.setup(
{
projectNameAlias: undefined, // TODO: add param for this
entryPoint: program.entry,
projectDir: program.dir,
webpackConfigPath: program.webpack,
clientPort: program.port
},
false
);

3
commitlint.config.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional']
};

BIN
docs/codecrumbs-ui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

BIN
docs/live-changes.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

BIN
docs/share-knowledge.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@@ -1,3 +0,0 @@
import move from '../zoom/move';
export default () => Promise.resolve({ data: [] });

View File

@@ -1,10 +0,0 @@
import tabs from './views/tabs';
import dataModel from './dataModel/model';
const App = {
init() {
tabs.render(); //cc:render;CallLong line check out tabs.js for more details
}
};
App.init();

View File

@@ -0,0 +1,6 @@
export const INIT_AUTH = 'INIT_AUTH';
export const SIGN_IN_ERROR = 'SIGN_IN_ERROR';
export const SIGN_IN_SUCCESS = 'SIGN_IN_SUCCESS';
export const SIGN_OUT_SUCCESS = 'SIGN_OUT_SUCCESS';

View File

@@ -0,0 +1,72 @@
import firebase from 'firebase';
import { firebaseAuth } from '../firebase';
import {
INIT_AUTH,
SIGN_IN_ERROR,
SIGN_IN_SUCCESS,
SIGN_OUT_SUCCESS
} from './action-types';
function authenticate(provider) {
return dispatch => {
//cc:signin#1;firebase sign in;+2
firebaseAuth.signInWithPopup(provider)
.then(result => dispatch(signInSuccess(result)))
.catch(error => dispatch(signInError(error)));
};
}
export function initAuth(user) {
return {
type: INIT_AUTH,
payload: user
};
}
export function signInError(error) {
return {
type: SIGN_IN_ERROR,
payload: error
};
}
export function signInSuccess(result) {
return {
type: SIGN_IN_SUCCESS,
payload: result.user
};
}
export function signInWithGithub() {
return authenticate(new firebase.auth.GithubAuthProvider());
}
export function signInWithGoogle() {
return authenticate(new firebase.auth.GoogleAuthProvider());
}
export function signInWithTwitter() {
return authenticate(new firebase.auth.TwitterAuthProvider());
}
export function signOut() {
return dispatch => {
firebaseAuth.signOut()
.then(() => dispatch(signOutSuccess()));
};
}
export function signOutSuccess() {
return {
type: SIGN_OUT_SUCCESS
};
}

View File

@@ -0,0 +1,16 @@
import { firebaseAuth } from '../firebase';
import * as authActions from './actions';
export function initAuth(dispatch) {
return new Promise((resolve, reject) => {
const unsubscribe = firebaseAuth.onAuthStateChanged(
authUser => {
dispatch(authActions.initAuth(authUser));
unsubscribe();
resolve();
},
error => reject(error)
);
});
}

View File

@@ -0,0 +1,8 @@
import * as authActions from './actions';
export { authActions };
export * from './action-types';
export { initAuth } from './auth';
export { authReducer } from './reducer';
export { getAuth, isAuthenticated } from './selectors';

View File

@@ -0,0 +1,26 @@
import { Record } from 'immutable';
import { INIT_AUTH, SIGN_IN_SUCCESS, SIGN_OUT_SUCCESS } from './action-types';
export const AuthState = new Record({
authenticated: false,
id: null
});
export function authReducer(state = new AuthState(), {payload, type}) {
switch (type) {
case INIT_AUTH:
case SIGN_IN_SUCCESS:
return state.merge({
authenticated: !!payload, // cc:signin#2;toggle 'authenticated' flag
id: payload ? payload.uid : null
});
case SIGN_OUT_SUCCESS:
return new AuthState();
default:
return state;
}
}

View File

@@ -0,0 +1,16 @@
import { createSelector } from 'reselect';
export function isAuthenticated(state) {
return getAuth(state).authenticated;
}
//=====================================
// MEMOIZED SELECTORS
//-------------------------------------
export const getAuth = createSelector(
state => state.auth,
auth => auth.toJS()
);

View File

@@ -0,0 +1,6 @@
export const firebaseConfig = {
apiKey: 'AIzaSyBsVVpEDrlNPEmshLcmOuE0FxhjPn0AqMg',
authDomain: 'todo-react-redux.firebaseapp.com',
databaseURL: 'https://todo-react-redux.firebaseio.com',
storageBucket: 'firebase-todo-react-redux.appspot.com'
};

View File

@@ -0,0 +1,86 @@
import { firebaseDb } from './firebase';
export class FirebaseList {
constructor(actions, modelClass, path = null) {
this._actions = actions;
this._modelClass = modelClass;
this._path = path;
}
get path() {
return this._path;
}
set path(value) {
this._path = value;
}
push(value) {
return new Promise((resolve, reject) => {
firebaseDb.ref(this._path)
.push(value, error => error ? reject(error) : resolve());
});
}
remove(key) {
return new Promise((resolve, reject) => {
firebaseDb.ref(`${this._path}/${key}`)
.remove(error => error ? reject(error) : resolve());
});
}
set(key, value) {
return new Promise((resolve, reject) => {
firebaseDb.ref(`${this._path}/${key}`)
.set(value, error => error ? reject(error) : resolve());
});
}
update(key, value) {
return new Promise((resolve, reject) => {
firebaseDb.ref(`${this._path}/${key}`)
.update(value, error => error ? reject(error) : resolve());
});
}
subscribe(emit) {
let ref = firebaseDb.ref(this._path);
let initialized = false;
let list = [];
ref.once('value', () => {
initialized = true;
emit(this._actions.onLoad(list));
});
ref.on('child_added', snapshot => {
if (initialized) {
emit(this._actions.onAdd(this.unwrapSnapshot(snapshot)));
}
else {
list.push(this.unwrapSnapshot(snapshot));
}
});
ref.on('child_changed', snapshot => {
emit(this._actions.onChange(this.unwrapSnapshot(snapshot)));
});
ref.on('child_removed', snapshot => {
emit(this._actions.onRemove(this.unwrapSnapshot(snapshot)));
});
this._unsubscribe = () => ref.off();
}
unsubscribe() {
this._unsubscribe();
}
unwrapSnapshot(snapshot) {
let attrs = snapshot.val();
attrs.key = snapshot.key;
return new this._modelClass(attrs);
}
}

View File

@@ -0,0 +1,10 @@
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';
import { firebaseConfig } from './config';
export const firebaseApp = firebase.initializeApp(firebaseConfig);
export const firebaseAuth = firebase.auth();
export const firebaseDb = firebase.database();

View File

@@ -0,0 +1,2 @@
export { firebaseApp, firebaseAuth, firebaseDb } from './firebase';
export { FirebaseList } from './firebase-list';

View File

@@ -0,0 +1,4 @@
import createHistory from 'history/createBrowserHistory';
export default createHistory();

View File

@@ -0,0 +1,44 @@
import './views/styles/styles.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { initAuth } from './auth';
import history from './history';
import configureStore from './store';
import registerServiceWorker from './utils/register-service-worker';
import App from './views/app';
const store = configureStore();
const rootElement = document.getElementById('root');
//cc:layout#0;start;provider
function render(Component) {
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Component/>
</div>
</ConnectedRouter>
</Provider>,
rootElement
);
}
if (module.hot) {
module.hot.accept('./views/app', () => {
render(require('./views/app').default);
})
}
registerServiceWorker();
initAuth(store.dispatch)
.then(() => render(App))
.catch(error => console.error(error));

View File

@@ -0,0 +1 @@
export const DISMISS_NOTIFICATION = 'DISMISS_NOTIFICATION';

View File

@@ -0,0 +1,8 @@
import { DISMISS_NOTIFICATION } from './action-types';
export function dismissNotification() {
return {
type: DISMISS_NOTIFICATION
};
}

View File

@@ -0,0 +1,7 @@
import * as notificationActions from './actions';
export { notificationActions };
export * from './action-types';
export { notificationReducer } from './reducer';
export { getNotification } from './selectors';

View File

@@ -0,0 +1,28 @@
import { Record } from 'immutable';
import { REMOVE_TASK_SUCCESS } from '../tasks';
import { DISMISS_NOTIFICATION } from './action-types';
export const NotificationState = new Record({
actionLabel: '',
display: false,
message: ''
});
export function notificationReducer(state = new NotificationState(), action) {
switch (action.type) {
case REMOVE_TASK_SUCCESS:
return state.merge({
actionLabel: 'Undo',
display: true,
message: 'Task deleted'
});
case DISMISS_NOTIFICATION:
return new NotificationState();
default:
return new NotificationState();
}
}

View File

@@ -0,0 +1,3 @@
export function getNotification(state) {
return state.notification;
}

View File

@@ -0,0 +1,13 @@
import { routerReducer } from 'react-router-redux';
import { combineReducers } from 'redux';
import { authReducer } from './auth';
import { notificationReducer } from './notification';
import { tasksReducer } from './tasks';
export default combineReducers({
auth: authReducer,
notification: notificationReducer,
routing: routerReducer,
tasks: tasksReducer
});

View File

@@ -0,0 +1,27 @@
import { routerMiddleware } from 'react-router-redux';
import { applyMiddleware, compose, createStore } from 'redux';
import thunk from 'redux-thunk';
import history from './history';
import reducers from './reducers';
export default (initialState = {}) => {
let middleware = applyMiddleware(thunk, routerMiddleware(history));
if (process.env.NODE_ENV !== 'production') {
const devToolsExtension = window.devToolsExtension;
if (typeof devToolsExtension === 'function') {
middleware = compose(middleware, devToolsExtension());
}
}
const store = createStore(reducers, initialState, middleware);
if (module.hot) {
module.hot.accept('./reducers', () => {
store.replaceReducer(require('./reducers').default);
});
}
return store;
};

View File

@@ -0,0 +1,14 @@
export const CREATE_TASK_ERROR = 'CREATE_TASK_ERROR';
export const CREATE_TASK_SUCCESS = 'CREATE_TASK_SUCCESS';
export const REMOVE_TASK_ERROR = 'REMOVE_TASK_ERROR';
export const REMOVE_TASK_SUCCESS = 'REMOVE_TASK_SUCCESS';
export const UNDELETE_TASK_ERROR = 'UNDELETE_TASK_ERROR';
export const UPDATE_TASK_ERROR = 'UPDATE_TASK_ERROR';
export const UPDATE_TASK_SUCCESS = 'UPDATE_TASK_SUCCESS';
export const FILTER_TASKS = 'FILTER_TASKS';
export const LOAD_TASKS_SUCCESS = 'LOAD_TASKS_SUCCESS';
export const UNLOAD_TASKS_SUCCESS = 'UNLOAD_TASKS_SUCCESS';

View File

@@ -0,0 +1,124 @@
import { getDeletedTask } from './selectors';
import { taskList } from './task-list';
import {
CREATE_TASK_ERROR,
CREATE_TASK_SUCCESS,
REMOVE_TASK_ERROR,
REMOVE_TASK_SUCCESS,
FILTER_TASKS,
LOAD_TASKS_SUCCESS,
UNDELETE_TASK_ERROR,
UNLOAD_TASKS_SUCCESS,
UPDATE_TASK_ERROR,
UPDATE_TASK_SUCCESS
} from './action-types';
export function createTask(title) {
return dispatch => {
taskList.push({completed: false, title})
.catch(error => dispatch(createTaskError(error)));
};
}
export function createTaskError(error) {
return {
type: CREATE_TASK_ERROR,
payload: error
};
}
export function createTaskSuccess(task) {
return {
type: CREATE_TASK_SUCCESS,
payload: task
};
}
export function removeTask(task) {
return dispatch => {
taskList.remove(task.key)
.catch(error => dispatch(removeTaskError(error)));
};
}
export function removeTaskError(error) {
return {
type: REMOVE_TASK_ERROR,
payload: error
};
}
export function removeTaskSuccess(task) {
return {
type: REMOVE_TASK_SUCCESS,
payload: task
};
}
export function undeleteTask() {
return (dispatch, getState) => {
const task = getDeletedTask(getState());
if (task) {
taskList.set(task.key, {completed: task.completed, title: task.title})
.catch(error => dispatch(undeleteTaskError(error)));
}
};
}
export function undeleteTaskError(error) {
return {
type: UNDELETE_TASK_ERROR,
payload: error
};
}
export function updateTaskError(error) {
return {
type: UPDATE_TASK_ERROR,
payload: error
};
}
export function updateTask(task, changes) {
return dispatch => {
taskList.update(task.key, changes)
.catch(error => dispatch(updateTaskError(error)));
};
}
export function updateTaskSuccess(task) {
return {
type: UPDATE_TASK_SUCCESS,
payload: task
};
}
export function loadTasksSuccess(tasks) {
return {
type: LOAD_TASKS_SUCCESS,
payload: tasks
};
}
export function filterTasks(filterType) {
return {
type: FILTER_TASKS,
payload: {filterType}
};
}
export function loadTasks() {
return (dispatch, getState) => {
const { auth } = getState();
taskList.path = `tasks/${auth.id}`;
taskList.subscribe(dispatch);
};
}
export function unloadTasks() {
taskList.unsubscribe();
return {
type: UNLOAD_TASKS_SUCCESS
};
}

View File

@@ -0,0 +1,8 @@
import * as tasksActions from './actions';
export { tasksActions };
export * from './action-types';
export { tasksReducer } from './reducer';
export { getTaskFilter, getVisibleTasks } from './selectors';
export { Task } from './task';

View File

@@ -0,0 +1,59 @@
import { List, Record } from 'immutable';
import { SIGN_OUT_SUCCESS } from '../auth/action-types';
import {
CREATE_TASK_SUCCESS,
REMOVE_TASK_SUCCESS,
FILTER_TASKS,
LOAD_TASKS_SUCCESS,
UPDATE_TASK_SUCCESS
} from './action-types';
export const TasksState = new Record({
deleted: null,
filter: '',
list: new List(),
previous: null
});
export function tasksReducer(state = new TasksState(), {payload, type}) {
switch (type) {
case CREATE_TASK_SUCCESS:
return state.merge({
deleted: null,
previous: null,
list: state.deleted && state.deleted.key === payload.key ?
state.previous :
state.list.unshift(payload)
});
case REMOVE_TASK_SUCCESS:
return state.merge({
deleted: payload,
previous: state.list,
list: state.list.filter(task => task.key !== payload.key)
});
case FILTER_TASKS:
return state.set('filter', payload.filterType || '');
case LOAD_TASKS_SUCCESS:
return state.set('list', new List(payload.reverse()));
case UPDATE_TASK_SUCCESS:
return state.merge({
deleted: null,
previous: null,
list: state.list.map(task => {
return task.key === payload.key ? payload : task;
})
});
case SIGN_OUT_SUCCESS:
return new TasksState();
default:
return state;
}
}

View File

@@ -0,0 +1,40 @@
import { createSelector } from 'reselect';
export function getTasks(state) {
return state.tasks;
}
export function getTaskList(state) {
return getTasks(state).list;
}
export function getTaskFilter(state) {
return getTasks(state).filter;
}
export function getDeletedTask(state) {
return getTasks(state).deleted;
}
//=====================================
// MEMOIZED SELECTORS
//-------------------------------------
export const getVisibleTasks = createSelector(
getTaskList,
getTaskFilter,
(tasks, filter) => {
switch (filter) {
case 'active':
return tasks.filter(task => !task.completed);
case 'completed':
return tasks.filter(task => task.completed);
default:
return tasks;
}
}
);

View File

@@ -0,0 +1,11 @@
import { FirebaseList } from '../firebase';
import * as taskActions from './actions';
import { Task } from './task';
export const taskList = new FirebaseList({
onAdd: taskActions.createTaskSuccess,
onChange: taskActions.updateTaskSuccess,
onLoad: taskActions.loadTasksSuccess,
onRemove: taskActions.removeTaskSuccess
}, Task);

View File

@@ -0,0 +1,8 @@
import { Record } from 'immutable';
export const Task = new Record({
completed: false,
key: null,
title: null
});

View File

@@ -0,0 +1,10 @@
import React from 'react';
import { findRenderedComponentWithType, renderIntoDocument } from 'react-dom/test-utils';
export function createTestComponent(TestComponent, props) {
return findRenderedComponentWithType(
renderIntoDocument(<TestComponent {...props}/>),
TestComponent
);
}

View File

@@ -0,0 +1,97 @@
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export default function register() {
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) return;
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (!isLocalhost) {
registerValidSW(swUrl);
} else {
checkValidServiceWorker(swUrl);
}
});
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}

View File

@@ -0,0 +1,50 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { authActions, getAuth } from '../../auth';
import Header from '../components/header';
import RequireAuthRoute from '../components/require-auth-route';
import RequireUnauthRoute from '../components/require-unauth-route';
import SignInPage from '../pages/sign-in';
import TasksPage from '../pages/tasks';
//cc:layout#1;describe pages
const App = ({authenticated, signOut}) => (
<div>
<Header
authenticated={authenticated}
signOut={signOut}
/>
<main>
<RequireAuthRoute authenticated={authenticated} exact path="/" component={TasksPage}/>
<RequireUnauthRoute authenticated={authenticated} path="/sign-in" component={SignInPage}/>
</main>
</div>
);
App.propTypes = {
authenticated: PropTypes.bool.isRequired,
signOut: PropTypes.func.isRequired
};
//=====================================
// CONNECT
//-------------------------------------
const mapStateToProps = getAuth;
const mapDispatchToProps = {
signOut: authActions.signOut
};
//cc:here
export default withRouter(
connect(
mapStateToProps,
mapDispatchToProps
)(App)
);

View File

@@ -0,0 +1 @@
export { default } from './app';

View File

@@ -0,0 +1,25 @@
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import './button.css';
const Button = ({children, className, onClick, type = 'button'}) => {
const cssClasses = classNames('btn', className);
return (
<button className={cssClasses} onClick={onClick} type={type}>
{children}
</button>
);
};
Button.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
onClick: PropTypes.func,
type: PropTypes.oneOf(['button', 'reset', 'submit'])
};
export default Button;

View File

@@ -0,0 +1,19 @@
@import 'views/styles/shared';
.btn {
@include button-base;
outline: none;
border: 0;
padding: 0;
overflow: hidden;
transform: translate(0, 0);
background: transparent;
}
.btn--icon {
border-radius: 40px;
padding: 8px;
width: 40px;
height: 40px;
}

View File

@@ -0,0 +1 @@
export { default } from './button';

View File

@@ -0,0 +1,10 @@
import React from 'react';
export default function GitHubLogo() {
return (
<svg viewBox="0 0 20 20">
<path d="M10 0C4.5 0 0 4.5 0 10c0 4.4 2.9 8.2 6.8 9.5.5.1.7-.2.7-.5v-1.9c-2.5.5-3.2-.6-3.4-1.1-.1-.3-.6-1.2-1-1.4-.4-.2-.9-.6 0-.7.8 0 1.3.7 1.5 1 .9 1.5 2.4 1.1 3 .9.1-.6.4-1.1.6-1.3-2.2-.3-4.6-1.2-4.6-5 0-1.1.4-2 1-2.7 0-.3-.4-1.3.2-2.7 0 0 .8-.3 2.8 1 .7-.2 1.6-.3 2.4-.3s1.7.1 2.5.3c1.9-1.3 2.8-1 2.8-1 .5 1.4.2 2.4.1 2.7.6.7 1 1.6 1 2.7 0 3.8-2.3 4.7-4.6 4.9.4.3.7.9.7 1.9v2.8c0 .3.2.6.7.5 4-1.3 6.8-5.1 6.8-9.5C20 4.5 15.5 0 10 0z" />
</svg>
);
}

View File

@@ -0,0 +1 @@
export { default } from './github-logo';

View File

@@ -0,0 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
import Button from '../button';
import GitHubLogo from '../github-logo';
import './header.css';
const Header = ({authenticated, signOut}) => (
<header className="header">
<div className="g-row">
<div className="g-col">
<h1 className="header__title">Todo React Redux</h1>
<ul className="header__actions">
{authenticated ? <li><Button onClick={signOut}>Sign out</Button></li> : null}
<li>
<a className="link link--github" href="https://github.com/r-park/todo-react-redux">
<GitHubLogo />
</a>
</li>
</ul>
</div>
</div>
</header>
);
Header.propTypes = {
authenticated: PropTypes.bool.isRequired,
signOut: PropTypes.func.isRequired
};
export default Header;

View File

@@ -0,0 +1,73 @@
@import 'views/styles/shared';
.header {
padding: 10px 0;
height: 60px;
overflow: hidden;
line-height: 40px;
}
.header__title {
display: flex;
align-items: center;
float: left;
font-size: rem(14px);
font-weight: 400;
line-height: 40px;
text-rendering: auto;
transform: translate(0,0);
&:before {
display: inline-block;
border: 2px solid #eee;
margin-right: 8px;
border-radius: 100%;
height: 16px;
width: 16px;
content: ' ';
}
}
.header__actions {
@include clearfix;
float: right;
padding: 8px 0;
line-height: 24px;
li {
float: left;
list-style: none;
&:last-child {
margin-left: 12px;
padding-left: 12px;
border-left: 1px solid #333;
}
&:first-child {
border: none;
}
}
.btn {
display: block;
margin: 0;
color: #999;
font-size: rem(14px);
line-height: 24px;
}
.link {
display: block;
fill: #98999a;
transform: translate(0, 0);
}
.link--github {
padding-top: 1px;
width: 22px;
height: 24px;
}
}

View File

@@ -0,0 +1 @@
export { default } from './header';

View File

@@ -0,0 +1,17 @@
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
const Icon = ({className, name}) => {
const cssClasses = classNames('material-icons', className);
return <span className={cssClasses}>{name}</span>;
};
Icon.propTypes = {
className: PropTypes.string,
name: PropTypes.string.isRequired
};
export default Icon;

View File

@@ -0,0 +1 @@
export { default } from './icon';

View File

@@ -0,0 +1 @@
export { default } from './notification';

View File

@@ -0,0 +1,58 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './notification.css';
class Notification extends Component {
static propTypes = {
action: PropTypes.func.isRequired,
actionLabel: PropTypes.string.isRequired,
dismiss: PropTypes.func.isRequired,
display: PropTypes.bool.isRequired,
duration: PropTypes.number,
message: PropTypes.string.isRequired
};
componentDidMount() {
this.startTimer();
}
componentWillReceiveProps(nextProps) {
if (nextProps.display) {
this.startTimer();
}
}
componentWillUnmount() {
this.clearTimer();
}
clearTimer() {
if (this.timerId) {
clearTimeout(this.timerId);
}
}
startTimer() {
this.clearTimer();
this.timerId = setTimeout(() => {
this.props.dismiss();
}, this.props.duration || 5000);
}
render() {
return (
<div className="notification">
<p className="notification__message" ref={c => this.message = c}>{this.props.message}</p>
<button
className="btn notification__button"
onClick={this.props.action}
ref={c => this.button = c}
type="button">{this.props.actionLabel}</button>
</div>
);
}
}
export default Notification;

View File

@@ -0,0 +1,27 @@
@import 'views/styles/shared';
.notification {
@include clearfix;
position: fixed;
left: 50%;
top: 60px;
margin-left: -100px;
border: 1px solid #aaa;
padding: 10px 15px;
width: 200px;
font-size: rem(16px);
line-height: 24px;
}
.notification__message {
float: left;
}
.notification__button {
float: right;
font-size: rem(16px);
line-height: 24px;
text-transform: uppercase;
color: #85bf6b;
}

View File

@@ -0,0 +1 @@
export { default } from './require-auth-route';

View File

@@ -0,0 +1,22 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom'
//cc:signin#3;enable route;+6
const RequireAuthRoute = ({component: Component, authenticated, ...rest}) => (
<Route
{...rest}
render={props => {
return authenticated ? (
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/sign-in',
state: {from: props.location}
}}/>
)
}}
/>
);
export default RequireAuthRoute;

View File

@@ -0,0 +1 @@
export { default } from './require-unauth-route';

View File

@@ -0,0 +1,22 @@
import React from 'react';
import { Route, Redirect } from 'react-router-dom'
const RequireUnauthRoute = ({component: Component, authenticated, ...rest}) => (
<Route
{...rest}
render={props => {
return authenticated ? (
<Redirect to={{
pathname: '/',
state: {from: props.location}
}}/>
) : (
<Component {...props}/>
)
}}
/>
);
export default RequireUnauthRoute;

View File

@@ -0,0 +1 @@
export { default } from './task-filters';

View File

@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';
import './task-filters.css';
const TaskFilters = ({filter}) => (
<ul className="task-filters">
<li><NavLink isActive={() => !filter} to="/">View All</NavLink></li>
<li><NavLink isActive={() => filter === 'active'} to={{pathname: '/', search: '?filter=active'}}>Active</NavLink></li>
<li><NavLink isActive={() => filter === 'completed'} to={{pathname: '/', search: '?filter=completed'}}>Completed</NavLink></li>
</ul>
);
TaskFilters.propTypes = {
filter: PropTypes.string
};
export default TaskFilters;

View File

@@ -0,0 +1,38 @@
@import 'views/styles/shared';
.task-filters {
@include clearfix;
margin-bottom: 45px;
padding-left: 1px;
font-size: rem(16px);
line-height: 24px;
list-style-type: none;
@include media-query(540) {
margin-bottom: 55px;
}
li {
float: left;
&:not(:first-child) {
margin-left: 12px;
}
&:not(:first-child):before {
padding-right: 12px;
content: '/';
font-weight: 300;
}
}
a {
color: #999;
text-decoration: none;
&.active {
color: #fff;
}
}
}

View File

@@ -0,0 +1 @@
export { default } from './task-form';

View File

@@ -0,0 +1,62 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './task-form.css';
export class TaskForm extends Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired
};
constructor() {
super(...arguments);
this.state = {title: ''};
this.handleChange = this.handleChange.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
clearInput() {
this.setState({title: ''});
}
handleChange(event) {
this.setState({title: event.target.value});
}
handleKeyUp(event) {
if (event.keyCode === 27) this.clearInput();
}
handleSubmit(event) {
event.preventDefault();
const title = this.state.title.trim();
if (title.length) this.props.handleSubmit(title);
this.clearInput();
}
render() {
return (
<form className="task-form" onSubmit={this.handleSubmit} noValidate>
<input
autoComplete="off"
autoFocus
className="task-form__input"
maxLength="64"
onChange={this.handleChange}
onKeyUp={this.handleKeyUp}
placeholder="What needs to be done?"
ref={e => this.titleInput = e}
type="text"
value={this.state.title}
/>
</form>
);
}
}
export default TaskForm;

View File

@@ -0,0 +1,48 @@
@import 'views/styles/shared';
.task-form {
margin: 40px 0 10px;
@include media-query(540) {
margin: 80px 0 20px;
}
}
.task-form__input {
outline: none;
border: 0;
border-bottom: 1px dotted #666;
border-radius: 0;
padding: 0 0 5px 0;
width: 100%;
height: 50px;
font-family: inherit;
font-size: rem(24px);
font-weight: 300;
color: #fff;
background: transparent;
@include media-query(540) {
height: 61px;
font-size: rem(32px);
}
&::placeholder {
color: #999;
opacity: 1; // firefox native placeholder style has opacity < 1
}
&:focus::placeholder {
color: #777;
opacity: 1;
}
// webkit input doesn't inherit font-smoothing from ancestors
-webkit-font-smoothing: antialiased;
// remove `x`
&::-ms-clear {
display: none;
}
}

View File

@@ -0,0 +1 @@
export { default } from './task-item';

View File

@@ -0,0 +1,137 @@
import React, { Component } from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import Button from '../button';
import Icon from '../icon';
import './task-item.css';
//cc:there is task
export class TaskItem extends Component {
constructor() {
super(...arguments);
this.state = {editing: false};
this.edit = this.edit.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.remove = this.remove.bind(this);
this.save = this.save.bind(this);
this.stopEditing = this.stopEditing.bind(this);
this.toggleStatus = this.toggleStatus.bind(this);
}
edit() {
this.setState({editing: true});
}
handleKeyUp(event) {
if (event.keyCode === 13) {
this.save(event);
}
else if (event.keyCode === 27) {
this.stopEditing();
}
}
remove() {
this.props.removeTask(this.props.task);
}
save(event) {
if (this.state.editing) {
const { task } = this.props;
const title = event.target.value.trim();
if (title.length && title !== task.title) {
this.props.updateTask(task, {title});
}
this.stopEditing();
}
}
stopEditing() {
this.setState({editing: false});
}
toggleStatus() {
const { task } = this.props;
this.props.updateTask(task, {completed: !task.completed});
}
renderTitle(task) {
return (
<div className="task-item__title" tabIndex="0">
{task.title}
</div>
);
}
renderTitleInput(task) {
return (
<input
autoComplete="off"
autoFocus
className="task-item__input"
defaultValue={task.title}
maxLength="64"
onKeyUp={this.handleKeyUp}
type="text"
/>
);
}
render() {
const { editing } = this.state;
const { task } = this.props;
let containerClasses = classNames('task-item', {
'task-item--completed': task.completed,
'task-item--editing': editing
});
return (
<div className={containerClasses} tabIndex="0">
<div className="cell">
<Button
className={classNames('btn--icon', 'task-item__button', {'active': task.completed, 'hide': editing})}
onClick={this.toggleStatus}>
<Icon name="done" />
</Button>
</div>
<div className="cell">
{editing ? this.renderTitleInput(task) : this.renderTitle(task)}
</div>
<div className="cell">
<Button
className={classNames('btn--icon', 'task-item__button', {'hide': editing})}
onClick={this.edit}>
<Icon name="mode_edit" />
</Button>
<Button
className={classNames('btn--icon', 'task-item__button', {'hide': !editing})}
onClick={this.stopEditing}>
<Icon name="clear" />
</Button>
<Button
className={classNames('btn--icon', 'task-item__button', {'hide': editing})}
onClick={this.remove}>
<Icon name="delete" />
</Button>
</div>
</div>
);
}
}
TaskItem.propTypes = {
removeTask: PropTypes.func.isRequired,
task: PropTypes.object.isRequired,
updateTask: PropTypes.func.isRequired
};
export default TaskItem;

View File

@@ -0,0 +1,124 @@
@import 'views/styles/shared';
.task-item {
display: flex;
outline: none;
border-bottom: 1px dotted #666;
height: 60px;
overflow: hidden;
color: #fff;
font-size: rem(18px);
font-weight: 300;
@include media-query(540) {
font-size: rem(24px);
}
}
.task-item--editing {
border-bottom: 1px dotted #ccc;
}
//=====================================
// Cells
//-------------------------------------
.cell {
&:first-child,
&:last-child {
display: flex;
flex: 0 0 auto;
align-items: center;
}
&:first-child {
padding-right: 20px;
}
&:nth-child(2) {
flex: 1;
padding-right: 30px;
overflow: hidden;
}
}
//=====================================
// Buttons
//-------------------------------------
.task-item__button {
margin-left: 5px;
background: #2a2a2a;
&:first-child {
margin: 0;
}
color: #555;
&:hover {
color: #999;
}
&:active {
background: #262626;
}
&.active {
color: #85bf6b;
}
}
//=====================================
// Title (static)
//-------------------------------------
.task-item__title {
display: inline-block;
position: relative;
max-width: 100%;
line-height: 60px;
outline: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:after {
position: absolute;
left: 0;
bottom: 0;
border-top: 2px solid #85bf6b;
width: 0;
height: 46%;
content: '';
}
.task-item--completed & {
color: #666;
}
.task-item--completed &:after {
width: 100%;
}
}
//=====================================
// Title (input)
//-------------------------------------
.task-item__input {
outline: none;
border: 0;
padding: 0;
width: 100%;
height: 60px;
color: inherit;
font: inherit;
background: transparent;
// hide `x`
&::-ms-clear {
display: none;
}
}

View File

@@ -0,0 +1 @@
export { default } from './task-list';

View File

@@ -0,0 +1,32 @@
import React from 'react';
import { List } from 'immutable';
import PropTypes from 'prop-types';
import TaskItem from '../task-item/task-item';
//cc:layout#3;tasks list;
function TaskList({removeTask, tasks, updateTask}) {
let taskItems = tasks.map((task, index) => {
return (
<TaskItem
key={index}
task={task}
removeTask={removeTask}
updateTask={updateTask}
/>
);
});
return (
<div className="task-list">
{taskItems}
</div>
);
}
TaskList.propTypes = {
removeTask: PropTypes.func.isRequired,
tasks: PropTypes.instanceOf(List).isRequired,
updateTask: PropTypes.func.isRequired
};
export default TaskList;

View File

@@ -0,0 +1,6 @@
@import 'views/styles/shared';
.task-list {
border-top: 1px dotted #666;
}

View File

@@ -0,0 +1 @@
export { default } from './sign-in-page';

View File

@@ -0,0 +1,46 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { authActions } from '../../../auth';
import Button from '../../../views/components/button';
import './sign-in-page.css';
const SignInPage = ({signInWithGithub, signInWithGoogle, signInWithTwitter}) => {
return (
<div className="g-row sign-in">
<div className="g-col">
<h1 className="sign-in__heading">Sign in</h1>
<Button className="sign-in__button" onClick={signInWithGithub}>GitHub</Button>
<Button className="sign-in__button" onClick={signInWithGoogle}>Google</Button>
<Button className="sign-in__button" onClick={signInWithTwitter}>Twitter</Button>
</div>
</div>
);
};
SignInPage.propTypes = {
signInWithGithub: PropTypes.func.isRequired,
signInWithGoogle: PropTypes.func.isRequired,
signInWithTwitter: PropTypes.func.isRequired
};
//=====================================
// CONNECT
//-------------------------------------
const mapDispatchToProps = {
signInWithGithub: authActions.signInWithGithub, //cc:signin#0;dispatch action
signInWithGoogle: authActions.signInWithGoogle,
signInWithTwitter: authActions.signInWithTwitter
};
export default withRouter(
connect(
null,
mapDispatchToProps
)(SignInPage)
);

View File

@@ -0,0 +1,30 @@
@import 'views/styles/shared';
.sign-in {
margin-top: 90px;
max-width: 300px;
}
.sign-in__heading {
margin-bottom: 36px;
font-size: 30px;
font-weight: 300;
text-align: center;
}
.sign-in__button {
margin-bottom: 10px;
border: 1px solid #555;
width: 100%;
height: 48px;
font-family: inherit;
font-size: rem(18px);
line-height: 48px;
color: #999;
&:hover {
border: 2px solid #aaa;
line-height: 46px;
}
}

View File

@@ -0,0 +1 @@
export { default } from './tasks-page';

View File

@@ -0,0 +1,115 @@
import React, { Component } from 'react';
import { List } from 'immutable';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { getNotification, notificationActions } from '../../../notification';
import { getTaskFilter, getVisibleTasks, tasksActions } from '../../../tasks';
import Notification from '../../components/notification';
import TaskFilters from '../../components/task-filters';
import TaskForm from '../../components/task-form';
import TaskList from '../../components/task-list';
//cc:layout#2;tasks page
export class TasksPage extends Component {
static propTypes = {
createTask: PropTypes.func.isRequired,
dismissNotification: PropTypes.func.isRequired,
filterTasks: PropTypes.func.isRequired,
filterType: PropTypes.string.isRequired,
loadTasks: PropTypes.func.isRequired,
location: PropTypes.object.isRequired,
notification: PropTypes.object.isRequired,
removeTask: PropTypes.func.isRequired,
tasks: PropTypes.instanceOf(List).isRequired,
undeleteTask: PropTypes.func.isRequired,
unloadTasks: PropTypes.func.isRequired,
updateTask: PropTypes.func.isRequired
};
componentWillMount() {
this.props.loadTasks();
this.props.filterTasks(
this.getFilterParam(this.props.location.search)
);
}
componentWillReceiveProps(nextProps) {
if (nextProps.location.search !== this.props.location.search) {
this.props.filterTasks(
this.getFilterParam(nextProps.location.search)
);
}
}
componentWillUnmount() {
this.props.unloadTasks();
}
getFilterParam(search) {
const params = new URLSearchParams(search);
return params.get('filter');
}
renderNotification() {
const { notification } = this.props;
return (
<Notification
action={this.props.undeleteTask}
actionLabel={notification.actionLabel}
dismiss={this.props.dismissNotification}
display={notification.display}
message={notification.message}
/>
);
}
render() {
return (
<div className="g-row">
<div className="g-col">
<TaskForm handleSubmit={this.props.createTask} />
</div>
<div className="g-col">
<TaskFilters filter={this.props.filterType} />
<TaskList
removeTask={this.props.removeTask}
tasks={this.props.tasks}
updateTask={this.props.updateTask}
/>
</div>
{this.props.notification.display ? this.renderNotification() : null}
</div>
);
}
}
//=====================================
// CONNECT
//-------------------------------------
const mapStateToProps = createSelector(
getNotification,
getTaskFilter,
getVisibleTasks,
(notification, filterType, tasks) => ({
notification,
filterType,
tasks
})
);
const mapDispatchToProps = Object.assign(
{},
tasksActions,
notificationActions
);
export default connect(
mapStateToProps,
mapDispatchToProps
)(TasksPage);

View File

@@ -0,0 +1,8 @@
.g-row {
@include grid-row;
}
.g-col {
@include grid-column;
width: 100%;
}

View File

@@ -0,0 +1,11 @@
$base-background-color: #222 !default;
$base-font-color: #999 !default;
$base-font-family: 'aktiv-grotesk-std', Helvetica Neue, Arial, sans-serif !default;
$base-font-size: 18px !default;
$base-line-height: 24px !default;
//=====================================
// Grid
//-------------------------------------
$grid-max-width: 810px !default;

View File

@@ -0,0 +1,5 @@
@import
'./settings',
'minx/src/settings',
'minx/src/functions',
'minx/src/mixins';

View File

@@ -0,0 +1,27 @@
@import
'./shared',
'minx/src/reset',
'minx/src/elements',
'./grid';
html {
overflow-y: scroll;
}
body {
padding-bottom: 120px;
}
a {
color: inherit;
text-decoration: none;
}
.hide {
display: none !important;
}
::selection {
background: rgba(200,200,255,.1);
}

View File

@@ -1,3 +0,0 @@
/**
* Created by bliashenko on 2018-06-07.
*/

View File

@@ -1,2 +0,0 @@
import stringFormat from '../../utils/string/format/string';
export default 'HOME_PAGE';

View File

@@ -1 +0,0 @@
export default 'PRODUCT_PAGE';

View File

@@ -1,14 +0,0 @@
import HomePage from './home/home-page';
import ProductPage from './product/product-page';
//codecrumb:tabsSwitch;details 1
const tabsSwitch = index => {
console.log(index);
};
export default {
tabsSwitch,//codecrumb:setup call;details 2
render: () => {
return [HomePage, ProductPage];
}
};

View File

@@ -0,0 +1,22 @@
/* global __dirname, require, module*/
const path = require('path');
const outputFile = 'bundle.js';
const config = {
entry: __dirname + '/src/index.js',
output: {
path: __dirname + '/dist',
filename: outputFile
},
module: {
rules: [ ]
},
resolve: {
extensions: ['.js']
},
mode: 'development'
};
module.exports = config;

View File

@@ -1,3 +0,0 @@
/**
* Created by bliashenko on 2018-06-07.
*/

View File

@@ -1,57 +1,86 @@
{ {
"name": "codecrumbs", "name": "codecrumbs",
"version": "1.0.0", "version": "1.0.12-alpha",
"main": "index.js",
"author": "Bohdan Liashenko", "author": "Bohdan Liashenko",
"license": "MIT", "license": "BSD-3-Clause",
"repository": {
"type": "git",
"url": "https://github.com/Bogdan-Lyashenko/codecrumbs.git"
},
"scripts": { "scripts": {
"start": "yarn start:client & yarn start:server", "start": "yarn client-dev & yarn server-dev",
"start:client": "cd src/public && webpack --progress --colors --watch --env dev", "start:demo": "node src/index.dev.js",
"start:server": "nodemon ./src/server/index.js", "client-dev": "cd src/public && webpack --config webpack.dev.js --progress --colors --watch --env dev",
"start:server-debug": "nodemon --inspect ./src/server/index.js", "server-dev": "nodemon src/index.dev.js",
"start:demo": "node ./src/server/index.js", "server-debug": "nodemon --inspect src/index.dev.js",
"build": "cd src/public && webpack --config webpack.prod.js --progress --colors",
"start:standalone": "cd src/public/dist/standalone && http-server",
"pretty": "prettier --write \"./src/public/js/**/*.js\"" "pretty": "prettier --write \"./src/public/js/**/*.js\""
}, },
"bin": {
"codecrumbs": "./cli/index.cli.js"
},
"dependencies": { "dependencies": {
"antd": "^3.5.0", "@babel/parser": "^7.1.2",
"babel-core": "^6.26.3", "@babel/polyfill": "^7.0.0",
"babel-generator": "^6.26.1", "@babel/traverse": "^7.1.0",
"babel-loader": "^7.1.4", "antd": "^3.9.2",
"babel-plugin-import": "^1.7.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-polyfill": "^6.26.0",
"babel-traverse": "^6.26.0",
"babylon": "^6.18.0",
"chokidar": "^2.0.3", "chokidar": "^2.0.3",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"css-loader": "^0.28.11", "colors": "^1.3.2",
"commander": "^2.19.0",
"copy-text-to-clipboard": "^1.0.4",
"d3-flextree": "^2.1.1", "d3-flextree": "^2.1.1",
"directory-tree": "^2.1.0", "directory-tree": "^2.1.0",
"file-saver": "^2.0.0",
"http-server": "^0.11.1",
"js2flowchart": "^1.1.7",
"lodash": "^4.17.10", "lodash": "^4.17.10",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"madge": "^3.0.1", "madge": "^3.3.0",
"mime-types": "^2.1.18", "portscanner": "^2.2.0",
"react": "^16.3.2", "react": "^16.7.0",
"react-dom": "^16.3.2", "react-dom": "^16.7.0",
"react-draggable": "^3.0.5",
"react-redux": "^5.0.7", "react-redux": "^5.0.7",
"react-syntax-highlighter": "^7.0.4", "react-syntax-highlighter": "8.0.1",
"redux": "^4.0.0", "redux": "^4.0.0",
"redux-persist": "^5.10.0",
"redux-saga": "^0.16.0", "redux-saga": "^0.16.0",
"redux-thunk": "^2.2.0", "redux-thunk": "^2.2.0",
"style-loader": "^0.21.0", "reselect": "^4.0.0",
"webpack": "^4.6.0",
"websocket": "^1.0.26" "websocket": "^1.0.26"
}, },
"devDependencies": { "devDependencies": {
"babel-preset-stage-2": "^6.24.1", "@babel/core": "^7.1.2",
"nodemon": "^1.17.3", "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.1.0",
"@babel/preset-react": "^7.0.0",
"@commitlint/cli": "^7.3.2",
"@commitlint/config-conventional": "^7.3.1",
"babel-loader": "^8.0.4",
"babel-plugin-import": "^1.9.1",
"css-loader": "^0.28.11",
"husky": "^1.3.1",
"node-sass": "^4.9.3",
"nodemon": "^1.18.7",
"prettier": "^1.14.0", "prettier": "^1.14.0",
"webpack-cli": "^2.1.2" "sass-loader": "^7.1.0",
"style-loader": "^0.21.0",
"webpack": "^4.20.2",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^3.1.2",
"webpack-merge": "^4.1.5"
}, },
"nodemonConfig": { "nodemonConfig": {
"ignore": [ "ignore": [
"src/public/**/*.*" "src/public/**/*.*"
], ],
"delay": "2500" "delay": "2500"
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
} }
} }

10
src/index.dev.js Normal file
View File

@@ -0,0 +1,10 @@
const server = require('../src/server');
const projectNameAlias = 'react-todo-example';
const projectDir = `example-project/src`;
const entryPoint = `example-project/src/index.js`;
const webpackConfigPath = `example-project/webpack.config.js`;
const clientPort = 2018;
const isDev = true;
server.setup({ projectNameAlias, projectDir, entryPoint, webpackConfigPath, clientPort }, isDev);

82714
src/public/dist/bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Codecrumbs!</title>
</head>
<body>
<div id="mount-node" style="height: 100%"></div>
<script src="bundle.js" type="text/javascript"></script>
</body>
</html>

48908
src/public/dist/local/bundle/main.bundle.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

21
src/public/dist/local/index.html vendored Normal file
View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Codecrumbs: better way to navigate the code maze!</title>
</head>
<body>
<div id="mount-node" style="height: 100%"></div>
<script src="./bundle/main.bundle.js" type="text/javascript"></script>
<script type="text/javascript">
(function(window) {
if (!window.codecrumbs) {
console.error('Codecrumbs project is not loaded!');
return false;
}
window.codecrumbs.default({}, 'mount-node');
})(window)
</script>
</body>
</html>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 233.741 233.741" style="enable-background:new 0 0 233.741 233.741;" xml:space="preserve" width="512px" height="512px">
<path d="M233.486,83.462V54.886c0-10.201-8.299-18.5-18.5-18.5h-85.322c-3.63,0-9.295-2.876-11.437-5.806 l-6.386-8.736C106.859,15.03,96.736,9.892,88.296,9.892H58.731c-9.295,0-18.64,6.608-21.738,15.371l-2.034,5.753 c-0.958,2.711-4.72,5.37-7.595,5.37H18.5c-10.201,0-18.5,8.299-18.5,18.5v41.456c0,0.661,0.095,1.299,0.255,1.91V201.35 c0,12.407,10.094,22.5,22.5,22.5h188.486c12.406,0,22.5-10.093,22.5-22.5V86.847C233.741,85.696,233.653,84.566,233.486,83.462z M18.5,51.386h8.864c9.296,0,18.641-6.608,21.737-15.371l2.034-5.752c0.958-2.711,4.721-5.371,7.596-5.371h29.564 c3.63,0,9.295,2.877,11.438,5.806l6.385,8.735c4.982,6.815,15.104,11.954,23.546,11.954h85.322c1.898,0,3.5,1.604,3.5,3.5V65.55 c-2.275-0.776-4.71-1.204-7.245-1.204H22.755c-2.725,0-5.336,0.487-7.755,1.378V54.886C15,52.989,16.603,51.386,18.5,51.386z M211.241,208.85H22.755c-4.136,0-7.5-3.365-7.5-7.5V86.847c0-4.135,3.364-7.5,7.5-7.5h188.486c3.477,0,6.398,2.38,7.245,5.594 v3.915c0,0.661,0.095,1.3,0.255,1.91V201.35C218.741,205.485,215.377,208.85,211.241,208.85z" fill="#ccc"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 233.741 233.741" style="enable-background:new 0 0 233.741 233.741;" xml:space="preserve" width="512px" height="512px">
<path d="M233.486,83.462V54.886c0-10.201-8.299-18.5-18.5-18.5h-85.322c-3.63,0-9.295-2.876-11.437-5.806 l-6.386-8.736C106.859,15.03,96.736,9.892,88.296,9.892H58.731c-9.295,0-18.64,6.608-21.738,15.371l-2.034,5.753 c-0.958,2.711-4.72,5.37-7.595,5.37H18.5c-10.201,0-18.5,8.299-18.5,18.5v41.456c0,0.661,0.095,1.299,0.255,1.91V201.35 c0,12.407,10.094,22.5,22.5,22.5h188.486c12.406,0,22.5-10.093,22.5-22.5V86.847C233.741,85.696,233.653,84.566,233.486,83.462z M18.5,51.386h8.864c9.296,0,18.641-6.608,21.737-15.371l2.034-5.752c0.958-2.711,4.721-5.371,7.596-5.371h29.564 c3.63,0,9.295,2.877,11.438,5.806l6.385,8.735c4.982,6.815,15.104,11.954,23.546,11.954h85.322c1.898,0,3.5,1.604,3.5,3.5V65.55 c-2.275-0.776-4.71-1.204-7.245-1.204H22.755c-2.725,0-5.336,0.487-7.755,1.378V54.886C15,52.989,16.603,51.386,18.5,51.386z M211.241,208.85H22.755c-4.136,0-7.5-3.365-7.5-7.5V86.847c0-4.135,3.364-7.5,7.5-7.5h188.486c3.477,0,6.398,2.38,7.245,5.594 v3.915c0,0.661,0.095,1.3,0.255,1.91V201.35C218.741,205.485,215.377,208.85,211.241,208.85z" fill="#1890ff"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 276.157 276.157" style="enable-background:new 0 0 276.157 276.157;" xml:space="preserve" width="512px" height="512px">
<g>
<rect x="50" width="270" height="270" style="fill:white;" opacity="0.4"/>
</g>
<g>
<path d="M273.081,101.378c-3.3-4.651-8.86-7.319-15.255-7.319h-24.34v-26.47c0-10.201-8.299-18.5-18.5-18.5 h-85.322c-3.63,0-9.295-2.876-11.436-5.806l-6.386-8.735c-4.982-6.814-15.104-11.954-23.546-11.954H58.731 c-9.293,0-18.639,6.608-21.738,15.372l-2.033,5.752c-0.958,2.71-4.721,5.371-7.596,5.371H18.5c-10.201,0-18.5,8.299-18.5,18.5 v167.07c0,0.885,0.161,1.73,0.443,2.519c0.152,3.306,1.18,6.424,3.053,9.064c3.3,4.652,8.86,7.319,15.255,7.319h188.486 c11.395,0,23.27-8.424,27.035-19.179l40.677-116.188C277.061,112.159,276.381,106.03,273.081,101.378z M18.5,64.089h8.864 c9.295,0,18.64-6.608,21.738-15.372l2.032-5.75c0.959-2.711,4.722-5.372,7.597-5.372h29.564c3.63,0,9.295,2.876,11.437,5.806 l6.386,8.734c4.982,6.815,15.104,11.954,23.546,11.954h85.322c1.898,0,3.5,1.603,3.5,3.5v26.47H69.34 c-11.395,0-23.27,8.424-27.035,19.179L15,191.231V67.589C15,65.692,16.603,64.089,18.5,64.089z M260.791,113.238l-40.677,116.188 c-1.674,4.781-7.812,9.135-12.877,9.135H18.751c-1.448,0-2.577-0.373-3.02-0.998c-0.443-0.625-0.423-1.814,0.056-3.181 l40.677-116.188c1.674-4.781,7.812-9.135,12.877-9.135h188.486c1.448,0,2.577,0.373,3.021,0.998 C261.29,110.682,261.27,111.871,260.791,113.238z" fill="#ccc"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 276.157 276.157" style="enable-background:new 0 0 276.157 276.157;" xml:space="preserve" width="512px" height="512px">
<g>
<rect x="50" width="270" height="270" style="fill:white;" opacity="0.4"/>
</g>
<g>
<path d="M273.081,101.378c-3.3-4.651-8.86-7.319-15.255-7.319h-24.34v-26.47c0-10.201-8.299-18.5-18.5-18.5 h-85.322c-3.63,0-9.295-2.876-11.436-5.806l-6.386-8.735c-4.982-6.814-15.104-11.954-23.546-11.954H58.731 c-9.293,0-18.639,6.608-21.738,15.372l-2.033,5.752c-0.958,2.71-4.721,5.371-7.596,5.371H18.5c-10.201,0-18.5,8.299-18.5,18.5 v167.07c0,0.885,0.161,1.73,0.443,2.519c0.152,3.306,1.18,6.424,3.053,9.064c3.3,4.652,8.86,7.319,15.255,7.319h188.486 c11.395,0,23.27-8.424,27.035-19.179l40.677-116.188C277.061,112.159,276.381,106.03,273.081,101.378z M18.5,64.089h8.864 c9.295,0,18.64-6.608,21.738-15.372l2.032-5.75c0.959-2.711,4.722-5.372,7.597-5.372h29.564c3.63,0,9.295,2.876,11.437,5.806 l6.386,8.734c4.982,6.815,15.104,11.954,23.546,11.954h85.322c1.898,0,3.5,1.603,3.5,3.5v26.47H69.34 c-11.395,0-23.27,8.424-27.035,19.179L15,191.231V67.589C15,65.692,16.603,64.089,18.5,64.089z M260.791,113.238l-40.677,116.188 c-1.674,4.781-7.812,9.135-12.877,9.135H18.751c-1.448,0-2.577-0.373-3.02-0.998c-0.443-0.625-0.423-1.814,0.056-3.181 l40.677-116.188c1.674-4.781,7.812-9.135,12.877-9.135h188.486c1.448,0,2.577,0.373,3.021,0.998 C261.29,110.682,261.27,111.871,260.791,113.238z" fill="#1890ff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 550.801 550.801" style="enable-background:#" xml:space="preserve">
<g>
<rect x="50" width="412" height="512" style="fill:white;" opacity="0.7" />
</g>
<g>
<path d="M475.084,131.997c-0.021-2.531-0.833-5.021-2.567-6.992L366.325,3.694c-0.032-0.034-0.063-0.045-0.085-0.076 c-0.633-0.707-1.371-1.295-2.151-1.804c-0.231-0.155-0.464-0.285-0.706-0.422c-0.676-0.366-1.393-0.675-2.131-0.896 c-0.2-0.053-0.38-0.135-0.58-0.188C359.87,0.119,359.037,0,358.193,0H97.2c-11.918,0-21.6,9.693-21.6,21.601v507.6 c0,11.907,9.682,21.601,21.6,21.601h356.4c11.907,0,21.6-9.693,21.6-21.601V133.202C475.2,132.796,475.137,132.398,475.084,131.997 z M204.051,521.143c-6.94,0-16.055-1.182-21.998-3.164l3.375-24.374c4.158,1.393,9.503,2.384,15.448,2.384 c12.68,0,20.596-5.759,20.596-26.557v-83.996h30.122v84.396h0.005C251.599,507.875,233.374,521.143,204.051,521.143z M309.445,520.942c-15.25,0-30.29-3.966-37.823-8.121l6.138-24.965c8.124,4.166,20.606,8.321,33.489,8.321 c13.864,0,21.188-5.731,21.188-14.459c0-8.322-6.338-13.078-22.386-18.816c-22.185-7.73-36.647-20.007-36.647-39.424 c0-22.781,19.014-40.215,50.512-40.215c15.051,0,26.156,3.164,34.077,6.739l-6.719,24.363c-5.357-2.573-14.86-6.339-27.949-6.339 c-13.067,0-19.417,5.959-19.417,12.878c0,8.511,7.541,12.287,24.775,18.815c23.562,8.723,34.667,20.999,34.667,39.814 C363.34,501.926,346.096,520.942,309.445,520.942z M453.601,366.747H97.2V21.601h250.193v110.51c0,5.967,4.841,10.8,10.8,10.8 h95.407V366.747z M357.592,230.798c2.489,5.16,3.597,10.383,3.597,17.062c0,10.465-3.296,18.808-9.987,25.262 c-6.281,6.097-14.392,9.683-25.202,11.201c-4.303,0.591-12.725,0.622-17.218,0c-17.181-2.3-29.893-10.32-38.024-24.021 c-1.041-1.706-1.252-2.268-0.988-2.511c0.427-0.4,20.788-12.145,21.03-12.145c0.11,0,0.886,1.013,1.74,2.247 c6.26,9.255,14.049,13.537,24.474,13.537c6.187,0,11.153-1.685,14.308-4.872c0.943-0.934,1.982-2.326,2.383-3.154 c2.057-4.282,1.15-9.869-2.114-13.374c-2.647-2.837-6.798-5.115-17.951-9.898c-8.189-3.533-12.925-5.806-16.4-7.894 c-13.663-8.269-19.802-18.702-19.802-33.634c0-9.977,3.106-17.84,9.604-24.286c6.322-6.26,14.803-9.898,24.906-10.697 c3.828-0.298,4.366-0.298,8.433,0.026c8.295,0.614,14.581,2.618,20.466,6.528c3.186,2.117,7.815,6.927,10.378,10.779 c1.213,1.819,2.199,3.37,2.199,3.48c0,0.185-19.454,12.762-20.14,13.06c-0.221,0.073-0.833-0.644-1.666-1.957 c-0.723-1.149-2.272-3.045-3.48-4.221c-3.396-3.43-6.739-4.764-11.907-4.764c-4.546-0.032-7.488,1.118-10.025,3.878 c-1.767,1.901-2.567,3.85-2.758,6.74c-0.211,3.639,0.78,6.555,3.101,9.044c2.437,2.592,6.134,4.627,17.149,9.358 c14.576,6.265,21.885,10.597,27.527,16.318C354.175,224.889,355.884,227.259,357.592,230.798z M241.861,154.958h13.112v47.429 c0,31.462-0.108,48.179-0.271,49.673c-1.846,14.792-8.822,24.743-20.73,29.563c-9.924,3.986-23.461,4.313-34.003,0.802 c-9.975-3.322-18.27-10.539-23.058-20.092l-0.804-1.604l10.568-6.423c5.804-3.499,10.647-6.413,10.75-6.468 c0.087-0.032,0.783,1.015,1.556,2.302c4.786,8.189,8.904,11.101,15.783,11.074c4.817-0.026,7.702-0.968,9.954-3.214 c1.603-1.604,2.516-3.341,3.288-6.257l0.588-2.22l0.082-47.297l0.108-47.268H241.861z" fill="#1890ff"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

Some files were not shown because too many files have changed in this diff Show More