Procházet zdrojové kódy

[https://github.com/tracim/tracim/issues/644] added autogenerated avatar when missing

Skylsmoi před 5 roky
rodič
revize
2af4b70d4d

+ 4 - 1
frontend/src/reducer/user.js Zobrazit soubor

6
   USER_DATA,
6
   USER_DATA,
7
   USER_LANG
7
   USER_LANG
8
 } from '../action-creator.sync.js'
8
 } from '../action-creator.sync.js'
9
+import { generateAvatarFromPublicName } from 'tracim_frontend_lib'
9
 
10
 
10
 const defaultUser = {
11
 const defaultUser = {
11
   user_id: -1,
12
   user_id: -1,
31
       return {
32
       return {
32
         ...state,
33
         ...state,
33
         ...action.user,
34
         ...action.user,
34
-        avatar_url: 'https://www.algoo.fr/static/images/people_images/PERSO_SEUL.png' // @FIXME use avatar from api when db handles it
35
+        avatar_url: action.user.avatar_url
36
+          ? action.user.avatar_url
37
+          : generateAvatarFromPublicName(action.user.public_name)
35
       }
38
       }
36
 
39
 
37
     case `${SET}/${USER_DISCONNECTED}`:
40
     case `${SET}/${USER_DISCONNECTED}`:

+ 12 - 2
frontend_app_html-document/src/container/HtmlDocument.jsx Zobrazit soubor

5
 import {
5
 import {
6
   addAllResourceI18n,
6
   addAllResourceI18n,
7
   handleFetchResult,
7
   handleFetchResult,
8
+  generateAvatarFromPublicName,
8
   PopinFixed,
9
   PopinFixed,
9
   PopinFixedHeader,
10
   PopinFixedHeader,
10
   PopinFixedOption,
11
   PopinFixedOption,
119
       handleFetchResult(await fetchResultRevision)
120
       handleFetchResult(await fetchResultRevision)
120
     ])
121
     ])
121
       .then(([resComment, resRevision]) => {
122
       .then(([resComment, resRevision]) => {
122
-        const resCommentWithProperDate = resComment.body.map(c => ({...c, created: (new Date(c.created)).toLocaleString()}))
123
+        const resCommentWithProperDateAndAvatar = resComment.body.map(c => ({
124
+          ...c,
125
+          created: (new Date(c.created)).toLocaleString(),
126
+          author: {
127
+            ...c.author,
128
+            avatar_url: c.author.avatar_url
129
+              ? c.author.avatar_url
130
+              : generateAvatarFromPublicName(c.author.public_name)
131
+          }
132
+        }))
123
 
133
 
124
         const revisionWithComment = resRevision.body
134
         const revisionWithComment = resRevision.body
125
           .map((r, i) => ({
135
           .map((r, i) => ({
128
             timelineType: 'revision',
138
             timelineType: 'revision',
129
             commentList: r.comment_ids.map(ci => ({
139
             commentList: r.comment_ids.map(ci => ({
130
               timelineType: 'comment',
140
               timelineType: 'comment',
131
-              ...resCommentWithProperDate.find(c => c.content_id === ci)
141
+              ...resCommentWithProperDateAndAvatar.find(c => c.content_id === ci)
132
             })),
142
             })),
133
             number: i + 1
143
             number: i + 1
134
           }))
144
           }))

+ 0 - 3
frontend_app_html-document/src/css/index.styl Zobrazit soubor

37
     &__messagelist
37
     &__messagelist
38
       min-height 70px
38
       min-height 70px
39
       &__item
39
       &__item
40
-        &__avatar
41
-          border 1px solid darkHtmlColor
42
-          background-color off-white
43
         &__content
40
         &__content
44
           color darkGrey
41
           color darkGrey
45
       &__version
42
       &__version

+ 8 - 1
frontend_app_thread/src/container/Thread.jsx Zobrazit soubor

4
 import {
4
 import {
5
   addAllResourceI18n,
5
   addAllResourceI18n,
6
   handleFetchResult,
6
   handleFetchResult,
7
+  generateAvatarFromPublicName,
7
   PopinFixed,
8
   PopinFixed,
8
   PopinFixedHeader,
9
   PopinFixedHeader,
9
   PopinFixedOption,
10
   PopinFixedOption,
108
         listMessage: resComment.body.map(c => ({
109
         listMessage: resComment.body.map(c => ({
109
           ...c,
110
           ...c,
110
           timelineType: 'comment',
111
           timelineType: 'comment',
111
-          created: (new Date(c.created)).toLocaleString()
112
+          created: (new Date(c.created)).toLocaleString(),
113
+          author: {
114
+            ...c.author,
115
+            avatar_url: c.author.avatar_url
116
+              ? c.author.avatar_url
117
+              : generateAvatarFromPublicName(c.author.public_name)
118
+          }
112
         }))
119
         }))
113
       }))
120
       }))
