squirrels 0.5.0b3__py3-none-any.whl → 0.6.0.post0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. squirrels/__init__.py +4 -0
  2. squirrels/_api_routes/__init__.py +5 -0
  3. squirrels/_api_routes/auth.py +337 -0
  4. squirrels/_api_routes/base.py +196 -0
  5. squirrels/_api_routes/dashboards.py +156 -0
  6. squirrels/_api_routes/data_management.py +148 -0
  7. squirrels/_api_routes/datasets.py +220 -0
  8. squirrels/_api_routes/project.py +289 -0
  9. squirrels/_api_server.py +440 -792
  10. squirrels/_arguments/__init__.py +0 -0
  11. squirrels/_arguments/{_init_time_args.py → init_time_args.py} +23 -43
  12. squirrels/_arguments/{_run_time_args.py → run_time_args.py} +32 -68
  13. squirrels/_auth.py +590 -264
  14. squirrels/_command_line.py +130 -58
  15. squirrels/_compile_prompts.py +147 -0
  16. squirrels/_connection_set.py +16 -15
  17. squirrels/_constants.py +36 -11
  18. squirrels/_dashboards.py +179 -0
  19. squirrels/_data_sources.py +40 -34
  20. squirrels/_dataset_types.py +16 -11
  21. squirrels/_env_vars.py +209 -0
  22. squirrels/_exceptions.py +9 -37
  23. squirrels/_http_error_responses.py +52 -0
  24. squirrels/_initializer.py +7 -6
  25. squirrels/_logging.py +121 -0
  26. squirrels/_manifest.py +155 -77
  27. squirrels/_mcp_server.py +578 -0
  28. squirrels/_model_builder.py +11 -55
  29. squirrels/_model_configs.py +5 -5
  30. squirrels/_model_queries.py +1 -1
  31. squirrels/_models.py +276 -143
  32. squirrels/_package_data/base_project/.env +1 -24
  33. squirrels/_package_data/base_project/.env.example +31 -17
  34. squirrels/_package_data/base_project/connections.yml +4 -3
  35. squirrels/_package_data/base_project/dashboards/dashboard_example.py +13 -7
  36. squirrels/_package_data/base_project/dashboards/dashboard_example.yml +6 -6
  37. squirrels/_package_data/base_project/docker/Dockerfile +2 -2
  38. squirrels/_package_data/base_project/docker/compose.yml +1 -1
  39. squirrels/_package_data/base_project/duckdb_init.sql +1 -0
  40. squirrels/_package_data/base_project/models/builds/build_example.py +2 -2
  41. squirrels/_package_data/base_project/models/dbviews/dbview_example.sql +7 -2
  42. squirrels/_package_data/base_project/models/dbviews/dbview_example.yml +16 -10
  43. squirrels/_package_data/base_project/models/federates/federate_example.py +27 -17
  44. squirrels/_package_data/base_project/models/federates/federate_example.sql +3 -7
  45. squirrels/_package_data/base_project/models/federates/federate_example.yml +7 -7
  46. squirrels/_package_data/base_project/models/sources.yml +5 -6
  47. squirrels/_package_data/base_project/parameters.yml +24 -38
  48. squirrels/_package_data/base_project/pyconfigs/connections.py +8 -3
  49. squirrels/_package_data/base_project/pyconfigs/context.py +26 -14
  50. squirrels/_package_data/base_project/pyconfigs/parameters.py +124 -81
  51. squirrels/_package_data/base_project/pyconfigs/user.py +48 -15
  52. squirrels/_package_data/base_project/resources/public/.gitkeep +0 -0
  53. squirrels/_package_data/base_project/seeds/seed_categories.yml +1 -1
  54. squirrels/_package_data/base_project/seeds/seed_subcategories.yml +1 -1
  55. squirrels/_package_data/base_project/squirrels.yml.j2 +21 -31
  56. squirrels/_package_data/templates/login_successful.html +53 -0
  57. squirrels/_package_data/templates/squirrels_studio.html +22 -0
  58. squirrels/_parameter_configs.py +43 -22
  59. squirrels/_parameter_options.py +1 -1
  60. squirrels/_parameter_sets.py +41 -30
  61. squirrels/_parameters.py +560 -123
  62. squirrels/_project.py +487 -277
  63. squirrels/_py_module.py +71 -10
  64. squirrels/_request_context.py +33 -0
  65. squirrels/_schemas/__init__.py +0 -0
  66. squirrels/_schemas/auth_models.py +83 -0
  67. squirrels/_schemas/query_param_models.py +70 -0
  68. squirrels/_schemas/request_models.py +26 -0
  69. squirrels/_schemas/response_models.py +286 -0
  70. squirrels/_seeds.py +52 -13
  71. squirrels/_sources.py +29 -23
  72. squirrels/_utils.py +221 -42
  73. squirrels/_version.py +1 -3
  74. squirrels/arguments.py +7 -2
  75. squirrels/auth.py +4 -0
  76. squirrels/connections.py +2 -0
  77. squirrels/dashboards.py +3 -1
  78. squirrels/data_sources.py +6 -0
  79. squirrels/parameter_options.py +5 -0
  80. squirrels/parameters.py +5 -0
  81. squirrels/types.py +10 -3
  82. squirrels-0.6.0.post0.dist-info/METADATA +148 -0
  83. squirrels-0.6.0.post0.dist-info/RECORD +101 -0
  84. {squirrels-0.5.0b3.dist-info → squirrels-0.6.0.post0.dist-info}/WHEEL +1 -1
  85. squirrels/_api_response_models.py +0 -190
  86. squirrels/_dashboard_types.py +0 -82
  87. squirrels/_dashboards_io.py +0 -79
  88. squirrels-0.5.0b3.dist-info/METADATA +0 -110
  89. squirrels-0.5.0b3.dist-info/RECORD +0 -80
  90. /squirrels/_package_data/base_project/{assets → resources}/expenses.db +0 -0
  91. /squirrels/_package_data/base_project/{assets → resources}/weather.db +0 -0
  92. {squirrels-0.5.0b3.dist-info → squirrels-0.6.0.post0.dist-info}/entry_points.txt +0 -0
  93. {squirrels-0.5.0b3.dist-info → squirrels-0.6.0.post0.dist-info}/licenses/LICENSE +0 -0
