Scorecard.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import React from 'react'
  21. import { IChartProps } from './'
  22. import { IWidgetMetric } from 'containers/Widget/components/Widget'
  23. import { decodeMetricName, getTextWidth } from 'containers/Widget/components/util'
  24. import { getFormattedValue } from '../Config/Format'
  25. const styles = require('./Chart.less')
  26. export class Scorecard extends React.PureComponent<IChartProps, {}> {
  27. private getMetricText = (metric: IWidgetMetric, visible: boolean) => {
  28. if (!metric || !visible) { return '' }
  29. const { data } = this.props
  30. const { name, agg, format } = metric
  31. const metricName = `${agg}(${decodeMetricName(name)})`
  32. const text = data.length ? getFormattedValue(data[0][metricName], format) : ''
  33. return text
  34. }
  35. private renderMetric = (
  36. text: string,
  37. fontFamily: string, fontSize: number, color: string,
  38. prefix: string, prefixFontFamily: string, prefixFontSize: number, prefixColor: string,
  39. suffix: string, suffixFontFamily: string, suffixFontSize: number, suffixColor: string
  40. ) => {
  41. const style: React.CSSProperties = {
  42. fontFamily,
  43. fontSize,
  44. color
  45. }
  46. const stylePrefix: React.CSSProperties = {
  47. fontFamily: prefixFontFamily,
  48. fontSize: prefixFontSize,
  49. color: prefixColor
  50. }
  51. const styleSuffix: React.CSSProperties = {
  52. fontFamily: suffixFontFamily,
  53. fontSize: suffixFontSize,
  54. color: suffixColor
  55. }
  56. return (
  57. <p
  58. className={styles.scorecardTitle}
  59. >
  60. <span style={stylePrefix}>{prefix}</span>
  61. <span style={style}>{text}</span>
  62. <span style={styleSuffix}>{suffix}</span>
  63. </p>
  64. )
  65. }
  66. private computeFontSize = (
  67. prefixHeader: string, headerText: string, suffixHeader: string,
  68. prefixContent: string, contentText: string, suffixContent: string,
  69. prefixFooter: string, footerText: string, suffixFooter: string): {
  70. titleFontSize: number
  71. contentFontSize: number
  72. } => {
  73. const hasHeader = prefixHeader || headerText || suffixHeader
  74. const hasContent = prefixContent || contentText || suffixContent
  75. const hasFooter = prefixFooter || footerText || suffixFooter
  76. const { width, height } = this.props
  77. const maxPartSize = 16
  78. const exactWidth = width * (width <= 150 ? 1 : (width <= 250 ? 0.9 : 0.7)) - 16 * 2
  79. const sumPartsW = Math.max(
  80. getTextWidth(prefixHeader + headerText + suffixHeader, '', '12px'),
  81. getTextWidth(prefixContent + suffixContent, '', '12px') + getTextWidth(contentText, '', '32px'),
  82. getTextWidth(prefixFooter + footerText + suffixFooter, '', '12px')
  83. )
  84. const exactHeight = height * (height <= 150 ? 1 : (height <= 250 ? 0.9 : 0.7)) - 40
  85. const sumPartsH = (hasHeader ? 3 : 0) + (hasContent ? 8 : 0) + (hasFooter ? 3 : 0)
  86. const gapH = 8
  87. const sumGapH = (hasHeader ? gapH : 0) + (hasContent ? gapH : 0) + (hasFooter ? gapH : 0)
  88. const exactPartSize = Math.min((exactWidth / sumPartsW * 3), ((exactHeight - sumGapH) / sumPartsH), maxPartSize)
  89. return {
  90. titleFontSize: Math.floor(3 * exactPartSize),
  91. contentFontSize: Math.floor(8 * exactPartSize)
  92. }
  93. }
  94. public render () {
  95. const {
  96. metrics,
  97. chartStyles
  98. } = this.props
  99. let metricHeader
  100. let metricContent
  101. let metricFooter
  102. if (metrics.length === 1) {
  103. metricContent = metrics[0]
  104. } else {
  105. [ metricHeader, metricContent, metricFooter ] = metrics
  106. }
  107. const { scorecard } = chartStyles
  108. const {
  109. headerVisible, headerFontFamily, headerColor,
  110. prefixHeader, prefixHeaderFontFamily, prefixHeaderColor,
  111. suffixHeader, suffixHeaderFontFamily, suffixHeaderColor,
  112. contentVisible, contentFontFamily, contentColor,
  113. prefixContent, prefixContentFontFamily, prefixContentColor,
  114. suffixContent, suffixContentFontFamily, suffixContentColor,
  115. footerVisible, footerFontFamily, footerColor,
  116. prefixFooter, prefixFooterFontFamily, prefixFooterColor,
  117. suffixFooter, suffixFooterFontFamily, suffixFooterColor,
  118. fontSizeFixed, fontSizeMain, fontSizeSub
  119. } = scorecard
  120. const headerText = this.getMetricText(metricHeader, headerVisible)
  121. const contentText = this.getMetricText(metricContent, contentVisible)
  122. const footerText = this.getMetricText(metricFooter, footerVisible)
  123. let titleFontSize = +fontSizeSub
  124. let contentFontSize = +fontSizeMain
  125. if (!fontSizeFixed) {
  126. ({ titleFontSize, contentFontSize } = this.computeFontSize(
  127. prefixHeader || '', headerText, suffixHeader || '',
  128. prefixContent || '', contentText, suffixContent || '',
  129. prefixFooter || '', footerText, suffixFooter || ''
  130. ))
  131. }
  132. return (
  133. <div className={styles.scorecard}>
  134. <div className={styles.scorecardContainer}>
  135. {this.renderMetric(headerText,
  136. headerFontFamily, titleFontSize, headerColor, prefixHeader, prefixHeaderFontFamily, titleFontSize, prefixHeaderColor,
  137. suffixHeader, suffixHeaderFontFamily, titleFontSize, suffixHeaderColor)}
  138. {this.renderMetric(contentText,
  139. contentFontFamily, contentFontSize, contentColor, prefixContent, prefixContentFontFamily, titleFontSize, prefixContentColor,
  140. suffixContent, suffixContentFontFamily, titleFontSize, suffixContentColor)}
  141. {this.renderMetric(footerText,
  142. footerFontFamily, titleFontSize, footerColor, prefixFooter, prefixFooterFontFamily, titleFontSize, prefixFooterColor,
  143. suffixFooter, suffixFooterFontFamily, titleFontSize, suffixFooterColor)}
  144. </div>
  145. </div>
  146. )
  147. }
  148. }
  149. export default Scorecard