@vixoniccom/aniversarios 1.2.3-dev.2 → 1.3.0-dev.0

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.
@@ -0,0 +1,30 @@
1
+ name: Sonarqube Analysis
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - development
7
+ pull_request:
8
+ types: [opened, synchronize, reopened]
9
+
10
+ jobs:
11
+ sonarqube:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with:
16
+ # Disabling shallow clone is recommended for improving relevancy of reporting.
17
+ fetch-depth: 0
18
+
19
+ - name: SonarQube Scan
20
+ uses: sonarsource/sonarqube-scan-action@master
21
+ env:
22
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
23
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
24
+
25
+ - name: SonarQube Quality Gate Check
26
+ uses: sonarsource/sonarqube-quality-gate-action@master
27
+ timeout-minutes: 5
28
+ env:
29
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
30
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [1.3.0-dev.0](https://github.com/Vixonic/store-aniversarios/compare/v1.2.3-dev.2...v1.3.0-dev.0) (2025-07-14)
6
+
7
+
8
+ ### Features
9
+
10
+ * Add support for photo mode in settings and related components ([5eeab44](https://github.com/Vixonic/store-aniversarios/commit/5eeab443f73553239c940941fc6740b41601228b))
11
+
5
12
  ### [1.2.3-dev.2](https://github.com/Vixonic/store-aniversarios/compare/v1.2.3-dev.1...v1.2.3-dev.2) (2025-07-11)
6
13
 
7
14
  ### [1.2.3-dev.1](https://github.com/Vixonic/store-aniversarios/compare/v1.2.3-dev.0...v1.2.3-dev.1) (2025-07-09)
package/build.zip CHANGED
Binary file
@@ -25,6 +25,16 @@ export const dataInputs = [
25
25
  serviceType: 'RexmasAnniversarieService',
26
26
  show: serviceEnabled.rexmasServiceEnabled
27
27
  }),
28
+ new SelectInput({
29
+ id: 'photoMode',
30
+ label: 'Modo de fotos',
31
+ items: [
32
+ { label: 'Zip', value: 'zip' },
33
+ { label: 'En linea', value: 'online' }
34
+ ],
35
+ defaultValue: 'zip',
36
+ description: 'Selecciona el modo de fotos. Por defecto, Zip.'
37
+ }),
28
38
  new SelectAssetKna({
29
39
  id: 'photosZip',
30
40
  label: 'Archivo Zip para fotos',
@@ -40,6 +40,23 @@
40
40
  "type": "service-input",
41
41
  "serviceType": "RexmasAnniversarieService"
42
42
  },
43
+ {
44
+ "id": "photoMode",
45
+ "label": "Modo de fotos",
46
+ "type": "select-input",
47
+ "description": "Selecciona el modo de fotos. Por defecto, Zip.",
48
+ "items": [
49
+ {
50
+ "label": "Zip",
51
+ "value": "zip"
52
+ },
53
+ {
54
+ "label": "En linea",
55
+ "value": "online"
56
+ }
57
+ ],
58
+ "defaultValue": "zip"
59
+ },
43
60
  {
44
61
  "id": "photosZip",
45
62
  "label": "Archivo Zip para fotos",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vixoniccom/aniversarios",
3
3
  "alias": "Aniversarios",
4
- "version": "1.2.3-dev.2",
4
+ "version": "1.3.0-dev.0",
5
5
  "description": "Muestra el día que el trabajador está de aniversario en la empresa.",
6
6
  "main": "main.js",
7
7
  "author": "",
@@ -0,0 +1 @@
1
+ sonar.projectKey=Vixonic_store-aniversarios_cb1129c3-491c-4ada-ac60-75ab0fad0c6a
@@ -20,8 +20,8 @@ export const CircleDate: React.FunctionComponent<Props> = ({ day, month, data })
20
20
  <circle fill={datePrimaryColor} cx='200' cy='200' r='200' />
21
21
  <foreignObject width='400' height='400'>
22
22
  <div style={{ height: 400, width: 400, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
23
- <FormattedText text={AnniveraryDateUtils.getMonth(month, true)} format={Object.assign({}, dateMonthFormat, { fontSize: monthSize })} unit='px' />
24
- <FormattedText text={AnniveraryDateUtils.getZeroLeadedText(day)} format={Object.assign({}, dateDayFormat, { fontSize: daySize })} unit='px' />
23
+ <FormattedText text={AnniveraryDateUtils.getMonth(month, true)} format={{...dateMonthFormat, fontSize: monthSize}} unit='px' />
24
+ <FormattedText text={AnniveraryDateUtils.getZeroLeadedText(day)} format={{...dateDayFormat, fontSize: daySize}} unit='px' />
25
25
  </div>
26
26
  </foreignObject>
27
27
  </g>
@@ -14,11 +14,10 @@ export const OutlineDate: React.FunctionComponent<Props> = ({ day, month, data }
14
14
  const sizeProp = AnniveraryDateUtils.utils(orientation)
15
15
 
16
16
  const parseFormat = (format: any, defaultSize: any) => {
17
- return Object.assign(
18
- {},
19
- format,
20
- { fontSize: format.fontSize || defaultSize }
21
- )
17
+ return {
18
+ ...format,
19
+ fontSize: format.fontSize || defaultSize
20
+ }
22
21
  }
23
22
 
24
23
  const [monthFormatState,] = useState(parseFormat(dateMonthFormat, 20))
@@ -13,11 +13,10 @@ export const TextCalendarDate: React.FunctionComponent<Props> = ({ day, month, d
13
13
  const sizeProp = AnniveraryDateUtils.utils(orientation, '100%')
14
14
 
15
15
  const parseFormat = (format: any, defaultSize: any) => {
16
- return Object.assign(
17
- {},
18
- format,
19
- { fontSize: format.fontSize || defaultSize }
20
- )
16
+ return {
17
+ ...format,
18
+ fontSize: format.fontSize || defaultSize
19
+ }
21
20
  }
22
21
 
23
22
  const [monthFormatState,] = useState(parseFormat(dateMonthFormat, 20))
@@ -12,14 +12,6 @@ const itemStyles = {
12
12
  outlines: OutlineDate
13
13
  }
14
14
 
15
- interface itemStyles {
16
- calendarFlat: string
17
- calendarText: string
18
- circle: string
19
- text: string
20
- outlines: string
21
- }
22
-
23
15
  interface Props {
24
16
  style: keyof typeof itemStyles,
25
17
  day: number,
@@ -14,11 +14,11 @@ export const ClassicItem: React.FunctionComponent<Props> = ({ anniversary, data
14
14
  const { parameters, downloadsPath } = data
15
15
  const { orientation, separatorColor, separatorWidth, imageSize } = parameters
16
16
  const [margins, setMargins] = useState(parseBorderMargin(parameters.itemMargins))
17
- const [state, setState] = useState(Object.assign({}, parseParameters(parameters)))
17
+ const [state, setState] = useState({...parseParameters(parameters)})
18
18
 
19
19
  useEffect(() => {
20
20
  setMargins(parseBorderMargin(parameters.itemMargins))
21
- setState(Object.assign({}, parseParameters(parameters)))
21
+ setState({...parseParameters(parameters)})
22
22
  }, [])
23
23
 
24
24
  const separatorProps = {
@@ -1,5 +1,3 @@
1
- import React from 'react'
2
-
3
1
  interface Props {
4
2
  order: number | undefined
5
3
  size: number | undefined
@@ -12,12 +10,12 @@ export const Separator = ({ order, size, color, orientation, margins }: Props) =
12
10
  const getSizeStyle = (orientation: any, size: any) => {
13
11
  if (orientation === 'h') {
14
12
  return {
15
- width: size || 0,
13
+ width: size ?? 0,
16
14
  height: '100%'
17
15
  }
18
16
  } else {
19
17
  return {
20
- height: size || 0,
18
+ height: size ?? 0,
21
19
  width: '100%'
22
20
  }
23
21
  }
@@ -1,11 +1,20 @@
1
1
  export const utils = (orientation: string, size: number) => {
2
2
  const sizeAttr = orientation === 'v' ? 'width' : 'height'
3
- const percentage = size ? `${size}` : orientation === 'v' ? '40%' : '80%'
3
+ let percentage: string
4
+ if (size) {
5
+ percentage = `${size}%`
6
+ } else {
7
+ percentage = orientation === 'v' ? '40%' : '80%'
8
+ }
4
9
  return { [sizeAttr]: percentage }
5
10
  }
6
11
 
7
12
  export const parseBorderMargin = (marginString: any) => {
8
- const pattern = /(( )?[+-]?[0-9]+.?([0-9]+)?(px|em|ex|%|in|cm|mm|pt|pc))?/g
13
+ const numberPattern = '[+-]?[0-9]+\\.?[0-9]*'
14
+ const unitPattern = '(px|em|ex|%|in|cm|mm|pt|pc)'
15
+ const spacePattern = '( )?'
16
+ const fullPattern = `(${spacePattern}${numberPattern}${unitPattern})?`
17
+ const pattern = new RegExp(fullPattern, 'g')
9
18
  const match = marginString ? marginString.match(pattern) : ['']
10
19
 
11
20
  switch (match.length) {
@@ -22,11 +31,11 @@ const parseElementStyles = (margin: string, position: number, defaultPosition: n
22
31
  const { orientation, separator } = parameters
23
32
  const marginAttr = orientation === 'v' ? 'marginBottom' : 'marginRight'
24
33
  const sizeAttr = orientation === 'v' ? 'width' : 'height'
25
- const pos = position !== undefined ? position : defaultPosition
34
+ const pos = position ?? defaultPosition
26
35
  return {
27
36
  order: pos,
28
37
  [sizeAttr]: '100%',
29
- [marginAttr]: margin !== undefined && margin !== '' ? `${margin}%` : pos === 3 || separator === true ? 0 : '4%',
38
+ [marginAttr]: getMarginValue(margin, pos, separator)
30
39
  }
31
40
  }
32
41
 
@@ -37,39 +46,45 @@ export const parseParameters = (parameters: any) => {
37
46
 
38
47
  return {
39
48
  imageEnabled: parameters.imageEnabled,
40
- imageStyle: Object.assign(
41
- {
42
- flexShrink: 0,
43
- display: 'flex',
44
- justifyContent: imageAlignment,
45
- alignItems: imageAlignment,
46
- },
47
- parseElementStyles(parameters.imageMargin, parameters.imagePosition, 1, parameters)
48
- ),
49
+ imageStyle: {
50
+ flexShrink: 0,
51
+ display: 'flex',
52
+ justifyContent: imageAlignment,
53
+ alignItems: imageAlignment,
54
+ ...parseElementStyles(parameters.imageMargin, parameters.imagePosition, 1, parameters)
55
+ },
49
56
  descriptionEnabled: parameters.descriptionEnabled,
50
57
  optionalEnabled: parameters.optionalEnabled,
51
- textStyle: Object.assign(
52
- { display: 'flex', flexDirection: 'column', justifyContent: textAlignment, flex: 1 },
53
- parseElementStyles(parameters.textMargin, parameters.textPosition, 2, parameters)
54
- ),
58
+ textStyle: {
59
+ display: 'flex',
60
+ flexDirection: 'column',
61
+ justifyContent: textAlignment,
62
+ flex: 1,
63
+ ...parseElementStyles(parameters.textMargin, parameters.textPosition, 2, parameters)
64
+ },
55
65
  dateEnabled: parameters.dateEnabled,
56
- dateStyle: Object.assign(
57
- {
58
- display: 'flex',
59
- justifyContent: dateAlignment,
60
- alignItems: dateAlignment,
61
- flexShrink: 0,
62
- },
63
- parseElementStyles(parameters.dateMargin, parameters.datePosition, 3, parameters)
64
- ),
66
+ dateStyle: {
67
+ display: 'flex',
68
+ justifyContent: dateAlignment,
69
+ alignItems: dateAlignment,
70
+ flexShrink: 0,
71
+ ...parseElementStyles(parameters.dateMargin, parameters.datePosition, 3, parameters)
72
+ },
65
73
  }
66
74
  }
67
75
 
68
76
  export const getPhotoUrl = (filename: string, parameters: VixonicParameters, downloadsPath: string) => {
69
- const mode = parameters.photosMode
70
- if (mode === 'zip' && parameters.photosZip && parameters.photosZip.filename !== undefined) {
77
+ const mode = parameters.photoMode
78
+ if (mode === 'zip' && parameters.photosZip?.filename !== undefined) {
71
79
  return downloadsPath + '/' + parameters.photosZip.filename.replace('.zip', '/') + filename
72
80
  } else {
73
81
  return filename
74
82
  }
75
83
  }
84
+
85
+ const getMarginValue = (margin: string, pos: number, separator?: boolean): string | number => {
86
+ if (margin !== undefined && margin !== '') {
87
+ return `${margin}%`;
88
+ }
89
+ return pos === 3 || separator === true ? 0 : '4%';
90
+ };
@@ -25,7 +25,7 @@ interface Props {
25
25
  export const FormattedText: React.FunctionComponent<Props> = ({ text, format, maxChar, lineHeight, style, unit, paddingBottom, paddingTop }) => {
26
26
  const trimText = (text: any, maxChar: any) => {
27
27
  const isValid = maxChar && maxChar >= 3
28
- if (isValid && (text && text.length > maxChar) || false) {
28
+ if (isValid && (text && text.length > maxChar)) {
29
29
  const returnText = text.substring(0, maxChar - 3)
30
30
  returnText.substr(-1, 3)
31
31
  return `${returnText.trim()}...`
@@ -35,7 +35,7 @@ export const FormattedText: React.FunctionComponent<Props> = ({ text, format, ma
35
35
 
36
36
  const checkNested = (obj: any, path: string): boolean => {
37
37
  return path.split('.').every(segment => {
38
- if (obj && obj.hasOwnProperty(segment)) {
38
+ if (obj?.hasOwnProperty(segment)) {
39
39
  obj = obj[segment]
40
40
  return true
41
41
  }
@@ -52,10 +52,11 @@ export const FormattedText: React.FunctionComponent<Props> = ({ text, format, ma
52
52
  }
53
53
 
54
54
  const renderText = maxChar ? trimText(text, maxChar) : text
55
- const containerStyle = Object.assign({
55
+ const containerStyle = {
56
56
  display: 'inline-flex',
57
- justifyContent: getHorizontalAlignment(format.alignment)
58
- }, style)
57
+ justifyContent: getHorizontalAlignment(format.alignment),
58
+ ...(style as any)
59
+ }
59
60
 
60
61
  return (
61
62
  <div style={containerStyle}>
@@ -16,9 +16,21 @@ interface Props {
16
16
  style: any
17
17
  }
18
18
 
19
+
20
+
19
21
  export const Item = ({ width, height, containerData, verticalGap, horizontalGap, children, style }: Props) => {
20
22
  const itemRef = useRef(null)
21
23
 
24
+ let topPosition = '0';
25
+ if (containerData.ic_rowIndex !== 0) {
26
+ topPosition = verticalGap ? `${verticalGap * containerData.ic_rowIndex}%` : '0';
27
+ }
28
+
29
+ let leftPadding = '0'
30
+ if (containerData.ic_columnIndex !== 0) {
31
+ leftPadding = horizontalGap ? `${horizontalGap}%` : '0';
32
+ }
33
+
22
34
  return (
23
35
  <div ref={itemRef}
24
36
  style={{
@@ -29,13 +41,9 @@ export const Item = ({ width, height, containerData, verticalGap, horizontalGap,
29
41
  justifyContent: aligments['center'],
30
42
  width: width,
31
43
  height: height,
32
- top: containerData.ic_rowIndex === 0
33
- ? '0'
34
- : verticalGap ? `${verticalGap * containerData.ic_rowIndex}%` : '0',
35
- paddingLeft: containerData.ic_columnIndex === 0
36
- ? '0'
37
- : horizontalGap ? `${horizontalGap}%` : '0'
38
- , ...style
44
+ top: topPosition,
45
+ paddingLeft: leftPadding,
46
+ ...style
39
47
  }}
40
48
  >
41
49
  {React.cloneElement(children, containerData)}
@@ -96,31 +96,27 @@ export class AnimationController {
96
96
  autoplay: false,
97
97
  })
98
98
  animation.add(
99
- Object.assign(
100
- {
101
- targets: els,
102
- duration: this.speed,
103
- delay: function (_el: any, i: any, _l: any) {
104
- return i * self.stagger
105
- },
99
+ {
100
+ targets: els,
101
+ duration: this.speed,
102
+ delay: function (_el: any, i: any, _l: any) {
103
+ return i * self.stagger
106
104
  },
107
- this.mode.in
108
- )
105
+ ...this.mode.in
106
+ }
109
107
  )
110
108
  animation.add(
111
- Object.assign(
112
- {
113
- targets: els,
114
- duration: this.speed,
115
- delay: function (_el: any, _i: any, _l: any) {
116
- return _i * self.stagger
117
- },
118
- complete: () => {
119
- finished()
120
- },
109
+ {
110
+ targets: els,
111
+ duration: this.speed,
112
+ delay: function (_el: any, _i: any, _l: any) {
113
+ return _i * self.stagger
121
114
  },
122
- this.mode.out
123
- ),
115
+ complete: () => {
116
+ finished()
117
+ },
118
+ ...this.mode.out
119
+ },
124
120
  `+=${offset}`
125
121
  )
126
122
  animation.play()
@@ -21,7 +21,7 @@ export const Render = ({ start, appData, anniversaries }: Props) => {
21
21
  animationTime,
22
22
  } = parameters
23
23
 
24
- const backgroundImageState = backgroundImage && backgroundImage.filename
24
+ const backgroundImageState = backgroundImage?.filename
25
25
  ? `url("${downloadsPath}/${backgroundImage.filename}")` : ''
26
26
 
27
27
  const anniversaryItems = anniversaries.map((anniversary: Anniversary) => {
@@ -5,5 +5,5 @@ declare type VixonicData = {
5
5
  }
6
6
 
7
7
  declare type VixonicParameters = Partial<{
8
- displayService: 'AnniversaryAppService' | 'RexmasAnniversarieService', documentService: { id: string }, rexmasService: { id: string }, photosZip: {id?: string, filename?: string, extension?: string}, updateTime: 600000 | 1800000 | 3600000 | 21600000 | 43200000 | 86400000 | 604800000, defaultMessage: string, defaultMessageFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, orientation: 'h' | 'v', animationMode: 'fade' | 'slideRight' | 'slideLeft', animationSpeed: 2 | 1.5 | 1, animationOrder: boolean, animationTime: number, containerColumns: number, containerColumnsGap: number, containerRows: number, containerRowsGap: number, backgroundImage: {id?: string, filename?: string, extension?: string}, padding: string, textPosition: 1 | 2 | 3, textAlignment: 'start' | 'center' | 'end', nameFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, nameMaxChar: number, textMargin: string, descriptionEnabled: boolean, descriptionFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, descriptionMaxChar: number, optionalEnabled: boolean, optionalFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, imageEnabled: boolean, imagePosition: 1 | 2 | 3, imageAlignment: 'start' | 'center' | 'end', imageStyle: 'normal' | 'rounded' | 'circle', imageMargin: string, imageSize: number, dateEnabled: boolean, datePosition: 1 | 2 | 3, dateAlignment: 'start' | 'center' | 'end', dateStyle: 'calendarFlat' | 'calendarText' | 'circle' | 'text' | 'outlines', dateDayFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, dateMonthFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, abbreviatedMonths: boolean, datePrimaryColor: string, dateMargin: string, separator: boolean, separatorWidth: number, separatorColor: string, itemMargins: string
8
+ displayService: 'AnniversaryAppService' | 'RexmasAnniversarieService', documentService: { id: string }, rexmasService: { id: string }, photoMode: 'zip' | 'online', photosZip: {id?: string, filename?: string, extension?: string}, updateTime: 600000 | 1800000 | 3600000 | 21600000 | 43200000 | 86400000 | 604800000, defaultMessage: string, defaultMessageFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, orientation: 'h' | 'v', animationMode: 'fade' | 'slideRight' | 'slideLeft', animationSpeed: 2 | 1.5 | 1, animationOrder: boolean, animationTime: number, containerColumns: number, containerColumnsGap: number, containerRows: number, containerRowsGap: number, backgroundImage: {id?: string, filename?: string, extension?: string}, padding: string, textPosition: 1 | 2 | 3, textAlignment: 'start' | 'center' | 'end', nameFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, nameMaxChar: number, textMargin: string, descriptionEnabled: boolean, descriptionFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, descriptionMaxChar: number, optionalEnabled: boolean, optionalFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, imageEnabled: boolean, imagePosition: 1 | 2 | 3, imageAlignment: 'start' | 'center' | 'end', imageStyle: 'normal' | 'rounded' | 'circle', imageMargin: string, imageSize: number, dateEnabled: boolean, datePosition: 1 | 2 | 3, dateAlignment: 'start' | 'center' | 'end', dateStyle: 'calendarFlat' | 'calendarText' | 'circle' | 'text' | 'outlines', dateDayFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, dateMonthFormat: { fontSize?: number, fontColor?: string, alignment?: { horizontal?: 'left' | 'right' | 'center' }, font?: { filename: string, id: string, __isAsset: true } }, abbreviatedMonths: boolean, datePrimaryColor: string, dateMargin: string, separator: boolean, separatorWidth: number, separatorColor: string, itemMargins: string
9
9
  }>