@@ -1,35 +1,47 @@
1
- from typing import Any
2
- from squirrels import arguments as args, parameters as p
1
+ from typing import cast, Any
2
+ from squirrels.arguments import ContextArgs
3
+ from squirrels import parameters as p
3
4
 
5
+ from pyconfigs.user import CustomUserFields
4
6
 
5
- def main(ctx: dict[str, Any], sqrl: args.ContextArgs) -> None:
7
+
8
+ def main(ctx: dict[str, Any], sqrl: ContextArgs) -> None:
6
9
  """
7
10
  Define context variables AFTER parameter selections are made by adding entries to the dictionary "ctx".
8
11
  These context variables can then be used in the models.
9
12
 
10
13
  Note that the code here is used by all datasets, regardless of the parameters they use. You can use
11
- sqrl.prms and/or sqrl.traits to determine the conditions to execute certain blocks of code.
14
+ sqrl.param_exists to determine the conditions to execute certain blocks of code.
12
15
  """
16
+ custom_fields = cast(CustomUserFields, sqrl.user.custom_fields)
17
+
13
18
  if sqrl.param_exists("group_by"):
14
19
  group_by_param = sqrl.prms["group_by"]
15
20
  assert isinstance(group_by_param, p.SingleSelectParameter)
16
21
 
22
+ selected_id = group_by_param.get_selected_id()
17
23
  columns = group_by_param.get_selected("columns")
18
24
  aliases = group_by_param.get_selected("aliases", default_field="columns")
