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.
- squirrels/__init__.py +4 -0
- squirrels/_api_routes/__init__.py +5 -0
- squirrels/_api_routes/auth.py +337 -0
- squirrels/_api_routes/base.py +196 -0
- squirrels/_api_routes/dashboards.py +156 -0
- squirrels/_api_routes/data_management.py +148 -0
- squirrels/_api_routes/datasets.py +220 -0
- squirrels/_api_routes/project.py +289 -0
- squirrels/_api_server.py +440 -792
- squirrels/_arguments/__init__.py +0 -0
- squirrels/_arguments/{_init_time_args.py → init_time_args.py} +23 -43
- squirrels/_arguments/{_run_time_args.py → run_time_args.py} +32 -68
- squirrels/_auth.py +590 -264
- squirrels/_command_line.py +130 -58
- squirrels/_compile_prompts.py +147 -0
- squirrels/_connection_set.py +16 -15
- squirrels/_constants.py +36 -11
- squirrels/_dashboards.py +179 -0
- squirrels/_data_sources.py +40 -34
- squirrels/_dataset_types.py +16 -11
- squirrels/_env_vars.py +209 -0
- squirrels/_exceptions.py +9 -37
- squirrels/_http_error_responses.py +52 -0
- squirrels/_initializer.py +7 -6
- squirrels/_logging.py +121 -0
- squirrels/_manifest.py +155 -77
- squirrels/_mcp_server.py +578 -0
- squirrels/_model_builder.py +11 -55
- squirrels/_model_configs.py +5 -5
- squirrels/_model_queries.py +1 -1
- squirrels/_models.py +276 -143
- squirrels/_package_data/base_project/.env +1 -24
- squirrels/_package_data/base_project/.env.example +31 -17
- squirrels/_package_data/base_project/connections.yml +4 -3
- squirrels/_package_data/base_project/dashboards/dashboard_example.py +13 -7
- squirrels/_package_data/base_project/dashboards/dashboard_example.yml +6 -6
- squirrels/_package_data/base_project/docker/Dockerfile +2 -2
- squirrels/_package_data/base_project/docker/compose.yml +1 -1
- squirrels/_package_data/base_project/duckdb_init.sql +1 -0
- squirrels/_package_data/base_project/models/builds/build_example.py +2 -2
- squirrels/_package_data/base_project/models/dbviews/dbview_example.sql +7 -2
- squirrels/_package_data/base_project/models/dbviews/dbview_example.yml +16 -10
- squirrels/_package_data/base_project/models/federates/federate_example.py +27 -17
- squirrels/_package_data/base_project/models/federates/federate_example.sql +3 -7
- squirrels/_package_data/base_project/models/federates/federate_example.yml +7 -7
- squirrels/_package_data/base_project/models/sources.yml +5 -6
- squirrels/_package_data/base_project/parameters.yml +24 -38
- squirrels/_package_data/base_project/pyconfigs/connections.py +8 -3
- squirrels/_package_data/base_project/pyconfigs/context.py +26 -14
- squirrels/_package_data/base_project/pyconfigs/parameters.py +124 -81
- squirrels/_package_data/base_project/pyconfigs/user.py +48 -15
- squirrels/_package_data/base_project/resources/public/.gitkeep +0 -0
- squirrels/_package_data/base_project/seeds/seed_categories.yml +1 -1
- squirrels/_package_data/base_project/seeds/seed_subcategories.yml +1 -1
- squirrels/_package_data/base_project/squirrels.yml.j2 +21 -31
- squirrels/_package_data/templates/login_successful.html +53 -0
- squirrels/_package_data/templates/squirrels_studio.html +22 -0
- squirrels/_parameter_configs.py +43 -22
- squirrels/_parameter_options.py +1 -1
- squirrels/_parameter_sets.py +41 -30
- squirrels/_parameters.py +560 -123
- squirrels/_project.py +487 -277
- squirrels/_py_module.py +71 -10
- squirrels/_request_context.py +33 -0
- squirrels/_schemas/__init__.py +0 -0
- squirrels/_schemas/auth_models.py +83 -0
- squirrels/_schemas/query_param_models.py +70 -0
- squirrels/_schemas/request_models.py +26 -0
- squirrels/_schemas/response_models.py +286 -0
- squirrels/_seeds.py +52 -13
- squirrels/_sources.py +29 -23
- squirrels/_utils.py +221 -42
- squirrels/_version.py +1 -3
- squirrels/arguments.py +7 -2
- squirrels/auth.py +4 -0
- squirrels/connections.py +2 -0
- squirrels/dashboards.py +3 -1
- squirrels/data_sources.py +6 -0
- squirrels/parameter_options.py +5 -0
- squirrels/parameters.py +5 -0
- squirrels/types.py +10 -3
- squirrels-0.6.0.post0.dist-info/METADATA +148 -0
- squirrels-0.6.0.post0.dist-info/RECORD +101 -0
- {squirrels-0.5.0b3.dist-info → squirrels-0.6.0.post0.dist-info}/WHEEL +1 -1
- squirrels/_api_response_models.py +0 -190
- squirrels/_dashboard_types.py +0 -82
- squirrels/_dashboards_io.py +0 -79
- squirrels-0.5.0b3.dist-info/METADATA +0 -110
- squirrels-0.5.0b3.dist-info/RECORD +0 -80
- /squirrels/_package_data/base_project/{assets → resources}/expenses.db +0 -0
- /squirrels/_package_data/base_project/{assets → resources}/weather.db +0 -0
- {squirrels-0.5.0b3.dist-info → squirrels-0.6.0.post0.dist-info}/entry_points.txt +0 -0
- {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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
22
|
-
|
|
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["
|
|
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
|
|
1
|
+
from squirrels import parameters as p, parameter_options as po, data_sources as ds
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
"
|
|
24
|
-
columns=["
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
|
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
|
|
6
|
+
class CustomUserFields(BaseCustomUserFields):
|
|
6
7
|
"""
|
|
7
|
-
Extend the
|
|
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
|
-
-
|
|
10
|
-
- Always set a default value for the
|
|
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", "
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
File without changes
|
|
@@ -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 -
|
|
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 -
|
|
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:
|
|
3
|
-
label: Sample
|
|
4
|
-
description: This is a sample
|
|
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:
|
|
25
|
-
label:
|
|
26
|
-
description:
|
|
27
|
-
model: dbview_example
|
|
28
|
-
scope:
|
|
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:
|
|
37
|
-
label:
|
|
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:
|
|
53
|
-
|
|
54
|
-
-
|
|
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:
|
|
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-
|
|
55
|
+
date_range: [2024-02-01,2024-11-30] ## this parameter is only used by model "federate_example"
|
|
65
56
|
|
|
66
|
-
- name:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
role: manager
|
|
57
|
+
- name: use_admin_privileged_group_by
|
|
58
|
+
user:
|
|
59
|
+
access_level: admin
|
|
70
60
|
parameters:
|
|
71
|
-
group_by:
|
|
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>
|