114
       .catch(e => console.log('Error loading Thread data.', e))
121
       .catch(e => console.log('Error loading Thread data.', e))

+ 0 - 4
frontend_app_thread/src/css/index.styl Zobrazit soubor

16
     &__contentpage
16
     &__contentpage
17
       &__content
17
       &__content
18
         width 100%
18
         width 100%
19
-      &__messagelist
20
-        &__item__avatar
21
-          border 1px solid darkenThread
22
-          background-color off-white
23
       &__texteditor
19
       &__texteditor
24
         flex 0 0 auto
20
         flex 0 0 auto
25
 
21
 

+ 5 - 5
frontend_lib/dist/index.html Zobrazit soubor

6
   <title>Tracim Lib</title>
6
   <title>Tracim Lib</title>
7
   <link rel='shortcut icon' href='favicon.ico'>
7
   <link rel='shortcut icon' href='favicon.ico'>
8
 
8
 
9
-  <link rel="stylesheet" type="text/css" href="./font/font-awesome-4.7.0/css/font-awesome.css">
9
+  <link rel="stylesheet" type="text/css" href="./asset/font/font-awesome-4.7.0/css/font-awesome.css">
10
   <link href="https://fonts.googleapis.com/css?family=Quicksand:300,400,500,700" rel="stylesheet">
10
   <link href="https://fonts.googleapis.com/css?family=Quicksand:300,400,500,700" rel="stylesheet">
11
-  <link rel="stylesheet" type="text/css" href="./dev/bootstrap-4.0.0-beta.css">
11
+  <link rel="stylesheet" type="text/css" href="./asset/bootstrap/bootstrap-4.0.0-beta.css">
12
 </head>
12
 </head>
13
 <body>
13
 <body>
14
-  <script src="./dev/jquery-3.2.1.js"></script>
15
-  <script src="./dev/popper-1.12.3.js"></script>
16
-  <script src="./dev/bootstrap-4.0.0-beta.2.js"></script>
14
+  <script src="./asset/bootstrap/jquery-3.2.1.js"></script>
15
+  <script src="./asset/bootstrap/popper-1.12.3.js"></script>
16
+  <script src="./asset/bootstrap/bootstrap-4.0.0-beta.2.js"></script>
17
 
17
 
18
   <div id='content'></div>
18
   <div id='content'></div>
19
 
19
 

+ 1 - 1
frontend_lib/package.json Zobrazit soubor

50
     "webpack-dev-server": "^2.9.2"
50
     "webpack-dev-server": "^2.9.2"
51
   },
51
   },
52
   "standard": {
52
   "standard": {
53
-    "globals": [],
53
+    "globals": ["G_vmlCanvasManager"],
54
     "parser": "babel-eslint",
54
     "parser": "babel-eslint",
55
     "ignore": []
55
     "ignore": []
56
   },
56
   },

+ 1 - 1
frontend_lib/src/component/Timeline/Comment.jsx Zobrazit soubor

22
     )}>
22
     )}>
23
       <div className={classnames(`${props.customClass}__messagelist__item__wrapper`, 'timeline__body__messagelist__item__wrapper')}>
23
       <div className={classnames(`${props.customClass}__messagelist__item__wrapper`, 'timeline__body__messagelist__item__wrapper')}>
24
         <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__body__messagelist__item__avatar')}>
24
         <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__body__messagelist__item__avatar')}>
25
-          {props.avatar ? <img src={props.avatar} /> : ''}
25
+          <img src={props.avatar} />
26
         </div>
26
         </div>
27
       </div>
27
       </div>
28
       <div className={classnames(`${props.customClass}__messagelist__item__authorandhour`, 'timeline__body__messagelist__item__authorandhour')}>
28
       <div className={classnames(`${props.customClass}__messagelist__item__authorandhour`, 'timeline__body__messagelist__item__authorandhour')}>

+ 33 - 0
frontend_lib/src/helper.js Zobrazit soubor

1
+import color from 'color'
2
+
1
 export const libHandleFetchResult = async fetchResult => {
3
 export const libHandleFetchResult = async fetchResult => {
2
   switch (fetchResult.status) {
4
   switch (fetchResult.status) {
3
     case 200:
5
     case 200:
28
     )
30
     )
29
   )
31
   )
30
 }
32
 }
