@politicalwatch/tipi-uikit 1.9.3 → 1.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +1 -1
  2. package/src/components/CSVDownload/CSVDownload.vue +3 -1
  3. package/src/components/Charts/WordsCloud/d3.wordscloud.vue +1 -1
  4. package/src/components/Charts/d3.chart.vue +63 -57
  5. package/src/components/CongressLink/CongressLink.vue +3 -1
  6. package/src/components/Deputy/Deputy.vue +7 -6
  7. package/src/components/Header/Header.vue +9 -5
  8. package/src/components/InitiativeCard/InitiativeCard.vue +20 -16
  9. package/src/components/InitiativeMeta/InitiativeMeta.vue +20 -20
  10. package/src/components/Message/Message.vue +5 -1
  11. package/src/components/Navbar/Navbar.vue +4 -2
  12. package/src/components/Neuron/Neuron.vue +10 -9
  13. package/src/components/PartyLogo/PartyLogo.vue +1 -1
  14. package/src/components/PartyLogo/PartyLogoIcon.vue +9 -7
  15. package/src/components/Results/Results.vue +21 -22
  16. package/src/components/Splash/Splash.vue +3 -2
  17. package/src/components/Text/Text.vue +16 -12
  18. package/src/components/TopicCard/TopicCard.vue +15 -10
  19. package/src/components/TopicLink/TopicLink.vue +6 -3
  20. package/src/components/TopicPill/TopicPill.vue +13 -6
  21. package/src/components/Topics/Topics.vue +30 -33
  22. package/src/components/TwoCircles/TwoCircles.vue +10 -10
  23. package/src/stories/D3BarChart.stories.js +40 -0
  24. package/src/stories/D3SlicesChart.stories.js +64 -0
  25. package/src/stories/D3Sunburst.stories.js +293 -0
  26. package/src/stories/{Charts.stories.js → D3WordsCloud.stories.js} +15 -3
  27. package/src/stories/InitiativeCard.stories.js +3 -153
  28. package/src/stories/Navbar.stories.js +40 -0
  29. package/src/stories/Results.stories.js +2 -105
  30. package/src/stories/Text.stories.js +10 -0
  31. package/src/stories/TopicCard.stories.js +2 -9
  32. package/src/stories/TopicPill.stories.js +6 -107
  33. package/src/stories/Topics.stories.js +80 -0
  34. package/src/stories/mocks.js +153 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@politicalwatch/tipi-uikit",
3
- "version": "1.9.3",
3
+ "version": "1.9.5",
4
4
  "main": "src/components/index.js",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -58,9 +58,10 @@
58
58
  </template>
59
59
 
60
60
  <script setup>
61
+ import { toRefs } from 'vue';
61
62
  import JsonExcel from 'vue-json-excel3';
62
63
 