19
25
  assert isinstance(columns, list) and isinstance(aliases, list) and len(columns) == len(aliases)
20
26
 
21
- ctx["group_by_cols"] = columns
22
- ctx["rename_dict"] = {x: y for x, y in zip(columns, aliases) if not y.startswith("_")}
23
- ctx["select_dim_cols"] = list(x+" as "+y for x, y in ctx["rename_dict"].items())
24
- ctx["order_by_cols"] = list(ctx["rename_dict"].values())
25
- ctx["order_by_cols_desc"] = list(x+" DESC" for x in ctx["order_by_cols"])
26
-
27
- if sqrl.param_exists("limit"):
28
- limit_param = sqrl.prms["limit"]
29
- assert isinstance(limit_param, p.NumberParameter)
27
+ column_to_alias_mapping = {x: y for x, y in zip(columns, aliases) if not y.startswith("_")}
28
+ order_by_cols = list(column_to_alias_mapping.values())
30
29
 
31
- ctx["limit"] = int(limit_param.get_selected_value())
30
+ ctx["column_to_alias_mapping"] = column_to_alias_mapping
31
+ ctx["group_by_cols"] = order_by_cols if selected_id != "trans" else None
32
32
 
33
+ # Only used if federate_example is a Python model
34
+ mask_column = lambda x: x if custom_fields.role == "manager" else "***MASKED***"
35
+ ctx["order_by_cols"] = order_by_cols
36
+ ctx["mask_column_function"] = mask_column
37
+
38
+ # Only used if federate_example is a SQL model
39
+ mask_column = lambda x: x if custom_fields.role == "manager" else "'***MASKED***'"
40
+ x_as_y = lambda x, y: (mask_column(x) if x in ["description"] else x)+" as "+y
41
+ ctx["select_dim_cols"] = list(x_as_y(x, y) for x, y in column_to_alias_mapping.items())
42
+ ctx["aggregator"] = "SUM" if selected_id != "trans" else ""
43
+ ctx["order_by_cols_desc"] = list(y+" DESC" for y in order_by_cols)
44
+
33
45
  if sqrl.param_exists("start_date"):
34
46
  start_date_param = sqrl.prms["start_date"]
35
47
  assert isinstance(start_date_param, p.DateParameter)
@@ -1,98 +1,141 @@
1
- from squirrels import arguments as args, data_sources as ds, parameter_options as po, parameters as p
1
+ from squirrels import parameters as p, parameter_options as po, data_sources as ds
2
2
 
3
3
 
