gramener / gramex Goto Github PK
View Code? Open in Web Editor NEWA visual analytics platform to build data-based web apps with less code.
Home Page: https://gramener.com/gramex/guide/
License: Other
A visual analytics platform to build data-based web apps with less code.
Home Page: https://gramener.com/gramex/guide/
License: Other
Do not recreate what's in underlying libraries. Just return a manipulable object. Provide an easy mechanism to render it
The technical architecture template is a Markdown document that explains the technical solution for the project.
It is intended to be a live document -- changing as the requirements flow.
It is a testable document -- i.e. can be translated into test cases directly. Ideally, this should be automatable
It is a mandatory document -- not filling it should result in test errors
Author: s.anand
Created: Thu 05 Apr 2018 16:49
FormHandler should allow only specific users to perform specific database actions. For example:
This requires identifying the users, and identifying their permissions. FormHandler (and gramex.data.filter
) should accept an auth
object that has 3 keys:
membership
: same as in auth roles. Defines WHO this rule is for. This is a list of attr: values that match the user object. For example:
email: '*@gramener.com'
-- matches any user where handler.current_user['email']
matches *@gramener.com
email: [x@..., y@...]
matches both x@...
OR y@...
[domain: gramener.com, user: s.anand]
means that handler.current_user['user']
MUST equal s.anand AND handler.current_user['domain']
MUST equal gramener.com`conditition
: same as in auth roles. Defines WHO this rule is for. Typically used INSTEAD of membership if we want advanced rules / custom functions.permissions
: optional list of rule objects. Defaults to all access. A rule object has:
type
: allow or denyurl
: DB URL to allow/deny accesssheetname
or table
or anything else gramex.data.filter
acceptscolumn
: columns to allow/deny accessaccess
: type of access to allow or denyfnmatch
style wildcardscondition: ...
membership:
- col: val
- col: [val, val]
permission:
- {type: allow, url: data.db, access: [all = create, read, update, delete]}
- {type: deny, url: data.db, table: t1, access: [create]}
- {type: deny, url: data.db, table: t2, column: c1, access: [write = update, delete, create]}
To be implemented as gramex.data.access(auth, ...)
that returns True / False
Example: gramex.data.filter('adl://data-lake-store-name.azuredatalakestore.net/dir/file')
Reference: https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.6.5/bk_cloud-data-access/content/adls-uri.html
Requested by @sundeep.mallu
This would be an added optional parameter for any auth. Perhaps best implemented as a login action.
Adding standard .gitlab/issue_templates/
allows projects to use a standard set of Gitlab issue templates
The new issue page will have a dropdown listing all templates. Users can choose one of these.
Star team requests having an ability to search by user/ pages in LogViewer UI.
Enhance Gramex big data processing capability by integrating with Spark or Arrow
This allows for Gramex to position as a real-time analytics engine platform.
Clustering component available as part of Gramex.
Existing DataApps can use transformed data to run Clustering algorithm on them. This will enhance the value proposition for Gramex Platform offering.
Any usecase where segmentation of data into Homogeneous groups is required.
Features like settings page (configure data connection, selection of data elements, selection of ML algorithm to apply) should be part of Gramex and not tied to Clustering tool alone.
prepare
The requirement for "No duplicate entry for Username. Unique username" is to ensure that a user has a unique mobile number AND a unique email ID.
admin2
SmartAlert feature should allow individual end users to configure the frequency of emails they opt for.
End users can control the volume of alerts they get and when.
Note from @pratap.vardhan
update_schedule
def update_schedule(handler):
# key with user.id and page
key = row[user.id] + row[ur]
gramex.service.schedule[key] = Task(... email_service ...)
update_entry_into_db(row)
Use formhandler to read user's preferences
Integrate subscription edits from existing user page with endpoints.
todo: Use formhandler instead of functionhandler to read/edit user preferences with post function to trigger Scheduler API.
(Currently, formhandler's modify is restricted to reads, we need to extend to edits, to replace the use of functionhandler)
Sample UI from tableau - https://cdnl.tblsft.com/sites/default/files/blog/dda_opener.gif
Make sure you setup fresh environment
Install gramex
Run nosetests
Run guide
Author: pratap.vardhan
Created: Tue 06 Nov 2018 11:57
Allow LogViewer to render data from other log files
Projects can include other logs as part of the same log viewer, such as:
Create a configuration that accepts
Given this, Log Viewer will
pre-aggregate the data source(s) into daily, weekly, monthly, etc
render the charts based on the configuration
Author: s.anand
Created: Sun 04 Mar 2018 09:53
Excel is used to create models (data, pivot, charts, controls, what-if scenarios)
We provide an interface to modify model-copy via web apis.
# SET VALUES
model = gramex.excel.open(filename)
model.Sheet1['A3'] = 20 # cell address
model.Sheet1['roi'] = 0.5 # named cell
# model['sheet name']['roi'] = 0.5
print model.Sheet1['result'] # named range as dataframe
model.Sheet1['result'] = 1.0
# READ ...
print model.Sheet1['chart1'] # named chart as base64 bitmap READONLY
Driven by com interface.
This most common features required are:
The following are better done within the Excel interface:
Get / set multiple values based on input. (Use Excel to change other cells based on input)
Changing fonts, styles, etc. (Use Excel)
Adding formulas into cells. (Use Excel)
Author: pratap.vardhan
Created: Thu 05 Jul 2018 08:00
When, new handler spec is added to gramex.yaml
or gramex.init(kwargs)
, gramex
reloads all the configurations, which takes time.
We should update config cruds (update, add, delete) atomically. This helps IDE to be performant.
Users can add comments
Users can edit or delete their own comments
Visibility level for comments can be set by developer to Public, Logged-in or role-restricted
Multiple comment sections allowed per page
Integrated with Gramex auth
Flexible UI
Ignore optional features
The main reasons not to use a third-party embedded commenting system or discussion forum are (a) ease of integrating authentication, and (b) being able to install on-prem
Discourse? SSO is painful. It can't be on-prem.
Facebook? Only Facebook auth
Author: s.anand
Created: Fri 18 Aug 2017 05:52
New Logviewer config has a capturehandler at port:9900 this can conflict with someone running their own capturehandler at the same port. Also, if an app is already using capturehandler, should logviewer take that endpoint instead of creating its own?
Show a FormHandler table that lists all objects in the gramex cache with:
key
type
size
an action to delete
Author: s.anand
Created: Thu 28 Jun 2018 05:10
This issue tracks the current status and next steps on admin module changes.
@sindhura.ch to ask @dipika.verma
Sindhura to migrate to admin2/ and reproduce the problems below. They may vanish:
In our next discussion, Anand to guide on how to implementt :
No duplicate entry for Username. Unique username
Allow users to register themselves with custom fields with approval
Add Approval action item in the Action column
User profile page that users can edit themselves
Author: s.anand
Created: Tue 18 Dec 2018 06:29
Create gramex.data.table()
that creates or alters table column structures
def columns(url, args, meta={}, engine=None, table=None, ext=None, **kwargs):
'''
Allows adding / changing / deleting columns in a table in a DataFrame, file
or database. This is URL friendle.
This URL structure::
?name=col1&type=text&default=&primary=Y&op=add
&name=col2&type=int&default=0
&name=col3&op=del
...is the same as calling::
columns(url, table, args={
'name': ['col1', 'col2', 'col3'],
'type': ['text', 'int', '' ]
'default': ['', '0', '' ],
'primary': ['Y', '', '' ],
'op': ['add', 'add', 'del' ],
})
The URL query parameters (args) have the following structure:
- name: column name
- type: column type. Can be a python or SQLAlchemy at
- default: blank indicates NULL, any other value is converted to the type
- primary: blank indicates False, any other value is true
- op: 'add' (default) or 'del'
Parameters:
:arg source url: Pandas DataFrame, sqlalchemy URL, directory or file name,
``.format``-ed using ``args``.
:arg dict args: Column structure query parameters. Pass handler.args or parse_qs results
:arg dict meta: this dict is updated with metadata during the course of filtering
:arg string table: table name (if url is an SQLAlchemy URL), ``.format``-ed
using ``args``.
:arg string ext: file extension (if url is a file). Defaults to url extension
:arg dict kwargs: Additional parameters are passed to
:py:func:`gramex.cache.open` or ``sqlalchemy.create_engine``
:return: resulting table structure
'''
Provide an ability to show a pop-up periodically to Visual Solution users.
The goal is to capture instant feedback from users by using a simple scale (attractive design) and track it as part of User activity data.
The popup allow for the below configuration
DEPENDENCIES - Design team to give provide high fidelity UI for the pop.
28/12 - Hemanth has identified few UI proposals/ questions. Will be sharing them via email.
Suggested questions from Hemanth:
What is the goal of your today's visit to Dashboard? (Open ended)
Were you able to complete the purpose of your visit today to Dashboard? (5 point scale)
What do you like the most/the least about Dashboard>? (Open ended)
Overall how well does Dashboard meet your needs? (5 point scale)
How easy was it to find the information you were looking for on Dashboard (5 point scale)
How easy was it to understand the information on Dashboard? (5 point scale)
Do you have any feedback on how can we improve Dashboard? (Open ended)
Author: sundeep.mallu
Created: Fri 08 Dec 2017 10:33
Create a CMS component in gramex, that will allow users to maintain the homepage(s) content in a google sheet or other soruces.
Business Users can modify the content of a Visual story board, without need for a code change/ deployment.
gramener.com/demo page today is driven off content in a google sheet. We can provide similar CMS capability as part of customer offering.
For example, we want something like this:
pattern: /(special|img|css)/(.*)
handler: FileHandler
kwargs:
map:
/special/(.*): assets/special/$1.html
/(.*)/(.*): $1/$2.html
transform:
...
We also want to allow fallback paths. For example: some projects use favicon.ico. Pick it from the project directory. If that doesn't exist, pick it from $GRAMEXPATH.
This will help developers create friendly URLs for static files and not have to create multiple FileHandlers.
Alerts should be able to send SMS notifications, apart from emails
The same alert should be able to send SMS and email notifications (based on the same conditions, data, etc.) This can be enabled via:
kwargs:
sms_service: ...
sms_to: ...
sms_subject: ... # Which defaults to subject
sms_sender: ...
This needs to be logged as well. Plan a consistent logging mechanism.
This is a master issue for current log viewer issues.
Note on the calendar component: pick a from date, pick a to date, continue hovering. This changes the from date. Suggested behavior: don't change the from/to date until clicked.
The log files are at gramex.conf.variables['GRAMEXDATA']
under logs/
. Files are:
requests.csv*
: each request & response made to Gramexuser.csv*
: user login and logout informationalert.csv*
: logs alerts data (optional)access.csv*
: old Gramex logs. Ignore thisgramex.log*
: new Gramex logs. Ignore thisCode is at gramex/apps/logviewer/. @pratap.vardhan is the author.
We want to create admin/logviewer as a series of individual components that addresses these needs:
Phase 1: Migrate logviewer backend to admin/log/
logviewer-admin
to migrate logviewer as-is into admin modulelogviewer.py
and gramex.yaml
schedule into admin page and test that the back-end FormHandler endpoints workPhase 2: Create simple front-end components in admin/log/
Phase 3: Integrate all components required into admin/log/
page
More project uses MongoDB. This warrants integration with MongoDB and ElasticSearch.
We would want to extend FormHandler API behavior which resides in gramex.data.{filter,update,etc}
to connect to MongoDB and ElasticSearch. See docstrings for usage and URL query parameters to understood API.
filtered = gramex.data.filter('connection_string_to_detect', table='table', args=handler.args)
testlib/test_data.py
and tests/test_formhandler.py
for the given connector. These already have bunch of testcases, tested across different connectors, Inherit and extend for new connectors.Approaches For ElasticSearch:
sqlalchemy-elasticquery
can be used. We directly support sqlalchemy dialects.Create a component that indexes structured. Back-end options are:
An example of real-life usage would be at https://learn.gramener.com/search/
The URL filterhandler?_c=Country&_c=State&_c=City
displays all Country, State, City ignoring the hierarchy.
But after filterhandler?_c=Country&_c=State&_c=City
if we add a &_h=Country>State>City
then:
Country
values. State
and City
are empty listsfilterhandler?_c=Country&_c=State&_c=City&_h=Country>State>City&Country=USA
.
Country
values, and all State
values for Country=USA
. City
is an empty listfilterhandler?_c=Country&_c=State&_c=City&_h=Country>State>City&Country=USA&State=Utah
.
Country
values, and all State
values for Country=USA
, and all City
values for Country=USA&State=Utah
FilterHandlers may contain multiple hierarchies. For example: ?_h=Country>State>City&_h=Category>Brand
has 2 heirarchies:
Country>State>City
Category>Brand
Set up discourse on gramener.com
Embed discourse on the guide template pages
Display on all pages publicly
Author: s.anand
Created: Mon 17 Sep 2018 12:59
Build a Forecasting component in gramex platform
All Visual story boards that have time series data can use this component to build forecasting components.
This feature is required to ensure the Visual Story board built on top of Gramex doesn't expose a vulnerability.
oEmbed gives the ability to embed visuals seamlessly in blogs, articles, Gramener projects.
Maps and charts created from MapViewer UI
, Vega chart interface
can be easily exposed to projects without additional effort.
Immediate use: Open data platform project
, MapViewer UI
features export options (image, embed).
Request for a URL such as https://some-dashboard.gramener.com/oembed?visual=some_random_string_id should return a oEmbed formatted JSON object
This blog post details an example including their implementation in django
framework
class OEmbed(APIView):
def get(self, request):
# The second param passed to the .get() method is the default value, which
# is returned if the specified key (first param) isn't found in the dictionary.
url = request.query_params.get('url', '')
max_width = request.query_params.get('maxwidth', 0)
max_height = request.query_params.get('maxheight', 0)
resp_format = request.query_params.get('format', '')
referrer = request.query_params.get('referrer', '')
if resp_format and not resp_format == 'json':
return Response(data={}, status=501)
if max_width < 280:
return Response(data={}, status=501)
if max_height < 825:
return Response(data={}, status=501)
try:
thread_id = utils.get_thread_id_from_url(url)
except ObjectDoesNotExist:
return Response(data={}, status=404)
try:
thread = thread_service.get_thread_from_thread_id(request, thread_id)
except InvalidPermissionError:
return Response(data={}, status=401)
width = max_width if (max_width and max_width <= 700) else 700
height = 825
resp = thread_service.build_oembed_response(thread, width, height, referrer)
return Response(data=resp, status=status.HTTP_200_OK)
For example, FWD:everyone implements oEmbed
for a request, https://api.fwdeveryone.com/oembed?url=https://www.fwdeveryone.com/t/e8RFukWTS5Wo54fBNbZ2yQ, and responds as below:
{
"version": "1.0",
"type": "rich",
"provider_name": "FWD:Everyone",
"provider_url": "https://www.fwdeveryone.com"
"author_name": "Alex Krupp",
"author_url": "https://www.fwdeveryone.com/u/alex3917",
"html": "<iframe src=\"https://oembed.fwdeveryone.com?thread-id=e8RFukWTS5Wo54fBNbZ2yQ\" width=\"700\" height=\"825\" scrolling=\"yes\" frameborder=\"0\" allowfullscreen></iframe>",
"width": 700,
"height": 825,
"thumbnail_url": "https://ddc2txxlo9fx3.cloudfront.net/static/fwd_media_preview.png",
"thumbnail_width": 280,
"thumbnail_height": 175,
"referrer": "",
"cache_age": 3600,
}
Migrate the Gramex FAQ's Google Doc to /guide for easier access.
Allow for SQL query editor in IDE/ Query page
Allowing for SQL query will expand the no.of users who can go past Query page. Current capability only allows for Python queries. This limits the no.of users who can benefit from the flexibility that IDE allows for.
Include Pandas SQL for allowing for SQL querying.
While trying to uninstall Gramex from Git Bash, I get stuck at c:\users\gramener\anaconda\lib\site-packages\gramex\transforms.py . It doesn't progress after that.
?_q=text
filters rows that match "text" in any of the chosen query columns?_qc
. For example, ?_qc=firstname&_qc=lastname&_q=name
searches for "name" in the "firstname" and "lastname" columns.columns['firstname'].contains('name') or columns['lastname'].contains('name')
. See contains_qc
defaults to all string columns in the table_qc
contains non-string columns, these are added to metadata as meta['ignored']
as ('_qc', col), ...
Implementation notes in gramex/data.py
:
_pop_controls()
must pop out _q
and _qc
as controls_filter_db()
, under the # Apply controls
, add a if '_q' in controls:
section_qc
is in controls, pick only those columns._qc
columns are not in controls, add them to meta['ignored'].append(('_qc', qc_ignored_cols))
columns[col].contains(query)
for each column, using an OR join.Origin:
Integration with Amazon SNS is a pre-requisite.
Currently we support Info
, Shell
, Users
as options in Admin2
panel.
Is it a good idea to expose session details there as well?
Session details -- how long can users log in to the application (session expiry), purged session duration. These details display the same (User session expiry -- 1 month
) instead of user level session details (Bhanu's session will expire on December 11th 2pm since he logged on November 11th 2pm.
)
This helps in debugging session expiry related issues.
FIRST find out why this is important. Whom it will help. Why existing products don't work. Re-use, don't build.
This is an app that should be bundled with Gramex. It allows users to point to directories or databases. It scans all files / tables under these and presents a searchable list of all datasets, and lets them explore and edit these using FormHandler.
We already have a version of this in https://code.gramener.com/soumya.ranjan/databrowse
Features:
Examples?
Author: s.anand
Created: Mon 13 Nov 2017 06:36
Build a Text Classification handler in Gramex as a component. This component can be embedded into a DataApp to perform text classification operation.
Text Classification capability is one of the most commonly used ML feature across businesses. By having this model built as component in Gramex, we can offer value propositions to the Visual Story boards that we build for customers.
Potential usage in engagements like PMOsocial where each tweet is classified as positive/ negative/ neutral.
Backend - Handler - Accept post request, take meta data (json, key=sentence, key=classiciation)
- get request (json object. )
- Bulk classifire (classify text as an array)
- Handler should be able to invoke any model - scikit-learn, cloud API - google ML, tensorflow,
Front end - standard application
See https://developers.google.com/analytics/devguides/collection/protocol/v1/email
Developers can quickly introduce mail tracking
Users can see which emails are being opened, perhaps by whwom
Author: s.anand
Created: Sat 10 Mar 2018 01:48
Feature request from Sarad G
Can we have a diagnostic page on top of gramex logs which gives info on some of the basic questions below
We want to migrate our code into Github.
pip install gramex
installs the open source version of Gramex.
gramex install auth
installs additional authentication plugins from Gitlab for authenticated users.
I propose Gramex 2.0 as a:
Pandas and Numpy have already dropped support. Tornado drops Python 2 support in July 2019.
We will target March 2019 for this release.
Create a component that lets users check if links are working.
This component is deployed at https://learn.gramener.com/guide/linkcheck/ and needs to be componentised
Ability to generate static file from templates driven by data
for a given row
Pick template from templates/{row.country}/index.html
pass {{ row }}
data to generate stories/countries/{row.country}/index.html
Add more details.
Alerts use email service, extend to use file writer.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.