63
- const { initiatives } = defineProps({
64
+ const props = defineProps({
64
65
  initiatives: {
65
66
  type: Array,
66
67
  default: function () {
@@ -95,6 +96,7 @@ const { initiatives } = defineProps({
95
96
  default: 'c-button--compact',
96
97
  },
97
98
  });
99
+ const { initiatives, csvItems, canDownloadCSV, csvFields, label, buttonClass } = toRefs(props);
98
100
 
99
101
  const emit = defineEmits(['loadCSVItems']);
100
102
 
@@ -9,7 +9,7 @@ export default {
9
9
  this.chart = new d3wordscloud(
10
10
  this.$refs.chart,
11
11
  JSON.parse(JSON.stringify(this.datum)),
12
- this.config,
12
+ this.config
13
13
  );
14
14
  },
15
15
  };
@@ -9,71 +9,77 @@
9
9
  </div>
10
10
  </template>
11
11
 
12
- <script>
12
+ <script setup>
13
+ import { ref, watch, onBeforeUnmount } from 'vue';
13
14
  import { saveSvgAsPng } from 'save-svg-as-png';
14
15
 
15
- export default {
16
- name: 'D3Chart',
17
- data() {
18
- return {
19
- chart: {},
20
- };
16
+ const chart = ref(null);
17
+
18
+ const props = defineProps({
19
+ config: {
20
+ type: Object,
21
+ required: true,
22
+ default: () => ({}),
23
+ },
24
+ datum: {
25
+ type: Array,
26
+ required: true,
27
+ default: () => [],
21
28
  },
22
- props: {
23
- config: {
24
- type: Object,
25
- required: true,
26
- default: () => ({}),
27
- },
28
- datum: {
29
- type: Array,
30
- required: true,
31
- default: () => [],
32
- },
33
- title: {
34
- type: String,
35
- default: '',
36
- },
37
- source: {
38
- type: String,
39
- default: '',
40
- },
41
- height: {
42
- type: Number,
43
- default: 300,
44
- },
45
- download: {
46
- type: String,
47
- },
29
+ title: {
30
+ type: String,
31
+ default: '',
48
32
  },
49
- methods: {
50
- downloadSVG() {
51
- const node = this.$refs.chart.getElementsByClassName('chart')[0];
52
- saveSvgAsPng(node, 'chart.png', {
53
- backgroundColor: '#FFF',
54
- });
55
- },
33
+ source: {
34
+ type: String,
35
+ default: '',
56
36
  },
57
- watch: {
58
- config: {
59
- handler(val) {
60
- this.chart.updateConfig(val);
61
- },
62
- deep: true,
63
- },
64
- datum(vals) {
65
- this.chart.updateData([...vals]);
66
- },
67
- height(val) {
68
- setTimeout(() => {
69
- this.chart.resizeChart();
70
- }, 10);
71
- },
37
+ height: {
38
+ type: Number,
39
+ default: 300,
72
40
  },
73
- beforeDestroy() {
74
- this.chart.destroyChart();
41
+ download: {
42
+ type: String,
75
43
  },
44
+ });
45
+
46
+ const { config, datum, title, source, height, download } = toRefs(props);
47
+
48
+ const downloadSVG = () => {
49
+ const node = chart.value.getElementsByClassName('chart')[0];
50
+ saveSvgAsPng(node, 'chart.png', {
51
+ backgroundColor: '#FFF',
52
+ });
76
53
  };
54
+
55
+ watch(
56
+ () => config.value,
57
+ (val) => {
58
+ chart.value.updateConfig(val);
59
+ },
60
+ { deep: true }
61
+ );
62
+
63
+ watch(
64
+ () => datum.value,
65
+ (vals) => {
66
+ chart.value.updateData([...vals]);
67
+ },
68
+ { deep: true }
69
+ );
70
+
71
+ watch(
72
+ () => height.value,
73
+ (val) => {
74
+ setTimeout(() => {
75
+ chart.value.resizeChart();
76
+ }, 10);
77
+ }
78
+ );
79
+
80
+ onBeforeUnmount(() => {
81
+ chart.value.destroyChart();
82
+ });
77
83
  </script>
78
84
 
79
85
  <style lang="scss">
@@ -9,9 +9,11 @@
9
9
  </template>
10
10
 
11
11
  <script setup>
12
+ import { toRefs } from 'vue';
12
13
  import TipiIcon from '../Icon/Icon.vue';
13
14
 
14
- const { url } = defineProps({
15
+ const props = defineProps({
15
16
  url: { type: String },
16
17
  });
18
+ const { url } = toRefs(props);
17
19
  </script>
@@ -53,17 +53,18 @@
53
53
  </template>
54
54
 
55
55
  <script setup>
56
- import { ref } from 'vue';
56
+ import { ref, toRefs } from 'vue';
57
57
 
58
58
  import TipiIcon from '../Icon/Icon.vue';
59
- import PartyLogo from '../PartyLogo/PartyLogo.vue';
60
59
  import PartyLogoIcon from '../PartyLogo/PartyLogoIcon.vue';
61
60
 
62
- const { deputy, parliamentaryGroup } = defineProps({
61
+ const props = defineProps({
63
62
  deputy: Object,
64
63
  parliamentaryGroup: Object,
65
64
  });
66
65
 
66
+ const { deputy, parliamentaryGroup } = toRefs(props);
67
+
67
68
  const isCollapsed = ref(true);
68
69
 
69
70
  const getCollapsedClass = () => {
@@ -83,7 +84,7 @@ const collapse = () => {
83
84
  };
84
85
 
85
86
  const addBirthdayClass = () => {
86
- const date = new Date(deputy.birthdate);
87
+ const date = new Date(deputy.value.birthdate);
87
88
  const today = new Date();
88
89
  if (date.getDate() == today.getDate() && date.getMonth() == today.getMonth()) {
89
90
  return 'c-deputy__birthday';
@@ -91,14 +92,14 @@ const addBirthdayClass = () => {
91
92
  };
92
93
 
93
94
  const getAge = () => {
94
- const date = new Date(deputy.birthdate);
95
+ const date = new Date(deputy.value.birthdate);
95
96
  const today = new Date();
96
97
  const age = today.getFullYear() - date.getFullYear();
97
98
  return age;
98
99
  };
99
100
 
100
101
  const getConstituency = () => {
101
- return deputy.constituency;
102
+ return deputy.value.constituency;
102
103
  };
103
104
  </script>
104
105
 
@@ -7,9 +7,13 @@
7
7
  </header>
8
8
  </template>
9
9
 
10
- <script>
11
- export default {
12
- name: 'TipiHeader',
13
- props: ['title', 'subtitle'],
14
- };
10
+ <script setup>
11
+ import { toRefs } from 'vue';
12
+
13
+ const props = defineProps({
14
+ title: String,
15
+ subtitle: String,
16
+ });
17
+
18
+ const { title, subtitle } = toRefs(props);
15
19
  </script>
@@ -52,34 +52,38 @@
52
52
  </template>
53
53
 
54
54
  <script setup>
55
+ import { toRefs } from 'vue';
56
+
55
57
  import TipiIcon from '../Icon/Icon.vue';
56
58
  import TipiTopicPill from '../TopicPill/TopicPill.vue';
57
59
  import TipiInitiativeMeta from '../InitiativeMeta/InitiativeMeta.vue';
58
60
 
59
- const { initiative, topicsStyles, extendedLayout, metaDeputies, metaGroupsOthers, metaColors } =
60
- defineProps({
61
- initiative: Object,
62
- topicsStyles: Object,
63
- extendedLayout: Boolean,
64
- metaDeputies: String,
65
- metaGroupsOthers: String,
66
- metaColors: { type: Object, default: undefined },
67
- });
61
+ const props = defineProps({
62
+ initiative: Object,
63
+ topicsStyles: Object,
64
+ extendedLayout: Boolean,
65
+ metaDeputies: String,
66
+ metaGroupsOthers: String,
67
+ metaColors: { type: Object, default: undefined },
68
+ });
69
+
70
+ const { initiative, extendedLayout, metaDeputies, metaGroupsOthers, metaColors } = toRefs(props);
71
+ const { topicsStyles } = props;
68
72
 
69
- const getAuthors = (initiative) => {
70
- return initiative.authors.length ? initiative.authors.join('<br/>') : '';
73
+ const getAuthors = () => {
74
+ return initiative.value.authors.length ? initiative.value.authors.join('<br/>') : '';
71
75
  };
72
76
 
73
- const getTopics = (initiative) => {
74
- return initiative['tagged'].reduce((topics, tagged) => {
77
+ const getTopics = () => {
78
+ return initiative.value['tagged'].reduce((topics, tagged) => {
75
79
  return topics.concat(tagged['topics']);
76
80
  }, []);
77
81
  };
78
82
 
79
- const getDeputies = (initiative) => {
80
- if (initiative.deputies.length == 0) return '';
83
+ const getDeputies = () => {
84
+ if (initiative.value.deputies.length == 0) return '';
81
85
  let regex_id = /\[.*\]/;
82
- return initiative.deputies
86
+ return initiative.value.deputies
83
87
  .map((d) => {
84
88
  var has_id = regex_id.exec(d);
85
89
  if (!has_id) return d;
@@ -1,24 +1,22 @@
1
1
  <template>
2
2
  <div class="c-initiative-meta">
3
- <div
4
- :class="`c-initiative-meta__status c-initiative-meta__status--${getColorByStatus(
5
- initiative.status
6
- )}`"
7
- >
3
+ <div :class="`c-initiative-meta__status c-initiative-meta__status--${getColorByStatus()}`">
8
4
  <strong>
9
- <tipi-icon :icon="getIcon(initiative)"></tipi-icon>
10
- {{ getStateMessage(initiative) }}
5
+ <tipi-icon :icon="getIcon()"></tipi-icon>
6
+ {{ getStateMessage() }}
11
7
  </strong>
12
8
  </div>
13
9
  </div>
14
10
  </template>
15
11
 
16
12
  <script setup>
13
+ import { toRefs } from 'vue';
17
14
  import { formatDistanceToNow } from 'date-fns/formatDistanceToNow';
18
15
  import { es } from 'date-fns/locale/es';
16
+
19
17
  import TipiIcon from '../Icon/Icon.vue';
20
18
 
21
- const { initiative, metaColors } = defineProps({
19
+ const props = defineProps({
22
20
  initiative: Object,
23
21
  metaColors: {
24
22
  type: Object,
@@ -46,34 +44,36 @@ const { initiative, metaColors } = defineProps({
46
44
  },
47
45
  });
48
46
 
49
- const getColorByStatus = (status) => {
50
- for (let color in metaColors) {
51
- if (metaColors[color].indexOf(status) != -1) return color;
47
+ const { initiative, metaColors } = toRefs(props);
48
+
49
+ const getColorByStatus = () => {
50
+ for (let color in metaColors.value) {
51
+ if (metaColors.value[color].indexOf(initiative.value.status) != -1) return color;
52
52
  }
53
53
  return 'neutral';
54
54
  };
55
55
 
56
- const getIcon = (initiative) => {
57
- const color = getColorByStatus(initiative['status']);
56
+ const getIcon = () => {
57
+ const color = getColorByStatus();
58
58
  const map = { completed: 'success', neutral: 'clock', error: 'denied' };
59
59
  return map[color];
60
60
  };
61
61
 
62
- const getStateMessage = (initiative) => {
63
- if (initiative['status'] == 'Desconocida') {
64
- return `${initiative['status']}`;
62
+ const getStateMessage = () => {
63
+ if (initiative.value['status'] == 'Desconocida') {
64
+ return `${initiative.value['status']}`;
65
65
  }
66
66
 
67
- const color = getColorByStatus(initiative['status']);
68
- let date = initiative['updated'];
67
+ const color = getColorByStatus();
68
+ let date = initiative.value['updated'];
69
69
  if (color == 'neutral') {
70
- date = initiative['created'];
70
+ date = initiative.value['created'];
71
71
  }
72
72
 
73
73
  const formattedDate = formatDistanceToNow(new Date(date), {
74
74
  locale: es,
75
75
  addSuffix: true,
76
76
  }).replace('alrededor de ', '');
77
- return `${initiative['status']} ${formattedDate}`;
77
+ return `${initiative.value['status']} ${formattedDate}`;
78
78
  };
79
79
  </script>
@@ -8,9 +8,11 @@
8
8
  </template>
9
9
 
10
10
  <script setup>
11
+ import { toRefs } from 'vue';
12
+
11
13
  import TipiIcon from '../Icon/Icon.vue';
12
14
 
13
- const { type, icon } = defineProps({
15
+ const props = defineProps({
14
16
  type: {
15
17
  type: String,
16
18
  default: 'success',
@@ -20,4 +22,6 @@ const { type, icon } = defineProps({
20
22
  },
21
23
  icon: Boolean,
22
24
  });
25
+
26
+ const { type, icon } = toRefs(props);
23
27
  </script>
@@ -75,11 +75,11 @@
75
75
  </template>
76
76
 
77
77
  <script setup>
78
- import { ref, computed } from 'vue';
78
+ import { ref, toRefs, computed } from 'vue';
79
79
 
80
80
  import Icon from '../Icon/Icon.vue';
81
81
 
82
- const { links, disclaimerLink, preImage, logo } = defineProps({
82
+ const props = defineProps({
83
83
  links: Array,
84
84
  disclaimerLink: {
85
85
  type: Object,
@@ -91,6 +91,8 @@ const { links, disclaimerLink, preImage, logo } = defineProps({
91
91
  logo: String,
92
92
  });
93
93
 
94
+ const { links, disclaimerLink, preImage, logo } = toRefs(props);
95
+
94
96
  const closedMessage = ref(false);
95
97
  const menuVisible = ref(false);
96
98
 
@@ -3,12 +3,13 @@
3
3
  </template>
4
4
 
5
5
  <script setup>
6
- import { onMounted, watch } from 'vue';
6
+ import { toRefs, onMounted, watch } from 'vue';
7
+ import { useRoute } from 'vue-router';
7
8
  import { select } from 'd3-selection';
8
9
  import { easeBackOut } from 'd3-ease';
9
10
  import { transition } from 'd3-transition';
10
11
 
11
- const { initiative, topics, styles } = defineProps({
12
+ const props = defineProps({
12
13
  initiative: Object,
13
14
  topics: Array,
14
15
  styles: {
@@ -19,6 +20,9 @@ const { initiative, topics, styles } = defineProps({
19
20
  },
20
21
  });
21
22
 
23
+ const { initiative, topics, styles } = toRefs(props);
24
+ const route = useRoute();
25
+
22
26
  const loadVizz = (topics, initiative, styles, color = { center: '#222' }) => {
23
27
  //Mapping ranges
24
28
  function map(x, in_min, in_max, out_min, out_max) {
@@ -186,15 +190,12 @@ const loadVizz = (topics, initiative, styles, color = { center: '#222' }) => {
186
190
  };
187
191
 
188
192
  onMounted(() => {
189
- loadVizz(topics, initiative, styles);
193
+ loadVizz(topics.value, initiative.value, styles.value);
190
194
  });
191
195
 
192
- watch(
193
- () => [topics, initiative],
194
- ([topics, initiative, styles]) => {
195
- loadVizz(topics, initiative, styles);
196
- }
197
- );
196
+ watch(route, () => {
197
+ loadVizz(topics.value, initiative.value, styles.value);
198
+ });
198
199
  </script>
199
200
 
200
201
  <style lang="scss">
@@ -7,7 +7,7 @@
7
7
  <script setup>
8
8
  import { ref, toRefs, watchEffect } from 'vue';
9
9
  const props = defineProps({
10
- party: String,
10
+ party: { type: String },
11
11
  });
12
12
  const { party } = toRefs(props);
13
13
 
@@ -7,13 +7,15 @@
7
7
  </template>
8
8
 
9
9
  <script setup>
10
- import { computed } from 'vue';
10
+ import { toRefs, computed } from 'vue';
11
11
  import InlineSvg from 'vue-inline-svg';
12
12
 
13
- const { party } = defineProps({
14
- party: String,
13
+ const props = defineProps({
14
+ party: { type: String },
15
15
  });
16
16
 
17
+ const { party } = toRefs(props);
18
+
17
19
  const parties = {
18
20
  Cs: {
19
21
  name: 'Ciudadanos',
@@ -185,8 +187,8 @@ const parties = {
185
187
  const svg = computed(() => {
186
188
  let svg = '';
187
189
  try {
188
- if (party in parties) {
189
- svg = `../../assets/party_logos/icon/${parties[party].logo}.svg`;
190
+ if (party.value in parties) {
191
+ svg = `../../assets/party_logos/icon/${parties[party.value].logo}.svg`;
190
192
  } else {
191
193
  svg = '../../assets/svg/icon-error.svg';
192
194
  }
@@ -197,7 +199,7 @@ const svg = computed(() => {
197
199
  });
198
200
 
199
201
  const getBackground = computed(() => {
200
- const bg = parties[party]?.color ? parties[party].color : '#f4f6f8';
202
+ const bg = parties[party.value]?.color ? parties[party.value].color : '#f4f6f8';
201
203
  if (bg.length == 7) {
202
204
  return 'background-color:' + bg;
203
205
  }
@@ -205,7 +207,7 @@ const getBackground = computed(() => {
205
207
  });
206
208
 
207
209
  const getName = computed(() => {
208
- return parties[party]?.name ? parties[party].name : '';
210
+ return parties[party.value]?.name ? parties[party.value].name : '';
209
211
  });
210
212
  </script>
211
213
 
@@ -1,17 +1,14 @@
1
1
  <template>
2
2
  <div>
3
3
  <tipi-loader
4
- v-if="this.loadingResults"
4
+ v-if="loadingResults"
5
5
  title="Cargando resultados"
6
6
  subtitle="Puede llevar algun tiempo"
7
7
  />
8
- <section
9
- class="o-masonry o-grid"
10
- v-if="this.initiatives && this.initiatives.length && !this.loadingResults"
11
- >
8
+ <section class="o-masonry o-grid" v-if="initiatives && initiatives.length && !loadingResults">
12
9
  <div
13
10
  class="o-grid__col u-12 u-4@sm o-masonry__item"
14
- v-for="(initiative, index) in this.initiatives"
11
+ v-for="(initiative, index) in initiatives"
15
12
  :key="index"
16
13
  >
17
14
  <tipi-initiative-card
@@ -35,22 +32,13 @@
35
32
  </template>
36
33
 
37
34
  <script setup>
38
- import { computed, onMounted, watch } from 'vue';
35
+ import { toRefs, computed, onMounted, watch } from 'vue';
39
36
 
40
37
  import TipiInitiativeCard from '../InitiativeCard/InitiativeCard.vue';
41
38
  import TipiLoader from '../Loader/Loader.vue';
42
39
  import Masonry from 'masonry-layout';
43
40
 
44
- const {
45
- loadingResults,
46
- initiatives,
47
- queryMeta,
48
- layout,
49
- topicsStyles,
50
- metaDeputies,
51
- metaGroupsOthers,
52
- metaColors,
53
- } = defineProps({
41
+ const props = defineProps({
54
42
  loadingResults: Boolean,
55
43
  initiatives: {
56
44
  type: Array,
@@ -66,18 +54,29 @@ const {
66
54
  metaColors: { type: Object, default: undefined },
67
55
  });
68
56
 
57
+ const {
58
+ loadingResults,
59
+ initiatives,
60
+ queryMeta,
61
+ layout,
62
+ metaDeputies,
63
+ metaGroupsOthers,
64
+ metaColors,
65
+ } = toRefs(props);
66
+ const { topicsStyles } = props;
67
+
69
68
  const isMoreResults = computed(() => {
70
- return !loadingResults && queryMeta?.page < queryMeta?.pages;
69
+ return !loadingResults.value && queryMeta.value?.page < queryMeta.value?.pages;
71
70
  });
72
71
 
73
72
  const nextResultsLabel = computed(() => {
74
- let nextResult = queryMeta?.page * queryMeta?.per_page + 1;
75
- let lastResult = nextResult + queryMeta?.per_page - 1;
73
+ let nextResult = queryMeta.value?.page * queryMeta.value?.per_page + 1;
74
+ let lastResult = nextResult + queryMeta.value?.per_page - 1;
76
75
  return `(${nextResult}-${lastResult})`;
77
76
  });
78
77
 
79
78
  const extendedLayout = computed(() => {
80
- return layout != 'tiny';
79
+ return layout.value != 'tiny';
81
80
  });
82
81
 
83
82
  const loadMore = () => {
@@ -106,7 +105,7 @@ onMounted(() => {
106
105
  });
107
106
 
108
107
  watch(initiatives, () => {
109
- if (initiatives && initiatives.length && !loadingResults) {
108
+ if (initiatives.value && initiatives.value.length && !loadingResults.value) {
110
109
  setupMasonry();
111
110
  }
112
111
  });
@@ -14,9 +14,9 @@
14
14
  </template>
15
15
 
16
16
  <script setup>
17
- import { ref, computed } from 'vue';
17
+ import { ref, toRefs, computed } from 'vue';
18
18
 
19
- const { closeClass, closeText } = defineProps({
19
+ const props = defineProps({
20
20
  closeClass: {
21
21
  type: String,
22
22
  default: 'c-button c-button--primary',
@@ -26,6 +26,7 @@ const { closeClass, closeText } = defineProps({
26
26
  default: 'Comenzar',
27
27
  },
28
28
  });
29
+ const { closeClass, closeText } = toRefs(props);
29
30
 
30
31
  const closedMessage = ref(false);
31
32