4
- def main(sqrl: args.ParametersArgs) -> None:
5
- """
6
- Create all widget parameters in this file. If two or more datasets use a different set of parameters, define them all
7
- here, and specify the subset of parameters used for each dataset in the "squirrels.yml" file.
8
-
9
- Parameters are created by a factory method associated to the parameter class. For example, "CreateWithOptions" is the factory method used here:
10
- > p.SingleSelectParameter.CreateWithOptions(...)
11
-
12
- The parameter classes available are:
13
- - SingleSelectParameter, MultiSelectParameter, DateParameter, DateRangeParameter, NumberParameter, NumberRangeParameter, TextParameter
14
-
15
- The factory methods available are:
16
- - CreateSimple, CreateWithOptions, CreateFromSource
17
- """
18
-
19
- ## Example of creating SingleSelectParameter and specifying each option by code
20
- user_attribute = "role"
21
- group_by_options = [
4
+ ## Example of creating SingleSelectParameter and specifying each option by code
5
+ @p.SingleSelectParameter.create_with_options(
6
+ name="group_by", label="Group By",
7
+ description="Dimension(s) to aggregate by",
8
+ user_attribute="access_level"
9
+ )
10
+ def group_by_options():
11
+ return [
12
+ po.SelectParameterOption(
13
+ id="trans", label="Transaction",
14
+ columns=["id","date","category","subcategory","description"],
15
+ aliases=["_id","date","category","subcategory","description"], # in context.py, any alias starting with "_" will not be selected
16
+ user_groups=["admin"]
17
+ ),
18
+ po.SelectParameterOption(
19
+ id="day", label="Day",
20
+ columns=["date"],
21
+ aliases=["day"],
22
+ user_groups=["admin","member"]
23
+ ),
22
24
  po.SelectParameterOption(
23
- "trans", "Transaction",
24
- columns=["id", "date", "category", "subcategory", "description"],
25
- aliases=["_id", "date", "category", "subcategory", "description"], # any alias starting with "_" will not be selected - see context.py for implementation
26
- user_groups=["manager"]
25
+ id="month", label="Month",
26
+ columns=["month"],
27
+ user_groups=["admin","member","guest"]
28
+ ),
29
+ po.SelectParameterOption(
30
+ id="cat", label="Category",
31
+ columns=["category"],
32
+ user_groups=["admin","member","guest"]
33
+ ),
34
+ po.SelectParameterOption(
35
+ id="subcat", label="Subcategory",
36
+ columns=["category","subcategory"],
37
+ user_groups=["admin","member","guest"]
27
38
  ),
28
- po.SelectParameterOption("day", "Day", columns=["date"], aliases=["day"], user_groups=["manager", "employee"]),
29
- po.SelectParameterOption("month", "Month", columns=["month"], user_groups=["manager", "employee"]),
30
- po.SelectParameterOption("cat", "Category", columns=["category"], user_groups=["manager", "employee"]),
31
- po.SelectParameterOption("subcat", "Subcategory", columns=["category", "subcategory"], user_groups=["manager", "employee"]),
32
39
  ]
33
- p.SingleSelectParameter.CreateWithOptions(
34
- "group_by", "Group By", group_by_options, description="Dimension(s) to aggregate by", user_attribute=user_attribute
35
- )
36
40
 
37
- ## Example of creating NumberParameter with options
38
- parent = "group_by"
39
- limit_options = [po.NumberParameterOption(0, 1000, increment=10, default_value=1000, parent_option_ids="trans")]
40
- p.NumberParameter.CreateWithOptions(
41
- "limit", "Max Number of Rows", limit_options, parent_name=parent, description="Maximum number of rows to return"
42
- )
43
41
 
44
- ## Example of creating DateParameter
45
- start_date_source = ds.DateDataSource(
46
- "SELECT min(date) AS min_date, max(date) AS max_date FROM expenses",
47
- default_date_col="min_date", min_date_col="min_date", max_date_col="max_date"
48
- )
49
- p.DateParameter.CreateFromSource(
50
- "start_date", "Start Date", start_date_source, description="Start date to filter transactions by"
42
+ ## Example of creating DateParameter
43
+ @p.DateParameter.create_from_source(
44
+ name="start_date", label="Start Date",
45
+ description="Start date to filter transactions by"
46
+ )
47
+ def start_date_source():
48
+ return ds.DateDataSource(
49
+ table_or_query="SELECT min(date) AS min_date, max(date) AS max_date FROM expenses",
50
+ default_date_col="min_date",
51
+ min_date_col="min_date", max_date_col="max_date",
51
52
  )
52
53
 
53
- ## Example of creating DateParameter from list of DateParameterOption's
54
- end_date_option = [po.DateParameterOption("2024-12-31", min_date="2024-01-01", max_date="2024-12-31")]
55
- p.DateParameter.CreateWithOptions(
56
- "end_date", "End Date", end_date_option, description="End date to filter transactions by"
57
- )
58
54
 
59
- ## Example of creating DateRangeParameter
60
- p.DateRangeParameter.CreateSimple(
61
- "date_range", "Date Range", "2024-01-01", "2024-12-31", min_date="2024-01-01", max_date="2024-12-31",
62
- description="Date range to filter transactions by"
63
- )
55
+ ## Example of creating DateParameter from list of DateParameterOption's
56
+ @p.DateParameter.create_with_options(
57
+ name="end_date", label="End Date",
58
+ description="End date to filter transactions by"
59
+ )
60
+ def end_date_options():
61
+ return [
62
+ po.DateParameterOption(
63
+ default_date="2024-12-31", min_date="2024-01-01", max_date="2024-12-31"
64
+ )
65
+ ]
64
66
 
65
- ## Example of creating MultiSelectParameter from lookup query/table
66
- category_ds = ds.SelectDataSource("seed_categories", "category_id", "category", from_seeds=True)
67
- p.MultiSelectParameter.CreateFromSource(
68
- "category", "Category Filter", category_ds, description="The expense categories to filter transactions by"
69
- )
70
67
 
71
- ## Example of creating MultiSelectParameter with parent from lookup query/table
72
- parent_name = "category"
73
- subcategory_ds = ds.SelectDataSource(
74
- "seed_subcategories", "subcategory_id", "subcategory", from_seeds=True, parent_id_col="category_id"
75
- )
76
- p.MultiSelectParameter.CreateFromSource(
77
- "subcategory", "Subcategory Filter", subcategory_ds, parent_name=parent_name,
78
- description="The expense subcategories to filter transactions by (available options are based on selected value(s) of 'Category Filter')"
79
- )
68
+ ## Example of creating DateRangeParameter
69
+ @p.DateRangeParameter.create_simple(
70
+ name="date_range", label="Date Range",
71
+ default_start_date="2024-01-01", default_end_date="2024-12-31",
72
+ min_date="2024-01-01", max_date="2024-12-31",
73
+ description="Date range to filter transactions by"
74
+ )
75
+ def date_range_options():
76
+ pass
77
+
80
78
 
81
- ## Example of creating NumberParameter
82
- p.NumberParameter.CreateSimple(
83
- "min_filter", "Amounts Greater Than", min_value=0, max_value=300, increment=10,
84
- description="Number to filter on transactions with an amount greater than this value"
79
+ ## Example of creating MultiSelectParameter from lookup query/table
80
+ @p.MultiSelectParameter.create_from_source(
81
+ name="category", label="Category Filter",
82
+ description="The expense categories to filter transactions by"
83
+ )
84
+ def category_source():
85
+ return ds.SelectDataSource(
86
+ table_or_query="seed_categories",
87
+ id_col="category_id",
88
+ options_col="category",
89
+ source=ds.SourceEnum.SEEDS
85
90
  )
86
-
87
- ## Example of creating NumberParameter from lookup query/table
88
- query = "SELECT 0 as min_value, 300 as max_value, 10 as increment"
89
- max_amount_ds = ds.NumberDataSource(query, "min_value", "max_value", increment_col="increment", default_value_col="max_value")
90
- p.NumberParameter.CreateFromSource(
91
- "max_filter", "Amounts Less Than", max_amount_ds, description="Number to filter on transactions with an amount less than this value"
91
+
92
+
93
+ ## Example of creating MultiSelectParameter with parent from lookup query/table
94
+ @p.MultiSelectParameter.create_from_source(
95
+ name="subcategory", label="Subcategory Filter",
96
+ description="The expense subcategories to filter transactions by (available options are based on selected value(s) of 'Category Filter')",
97
+ parent_name="category"
98
+ )
99
+ def subcategory_source():
100
+ return ds.SelectDataSource(
101
+ table_or_query="seed_subcategories",
102
+ id_col="subcategory_id",
103
+ options_col="subcategory",
104
+ source=ds.SourceEnum.SEEDS,
105
+ parent_id_col="category_id"
92
106
  )
93
107
 
94
- ## Example of creating NumberRangeParameter
95
- p.NumberRangeParameter.CreateSimple(
96
- "between_filter", "Amounts Between", 0, 300, default_lower_value=0, default_upper_value=300,
97
- description="Number range to filter on transactions with an amount within this range"
108
+
109
+ ## Example of creating NumberParameter
110
+ @p.NumberParameter.create_simple(
111
+ name="min_filter", label="Amounts Greater Than",
112
+ min_value=0, max_value=300, increment=10,
113
+ description="Number to filter on transactions with an amount greater than this value"
114
+ )
115
+ def min_filter_options():
116
+ pass
117
+
118
+
119
+ ## Example of creating NumberParameter from lookup query/table
120
+ @p.NumberParameter.create_from_source(
121
+ name="max_filter", label="Amounts Less Than",
122
+ description="Number to filter on transactions with an amount less than this value"
123
+ )
124
+ def max_filter_source():
125
+ return ds.NumberDataSource(
126
+ table_or_query="SELECT 0 as min_value, 300 as max_value, 10 as increment",
127
+ min_value_col="min_value", max_value_col="max_value",
128
+ increment_col="increment",
129
+ default_value_col="max_value"
98
130
  )
131
+
132
+
133
+ ## Example of creating NumberRangeParameter
134
+ @p.NumberRangeParameter.create_simple(
135
+ name="between_filter", label="Amounts Between",
136
+ min_value=0, max_value=300,
137
+ default_lower_value=0, default_upper_value=300,
138
+ description="Number range to filter on transactions with an amount within this range"
139
+ )
140
+ def between_filter_options():
141
+ pass
@@ -1,23 +1,56 @@
1
- from typing import Literal
2
- from squirrels import types as t
1
+ from typing import Literal, Any
2
+ from squirrels.auth import CustomUserFields as BaseCustomUserFields, ProviderConfigs, RegisteredUser, provider
3
+ from squirrels.arguments import AuthProviderArgs
3
4
 
4
5
 
5
- class User(t.BaseUser):
6
+ class CustomUserFields(BaseCustomUserFields):
6
7
  """
7
- Extend the BaseUser class with custom attributes. The attributes defined here will be added as columns to the users table.
8
+ Extend the CustomUserFields class to add custom user attributes.
8
9
  - Only the following types are supported: [str, int, float, bool, typing.Literal]
9
- - For str, int, and float types, add "| None" after the type to make it nullable.
10
- - Always set a default value for the column (use None if default is null).
10
+ - Add "| None" after the type to make it nullable.
11
+ - Always set a default value for the field (use None if default is null).
11
12
 
12
13
  Example:
13
14
  organization: str | None = None
14
15
  """
15
- role: Literal["manager", "employee"] = "employee"
16
-
17
- @classmethod
18
- def dropped_columns(cls) -> list[str]:
19
- """
20
- The fields defined above cannot be modified once added to the database.
21
- However, you can choose to drop columns by adding them to this list.
22
- """
23
- return []
16
+ role: Literal["manager", "staff", "customer"] = "staff"
17
+
18
+
19
+ # @provider(
20
+ # name="google", label="Google",
21
+ # icon="https://www.google.com/favicon.ico"
22
+ # # ^ Note: You also can save the google favicon as an image file in "resources/public/logos/google.ico"
23
+ # # and use icon="/public/logos/google.ico" instead
24
+ # )
25
+ def google_auth_provider(sqrl: AuthProviderArgs) -> ProviderConfigs:
26
+ """
27
+ Example provider configs for authenticating a user using Google credentials.
28
+
29
+ See the following page for setting up the CLIENT_ID and CLIENT_SECRET for Google specifically:
30
+ - https://support.google.com/googleapi/answer/6158849?hl=en
31
+
32
+ IMPORTANT: Avoid using Google OAuth if you set auth_strategy to 'external'.
33
+ - If auth_strategy is 'external', MCP clients would require Dynamic Client Registration (DCR) to
34
+ authenticate with the associated OAuth provider used by the Squirrels MCP server.
35
+ - Unfortunately, Google OAuth (and many other OAuth providers) do not support DCR. If auth_strategy
36
+ is 'external', consider using an alternative that supports DCR instead (such as WorkOS or Keycloak).
37
+ """
38
+ def get_sqrl_user(claims: dict[str, Any]) -> RegisteredUser:
39
+ custom_fields = CustomUserFields(role="customer")
40
+ return RegisteredUser(
41
+ username=claims["email"],
42
+ access_level="member", # or "admin"
43
+ custom_fields=custom_fields
44
+ )
45
+
46
+ # TODO: Add GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to the .env file
47
+ # Then, uncomment the @provider decorator above and set the client_id and client_secret below
48
+ provider_configs = ProviderConfigs(
49
+ client_id="", # sqrl.env_vars["GOOGLE_CLIENT_ID"],
50
+ client_secret="", # sqrl.env_vars["GOOGLE_CLIENT_SECRET"],
51
+ server_url="https://accounts.google.com",
52
+ client_kwargs={"scope": "openid email profile"},
53
+ get_user=get_sqrl_user
54
+ )
55
+
56
+ return provider_configs
@@ -1,7 +1,7 @@
1
1
  description: |
2
2
  Lookup table for the category IDs and names of transactions.
3
3
 
4
- cast_column_types: true # optional, default is false - setting SQRL_SEEDS__INFER_SCHEMA is ignored for this seed if this is set to true
4
+ cast_column_types: true # optional, default is false - if set to true, then SQRL_SEEDS__INFER_SCHEMA is ignored for this seed
5
5
 
6
6
  columns:
7
7
  - name: category_id
@@ -1,7 +1,7 @@
1
1
  description: |
2
2
  Lookup table for the subcategory IDs and names of transactions.
3
3
 
4
- cast_column_types: true # optional, default is false - setting SQRL_SEEDS__INFER_SCHEMA is ignored for this seed if this is set to true
4
+ cast_column_types: true # optional, default is false - if set to true, then SQRL_SEEDS__INFER_SCHEMA is ignored for this seed
5
5
 
6
6
  columns:
7
7
  - name: subcategory_id
@@ -1,8 +1,9 @@
1
1
  project_variables:
2
- name: sample
3
- label: Sample Project - Expenses
4
- description: This is a sample squirrels project for analyzing expense transactions
2
+ name: expenses
3
+ label: "Sample Expenses"
4
+ description: This is a sample Squirrels project for analyzing expense transactions
5
5
  major_version: 1
6
+ auth_type: optional ## one of 'optional' (default) or 'required'
6
7
 
7
8
 
8
9
  packages: []
@@ -21,51 +22,40 @@ packages: []
21
22
 
22
23
 
23
24
  datasets:
24
- - name: dbview_dataset_example ## model name uses same name unless "model" field is specified
25
- label: Example Dataset from DBView Model
26
- description: Aggregated expense transactions by month using dbview_example model
27
- model: dbview_example
28
- scope: public ## optional - one of 'public' (default), 'protected', or 'private'
25
+ - name: expense_transactions
26
+ label: Expense Transactions - DBView Example
27
+ description: All expense transactions
28
+ model: dbview_example ## optional - if not specified, model name uses the dataset name
29
+ scope: private ## optional - one of 'public', 'protected', or 'private'. Default is 'public' (if auth_type is 'optional') or 'protected' (if auth_type is 'required').
29
30
  parameters: ## optional - if not specified, then all parameters are used
30
31
  - start_date
31
32
  - end_date
32
33
  - min_filter
33
34
  - max_filter
34
- traits: {} ## optional - defaults to empty object
35
35
 
36
- - name: federate_dataset_example
37
- label: Example Dataset from Federate Model
36
+ - name: grouped_expenses
37
+ label: Grouped Expenses - Federate Example
38
38
  description: Aggregated expense transactions by custom dimension using federate_example model
39
- model: federate_example
40
- scope: protected ## using an auth.py file is suggested for protected or private datasets
39
+ model: federate_example
41
40
  parameters:
42
41
  - group_by
43
- - limit
44
42
  - date_range
45
43
  - category
46
44
  - subcategory
47
45
  - between_filter
48
- default_test_set: auth_test1 ## optional - if not specified, uses setting 'selection_test_sets.default_name_used'
49
46
 
50
47
 
51
48
  selection_test_sets:
52
- - name: no_auth_test1
53
- datasets: ## optional section - if not provided, then test set is applicable for any dataset
54
- - dbview_dataset_example
55
- parameters: ## optional section - if not provided, then assumes no parameters. For unspecified parameters, default value is used
56
- start_date: 2024-07-01 ## this parameter only exists for dataset 'dataset_example'
49
+ - name: set_start_date
50
+ parameters: ## optional section - if not provided, then default value is used for all parameters
51
+ start_date: 2024-07-01 ## this parameter is only used by model "dbview_example"
57
52
 
58
- - name: auth_test1
59
- datasets:
60
- - federate_dataset_example
61
- user_attributes: ## optional section - required if using test set on non-public datasets
62
- role: employee
53
+ - name: set_date_range
63
54
  parameters:
64
- date_range: [2024-02-01,2024-12-01] ## this parameter only exists for dataset 'protected_dataset_example'
55
+ date_range: [2024-02-01,2024-11-30] ## this parameter is only used by model "federate_example"
65
56
 
66
- - name: auth_test2
67
- user_attributes:
68
- is_internal: True ## optional - defaults to False
69
- role: manager
57
+ - name: use_admin_privileged_group_by
58
+ user:
59
+ access_level: admin
70
60
  parameters:
71
- group_by: g3 ## this parameter exists for all datasets. "g3" is the id for option "subcategory"
61
+ group_by: trans
@@ -0,0 +1,53 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Signed In</title>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, system-ui, sans-serif;
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ height: 100vh;
14
+ margin: 0;
15
+ background-color: #f9fafb;
16
+ color: #111827;
17
+ }
18
+ .card {
19
+ text-align: center;
20
+ padding: 24px;
21
+ }
22
+ .icon {
23
+ color: #059669;
24
+ font-size: 48px;
25
+ margin-bottom: 16px;
26
+ }
27
+ h1 {
28
+ font-size: 24px;
29
+ font-weight: 600;
30
+ margin: 0 0 8px;
31
+ }
32
+ p {
33
+ font-size: 16px;
34
+ color: #6b7280;
35
+ margin: 0;
36
+ }
37
+ </style>
38
+ </head>
39
+ <body>
40
+ <div class="card">
41
+ <div class="icon">✓</div>
42
+ <h1>Signed in successfully</h1>
43
+ <p>You can close this window now.</p>
44
+ </div>
45
+
46
+ <script>
47
+ if (window.opener) {
48
+ window.opener.postMessage({ type: "squirrels:auth:login-successful" }, "*");
49
+ setTimeout(function() { window.close(); }, 1000);
50
+ }
51
+ </script>
52
+ </body>
53
+ </html>
@@ -0,0 +1,22 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link id="favicon" rel="icon" type="image/svg+xml" href="{{ sqrl_studio_base_url }}/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Squirrels Studio</title>
8
+ <script>
9
+ // Optional: Set global defaults for project parameters
10
+ window.DEFAULT_MOUNTPATH = '{{ mount_path }}';
11
+ </script>
12
+ <!--
13
+ GitHub Pages serves static files with a Cache-Control header that typically tells the browser to cache for 10 minutes.
14
+ The implementation of squirrels-studio-v2 should be compatible with all versions of Squirrels from v0.6.0 onwards.
15
+ -->
16
+ <script type="module" crossorigin src="{{ sqrl_studio_base_url }}/assets/index.js"></script>
17
+ <link rel="stylesheet" crossorigin href="{{ sqrl_studio_base_url }}/assets/index.css">
18
+ </head>
19
+ <body>
20
+ <div id="root"></div>
21
+ </body>
22
+ </html>