Plugin Directory

Changeset 3334722


Ignore:
Timestamp:
07/27/2025 07:19:08 AM (8 months ago)
Author:
notitia
Message:

chart data update

Location:
plot-beam/trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • plot-beam/trunk/package.json

    r3009739 r3334722  
    2222        "test": "vitest"
    2323    },
    24     "devDependencies": {
     24    "dependencies": {
    2525        "@sveltejs/vite-plugin-svelte": "^2.4.2",
     26        "@tsconfig/svelte": "^5.0.0",
     27        "@types/d3": "^7.4.3",
     28        "@wordpress/scripts": "^26.9.0",
     29        "d3": "^7.8.5",
     30        "npm-run-all": "^4.1.5",
     31        "vite": "^4.4.5",
     32        "vitest": "^0.34.3",
    2633        "@testing-library/jest-dom": "^6.1.2",
    2734        "@testing-library/svelte": "^4.0.3",
    28         "@tsconfig/svelte": "^5.0.0",
    29         "@types/d3": "^7.4.0",
    30         "@wordpress/scripts": "^26.11.0",
    3135        "jsdom": "^22.1.0",
    3236        "svelte": "^4.0.5",
     
    3438        "tslib": "^2.6.0",
    3539        "typescript": "^5.0.2",
    36         "vite": "^4.4.5",
    37         "vitest": "^0.34.3"
    38     },
    39     "dependencies": {
    40         "@sveltestack/svelte-query": "^1.6.0",
    41         "d3": "^7.8.5",
    42         "npm-run-all": "^4.1.5",
    43         "vitest": "^0.34.3"
     40        "uuid": "^11.1.0"
    4441    }
    4542}
  • plot-beam/trunk/src/edit.js

    r3011616 r3334722  
    44    SelectControl,
    55    Button,
    6 } from "@wordpress/components";
     6} from '@wordpress/components';
    77
    88/**
     
    1111 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
    1212 */
    13 import { __ } from "@wordpress/i18n";
     13import { __ } from '@wordpress/i18n';
    1414
    1515/**
     
    1919 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
    2020 */
    21 import { useBlockProps } from "@wordpress/block-editor";
     21import { useBlockProps } from '@wordpress/block-editor';
    2222
    2323/**
     
    2727 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
    2828 */
    29 import "./editor.scss";
     29import './editor.scss';
    3030
    3131/**
     
    3737 * @return {WPElement} Element to render.
    3838 */
    39 export default function Edit(props) {
     39export default function Edit( props ) {
    4040    const blockProps = useBlockProps();
    41     const dataTypeFn = (value) => {
    42         props.setAttributes({ dataType: value });
    43         switch (value) {
    44             case "userData":
    45                 props.setAttributes({ appID: "" });
    46                 props.setAttributes({ objectID: "" });
    47                 props.setAttributes({
    48                     description: "This contains organisational data",
    49                 });
    50                 break;
    51             case "bar":
    52                 props.setAttributes({ appID: "da8c91fe-88fd-45ef-b573-596621f7ec6f" });
    53                 props.setAttributes({ objectID: "aBGkzz" });
    54                 props.setAttributes({ objectTitle: "Example bar plot" });
    55                 props.setAttributes({ description: "This contains test data" });
    56                 break;
    57             case "line":
    58                 props.setAttributes({ appID: "da8c91fe-88fd-45ef-b573-596621f7ec6f" });
    59                 props.setAttributes({
    60                     objectID: "ec48858d-b158-432d-b60c-da7344d8bc9a",
    61                 });
    62                 props.setAttributes({ objectTitle: "Example line plot" });
    63                 props.setAttributes({ description: "This contains test data" });
    64                 break;
    65             case "scatterplot":
    66                 props.setAttributes({ appID: "da8c91fe-88fd-45ef-b573-596621f7ec6f" });
    67                 props.setAttributes({
    68                     objectID: "e3ed1aa7-a066-4358-a64e-0beb1c433317",
    69                 });
    70                 props.setAttributes({ objectTitle: "Example scatterplot" });
    71                 props.setAttributes({ description: "This contains test data" });
    72                 break;
    73             case "gauge":
    74                 props.setAttributes({ appID: "da8c91fe-88fd-45ef-b573-596621f7ec6f" });
    75                 props.setAttributes({
    76                     objectID: "576c5fc2-e038-4c90-b682-4e17b2fd846e",
    77                 });
    78                 props.setAttributes({ objectTitle: "Example gauge plot " });
    79                 props.setAttributes({ description: "This contains test data" });
     41    const dataTypeFn = ( value ) => {
     42        props.setAttributes( { dataType: value } );
     43        switch ( value ) {
     44            case 'userData':
     45                props.setAttributes( { appID: '' } );
     46                props.setAttributes( { objectID: '' } );
     47                props.setAttributes( {
     48                    description: 'This contains organisational data',
     49                } );
     50                break;
     51            case 'bar':
     52                props.setAttributes( {
     53                    appID: 'da8c91fe-88fd-45ef-b573-596621f7ec6f',
     54                } );
     55                props.setAttributes( { objectID: 'aBGkzz' } );
     56                props.setAttributes( { objectTitle: 'Example bar plot' } );
     57                props.setAttributes( {
     58                    description: 'This contains test data',
     59                } );
     60                break;
     61            case 'line':
     62                props.setAttributes( {
     63                    appID: 'da8c91fe-88fd-45ef-b573-596621f7ec6f',
     64                } );
     65                props.setAttributes( {
     66                    objectID: 'ec48858d-b158-432d-b60c-da7344d8bc9a',
     67                } );
     68                props.setAttributes( { objectTitle: 'Example line plot' } );
     69                props.setAttributes( {
     70                    description: 'This contains test data',
     71                } );
     72                break;
     73            case 'scatterplot':
     74                props.setAttributes( {
     75                    appID: 'da8c91fe-88fd-45ef-b573-596621f7ec6f',
     76                } );
     77                props.setAttributes( {
     78                    objectID: 'e3ed1aa7-a066-4358-a64e-0beb1c433317',
     79                } );
     80                props.setAttributes( { objectTitle: 'Example scatterplot' } );
     81                props.setAttributes( {
     82                    description: 'This contains test data',
     83                } );
     84                break;
     85            case 'gauge':
     86                props.setAttributes( {
     87                    appID: 'da8c91fe-88fd-45ef-b573-596621f7ec6f',
     88                } );
     89                props.setAttributes( {
     90                    objectID: '576c5fc2-e038-4c90-b682-4e17b2fd846e',
     91                } );
     92                props.setAttributes( { objectTitle: 'Example gauge plot ' } );
     93                props.setAttributes( {
     94                    description: 'This contains test data',
     95                } );
    8096                break;
    8197            default:
    82                 props.setAttributes({ appID: "" });
    83                 props.setAttributes({ objectID: "" });
    84                 props.setAttributes({ description: "" });
     98                props.setAttributes( { appID: '' } );
     99                props.setAttributes( { objectID: '' } );
     100                props.setAttributes( { description: '' } );
    85101                break;
    86102        }
    87103    };
    88     const openInNewTab = (url) => {
    89         window.open(url, "_blank", "noopener,noreferrer");
     104    const openInNewTab = ( url ) => {
     105        window.open( url, '_blank', 'noopener,noreferrer' );
    90106    };
    91107
    92108    return (
    93         <div className="wp-block-create-block-plot-beam" {...blockProps}>
    94             {__(
     109        <div className="wp-block-create-block-plot-beam" { ...blockProps }>
     110            { __(
    95111                <div className="admin-form">
    96112                    <SelectControl
    97113                        className="select first"
    98114                        label="Select data type"
    99                         value={props.attributes.dataType}
     115                        value={ props.attributes.dataType }
    100116                        required
    101                         options={[
    102                             { label: "Select Options", value: null },
    103                             { label: "Your Organisation Data", value: "userData" },
    104                             { label: "Example data-Bar chart", value: "bar" },
    105                             { label: "Example data-Line chart", value: "line" },
    106                             { label: "Example data-Scatterplot chart", value: "scatterplot" },
    107                             { label: "Example data-Gauge chart", value: "gauge" },
    108                         ]}
    109                         onChange={(value) => dataTypeFn(value)}
     117                        options={ [
     118                            { label: 'Select Options', value: null },
     119                            {
     120                                label: 'Your Organisation Data',
     121                                value: 'userData',
     122                            },
     123                            { label: 'Example data-Bar chart', value: 'bar' },
     124                            { label: 'Example data-Line chart', value: 'line' },
     125                            {
     126                                label: 'Example data-Scatterplot chart',
     127                                value: 'scatterplot',
     128                            },
     129                            {
     130                                label: 'Example data-Gauge chart',
     131                                value: 'gauge',
     132                            },
     133                        ] }
     134                        onChange={ ( value ) => dataTypeFn( value ) }
    110135                    />
    111                     {props.attributes.dataType === "userData" && (
     136                    { props.attributes.dataType === 'userData' && (
    112137                        <div className="button-group">
    113138                            <Button
    114139                                className="button"
    115                                 onClick={() =>
    116                                     openInNewTab("https://plot-beam.azurewebsites.net/register")
     140                                onClick={ () =>
     141                                    openInNewTab(
     142                                        'https://plot-beam.azurewebsites.net/register'
     143                                    )
    117144                                }
    118145                            >
    119146                                Create a new Plot Beam page
    120147                                <br />
    121                                 Connect my QlikSense data and create new visualisation
     148                                Connect my QlikSense data and create new
     149                                visualisation
    122150                            </Button>
    123151                            <Button
    124152                                className="button"
    125                                 onClick={() =>
    126                                     openInNewTab("https://plot-beam.azurewebsites.net/return")
     153                                onClick={ () =>
     154                                    openInNewTab(
     155                                        'https://plot-beam.azurewebsites.net/return'
     156                                    )
    127157                                }
    128158                            >
    129159                                Go to my Plot Beam page
    130                                 <br />I have already created a Plot Beam site for my
    131                                 organisation
     160                                <br />I have already created a Plot Beam site
     161                                for my organisation
    132162                            </Button>
    133163                        </div>
    134                     )}
     164                    ) }
    135165                    <TextControl
    136166                        className="form-text"
     
    138168                        type="text"
    139169                        help="Short title for the chart, 5 words max"
    140                         value={props.attributes.objectTitle}
    141                         onChange={(value) => props.setAttributes({ objectTitle: value })}
     170                        value={ props.attributes.objectTitle }
     171                        onChange={ ( value ) =>
     172                            props.setAttributes( { objectTitle: value } )
     173                        }
    142174                    />
    143                     {props.attributes.dataType === "userData" ? (
     175                    { props.attributes.dataType === 'userData' ? (
    144176                        <TextControl
    145177                            className="form-text"
     
    147179                            type="text"
    148180                            help="Object Slug Example:0gnriLVVas7CxY0Q-cZ77OKLLeEwNoumk/aBGkzz "
    149                             value={props.attributes.objectSlug}
    150                             onChange={(value) => props.setAttributes({ objectSlug: value })}
     181                            value={ props.attributes.objectSlug }
     182                            onChange={ ( value ) =>
     183                                props.setAttributes( { objectSlug: value } )
     184                            }
    151185                        />
    152186                    ) : (
     
    157191                                type="text"
    158192                                help="Demo App ID: da8c91fe-88fd-45ef-b573-596621f7ec6f"
    159                                 value={props.attributes.appID}
    160                                 onChange={(value) => props.setAttributes({ appID: value })}
     193                                value={ props.attributes.appID }
     194                                onChange={ ( value ) =>
     195                                    props.setAttributes( { appID: value } )
     196                                }
    161197                            />
    162198                            <TextControl
     
    165201                                type="text"
    166202                                help="Demo Object ID: aBGkzz"
    167                                 value={props.attributes.objectID}
    168                                 onChange={(value) => props.setAttributes({ objectID: value })}
     203                                value={ props.attributes.objectID }
     204                                onChange={ ( value ) =>
     205                                    props.setAttributes( { objectID: value } )
     206                                }
    169207                            />
    170208                        </>
    171                     )}
     209                    ) }
    172210                    <TextControl
    173211                        className="form-text"
     
    175213                        type="text"
    176214                        help="Short description for the chart, 100 words max"
    177                         value={props.attributes.description}
    178                         onChange={(value) => props.setAttributes({ description: value })}
     215                        value={ props.attributes.description }
     216                        onChange={ ( value ) =>
     217                            props.setAttributes( { description: value } )
     218                        }
    179219                    />
    180220                    <Text className="support">
    181                         For assistance, please visit our Support Portal at{" "}
     221                        For assistance, please visit our Support Portal at{ ' ' }
    182222                        <a
    183223                            className="notitia"
     
    187227                        </a>
    188228                    </Text>
    189                 </div>,
    190             )}
     229                </div>
     230            ) }
    191231        </div>
    192232    );
  • plot-beam/trunk/src/index.js

    r3009739 r3334722  
    44 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
    55 */
    6 import { registerBlockType } from "@wordpress/blocks";
     6import { registerBlockType } from '@wordpress/blocks';
    77
    88/**
     
    1313 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
    1414 */
    15 import "./style.scss";
     15import './style.scss';
    1616
    1717/**
    1818 * Internal dependencies
    1919 */
    20 import Edit from "./edit.js";
    21 import save from "./save.js";
    22 import metadata from "./block.json";
     20import Edit from './edit.js';
     21import save from './save.js';
     22import metadata from './block.json';
    2323
    2424/**
     
    2727 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
    2828 */
    29 registerBlockType(metadata.name, {
     29registerBlockType( metadata.name, {
    3030    icon: (
    3131        <svg
     
    7070    ),
    7171    attributes: {
    72         appID: { type: "string" },
    73         objectID: { type: "string" },
    74         objectTitle: { type: "string" },
    75         description: { type: "string" },
    76         dataType: { type: "string" },
    77         objectSlug: { type: "string" },
     72        appID: { type: 'string' },
     73        objectID: { type: 'string' },
     74        objectTitle: { type: 'string' },
     75        description: { type: 'string' },
     76        dataType: { type: 'string' },
     77        objectSlug: { type: 'string' },
    7878    },
    7979
    8080    example: {
    8181        attributes: {
    82             objectTitle: "Sales",
    83             appID: "0d40467d-e362-4d74-b445-4166a1b32cc9",
    84             objectID: "MkcvQD",
    85             description: "A chart to show case sales in detail",
    86             dataType: "userData",
    87             objectSlug: "0gnriLVVas7CxY0Q-cZ77OKLLeEwNoumk/aBGkzz",
     82            objectTitle: 'Sales',
     83            appID: '0d40467d-e362-4d74-b445-4166a1b32cc9',
     84            objectID: 'MkcvQD',
     85            description: 'A chart to show case sales in detail',
     86            dataType: 'userData',
     87            objectSlug: '0gnriLVVas7CxY0Q-cZ77OKLLeEwNoumk/aBGkzz',
    8888        },
    8989    },
     
    9797     */
    9898    save,
    99 });
     99} );
  • plot-beam/trunk/src/svelte/App.svelte

    r3009739 r3334722  
    11<script lang="ts">
    2     import { QueryClient, QueryClientProvider } from "@sveltestack/svelte-query";
    32    import Entry from "./Entry.svelte"
    43    import type{AppProp} from './appConfig/types';
    54    export let props: AppProp;
    6 
    7     const queryClient = new QueryClient({
    8         defaultOptions: {
    9             queries: {
    10                 cacheTime: 1 * (60 * 1000), // 5 mins
    11                 retry: 1,
    12                 refetchOnWindowFocus: "always",
    13                 refetchInterval: 5 * 60 * 1000,
    14             },
    15         },
    16     });
    175</script>
    186
    19 <QueryClientProvider client={queryClient}>
    207    <Entry {props} />
    21 </QueryClientProvider>
     8
    229
    2310<style>
  • plot-beam/trunk/src/svelte/Chart.svelte

    r3073590 r3334722  
    66    import ScatterPlot from './component/scatterPlot/ScatterPlot.svelte';
    77    import LineChart from './component/lineChart/LineChart.svelte';
    8     import { getGaugeProps } from './lib/gauge/getGaugePorps';
    9   import getLineProps from './lib/line/getLineProps';
    10   import getBarProps from './lib/bar/getBarProps';
    11   import getScatterPlotProps from './lib/scatterPlot/getScatterPlotProps';
    12     import { isGauge } from './lib/chartDataTypeCheck';
    13   // export let data: QlikChartDataType<GaugeChartDataType | LineChartDataType | ScatterplotChartDataType | BarChartDataType>;
    14     export let data: ChartData;
    15 
    16   const styleChoice ="notitia"
    17   const decimal = 0
    18   const label = "percentage"
    19   const valueOptions = "millions"
     8    import { isBar, isGauge, isLine, isScatterPlot } from './lib/chartDataTypeCheck';
     9  export let chartID;
     10  export let data;
    2011
    2112  const chartPool = ['gauge', 'scatterplot', 'barchart', 'linechart']
     
    2718  {#if isInPool && data}
    2819    {#if isGauge(data) }
    29       {#await getGaugeProps(data, styleChoice, label, valueOptions, decimal) then gaugeProps}
    3020      <Gauge   
    31       valueSlices={gaugeProps.valueSlices}
    32       segmentSlices={gaugeProps.segmentSlices}
    33       valueColors={gaugeProps.valueColors}
    34       displayMarks={gaugeProps.displayMarks}
    35       displayValue ={gaugeProps.displayValue}
    36       segmentColors={gaugeProps.segmentColors}
    37     />
    38       {/await}
     21        {...data}
     22      />
    3923    {/if}
    40     {#if data.visType === "barchart"}
    41       {#await getBarProps(data, styleChoice, label, valueOptions, decimal) then barProps}
     24    {#if isBar(data)}
    4225        <Bar   
    43           nodesData = {barProps.nodesData}
    44           group = {barProps.group}
    45           subGroup={barProps.subGroup}
    46           groupLabel={barProps.groupLabel}
     26          {...data}
     27          {chartID}
    4728        />
    48         {/await}
    4929    {/if}
    5030
    51     {#if data.visType === "scatterplot"}
    52       {#await getScatterPlotProps(data, styleChoice, label, valueOptions, decimal) then scatterPlotProps}
     31    {#if isScatterPlot(data)}
    5332        <ScatterPlot   
    54           xMeasure = {scatterPlotProps.xMeasure}
    55           yMeasure = {scatterPlotProps.yMeasure}
    56           dimension = {scatterPlotProps.dimension}
    57           nodesData = {scatterPlotProps.nodesData}
    58           nodeLabel = {scatterPlotProps.nodeLabel}
     33          {...data}
     34          {chartID}
    5935        />
    60         {/await}
    6136    {/if}
    6237
    63     {#if data.visType === "linechart"}
    64       {#await getLineProps(data, styleChoice, label, valueOptions, decimal) then lineProps}
    65         <LineChart 
    66           nodesData={lineProps.nodesData}
    67           xTicks={lineProps.xTicks}
    68           lines={lineProps.lines}
    69           measurements={lineProps.measurements}
    70           dimensions={lineProps.dimensions}
    71         />
    72       {/await}
     38    {#if isLine(data)}
     39      <LineChart   
     40        {...data}
     41        {chartID}
     42      />
    7343    {/if}
    7444{:else}
  • plot-beam/trunk/src/svelte/Entry.svelte

    r3073590 r3334722  
    11<script lang="ts">
    2   import type {AppProp, BarChartDataType, ChartData, LineChartDataType, QlikChartDataType, ScatterplotChartDataType} from './appConfig/types';
     2  import type {AppProp} from './appConfig/types';
    33  export let props: AppProp;
    4   import type { UseQueryStoreResult } from "@sveltestack/svelte-query";
    54  import Chart from './Chart.svelte';
    65    import BrandIcon from './component/BrandIcon.svelte';
    7     import type {AxiosError} from 'axios';
    8     import { getPBChartData } from './lib/getPbChartData';
    9     import { getTestChartData } from './lib/getTestChartData';
    10 
     6    import { getChartData } from './lib/getChartData';
     7    import { v4 as uuidv4 } from 'uuid';
     8    const chartID=uuidv4()
    119  const {
    12         appID,
    13         objectID,
    1410    description,
    1511        objectTitle,
    16         dataType,
    17         objectSlug
    1812    } = props;
    19 
    20   let result: UseQueryStoreResult<ChartData, AxiosError>;
    21     //getting object data from Qlik
    22     $: result = dataType==="userData"? getPBChartData(objectSlug): getTestChartData(appID, objectID);
    23  
    2413</script>
    2514
     
    3120    </div>
    3221    <div class="card-body">
    33       {#if $result.isLoading}
    34         <div class="card-chart">
     22            {#await getChartData(props)}
     23                <div class="card-chart">
    3524          <div class="custom-loader" />
    3625        </div>
    37       {:else if $result.error}
    38         <div class="card-chart card-error">
    39           Something went wrong: {$result.error.message}
     26            {:then result}
     27                <div class="card-chart-title">
     28          {props.objectTitle}
    4029        </div>
    41       {:else if $result.data}
    42         <div class="card-chart-title">
    43           {$result.data.measurements[0]}
    44         </div>
    45         <div class="card-chart">
    46           <Chart data={$result.data} {props} />
     30        <div class="card-chart" id="">
     31          <Chart data={result.data} {chartID}/>
    4732        </div>
    4833                {#if description}
    4934                <div class="card-description">{description}</div>
    5035                {/if}
    51       {/if}
     36            {:catch error}
     37                <div class="card-chart card-error">
     38          Something went wrong: {error}
     39        </div>
     40            {/await}
    5241    </div>
    5342  </div>
  • plot-beam/trunk/src/svelte/appConfig/types.ts

    r3073590 r3334722  
    22
    33type AppProp = {
    4     appID: string;
    5     objectID: string;
    6     description: string;
    7     objectTitle: string;
    8     dataType: string;
    9     objectSlug: string;
    10     // styleChoice: StyleOptions;
    11     // label: LabelOptions;
    12     // valueOptions: ValueOptions;
    13     // decimal: number;
    14 };
    15 
    16 type QlikChartDataType<ChartData> = {
    17     data: ChartData;
    18 };
    19 
    20 type GaugeChartDataType = QlikChartDataType<{
    21     visType: string;
    22     dimensions: string[];
    23     measurements: string[];
    24     measureAxis: MeasureAxis;
    25     segmentInfo: SegmentInfo;
    26     exactData: string[];
    27 }>;
    28 
    29 type LineChartDataType = QlikChartDataType<{
    30     visType: string;
    31     dimensions: string[];
    32     measurements: string[];
    33     exactData: ExactData<TypeOneExactData[]> | ExactData<TypeTwoExactData[]>;
    34 }>;
    35 
    36 type BarChartDataType = QlikChartDataType<{
    37     visType: string;
    38     dimensions: string[];
    39     measurements: string[];
    40     exactData: ExactData<TypeOneExactData[]> | ExactData<TypeTwoExactData[]>;
    41 }>;
    42 
    43 type ScatterplotChartDataType = QlikChartDataType<{
    44     visType: string;
    45     dimensions: string[];
    46     measurements: string[];
    47     exactData: [string, number, number][];
    48 }>;
    49 
    50 type SubNode = {
    51     qText: string;
    52     qNum: number;
    53     qSubNodes: {
    54         qText: string;
    55         qValue: number;
    56     }[];
    57 };
    58 type Nodes = {
    59     qSubNodes: SubNode[];
    60     qText: string;
    61 };
    62 type QData = {
    63     qElemNumber: number;
    64     qText: string;
    65     qNum: number;
    66     qSubNodes: Nodes[];
    67 };
    68 type TypeOneExactData = {
    69     qData: QData[];
    70 };
    71 type TypeTwoExactData = [string, ...[number]];
    72 type ExactData<T extends TypeOneExactData[] | TypeTwoExactData[]> = T;
    73 // type ChartData<
    74 //  T extends
    75 //      | BarChartDataType
    76 //      | LineChartDataType
    77 //      | ScatterplotChartDataType
    78 //      | GaugeChartDataType,
    79 // > = T["data"];
    80 type MeasureAxis = {
    81     min: number;
    82     max: number;
    83 };
    84 type Limits = {
    85     value: number;
    86     gradient: boolean;
    87 };
    88 
    89 type PaletteColors = {
    90     color: string;
    91     index: number;
    92 };
    93 type SegmentInfo = {
    94     paletteColors: PaletteColors[];
    95     limits: Limits[];
    96 };
    97 
    98 type ChartData = {
    99     visType: string;
    100     dimensions: string[];
    101     measurements: string[];
    102     measureAxis?: MeasureAxis;
    103     segmentInfo?: SegmentInfo;
    104     exactData: any[];
     4  appID: string;
     5  objectID: string;
     6  description: string;
     7  objectTitle: string;
     8  dataType: string;
     9  objectSlug: string;
     10  // styleChoice: StyleOptions;
     11  // label: LabelOptions;
     12  // valueOptions: ValueOptions;
     13  // decimal: number;
    10514};
    10615
    10716type GaugeProps = {
    108     segmentColors: string[];
    109     segmentSlices: number[];
    110     displayMarks: string[];
    111     displayValue: string;
    112     valueSlices: number[];
    113     valueColors: string[];
    114 };
    115 
    116 type DonutProps = {
    117     data: number;
    118     index: number;
    119     value: number;
    120     startAngle: number;
    121     endAngle: number;
    122     padAngle: number;
     17  segmentColors: string[];
     18  segmentSlices: number[];
     19  segmentMarks: string[];
     20  value: string;
     21  valueSlices: number[];
     22  valueColors: string[];
    12323};
    12424
    12525type ScatterPlotProps = {
    126     xMeasure: string;
    127     yMeasure: string;
    128     dimension: string;
    129     nodesData: number[][];
    130     nodeLabel: string[];
     26  xMeasure: string;
     27  yMeasure: string;
     28  dimension: string;
     29  nodesData: number[][];
     30  nodeLabel: string[];
    13131};
    13232
    13333type BarProps = {
    134     group: string[];
    135     subGroup: string[];
    136     groupLabel: string;
    137     nodesData: number[][];
     34  group: string[];
     35  subGroup: string[];
     36  groupLabel: string;
     37  nodesData: number[][];
    13838};
    13939
    14040type LineProps = {
    141     nodesData: number[][];
    142     lines: string[];
    143     xTicks: string[];
    144     measurements: string[];
    145     dimensions: string[];
     41  nodesData: number[][];
     42  lines: string[];
     43  xTicks: string[];
     44  measurement: string[];
     45  dimensions: string[];
    14646};
    14747
    148 type ChartProps = BarProps | ScatterPlotProps | GaugeProps | LineProps;
    14948type StyleOptions = "qlik" | "notitia";
    15049type LabelOptions = "value" | "percentage";
     
    15251
    15352export type {
    154     AppProp,
    155     BarChartDataType,
    156     GaugeChartDataType,
    157     ScatterplotChartDataType,
    158     ScatterPlotProps,
    159     BarProps,
    160     GaugeProps,
    161     DonutProps,
    162     StyleOptions,
    163     LabelOptions,
    164     ValueOptions,
    165     SegmentInfo,
    166     ChartProps,
    167     LineProps,
    168     MeasureAxis,
    169     LineChartDataType,
    170     ExactData,
    171     TypeOneExactData,
    172     TypeTwoExactData,
    173     QlikChartDataType,
    174     ChartData,
     53  AppProp,
     54  ScatterPlotProps,
     55  BarProps,
     56  GaugeProps,
     57  StyleOptions,
     58  LabelOptions,
     59  ValueOptions,
     60  LineProps,
    17561};
  • plot-beam/trunk/src/svelte/component/bar/AxisX.svelte

    r3009739 r3334722  
    11<script lang="ts">
    2   import { height, width, margin, innerHeight, innerWidth} from "../../lib/canvasSetup";
     2  import { innerHeight, innerWidth} from "../../lib/canvasSetup";
    33  export let xScale: any;
    44  export let nodesData: number[][];
    55  export let bandwidth: number;
    66  export let barsWidth:number;
    7   export let yScale: any;
    87  export let groupLabel: string;
    98  export let group: string[];
     
    1817    <text class="xTicks"  y={innerHeight} x={xScale(group[index])} stroke="grey"
    1918    dx={bandwidth/2} dy={15} text-anchor="middle">{group[index]}</text>
    20     <!-- {#if yScale(row[1]) < innerHeight/2}
    21       <text class="subGroup"  y={innerHeight/2} x={xScale(row[0])} stroke="grey"
    22     dx={bandwidth/2} dy={-5} text-anchor="middle">{row[0]}</text>
    23     {:else} -->
    24     <!-- <text class="subGroup"  y={yScale(row[1])} x={xScale(row[0])} stroke="grey"
    25     dx={bandwidth/2} dy={-5} text-anchor="end">{row[0]}</text> -->
    26     <!-- {/if} -->
    2719  {/each}
    2820</g>
     
    3022  .xTicks {
    3123  font-size: 10px;
    32 }
    33 .subGroup {
    34   writing-mode: vertical-rl;
    35   text-orientation: mixed;
    36 }
     24  }
    3725</style>
  • plot-beam/trunk/src/svelte/component/bar/AxisY.svelte

    r3009739 r3334722  
    11<script lang="ts">
    2   import * as d3 from "d3"
    3   import {margin, height, width, innerHeight, innerWidth} from '../../lib/canvasSetup'
     2  import { innerHeight} from '../../lib/canvasSetup'
    43  export let yTicks: number[];
    54  export let yScale: any;
  • plot-beam/trunk/src/svelte/component/bar/Bar.svelte

    r3009739 r3334722  
    99    import AxisX from "./AxisX.svelte";
    1010    import AxisY from "./AxisY.svelte";
    11     import { getExtendedRange } from "../../lib/getExtendedRange";
    12     import getBaseRange from "../../lib/getBaseRange";
    1311    import getBarsWidth from "../../lib/bar/getBarsWidth";
    1412    import getTicks from "../../lib/getTicks";
    1513    import Tooltip from "./Tooltip.svelte";
    16     export let nodesData: number[][];
    17     export let groupLabel: string;
    18     export let group: string[];
    19     export let subGroup: string[]
    20 let width: number;
     14
     15    export let data;
     16    export let measure;
     17    export let dimensions;
     18    export let chartID: string;
     19   
     20    let width: number;
     21   
    2122    const colors = ['#9ADDC2', '#37CC90', '#29996C', '#154D36', '#002415',
    2223          '#BECDF7','#185DF2', '#1245B3', '#0B2C73', '#C4C4C4']
    23     $: xMeasureData = group
    24     $: yBaseRange = getBaseRange(nodesData)
    25     $: yDomain = getExtendedRange(yBaseRange);
    26     $: barsWidth = getBarsWidth(group, subGroup, nodesData, innerWidth);
     24    $: subGroup = dimensions.subgroupTicks;
     25    $: group = dimensions.groupTicks;
     26    $: groupLabel = dimensions.groupTitle;
     27    $: yTicks = measure.ticks;
    2728
     29    $: nodesData = data.map((node: [string, number[]]) => node[1]);
     30    $: yDomain = [measure.ticks[0], measure.ticks[measure.ticks.length - 1]];
     31
     32    $: barsWidth = getBarsWidth(group, subGroup , nodesData, innerWidth);
     33   
    2834    $: yScale = d3.scaleLinear().domain(yDomain).range([innerHeight, 0]);
    2935    $: xScale = d3
    3036        .scaleBand()
    31         .domain(xMeasureData)
     37        .domain(group)
    3238        .range([0, barsWidth])
    3339        .paddingInner(0.1)
     
    3844    .range(colors)
    3945
    40     $: yTicks = getTicks(yDomain, 5);
    4146    $: bandwidth = xScale.bandwidth();
    4247    $: xSubgroup = d3.scaleBand<string>()
     
    7479    };
    7580</script>
    76 
    77 <div role="tooltip" class="container" on:mousemove={handleMouseCoord}   
    78 bind:clientWidth={width}
    79 style="--max-width: {width};" id="bar-group" >
    80     <svg width={barsWidth+margin.right+margin.left} {height} class="chart" data-testid="svg-element">
    81         <g transform="translate({margin.left}, {margin.top})" class="bar-frame">
    82             {#each nodesData as node, index}
    83                 {#each node as subnode, i}
    84                     <rect y={yScale(subnode)} width={subBarWidth} x={getSubNodeX(i, index)} height={innerHeight - yScale(subnode)} fill={getFillColor(i)}
    85                     opacity={hoveredData ? (hoveredData[0] === subnode? '1' : '0.6') : '0.8'}
    86                     on:mouseover={() => handleChartHover([subnode, group[index], subGroup[i]])}
    87                     on:focus={() => handleChartHover([subnode, group[index], subGroup[i]])}
    88                     on:mouseleave={() => handleLeaveChart()}
    89                     tabIndex="0"
    90                     role="tooltip"
    91                     />
     81<div id={chartID} class="barchart">
     82    <div role="tooltip" class="container" on:mousemove={handleMouseCoord}   
     83    bind:clientWidth={width}
     84    style="--max-width: {width};" id="bar-group" >
     85        <svg width={barsWidth+margin.right+margin.left} {height} class="chart" data-testid="svg-element">
     86            <g transform="translate({margin.left}, {margin.top})" class="bar-frame">
     87                {#each nodesData as node, index}
     88                    {#each node as subnode, i}
     89                        <rect y={yScale(subnode)} width={subBarWidth} x={getSubNodeX(i, index)} height={innerHeight - yScale(subnode)} fill={getFillColor(i)}
     90                        opacity={hoveredData ? (hoveredData[0] === subnode? '1' : '0.6') : '0.8'}
     91                        on:mouseover={() => handleChartHover([subnode, group[index], subGroup[i]])}
     92                        on:focus={() => handleChartHover([subnode, group[index], subGroup[i]])}
     93                        on:mouseleave={() => handleLeaveChart()}
     94                        tabIndex="0"
     95                        role="tooltip"
     96                        />
     97                    {/each}
    9298                {/each}
    93             {/each}
    94             <AxisX {xScale} {barsWidth} {nodesData} {bandwidth} {yScale} {groupLabel} {group}/>
    95             <AxisY {yTicks} {yScale} />
    96         </g>
    97     </svg>
     99                <AxisX {xScale} {barsWidth} {nodesData} {bandwidth} {yScale} {groupLabel} {group}/>
     100                <AxisY {yTicks} {yScale} />
     101            </g>
     102        </svg>
     103    </div>
     104    <div>
     105        {#if hoveredData}
     106            <Tooltip
     107                data={hoveredData}
     108                xPosition={mousePointWithMarginOffset.x}
     109                yPosition={mousePointWithMarginOffset.y}
     110                {groupLabel}
     111                {chartID}
     112            />
     113        {/if}
     114    </div>
    98115</div>
    99 <div>
    100     {#if hoveredData}
    101         <Tooltip
    102             data={hoveredData}
    103             xPosition={mousePointWithMarginOffset.x}
    104             yPosition={mousePointWithMarginOffset.y}
    105             {groupLabel}
    106         />
    107     {/if}
    108 </div>
    109 
    110116<style>
    111117  #bar-group {
    112     position: relative;
    113118    max-width: var(--max-width);
    114119    height: fit-content;
     
    117122    padding:0
    118123  }
     124    .barchart{
     125        position: relative;
     126        display: flex;
     127        width: 100%;
     128        height: 100%;
     129    }
    119130</style>
  • plot-beam/trunk/src/svelte/component/bar/Tooltip.svelte

    r3009739 r3334722  
    55  export let yPosition: number;
    66    export let groupLabel: string;
     7    export let chartID: string;
     8    const block = document.getElementById(chartID)
     9    let xOffset = 0
     10    let yOffset = 0
     11    if (block) {
     12        const blockRect = block.getBoundingClientRect();
     13        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
     14        const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
     15
     16        yOffset = blockRect.top + scrollTop;
     17        xOffset = blockRect.left + scrollLeft;
     18    }
    719</script>
    820
    9     <div class="tooltip" style="position: absolute; top: {yPosition}px; left: {xPosition}px;">
     21    <div class="tooltip" style="position: absolute; top: {yPosition-yOffset}px; left: {xPosition-xOffset}px;">
    1022    <h5>{groupLabel}: {data[1]}</h5>
    1123        <h5>{data[2]}</h5>
     
    1830        margin-left: 0.3rem;
    1931        margin-right: 0.3rem;
     32        font-size: 0.8rem;
    2033    }
    2134    p {
    22         font-size: small;
     35        font-size: 0.6rem;
    2336        margin: 0;
    2437        margin-left: 0.3rem;
     
    3346        opacity: 0;
    3447        animation: fadeIn 300ms ease-in forwards;
     48        overflow-x: visible;
     49        overflow-x: visible;
     50        z-index: 2;
    3551    }
    3652    @keyframes fadeIn {
  • plot-beam/trunk/src/svelte/component/gauge/Gauge.svelte

    r3009739 r3334722  
    33    import type { DefaultArcObject, Arc } from "d3";
    44  import {width, height} from "../../lib/canvasSetup"
    5   export let valueSlices: number[];
    6   export let segmentSlices: number[];
    7   export let valueColors: string[];
    8   export let displayMarks: string[];
    9   export let displayValue: string;
    10   export let segmentColors: string[];
     5  import  getDisplayValue  from '../../lib/getDisplayValue';
    116
     7  export let data;
     8  export let measure;
     9  console.log(data, measure)
    1210  const radius: number = height / 2;
    1311  const pie = d3
     
    1614    .endAngle((2 / 3) * Math.PI)
    1715    .sort(null);
     16  $: value = data[0][1];
     17  $: valueSlice = [value - measure.ticks[0], measure.ticks[measure.ticks.length - 1]- value];
     18  console.log(18, valueSlice, measure, data)
     19  const segmentColors = measure.colors;
     20  $: segmentDonut= pie(measure.ticks);
     21  $: valueDonut = pie(valueSlice);
     22  $: segmentMarks = measure.ticks;
    1823
    19   $: segmentDonut= pie(segmentSlices);
    20   $: valueDonut = pie(valueSlices);
    21  
     24  const valueColors = ['#70B1A0', '#EFEFEF'];
    2225  const valueArc: Arc<any, DefaultArcObject> = d3
    2326    .arc()
     
    4245        fill={segmentColors[i]}
    4346        id={`${slice.startAngle}`}
    44       />
    45       <text class='segment-label' dy={-5}>
    46         <textPath  href={`#${slice.startAngle}`} >{displayMarks[i]}</textPath>
    47       </text>
    48       <text class='segment-label' dy={-5}>
    49         <textPath startOffset="48%" text-anchor="end" href={`#${slice.startAngle}`}>{displayMarks.slice(-1)[0]}</textPath>
    50       </text>
     47       />
     48        <text class='segment-label' dy={-5}>
     49          <textPath  href={`#${slice.startAngle}`} text-anchor="start" >{getDisplayValue(segmentMarks[i-1])}</textPath>
     50        </text>
     51        <text class='segment-label' dy={-5}>
     52          <textPath startOffset="48%" text-anchor="end" href={`#${slice.startAngle}`}>{getDisplayValue(segmentMarks[segmentMarks.length -1])}</textPath>
     53        </text>
    5154        {:else}
     55        {console.log(55,i, segmentMarks[i])}
    5256        <path
    53         class="segments"
    54         d={segmentArc(slice)}
    55         fill={segmentColors[i]}
    56         id={`${slice.startAngle}`}
    57       />
    58       <text class='segment-label' dy={-5}>
    59        <textPath  href={`#${slice.startAngle}`} >{displayMarks[i]}</textPath>
    60       </text>
     57          class="segments"
     58          d={segmentArc(slice)}
     59          fill={segmentColors[i]}
     60          id={`${slice.startAngle}`}
     61        />
     62        <text class='segment-label' dy={-5}>
     63          <textPath  href={`#${slice.startAngle}`} text-anchor="start">{getDisplayValue(segmentMarks[i-1])}</textPath>
     64        </text>
    6165        {/if}
    6266      {/each}
     
    6468      <!-- getting the value arc -->
    6569      {#each valueDonut as slice, i}
    66         <path d={valueArc(slice)} fill={valueColors[i]} class="valueSlices" />
     70        <path d={valueArc(slice)} fill={valueColors[i-1]} class="valueSlices" />
    6771      {/each}
    68       <text text-anchor="middle" class="value-label"  data-testid="value">{displayValue}</text>
     72      <text text-anchor="middle" class="value-label"  data-testid="value">{getDisplayValue(value)}</text>
    6973    </g>
    7074  </svg>
  • plot-beam/trunk/src/svelte/component/lineChart/LineChart.svelte

    r3073590 r3334722  
    11<script lang="ts">
    2   export let nodesData:number[][];
    3   export let dimensions: string[]
    4   export let xTicks:  string[];
    5   export let lines:  string[];
    6   export let measurements: string[];
    72  import {margin, innerHeight, innerWidth, width,height} from '../../lib/canvasSetup';
    83  import * as d3 from 'd3';
     
    149    import { getExtendedRange } from '../../lib/getExtendedRange';
    1510    import Legend from './Legend.svelte';
     11  import type { LineRawData } from 'src/svelte/appConfig/chartData';
    1612
     13  export let data:LineRawData['data'];
     14  export let dimensions: LineRawData['dimensions']
     15  export let measure: LineRawData['measure']
     16  export let chartID: string;
    1717  const radius = 5
    1818  const colors = ['#9ADDC2', '#37CC90', '#29996C', '#154D36', '#002415',
    1919          '#BECDF7','#185DF2', '#1245B3', '#0B2C73', '#C4C4C4']
    2020
    21   const getTimeParser = (dimensions:string[], xTicks: string[] ) => {
    22     if (dimensions[0] === "YearMonth" && xTicks[0].includes('-'))
     21  $: xTicks = dimensions.groupTicks
     22  $: lines = dimensions.subgroupTicks
     23  $: measurement = measure.title
     24
     25  const getTimeParser = (dimensions:string, xTicks: string[] ) => {
     26    if (dimensions === "YearMonth" && xTicks[0].includes('-'))
    2327      return d3.timeParse('%Y-%b')
    2428
     
    2630  }
    2731
    28   const getTimeFormatter = (dimensions:string[], xTicks: string[]) => {
    29     if (dimensions[0] === "YearMonth" && xTicks[0].includes('-'))
     32  const getTimeFormatter = (dimensions:string, xTicks: string[]) => {
     33    if (dimensions === "YearMonth" && xTicks[0].includes('-'))
    3034      return d3.timeFormat('%Y-%b')
    3135
    3236    return d3.timeFormat("%Y")
    3337  }
    34   $: timeParser = getTimeParser(dimensions, xTicks)
    35   $: timeFormatter = getTimeFormatter(dimensions, xTicks)
     38  $: timeParser = getTimeParser(dimensions.groupTitle, xTicks)
     39  $: timeFormatter = getTimeFormatter(dimensions.groupTitle, xTicks)
    3640
    3741  $: timeSeries = xTicks.map(tick => {
    38     if (dimensions[0] === "Year" && tick.length >4)
     42    if (dimensions.groupTitle === "Year" && tick.length >4)
    3943      return timeParser(tick.slice(0, 4))
    4044    return timeParser(tick)
    4145  })
    4246
    43   $: yBaseRange = getBaseRange(nodesData)
    44   $: yDomain = getExtendedRange(yBaseRange)
     47  $: yDomain = [measure.ticks[0], measure.ticks[measure.ticks.length - 1]]
    4548  $: yScale = d3.scaleLinear().domain(yDomain).range([innerHeight, 0])
    4649 
     
    5760  }
    5861
     62  $: nodesData = xTicks.map((_: string, index: number) => {
     63            return data.map((line: any) => line[1][index]);
     64        });
    5965  $: displayTicks=xTicks.length > 6? getDisplayTicks(xScale, 5, xTicks): timeSeries
    60  
    61   $: indexArray = displayTicks.map((tick:any) => {
    62     return xTicks.indexOf(timeFormatter(tick))
    63   })
    64  
     66
    6567  //getTicks is a function taking extented range and numbers of ticks, return the array of tick display values
    66   $: yTicks = getTicks(yDomain, 4)
     68  $: yTicks = measure.ticks
    6769  // $: bandWidth = xScale.bandwidth()
    6870
     
    8385</script>
    8486
    85 <div class="container" role="tooltip"
    86 on:mousemove={handleMouseCoord}>
    87   <svg {width} {height} class="chart" data-testid="svg-element">
    88     <g transform="translate({margin.left}, {margin.top})">
    89       <AxisX {displayTicks} {xScale} {timeFormatter} {xTicks} {timeParser} {timeSeries}/>
    90         <g>
    91           {#if xTicks.length > 6}
    92             {#each lines as line, index}
    93               {#each nodesData as node, i}
    94                 {#if i > 0}
    95                   <line x1={xScale(timeParser(xTicks[i-1]))} y1={yScale(nodesData[i-1][index])} x2={xScale(timeParser(xTicks[i]))} y2={yScale(node[index])} stroke={colors[index]} />
    96                 {/if}
    97               {/each}
    98             {/each}
    99           {:else}
    100             {#each nodesData as node, index}
    101               {#each node as subNode, i}
    102                   <circle class="intersection" cx={xScale(timeSeries[index])} cy={yScale(subNode)} fill={colors[i]}  on:mouseover={() => handleCircleHover([subNode, i])}
     87<div class="linechart" id={chartID}>
     88  <div class="container" role="tooltip"
     89  on:mousemove={handleMouseCoord}>
     90    <svg {width} {height} class="chart" data-testid="svg-element">
     91      <g transform="translate({margin.left}, {margin.top})">
     92        <AxisX {displayTicks} {xScale} {timeFormatter} {xTicks} {timeParser} {timeSeries}/>
     93          <g>
     94            {#if xTicks.length > 6}
     95              {#each lines as line, index}
     96                {#each nodesData as node, i}
     97                  {#if i > 0}
     98                    <line x1={xScale(timeParser(xTicks[i-1]))} y1={yScale(nodesData[i-1][index])} x2={xScale(timeParser(xTicks[i]))} y2={yScale(node[index])} stroke={colors[index]} />
     99                  {/if}
     100                {/each}
     101              {/each}
     102            {:else}
     103              {#each nodesData as node, index}
     104              <!-- each node is number array which represent value of 6 states for a time -->
     105                <!-- i respresent index of the state -->
     106                {#each node as subNode, i} 
     107                  <!-- this is for the intersections -->
     108                  <!-- xScale(timeSeries[index]) is the x for each time  -->
     109                  <circle class="intersection" cx={xScale(timeSeries[index])} cy={yScale(subNode)} fill={colors[i]} 
     110                    on:mouseover={() => handleCircleHover([subNode, i])}
    103111                    on:focus={() => handleCircleHover([subNode, i])}
    104112                    on:mouseleave={() => handleLeaveChart()} 
    105113                    r={hoveredData&&hoveredData[0]==subNode? radius+3 : radius}
    106114                    opacity={hoveredData ? (hoveredData[0]== subNode? '1' : '0.6') : '1'}
     115                    tabIndex="0"
    107116                    role="tooltip"/>
     117                {/each}
     118               
     119                {#each lines as line, index}
     120                  {#each nodesData as node, i}
     121                    {#if i > 0}
     122                      <line x1={xScale(timeSeries[i-1])} y1={yScale(nodesData[i-1][index])} x2={xScale(timeSeries[i])} y2={yScale(node[index])} stroke={colors[index]} />
     123                    {/if}
     124                  {/each}
     125                {/each}
    108126              {/each}
    109               {#each lines as line, index}
    110               {#each nodesData as node, i}
    111                 {#if i > 0}
    112                   <line x1={xScale(timeSeries[i-1])} y1={yScale(nodesData[i-1][index])} x2={xScale(timeSeries[i])} y2={yScale(node[index])} stroke={colors[index]} />
    113                 {/if}
    114               {/each}
    115             {/each}
    116             {/each}
    117           {/if}
     127            {/if}
     128       
     129          </g>
     130        <AxisY {yScale} {yTicks} />
     131      </g>
     132      <g transform="translate({margin.left+innerWidth}, {10})">
     133        <Legend {lines} {colors}/>
     134      </g>
    118135     
    119         </g>
    120       <AxisY {yScale} {yTicks} />
    121     </g>
    122     <g transform="translate({margin.left+innerWidth}, {10})">
    123       <Legend {lines} {colors}/>
    124     </g>
    125    
    126   </svg>
     136    </svg>
     137  </div>
     138
     139  {#if hoveredData}
     140    <Tooltip data={hoveredData} xPosition={mousePointWithMarginOffset.x}
     141    yPosition={mousePointWithMarginOffset.y} {lines} {measurement} {chartID}/>
     142  {/if}
    127143</div>
    128144
    129 
    130 {#if hoveredData}
    131   <Tooltip data={hoveredData} xPosition={mousePointWithMarginOffset.x}
    132   yPosition={mousePointWithMarginOffset.y} {lines} {measurements}/>
    133 {/if}
    134 
     145<style>
     146  circle {
     147        transition: all 300ms ease;
     148        cursor: pointer;
     149    }
     150  .linechart{
     151        position: relative;
     152        display: flex;
     153        width: 100%;
     154        height: 100%;
     155    overflow-x: visible;
     156        overflow-y: visible;
     157    }
     158</style>
  • plot-beam/trunk/src/svelte/component/lineChart/Tooltip.svelte

    r3009739 r3334722  
    11<script lang="ts">
     2  // data is [value of intersection, state index]
    23  export let data: number[];
    34  export let xPosition: number;
    45  export let yPosition: number;
    56  export let lines: string[];
    6   export let measurements: string[];
     7  export let measurement: string[];
     8  export let chartID;
     9
    710  import getTooltipValue from "../../lib/getTooltipValue";
    8   import {margin} from "../../lib/canvasSetup"
     11
     12  let xOffset = 0
     13    let yOffset = 0
     14  const block = document.getElementById(chartID);
     15    if (block) {
     16        const blockRect = block.getBoundingClientRect();
     17        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
     18        const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
     19
     20        yOffset = blockRect.top + scrollTop;
     21        xOffset = blockRect.left + scrollLeft;
     22    }
    923</script>
    1024
    11 <div class="tooltip" style="position: absolute; top: {yPosition+margin.top-10}px; left: {xPosition+50}px;">
    12   <h5>{lines[data[1]]}</h5>
    13   <p>{measurements[0]}: {getTooltipValue(data[0])}</p>
    14 </div>
     25
     26  <div class="tooltip" style="position: absolute; top: {yPosition-yOffset}px; left: {xPosition-xOffset}px;">
     27    <h5>{lines[data[1]]}</h5>
     28    <p>{measurement}: {getTooltipValue(data[0])}</p>
     29  </div>
     30
    1531
    1632
     
    2036  margin-left: 0.3rem;
    2137  margin-right: 0.3rem;
     38  font-size: 0.8rem;
    2239}
    2340p {
    24   font-size: small;
    2541  margin: 0;
    2642  margin-left: 0.3rem;
    2743  margin-right: 0.3rem;
     44  font-size: 0.6rem;
    2845}
    2946.tooltip {
  • plot-beam/trunk/src/svelte/component/scatterPlot/AxisX.svelte

    r3009739 r3334722  
    22    import { getNumberOfDigits } from '../../lib/getExtendedRange';
    33    import {  innerHeight, innerWidth} from "../../lib/canvasSetup";
     4  import getDisplayValue from '../../lib/getDisplayValue';
    45  export let xMeasure: string;
    56  export let xTicks: number[];
     
    1314      {#if index !== 0 }
    1415        <line x1={xScale(tick)} y1={innerHeight} x2={xScale(tick)} y2={innerHeight-6} stroke="grey" />
    15         <text class="label" x={xScale(tick)} y={innerHeight} text-anchor="middle" dy={15}>{ getNumberOfDigits(tick) > 3? `${tick/1000}k` : tick}</text>
     16        <text class="label" x={xScale(tick)} y={innerHeight} text-anchor="middle" dy={15}>{ getDisplayValue(tick) }</text>
    1617      {:else}
    17         <text class="label" x={xScale(tick)} y={innerHeight} text-anchor="start" dy={15}>{ getNumberOfDigits(tick) > 3? `${tick/1000}k` : tick}</text>
     18        <text class="label" x={xScale(tick)} y={innerHeight} text-anchor="start" dy={15}>{ getDisplayValue(tick) }</text>
    1819      {/if}   
    1920  {/each}
  • plot-beam/trunk/src/svelte/component/scatterPlot/ScatterPlot.svelte

    r3009739 r3334722  
    55    import AxisY from "./AxisY.svelte";
    66    import Tooltip from "./Tooltip.svelte";
    7     import {getExtendedRange }from "../../lib/getExtendedRange";
    8   import getTicks from "../../lib/getTicks";
     7  import type { ScatterplotRawData } from "src/svelte/appConfig/chartData";
     8 
     9  export let data: ScatterplotRawData['data'];
     10  export let dimensions: ScatterplotRawData['dimensions'];
     11  export let measure: ScatterplotRawData['measure'];
     12  export let chartID: string;
    913
    10   export let xMeasure: string;
    11   export let yMeasure: string;
    12   export let nodesData: number[][];
    13   export let dimension: string;
    14   export let nodeLabel: string[];
     14  $: xMeasure = measure.title[0]
     15  $: yMeasure = measure.title[1]
    1516
    16   $: xMeasureData = nodesData.map(row=> row[0])
    17   $: yMeasureData = nodesData.map(row=> row[1])
    18 
    19   $: yBaseRange = [Math.min(...yMeasureData), Math.max(...yMeasureData)]
    20   $: xBaseRange = [Math.min(...xMeasureData), Math.max(...xMeasureData)]
    21 
    22   $: xDomain = getExtendedRange(xBaseRange)
    23   $: yDomain = getExtendedRange(yBaseRange)
     17  $: xDomain = [measure.xTicks[0], measure.xTicks[measure.xTicks.length-1]]
     18  $: yDomain = [measure.yTicks[0], measure.yTicks[measure.xTicks.length-1]]
    2419 
    2520  $: xScale = d3.scaleLinear().domain(xDomain).range([0, innerWidth])
    2621  $: yScale = d3.scaleLinear().domain(yDomain).range([innerHeight, 0])
    27   $: yTicks = getTicks(yDomain, 5)
    28   $: xTicks = getTicks(xDomain, 5)
     22  $: yTicks = measure.yTicks
     23  $: xTicks = measure.xTicks
     24  $: nodesData = data
     25  $: nodeLabel = dimensions.groupTicks
    2926
    3027  let hoveredData: number[] | null
     
    4441</script>
    4542
    46 <div
    47 role="tooltip"
    48 class="container"
    49 on:mousemove={handleMouseCoord}
    50 >
    51   <svg {width} {height} class="chart" data-testid="svg-element">
    52     <g transform="translate({margin.left}, {margin.top})">
    53       {#each nodesData as row, index}
    54         <circle class="circle" cx={xScale(row[0])} cy={yScale(row[1])}
    55           r={hoveredData && hoveredData === row ? '12' : '8'}
    56                   opacity={hoveredData ? (hoveredData[2] === index ? '1' : '0.6') : '1'}
    57                         fill="#37cc90"
    58                         stroke="#010101"
    59         on:mouseover={() => handleCircleHover([...row, index])}
    60         on:focus={() => handleCircleHover([...row, index])}
    61         on:mouseleave={() => handleLeaveChart()}
    62         tabIndex="0" role="tooltip"/>     
    63       {/each}
    64       <AxisX {xMeasure} {xTicks} {xScale} />
    65       <AxisY {yMeasure} {yTicks} {yScale} />
    66     </g>
    67   </svg>
     43<div class="scatterplot" id={chartID}>
     44  <div
     45  role="tooltip"
     46  class="container"
     47  on:mousemove={handleMouseCoord}
     48  >
     49    <svg {width} {height} class="chart" data-testid="svg-element">
     50      <g transform="translate({margin.left}, {margin.top})">
     51        {#each data as row, index}
     52          <circle class="circle" cx={xScale(row[1][0])} cy={yScale(row[1][1])}
     53            r={hoveredData && hoveredData === row[1]? '12' : '8'}
     54            opacity={hoveredData ? (hoveredData[2] === index ? '1' : '0.6') : '1'}
     55              fill="#37cc90"
     56              stroke="#010101"
     57          on:mouseover={() => handleCircleHover([...row[1], index])}
     58          on:focus={() => handleCircleHover([...row[1], index])}
     59          on:mouseleave={() => handleLeaveChart()}
     60          tabIndex="0" role="tooltip"/>     
     61        {/each}
     62        <AxisX {xMeasure} {xTicks} {xScale} />
     63        <AxisY {yMeasure} {yTicks} {yScale} />
     64      </g>
     65    </svg>
    6866  </div>
    69   {#if hoveredData}
    70     <Tooltip
    71       {xMeasure}
    72       {yMeasure}
    73       data={hoveredData}
    74       xPosition={mousePointWithMarginOffset.x}
    75       yPosition={mousePointWithMarginOffset.y}
    76       {nodeLabel}
    77     />
    78   {/if}
    79 
     67    {#if hoveredData}
     68      <Tooltip
     69        {xMeasure}
     70        {yMeasure}
     71        data={hoveredData}
     72        xPosition={mousePointWithMarginOffset.x}
     73        yPosition={mousePointWithMarginOffset.y}
     74        {nodeLabel}
     75        {chartID}
     76      />
     77    {/if}
     78  </div>
    8079<style>
    8180    circle {
     
    8382        cursor: pointer;
    8483    }
     84    .scatterplot{
     85        position: relative;
     86        display: flex;
     87        width: 100%;
     88        height: 100%;
     89    overflow-x: visible;
     90        overflow-y: visible;
     91    }
    8592</style>
  • plot-beam/trunk/src/svelte/component/scatterPlot/Tooltip.svelte

    r3009739 r3334722  
    77  export let yMeasure: string;
    88    export let nodeLabel: string[];
     9    export let chartID: string;
    910
    10     $: xAdjusted = xPosition - 50;
    11     $: yAdjusted = yPosition - 50;
     11    const block = document.getElementById(chartID);
     12    let xOffset = 0
     13    let yOffset = 0
     14    if (block) {
     15        const blockRect = block.getBoundingClientRect();
     16        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
     17        const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
     18
     19        yOffset = blockRect.top + scrollTop;
     20        xOffset = blockRect.left + scrollLeft;
     21    }
    1222</script>
    1323
    14 <div class="tooltip" style="position: absolute; top: {yAdjusted}px; left: {xAdjusted}px;">
     24<div class="tooltip" style="position: absolute; top: {yPosition-yOffset}px; left: {xPosition-xOffset}px;">
    1525    <h5>{nodeLabel[data[2]]}</h5>
    1626    <p>{xMeasure}: {getTooltipValue(data[0])}</p>
     
    2434        margin-left: 0.3rem;
    2535        margin-right: 0.3rem;
     36        font-size: 0.8rem;
    2637    }
    2738    p {
     
    3041        margin-left: 0.3rem;
    3142        margin-right: 0.3rem;
     43        font-size: 0.6rem;
    3244    }
    3345    .tooltip {
     
    3951        opacity: 0;
    4052        animation: fadeIn 300ms ease-in forwards;
     53        overflow-x: visible;
     54        overflow-y: visible;
     55        z-index: 2;
    4156    }
    4257    @keyframes fadeIn {
  • plot-beam/trunk/src/svelte/lib/bar/getBarsWidth.ts

    r3009739 r3334722  
    11const getBarsWidth = (
    2     group:string[],
    3     subGroup: string[], 
     2    group: string[],
     3    subGroup: string[],
    44    nodesData: number[][],
    55    innerWidth: number
     
    77    let barWidth;
    88    //check if it is a grouped bar
    9     if (subGroup.length>1) {
    10         barWidth = 31*subGroup.length
     9    if ( subGroup.length > 1 ) {
     10        barWidth = 31 * subGroup.length;
    1111    } else {
    12         barWidth = 40
     12        barWidth = 40;
    1313    }
    1414    const barsWidth = barWidth * group.length;
    15    
    16     if ( innerWidth < barsWidth )
    17     return barsWidth;
    18  
     15
     16    if ( innerWidth < barsWidth ) return barsWidth;
     17
    1918    return innerWidth;
    2019};
  • plot-beam/trunk/src/svelte/lib/getBaseRange.test.ts

    r3009739 r3334722  
    44it( 'base tst', () => {
    55    const testArray: number[][] = [
    6         [  23, 49, 198 ],
    7         [  223, 249, 698 ],
    8         [  77, 97, 54 ],
     6        [ 23, 49, 198 ],
     7        [ 223, 249, 698 ],
     8        [ 77, 97, 54 ],
    99        [ 628, 29, 763 ],
    1010    ];
     
    1818    const testArray: number[][] = [
    1919        [ 87666.29400000005, 72043.92419999996, 208757.69999999992 ],
    20         [  458871.0101, 363073.9277000001, 580147.4999999994 ],
     20        [ 458871.0101, 363073.9277000001, 580147.4999999994 ],
    2121        [ 1101379.7817, 868841.0968000006, 1280426.099999999 ],
    2222        [ 1785036.1851000001, 1421877.3500000006, 1222286.9999999993 ],
  • plot-beam/trunk/src/svelte/lib/getDisplayValue.ts

    r3009739 r3334722  
    11import { getNumberOfDigits } from './getExtendedRange';
    22
    3 const getDisplayValue = ( value: number ) => {
     3const getDisplayValue = ( value: number | string ) => {
     4    if ( typeof value === 'string' ) {
     5        const parsedValue = parseFloat( value );
     6        if ( isNaN( parsedValue ) ) return value;
     7        value = parsedValue;
     8    }
    49    const trimedValue = Math.round( value );
    510    const digits = getNumberOfDigits( trimedValue );
Note: See TracChangeset for help on using the changeset viewer.