33
+
34
+export const libGenerateAvatarFromPublicName = publicName => {
35
+  // code from https://stackoverflow.com/questions/3426404/create-a-hexadecimal-colour-based-on-a-string-with-javascript
36
+  const stringToHashCode = str => str.split('').reduce((acc, char) => char.charCodeAt(0) + ((acc << 5) - acc), 0)
37
+
38
+  const intToRGB = i => {
39
+    const c = (i & 0x00FFFFFF).toString(16).toUpperCase()
40
+    return '00000'.substring(0, 6 - c.length) + c
41
+  }
42
+
43
+  const hexcolor = '#' + intToRGB(stringToHashCode(publicName))
44
+
45
+  let canvas = document.createElement('canvas')
46
+
47
+  // http://code.google.com/p/explorercanvas/wiki/Instructions#Dynamically_created_elements
48
+  if (!canvas.getContext) G_vmlCanvasManager.initElement(canvas)
49
+
50
+  let ctx = canvas.getContext('2d')
51
+  canvas.width = 44
52
+  canvas.height = 44
53
+
54
+  const { r, g, b } = color(hexcolor).desaturate(0.75).rgb()
55
+
56
+  ctx.beginPath()
57
+  ctx.arc(22, 22, 20, 0, 2 * Math.PI, false)
58
+  ctx.fillStyle = 'rgba(' + [r, g, b, 1].join() + ')'
59
+  ctx.fill()
60
+  ctx.stroke()
61
+
62
+  return canvas.toDataURL('image/png', '')
63
+}

+ 13 - 1
frontend_lib/src/index.dev.js Zobrazit soubor

18
 import CardPopup from './component/CardPopup/CardPopup.jsx'
18
 import CardPopup from './component/CardPopup/CardPopup.jsx'
19
 import CardPopupCreateContent from './component/CardPopup/CardPopupCreateContent.jsx'
19
 import CardPopupCreateContent from './component/CardPopup/CardPopupCreateContent.jsx'
20
 
20
 
21
+import { libGenerateAvatarFromPublicName } from './helper.js'
21
 
22
 
22
 import NewVersionButton from './component/OptionComponent/NewVersionBtn.jsx'
23
 import NewVersionButton from './component/OptionComponent/NewVersionBtn.jsx'
23
 import ArchiveDeleteContent from './component/OptionComponent/ArchiveDeleteContent.jsx'
24
 import ArchiveDeleteContent from './component/OptionComponent/ArchiveDeleteContent.jsx'
98
             email: 'osef@algoo.fr',
99
             email: 'osef@algoo.fr',
99
             avatar_url: 'https://avatars3.githubusercontent.com/u/11177014?s=460&v=4'
100
             avatar_url: 'https://avatars3.githubusercontent.com/u/11177014?s=460&v=4'
100
           }}
101
           }}
101
-          timelineData={TimelineDebugData}
102
+          timelineData={TimelineDebugData.map(item => item.timelineType === 'comment'
103
+            ? {
104
+              ...item,
105
+              author: {
106
+                ...item.author,
107
+                avatar_url: item.author.avatar_url
108
+                  ? item.author.avatar_url
109
+                  : libGenerateAvatarFromPublicName(item.author.public_name)
110
+              }
111
+            }
112
+            : item
113
+          )}
102
           newComment={''}
114
           newComment={''}
103
           disableComment={false}
115
           disableComment={false}
104
           wysiwyg={false}
116
           wysiwyg={false}

+ 3 - 2
frontend_lib/src/index.js Zobrazit soubor

1
 import {
1
 import {
2
   libAddAllResourceI18n,
2
   libAddAllResourceI18n,
3
-  libHandleFetchResult
3
+  libHandleFetchResult,
4
+  libGenerateAvatarFromPublicName
4
 } from './helper.js'
5
 } from './helper.js'
5
 
6
 
6
 import libPopinFixed from './component/PopinFixed/PopinFixed.jsx'
7
 import libPopinFixed from './component/PopinFixed/PopinFixed.jsx'
28
 import libSelectStatus from './component/Input/SelectStatus/SelectStatus.jsx'
29
 import libSelectStatus from './component/Input/SelectStatus/SelectStatus.jsx'
29
 
30
 
30
 export const addAllResourceI18n = libAddAllResourceI18n
31
 export const addAllResourceI18n = libAddAllResourceI18n
31
-
32
 export const handleFetchResult = libHandleFetchResult
32
 export const handleFetchResult = libHandleFetchResult
33
+export const generateAvatarFromPublicName = libGenerateAvatarFromPublicName
33
 
34
 
34
 export const PopinFixed = libPopinFixed
35
 export const PopinFixed = libPopinFixed
35
 export const PopinFixedHeader = libPopinFixedHeader
36
 export const PopinFixedHeader = libPopinFixedHeader