feat: Ristrutturazione completa del progetto

This commit is contained in:
Maicol Battistini 2023-04-20 20:00:38 +02:00
parent 805cc35334
commit 2ea9606a38
No known key found for this signature in database
224 changed files with 9985 additions and 15363 deletions

View File

@ -1,16 +0,0 @@
{
"directory": [
"resources/js"
],
"delete": true,
"exclude": [
"_material.ts",
"app.ts",
"styles.ts"
],
"include": [
".(?<!d\\.)(ts|tsx)$"
],
"location": "all",
"singleQuotes": true
}

View File

@ -31,61 +31,12 @@ ij_css_hex_color_upper_case = false
ij_css_keep_blank_lines_in_code = 2 ij_css_keep_blank_lines_in_code = 2
ij_css_keep_indents_on_empty_lines = false ij_css_keep_indents_on_empty_lines = false
ij_css_keep_single_line_blocks = false ij_css_keep_single_line_blocks = false
ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow ij_css_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
ij_css_space_after_colon = true ij_css_space_after_colon = true
ij_css_space_before_opening_brace = true ij_css_space_before_opening_brace = true
ij_css_use_double_quotes = true ij_css_use_double_quotes = true
ij_css_value_alignment = do_not_align ij_css_value_alignment = do_not_align
[*.feature]
indent_size = 2
ij_gherkin_keep_indents_on_empty_lines = false
[*.less]
indent_size = 2
ij_less_align_closing_brace_with_properties = false
ij_less_blank_lines_around_nested_selector = 1
ij_less_blank_lines_between_blocks = 1
ij_less_block_comment_add_space = false
ij_less_brace_placement = 0
ij_less_enforce_quotes_on_format = false
ij_less_hex_color_long_format = false
ij_less_hex_color_lower_case = false
ij_less_hex_color_short_format = false
ij_less_hex_color_upper_case = false
ij_less_keep_blank_lines_in_code = 2
ij_less_keep_indents_on_empty_lines = false
ij_less_keep_single_line_blocks = false
ij_less_line_comment_add_space = false
ij_less_line_comment_at_first_column = false
ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_less_space_after_colon = true
ij_less_space_before_opening_brace = true
ij_less_use_double_quotes = true
ij_less_value_alignment = 0
[*.sass]
indent_size = 2
ij_sass_align_closing_brace_with_properties = false
ij_sass_blank_lines_around_nested_selector = 1
ij_sass_blank_lines_between_blocks = 1
ij_sass_brace_placement = 0
ij_sass_enforce_quotes_on_format = false
ij_sass_hex_color_long_format = false
ij_sass_hex_color_lower_case = false
ij_sass_hex_color_short_format = false
ij_sass_hex_color_upper_case = false
ij_sass_keep_blank_lines_in_code = 2
ij_sass_keep_indents_on_empty_lines = false
ij_sass_keep_single_line_blocks = false
ij_sass_line_comment_add_space = false
ij_sass_line_comment_at_first_column = false
ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_sass_space_after_colon = true
ij_sass_space_before_opening_brace = true
ij_sass_use_double_quotes = true
ij_sass_value_alignment = 0
[*.scss] [*.scss]
ij_scss_align_closing_brace_with_properties = false ij_scss_align_closing_brace_with_properties = false
ij_scss_blank_lines_around_nested_selector = 1 ij_scss_blank_lines_around_nested_selector = 1
@ -102,49 +53,12 @@ ij_scss_keep_indents_on_empty_lines = false
ij_scss_keep_single_line_blocks = false ij_scss_keep_single_line_blocks = false
ij_scss_line_comment_add_space = false ij_scss_line_comment_add_space = false
ij_scss_line_comment_at_first_column = false ij_scss_line_comment_at_first_column = false
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow ij_scss_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
ij_scss_space_after_colon = true ij_scss_space_after_colon = true
ij_scss_space_before_opening_brace = true ij_scss_space_before_opening_brace = true
ij_scss_use_double_quotes = true ij_scss_use_double_quotes = true
ij_scss_value_alignment = 0 ij_scss_value_alignment = 0
[*.styl]
indent_size = 2
ij_stylus_align_closing_brace_with_properties = false
ij_stylus_blank_lines_around_nested_selector = 1
ij_stylus_blank_lines_between_blocks = 1
ij_stylus_brace_placement = 0
ij_stylus_enforce_quotes_on_format = false
ij_stylus_hex_color_long_format = false
ij_stylus_hex_color_lower_case = false
ij_stylus_hex_color_short_format = false
ij_stylus_hex_color_upper_case = false
ij_stylus_keep_blank_lines_in_code = 2
ij_stylus_keep_indents_on_empty_lines = false
ij_stylus_keep_single_line_blocks = false
ij_stylus_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_stylus_space_after_colon = true
ij_stylus_space_before_opening_brace = true
ij_stylus_use_double_quotes = true
ij_stylus_value_alignment = 0
[*.twig]
ij_twig_keep_indents_on_empty_lines = false
ij_twig_spaces_inside_comments_delimiters = true
ij_twig_spaces_inside_delimiters = true
ij_twig_spaces_inside_variable_delimiters = true
[*.vue]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 4
ij_vue_indent_children_of_top_level = template
ij_vue_interpolation_new_line_after_start_delimiter = true
ij_vue_interpolation_new_line_before_end_delimiter = true
ij_vue_interpolation_wrap = off
ij_vue_keep_indents_on_empty_lines = false
ij_vue_spaces_within_interpolation_expressions = true
[.editorconfig] [.editorconfig]
ij_editorconfig_align_group_field_declarations = false ij_editorconfig_align_group_field_declarations = false
ij_editorconfig_space_after_colon = false ij_editorconfig_space_after_colon = false
@ -152,6 +66,7 @@ ij_editorconfig_space_after_comma = true
ij_editorconfig_space_before_colon = false ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true ij_editorconfig_spaces_around_assignment_operators = true
max_line_length = 300
[machete] [machete]
indent_style = tab indent_style = tab
@ -179,8 +94,8 @@ ij_xml_text_wrap = normal
[{*.ats,*.cts,*.mts,*.ts,*.tsx}] [{*.ats,*.cts,*.mts,*.ts,*.tsx}]
indent_size = 2 indent_size = 2
max_line_length = 100
tab_width = 2 tab_width = 2
max_line_length = 200
ij_continuation_indent_size = 2 ij_continuation_indent_size = 2
ij_wrap_on_typing = true ij_wrap_on_typing = true
ij_typescript_align_imports = false ij_typescript_align_imports = false
@ -201,7 +116,7 @@ ij_typescript_array_initializer_wrap = off
ij_typescript_assignment_wrap = off ij_typescript_assignment_wrap = off
ij_typescript_binary_operation_sign_on_next_line = false ij_typescript_binary_operation_sign_on_next_line = false
ij_typescript_binary_operation_wrap = off ij_typescript_binary_operation_wrap = off
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/** ij_typescript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/**
ij_typescript_blank_lines_after_imports = 1 ij_typescript_blank_lines_after_imports = 1
ij_typescript_blank_lines_around_class = 1 ij_typescript_blank_lines_around_class = 1
ij_typescript_blank_lines_around_field = 0 ij_typescript_blank_lines_around_field = 0
@ -367,7 +282,6 @@ ij_shell_use_google_code_style = false
[{*.cjs,*.js}] [{*.cjs,*.js}]
indent_size = 2 indent_size = 2
max_line_length = 100
tab_width = 2 tab_width = 2
ij_continuation_indent_size = 2 ij_continuation_indent_size = 2
ij_wrap_on_typing = true ij_wrap_on_typing = true
@ -389,7 +303,7 @@ ij_javascript_array_initializer_wrap = off
ij_javascript_assignment_wrap = off ij_javascript_assignment_wrap = off
ij_javascript_binary_operation_sign_on_next_line = false ij_javascript_binary_operation_sign_on_next_line = false
ij_javascript_binary_operation_wrap = off ij_javascript_binary_operation_wrap = off
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/** ij_javascript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/**
ij_javascript_blank_lines_after_imports = 1 ij_javascript_blank_lines_after_imports = 1
ij_javascript_blank_lines_around_class = 1 ij_javascript_blank_lines_around_class = 1
ij_javascript_blank_lines_around_field = 0 ij_javascript_blank_lines_around_field = 0
@ -781,23 +695,23 @@ ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false ij_json_wrap_long_lines = false
[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}] [{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3 ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3
ij_html_align_attributes = true ij_html_align_attributes = true
ij_html_align_text = false ij_html_align_text = false
ij_html_attribute_wrap = normal ij_html_attribute_wrap = normal
ij_html_block_comment_add_space = false ij_html_block_comment_add_space = false
ij_html_block_comment_at_first_column = true ij_html_block_comment_at_first_column = true
ij_html_do_not_align_children_of_min_lines = 0 ij_html_do_not_align_children_of_min_lines = 0
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p
ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot
ij_html_enforce_quotes = false ij_html_enforce_quotes = false
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var
ij_html_keep_blank_lines = 2 ij_html_keep_blank_lines = 2
ij_html_keep_indents_on_empty_lines = false ij_html_keep_indents_on_empty_lines = false
ij_html_keep_line_breaks = true ij_html_keep_line_breaks = true
ij_html_keep_line_breaks_in_text = true ij_html_keep_line_breaks_in_text = true
ij_html_keep_whitespaces = false ij_html_keep_whitespaces = false
ij_html_keep_whitespaces_inside = span,pre,textarea ij_html_keep_whitespaces_inside = span, pre, textarea
ij_html_line_comment_at_first_column = true ij_html_line_comment_at_first_column = true
ij_html_new_line_after_last_attribute = never ij_html_new_line_after_last_attribute = never
ij_html_new_line_before_first_attribute = never ij_html_new_line_before_first_attribute = never
@ -808,11 +722,6 @@ ij_html_space_around_equality_in_attribute = false
ij_html_space_inside_empty_tag = false ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal ij_html_text_wrap = normal
[{*.http,*.rest}]
indent_size = 0
ij_continuation_indent_size = 4
ij_http request_call_parameters_wrap = normal
[{*.markdown,*.md}] [{*.markdown,*.md}]
ij_markdown_force_one_space_after_blockquote_symbol = true ij_markdown_force_one_space_after_blockquote_symbol = true
ij_markdown_force_one_space_after_header_symbol = true ij_markdown_force_one_space_after_header_symbol = true
@ -831,102 +740,6 @@ ij_markdown_min_lines_between_paragraphs = 1
ij_markdown_wrap_text_if_long = true ij_markdown_wrap_text_if_long = true
ij_markdown_wrap_text_inside_blockquotes = true ij_markdown_wrap_text_inside_blockquotes = true
[{*.ps1,*.psd1,*.psm1}]
max_line_length = 115
ij_powershell_align_multiline_binary_operation = false
ij_powershell_align_multiline_chained_methods = false
ij_powershell_align_multiline_for = true
ij_powershell_align_multiline_parameters = true
ij_powershell_align_multiline_parameters_in_calls = false
ij_powershell_binary_operation_wrap = off
ij_powershell_block_brace_style = next_line
ij_powershell_call_parameters_new_line_after_left_paren = false
ij_powershell_call_parameters_right_paren_on_new_line = false
ij_powershell_call_parameters_wrap = off
ij_powershell_catch_on_new_line = true
ij_powershell_class_annotation_wrap = split_into_lines
ij_powershell_class_brace_style = next_line
ij_powershell_else_on_new_line = true
ij_powershell_field_annotation_wrap = off
ij_powershell_finally_on_new_line = true
ij_powershell_for_statement_new_line_after_left_paren = false
ij_powershell_for_statement_right_paren_on_new_line = false
ij_powershell_for_statement_wrap = off
ij_powershell_keep_blank_lines_in_code = 2
ij_powershell_keep_first_column_comment = true
ij_powershell_keep_line_breaks = true
ij_powershell_keep_simple_blocks_in_one_line = false
ij_powershell_keep_simple_classes_in_one_line = false
ij_powershell_keep_simple_lambdas_in_one_line = true
ij_powershell_keep_simple_methods_in_one_line = false
ij_powershell_method_annotation_wrap = split_into_lines
ij_powershell_method_brace_style = next_line
ij_powershell_method_call_chain_wrap = off
ij_powershell_method_parameters_new_line_after_left_paren = false
ij_powershell_method_parameters_right_paren_on_new_line = false
ij_powershell_method_parameters_wrap = off
ij_powershell_parameter_annotation_wrap = off
ij_powershell_parentheses_expression_new_line_after_left_paren = false
ij_powershell_parentheses_expression_right_paren_on_new_line = false
ij_powershell_space_after_colon = true
ij_powershell_space_after_comma = true
ij_powershell_space_after_for_semicolon = true
ij_powershell_space_after_type_cast = false
ij_powershell_space_before_annotation_parameter_list = false
ij_powershell_space_before_array_initializer_left_brace = true
ij_powershell_space_before_catch_keyword = true
ij_powershell_space_before_catch_left_brace = true
ij_powershell_space_before_class_left_brace = true
ij_powershell_space_before_colon = true
ij_powershell_space_before_comma = false
ij_powershell_space_before_do_left_brace = true
ij_powershell_space_before_else_keyword = true
ij_powershell_space_before_else_left_brace = true
ij_powershell_space_before_finally_keyword = true
ij_powershell_space_before_finally_left_brace = true
ij_powershell_space_before_for_left_brace = true
ij_powershell_space_before_for_parentheses = true
ij_powershell_space_before_for_semicolon = false
ij_powershell_space_before_if_left_brace = true
ij_powershell_space_before_if_parentheses = true
ij_powershell_space_before_method_call_parentheses = false
ij_powershell_space_before_method_left_brace = true
ij_powershell_space_before_method_parentheses = false
ij_powershell_space_before_switch_left_brace = true
ij_powershell_space_before_switch_parentheses = true
ij_powershell_space_before_try_left_brace = true
ij_powershell_space_before_while_keyword = true
ij_powershell_space_before_while_left_brace = true
ij_powershell_space_before_while_parentheses = true
ij_powershell_space_within_empty_method_call_parentheses = false
ij_powershell_space_within_empty_method_parentheses = false
ij_powershell_spaces_around_additive_operators = true
ij_powershell_spaces_around_assignment_operators = true
ij_powershell_spaces_around_bitwise_operators = true
ij_powershell_spaces_around_logical_operators = true
ij_powershell_spaces_around_method_ref_dbl_colon = false
ij_powershell_spaces_around_multiplicative_operators = true
ij_powershell_spaces_around_relational_operators = true
ij_powershell_spaces_around_unary_operator = false
ij_powershell_spaces_within_annotation_parentheses = false
ij_powershell_spaces_within_braces = true
ij_powershell_spaces_within_brackets = false
ij_powershell_spaces_within_cast_parentheses = false
ij_powershell_spaces_within_for_parentheses = false
ij_powershell_spaces_within_if_parentheses = false
ij_powershell_spaces_within_method_call_parentheses = false
ij_powershell_spaces_within_method_parentheses = false
ij_powershell_spaces_within_parentheses = false
ij_powershell_spaces_within_switch_parentheses = false
ij_powershell_spaces_within_while_parentheses = false
ij_powershell_special_else_if_treatment = true
ij_powershell_while_on_new_line = false
ij_powershell_wrap_first_method_in_call_chain = false
ij_powershell_wrap_long_lines = false
[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}]
ij_toml_keep_indents_on_empty_lines = false
[{*.yaml,*.yml}] [{*.yaml,*.yml}]
indent_size = 2 indent_size = 2
ij_yaml_align_values_properties = do_not_align ij_yaml_align_values_properties = do_not_align
@ -938,4 +751,4 @@ ij_yaml_keep_line_breaks = true
ij_yaml_sequence_on_new_line = false ij_yaml_sequence_on_new_line = false
ij_yaml_space_before_colon = false ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true ij_yaml_spaces_within_brackets = true

View File

@ -2,5 +2,8 @@ root: true
extends: extends:
- '@maicol07' - '@maicol07'
rules: rules:
import/export: 'off' import/prefer-default-export: 'warn'
import/no-cycle: 'off' max-len:
- "error"
- "code": 200
consistent-return: 'off'

2
.gitignore vendored
View File

@ -4,6 +4,7 @@ composer.lock
composer.local.json composer.local.json
public/build public/build
public/modules public/modules
public/vendor
.idea/inertia.xml .idea/inertia.xml
.idea/git_toolbox_prj.xml .idea/git_toolbox_prj.xml
.php-cs-fixer.cache .php-cs-fixer.cache
@ -17,6 +18,7 @@ _ide_helper_models.php
.idea/sshConfigs.xml .idea/sshConfigs.xml
.idea/watcherTasks.xml .idea/watcherTasks.xml
.idea/webServers.xml .idea/webServers.xml
storage/dotenv-editor/backups
# Created by https://www.toptal.com/developers/gitignore/api/laravel,composer,phpstorm,phpstorm+iml # Created by https://www.toptal.com/developers/gitignore/api/laravel,composer,phpstorm,phpstorm+iml
# Edit at https://www.toptal.com/developers/gitignore?templates=laravel,composer,phpstorm,phpstorm+iml # Edit at https://www.toptal.com/developers/gitignore?templates=laravel,composer,phpstorm,phpstorm+iml

6
.idea/GitLink.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="uk.co.ben_gibson.git.link.SettingsState">
<option name="host" value="72037fcc-cb9c-4c22-960a-ffe73fd5e229" />
</component>
</project>

View File

@ -59,6 +59,7 @@
<data directive="@endunless" /> <data directive="@endunless" />
<data directive="@endverbatim" /> <data directive="@endverbatim" />
<data directive="@endwhile" /> <data directive="@endwhile" />
<data directive="@entangle" injection="true" prefix="&lt;?php \print_r(" suffix="); ?&gt;" />
<data directive="@env" injection="true" prefix="&lt;?php if(app()-&gt;environment(" suffix=")): ?&gt;" /> <data directive="@env" injection="true" prefix="&lt;?php if(app()-&gt;environment(" suffix=")): ?&gt;" />
<data directive="@error" injection="true" prefix="&lt;?php $__errorArgs = [" suffix="];&#10;$__bag = $errors-&gt;getBag($__errorArgs[1] ?? 'default');&#10;if ($__bag-&gt;has($__errorArgs[0])) :&#10;if (isset($message)) { $__messageOriginal = $message; }&#10;$message = $__bag-&gt;first($__errorArgs[0]); ?&gt;" /> <data directive="@error" injection="true" prefix="&lt;?php $__errorArgs = [" suffix="];&#10;$__bag = $errors-&gt;getBag($__errorArgs[1] ?? 'default');&#10;if ($__bag-&gt;has($__errorArgs[0])) :&#10;if (isset($message)) { $__messageOriginal = $message; }&#10;$message = $__bag-&gt;first($__errorArgs[0]); ?&gt;" />
<data directive="@extends" injection="true" prefix="&lt;?php echo $__env-&gt;make(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))-&gt;render(); ?&gt;" /> <data directive="@extends" injection="true" prefix="&lt;?php echo $__env-&gt;make(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))-&gt;render(); ?&gt;" />
@ -79,6 +80,9 @@
<data directive="@js" injection="true" prefix="&lt;?php _bladeDirective(" suffix="); ?&gt;" /> <data directive="@js" injection="true" prefix="&lt;?php _bladeDirective(" suffix="); ?&gt;" />
<data directive="@json" injection="true" prefix="&lt;?php echo json_encode(" suffix=") ?&gt;" /> <data directive="@json" injection="true" prefix="&lt;?php echo json_encode(" suffix=") ?&gt;" />
<data directive="@lang" injection="true" prefix="&lt;?php echo app('translator')-&gt;get(" suffix="); ?&gt;" /> <data directive="@lang" injection="true" prefix="&lt;?php echo app('translator')-&gt;get(" suffix="); ?&gt;" />
<data directive="@livewire" injection="true" prefix="&lt;?php \Livewire\Livewire::mount(" suffix="); ?&gt;" />
<data directive="@livewireScripts" />
<data directive="@livewireStyles" />
<data directive="@method" injection="true" prefix="&lt;?php echo method_field(" suffix="); ?&gt;" /> <data directive="@method" injection="true" prefix="&lt;?php echo method_field(" suffix="); ?&gt;" />
<data directive="@once" /> <data directive="@once" />
<data directive="@overwrite" /> <data directive="@overwrite" />
@ -97,8 +101,11 @@
<data directive="@slot" injection="true" prefix="&lt;?php $__env-&gt;slot(" suffix="); ?&gt;" /> <data directive="@slot" injection="true" prefix="&lt;?php $__env-&gt;slot(" suffix="); ?&gt;" />
<data directive="@stack" injection="true" prefix="&lt;?php echo $__env-&gt;yieldPushContent(" suffix="); ?&gt;" /> <data directive="@stack" injection="true" prefix="&lt;?php echo $__env-&gt;yieldPushContent(" suffix="); ?&gt;" />
<data directive="@stop" /> <data directive="@stop" />
<data directive="@style" injection="true" prefix="class=&quot;&lt;?php echo \Illuminate\Support\Arr::toCssStyles(" suffix=")?&gt;&quot;" />
<data directive="@svg" injection="true" prefix="&lt;?php echo e(svg(" suffix=")); ?&gt;" />
<data directive="@switch" injection="true" prefix="&lt;?php switch(" suffix="): ?&gt;" /> <data directive="@switch" injection="true" prefix="&lt;?php switch(" suffix="): ?&gt;" />
<data directive="@tag" injection="true" prefix="&lt;?php echo vite_tag(" suffix="); ?&gt;" /> <data directive="@tag" injection="true" prefix="&lt;?php echo vite_tag(" suffix="); ?&gt;" />
<data directive="@this" />
<data directive="@unless" injection="true" prefix="&lt;?php if (! (" suffix=")): ?&gt;" /> <data directive="@unless" injection="true" prefix="&lt;?php if (! (" suffix=")): ?&gt;" />
<data directive="@unset" injection="true" prefix="&lt;?php unset(" suffix="); ?&gt;" /> <data directive="@unset" injection="true" prefix="&lt;?php unset(" suffix="); ?&gt;" />
<data directive="@verbatim" /> <data directive="@verbatim" />

View File

@ -1,6 +1,7 @@
<component name="ProjectCodeStyleConfiguration"> <component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" /> <option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="140" />
<JSCodeStyleSettings version="0"> <JSCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" /> <option name="USE_DOUBLE_QUOTES" value="false" />
@ -49,13 +50,14 @@
<codeStyleSettings language="SCSS"> <codeStyleSettings language="SCSS">
<indentOptions> <indentOptions>
<option name="INDENT_SIZE" value="4" /> <option name="INDENT_SIZE" value="4" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions> </indentOptions>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="TypeScript"> <codeStyleSettings language="TypeScript">
<option name="RIGHT_MARGIN" value="100" /> <option name="RIGHT_MARGIN" value="200" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" /> <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" /> <option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="METHOD_CALL_CHAIN_WRAP" value="2" /> <option name="METHOD_CALL_CHAIN_WRAP" value="5" />
<option name="IF_BRACE_FORCE" value="1" /> <option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" /> <option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" /> <option name="WHILE_BRACE_FORCE" value="1" />

15
.idea/codeception.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Codeception">
<option name="configurations">
<list>
<Configuration>
<option name="path" value="$PROJECT_DIR$/tests" />
</Configuration>
<Configuration>
<option name="path" value="$PROJECT_DIR$/tests" />
</Configuration>
</list>
</option>
</component>
</project>

View File

@ -1,10 +1,7 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false"> <profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="AnonymousFunctionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentResultUsedJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="AssignmentResultUsedJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentToForLoopParameterJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AssignmentToFunctionParameterJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="BadExceptionsProcessingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="BadExceptionsProcessingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="BlockStatementJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="BlockStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="BreakStatementJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="BreakStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
@ -27,13 +24,18 @@
<inspection_tool class="ConfusingFloatingPointLiteralJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ConfusingFloatingPointLiteralJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConfusingPlusesOrMinusesJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ConfusingPlusesOrMinusesJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConstantOnLHSOfComparisonJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ConstantOnLHSOfComparisonJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ConstantOnRHSOfComparisonJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ContinueStatementJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ContinueStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ContinueStatementWithLabelJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ContinueStatementWithLabelJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssBrowserCompatibilityForProperties" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="CssBrowserCompatibilityForProperties" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myChromeVersion" value="100" />
<option name="myEdgeVersion" value="100" />
<option name="myFirefoxVersion" value="100" />
<option name="myCheckIE" value="false" />
<option name="myOperaVersion" value="100" />
</inspection_tool>
<inspection_tool class="CssConvertColorToHexInspection" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="CssConvertColorToHexInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssConvertColorToRgbInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssMissingSemicolon" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="CssMissingSemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CssNonIntegerLengthInPixels" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="CyclomaticComplexityJS" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="CyclomaticComplexityJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="10" /> <option name="m_limit" value="10" />
</inspection_tool> </inspection_tool>
@ -46,6 +48,7 @@
<inspection_tool class="DuplicateConditionJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="DuplicateConditionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="DynamicallyGeneratedCodeJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="DynamicallyGeneratedCodeJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ES6TopLevelAwaitExpression" enabled="true" level="ERROR" enabled_by_default="true" /> <inspection_tool class="ES6TopLevelAwaitExpression" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="EditorConfigPartialOverride" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="EfferentObjectCouplingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="EfferentObjectCouplingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="EmptyCatchBlockJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="EmptyCatchBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="EmptyClassInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="EmptyClassInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
@ -133,12 +136,10 @@
</inspection_tool> </inspection_tool>
<inspection_tool class="FunctionNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="FunctionNamingConventionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_regex" value="[a-z][A-Za-z]*" /> <option name="m_regex" value="[a-z][A-Za-z]*" />
<option name="m_minLength" value="4" /> <option name="m_minLength" value="3" />
<option name="m_maxLength" value="32" /> <option name="m_maxLength" value="32" />
</inspection_tool> </inspection_tool>
<inspection_tool class="FunctionWithInconsistentReturnsJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="FunctionWithInconsistentReturnsJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FunctionWithMultipleLoopsJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FunctionWithMultipleReturnPointsJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GrazieInspection" enabled="true" level="TYPO" enabled_by_default="true" /> <inspection_tool class="GrazieInspection" enabled="true" level="TYPO" enabled_by_default="true" />
<inspection_tool class="HamlNestedTagContent" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="HamlNestedTagContent" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="HtmlNonExistentInternetResource" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="HtmlNonExistentInternetResource" enabled="true" level="WARNING" enabled_by_default="true" />
@ -159,26 +160,15 @@
</list> </list>
</value> </value>
</option> </option>
<option name="myCustomValuesEnabled" value="true" /> <option name="myCustomValuesEnabled" value="false" />
</inspection_tool> </inspection_tool>
<inspection_tool class="HtmlUnknownBooleanAttribute" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="HtmlUnknownBooleanAttribute" enabled="true" level="WARNING" enabled_by_default="true">
<myValues> <option name="myCustomValuesEnabled" value="false" />
<item value="required" />
<item value="raised" />
<item value="outlined" />
<item value="disabled" />
<item value="indeterminate" />
<item value="inner" />
<item value="fixedmenuposition" />
<item value="comfortable" />
<item value="dense" />
<item value="compact" />
</myValues>
</inspection_tool> </inspection_tool>
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues"> <option name="myValues">
<value> <value>
<list size="24"> <list size="9">
<item index="0" class="java.lang.String" itemvalue="nobr" /> <item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" /> <item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" /> <item index="2" class="java.lang.String" itemvalue="comment" />
@ -186,23 +176,8 @@
<item index="4" class="java.lang.String" itemvalue="embed" /> <item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" /> <item index="5" class="java.lang.String" itemvalue="script" />
<item index="6" class="java.lang.String" itemvalue="slot" /> <item index="6" class="java.lang.String" itemvalue="slot" />
<item index="7" class="java.lang.String" itemvalue="mwc-list-item" /> <item index="7" class="java.lang.String" itemvalue="md-fab" />
<item index="8" class="java.lang.String" itemvalue="mwc-menu" /> <item index="8" class="java.lang.String" itemvalue="md-icon" />
<item index="9" class="java.lang.String" itemvalue="mwc-list" />
<item index="10" class="java.lang.String" itemvalue="mwc-button" />
<item index="11" class="java.lang.String" itemvalue="mwc-icon-button" />
<item index="12" class="java.lang.String" itemvalue="material-drawer" />
<item index="13" class="java.lang.String" itemvalue="top-app-bar" />
<item index="14" class="java.lang.String" itemvalue="mwc-fab" />
<item index="15" class="java.lang.String" itemvalue="mwc-textfield" />
<item index="16" class="java.lang.String" itemvalue="text-field" />
<item index="17" class="java.lang.String" itemvalue="text-area" />
<item index="18" class="java.lang.String" itemvalue="icon-button" />
<item index="19" class="java.lang.String" itemvalue="mwc-circular-progress" />
<item index="20" class="java.lang.String" itemvalue="mwc-dialog" />
<item index="21" class="java.lang.String" itemvalue="mwc-linear-progress" />
<item index="22" class="java.lang.String" itemvalue="mwc-checkbox" />
<item index="23" class="java.lang.String" itemvalue="mwc-snackbar" />
</list> </list>
</value> </value>
</option> </option>
@ -221,7 +196,6 @@
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="IncorrectFormatting" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="IncorrectFormatting" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="IncrementDecrementResultUsedJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="IncrementDecrementResultUsedJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InnerHTMLJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InvertedIfElseConstructsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="InvertedIfElseConstructsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="IsNullFunctionUsageInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="IsNullFunctionUsageInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="JSClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="JSClassNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
@ -245,9 +219,8 @@
</inspection_tool> </inspection_tool>
<inspection_tool class="LongInheritanceChainInspection" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="LongInheritanceChainInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MagicNumberJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MessDetectorValidationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="MessDetectorValidationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="MultipleReturnStatementsInspection" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="MethodShouldBeFinalInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NegatedConditionalExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NegatedConditionalExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NegatedIfStatementJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NegatedIfStatementJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NestedAssignmentJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NestedAssignmentJS" enabled="true" level="WARNING" enabled_by_default="true" />
@ -261,6 +234,10 @@
<option name="m_limit" value="5" /> <option name="m_limit" value="5" />
</inspection_tool> </inspection_tool>
<inspection_tool class="NonBlockStatementBodyJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="NonBlockStatementBodyJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NullPointerExceptionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NullableTypeFormatInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="nullableTypeFormat" value="SHORT" />
</inspection_tool>
<inspection_tool class="ObjectAllocationIgnoredJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="ObjectAllocationIgnoredJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OffsetOperationsInspection" enabled="true" level="ERROR" enabled_by_default="true" /> <inspection_tool class="OffsetOperationsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="OverlyComplexArithmeticExpressionJS" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="OverlyComplexArithmeticExpressionJS" enabled="true" level="WARNING" enabled_by_default="true">
@ -286,13 +263,13 @@
<option name="ALLOW_RISKY_RULES" value="true" /> <option name="ALLOW_RISKY_RULES" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="PhpCSValidationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpCSValidationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpClassConstantAccessedViaChildClassInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpClassHasTooManyDeclaredMembersInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpClassHasTooManyDeclaredMembersInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpClassNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpClassNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpComplexClassInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpComplexClassInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpComplexFunctionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpComplexFunctionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpCompoundNamespaceDepthInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpCompoundNamespaceDepthInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpConstantNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpConstantNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpEnforceDocCommentInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpFeatureEnvyLocalInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpFeatureEnvyLocalInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpFunctionCyclomaticComplexityInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpFunctionCyclomaticComplexityInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpFunctionNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpFunctionNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
@ -302,10 +279,11 @@
<inspection_tool class="PhpMemberCanBePulledUpInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMemberCanBePulledUpInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMethodNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodOrClassCallIsNotCaseSensitiveInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMethodOrClassCallIsNotCaseSensitiveInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMissingDocCommentInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMissingDocCommentInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="CHECK_CLASS" value="false" />
</inspection_tool>
<inspection_tool class="PhpMissingParentCallCommonInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMissingParentCallCommonInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMissingParentCallMagicInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMissingParentCallMagicInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMissingStrictTypesDeclarationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMissingVisibilityInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpMissingVisibilityInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpModifierOrderInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpModifierOrderInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpNewClassMissingParameterListInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpNewClassMissingParameterListInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
@ -322,7 +300,9 @@
<inspection_tool class="PhpUnnecessaryDoubleQuotesInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpUnnecessaryDoubleQuotesInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUsageOfSilenceOperatorInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpUsageOfSilenceOperatorInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpVarUsageInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpVarUsageInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpVariableNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpVariableNamingConventionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="m_minLength" value="1" />
</inspection_tool>
<inspection_tool class="PhpVariableVariableInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="PhpVariableVariableInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PlatformDetectionJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="PlatformDetectionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PointlessBitwiseExpressionJS" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="PointlessBitwiseExpressionJS" enabled="true" level="WARNING" enabled_by_default="true">
@ -401,6 +381,7 @@
<inspection_tool class="StatementsPerFunctionJS" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="StatementsPerFunctionJS" enabled="true" level="WARNING" enabled_by_default="true">
<option name="m_limit" value="30" /> <option name="m_limit" value="30" />
</inspection_tool> </inspection_tool>
<inspection_tool class="StringCurlyInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="StringLiteralBreaksHTMLJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="StringLiteralBreaksHTMLJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" /> <inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="TailRecursionJS" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="TailRecursionJS" enabled="true" level="WARNING" enabled_by_default="true" />
@ -422,12 +403,10 @@
</inspection_tool> </inspection_tool>
<inspection_tool class="UnusedDefine" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UnusedDefine" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UsingInclusionReturnValueInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="UsingInclusionReturnValueInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="VoidExpressionJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="W3CssValidation" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="W3CssValidation" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myCssVersion" value="css3svg" /> <option name="myCssVersion" value="css3svg" />
<option name="myIgnoreVendorSpecificProperties" value="false" /> <option name="myIgnoreVendorSpecificProperties" value="false" />
</inspection_tool> </inspection_tool>
<inspection_tool class="XHTMLIncompatabilitiesJS" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="bashproExecutableNoShebang" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="bashproExecutableNoShebang" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="bashproShebangNotExecutable" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="bashproShebangNotExecutable" enabled="true" level="WARNING" enabled_by_default="true" />
</profile> </profile>

View File

@ -0,0 +1,7 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Default" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="JavaScriptLibraryMappings"> <component name="JavaScriptLibraryMappings">
<file url="PROJECT" libraries="{@types/prop-types, osm3/node_modules}" /> <file url="file://$PROJECT_DIR$" libraries="{osm3/node_modules}" />
<file url="PROJECT" libraries="{osm3/node_modules}" />
</component> </component>
</project> </project>

View File

@ -10,10 +10,37 @@
<component name="LaravelIdeaMainSettings"> <component name="LaravelIdeaMainSettings">
<option name="codeGeneration"> <option name="codeGeneration">
<LaravelCodeGeneration> <LaravelCodeGeneration>
<option name="generationBooleanSettings">
<map>
<entry key="createConfigFile:inModules" value="true" />
<entry key="createConsoleCommand:inModules" value="true" />
<entry key="createDatabaseMigration:inModules" value="true" />
<entry key="createEvent:inModules" value="true" />
<entry key="createListener:inModules" value="true" />
<entry key="createMailable:inModules" value="true" />
<entry key="createMiddleware:inModules" value="true" />
<entry key="createNotification:inModules" value="true" />
</map>
</option>
<option name="generationStringSettings"> <option name="generationStringSettings">
<map> <map>
<entry key="createBladeComponent:classSuffix" value="" />
<entry key="createChannel:classSuffix" value="Channel" />
<entry key="createConsoleCommand:classSuffix" value="Command" />
<entry key="createController:classSuffix" value="Controller" />
<entry key="createDatabaseClassFactory:classSuffix" value="Factory" />
<entry key="createEloquentScope:namespace" value="Models\Scopes" /> <entry key="createEloquentScope:namespace" value="Models\Scopes" />
<entry key="createEvent:classSuffix" value="Event" />
<entry key="createFormRequest:classSuffix" value="Request" />
<entry key="createJob:classSuffix" value="Job" />
<entry key="createListener:classSuffix" value="Listener" />
<entry key="createMailable:classSuffix" value="Mail" />
<entry key="createMiddleware:classSuffix" value="Middleware" />
<entry key="createModel:classSuffix" value="" />
<entry key="createModel:namespace" value="Models" /> <entry key="createModel:namespace" value="Models" />
<entry key="createNotification:classSuffix" value="Notification" />
<entry key="createResourceController:classSuffix" value="Controller" />
<entry key="createServiceProvider:classSuffix" value="ServiceProvider" />
</map> </map>
</option> </option>
</LaravelCodeGeneration> </LaravelCodeGeneration>
@ -26,6 +53,11 @@
<entry key="createModel:namespace" value="Models" /> <entry key="createModel:namespace" value="Models" />
</map> </map>
</option> </option>
<option name="translation">
<LaravelTranslation>
<option name="defaultPath" value="lang" />
</LaravelTranslation>
</option>
<option name="userClassName" value="App\Models\User" /> <option name="userClassName" value="App\Models\User" />
</component> </component>
</project> </project>

13
.idea/phpspec.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPSpec">
<suites>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
</suites>
</component>
</project>

View File

@ -5,6 +5,7 @@
<list> <list>
<option value="$PROJECT_DIR$/tests/Unit" /> <option value="$PROJECT_DIR$/tests/Unit" />
<option value="$PROJECT_DIR$/tests/Feature" /> <option value="$PROJECT_DIR$/tests/Feature" />
<option value="$PROJECT_DIR$/tests" />
</list> </list>
</option> </option>
</component> </component>

View File

@ -0,0 +1,3 @@
<component name="DependencyValidationManager">
<scope name="Frontend" pattern="file[osm3]:resources/js/*.ts||file[osm3]:resources/js/*.tsx" />
</component>

7
.idea/symfony2.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Symfony2PluginSettings">
<option name="dismissEnableNotification" value="true" />
<option name="profilerCsvPath" value="" />
</component>
</project>

4
.npmrc
View File

@ -1,8 +1,6 @@
public-hoist-pattern[]=*@material* public-hoist-pattern[]=*@material*
public-hoist-pattern[]=autoprefixer
public-hoist-pattern[]=*eslint* public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=autoprefixer
public-hoist-pattern[]=*postcss* public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=*types*
public-hoist-pattern[]=*vite* public-hoist-pattern[]=*vite*
public-hoist-pattern[]=workbox-window public-hoist-pattern[]=workbox-window
node-linker=hoisted

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
v19.7.0

View File

@ -1,11 +1,24 @@
<?php <?php
// Source: https://github.com/laravel/pint/blob/main/resources/presets/laravel.php
$finder = PhpCsFixer\Finder::create() $finder = PhpCsFixer\Finder::create()
->files() ->files()
->exclude('.couscous') ->notName([
->exclude('node_modules') '_ide_helper_actions.php',
->exclude('vendor') '_ide_helper_models.php',
->exclude('tests') '_ide_helper.php',
'.phpstorm.meta.php',
'*.blade.php',
])
->exclude([
'bootstrap/cache',
'build',
'node_modules',
'storage',
'vendor',
'tests',
])
->ignoreDotFiles(true) ->ignoreDotFiles(true)
->ignoreVCS(true) ->ignoreVCS(true)
->in(__DIR__); ->in(__DIR__);
@ -16,11 +29,198 @@ $config->setRules([
'array_syntax' => ['syntax' => 'short'], 'array_syntax' => ['syntax' => 'short'],
'yoda_style' => false, 'yoda_style' => false,
'echo_tag_syntax' => ['format' => 'long'], 'echo_tag_syntax' => ['format' => 'long'],
'ordered_imports' => true, 'global_namespace_import' => true,
'no_alternative_syntax' => true,
'ordered_class_elements' => true, 'ordered_class_elements' => true,
'phpdoc_order' => true, 'array_indentation' => true,
'binary_operator_spaces' => [
'default' => 'single_space',
],
'blank_line_after_namespace' => true,
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => [
'statements' => [
'continue',
'return',
],
],
'braces' => [
'allow_single_line_anonymous_class_with_empty_body' => true,
'allow_single_line_closure' => true,
'position_after_control_structures' => 'same',
'position_after_functions_and_oop_constructs' => 'next',
'position_after_anonymous_constructs' => 'next',
],
'curly_braces_position' => [
'control_structures_opening_brace' => 'same_line',
'functions_opening_brace' => 'next_line_unless_newline_at_signature_end',
'anonymous_functions_opening_brace' => 'same_line',
'classes_opening_brace' => 'next_line_unless_newline_at_signature_end',
'anonymous_classes_opening_brace' => 'next_line_unless_newline_at_signature_end',
'allow_single_line_empty_anonymous_classes' => false,
'allow_single_line_anonymous_functions' => false,
],
'cast_spaces' => true,
'class_attributes_separation' => [
'elements' => [
'const' => 'one',
'method' => 'one',
'property' => 'one',
'trait_import' => 'none',
],
],
'class_definition' => [
'multi_line_extends_each_single_line' => true,
'single_item_single_line' => true,
'single_line' => true,
],
'clean_namespace' => true,
'compact_nullable_typehint' => true,
'concat_space' => [
'spacing' => 'none',
],
'constant_case' => ['case' => 'lower'],
'declare_equal_normalize' => true,
'elseif' => true,
'encoding' => true,
'full_opening_tag' => true,
'fully_qualified_strict_types' => true,
'function_declaration' => true,
'function_typehint_space' => true,
'general_phpdoc_tag_rename' => true,
'heredoc_to_nowdoc' => true,
'include' => true,
'increment_style' => ['style' => 'post'],
'indentation_type' => true,
'integer_literal_case' => true,
'lambda_not_used_import' => true,
'linebreak_after_opening_tag' => true,
'line_ending' => true,
'list_syntax' => true,
'lowercase_cast' => true,
'lowercase_keywords' => true,
'lowercase_static_reference' => true,
'magic_method_casing' => true,
'magic_constant_casing' => true,
'method_argument_space' => [
'on_multiline' => 'ignore',
],
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'native_function_casing' => true,
'native_function_type_declaration_casing' => true,
'no_alias_functions' => true,
'no_alias_language_construct_call' => true,
'no_alternative_syntax' => true,
'no_binary_string' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_closing_tag' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_blank_lines' => [
'tokens' => [
'extra',
'throw',
'use',
],
],
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => [
'use' => 'echo',
],
'no_multiline_whitespace_around_double_arrow' => true,
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_spaces_after_function_name' => true,
'no_space_around_double_colon' => true,
'no_spaces_around_offset' => [
'positions' => ['inside', 'outside'],
],
'no_spaces_inside_parenthesis' => true,
'no_superfluous_phpdoc_tags' => [
'allow_mixed' => true,
'allow_unused_params' => true,
],
'no_trailing_comma_in_singleline' => true,
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'no_unneeded_control_parentheses' => [
'statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield'],
],
'no_unneeded_curly_braces' => true,
'no_unset_cast' => true,
'no_unused_imports' => true,
'no_unreachable_default_argument_value' => true,
'no_useless_return' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'normalize_index_brace' => true,
'object_operator_without_whitespace' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'psr_autoloading' => false,
'phpdoc_indent' => true,
'phpdoc_inline_tag_normalizer' => true,
'phpdoc_no_access' => true,
'phpdoc_no_package' => true,
'phpdoc_no_useless_inheritdoc' => true,
'phpdoc_order' => [
'order' => ['param', 'return', 'throws'],
],
'phpdoc_scalar' => true,
'phpdoc_separation' => [
'groups' => [
['deprecated', 'link', 'see', 'since'],
['author', 'copyright', 'license'],
['category', 'package', 'subpackage'],
['property', 'property-read', 'property-write'],
['param', 'return'],
],
],
'phpdoc_single_line_var_spacing' => true,
'phpdoc_summary' => false,
'phpdoc_to_comment' => false,
'phpdoc_tag_type' => [
'tags' => [
'inheritdoc' => 'inline',
],
],
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_var_without_name' => true,
'return_type_declaration' => ['space_before' => 'none'],
'self_accessor' => false,
'short_scalar_cast' => true,
'simplified_null_return' => false,
'single_blank_line_at_eof' => true,
'single_blank_line_before_namespace' => true,
'single_class_element_per_statement' => [
'elements' => ['const', 'property'],
],
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'single_line_comment_style' => [
'comment_types' => ['hash'],
],
'single_quote' => true,
'space_after_semicolon' => true,
'standardize_not_equals' => true,
'statement_indentation' => false,
'switch_case_semicolon_to_colon' => true,
'switch_case_space' => true,
'ternary_operator_spaces' => true,
'trailing_comma_in_multiline' => ['elements' => ['arrays']],
'trim_array_spaces' => true,
'types_spaces' => true,
'unary_operator_spaces' => true,
'visibility_required' => [
'elements' => ['method', 'property'],
],
'whitespace_after_comma_in_array' => true,
]) ])
->setRiskyAllowed(true)
->setUsingCache(true)
->setFinder($finder); ->setFinder($finder);
return $config; return $config;

View File

@ -1,13 +1,14 @@
{ {
"extends": [ "extends": [
"stylelint-config-standard", "stylelint-config-standard-scss",
"stylelint-config-recommended-scss", "stylelint-config-clean-order",
"stylelint-config-idiomatic-order", "stylelint-config-html"
"stylelint-config-html" ],
], "rules": {
"rules": { "indentation": 4,
"indentation": 4, "selector-type-no-unknown": null,
"selector-type-no-unknown": null, "no-eol-whitespace": null,
"no-eol-whitespace": null "scss/at-extend-no-missing-placeholder": null,
} "custom-property-pattern": "^_?([a-z][a-z0-9]*)(-[a-z0-9]+)*$"
}
} }

View File

@ -42,7 +42,8 @@ Secondo questa definizione, OpenSTAManager riesce a generalizzare al proprio int
della contabilità e della gestione del magazzino, presentando inoltre moduli piuttosto avanzati e destinati a della contabilità e della gestione del magazzino, presentando inoltre moduli piuttosto avanzati e destinati a
complementare l'attività aziendale in relazione agli interventi di assistenza della realtà lavorativa in oggetto. complementare l'attività aziendale in relazione agli interventi di assistenza della realtà lavorativa in oggetto.
La documentazione ufficiale è disponibile all'indirizzo [https://docs.openstamanager.com/](https://docs.openstamanager.com/). La documentazione ufficiale è disponibile
all'indirizzo [https://docs.openstamanager.com/](https://docs.openstamanager.com/).
## Requisiti ## Requisiti
@ -50,34 +51,45 @@ L'installazione del gestionale richiede un server web con le seguenti tecnologie
- [PHP](https://php.net) 8.0+ - [PHP](https://php.net) 8.0+
- Un database a scelta tra: - Un database a scelta tra:
- [MySQL](https://www.mysql.com) 5.7+ (consigliato) - [MySQL](https://www.mysql.com) 5.7+ (consigliato) / [MariaDB](https://mariadb.org/) 10.3+
- [PostgreSQL](https://www.postgresql.org) 9.6+ - [PostgreSQL](https://www.postgresql.org) 9.6+
- [SQLite](https://www.sqlite.org) 3.8.8+ (non consigliato, in quanto viene salvato "in chiaro" sul filesystem del - [SQLite](https://www.sqlite.org) 3.8.8+ (non consigliato, in quanto viene salvato "in chiaro" sul filesystem del
server) server)
- [SQL Server](https://www.microsoft.com/it-it/sql-server) 2017+ - [SQL Server](https://www.microsoft.com/it-it/sql-server) 2017+
- Accesso SSH (**facoltativo**) - Accesso SSH (**facoltativo**)
- [Composer](https://getcomposer.org/) installato e disponibile da linea di comando (**facoltativo**) - [Composer](https://getcomposer.org/) installato e disponibile da linea di comando (**facoltativo**)
e un dispositivo (client) con le seguenti tecnologie disponibili: e un dispositivo (client) con le seguenti tecnologie disponibili:
- Browser moderno, a scelta tra: - Browser moderno, a scelta tra:
- [Microsoft Edge](https://www.microsoft.com/it-it/edge) 83+ - [Microsoft Edge](https://www.microsoft.com/it-it/edge) 83+
- [Google Chrome](https://www.google.com/intl/it_it/chrome/) 93+ - [Google Chrome](https://www.google.com/intl/it_it/chrome/) 93+
- [Mozilla Firefox](https://www.mozilla.org/it/firefox/) 92+ - [Mozilla Firefox](https://www.mozilla.org/it/firefox/) 92+
- [Opera](https://www.opera.com) 79+ - [Opera](https://www.opera.com) 79+
- [Safari](https://www.apple.com/it/safari/) (attualmente solo nella sua versione [Technology Preview](https://developer.apple.com/safari/technology-preview/) 33+) - [Safari](https://www.apple.com/it/safari/) (attualmente solo nella sua
versione [Technology Preview](https://developer.apple.com/safari/technology-preview/) 33+)
_Alcune note:_ _Alcune note:_
- _**Non** è supportato nessun browser diverso dai precedenti, nemmeno in versioni più datate. Pertanto, anche se il - _**Non** è supportato nessun browser diverso dai precedenti, nemmeno in versioni più datate. Pertanto, anche se il
gestionale potrebbe funzionare, non è garantita assistenza su tali browser. Si citano come esempi: Internet Explorer, gestionale potrebbe funzionare, non è garantita assistenza su tali browser. Si citano come esempi: Internet Explorer,
Samsung Internet, Opera Mini, Opera Mobile, UC Browser, Safari per iOS._ Samsung Internet, Opera Mini, Opera Mobile, UC Browser, Safari per iOS._
- _È fortemente consigliato aggiornare sempre il proprio browser alla versione più recente e non interrompere la ricezione degli aggiornamenti raggiunta la versione minima indicata_ - _È fortemente consigliato aggiornare sempre il proprio browser alla versione più recente e non interrompere la
ricezione degli aggiornamenti raggiunta la versione minima indicata_
- _Il gestionale viene testato sui 3 principali browser (Edge, Chrome, Firefox) nella loro versione più recente_ - _Il gestionale viene testato sui 3 principali browser (Edge, Chrome, Firefox) nella loro versione più recente_
Per ulteriori informazioni sui pacchetti che forniscono questi elementi di default, visitare la Per ulteriori informazioni sui pacchetti che forniscono questi elementi di default, visitare la
sezione [Installazione](https://docs.openstamanager.com/guide/configurazione/installazione) della documentazione. sezione [Installazione](https://docs.openstamanager.com/guide/configurazione/installazione) della documentazione.
### Dipendenze
Per installare le dipendenze del gestionale sono necessari i seguenti strumenti (installati sul server web o su un PC da utilizzare per la
preparazione del progetto):
- [Composer](https://getcomposer.org/)
- [Node.js](https://nodejs.org/) 19+
- [Git](https://git-scm.com/) (facoltativo, ma consigliato)
## Installazione ## Installazione
Per procedere all'installazione è necessario seguire i seguenti punti: Per procedere all'installazione è necessario seguire i seguenti punti:
@ -86,10 +98,10 @@ Per procedere all'installazione è necessario seguire i seguenti punti:
2. Creare una cartella (ad esempio `openstamanager`) nella root del server web installato ed estrarvi il contenuto della 2. Creare una cartella (ad esempio `openstamanager`) nella root del server web installato ed estrarvi il contenuto della
release scaricata. Il percorso della cartella root del server varia in base al software in utilizzo: release scaricata. Il percorso della cartella root del server varia in base al software in utilizzo:
- LAMP (`/var/www/html`) - LAMP (`/var/www/html`)
- XAMPP (`C:/xampp/htdocs` per Windows, `/opt/lampp/htdocs/` per Linux, `/Applications/XAMPP/htdocs/` per MAC) - XAMPP (`C:/xampp/htdocs` per Windows, `/opt/lampp/htdocs/` per Linux, `/Applications/XAMPP/htdocs/` per MAC)
- WAMP (`C:\wamp\www`) - WAMP (`C:\wamp\www`)
- MAMP (`C:\MAMP\htdocs` per Windows, `/Applications/MAMP/htdocs` per MAC) - MAMP (`C:\MAMP\htdocs` per Windows, `/Applications/MAMP/htdocs` per MAC)
3. Creare un database vuoto (tramite [PHPMyAdmin](http://localhost/phpmyadmin/) o riga di comando). 3. Creare un database vuoto (tramite [PHPMyAdmin](http://localhost/phpmyadmin/) o riga di comando).
4. Accedere a [http://localhost/openstamanager](http://localhost/openstamanager) dal vostro browser. 4. Accedere a [http://localhost/openstamanager](http://localhost/openstamanager) dal vostro browser.
5. Inserire i dati di configurazione per collegarsi al database. 5. Inserire i dati di configurazione per collegarsi al database.
@ -108,7 +120,8 @@ su GitHub (per versioni precedenti alla 2.3,
visitare [SourceForge](https://sourceforge.net/projects/openstamanager/files)). visitare [SourceForge](https://sourceforge.net/projects/openstamanager/files)).
Nel caso utilizziate il programma per uso commerciale, si consiglia di scaricare le release disponibili nel sito Nel caso utilizziate il programma per uso commerciale, si consiglia di scaricare le release disponibili nel sito
ufficiale del progetto ([https://www.openstamanager.com](https://www.openstamanager.com)), evitando di utilizzare direttamente il codice della ufficiale del progetto ([https://www.openstamanager.com](https://www.openstamanager.com)), evitando di utilizzare
direttamente il codice della
repository. Se siete inoltre interessati a supporto e assistenza professionali, li potete richiedere repository. Se siete inoltre interessati a supporto e assistenza professionali, li potete richiedere
nella [sezione dedicata](https://www.openstamanager.com/per-le-aziende/). nella [sezione dedicata](https://www.openstamanager.com/per-le-aziende/).
@ -147,7 +160,8 @@ La community è una componente importante in un progetto open-source, perché me
di loro e permette pertanto l'individuazione di soluzioni innovative e migliori. di loro e permette pertanto l'individuazione di soluzioni innovative e migliori.
Siamo presenti su [Facebook](https://www.facebook.com/openstamanager), e il nostro forum ufficiale è disponibile Siamo presenti su [Facebook](https://www.facebook.com/openstamanager), e il nostro forum ufficiale è disponibile
all'indirizzo [https://forum.openstamanager.com](https://forum.openstamanager.com), dove potete segnalare i vostri problemi e soddisfare le vostre all'indirizzo [https://forum.openstamanager.com](https://forum.openstamanager.com), dove potete segnalare i vostri
problemi e soddisfare le vostre
curiosità nelle sezioni più adeguate: curiosità nelle sezioni più adeguate:
- [Idee, suggerimenti e consigli](https://forum.openstamanager.com/viewforum.php?f=1) - [Idee, suggerimenti e consigli](https://forum.openstamanager.com/viewforum.php?f=1)

View File

@ -0,0 +1,40 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Laravel\Fortify\Contracts\CreatesNewUsers;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* @param array<string, string> $input
*/
public function create(array $input): User
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique(User::class),
],
'password' => $this->passwordRules(),
])->validate();
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Actions\Fortify;
use Laravel\Fortify\Rules\Password;
trait PasswordValidationRules
{
/**
* Get the validation rules used to validate passwords.
*
* @return array<int, \Illuminate\Contracts\Validation\Rule|array|string>
*/
protected function passwordRules(): array
{
return ['required', 'string', new Password(), 'confirmed'];
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\ResetsUserPasswords;
class ResetUserPassword implements ResetsUserPasswords
{
use PasswordValidationRules;
/**
* Validate and reset the user's forgotten password.
*
* @param array<string, string> $input
*/
public function reset(User $user, array $input): void
{
Validator::make($input, [
'password' => $this->passwordRules(),
])->validate();
$user->forceFill([
'password' => Hash::make($input['password']),
])->save();
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
class UpdateUserPassword implements UpdatesUserPasswords
{
use PasswordValidationRules;
/**
* Validate and update the user's password.
*
* @param array<string, string> $input
*/
public function update(User $user, array $input): void
{
Validator::make($input, [
'current_password' => ['required', 'string', 'current_password:web'],
'password' => $this->passwordRules(),
], [
'current_password.current_password' => __('The provided password does not match your current password.'),
])->validateWithBag('updatePassword');
$user->forceFill([
'password' => Hash::make($input['password']),
])->save();
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
{
/**
* Validate and update the given user's profile information.
*
* @param array<string, string> $input
*/
public function update(User $user, array $input): void
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($user->id),
],
])->validateWithBag('updateProfileInformation');
if ($input['email'] !== $user->email &&
$user instanceof MustVerifyEmail) {
$this->updateVerifiedUser($user, $input);
} else {
$user->forceFill([
'name' => $input['name'],
'email' => $input['email'],
])->save();
}
}
/**
* Update the given verified user's profile information.
*
* @param array<string, string> $input
*/
protected function updateVerifiedUser(User $user, array $input): void
{
$user->forceFill([
'name' => $input['name'],
'email' => $input['email'],
'email_verified_at' => null,
])->save();
$user->sendEmailVerificationNotification();
}
}

View File

@ -3,7 +3,6 @@
namespace App\Exceptions; namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use LaravelJsonApi\Exceptions\ExceptionParser;
use Throwable; use Throwable;
class Handler extends ExceptionHandler class Handler extends ExceptionHandler
@ -36,9 +35,5 @@ class Handler extends ExceptionHandler
$this->reportable(static function (Throwable $e): void { $this->reportable(static function (Throwable $e): void {
// //
}); });
$this->renderable(
ExceptionParser::make()->renderable()
);
} }
} }

View File

@ -0,0 +1,204 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use function in_array;
use PDOException;
use RuntimeException;
class SetupController extends Controller
{
public function __construct(private \Jackiedo\DotenvEditor\DotenvEditor $dotenvEditor)
{
}
/**
* Test the database connection with the request data.
*/
final public function testDatabase(Request $request): Response|JsonResponse
{
try {
$request->validate([
'database_driver' => 'required|string',
'database_host' => 'required|string',
'database_username' => 'required|string',
'database_password' => 'nullable|string',
'database_name' => 'required|string',
'database_port' => 'required|integer',
]);
} catch (ValidationException $e) {
return response()->json([
'message' => $e->getMessage(),
'errors' => $e->errors(),
], Response::HTTP_BAD_REQUEST);
}
$database_name = $request->input('database_name');
// Configure test connection
config(['database.connections.testing' => [
'driver' => $request->input('database_driver', 'mysql'),
'host' => $request->input('database_host'),
'port' => $request->input('database_port', '3306'),
'password' => $request->input('database_password'),
'database' => $database_name,
'username' => $request->input('database_username'),
]]);
$connection = DB::connection('testing');
try {
// Check DB connection either by checking if we can get PDO object or DB name
$connection->getPdo();
if (empty($connection->getDatabaseName())) {
throw new RuntimeException(__('Database non trovato'));
}
} catch (PDOException|RuntimeException $e) {
return response()->json([
'message' => __('Impossibile connettersi al database: :message', ['message' => $e->getMessage()]),
Response::HTTP_BAD_REQUEST,
]);
}
// Identifying permissions granted to the user
$database_name = Str::replace('_', '\_', $database_name);
$grants = $connection->select($connection->raw('SHOW GRANTS FOR CURRENT_USER'));
$requirements = [
'SELECT',
'INSERT',
'UPDATE',
'CREATE',
'ALTER',
'DROP',
];
foreach ($grants as $result) {
$privileges = current($result);
if (Str::contains($privileges, [" ON `$database_name`.*", ' ON *.*'])) {
$pieces = explode(', ', explode(' ON ', str_replace('GRANT ', '', (string) $privileges), 2)[0]);
// Database-generic permissions
if (in_array('ALL', $pieces) || in_array('ALL PRIVILEGES', $pieces)) {
$requirements = [];
break;
}
// Database-specific permissions
foreach ($requirements as $key => $value) {
if (in_array($value, $pieces)) {
unset($requirements[$key]);
}
}
}
}
if ($requirements === []) {
return response()->noContent();
}
return response()->json([
'message' => __("L'utente del database non ha i seguenti permessi necessari: :permissions_list",
['permissions_list' => implode(', ', $requirements)]
),
], Response::HTTP_BAD_REQUEST);
}
/**
* Save config.
*/
public function save(Request $request): JsonResponse|Response
{
// Check if the database connection is valid
try {
DB::connection()->getPdo();
} catch (PDOException) {
$response = $this->testDatabase($request);
if ($response->getStatusCode() !== Response::HTTP_NO_CONTENT) {
return $response;
}
}
$chmod_result = File::chmod(base_path('.env'), 0644);
try {
$this->dotenvEditor->setKeys([
'DB_CONNECTION' => $request->input('database_driver', 'mysql'),
'DB_HOST' => $request->input('database_host'),
'DB_PORT' => $request->input('database_port'),
'DB_DATABASE' => $request->input('database_name'),
'DB_USERNAME' => $request->input('database_username'),
'DB_PASSWORD' => $request->input('database_password'),
])->save();
} catch (Exception $e) {
return response()->json([
'message' => __('Impossibile scrivere il file di configurazione. :action', [
'action' => $chmod_result ? $e->getMessage() : 'Controllare i permessi del file .env',
]),
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Cache config
Artisan::call('cache:clear');
Artisan::call('config:cache');
// Run migrations
Artisan::call('migrate', ['--force' => true]);
try {
$request->validate([
'date_format_short' => 'required|string',
'date_format_long' => 'required|string',
'time_format' => 'required|string',
'locale' => 'sometimes|string',
]);
} catch (ValidationException $e) {
return response()->json([
'message' => $e->getMessage(),
'errors' => $e->errors(),
], Response::HTTP_BAD_REQUEST);
}
settings($request->only(['date_format_short', 'date_format_long', 'time_format']));
settings('locale', $request->input('locale', app()->getLocale()));
return $this->saveAdmin($request);
}
public function saveAdmin(Request $request): Response|JsonResponse
{
try {
$request->validate([
'admin_username' => 'required|string|min:3|max:255|unique:users,username',
'admin_password' => 'required|string|min:8|max:255',
'admin_password_confirmation' => 'required|string|min:8|max:255|same:admin_password',
'admin_email' => 'required|string|email|max:255|unique:users,email',
]);
} catch (ValidationException $e) {
return response()->json([
'message' => $e->getMessage(),
'errors' => $e->errors(),
], Response::HTTP_UNPROCESSABLE_ENTITY);
}
$user = new User();
$user->username = $request->input('username');
$user->email = $request->input('email');
$user->password = Hash::make($request->input('password'));
$user->save();
return response()->noContent();
}
}

View File

@ -10,37 +10,38 @@ use JetBrains\PhpStorm\ArrayShape;
class AuthController extends Controller class AuthController extends Controller
{ {
/** // /**
* Handle an authentication attempt. // * Handle an authentication attempt.
*/ // */
public function login(Request $request): JsonResponse|Response // public function login(Request $request): JsonResponse|Response
{ // {
try { // try {
$request->validate($this->rules($request)); // $request->validate($this->rules($request));
} catch (ValidationException $e) { // } catch (ValidationException $e) {
return response()->json(['errors' => $e->errors()], 422); // return response()->json(['message' => $e->getMessage(), 'errors' => $e->errors()], Response::HTTP_UNPROCESSABLE_ENTITY);
} // }
//
$credentials = $request->only(['username', 'password']); // $credentials = $request->only(['username', 'password']);
//
if (filter_var($request->get('username'), FILTER_VALIDATE_EMAIL)) { // // TODO: Rivedere con Laravel 10
$credentials['email'] = $credentials['username']; // if (filter_var($request->get('username'), FILTER_VALIDATE_EMAIL)) {
unset($credentials['username']); // $credentials['email'] = $credentials['username'];
} // unset($credentials['username']);
// }
if (auth()->attempt($credentials, $request->get('remember') === 'on')) { //
$request->session()->regenerate(); // if (auth()->attempt($credentials, $request->get('remember') === 'on')) {
if ($request->hasSession()) { // $request->session()->regenerate();
$request->session()->put('auth.password_confirmed_at', time()); // if ($request->hasSession()) {
} // $request->session()->put('auth.password_confirmed_at', time());
// }
return response()->noContent(); //
} // return response()->noContent();
// }
return response()->json([ //
'errors' => ['invalid_credentials' => __('Le credenziali non sono valide.')], // return response()->json([
], Response::HTTP_BAD_REQUEST); // 'message' => __('Le credenziali non sono valide.')
} // ], Response::HTTP_BAD_REQUEST);
// }
/** /**
* Log the user out of the application. * Log the user out of the application.
@ -57,23 +58,23 @@ class AuthController extends Controller
return response()->noContent(); return response()->noContent();
} }
/** // /**
* @return array{username: string, password: string, remember: string} // * @return array{username: string, password: string, remember: string}
*/ // */
#[ArrayShape(['username' => 'string', 'password' => 'string', 'remember' => 'string'])] // #[ArrayShape(['username' => 'string', 'password' => 'string', 'remember' => 'string'])]
private function rules(Request $request): array // private function rules(Request $request): array
{ // {
$additional_validation = ''; // $additional_validation = '';
$db_field = 'username'; // $db_field = 'username';
if (filter_var($request->input('username'), FILTER_VALIDATE_EMAIL)) { // if (filter_var($request->input('username'), FILTER_VALIDATE_EMAIL)) {
$additional_validation = '|email'; // $additional_validation = '|email';
$db_field = 'email'; // $db_field = 'email';
} // }
//
return [ // return [
'username' => "required|string|exists:users,$db_field|$additional_validation", // 'username' => "required|string|exists:users,$db_field|$additional_validation",
'password' => 'required|string', // 'password' => 'required|string',
'remember' => 'string|in:on', // 'remember' => 'string|in:on',
]; // ];
} // }
} }

View File

@ -1,7 +1,10 @@
<?php <?php
/** @noinspection ClassNameCollisionInspection */
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\ModuleServiceProvider;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
@ -11,6 +14,8 @@ use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Nette\Utils\Json; use Nette\Utils\Json;
use Nette\Utils\JsonException;
use ReflectionClass;
class Controller extends BaseController class Controller extends BaseController
{ {
@ -18,33 +23,67 @@ class Controller extends BaseController
use DispatchesJobs; use DispatchesJobs;
use ValidatesRequests; use ValidatesRequests;
public function getModules(?Request $request = null): JsonResponse|Collection public function setLanguage(Request $request): JsonResponse
{ {
$packages = collect(Json::decode(File::get(base_path('vendor/composer/installed.json')))->packages); $locale = $request->input('locale');
$languages = self::getLanguages();
if ($languages->contains($locale)) {
session()->put('locale', $locale);
session()->save();
app()->setLocale($locale);
$modules = $packages->filter(static fn($package) => $package->type === 'openstamanager-module'); return response()->json(['locale' => app()->getLocale()]);
}
$modules->transform(static function ($module) { return response()->json(['success' => false, 'message' => __("Locale isn't available"), 'locale' => app()->getLocale()], 400);
$osm_modules = collect($module->extra->{'osm-modules'}); }
$module->config = $osm_modules
->mapWithKeys(
static fn($item, $name) => config($name) ?? include base_path("vendor/$module->name/config/$name.php")
)
->reject(null)
->all();
// Modules
$module->modules = $osm_modules->map(static function ($item, $key) use ($module) {
$split = explode('/', (string)$module->name, 2);
$item->moduleFullName = $module->name;
$item->moduleVendor = $split[0];
$item->moduleName = $key;
return $item;
});
return $module;
});
$filtered = $modules->only($request?->input('filter')); /**
* @return Collection<string>
*/
public static function getLanguages(): Collection
{
return collect(File::glob(lang_path('*.json')))
->map(static fn (string $file) => File::name($file));
}
return ($request && $request->wantsJson()) ? response()->json($filtered) : $filtered; /**
* @return Collection<string>
*
* @throws JsonException
*/
public static function getTranslations(): Collection
{
return self::getLanguages()
->mapWithKeys(fn (string $locale) => [$locale => Json::decode(File::get(lang_path("$locale.json")))]);
}
/**
* @return Collection<array{
* name: string,
* description: string,
* slug: string,
* author: string,
* version: string,
* url: string,
* module_path: string
* }>
*/
public function getModules(): Collection
{
return collect(app()->getLoadedProviders())
->keys()
->filter(static fn (string $provider) => (new ReflectionClass($provider))->isSubclassOf(ModuleServiceProvider::class))
->map(static fn (string $provider) => app()->getProvider($provider))
->mapWithKeys(static fn (ModuleServiceProvider $provider) => [$provider::slug() => [
'name' => $provider::name(),
'description' => $provider::description(),
'slug' => $provider::slug(),
'author' => $provider::author(),
'version' => $provider::version(),
'url' => $provider::url(),
'module_path' => $provider::modulePath(),
'has_bootstrap' => $provider::hasBootstrap(),
]]);
} }
} }

View File

@ -10,42 +10,57 @@ use Illuminate\Http\Response;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password; use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class PasswordController extends Controller class PasswordController extends Controller
{ {
public function forgotPassword(Request $request): Response|JsonResponse // public function forgotPassword(Request $request): Response|JsonResponse
{ // {
$request->validate([ // try {
'email' => 'required|email|exists:users,email', // $request->validate([
]); // 'email' => 'required|email|exists:users,email',
// ]);
$response = Password::broker()->sendResetLink($request->input('email')); // } catch (ValidationException $e) {
// return response()->json([
return $response === Password::RESET_LINK_SENT // 'message' => $e->getMessage(),
? response()->noContent() // 'errors' => $e->errors(),
: \response()->json(['errors' => ['email' => [__($response)]]], Response::HTTP_BAD_REQUEST); // ], Response::HTTP_UNPROCESSABLE_ENTITY);
} // }
//
public function resetPassword(Request $request): JsonResponse|Response // $response = Password::broker()->sendResetLink($request->input('email'));
{ //
$request->validate([ // return $response === Password::RESET_LINK_SENT
'token' => 'required|string', // ? response()->noContent()
'email' => 'required|email|exists:users,email', // : \response()->json(['message' => __($response)], Response::HTTP_UNPROCESSABLE_ENTITY);
'password' => ['required|string|confirmed', \Illuminate\Validation\Rules\Password::defaults()], // }
]); //
// public function resetPassword(Request $request): JsonResponse|Response
$response = Password::broker()->reset( // {
$request->only(['email', 'password', 'password_confirmation', 'token']), // try {
static function (User $user, string $password): void { // $request->validate([
$user->password = Hash::make($password); // 'token' => 'required|string',
$user->setRememberToken(Str::random(60)); // 'email' => 'required|email|exists:users,email',
$user->save(); // 'password' => ['required|string|confirmed', \Illuminate\Validation\Rules\Password::defaults()],
event(new PasswordReset($user)); // ]);
} // } catch (ValidationException $e) {
); // return response()->json([
// 'message' => $e->getMessage(),
return $response === Password::PASSWORD_RESET // 'errors' => $e->errors(),
? response()->noContent() // ], Response::HTTP_UNPROCESSABLE_ENTITY);
: response()->json(['errors' => ['email' => [__($response)]]], Response::HTTP_BAD_REQUEST); // }
} //
// $response = Password::broker()->reset(
// $request->only(['email', 'password', 'password_confirmation', 'token']),
// static function (User $user, string $password): void {
// $user->password = Hash::make($password);
// $user->setRememberToken(Str::random(60));
// $user->save();
// event(new PasswordReset($user));
// }
// );
//
// return $response === Password::PASSWORD_RESET
// ? response()->noContent()
// : response()->json(['message' => __($response)], Response::HTTP_UNPROCESSABLE_ENTITY);
// }
} }

View File

@ -1,147 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class SetupController extends Controller
{
/**
* Verifica la connessione al database secondo i parametri indicati nella richiesta.
* Restituisce un array di permessi mancanti in caso la connessione avvenga con successo, oppure null in caso contrario.
*/
final public function testDatabase(Request $request): Response|JsonResponse
{
$database_name = $request->input('database_name');
// Configurazione della connessione di test
config(['database.connections.testing' => [
'driver' => 'mysql',
'host' => $request->input('host'),
'port' => '3306',
'password' => $request->input('password'),
'database' => $database_name,
'username' => $request->input('username'),
]]);
try {
$connection = DB::connection('testing');
// Controlla se la connessione al DB è stata stabilita in due modi
$connection->getPdo();
if (empty($connection->getDatabaseName())) {
throw new Exception(__('Impossibile connettersi al database selezionato! Controllare il nome del database'));
}
// Individuazione permessi garantiti all'utente
$database_name = Str::replace('_', '\_', $database_name);
$grants = $connection->select($connection->raw('SHOW GRANTS FOR CURRENT_USER'));
} catch (Exception $e) {
return response()->json([
'success' => false,
'error' => $e->getMessage(),
], Response::HTTP_BAD_REQUEST);
}
$requirements = [
'SELECT',
'INSERT',
'UPDATE',
'CREATE',
'ALTER',
'DROP',
];
foreach ($grants as $result) {
$privileges = current($result);
if (Str::contains($privileges, [" ON `$database_name`.*", ' ON *.*'])) {
$pieces = explode(', ', explode(' ON ', str_replace('GRANT ', '', (string)$privileges), 2)[0]);
// Permessi generici sul database
if (in_array('ALL', $pieces) || in_array('ALL PRIVILEGES', $pieces)) {
$requirements = [];
break;
}
// Permessi specifici sul database
foreach ($requirements as $key => $value) {
if (in_array($value, $pieces)) {
unset($requirements[$key]);
}
}
}
}
if ($requirements === []) {
return response()->noContent();
}
return response()->json([
'error' => __("L'utente del database non ha i seguenti permessi necessari: ", $requirements),
], Response::HTTP_BAD_REQUEST);
}
/**
* Metodo indirizzato al salvataggio della configurazione.
*/
public function save(Request $request)
{
$text = '<?php return '.var_export(config('database'), true).';';
$result = File::put(config_path('database.php'), $text);
// Errore in caso di fallimento
if ($result === false) {
$chmodded = File::chmod(config_path('database.php'), 0644);
$result = File::put(config_path('database.php'), $text);
if ($result === false) {
return response()->json([
'error' => 'writing',
'error_description' => __('Impossibile scrivere il file di configurazione. :action', ['action' => $chmodded ? '' : 'Controllare i permessi del file config/databasee.php']),
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
// Refresh della cache sulla configurazione
Artisan::call('cache:clear');
Artisan::call('config:cache');
// Avvia migrations
Artisan::call('migrate', ['--force' => true]);
setting($request->only(['timestamp_format', 'date_format', 'time_format', 'locale']));
return response()->noContent();
}
public function saveAdmin(Request $request): Response|JsonResponse
{
try {
$request->validate([
'username' => 'required|string|min:3|max:255|unique:users,username',
'password' => 'required|string|min:6|max:255',
'email' => 'required|string|email|max:255|unique:users,email',
]);
} catch (ValidationException $e) {
return response()->json(['errors' => $e->errors()], 422);
}
$user = new User();
$user->username = $request->input('username');
$user->email = $request->input('email');
$user->password = Hash::make($request->input('password'));
$user->save();
return response()->noContent();
}
}

View File

@ -3,14 +3,15 @@
namespace App\Http; namespace App\Http;
use App\Http\Middleware\Authenticate; use App\Http\Middleware\Authenticate;
use App\Http\Middleware\CheckConfigurationMiddleware;
use App\Http\Middleware\EncryptCookies; use App\Http\Middleware\EncryptCookies;
use App\Http\Middleware\HandleInertiaRequests; use App\Http\Middleware\HandleInertiaRequests;
use App\Http\Middleware\LocaleMiddleware;
use App\Http\Middleware\PreventRequestsDuringMaintenance; use App\Http\Middleware\PreventRequestsDuringMaintenance;
use App\Http\Middleware\RedirectIfAuthenticated; use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\TrimStrings; use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustProxies; use App\Http\Middleware\TrustProxies;
use App\Http\Middleware\VerifyCsrfToken; use App\Http\Middleware\VerifyCsrfToken;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Illuminate\Auth\Middleware\Authorize; use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Auth\Middleware\EnsureEmailIsVerified; use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
@ -19,12 +20,14 @@ use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Foundation\Http\Kernel as HttpKernel; use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize; use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Http\Middleware\SetCacheHeaders; use Illuminate\Http\Middleware\SetCacheHeaders;
use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Routing\Middleware\ValidateSignature; use Illuminate\Routing\Middleware\ValidateSignature;
use Illuminate\Session\Middleware\StartSession; use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession; use Illuminate\View\Middleware\ShareErrorsFromSession;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
class Kernel extends HttpKernel class Kernel extends HttpKernel
{ {
@ -59,10 +62,13 @@ class Kernel extends HttpKernel
ShareErrorsFromSession::class, ShareErrorsFromSession::class,
VerifyCsrfToken::class, VerifyCsrfToken::class,
SubstituteBindings::class, SubstituteBindings::class,
LocaleMiddleware::class,
CheckConfigurationMiddleware::class,
HandleInertiaRequests::class, HandleInertiaRequests::class,
], ],
'api' => [ 'api' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:api', 'throttle:api',
SubstituteBindings::class, SubstituteBindings::class,
], ],

View File

@ -3,18 +3,15 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware class Authenticate extends Middleware
{ {
/** /**
* Get the path the user should be redirected to when they are not authenticated. * Get the path the user should be redirected to when they are not authenticated.
*/ */
protected function redirectTo($request): string|null protected function redirectTo(Request $request): ?string
{ {
if (!$request->expectsJson()) { return $request->expectsJson() ? null : route('login');
return route('auth.login');
}
return null;
} }
} }

View File

@ -4,34 +4,43 @@ namespace App\Http\Middleware;
use App\Models\User; use App\Models\User;
use Closure; use Closure;
use Illuminate\Database\QueryException;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use InvalidArgumentException;
use PDOException;
class CheckConfigurationMiddleware class CheckConfigurationMiddleware
{ {
public function handle(Request $request, Closure $next): Response|RedirectResponse|JsonResponse public function handle(Request $request, Closure $next): Response|RedirectResponse|JsonResponse
{ {
$checks = [ $checks = [
empty(DB::connection()->getDatabaseName()) => [ 'database' => fn () => !empty(DB::connection()->getDatabaseName()) && DB::connection()->getPdo(),
'redirect' => 'setup.index', 'admin_user' => fn () => !empty(User::exists()),
'patterns' => [
'setup.index',
'setup.test',
'setup.save',
],
],
empty(User::exists()) => [
'redirect' => 'setup.admin',
'patterns' => 'setup.admin*',
],
]; ];
foreach ($checks as $check => $route) { foreach ($checks as $check) {
if ($check) { try {
return $request->routeIs($route['patterns']) ? $next($request) : redirect()->route($route['redirect']); $check = $check();
} catch (QueryException|InvalidArgumentException|PDOException $exception) {
$check = false;
logger()->error(
__('Configurazione del database mancante: ').$exception->getMessage(),
$exception->getTrace()
);
}
if (!$check) {
if (str_starts_with($request->route()?->getName(), 'setup.')) {
return $next($request);
}
return $request->wantsJson()
? \response()->json(['message' => __('Configurazione del database richiesta')], Response::HTTP_SERVICE_UNAVAILABLE)
: redirect()->route('setup.index');
} }
} }

View File

@ -0,0 +1,16 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class LocaleMiddleware
{
public function handle(Request $request, Closure $next): mixed
{
app()->setLocale(session()->get('locale', app()->getLocale()));
return $next($request);
}
}

View File

@ -6,15 +6,17 @@ use App\Providers\RouteServiceProvider;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated class RedirectIfAuthenticated
{ {
/** /**
* Handle an incoming request. * Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/ */
public function handle(Request $request, Closure $next, array $guards = []): mixed public function handle(Request $request, Closure $next, string ...$guards): Response
{ {
/** @noinspection CallableParameterUseCaseInTypeContextInspection */
$guards = empty($guards) ? [null] : $guards; $guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) { foreach ($guards as $guard) {

View File

@ -9,7 +9,7 @@ class TrimStrings extends Middleware
/** /**
* The names of the attributes that should not be trimmed. * The names of the attributes that should not be trimmed.
* *
* @var array * @var array<int, string>
*/ */
protected $except = [ protected $except = [
'current_password', 'current_password',

View File

@ -8,6 +8,8 @@ class TrustHosts extends Middleware
{ {
/** /**
* Get the host patterns that should be trusted. * Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/ */
public function hosts(): array public function hosts(): array
{ {

View File

@ -1,46 +0,0 @@
<?php
namespace App\JsonApi\V1;
use App\Http\Controllers\Controller;
use App\JsonApi\V1\Users\UserSchema;
use LaravelJsonApi\Core\Server\Server as BaseServer;
class Server extends BaseServer
{
/**
* The base URI namespace for this server.
*/
protected string $baseUri = '/api/v1';
/**
* Bootstrap the server when it is handling an HTTP request.
*/
public function serving(): void
{
// no-op
}
/**
* Get the server's list of schemas.
*/
protected function allSchemas(): array
{
return app(Controller::class)
->getModules()
->pluck('config.api.schemas')
->reject(null)
->push(UserSchema::class)
->flatten()
->all();
}
/**
* @inheritdoc
* TODO: Temporary: it must be added authentication to API routes
*/
public function authorizable(): bool
{
return false;
}
}

View File

@ -1,23 +0,0 @@
<?php
namespace App\JsonApi\V1\Users;
use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest;
class UserRequest extends ResourceRequest
{
/**
* Get the validation rules for the resource.
*
* @return array{username: string[], email: string[]}
*/
public function rules(): array
{
return [
'username' => ['required', 'string', 'unique:users,username'],
'email' => ['required', 'string', 'email', 'unique:users,email'],
];
}
}

View File

@ -1,54 +0,0 @@
<?php
namespace App\JsonApi\V1\Users;
use App\Models\User;
use LaravelJsonApi\Eloquent\Contracts\Paginator;
use LaravelJsonApi\Eloquent\Fields\DateTime;
use LaravelJsonApi\Eloquent\Fields\ID;
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
use LaravelJsonApi\Eloquent\Pagination\PagePagination;
use LaravelJsonApi\Eloquent\Schema;
class UserSchema extends Schema
{
/**
* The model the schema corresponds to.
*/
public static string $model = User::class;
/**
* Get the resource fields.
*/
public function fields(): array
{
return [
ID::make(),
Str::make('username'),
Str::make('email'),
DateTime::make('createdAt')->sortable()->readOnly(),
DateTime::make('updatedAt')->sortable()->readOnly(),
];
}
/**
* Get the resource filters.
*/
public function filters(): array
{
return [
WhereIdIn::make($this),
];
}
/**
* Get the resource paginator.
*/
public function pagination(): ?Paginator
{
return PagePagination::make();
}
}

View File

@ -5,11 +5,15 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Rawilk\Settings\Models\HasSettings;
class User extends Authenticatable class User extends Authenticatable
{ {
use HasSettings;
use HasFactory; use HasFactory;
use Notifiable; use Notifiable;
use HasApiTokens;
/** /**
* The attributes that are mass assignable. * The attributes that are mass assignable.

View File

@ -0,0 +1,77 @@
<?php
namespace App;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\File;
use Illuminate\Support\ServiceProvider;
use ReflectionClass;
abstract class ModuleServiceProvider extends ServiceProvider
{
public static string $name = '';
public static string $slug = '';
public static string $author = '';
public static string $description = '';
public static string $version = '';
public static string $url = '';
public static function name(): string
{
return static::$name;
}
public static function description(): string
{
return static::$description;
}
public static function slug(): string
{
$slug = static::$slug;
if (empty($slug)) {
$cachedPackages = require app()->getCachedServicesPath();
$slug = array_key_first(Arr::where($cachedPackages, static fn (array $package) => in_array(static::class, $package['providers'], true)));
static::$slug = $slug;
}
return $slug;
}
public static function author(): string
{
$author = static::$author;
if (empty($author)) {
$slug = static::slug();
$author = explode('/', $slug)[0] ?? '';
static::$author = $author;
}
return $author;
}
public static function version(): string
{
return static::$version;
}
public static function url(): string
{
return static::$url;
}
public static function modulePath(): string
{
return dirname((new ReflectionClass(static::class))->getFileName());
}
public static function hasBootstrap(): bool
{
return File::exists(static::modulePath().DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'ts'.DIRECTORY_SEPARATOR.'bootstrap.tsx');
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Policies;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class UserPolicy
{
use HandlesAuthorization;
public function allowRestify(User $user = null): bool
{
return true;
}
public function show(User $user = null, User $model): bool
{
return true;
}
public function store(User $user): bool
{
return false;
}
public function storeBulk(User $user): bool
{
return false;
}
public function update(User $user, User $model): bool
{
return false;
}
public function updateBulk(User $user, User $model): bool
{
return false;
}
public function deleteBulk(User $user, User $model): bool
{
return false;
}
public function delete(User $user, User $model): bool
{
return true;
}
}

View File

@ -4,8 +4,8 @@ namespace App\Providers;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Exception; use Exception;
use Illuminate\Support\Facades\Vite;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Nette\Utils\Json;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@ -18,15 +18,15 @@ class AppServiceProvider extends ServiceProvider
/** /**
* Bootstrap any application services. * Bootstrap any application services.
*
* @throws Exception * @throws Exception
*
* @noinspection StaticClosureCanBeUsedInspection Throws Cannot bind an instance to a static closure
* @noinspection AnonymousFunctionStaticInspection Throws Cannot bind an instance to a static closure
*/ */
public function boot(Controller $controller): void public function boot(Controller $controller): void
{ {
cache()->rememberForever( view()->share('modules', $controller->getModules());
'translations_' . app()->getLocale(), Vite::macro('image', fn ($asset) => Vite::asset("resources/images/$asset"));
static fn() => Json::decode(file_get_contents(resource_path('lang/' . app()->getLocale() . '.json')))
);
view()->share('modules', $controller->getModules(request()));
} }
} }

View File

@ -0,0 +1,58 @@
<?php
namespace App\Providers;
use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Models\User;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;
class FortifyServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::authenticateUsing(static function (Request $request) {
$user = User::where('email', $request->username)
->orWhere('username', $request->username)
->first();
if ($user && Hash::check($request->password, $user->password)) {
return $user;
}
return false;
});
// Fortify::createUsersUsing(CreateNewUser::class);
// Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
// Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
RateLimiter::for('login', function (Request $request) {
$email = (string) $request->email;
return Limit::perMinute(5)->by($email.$request->ip());
});
RateLimiter::for('two-factor', function (Request $request) {
return Limit::perMinute(5)->by($request->session()->get('login.id'));
});
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace App\Providers;
use App\Http\Controllers\Controller;
use Binaryk\LaravelRestify\Restify;
use Binaryk\LaravelRestify\RestifyApplicationServiceProvider;
use Illuminate\Support\Facades\Gate;
class RestifyServiceProvider extends RestifyApplicationServiceProvider
{
/**
* Register the Restify gate.
*
* This gate determines who can access Restify in non-local environments.
*/
protected function gate(): void
{
Gate::define('viewRestify', function ($user) {
return in_array($user->email, [
]);
});
}
protected function repositories(): void
{
parent::repositories();
// Register repositories from modules
$modules = app(Controller::class)->getModules();
foreach ($modules as $module) {
Restify::repositoriesFrom($module['module_path'].DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.'Api', app()->getNamespace());
}
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace App\Restify;
use Binaryk\LaravelRestify\Filters\MatchFilter;
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
use Binaryk\LaravelRestify\Repositories\Repository as RestifyRepository;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
abstract class Repository extends RestifyRepository
{
public static array $sort = ['id'];
/**
* Build a "show" and "index" query for the given repository.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function mainQuery(RestifyRequest $request, Builder|Relation $query)
{
return $query;
}
/**
* Build an "index" query for the given repository.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function indexQuery(RestifyRequest $request, Builder|Relation $query)
{
return $query;
}
/**
* Build a "show" query for the given repository.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function showQuery(RestifyRequest $request, Builder|Relation $query)
{
return $query;
}
public static function matches(): array
{
return array_map(static fn (string $type) => MatchFilter::make()->setType($type)->partial(), static::$match);
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Restify;
use App\Models\User;
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
class UserRepository extends Repository
{
public static string $model = User::class;
public static array $sort = ['id', 'username', 'email', 'created_at', 'updated_at'];
public static array $match = [
'id' => 'int',
'username' => 'string',
];
public function fields(RestifyRequest $request): array
{
return [
field('username')->rules('required'),
field('email')->storingRules('required', 'unique:users')->updatingRules('unique:users'),
field('created_at')->label('createdAt')->readOnly(),
field('updated_at')->label('updatedAt')->readOnly(),
];
}
}

View File

@ -31,39 +31,51 @@
"require": { "require": {
"php": ">=8.1", "php": ">=8.1",
"ext-pdo": "*", "ext-pdo": "*",
"akaunting/laravel-setting": "^1.2", "binaryk/laravel-restify": "^8",
"guzzlehttp/guzzle": "^7.4", "guzzlehttp/guzzle": "^7",
"inertiajs/inertia-laravel": "^0.5", "inertiajs/inertia-laravel": "^0",
"innocenzi/laravel-vite": "^0.2", "jackiedo/dotenv-editor": "^2",
"laravel-json-api/laravel": "^2.1", "laravel/fortify": "*",
"laravel/framework": "^9.0", "laravel/framework": "^10",
"laravel/tinker": "^2.7", "laravel/sanctum": "^3",
"nette/utils": "^3.2", "laravel/tinker": "^2",
"spatie/file-system-watcher": "^1.1", "nette/utils": "^4",
"tightenco/ziggy": "^1.4", "opcodesio/log-viewer": "^2",
"wikimedia/composer-merge-plugin": "^2.0" "outhebox/blade-flags": "^1",
"rawilk/laravel-settings": "^2",
"spatie/file-system-watcher": "^1",
"tightenco/ziggy": "^1",
"wikimedia/composer-merge-plugin": "^2"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.6", "barryvdh/laravel-debugbar": "^3",
"barryvdh/laravel-ide-helper": "^2.12", "doctrine/dbal": "^3.6",
"friendsofphp/php-cs-fixer": "^3.6", "driftingly/rector-laravel": "^0",
"kkomelin/laravel-translatable-string-exporter": "^1.16", "fakerphp/faker": "^1",
"nunomaduro/collision": "^6.1", "friendsofphp/php-cs-fixer": "^3",
"rector/rector": "^0.14.5", "fumeapp/modeltyper": "^2.1",
"glhd/laravel-dumper": "^1",
"laravel-lang/attributes": "^2",
"laravel-lang/lang": "^12",
"laravel-lang/publisher": "^14",
"laravel/pint": "^1",
"nunomaduro/collision": "^7",
"nunomaduro/larastan": "^2",
"rector/rector": "^0",
"roave/security-advisories": "dev-latest", "roave/security-advisories": "dev-latest",
"spatie/laravel-ignition": "^1.0" "spatie/laravel-ignition": "^2",
"thiagocordeiro/laravel-translator": "^1"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"App\\": "app/", "App\\": "app/"
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
} }
}, },
"scripts": { "scripts": {
"post-autoload-dump": [ "post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi" "@php artisan package:discover --ansi",
"@php artisan vendor:publish --tag=blade-flags --tag=log-viewer-assets --force"
], ],
"post-root-package-install": [ "post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
@ -83,7 +95,6 @@
"extra": { "extra": {
"merge-plugin": { "merge-plugin": {
"include": [ "include": [
"./composer.local.json"
], ],
"replace": true "replace": true
} }

View File

@ -173,7 +173,9 @@ return [
App\Providers\AuthServiceProvider::class, App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class, // App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\RestifyServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,
\App\Providers\FortifyServiceProvider::class,
], ],
@ -229,6 +231,7 @@ return [
'URL' => Illuminate\Support\Facades\URL::class, 'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class, 'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class, 'View' => Illuminate\Support\Facades\View::class,
'Vite' => Illuminate\Support\Facades\Vite::class,
], ],

147
config/fortify.php Normal file
View File

@ -0,0 +1,147 @@
<?php
use App\Providers\RouteServiceProvider;
use Laravel\Fortify\Features;
return [
/*
|--------------------------------------------------------------------------
| Fortify Guard
|--------------------------------------------------------------------------
|
| Here you may specify which authentication guard Fortify will use while
| authenticating users. This value should correspond with one of your
| guards that is already present in your "auth" configuration file.
|
*/
'guard' => 'web',
/*
|--------------------------------------------------------------------------
| Fortify Password Broker
|--------------------------------------------------------------------------
|
| Here you may specify which password broker Fortify can use when a user
| is resetting their password. This configured value should match one
| of your password brokers setup in your "auth" configuration file.
|
*/
'passwords' => 'users',
/*
|--------------------------------------------------------------------------
| Username / Email
|--------------------------------------------------------------------------
|
| This value defines which model attribute should be considered as your
| application's "username" field. Typically, this might be the email
| address of the users but you are free to change this value here.
|
| Out of the box, Fortify expects forgot password and reset password
| requests to have a field named 'email'. If the application uses
| another name for the field you may define it below as needed.
|
*/
'username' => 'username',
'email' => 'email',
/*
|--------------------------------------------------------------------------
| Home Path
|--------------------------------------------------------------------------
|
| Here you may configure the path where users will get redirected during
| authentication or password reset when the operations are successful
| and the user is authenticated. You are free to change this value.
|
*/
'home' => RouteServiceProvider::HOME,
/*
|--------------------------------------------------------------------------
| Fortify Routes Prefix / Subdomain
|--------------------------------------------------------------------------
|
| Here you may specify which prefix Fortify will assign to all the routes
| that it registers with the application. If necessary, you may change
| subdomain under which all of the Fortify routes will be available.
|
*/
'prefix' => '',
'domain' => null,
/*
|--------------------------------------------------------------------------
| Fortify Routes Middleware
|--------------------------------------------------------------------------
|
| Here you may specify which middleware Fortify will assign to the routes
| that it registers with the application. If necessary, you may change
| these middleware but typically this provided default is preferred.
|
*/
'middleware' => ['web'],
/*
|--------------------------------------------------------------------------
| Rate Limiting
|--------------------------------------------------------------------------
|
| By default, Fortify will throttle logins to five requests per minute for
| every email and IP address combination. However, if you would like to
| specify a custom rate limiter to call then you may specify it here.
|
*/
'limiters' => [
'login' => 'login',
'two-factor' => 'two-factor',
],
/*
|--------------------------------------------------------------------------
| Register View Routes
|--------------------------------------------------------------------------
|
| Here you may specify if the routes returning views should be disabled as
| you may not need them when building your own application. This may be
| especially true if you're writing a custom single-page application.
|
*/
'views' => false,
/*
|--------------------------------------------------------------------------
| Features
|--------------------------------------------------------------------------
|
| Some of the Fortify features are optional. You may disable the features
| by removing them from this array. You're free to only remove some of
| these features or you can even remove all of these if you need to.
|
*/
'features' => [
Features::registration(),
Features::resetPasswords(),
// Features::emailVerification(),
// Features::updateProfileInformation(),
// Features::updatePasswords(),
// Features::twoFactorAuthentication([
// 'confirm' => true,
// 'confirmPassword' => true,
// // 'window' => 0,
// ]),
],
];

View File

@ -4,7 +4,7 @@ return [
// Directories to search in. // Directories to search in.
'directories' => [ 'directories' => [
'app', 'app',
'resources/js', 'resources/ts',
'resources/views', 'resources/views',
], ],
@ -22,7 +22,8 @@ return [
// If your function name contains $ escape it using \$ . // If your function name contains $ escape it using \$ .
'functions' => [ 'functions' => [
'__', '__',
'_t', '_s',
'_v',
'@lang', '@lang',
], ],

168
config/restify.php Normal file
View File

@ -0,0 +1,168 @@
<?php
use Binaryk\LaravelRestify\Http\Middleware\AuthorizeRestify;
use Binaryk\LaravelRestify\Http\Middleware\DispatchRestifyStartingEvent;
use Binaryk\LaravelRestify\Repositories\ActionLogRepository;
return [
'auth' => [
/*
|--------------------------------------------------------------------------
| Table containing authenticatable resource
|--------------------------------------------------------------------------
|
| This configuration contain the name of the table used for the authentication.
|
*/
'table' => 'users',
/*
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
| Next you may configure the package you're using for the personal tokens generation,
| this will be used for the verification of the authenticatable model and provide the
| authorizable functionality
|
| Supported: "sanctum"
*/
'provider' => 'sanctum',
/*
|--------------------------------------------------------------------------
| Auth frontend app url
|--------------------------------------------------------------------------
|
|URL used for reset password URL generating.
|
|
*/
'frontend_app_url' => env('FRONTEND_APP_URL', env('APP_URL')),
'password_reset_url' => env('FRONTEND_APP_URL').'/password/reset?token={token}&email={email}',
'user_verify_url' => env('FRONTEND_APP_URL').'/verify/{id}/{emailHash}',
'user_model' => "\App\Models\User",
],
/*
|--------------------------------------------------------------------------
| RestifyJS
|--------------------------------------------------------------------------
|
| This configuration is used for supporting the RestifyJS
|
*/
'restifyjs' => [
/*
| Token to authorize the setup endpoint.
*/
'token' => env('RESTIFYJS_TOKEN', 'testing'),
/*
| The API base url.
*/
'api_url' => env('API_URL', env('APP_URL')),
],
/*
|--------------------------------------------------------------------------
| Restify Base Route
|--------------------------------------------------------------------------
|
| This configuration is used as a prefix path where Restify will be accessible from.
| Feel free to change this path to anything you like.
|
*/
'base' => '/api/restify',
/*
|--------------------------------------------------------------------------
| Restify Route Middleware
|--------------------------------------------------------------------------
|
| These middleware will be assigned to every Restify route, giving you the
| chance to add your own middleware to this stack or override any of
| the existing middleware. Or, you can just stick with this stack.
|
*/
'middleware' => [
'api',
'auth:sanctum',
DispatchRestifyStartingEvent::class,
AuthorizeRestify::class,
],
/*
|--------------------------------------------------------------------------
| Restify Logs
|--------------------------------------------------------------------------
*/
'logs' => [
/*
| Repository used to list logs.
*/
'repository' => ActionLogRepository::class,
/**
| Inform restify to log or not action logs.
*/
'enable' => env('RESTIFY_ENABLE_LOGS', true),
/**
| Inform restify to log model changes from any source, or just restify. Set to `false` to log just restify logs.
*/
'all' => env('RESTIFY_WRITE_ALL_LOGS', false),
],
/*
|--------------------------------------------------------------------------
| Restify Search
|--------------------------------------------------------------------------
*/
'search' => [
/*
| Specify either the search should be case-sensitive or not.
*/
'case_sensitive' => true,
],
'repositories' => [
/*
| Specify either to serialize index meta (policy) information or not. For performance reasons we recommend disabling it.
*/
'serialize_index_meta' => false,
/*
| Specify either to serialize show meta (policy) information or not.
*/
'serialize_show_meta' => true,
],
'cache' => [
/*
| Specify the cache configuration for the resources policies.
| When enabled, methods from the policy will be cached for the active user.
*/
'policies' => [
'enabled' => false,
'ttl' => 5 * 60, // seconds
],
],
/*
| Specify if restify can call OpenAI for solution generation.
|
| By default this feature is enabled, but you still have to extend the Exception handler with the Restify one and set the API key.
*/
'ai_solutions' => true,
];

67
config/sanctum.php Normal file
View File

@ -0,0 +1,67 @@
<?php
use Laravel\Sanctum\Sanctum;
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:8000,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
Sanctum::currentApplicationUrlWithPort()
))),
/*
|--------------------------------------------------------------------------
| Sanctum Guards
|--------------------------------------------------------------------------
|
| This array contains the authentication guards that will be checked when
| Sanctum is trying to authenticate a request. If none of these guards
| are able to authenticate the request, Sanctum will use the bearer
| token that's present on an incoming request for authentication.
|
*/
'guard' => ['web'],
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. If this value is null, personal access tokens do
| not expire. This won't tweak the lifetime of first-party sessions.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
];

20
config/translator.php Normal file
View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
use Translator\Framework\LaravelConfigLoader;
use Translator\Infra\LaravelJsonTranslationRepository;
return [
'languages' => ['pt-br', 'es'],
'directories' => [
app_path(),
resource_path('views'),
],
'output' => resource_path('lang'),
'extensions' => ['php'],
'container' => [
'config_loader' => LaravelConfigLoader::class,
'translation_repository' => LaravelJsonTranslationRepository::class,
],
];

View File

@ -1,115 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Configurations
|--------------------------------------------------------------------------
| The following describes a set of configurations that can be used
| independently. Because Vite does not support generating multiple
| bundles, using separate configuration files is necessary.
| https://laravel-vite.dev/configuration/laravel-package.html#configs
*/
'configs' => [
'default' => [
'entrypoints' => [
'paths' => [
'resources/js/index.ts',
'resources/js/app.ts',
'resources/js/styles.ts',
'resources/js/_material.ts',
],
'ignore' => '/\\.(d\\.ts|json)$/',
],
'dev_server' => [
'enabled' => true,
'url' => env('DEV_SERVER_URL', 'http://localhost:3000'),
'ping_before_using_manifest' => true,
'ping_url' => null,
'ping_timeout' => 1,
'key' => env('DEV_SERVER_KEY'),
'cert' => env('DEV_SERVER_CERT'),
],
'build_path' => 'build',
],
],
/*
|--------------------------------------------------------------------------
| Aliases
|--------------------------------------------------------------------------
| You can define aliases to avoid having to make relative imports.
| Aliases will be written to tsconfig.json automatically so your IDE
| can know how to resolve them.
| https://laravel-vite.dev/configuration/laravel-package.html#aliases
*/
'aliases' => [
'@osm' => 'resources/js',
'@osm-images' => 'public/images',
'@osm-scss' => 'resources/scss',
],
/*
|--------------------------------------------------------------------------
| Commands
|--------------------------------------------------------------------------
| Before starting the development server or building the assets, you
| may need to run specific commands. With these options, you can
| define what to run, automatically.
| https://laravel-vite.dev/configuration/laravel-package.html#commands
*/
'commands' => [
'artisan' => [
'vite:tsconfig',
// 'typescript:generate'
],
'shell' => [],
],
/*
|--------------------------------------------------------------------------
| Testing
|--------------------------------------------------------------------------
| Depending on the way you are testing your application,
| you may or may not need to use the manifest. This option controls
| the manifest should be used in the "testing" environment.
| https://laravel-vite.dev/configuration/laravel-package.html#testing
*/
'testing' => [
'use_manifest' => false,
],
/*
|--------------------------------------------------------------------------
| Environment variable prefixes
|--------------------------------------------------------------------------
| This option defines the prefixes that environment variables must
| have in order to be accessible from the front-end.
| https://laravel-vite.dev/configuration/laravel-package.html#env_prefixes
*/
'env_prefixes' => ['VITE_', 'MIX_', 'SCRIPT_'],
/*
|--------------------------------------------------------------------------
| Default interfaces
|--------------------------------------------------------------------------
| Here you may change how some parts of the package work by replacing
| their associated logic.
| https://laravel-vite.dev/configuration/laravel-package.html#interfaces
*/
'interfaces' => [
'heartbeat_checker' => Innocenzi\Vite\HeartbeatCheckers\HttpHeartbeatChecker::class,
'tag_generator' => Innocenzi\Vite\TagGenerators\CallbackTagGenerator::class,
'entrypoints_finder' => Innocenzi\Vite\EntrypointsFinder\DefaultEntrypointsFinder::class,
],
/*
|--------------------------------------------------------------------------
| Default configuration
|--------------------------------------------------------------------------
| Here you may specify which of the configurations above you wish
| to use as your default one.
| https://laravel-vite.dev/configuration/laravel-package.html#default
*/
'default' => env('VITE_DEFAULT_CONFIG', 'default'),
];

View File

@ -1,47 +0,0 @@
<?php /** @noinspection PhpUnused */
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use JetBrains\PhpStorm\ArrayShape;
use Illuminate\Support\Carbon;
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* @noinspection PhpUndefinedMethodInspection
* @return array{name: mixed, email: mixed, email_verified_at: \Illuminate\Support\Carbon, password: string, remember_token: string}
*/
#[ArrayShape(['name' => 'string', 'email' => 'mixed', 'email_verified_at' => Carbon::class, 'password' => 'string', 'remember_token' => 'string'])]
public function definition(): array
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): Factory
{
return $this->state(static fn() => [
'email_verified_at' => null,
]);
}
}

View File

@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Laravel\Fortify\Fortify;
return new class() extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->text('two_factor_secret')
->after('password')
->nullable();
$table->text('two_factor_recovery_codes')
->after('two_factor_secret')
->nullable();
if (Fortify::confirmsTwoFactorAuthentication()) {
$table->timestamp('two_factor_confirmed_at')
->after('two_factor_recovery_codes')
->nullable();
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(array_merge([
'two_factor_secret',
'two_factor_recovery_codes',
], Fortify::confirmsTwoFactorAuthentication() ? [
'two_factor_confirmed_at',
] : []));
});
}
};

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class() extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View File

@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class() extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('action_logs', function (Blueprint $table) {
$table->id();
$table->char('batch_id', 36);
$table->unsignedBigInteger('user_id')->index()->nullable();
$table->string('name');
$table->string('actionable_type');
$table->unsignedBigInteger('actionable_id');
$table->string('target_type')->nullable();
$table->unsignedBigInteger('target_id')->nullable();
$table->string('model_type')->nullable();
$table->unsignedBigInteger('model_id')->nullable();
$table->text('fields')->nullable();
$table->string('status', 25)->default('running');
$table->text('original')->nullable();
$table->text('changes')->nullable();
$table->text('exception')->nullable();
$table->json('meta')->nullable();
$table->timestamps();
$table->index(['actionable_type', 'actionable_id']);
$table->index(['batch_id', 'model_type', 'model_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('action_logs');
}
};

View File

@ -1,16 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// \App\Models\User::factory(10)->create();
}
}

112
lang/en.json Normal file
View File

@ -0,0 +1,112 @@
{
"(and :count more error)": "(and :count more error)",
"(and :count more errors)": "(and :count more errors)",
"* Campi obbligatori": "* Mandatory Fields",
"Accedi": "Login",
"Account creato con successo. Puoi ora accedere.": "Account created successfully. You can now login.",
"Aggiornamento del frontend disponibile!": "An update of the frontend available!",
"Aggiungi": "Add",
"Aggiungi nuovo record": "Add new record",
"All rights reserved.": "All rights reserved.",
"Annulla": "Cancel",
"assistenza ufficiale": "official assistance",
"Bandiera della lingua :language": "Bandiera della lingua :language",
"Benvenuto in :name!": "Welcome to :name!",
"Cambia periodo": "Change period",
"Campi non validi. Controlla i dati inseriti": "Invalid fields. Check the entered data",
"Conferma": "Confirm",
"Conferma password": "Confirm Password",
"Connessione al database riuscita": "Successfully connected to the database",
"Crea account": "Create account",
"Creazione account amministratore": "Administrator account creation",
"Dashboard": "Dashboard",
"Database": "Database",
"Elimina": "Delete",
"Email": "Email",
"Errore durante il salvataggio: :error": "Error during the save: :error",
"Errore durante l'eliminazione: :error": "Errore durante l'eliminazione: :error",
"Esci": "Exit",
"Esempio: :example": "Example : :example",
"Forbidden": "Forbidden",
"Formato data corta": "Short date format",
"Formato data lunga": "Long date format",
"Formato date": "Date format",
"Formato orario": "Time format",
"forum": "forum",
"Go to page :page": "Go to page :page",
"Hello!": "Hello!",
"Ho visionato e accetto la licenza": "I have visioned and I accept the license",
"Host": "Host",
"I formati sono impostabili attraverso lo standard previsto da :link.": "I formati sono impostabili attraverso lo standard previsto da :link.",
"If you did not create an account, no further action is required.": "If you did not create an account, no further action is required.",
"If you did not request a password reset, no further action is required.": "If you did not request a password reset, no further action is required.",
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:",
"Il tuo profilo": "Your profile",
"Impossibile connettersi al database selezionato! Controllare il nome del database": "Unable to connect to the selected database! Check the name of the database",
"Impossibile scrivere il file di configurazione. :action": "Unable to write the config file. :action",
"Impostazioni salvate correttamente": "Saved settings correctly",
"Inserisci le informazioni richieste per creare un nuovo account amministratore.": "Inserisci le informazioni richieste per creare un nuovo account amministratore.",
"L'utente del database non ha i seguenti permessi necessari: ": "The database user does not have the following necessary permits: ",
"La password è stata inviata alla tua email": "Your password has been sent to your email",
"Le credenziali non sono valide.": "The credentials are not valid.",
"Le password non corrispondono": "Passwords do not match",
"Licenza": "License",
"Lingua": "Language",
"Login": "Login",
"Logout": "Logout",
"No": "No",
"Nome database": "Database name",
"Nome utente": "Username",
"Nome utente/email": "Username/email",
"Non sono presenti dati": "There are no data",
"Not Found": "Not Found",
"Notifiche": "Notifications",
"of": "of",
"OpenSTAManager": "OpenSTAManager",
"OpenSTAManager è tutelato dalla licenza GPL 3.0, da accettare obbligatoriamente per poter utilizzare il gestionale.": "OpenSTAManager è tutelato dalla licenza GPL 3.0, da accettare obbligatoriamente per poter utilizzare il gestionale.",
"Page Expired": "Page Expired",
"Pagination Navigation": "Pagination Navigation",
"Password": "Password",
"Payment Required": "Payment Required",
"Please click the button below to verify your email address.": "Please click the button below to verify your email address.",
"Record eliminato!": "Record deleted!",
"Record salvato": "Record saved",
"Regards": "Regards",
"Register": "Register",
"Reimposta password": "Reset password",
"Reset della password effettuato con successo. Puoi ora accedere.": "Reset of the password done successfully. You can now access.",
"Reset Password": "Reset Password",
"Reset Password Notification": "Reset Password Notification",
"Resetta password": "Reset Password",
"results": "results",
"Ricarica": "Reload",
"Ricordami": "Remind me",
"Salva e installa": "Save and install",
"Se necessiti supporto puoi contattarci tramite l':contactLink o tramite il nostro :forumLink.": "Se necessiti supporto puoi contattarci tramite l':contactLink o tramite il nostro :forumLink.",
"Sei sicuro di voler eliminare questo record?": "Are you sure you want to eliminate this record?",
"Seleziona una voce dal menu a sinistra": "Select an entry from the menu on the left",
"Server Error": "Server Error",
"Service Unavailable": "Service Unavailable",
"Showing": "Showing",
"Si è verificato un errore durante la connessione al database: :error": "An error occurred during the connection to the database: :error",
"Stampa": "Print",
"Sì": "Yes",
"Testa il database": "Try the database",
"The :attribute must contain at least one letter.": "The :attribute must contain at least one letter.",
"The :attribute must contain at least one number.": "The :attribute must contain at least one number.",
"The :attribute must contain at least one symbol.": "The :attribute must contain at least one symbol.",
"The :attribute must contain at least one uppercase and one lowercase letter.": "The :attribute must contain at least one uppercase and one lowercase letter.",
"The given :attribute has appeared in a data leak. Please choose a different :attribute.": "The given :attribute has appeared in a data leak. Please choose a different :attribute.",
"The given data was invalid.": "The given data was invalid.",
"This password reset link will expire in :count minutes.": "This password reset link will expire in :count minutes.",
"to": "to",
"Toggle navigation": "Toggle navigation",
"Too Many Requests": "Too Many Requests",
"Unauthorized": "Unauthorized",
"Verify Email Address": "Verify Email Address",
"Versione": "Version",
"Versioni tradotte": "Translated versions",
"Whoops!": "Whoops!",
"You are receiving this email because we received a password reset request for your account.": "You are receiving this email because we received a password reset request for your account.",
"È ora possibile lavorare offline!": "It is now possible to work offline!"
}

9
lang/en/auth.php Normal file
View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
return [
'failed' => 'These credentials do not match our records.',
'password' => 'The password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
];

8
lang/en/pagination.php Normal file
View File

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
return [
'next' => 'Next &raquo;',
'previous' => '&laquo; Previous',
];

11
lang/en/passwords.php Normal file
View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
return [
'reset' => 'Your password has been reset!',
'sent' => 'We have emailed your password reset link!',
'throttled' => 'Please wait before retrying.',
'token' => 'This password reset token is invalid.',
'user' => 'We can\'t find a user with that email address.',
];

View File

@ -1,33 +1,25 @@
<?php <?php
declare(strict_types=1);
return [ return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.', 'accepted' => 'The :attribute must be accepted.',
'accepted_if' => 'The :attribute must be accepted when :other is :value.',
'active_url' => 'The :attribute is not a valid URL.', 'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.', 'after' => 'The :attribute must be a date after :date.',
'after_or_equal' => 'The :attribute must be a date after or equal to :date.', 'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
'alpha' => 'The :attribute must only contain letters.', 'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.', 'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
'alpha_num' => 'The :attribute must only contain letters and numbers.', 'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.', 'array' => 'The :attribute must be an array.',
'ascii' => 'The :attribute must only contain single-byte alphanumeric characters and symbols.',
'before' => 'The :attribute must be a date before :date.', 'before' => 'The :attribute must be a date before :date.',
'before_or_equal' => 'The :attribute must be a date before or equal to :date.', 'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
'between' => [ 'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.', 'array' => 'The :attribute must have between :min and :max items.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'numeric' => 'The :attribute must be between :min and :max.',
'string' => 'The :attribute must be between :min and :max characters.',
], ],
'boolean' => 'The :attribute field must be true or false.', 'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.', 'confirmed' => 'The :attribute confirmation does not match.',
@ -35,27 +27,33 @@ return [
'date' => 'The :attribute is not a valid date.', 'date' => 'The :attribute is not a valid date.',
'date_equals' => 'The :attribute must be a date equal to :date.', 'date_equals' => 'The :attribute must be a date equal to :date.',
'date_format' => 'The :attribute does not match the format :format.', 'date_format' => 'The :attribute does not match the format :format.',
'decimal' => 'The :attribute must have :decimal decimal places.',
'declined' => 'The :attribute must be declined.',
'declined_if' => 'The :attribute must be declined when :other is :value.',
'different' => 'The :attribute and :other must be different.', 'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.', 'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.', 'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.', 'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.', 'distinct' => 'The :attribute field has a duplicate value.',
'doesnt_end_with' => 'The :attribute may not end with one of the following: :values.',
'doesnt_start_with' => 'The :attribute may not start with one of the following: :values.',
'email' => 'The :attribute must be a valid email address.', 'email' => 'The :attribute must be a valid email address.',
'ends_with' => 'The :attribute must end with one of the following: :values.', 'ends_with' => 'The :attribute must end with one of the following: :values.',
'enum' => 'The selected :attribute is invalid.',
'exists' => 'The selected :attribute is invalid.', 'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.', 'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.', 'filled' => 'The :attribute field is required.',
'gt' => [ 'gt' => [
'numeric' => 'The :attribute must be greater than :value.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'string' => 'The :attribute must be greater than :value characters.',
'array' => 'The :attribute must have more than :value items.', 'array' => 'The :attribute must have more than :value items.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'numeric' => 'The :attribute must be greater than :value.',
'string' => 'The :attribute must be greater than :value characters.',
], ],
'gte' => [ 'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'string' => 'The :attribute must be greater than or equal :value characters.',
'array' => 'The :attribute must have :value items or more.', 'array' => 'The :attribute must have :value items or more.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'numeric' => 'The :attribute must be greater than or equal :value.',
'string' => 'The :attribute must be greater than or equal :value characters.',
], ],
'image' => 'The :attribute must be an image.', 'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.', 'in' => 'The selected :attribute is invalid.',
@ -65,92 +63,154 @@ return [
'ipv4' => 'The :attribute must be a valid IPv4 address.', 'ipv4' => 'The :attribute must be a valid IPv4 address.',
'ipv6' => 'The :attribute must be a valid IPv6 address.', 'ipv6' => 'The :attribute must be a valid IPv6 address.',
'json' => 'The :attribute must be a valid JSON string.', 'json' => 'The :attribute must be a valid JSON string.',
'lowercase' => 'The :attribute must be lowercase.',
'lt' => [ 'lt' => [
'numeric' => 'The :attribute must be less than :value.',
'file' => 'The :attribute must be less than :value kilobytes.',
'string' => 'The :attribute must be less than :value characters.',
'array' => 'The :attribute must have less than :value items.', 'array' => 'The :attribute must have less than :value items.',
'file' => 'The :attribute must be less than :value kilobytes.',
'numeric' => 'The :attribute must be less than :value.',
'string' => 'The :attribute must be less than :value characters.',
], ],
'lte' => [ 'lte' => [
'numeric' => 'The :attribute must be less than or equal :value.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'string' => 'The :attribute must be less than or equal :value characters.',
'array' => 'The :attribute must not have more than :value items.', 'array' => 'The :attribute must not have more than :value items.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'numeric' => 'The :attribute must be less than or equal :value.',
'string' => 'The :attribute must be less than or equal :value characters.',
], ],
'mac_address' => 'The :attribute must be a valid MAC address.',
'max' => [ 'max' => [
'numeric' => 'The :attribute must not be greater than :max.', 'array' => 'The :attribute may not have more than :max items.',
'file' => 'The :attribute must not be greater than :max kilobytes.', 'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute must not be greater than :max characters.', 'numeric' => 'The :attribute may not be greater than :max.',
'array' => 'The :attribute must not have more than :max items.', 'string' => 'The :attribute may not be greater than :max characters.',
], ],
'max_digits' => 'The :attribute must not have more than :max digits.',
'mimes' => 'The :attribute must be a file of type: :values.', 'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.', 'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [ 'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.', 'array' => 'The :attribute must have at least :min items.',
'file' => 'The :attribute must be at least :min kilobytes.',
'numeric' => 'The :attribute must be at least :min.',
'string' => 'The :attribute must be at least :min characters.',
], ],
'min_digits' => 'The :attribute must have at least :min digits.',
'missing' => 'The :attribute field must be missing.',
'missing_if' => 'The :attribute field must be missing when :other is :value.',
'missing_unless' => 'The :attribute field must be missing unless :other is :value.',
'missing_with' => 'The :attribute field must be missing when :values is present.',
'missing_with_all' => 'The :attribute field must be missing when :values are present.',
'multiple_of' => 'The :attribute must be a multiple of :value.', 'multiple_of' => 'The :attribute must be a multiple of :value.',
'not_in' => 'The selected :attribute is invalid.', 'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute format is invalid.', 'not_regex' => 'The :attribute format is invalid.',
'numeric' => 'The :attribute must be a number.', 'numeric' => 'The :attribute must be a number.',
'password' => 'The password is incorrect.', 'password' => [
'letters' => 'The :attribute must contain at least one letter.',
'mixed' => 'The :attribute must contain at least one uppercase and one lowercase letter.',
'numbers' => 'The :attribute must contain at least one number.',
'symbols' => 'The :attribute must contain at least one symbol.',
'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
],
'present' => 'The :attribute field must be present.', 'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values are present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'prohibited' => 'The :attribute field is prohibited.', 'prohibited' => 'The :attribute field is prohibited.',
'prohibited_if' => 'The :attribute field is prohibited when :other is :value.', 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.', 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
'prohibits' => 'The :attribute field prohibits :other from being present.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_array_keys' => 'The :attribute field must contain entries for: :values.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_if_accepted' => 'The :attribute field is required when :other is accepted.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.', 'same' => 'The :attribute and :other must match.',
'size' => [ 'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.', 'array' => 'The :attribute must contain :size items.',
'file' => 'The :attribute must be :size kilobytes.',
'numeric' => 'The :attribute must be :size.',
'string' => 'The :attribute must be :size characters.',
], ],
'starts_with' => 'The :attribute must start with one of the following: :values.', 'starts_with' => 'The :attribute must start with one of the following: :values',
'string' => 'The :attribute must be a string.', 'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid timezone.', 'timezone' => 'The :attribute must be a valid zone.',
'ulid' => 'The :attribute must be a valid ULID.',
'unique' => 'The :attribute has already been taken.', 'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.', 'uploaded' => 'The :attribute failed to upload.',
'url' => 'The :attribute must be a valid URL.', 'uppercase' => 'The :attribute must be uppercase.',
'url' => 'The :attribute format is invalid.',
'uuid' => 'The :attribute must be a valid UUID.', 'uuid' => 'The :attribute must be a valid UUID.',
'attributes' => [
/* 'address' => 'address',
|-------------------------------------------------------------------------- 'age' => 'age',
| Custom Validation Language Lines 'amount' => 'amount',
|-------------------------------------------------------------------------- 'area' => 'area',
| 'available' => 'available',
| Here you may specify custom validation messages for attributes using the 'birthday' => 'birthday',
| convention "attribute.rule" to name the lines. This makes it quick to 'body' => 'body',
| specify a specific custom language line for a given attribute rule. 'city' => 'city',
| 'content' => 'content',
*/ 'country' => 'country',
'created_at' => 'created at',
'custom' => [ 'creator' => 'creator',
'attribute-name' => [ 'current_password' => 'current password',
'rule-name' => 'custom-message', 'date' => 'date',
], 'date_of_birth' => 'date of birth',
'day' => 'day',
'deleted_at' => 'deleted at',
'description' => 'description',
'district' => 'district',
'duration' => 'duration',
'email' => 'email',
'excerpt' => 'excerpt',
'filter' => 'filter',
'first_name' => 'first name',
'gender' => 'gender',
'group' => 'group',
'hour' => 'hour',
'image' => 'image',
'last_name' => 'last name',
'lesson' => 'lesson',
'line_address_1' => 'line address 1',
'line_address_2' => 'line address 2',
'message' => 'message',
'middle_name' => 'middle name',
'minute' => 'minute',
'mobile' => 'mobile',
'month' => 'month',
'name' => 'name',
'national_code' => 'national code',
'number' => 'number',
'password' => 'password',
'password_confirmation' => 'password confirmation',
'phone' => 'phone',
'photo' => 'photo',
'postal_code' => 'postal code',
'price' => 'price',
'province' => 'province',
'recaptcha_response_field' => 'recaptcha response field',
'remember' => 'remember',
'restored_at' => 'restored at',
'result_text_under_image' => 'result text under image',
'role' => 'role',
'second' => 'second',
'sex' => 'sex',
'short_text' => 'short text',
'size' => 'size',
'state' => 'state',
'street' => 'street',
'student' => 'student',
'subject' => 'subject',
'teacher' => 'teacher',
'terms' => 'terms',
'test_description' => 'test description',
'test_locale' => 'test locale',
'test_name' => 'test name',
'text' => 'text',
'time' => 'time',
'title' => 'title',
'updated_at' => 'updated at',
'username' => 'username',
'year' => 'year',
], ],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
]; ];

112
lang/it.json Normal file
View File

@ -0,0 +1,112 @@
{
"(and :count more error)": "(e :count altro errore)",
"(and :count more errors)": "(e :count altri errori)",
"* Campi obbligatori": "* Campi obbligatori",
"Accedi": "Accedi",
"Account creato con successo. Puoi ora accedere.": "Account creato con successo. Puoi ora accedere.",
"Aggiornamento del frontend disponibile!": "Aggiornamento del frontend disponibile!",
"Aggiungi": "Aggiungi",
"Aggiungi nuovo record": "Aggiungi nuovo record",
"All rights reserved.": "Tutti i diritti riservati",
"Annulla": "Annulla",
"assistenza ufficiale": "assistenza ufficiale",
"Bandiera della lingua :language": "Bandiera della lingua :language",
"Benvenuto in :name!": "Benvenuto in :name!",
"Cambia periodo": "Cambia periodo",
"Campi non validi. Controlla i dati inseriti": "Campi non validi. Controlla i dati inseriti",
"Conferma": "Conferma",
"Conferma password": "Conferma password",
"Connessione al database riuscita": "Connessione al database riuscita",
"Crea account": "Crea account",
"Creazione account amministratore": "Creazione account amministratore",
"Dashboard": "Dashboard",
"Database": "Database",
"Elimina": "Elimina",
"Email": "Email",
"Errore durante il salvataggio: :error": "Errore durante il salvataggio: :error",
"Errore durante l'eliminazione: :error": "Errore durante l'eliminazione: :error",
"Esci": "Esci",
"Esempio: :example": "Esempio: :example",
"Forbidden": "Vietato",
"Formato data corta": "Formato data corta",
"Formato data lunga": "Formato data lunga",
"Formato date": "Formato date",
"Formato orario": "Formato orario",
"forum": "forum",
"Go to page :page": "Vai alla pagina :page",
"Hello!": "Ciao!",
"Ho visionato e accetto la licenza": "Ho visionato e accetto la licenza",
"Host": "Host",
"I formati sono impostabili attraverso lo standard previsto da :link.": "I formati sono impostabili attraverso lo standard previsto da :link.",
"If you did not create an account, no further action is required.": "Se non hai creato un account, non è richiesta alcuna azione.",
"If you did not request a password reset, no further action is required.": "Se non hai richiesto un reset della password, non è richiesta alcuna azione.",
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Se non riesci a cliccare sul pulsante \":actionText\", copia e incolla l'URL seguente\nnel tuo browser:",
"Il tuo profilo": "Il tuo profilo",
"Impossibile connettersi al database selezionato! Controllare il nome del database": "Impossibile connettersi al database selezionato! Controllare il nome del database",
"Impossibile scrivere il file di configurazione. :action": "Impossibile scrivere il file di configurazione. :action",
"Impostazioni salvate correttamente": "Impostazioni salvate correttamente",
"Inserisci le informazioni richieste per creare un nuovo account amministratore.": "Inserisci le informazioni richieste per creare un nuovo account amministratore.",
"L'utente del database non ha i seguenti permessi necessari: ": "L'utente del database non ha i seguenti permessi necessari: ",
"La password è stata inviata alla tua email": "La password è stata inviata alla tua email",
"Le credenziali non sono valide.": "Le credenziali non sono valide.",
"Le password non corrispondono": "Le password non corrispondono",
"Licenza": "Licenza",
"Lingua": "Lingua",
"Login": "Accedi",
"Logout": "Esci",
"No": "No",
"Nome database": "Nome database",
"Nome utente": "Nome utente",
"Nome utente/email": "Nome utente/email",
"Non sono presenti dati": "Non sono presenti dati",
"Not Found": "Non trovato",
"Notifiche": "Notifiche",
"of": "di",
"OpenSTAManager": "OpenSTAManager",
"OpenSTAManager è tutelato dalla licenza GPL 3.0, da accettare obbligatoriamente per poter utilizzare il gestionale.": "OpenSTAManager è tutelato dalla licenza GPL 3.0, da accettare obbligatoriamente per poter utilizzare il gestionale.",
"Page Expired": "Pagina scaduta",
"Pagination Navigation": "Navigazione della Paginazione",
"Password": "Password",
"Payment Required": "Pagamento richiesto",
"Please click the button below to verify your email address.": "Clicca sul pulsante qui sotto per verificare il tuo indirizzo email.",
"Record eliminato!": "Record eliminato!",
"Record salvato": "Record salvato",
"Regards": "Distinti saluti",
"Register": "Registrati",
"Reimposta password": "Reimposta password",
"Reset della password effettuato con successo. Puoi ora accedere.": "Reset della password effettuato con successo. Puoi ora accedere.",
"Reset Password": "Resetta la password",
"Reset Password Notification": "Notifica di reset della password",
"Resetta password": "Resetta password",
"results": "risultati",
"Ricarica": "Ricarica",
"Ricordami": "Ricordami",
"Salva e installa": "Salva e installa",
"Se necessiti supporto puoi contattarci tramite l':contactLink o tramite il nostro :forumLink.": "Se necessiti supporto puoi contattarci tramite l':contactLink o tramite il nostro :forumLink.",
"Sei sicuro di voler eliminare questo record?": "Sei sicuro di voler eliminare questo record?",
"Seleziona una voce dal menu a sinistra": "Seleziona una voce dal menu a sinistra",
"Server Error": "Errore server",
"Service Unavailable": "Servizio non disponibile",
"Showing": "Mostra",
"Si è verificato un errore durante la connessione al database: :error": "Si è verificato un errore durante la connessione al database: :error",
"Stampa": "Stampa",
"Sì": "Sì",
"Testa il database": "Testa il database",
"The :attribute must contain at least one letter.": ":Attribute deve contenere almeno una lettera.",
"The :attribute must contain at least one number.": ":Attribute deve contenere almeno un numero.",
"The :attribute must contain at least one symbol.": ":Attribute deve contenere almeno un carattere speciale.",
"The :attribute must contain at least one uppercase and one lowercase letter.": ":Attribute deve contenere almeno un carattere maiuscolo ed uno minuscolo.",
"The given :attribute has appeared in a data leak. Please choose a different :attribute.": ":Attribute sembra che faccia parte di un archivio con dati rubati. Per piacere, utilizza un valore differente.",
"The given data was invalid.": "I dati forniti non sono validi.",
"This password reset link will expire in :count minutes.": "Questo link di reset della password scadrà tra :count minuti.",
"to": "a",
"Toggle navigation": "Cambia navigazione",
"Too Many Requests": "Troppe richieste",
"Unauthorized": "Non autorizzato",
"Verify Email Address": "Verifica indirizzo email",
"Versione": "Versione",
"Versioni tradotte": "Versioni tradotte",
"Whoops!": "Ops!",
"You are receiving this email because we received a password reset request for your account.": "Hai ricevuto questa email perché abbiamo ricevuto una richiesta di reset della password per il tuo account.",
"È ora possibile lavorare offline!": "È ora possibile lavorare offline!"
}

9
lang/it/auth.php Normal file
View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
return [
'failed' => 'Credenziali non valide.',
'password' => 'Il campo :attribute non è corretto.',
'throttle' => 'Troppi tentativi di accesso. Riprova tra :seconds secondi.',
];

8
lang/it/pagination.php Normal file
View File

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
return [
'next' => 'Successivo &raquo;',
'previous' => '&laquo; Precedente',
];

11
lang/it/passwords.php Normal file
View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
return [
'reset' => 'La password è stata reimpostata!',
'sent' => 'Ti abbiamo inviato una email con il link per il reset della password!',
'throttled' => 'Per favore, attendi prima di riprovare.',
'token' => 'Questo token di reset della password non è valido.',
'user' => 'Non riusciamo a trovare un utente con questo indirizzo email.',
];

216
lang/it/validation.php Normal file
View File

@ -0,0 +1,216 @@
<?php
declare(strict_types=1);
return [
'accepted' => ':Attribute deve essere accettato.',
'accepted_if' => ':Attribute deve essere accettato quando :other è :value.',
'active_url' => ':Attribute non è un URL valido.',
'after' => ':Attribute deve essere una data successiva al :date.',
'after_or_equal' => ':Attribute deve essere una data successiva o uguale al :date.',
'alpha' => ':Attribute può contenere solo lettere.',
'alpha_dash' => ':Attribute può contenere solo lettere, numeri e trattini.',
'alpha_num' => ':Attribute può contenere solo lettere e numeri.',
'array' => ':Attribute deve essere un array.',
'ascii' => ':Attribute deve contenere solo caratteri alfanumerici single-byte e simboli.',
'before' => ':Attribute deve essere una data precedente al :date.',
'before_or_equal' => ':Attribute deve essere una data precedente o uguale al :date.',
'between' => [
'array' => ':Attribute deve avere tra :min - :max elementi.',
'file' => ':Attribute deve trovarsi tra :min - :max kilobyte.',
'numeric' => ':Attribute deve trovarsi tra :min - :max.',
'string' => ':Attribute deve trovarsi tra :min - :max caratteri.',
],
'boolean' => 'Il campo :attribute deve essere vero o falso.',
'confirmed' => 'Il campo di conferma per :attribute non coincide.',
'current_password' => 'Password non valida.',
'date' => ':Attribute non è una data valida.',
'date_equals' => ':Attribute deve essere una data e uguale a :date.',
'date_format' => ':Attribute non coincide con il formato :format.',
'decimal' => ':Attribute deve avere :decimal cifre decimali.',
'declined' => ':Attribute deve essere rifiutato.',
'declined_if' => ':Attribute deve essere rifiutato quando :other è :value.',
'different' => ':Attribute e :other devono essere differenti.',
'digits' => ':Attribute deve essere di :digits cifre.',
'digits_between' => ':Attribute deve essere tra :min e :max cifre.',
'dimensions' => 'Le dimensioni dell\'immagine di :attribute non sono valide.',
'distinct' => ':Attribute contiene un valore duplicato.',
'doesnt_end_with' => ':Attribute non può terminare con uno dei seguenti valori: :values.',
'doesnt_start_with' => ':Attribute non può iniziare con uno dei seguenti valori: :values.',
'email' => ':Attribute non è valido.',
'ends_with' => ':Attribute deve finire con uno dei seguenti valori: :values',
'enum' => 'Il campo :attribute non è valido.',
'exists' => ':Attribute selezionato non è valido.',
'file' => ':Attribute deve essere un file.',
'filled' => 'Il campo :attribute deve contenere un valore.',
'gt' => [
'array' => ':Attribute deve contenere più di :value elementi.',
'file' => ':Attribute deve essere maggiore di :value kilobyte.',
'numeric' => ':Attribute deve essere maggiore di :value.',
'string' => ':Attribute deve contenere più di :value caratteri.',
],
'gte' => [
'array' => ':Attribute deve contenere un numero di elementi uguale o maggiore di :value.',
'file' => ':Attribute deve essere uguale o maggiore di :value kilobyte.',
'numeric' => ':Attribute deve essere uguale o maggiore di :value.',
'string' => ':Attribute deve contenere un numero di caratteri uguale o maggiore di :value.',
],
'image' => ':Attribute deve essere un\'immagine.',
'in' => ':Attribute selezionato non è valido.',
'in_array' => 'Il valore del campo :attribute non esiste in :other.',
'integer' => ':Attribute deve essere un numero intero.',
'ip' => ':Attribute deve essere un indirizzo IP valido.',
'ipv4' => ':Attribute deve essere un indirizzo IPv4 valido.',
'ipv6' => ':Attribute deve essere un indirizzo IPv6 valido.',
'json' => ':Attribute deve essere una stringa JSON valida.',
'lowercase' => ':Attribute deve contenere solo caratteri minuscoli.',
'lt' => [
'array' => ':Attribute deve contenere meno di :value elementi.',
'file' => ':Attribute deve essere minore di :value kilobyte.',
'numeric' => ':Attribute deve essere minore di :value.',
'string' => ':Attribute deve contenere meno di :value caratteri.',
],
'lte' => [
'array' => ':Attribute deve contenere un numero di elementi minore o uguale a :value.',
'file' => ':Attribute deve essere minore o uguale a :value kilobyte.',
'numeric' => ':Attribute deve essere minore o uguale a :value.',
'string' => ':Attribute deve contenere un numero di caratteri minore o uguale a :value.',
],
'mac_address' => 'Il campo :attribute deve essere un indirizzo MAC valido .',
'max' => [
'array' => ':Attribute non può avere più di :max elementi.',
'file' => ':Attribute non può essere superiore a :max kilobyte.',
'numeric' => ':Attribute non può essere superiore a :max.',
'string' => ':Attribute non può contenere più di :max caratteri.',
],
'max_digits' => ':Attribute non può contenere più di :max cifre.',
'mimes' => ':Attribute deve essere del tipo: :values.',
'mimetypes' => ':Attribute deve essere del tipo: :values.',
'min' => [
'array' => ':Attribute deve avere almeno :min elementi.',
'file' => ':Attribute deve essere almeno di :min kilobyte.',
'numeric' => ':Attribute deve essere almeno :min.',
'string' => ':Attribute deve contenere almeno :min caratteri.',
],
'min_digits' => ':Attribute deve contenere almeno :min cifre.',
'missing' => 'Il campo :attribute deve mancare.',
'missing_if' => 'Il campo :attribute deve mancare quando :other è :value.',
'missing_unless' => 'Il campo :attribute deve mancare a meno che :other non sia :value.',
'missing_with' => 'Il campo :attribute deve mancare quando è presente :values.',
'missing_with_all' => 'Il campo :attribute deve mancare quando sono presenti :values.',
'multiple_of' => ':Attribute deve essere un multiplo di :value',
'not_in' => 'Il valore selezionato per :attribute non è valido.',
'not_regex' => 'Il formato di :attribute non è valido.',
'numeric' => ':Attribute deve essere un numero.',
'password' => [
'letters' => ':Attribute deve contenere almeno un carattere.',
'mixed' => ':Attribute deve contenere almeno un carattere maiuscolo ed un carattere minuscolo.',
'numbers' => ':Attribute deve contenere almeno un numero.',
'symbols' => ':Attribute deve contenere almeno un simbolo.',
'uncompromised' => ':Attribute è presente negli archivi dei dati trafugati. Per piacere scegli un valore differente per :attribute.',
],
'present' => 'Il campo :attribute deve essere presente.',
'prohibited' => ':Attribute non consentito.',
'prohibited_if' => ':Attribute non consentito quando :other è :value.',
'prohibited_unless' => ':Attribute non consentito a meno che :other sia contenuto in :values.',
'prohibits' => ':Attribute impedisce a :other di essere presente.',
'regex' => 'Il formato del campo :attribute non è valido.',
'required' => 'Il campo :attribute è richiesto.',
'required_array_keys' => 'Il campo :attribute deve contenere voci per: :values.',
'required_if' => 'Il campo :attribute è richiesto quando :other è :value.',
'required_if_accepted' => ':Attribute è richiesto quando :other è accettato.',
'required_unless' => 'Il campo :attribute è richiesto a meno che :other sia in :values.',
'required_with' => 'Il campo :attribute è richiesto quando :values è presente.',
'required_with_all' => 'Il campo :attribute è richiesto quando :values sono presenti.',
'required_without' => 'Il campo :attribute è richiesto quando :values non è presente.',
'required_without_all' => 'Il campo :attribute è richiesto quando nessuno di :values è presente.',
'same' => ':Attribute e :other devono coincidere.',
'size' => [
'array' => ':Attribute deve contenere :size elementi.',
'file' => ':Attribute deve essere :size kilobyte.',
'numeric' => ':Attribute deve essere :size.',
'string' => ':Attribute deve contenere :size caratteri.',
],
'starts_with' => ':Attribute deve iniziare con uno dei seguenti: :values',
'string' => ':Attribute deve essere una stringa.',
'timezone' => ':Attribute deve essere una zona valida.',
'ulid' => ':Attribute deve essere un ULID valido.',
'unique' => ':Attribute è stato già utilizzato.',
'uploaded' => ':Attribute non è stato caricato.',
'uppercase' => ':Attribute deve contenere solo caratteri maiuscoli.',
'url' => 'Il formato del campo :attribute non è valido.',
'uuid' => ':Attribute deve essere un UUID valido.',
'attributes' => [
'address' => 'indirizzo',
'age' => 'età',
'amount' => 'Quantità',
'area' => 'la zona',
'available' => 'disponibile',
'birthday' => 'compleanno',
'body' => 'corpo',
'city' => 'città',
'content' => 'contenuto',
'country' => 'paese',
'created_at' => 'creato a',
'creator' => 'Creatore',
'current_password' => 'password attuale',
'date' => 'data',
'date_of_birth' => 'data di nascita',
'day' => 'giorno',
'deleted_at' => 'cancellato a',
'description' => 'descrizione',
'district' => 'quartiere',
'duration' => 'durata',
'email' => 'e-mail',
'excerpt' => 'estratto',
'filter' => 'filtro',
'first_name' => 'nome',
'gender' => 'genere',
'group' => 'gruppo',
'hour' => 'ora',
'image' => 'Immagine',
'last_name' => 'cognome',
'lesson' => 'lezione',
'line_address_1' => 'indirizzo di linea 1',
'line_address_2' => 'indirizzo di linea 2',
'message' => 'Messaggio',
'middle_name' => 'secondo nome',
'minute' => 'minuto',
'mobile' => 'cellulare',
'month' => 'mese',
'name' => 'nome',
'national_code' => 'codice nazionale',
'number' => 'numero',
'password' => 'parola d\'ordine',
'password_confirmation' => 'conferma password',
'phone' => 'telefono',
'photo' => 'foto',
'postal_code' => 'Codice Postale',
'price' => 'prezzo',
'province' => 'Provincia',
'recaptcha_response_field' => 'campo di risposta recaptcha',
'remember' => 'ricordare',
'restored_at' => 'restaurato a',
'result_text_under_image' => 'testo del risultato sotto l\'immagine',
'role' => 'ruolo',
'second' => 'secondo',
'sex' => 'sesso',
'short_text' => 'breve testo',
'size' => 'dimensione',
'state' => 'stato',
'street' => 'strada',
'student' => 'alunno',
'subject' => 'argomento',
'teacher' => 'insegnante',
'terms' => 'termini',
'test_description' => 'descrizione del testo',
'test_locale' => 'locale di prova',
'test_name' => 'nome di prova',
'text' => 'testo',
'time' => 'ora',
'title' => 'titolo',
'updated_at' => 'aggiornato a',
'username' => 'nome utente',
'year' => 'anno',
],
];

View File

@ -1,93 +1,69 @@
{ {
"name": "openstamanager", "name": "openstamanager",
"version": "3.0.0-dev.2", "version": "3.0.0-dev.2",
"packageManager": "pnpm@7.14.0", "packageManager": "pnpm@8.2.0",
"files": [], "files": [],
"type": "module",
"scripts": { "scripts": {
"build": "vite build", "build": "vite build",
"build:dev": "vite build --mode development", "build:dev": "vite build --mode development",
"build:watch": "vite build --watch", "build:watch": "vite build --watch",
"dev": "php artisan osm:dev-server-fix && vite", "dev": "vite",
"generate-barrels": "barrelsby -c ./.barrelsby.config.json && php artisan osm:barrels-generation-fix && eslint --fix \"resources/js/**/index.ts\"",
"serve": "php artisan serve",
"serve-dev": "concurrently --raw pnpm:serve pnpm:dev",
"serve-watch": "concurrently --raw pnpm:serve pnpm:watch",
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"scss-types": "typed-scss-modules resources/scss -i node_modules" "scss-types": "typed-scss-modules resources/scss -i node_modules"
}, },
"dependencies": { "dependencies": {
"@inertiajs/inertia": "^0.11.1", "@formkit/auto-animate": "1.0.0-beta.6",
"@inertiajs/progress": "^0.2.7", "@maicol07/inertia-mithril": "^1.0.3",
"@maicol07/inertia-mithril": "^0.5.2", "@maicol07/material-web-additions": "^1.2.11",
"@maicol07/mwc-card": "^0.25.3",
"@maicol07/mwc-layout-grid": "0.25.3-1",
"@material/data-table": "^14.0.0",
"@material/elevation": "^14.0.0",
"@material/mwc-button": "^0.27.0",
"@material/mwc-checkbox": "^0.27.0",
"@material/mwc-circular-progress": "^0.27.0",
"@material/mwc-dialog": "^0.27.0",
"@material/mwc-drawer": "^0.27.0",
"@material/mwc-fab": "^0.27.0",
"@material/mwc-formfield": "^0.27.0",
"@material/mwc-icon-button": "^0.27.0",
"@material/mwc-icon-button-toggle": "^0.27.0",
"@material/mwc-linear-progress": "^0.27.0", "@material/mwc-linear-progress": "^0.27.0",
"@material/mwc-list": "^0.27.0",
"@material/mwc-menu": "^0.27.0",
"@material/mwc-ripple": "^0.27.0",
"@material/mwc-select": "^0.27.0",
"@material/mwc-snackbar": "^0.27.0", "@material/mwc-snackbar": "^0.27.0",
"@material/mwc-textarea": "^0.27.0",
"@material/mwc-textfield": "^0.27.0",
"@material/mwc-top-app-bar": "^0.27.0", "@material/mwc-top-app-bar": "^0.27.0",
"@material/textfield": "^14.0.0", "@material/textfield": "^14.0.0",
"@material/theme": "^14.0.0", "@material/theme": "^14.0.0",
"@material/typography": "^14.0.0", "@material/web": "1.0.0-pre.6",
"@mdi/font": "^7.0.96", "@mdi/js": "^7.2.96",
"async-wait-until": "2.0.12",
"cash-dom": "^8.1.1",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"collect.js": "^4.34.3", "collect.js": "^4.36.1",
"coloquent": "npm:@maicol07/coloquent@^3.0.1-beta", "coloquent": "npm:@maicol07/coloquent@^3.0.1-beta",
"deepmerge-ts": "^4.2.2", "dayjs": "^1.11.7",
"include-media": "^1.4.10", "include-media": "^2.0.0",
"lit": "^2.4.0", "lit": "^2.7.2",
"locale-code": "^2.0.2",
"lodash-es": "^4.17.21",
"mithril": "^2.2.2", "mithril": "^2.2.2",
"mithril-node-render": "^3.0.2", "mithril-utilities": "^1.1.0",
"modern-normalize": "^1.1.0", "modern-normalize": "^1.1.0",
"postcss-scss": "^4.0.6",
"prntr": "^2.0.18", "prntr": "^2.0.18",
"redaxios": "^0.5.1" "readable-http-codes": "^1.1.1",
"ts-pattern": "^4.2.2",
"typescript-cookie": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {
"@maicol07/eslint-config": "^2.2.2", "@maicol07/eslint-config": "^2.2.4",
"@openstamanager/vite-config": "github:devcode-it/openstamanager-vite-config", "@openstamanager/vite-config": "github:devcode-it/openstamanager-vite-config",
"@types/gulp": "^4.0.9", "@types/lodash-es": "^4.17.7",
"@types/lodash-es": "^4.17.6", "@types/mithril": "^2.0.12",
"@types/mithril": "^2.0.11", "@types/node": "^18.15.12",
"@types/node": "^18.11.6",
"@types/ziggy-js": "^1.3.2", "@types/ziggy-js": "^1.3.2",
"barrelsby": "^2.5.1",
"chokidar": "^3.5.3", "chokidar": "^3.5.3",
"concurrently": "^7.5.0", "csstype": "^3.1.2",
"csstype": "^3.1.1", "inertia-plugin": "^0.6.0",
"postcss": "^8.4.18", "laravel-vite-plugin": "^0.7.4",
"postcss": "^8.4.23",
"postcss-html": "^1.5.0", "postcss-html": "^1.5.0",
"sass": "^1.55.0", "sass": "^1.62.0",
"stylelint": "^14.14.0", "stylelint": "^15.5.0",
"stylelint-config-clean-order": "^5.0.1",
"stylelint-config-html": "^1.1.0", "stylelint-config-html": "^1.1.0",
"stylelint-config-idiomatic-order": "^9.0.0", "stylelint-config-standard": "^33.0.0",
"stylelint-config-recommended-scss": "^8.0.0", "stylelint-config-standard-scss": "^8.0.0",
"stylelint-config-standard": "^29.0.0", "stylelint-scss": "^4.6.0",
"stylelint-scss": "^4.3.0", "type-fest": "^3.8.0",
"typed-scss-modules": "^7.0.1", "typed-scss-modules": "^7.1.0",
"typescript": "^4.8.4", "typescript": "^5.0.4",
"vite": "^3.2.0", "vite": "^4.3.0",
"vite-plugin-laravel": "^0.2.2", "vite-plugin-laravel-translations": "^0.1.4",
"vite-plugin-pwa": "^0.13.1" "vite-plugin-progress": "^0.0.7",
"vite-plugin-pwa": "^0.14.7"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"

17
phpstan.neon Normal file
View File

@ -0,0 +1,17 @@
includes:
- ./vendor/nunomaduro/larastan/extension.neon
parameters:
paths:
- app/
# Level 9 is the highest level
level: 5
# ignoreErrors:
# - '#PHPDoc tag @var#'
#
# excludePaths:
# - ./*/*/FileToBeExcluded.php
#
# checkMissingIterableValueType: false

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,6 @@
<?php /** @noinspection DevelopmentDependenciesUsageInspection */ <?php
/** @noinspection DevelopmentDependenciesUsageInspection */
declare(strict_types=1); declare(strict_types=1);
@ -6,26 +8,26 @@ use Rector\CodingStyle\Rector\Catch_\CatchExceptionNameMatchingTypeRector;
use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector; use Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector;
use Rector\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector; use Rector\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector;
use Rector\Config\RectorConfig; use Rector\Config\RectorConfig;
use Rector\Laravel\Set\LaravelSetList;
use Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector; use Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector;
use Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector; use Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector;
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector; use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector;
use Rector\Set\ValueObject\LevelSetList; use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList; use Rector\Set\ValueObject\SetList;
use RectorLaravel\Set\LaravelSetList;
return static function (RectorConfig $rectorConfig): void { return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([ $rectorConfig->paths([
__DIR__ . '/app', __DIR__.'/app',
__DIR__ . '/config', __DIR__.'/config',
__DIR__ . '/database' __DIR__.'/database',
]); ]);
// define sets of rules // define sets of rules
$rectorConfig->sets([ $rectorConfig->sets([
SetList::PHP_80, SetList::PHP_80,
SetList::PHP_81, SetList::PHP_81,
// SetList::PHP_82, SetList::PHP_82,
LevelSetList::UP_TO_PHP_81, LevelSetList::UP_TO_PHP_82,
SetList::CODE_QUALITY, SetList::CODE_QUALITY,
SetList::CODING_STYLE, SetList::CODING_STYLE,
SetList::DEAD_CODE, SetList::DEAD_CODE,
@ -33,8 +35,9 @@ return static function (RectorConfig $rectorConfig): void {
SetList::MYSQL_TO_MYSQLI, SetList::MYSQL_TO_MYSQLI,
SetList::PSR_4, SetList::PSR_4,
SetList::PRIVATIZATION, SetList::PRIVATIZATION,
SetList::TYPE_DECLARATION_STRICT, SetList::TYPE_DECLARATION,
LaravelSetList::LARAVEL_90 LaravelSetList::LARAVEL_90,
LaravelSetList::LARAVEL_CODE_QUALITY,
]); ]);
$rectorConfig->skip([ $rectorConfig->skip([
@ -43,6 +46,6 @@ return static function (RectorConfig $rectorConfig): void {
RenameParamToMatchTypeRector::class, RenameParamToMatchTypeRector::class,
FinalizeClassesWithoutChildrenRector::class, FinalizeClassesWithoutChildrenRector::class,
FinalizePublicClassConstantRector::class, FinalizePublicClassConstantRector::class,
CatchExceptionNameMatchingTypeRector::class CatchExceptionNameMatchingTypeRector::class,
]); ]);
}; };

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 520 B

View File

Before

Width:  |  Height:  |  Size: 711 B

After

Width:  |  Height:  |  Size: 711 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,373 +0,0 @@
import '@material/mwc-linear-progress';
import '@material/mwc-list/mwc-list-item.js';
import '@osm/WebComponents/Select';
import type {LinearProgress as MWCLinearProgress} from '@material/mwc-linear-progress';
import {
type TableRowAttributes,
Component,
Mdi,
TableColumn,
TableFooter,
TableRow
} from '@osm/Components';
import type {Cash} from 'cash-dom';
import type {
Children,
Vnode,
VnodeDOM
} from 'mithril';
type PaginationAction = 'first' | 'next' | 'previous' | 'last';
export type Attributes = {
'rows-per-page'?: number,
'default-rows-per-page'?: number,
'aria-label'?: string,
checkable?: boolean,
paginated?: boolean
};
export class DataTable extends Component<Attributes> {
rows: Children[] = [];
columns: Children[];
footer: Children[];
rowsPerPage = {
options: [10, 25, 50, 75, 100],
currentStart: 0,
value: 10,
currentEnd: 10
};
oninit(vnode: Vnode<Attributes>) {
super.oninit(vnode);
let defaultRowsPerPage: number = Number.parseInt(this.attrs.get('default-rows-per-page', '10') as string, 10);
if (Number.isInteger(defaultRowsPerPage)) {
if (!this.rowsPerPage.options.includes(defaultRowsPerPage)) {
[defaultRowsPerPage] = this.rowsPerPage.options;
}
this.rowsPerPage.value = defaultRowsPerPage;
}
}
oncreate(vnode: VnodeDOM<Attributes>) {
super.oncreate(vnode);
$(this.element)
.find('thead th.mdc-data-table__header-cell--with-sort')
.on('click', this.onColumnClicked.bind(this));
$(this.element)
.find('.mdc-data-table__pagination-rows-per-page-select')
.val(String(this.rowsPerPage.value))
.on('selected', this.onPaginationSelected.bind(this));
$(this.element)
// eslint-disable-next-line sonarjs/no-duplicate-string
.find('.mdc-data-table__pagination-button')
.on('click', this.onPaginationButtonClicked.bind(this));
}
onbeforeupdate(vnode: VnodeDOM<Attributes, this>) {
super.onbeforeupdate(vnode);
const children = (vnode.children as Children[]).flat();
this.rows = this.tableRows(children);
this.columns = this.filterElements(children, TableColumn);
this.footer = this.filterElements(children, TableFooter);
const rowsPerPage = this.attrs.get('rows-per-page');
if (rowsPerPage) {
this.rowsPerPage.options = rowsPerPage
.split(',')
.map((value: string) => Number.parseInt(value, 10));
if (this.rowsPerPage.currentStart === 0) {
this.rowsPerPage.currentEnd = this.rowsPerPage.value >= this.rows.length
? this.rows.length
: this.rowsPerPage.value;
}
}
}
onupdate(vnode: VnodeDOM<Attributes, this>) {
super.onupdate(vnode);
const rows: Cash = $(this.element).find('tbody tr');
rows.hide().slice(this.rowsPerPage.currentStart, this.rowsPerPage.currentEnd).show();
if (this.rowsPerPage.currentStart === 0) {
this.paginate('first');
}
}
view() {
return (
<div className="mdc-data-table" {...this.attrs.all()}>
<div className="mdc-data-table__table-container">
<table
className="mdc-data-table__table"
aria-label={this.attrs.get('aria-label')}
>
<thead>
<tr className="mdc-data-table__header-row">
{this.attrs.has('checkable') && <TableColumn type="checkbox" />}
{this.columns}
</tr>
</thead>
<tbody className="mdc-data-table__content">{this.rows}</tbody>
{this.footer}
</table>
{this.attrs.has('paginated') && (
<div className="mdc-data-table__pagination">
<div className="mdc-data-table__pagination-trailing">
<div className="mdc-data-table__pagination-rows-per-page">
<div className="mdc-data-table__pagination-rows-per-page-label">
{__('Righe per pagina')}
</div>
<material-select
outlined
className="mdc-data-table__pagination-rows-per-page-select"
fixedMenuPosition
// @ts-ignore
style="--mdc-select-width: 112px; --mdc-select-height: 36px; --mdc-menu-item-height: 36px;"
>
{this.rowsPerPage.options.map((rowsPerPage) => (
<mwc-list-item key={rowsPerPage} value={String(rowsPerPage)}>
{rowsPerPage}
</mwc-list-item>
))}
</material-select>
</div>
<div className="mdc-data-table__pagination-navigation">
<div className="mdc-data-table__pagination-total">
{__(':start-:chunk di :total', {
start: this.rowsPerPage.currentStart + 1,
chunk: this.rowsPerPage.currentEnd > this.rows.length
? this.rows.length
: this.rowsPerPage.currentEnd,
total: this.rows.length
})}
</div>
<mwc-icon-button
className="mdc-data-table__pagination-button"
data-page="first"
disabled
>
<Mdi icon="page-first" />
</mwc-icon-button>
<mwc-icon-button
className="mdc-data-table__pagination-button"
data-page="previous"
disabled
>
<Mdi icon="chevron-left" />
</mwc-icon-button>
<mwc-icon-button
className="mdc-data-table__pagination-button"
data-page="next"
>
<Mdi icon="chevron-right" />
</mwc-icon-button>
<mwc-icon-button
className="mdc-data-table__pagination-button"
data-page="last"
>
<Mdi icon="page-last" />
</mwc-icon-button>
</div>
</div>
</div>
)}
<div className="mdc-data-table__progress-indicator">
<div className="mdc-data-table__scrim" />
<mwc-linear-progress
className="mdc-data-table__linear-progress"
indeterminate
/>
</div>
</div>
</div>
);
}
tableRows(children: Children[]): Children[] {
let rows = this.filterElements(children, TableRow);
if (this.attrs.has('checkable')) {
rows = rows.map<Children>((row: Children) => {
if (!row) {
return '';
}
const rowNode = row as Vnode<TableRowAttributes>;
return (
<TableRow key={rowNode.key} checkable {...rowNode.attrs}>
{rowNode.children}
</TableRow>
);
});
}
return rows;
}
filterElements(
elements: Children[],
tag: typeof TableRow | typeof TableColumn | typeof TableFooter | string
): Children[] {
const filtered = [];
for (const element of elements) {
if ((element as Vnode).tag === tag) {
filtered.push(element);
}
}
return filtered;
}
getProgress(): Element & Partial<MWCLinearProgress> | null {
return this.element.querySelector('.mdc-data-table__progress-indicator mwc-linear-progress');
}
showProgress() {
this.manageProgress(true);
}
hideProgress() {
this.manageProgress(false);
}
onColumnClicked(event: Event) {
this.showProgress();
const column: Cash = $(event.target as Element).closest('th');
const ascendingClass = 'mdc-data-table__header-cell--sorted';
// Clean previously sorted info and arrows
const columns = $(this.element).find('thead th');
columns.removeClass(ascendingClass);
columns.off('click').on('click', this.onColumnClicked.bind(this));
// Add ony one header to sort
column.addClass(ascendingClass);
// Do sorting
this.sortTable(column, false);
// Set/remove callbacks
column.off('click');
column.find('mwc-icon-button-toggle').on('click', () => {
this.sortTable(column);
});
}
sortTable(column: Cash, toggleClass = true) {
const cells = $(this.element)
.find(`tr td:nth-child(${column.index() + 1})`)
.get();
// Handle button class
if (toggleClass) {
column.toggleClass('mdc-data-table__header-cell--sorted-descending');
}
const isNumeric = column.attr('type') === 'numeric';
const isDescending = column.hasClass(
'mdc-data-table__header-cell--sorted-descending'
);
cells.sort((a: HTMLElement, b: HTMLElement) => {
let aValue: string | number = a.textContent as string;
let bValue: string | number = b.textContent as string;
if (isNumeric) {
aValue = Number.parseFloat(aValue);
bValue = Number.parseFloat(bValue);
}
if (!isDescending) {
const temporary = aValue;
aValue = bValue;
bValue = temporary;
}
if (typeof aValue === 'string' && typeof bValue === 'string') {
return aValue.localeCompare(bValue);
}
return aValue < bValue ? -1 : (aValue > bValue ? 1 : 0);
});
for (const cell of cells) {
const row = $(cell).parent();
row.appendTo(row.parent());
}
this.hideProgress();
}
onPaginationSelected(event: Event & {detail: {index: number}}) {
const selectValue = $(event.target as HTMLFormElement).val();
const rowsPerPage = Number.parseInt(selectValue as string, 10);
this.rowsPerPage = {
...this.rowsPerPage,
value: rowsPerPage,
currentStart: 0,
currentEnd: rowsPerPage
};
m.redraw();
}
onPaginationButtonClicked(event: Event) {
const button: HTMLButtonElement | null = (event.target as HTMLElement).closest('.mdc-data-table__pagination-button');
this.paginate(button?.dataset.page as PaginationAction);
m.redraw();
}
paginate(action: PaginationAction) {
if (action === 'first' || action === 'last') {
const checkPagination = () => (action === 'first' ? this.rowsPerPage.currentStart > 0 : this.rowsPerPage.currentEnd < this.rows.length);
let check = checkPagination();
while (check) {
this.paginate(action === 'first' ? 'previous' : 'next');
check = checkPagination();
}
} else {
const increments = {
next: this.rowsPerPage.value,
previous: -this.rowsPerPage.value
};
const increment = increments[action];
this.rowsPerPage.currentStart += increment;
if (this.rowsPerPage.currentStart < 0) {
this.rowsPerPage.currentStart = 0;
}
this.rowsPerPage.currentEnd += increment;
}
const paginationButtons: NodeListOf<HTMLButtonElement> = this.element.querySelectorAll('.mdc-data-table__pagination-button');
const disabled = {
first: this.rowsPerPage.currentStart === 0,
previous: this.rowsPerPage.currentStart === 0,
next: this.rowsPerPage.currentEnd >= this.rows.length,
last: this.rowsPerPage.currentEnd >= this.rows.length
};
for (const button of paginationButtons) {
button.disabled = disabled[button.dataset.page as PaginationAction];
}
}
private manageProgress(show: boolean) {
$(this.element).toggleClass('mdc-data-table--in-progress');
const progress = this.getProgress();
if (progress) {
(progress as MWCLinearProgress)[show ? 'open' : 'close']();
}
}
}

View File

@ -1,56 +0,0 @@
import type {Cash} from 'cash-dom/dist/cash';
import {inRange} from 'lodash-es';
import type {
Vnode,
VnodeDOM
} from 'mithril';
import {Component} from '../Component';
type Attributes = {type?: string};
export class TableCell extends Component<Attributes> {
view(vnode: Vnode) {
this.attrs.addClassNames('mdc-data-table__cell', {
[`mdc-data-table__cell--${this.attrs.get('type') as string}`]: this.attrs.has(
'type'
)
});
if (
(!Array.isArray(vnode.children) || vnode.children.length === 0)
&& this.attrs.get('type') === 'checkbox'
) {
vnode.children = [<mwc-checkbox key="checkbox" className="mdc-data-table__row-checkbox" />];
}
return <td {...this.attrs.all()}>{vnode.children}</td>;
}
oncreate(vnode: VnodeDOM<Attributes>) {
super.oncreate(vnode);
const checkboxes = (): Cash => $(this.element)
.closest('.mdc-data-table')
.find('tbody tr[checkable] mwc-checkbox');
const cell: Cash = $(this.element);
cell.children('mwc-checkbox').on('change', () => {
const row = cell.parent();
row.toggleClass('mdc-data-table__row--selected');
const headerCheckbox = cell
.closest('.mdc-data-table')
.find('thead th mwc-checkbox');
const checks = checkboxes();
const checked = checks.filter('[checked]');
if (inRange(checked.length, 1, checks.length)) {
headerCheckbox.prop('indeterminate', true);
headerCheckbox.prop('checked', false);
} else {
headerCheckbox.prop('checked', checks.length === checked.length);
headerCheckbox.prop('indeterminate', false);
}
});
}
}

View File

@ -1,153 +0,0 @@
import '@material/mwc-icon-button-toggle';
import type {Cash} from 'cash-dom';
import type {
Children,
Vnode,
VnodeDOM
} from 'mithril';
import {Component} from '../Component';
import {Mdi} from '../Mdi';
type Attributes = {
type?: 'numeric' | 'checkbox',
id?: string,
sortable?: boolean,
filterable?: boolean,
};
export class TableColumn extends Component<Attributes> {
view(vnode: Vnode) {
this.attrs.addClassNames('mdc-data-table__header-cell', {
[`mdc-data-table__header-cell--${this.attrs.get(
'type'
) as string}`]: this.attrs.has('type')
});
let {children}: {children?: Children} = vnode;
if (this.attrs.has('sortable')) {
this.attrs.addClassNames('mdc-data-table__header-cell--with-sort');
this.attrs
.put('aria-sort', 'none')
.put('data-column-id', this.attrs.get('id'));
children = (
<div className="mdc-data-table__header-cell-wrapper">
<mwc-icon-button-toggle style="--mdc-icon-button-size: 28px; display: none;">
<Mdi icon="arrow-down-thin" slot="onIcon" />
<Mdi icon="arrow-up-thin" slot="offIcon" />
</mwc-icon-button-toggle>
&nbsp;
<div className="mdc-data-table__header-cell-label">
{children}
</div>
</div>
);
}
if ((
(!children || (Array.isArray(children) && children.length === 0))
&& this.attrs.get('type') === 'checkbox'
)) {
children = <mwc-checkbox className="mdc-data-table__header-row-checkbox" />;
}
if (this.attrs.get('type') !== 'checkbox' && this.attrs.has('filterable')) {
children = (
<>
{children}
<div style="margin-top: 8px;">
<text-field
outlined
className="mdc-data-table__filter-textfield"
label={__('Filtro')}
compact
/>
</div>
</>
);
}
return (
<th {...this.attrs.all()} role="columnheader" scope="col">
{children}
</th>
);
}
oncreate(vnode: VnodeDOM<Attributes>) {
super.oncreate(vnode);
if (this.attrs.get('type') === 'checkbox') {
const checkbox = $(this.element).children(
'.mdc-data-table__header-row-checkbox'
);
checkbox.on('change', this.onCheckboxClicked.bind(this));
}
// Handle click on a column (add arrows)
const observer = new MutationObserver(this.onClassChanged.bind(this));
observer.observe(this.element, {
attributes: true,
attributeFilter: ['class']
});
$(this.element)
.find('.mdc-data-table__filter-textfield')
.on('input', this.onFilterInput.bind(this))
.on('click', (event: Event) => event.stopPropagation());
}
onCheckboxClicked(event: Event) {
const row: Cash = $(this.element)
.closest('table')
.find('tbody tr[checkable]');
const selectedClass = 'mdc-data-table__row--selected';
const checkbox = event.target as HTMLInputElement;
row.toggleClass(selectedClass, checkbox.checked);
row.find('mwc-checkbox').prop('checked', checkbox.checked);
}
onClassChanged(mutations: MutationRecord[]) {
for (const mutation of mutations) {
const {classList} = mutation.target as HTMLElement;
const ascendingClass = 'mdc-data-table__header-cell--sorted';
const descendingClass = 'mdc-data-table__header-cell--sorted-descending';
const onValue = classList.contains(descendingClass);
const button: Cash = $(this.element).find('mwc-icon-button-toggle');
button.prop('on', onValue);
if (
classList.contains(ascendingClass)
|| classList.contains(descendingClass)
) {
$(this.element).css('cursor', 'auto');
button.show();
} else if (
!classList.contains(ascendingClass)
&& !classList.contains(descendingClass)
) {
$(this.element).css('cursor', 'pointer');
button.hide();
}
}
}
onFilterInput(event: InputEvent) {
const index = $(this.element).index();
const rows: Cash = $(this.element).closest('table').find('tbody tr');
const {value} = event.target as HTMLInputElement;
rows.hide();
rows
.filter(
(index_, element) => $(element)
.find(`td:nth-child(${index + 1})`)
.text()
.search(value) !== -1
)
.show();
}
}

View File

@ -1,9 +0,0 @@
import type {Vnode} from 'mithril';
import {Component} from '../Component';
export class TableFooter extends Component {
view(vnode: Vnode) {
return <tfoot {...this.attrs.all()}>{vnode.children}</tfoot>;
}
}

View File

@ -1,42 +0,0 @@
import '@material/mwc-checkbox';
import {collect} from 'collect.js';
import type {
Children,
Vnode
} from 'mithril';
import {Component} from '../Component';
import {TableCell} from './TableCell';
export interface TableRowAttributes {
checkable?: boolean;
}
export class TableRow extends Component<TableRowAttributes> {
view(vnode: Vnode<TableRowAttributes>) {
this.attrs.addClassNames('mdc-data-table__row');
return (
<tr {...this.attrs.all()}>
{this.checkbox(vnode.children as Children[])}
{vnode.children}
</tr>
);
}
checkbox(children: Children[]): Children {
if (!this.attrs.has('checkable')) {
return <></>;
}
for (const child of children) {
const attributes = collect((child as Vnode).attrs);
if (attributes.get('type') === 'checkbox') {
break;
}
}
return <TableCell type="checkbox" />;
}
}

View File

@ -1,9 +0,0 @@
/**
* @file Automatically generated by barrelsby.
*/
export * from './DataTable';
export * from './TableCell';
export * from './TableColumn';
export * from './TableFooter';
export * from './TableRow';

View File

@ -1,6 +0,0 @@
import {InertiaLink as Link} from '@maicol07/inertia-mithril';
import {LinkAttributes} from '@maicol07/inertia-mithril/dist/Link.js';
export class InertiaLink extends Link {
attrsTypes: LinkAttributes;
}

View File

@ -1,64 +0,0 @@
import '@material/mwc-circular-progress';
import '@material/mwc-button';
import type {Button} from '@material/mwc-button';
import type {CircularProgress} from '@material/mwc-circular-progress';
import {
Component,
Mdi
} from '@osm/Components';
import type CSS from 'csstype';
import type {VnodeDOM} from 'mithril';
import {
JSXElement,
MaterialIcons
} from '../typings';
type Attributes = JSXElement<Button> & {
icon?: string
};
export class LoadingButton extends Component<Attributes> {
view() {
return (
<mwc-button data-component-type="loading-button" {...this.attrs.all()}>
<span slot="icon" style="display: inline;">
<mwc-circular-progress
indeterminate
// @ts-ignore
style={this.getCSSProperties()}
/>
{this.attrs.has('icon') ? (
<Mdi icon={this.attrs.get('icon') as MaterialIcons}/>
) : (
''
)}
</span>
</mwc-button>
);
}
getCSSProperties() {
const css: CSS.Properties & Record<string, string> = {
display: 'none',
verticalAlign: 'bottom'
};
if (this.attrs.has('raised')) {
css['--mdc-theme-primary'] = '#ffffff';
}
if (this.attrs.has('icon')) {
css.marginRight = '8px';
}
return css;
}
oncreate(vnode: VnodeDOM<Attributes>) {
super.oncreate(vnode);
this.element.querySelector<CircularProgress>('mwc-circular-progress')
?.setAttribute('density', '-7');
}
}

View File

@ -1,36 +0,0 @@
import {CircularProgress} from '@material/mwc-circular-progress';
import {Manager} from './Manager';
export class CircularProgressManager extends Manager {
static selector = 'mwc-circular-progress';
static filter = (element: CircularProgress) => element.closest('mwc-button')?.dataset.componentType !== 'loading-button';
constructor(protected loading: CircularProgress) {
super(loading);
}
public show() {
this.loading.open();
}
public hide() {
this.loading.close();
}
public get indeterminate(): boolean {
return this.loading.indeterminate;
}
public set indeterminate(value: boolean) {
this.loading.indeterminate = value;
}
public get progress(): number {
return this.loading.progress;
}
public set progress(value: number) {
this.loading.progress = value;
}
}

View File

@ -1,19 +0,0 @@
import {Dialog} from '@material/mwc-dialog';
import {Manager} from './Manager';
export class DialogManager extends Manager {
static selector = 'dialog';
constructor(protected dialog: Dialog) {
super(dialog);
}
public show(dialog: Dialog) {
this.dialog.show();
}
public hide() {
this.dialog.close();
}
}

View File

@ -1,13 +0,0 @@
import {Button} from '@material/mwc-button';
import {CircularProgressManager} from '@osm/Components/Managers';
export class LoadingButtonManager extends CircularProgressManager {
static selector = 'mwc-button[data-component-type="loading-button"]';
constructor(private button: Button) {
const loading = button.querySelector('mwc-circular-progress');
if (loading) {
super(loading);
}
}
}

Some files were not shown because too many files have changed in this diff Show More