From 59faaaba3875c60c88bb1aa7adea2ef16a94705c Mon Sep 17 00:00:00 2001 From: jeremytchang <78522362+jeremytchang@users.noreply.github.com> Date: Mon, 1 Nov 2021 17:09:14 -0700 Subject: [PATCH 1/3] fix: Add hackathon resources and refactor to use enums (#887) - Added JOIN Yt videos to hackathon resources - Updated resource tags and type to use enums for better maintenance - Updated resource buttonitem rendering to be based off tags enum Co-authored-by: John Kaster --- .../scenes/ResourceScene/ResourceScene.tsx | 17 +- .../src/scenes/ResourceScene/resource_data.ts | 241 +++++++++++------- 2 files changed, 154 insertions(+), 104 deletions(-) diff --git a/packages/hackathon/src/scenes/ResourceScene/ResourceScene.tsx b/packages/hackathon/src/scenes/ResourceScene/ResourceScene.tsx index 42e53646d..9aebfa351 100644 --- a/packages/hackathon/src/scenes/ResourceScene/ResourceScene.tsx +++ b/packages/hackathon/src/scenes/ResourceScene/ResourceScene.tsx @@ -41,7 +41,7 @@ import { } from '@looker/components' import { getExtensionSDK } from '@looker/extension-sdk' import { Routes } from '../../routes/AppRouter' -import { resources } from './resource_data' +import { resources, ResourceTag } from './resource_data' interface ResourceSceneProps {} @@ -90,16 +90,11 @@ export const ResourceScene: FC = () => { description="Select 1 or more areas" > - Embed - Extensions - LookML - Actions - API - Custom Viz - Dev Tools - Components - Datasets - Other + {Object.keys(ResourceTag).map((k) => ( + + {ResourceTag[k]} + + ))} diff --git a/packages/hackathon/src/scenes/ResourceScene/resource_data.ts b/packages/hackathon/src/scenes/ResourceScene/resource_data.ts index 450426f6a..b2347e90a 100644 --- a/packages/hackathon/src/scenes/ResourceScene/resource_data.ts +++ b/packages/hackathon/src/scenes/ResourceScene/resource_data.ts @@ -24,28 +24,83 @@ */ +// Enum serves as display strings too +enum ResourceType { + Resource = 'Resource', + Tutorial = 'Tutorial', + Example = 'Example', +} + +// Enum serves as display strings too +export enum ResourceTag { + Embed = 'Embed', + Extensions = 'Extensions', + Lookml = 'LookML', + Actions = 'Actions', + API = 'API', + Devtool = 'Dev Tools', + Components = 'Components', + Datasets = 'Datasets', + CustomViz = 'Custom Viz', + Other = 'Other', +} + export interface Resource { content: string - type: string - tag: string + type: ResourceType + tag: ResourceTag link: string shortenedLink: string title: string } export const resources: Array = [ + { + content: + 'A JOIN 2021 intro and demo video of the new visualization components.', + type: ResourceType.Resource, + tag: ResourceTag.Components, + link: 'https://www.youtube.com/watch?v=rSWX6oAOtMs', + shortenedLink: 'https://bit.ly/3nQxGkr', + title: 'Visualization Components Demo Video', + }, + { + content: + 'A JOIN 2021 tutorial video on developing with the Extension Framework.', + type: ResourceType.Tutorial, + tag: ResourceTag.Extensions, + link: 'https://www.youtube.com/watch?v=3lbq5w7kcLs', + shortenedLink: 'https://bit.ly/3jXck3Y', + title: 'Extension Framework Tutorial Video', + }, + { + content: 'A JOIN 2021 tutorial video on using API Explorer and Looker API.', + type: ResourceType.Tutorial, + tag: ResourceTag.API, + link: 'https://www.youtube.com/watch?v=f1Wb4dYZxhM', + shortenedLink: 'https://bit.ly/2ZT71eS', + title: 'API Explorer & API Tutorial Video', + }, + { + content: 'A JOIN 2021 tutorial video on Iframe and SSO Embedding.', + type: ResourceType.Tutorial, + tag: ResourceTag.Embed, + link: 'https://www.youtube.com/watch?v=XTvJjCeAT74', + shortenedLink: 'https://bit.ly/3q1f0RR', + title: 'Embed Tutorial Video', + }, { content: 'The API Explorer lets you learn and interact with Looker API.', - type: 'Resource', - tag: 'api', + type: ResourceType.Resource, + tag: ResourceTag.API, link: 'https://hack.looker.com/extensions/marketplace_git_github_com_looker_open_source_extension_api_explorer_git::api-explorer', shortenedLink: 'https://bit.ly/3j1sdWD', title: 'API Explorer', }, { content: 'Gzr is a Looker Content Utility developer tool', - type: 'Example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/looker-open-source/gzr', shortenedLink: 'https://bit.ly/3mSyZiu', title: 'Gzr', @@ -53,8 +108,8 @@ export const resources: Array = [ { content: 'The SDK Codegen is the source of truth for all SDKs and lets you create them for any language', - type: 'Resource', - tag: 'api', + type: ResourceType.Resource, + tag: ResourceTag.API, link: 'https://github.com/looker-open-source/sdk-codegen', shortenedLink: 'https://bit.ly/3lIk23g', title: 'SDK Codegen', @@ -62,8 +117,8 @@ export const resources: Array = [ { content: 'Our collection of SDK examples currently in: C#, Java, Kotlin, Python, R, Ruby, Swift, and TypeScript.', - type: 'Resource', - tag: 'api', + type: ResourceType.Resource, + tag: ResourceTag.API, link: 'https://github.com/looker-open-source/sdk-codegen/tree/main/examples', shortenedLink: 'https://bit.ly/3AL4VdI', title: 'SDK Examples', @@ -71,8 +126,8 @@ export const resources: Array = [ { content: 'Look At Me Sideways (LAMS) is the official LookML style guide and linter to help you create maintainable LookML projects.', - type: 'Example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/looker-open-source/look-at-me-sideways', shortenedLink: 'https://bit.ly/3DOrMGS', title: 'LookML Style Guide & Linter', @@ -80,16 +135,16 @@ export const resources: Array = [ { content: 'Looker Components are a collection of tools for building Looker data experiences.', - type: 'Resource', - tag: 'component', + type: ResourceType.Resource, + tag: ResourceTag.Components, link: 'https://components.looker.com/', shortenedLink: 'https://bit.ly/2Z2Q69C', title: 'Looker Components', }, { content: 'Looker Components Storybook contains component examples', - type: 'Resource', - tag: 'component', + type: ResourceType.Resource, + tag: ResourceTag.Components, link: 'https://components.looker.com/storybook', shortenedLink: 'https://bit.ly/3pbpygP', title: 'Components Examples Storybook', @@ -97,8 +152,8 @@ export const resources: Array = [ { content: 'The Looker JavaScript Embed SDK makes embedding Looker content in your web application easy!', - type: 'Resource', - tag: 'embed', + type: ResourceType.Resource, + tag: ResourceTag.Embed, link: 'https://github.com/looker-open-source/embed-sdk', shortenedLink: 'https://bit.ly/3n2mDEJ', title: 'Embed SDK', @@ -106,8 +161,8 @@ export const resources: Array = [ { content: 'Henry is a command line tool that finds model bloat in your Looker instance and identifies unused content in models and explores.', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/looker-open-source/henry', shortenedLink: 'https://bit.ly/3j1NShp', title: 'Henry', @@ -115,16 +170,16 @@ export const resources: Array = [ { content: 'A repository with multiple Extension Framework examples using Typescript, Javascript, React, and Redux', - type: 'example', - tag: 'extension', + type: ResourceType.Example, + tag: ResourceTag.Extensions, link: 'https://github.com/looker-open-source/extension-examples', shortenedLink: 'https://bit.ly/2YYdlkM', title: 'Extension Framework Examples', }, { content: `This example demonstrates most of Extension SDK's functionality and is a great starting point.`, - type: 'example', - tag: 'extension', + type: ResourceType.Example, + tag: ResourceTag.Extensions, link: 'https://github.com/looker-open-source/extension-examples/tree/main/react/typescript/kitchensink', shortenedLink: 'https://bit.ly/3n1zbMk', title: 'Extension Example: Kitchensink', @@ -132,8 +187,8 @@ export const resources: Array = [ { content: 'The React Extension SDK npm package. This lets you build a Looker extension — See the Extension Framework Examples for examples.', - type: 'resource', - tag: 'extension', + type: ResourceType.Resource, + tag: ResourceTag.Extensions, link: 'https://www.npmjs.com/package/@looker/extension-sdk-react', shortenedLink: 'https://bit.ly/3pbzoPN', title: 'Extension SDK: React', @@ -141,8 +196,8 @@ export const resources: Array = [ { content: 'Chatty is a simple web browser iframe host/client channel message manager. We use it for iframe communication.', - type: 'resources', - tag: 'embed', + type: ResourceType.Resource, + tag: ResourceTag.Embed, link: 'https://github.com/looker-open-source/chatty', shortenedLink: 'https://bit.ly/2Z2NrfP', title: 'Chatty - Iframe Msg Manager', @@ -150,8 +205,8 @@ export const resources: Array = [ { content: 'A Snowflake based LookML that demonstrates Looker’s value in the digital marketing landscape.', - type: 'example', - tag: 'lookml', + type: ResourceType.Example, + tag: ResourceTag.Lookml, link: 'https://github.com/looker-open-source/marketing_demo', shortenedLink: 'https://bit.ly/2YR9rKN', title: 'Digital Marketing Demo', @@ -159,8 +214,8 @@ export const resources: Array = [ { content: 'A BigQuery based LookML that demonstrates Looker’s value in the healthcare landscape.', - type: 'example', - tag: 'lookml', + type: ResourceType.Example, + tag: ResourceTag.Lookml, link: 'https://github.com/looker-open-source/healthcare_demo', shortenedLink: 'https://bit.ly/3FUokfN', title: 'Healthcare Demo', @@ -168,8 +223,8 @@ export const resources: Array = [ { content: 'This is the official Looker Data Dictionary, fully open source and available as an example.', - type: 'example', - tag: 'extension', + type: ResourceType.Example, + tag: ResourceTag.Extensions, link: 'https://github.com/looker-open-source/app-data-dictionary', shortenedLink: 'https://bit.ly/3vhMlZh', title: 'Data Dictionary Extension', @@ -177,8 +232,8 @@ export const resources: Array = [ { content: 'Thinking of doing a data analysis project for your hack? Browse and explore BigQuery public datasets through the hackathon instance', - type: 'resources', - tag: 'dataset', + type: ResourceType.Resource, + tag: ResourceTag.Datasets, link: 'https://hack.looker.com/dashboards/16', shortenedLink: 'https://bit.ly/3FX72yF', title: 'Public Datasets', @@ -186,16 +241,16 @@ export const resources: Array = [ { content: 'This COVID-19 Block consists of LookML models, pre-built dashboards, and explores. The underlying data is only available in BigQuery.', - type: 'example', - tag: 'lookml', + type: ResourceType.Example, + tag: ResourceTag.Lookml, link: 'https://github.com/looker/covid19/blob/master/readme.md', shortenedLink: 'https://bit.ly/3DPVWd5', title: 'COVID-19 Data Block', }, { content: 'Prebuilt dashboards for immediate access to COVID-19 data.', - type: 'resource', - tag: 'lookml', + type: ResourceType.Resource, + tag: ResourceTag.Lookml, link: 'https://covid19response.cloud.looker.com/embed/dashboards-next/51', shortenedLink: 'https://bit.ly/3n87txG', title: 'COVID-19 Dashboards', @@ -203,16 +258,16 @@ export const resources: Array = [ { content: 'This example demonstrates how to write a Looker extension that needs an access key to run.', - type: 'example', - tag: 'extension', + type: ResourceType.Example, + tag: ResourceTag.Extensions, link: 'https://github.com/looker-open-source/extension-examples/tree/main/react/typescript/access-key-demo', shortenedLink: 'https://bit.ly/3C6UXo8', title: 'Extension Example: Access Key', }, { content: 'An early-stage mockup of a Twitter-style Looker Extension.', - type: 'example', - tag: 'extension', + type: ResourceType.Example, + tag: ResourceTag.Extensions, link: 'https://github.com/bryan-at-looker/looker-feed', shortenedLink: 'https://bit.ly/3jhbyyu', title: 'Looker Feed Extension Mockup', @@ -220,8 +275,8 @@ export const resources: Array = [ { content: 'The official Looker Action Hub repository for all your action requirements and examples.', - type: 'example', - tag: 'action', + type: ResourceType.Example, + tag: ResourceTag.Actions, link: 'https://github.com/looker/actions', shortenedLink: 'https://bit.ly/3pc2vTa', title: 'Action Hub', @@ -229,8 +284,8 @@ export const resources: Array = [ { content: 'Direct link to the directory of all complete Actions in the official action hub.', - type: 'example', - tag: 'action', + type: ResourceType.Example, + tag: ResourceTag.Actions, link: 'https://github.com/looker/actions/tree/master/src/actions', shortenedLink: 'https://bit.ly/3vrwzeM', title: 'Actions Examples', @@ -238,8 +293,8 @@ export const resources: Array = [ { content: 'Mock ActionHub for local or serverless (Google Cloud Functions) use.', - type: 'example', - tag: 'action', + type: ResourceType.Example, + tag: ResourceTag.Actions, link: 'https://github.com/fabio-looker/sample-cloud-function-action', shortenedLink: 'https://bit.ly/3lSdCOU', title: 'Mock ActionHub', @@ -247,8 +302,8 @@ export const resources: Array = [ { content: 'Learn how to write an action that exports the results of a Looker Query to BigQuery.', - type: 'tutorial', - tag: 'action', + type: ResourceType.Tutorial, + tag: ResourceTag.Actions, link: 'https://discourse.looker.com/t/export-the-results-of-a-looker-query-to-bigquery/9720', shortenedLink: 'https://bit.ly/3jeJICU', title: 'BigQuery Writeback Action', @@ -256,32 +311,32 @@ export const resources: Array = [ { content: 'The official repository of Looker Custom Visualizations API and examples', - type: 'example', - tag: 'viz', + type: ResourceType.Example, + tag: ResourceTag.CustomViz, link: 'https://github.com/looker/custom_visualizations_v2', shortenedLink: 'https://bit.ly/3FYL2ni', title: 'Custom Visualizations v2', }, { content: 'Direct link to Looker Custom Visualization examples', - type: 'example', - tag: 'viz', + type: ResourceType.Example, + tag: ResourceTag.CustomViz, link: 'https://github.com/looker/custom_visualizations_v2/tree/master/src/examples', shortenedLink: 'https://bit.ly/3n3LRCE', title: 'Custom Viz Examples', }, { content: 'A Web IDE to help develop Looker Custom Visualizations.', - type: 'resource', - tag: 'viz', + type: ResourceType.Resource, + tag: ResourceTag.CustomViz, link: 'https://lookervisbuilder.com/', shortenedLink: 'https://bit.ly/3G2iHfw', title: 'Custom Viz Builder', }, { content: 'A tutorial to build a custom viz development environment', - type: 'tutorial', - tag: 'viz', + type: ResourceType.Tutorial, + tag: ResourceTag.CustomViz, link: 'https://discourse.looker.com/t/creating-a-development-environment-for-custom-visualizations/8470', shortenedLink: 'https://bit.ly/3DRnZc2', title: 'Custom Viz Dev Environment Setup', @@ -289,16 +344,16 @@ export const resources: Array = [ { content: 'An old example custom viz development environment developed by Headset. (may be out of date)', - type: 'example', - tag: 'viz', + type: ResourceType.Example, + tag: ResourceTag.CustomViz, link: 'https://github.com/Headset/looker-environment', shortenedLink: 'https://bit.ly/30EsLLL', - title: 'Custom Vis Dev Envronment Example', + title: 'Custom Vis Dev Environment Example', }, { content: 'An older demo of Lookers custom viz capabilities', - type: 'resource', - tag: 'viz', + type: ResourceType.Resource, + tag: ResourceTag.CustomViz, link: 'https://youtu.be/ixwWGKyG3wA', shortenedLink: 'https://bit.ly/2Z0MtjU', title: 'Custom Viz Demo Video', @@ -306,8 +361,8 @@ export const resources: Array = [ { content: 'This Google Apps Script uses Looker API to load Looks, get data dictionaries, etc.', - type: 'example', - tag: 'api', + type: ResourceType.Example, + tag: ResourceTag.API, link: 'https://github.com/brechtv/looker_google_sheets', shortenedLink: 'https://bit.ly/3BUdkg1', title: 'Looker API for Google Sheets', @@ -315,8 +370,8 @@ export const resources: Array = [ { content: 'This tool helps you troubleshoot SSO embed URLs generated by your scripts.', - type: 'resource', - tag: 'embed', + type: ResourceType.Resource, + tag: ResourceTag.Embed, link: 'https://fabio-looker.github.io/looker_sso_tool/', shortenedLink: 'https://bit.ly/30IY8F7', title: 'SSO Embed Tool', @@ -324,32 +379,32 @@ export const resources: Array = [ { content: 'The source code for the SSO embed tool for you to extend or run locally.', - type: 'example', - tag: 'embed', + type: ResourceType.Example, + tag: ResourceTag.Embed, link: 'https://github.com/fabio-looker/looker_sso_tool', shortenedLink: 'https://bit.ly/3n3MDzj', title: 'SSO Embed Tool Source', }, { content: 'Vim syntax for LookML. (may be out of date)', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/thalesmello/lkml.vim', shortenedLink: 'https://bit.ly/3G2qJFe', title: 'LookML Vim Syntax', }, { content: 'VSCode syntax for LookML. (may be out of date)', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/Ladvien/vscode-looker', shortenedLink: 'https://bit.ly/3lShYFK', title: 'LookML VSCode Syntax', }, { content: 'An automated EAV builder for EAV schemas.', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/fabio-looker/eav-builder', shortenedLink: 'https://bit.ly/2Xobcy8', title: 'EAV Builder', @@ -357,8 +412,8 @@ export const resources: Array = [ { content: 'Learn how to set up your Looker instance to poll and make changes to your LookML model with an AWS Lambda function.', - type: 'tutorial', - tag: 'devtool', + type: ResourceType.Tutorial, + tag: ResourceTag.Devtool, link: 'https://discourse.looker.com/t/automating-frequently-changing-schemas-with-aws-lambda/10196', shortenedLink: 'https://bit.ly/3lTyoOo', title: 'Automate Schema Changes', @@ -366,8 +421,8 @@ export const resources: Array = [ { content: 'Developed by WW, this repository contains tools to handle best practices with developing LookML files.', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/ww-tech/lookml-tools', shortenedLink: 'https://bit.ly/3vo5r01', title: 'LookML Tools', @@ -375,8 +430,8 @@ export const resources: Array = [ { content: 'This script was designed for data tables with JSON objects. It creates a LookML view file with a dimension for each JSON object field. (may be out of date)', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/leighajarett/JSON_to_LookML', shortenedLink: 'https://bit.ly/3lR2xhe', title: 'JSON To LookML', @@ -384,40 +439,40 @@ export const resources: Array = [ { content: 'A tool to persist descriptions from your dbt project to your lookml project.', - type: 'example', - tag: 'devtool', + type: ResourceType.Example, + tag: ResourceTag.Devtool, link: 'https://github.com/fishtown-analytics/dbtdocs-to-lookml', shortenedLink: 'https://bit.ly/2Z81Szd', title: 'DBTdocs To LookML', }, { content: 'A LookML parser and serializer implemented in Python.', - type: 'resource', - tag: 'devtool', + type: ResourceType.Resource, + tag: ResourceTag.Devtool, link: 'https://github.com/joshtemple/lkml', shortenedLink: 'https://bit.ly/3lTzc5S', title: 'LookML parser', }, { content: "A comprehensive demo of Looker's embedding capabilities", - type: 'example', - tag: 'embed', + type: ResourceType.Example, + tag: ResourceTag.Embed, link: 'https://atomfashion.io/', shortenedLink: 'https://bit.ly/3BUogKR', title: 'Embed Demo', }, { content: 'An awesome list of awesome Looker projects.', - type: 'resource', - tag: 'other', + type: ResourceType.Resource, + tag: ResourceTag.Other, link: 'https://gitlab.com/alison985/awesome-looker/-/tree/main', shortenedLink: 'https://bit.ly/3DSZzPw', title: 'Awesome Looker Projects', }, { content: 'Looker 3.0 SDK for R', - type: 'Example', - tag: 'api', + type: ResourceType.Example, + tag: ResourceTag.API, link: 'https://github.com/looker-open-source/lookr', shortenedLink: 'https://bit.ly/3vfJwIr', title: 'Looker R SDK 3.0', From 0ec156a210e7aa1e23bc33bbc3555ba90e166332 Mon Sep 17 00:00:00 2001 From: Lan <53841803+lanlooker@users.noreply.github.com> Date: Tue, 2 Nov 2021 14:35:55 +0900 Subject: [PATCH 2/3] feat: Python SDK Example: Gsheet / Cloud Functions / Looker SDK integration (#874) completed integration Gsheet / Cloud Functions / Looker Python SDK for use provision --- .../cloud-function-user-provision/README.md | 19 ++--- .../cloud-function-user-provision/main.py | 69 ++++++++++++++++--- .../requirements.txt | 4 +- 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/examples/python/cloud-function-user-provision/README.md b/examples/python/cloud-function-user-provision/README.md index 56ede8da8..e42a65c30 100644 --- a/examples/python/cloud-function-user-provision/README.md +++ b/examples/python/cloud-function-user-provision/README.md @@ -2,13 +2,13 @@ This repository contains a [Google Cloud Function](https://cloud.google.com/functions) that leverages Looker Python SDK. The repository can be used as a starter template to build serverless microservices that interact with Looker through the following workflow: -1. Send a POST request to trigger an HTTP-based Cloud Function +1. Trigger an HTTP-based Cloud Function 2. Initialize the Looker Python SDK 3. Call Looker SDK methods and build custom logic to manage users, content, queries, etc. -In this repository, the `main.py` file takes an email address as an input and checks if this email has been registered with an existing Looker user. If an exisiting user is found, an email to reset the password will be sent to the user. Otherwise, a new user will be created, and a setup email will be sent. +In this repository, the `main.py` file takes an email address as an input and checks if this email has been registered with an existing Looker user. If a current user is found, an email to reset the password will be sent to the user. Otherwise, a new user will be created, and a setup email will be sent. -For more use cases and Python examples, check out [Looker's Python SDK examples](https://github.com/looker-open-source/sdk-codegen/tree/main/examples/python). +Check out [Looker's Python SDK examples](https://github.com/looker-open-source/sdk-codegen/tree/main/examples/python) for more code examples. ## Demo @@ -16,23 +16,24 @@ For more use cases and Python examples, check out [Looker's Python SDK examples] Demo

- ## Setup -The following steps assume deployment using Google Cloud UI Console. Check out ["Your First Function: Python"](https://cloud.google.com/functions/docs/first-python) for steps to deploy using the `gcloud` command line tool +The following steps assume deployment using Google Cloud UI Console. Check out ["Your First Function: Python"](https://cloud.google.com/functions/docs/first-python) for steps to deploy using the `gcloud` command-line tool 1. Obtain a [Looker API3 Key](https://docs.looker.com/admin-options/settings/users#api3_keys) 2. Follow the steps [provided here](https://cloud.google.com/functions/docs/quickstart-python) to create a new Google Cloud Function -3. Configure runtime environment variables using the Cloud Function UI: Edit > Configuration > Runtime, build, connections and security settings > Runtime environment variables. Alternatively, environtment variables can be configured through the `os` module or a `.ini`. Check out [Configuring Looker Python SDK](https://github.com/looker-open-source/sdk-codegen/tree/main/python#configuring-the-sdk) to learn more +3. If using Google Sheet: Grant "Viewer" permission to the email address associated with the "Runtime service account" in Cloud Functions. The recommendation is to use the [Default App Engine Service Account](https://cloud.google.com/appengine/docs/standard/python/service-account) and share its email (`YOUR_PROJECT_ID@appspot.gserviceaccount.com`) to the Google Sheet. + +4. Configure runtime environment variables using the Cloud Function UI: Edit > Configuration > Runtime, build, connections and security settings > Runtime environment variables. Alternatively, environment variables can be configured through the `os` module or a `.ini` file. Check [Configuring Looker Python SDK](https://github.com/looker-open-source/sdk-codegen/tree/main/python#configuring-the-sdk) for more information

Setting environmental variables in Cloud Function UI

-4. Copy and paste the contents of `main.py` in this repository into `main.py` file once inside Cloud Function's inline editor. Change the "Entry point" in the top right to `main`. `main.py` is executed once the function is triggered +5. Copy and paste the contents of `main.py` in this repository into the `main.py` file once inside Cloud Function's inline editor. Change the "Entry point" in the top right to the main function. `main.py` is executed once the function is triggered -5. Copy and paste the contents of `requirements.txt` in this repository to the `requirements.txt` file once inside Cloud Function's inline editor. This file is used to install neccessary libraries to execute the function +6. Copy and paste the contents of `requirements.txt` in this repository to the `requirements.txt` file once inside Cloud Function's inline editor. This file is used to install necessary libraries to execute the function -6. Deploy and test the function. Check out [this article](https://cloud.google.com/functions/docs/quickstart-python#test_the_function) for instruction +7. Deploy and test the function. Check out [this article](https://cloud.google.com/functions/docs/quickstart-python#test_the_function) for instruction diff --git a/examples/python/cloud-function-user-provision/main.py b/examples/python/cloud-function-user-provision/main.py index 9f78da559..87060c2ce 100644 --- a/examples/python/cloud-function-user-provision/main.py +++ b/examples/python/cloud-function-user-provision/main.py @@ -1,16 +1,29 @@ -"""This Cloud Function leverages Looker Python SDK to manage user provision. The -`main` function is used as the entry point to the code. It takes an email address -as an input through a POST request, then checks if this email has been associated -with an existing Looker user. If an exisiting user is found, then an email to -reset password will be sent. Otherwise, a new user will be created, and a setup email -will be sent. +"""This Cloud Function leverages Looker Python SDK to manage user provision. +It takes an email address as an input, then checks if this email has been +associated with an existing Looker user. If a current user is found, then an +email to reset the password will be sent. Otherwise, a new user will be created, +and a setup email will be sent. + +The `main` function is triggered through an HTTP request. Two example approaches +are provided below: + main(request): take a POST request in form of {"email":"test@test.com"}, + and read the email value from the request body + main_gsheet(request): take a GET request and read the email value from a cell + inside an existing Google sheet. HTTP Cloud Functions: https://cloud.google.com/functions/docs/writing/http#sample_usage""" +# If not using Google Sheet, removing Google modules here and in `requirements.txt` +from googleapiclient.discovery import build +import google.auth + import looker_sdk sdk = looker_sdk.init40() +# [START main(request)] def main(request): + """Take email from JSON body of a POST request, and use the email value + as an input for looker_user_provision() function""" try: request_json = request.get_json() email = request_json["email"] @@ -18,7 +31,46 @@ def main(request): return result except: return 'Please provide JSON in the format of {"email":"test@test.com"}' +# [END main(request)] + +# [START main_gsheet(request)] +def main_gsheet(request): + """Take email from a cell inside an existing Google Sheet""" + try: + email = get_email_from_sheet() + result = looker_user_provision(email=email) + return result + except: + return 'An error occurred.' + +def get_email_from_sheet(): + """ Authenticate to an existing Google Sheet using the default runtime + service account and extract the email address from a cell inside the sheet. + + Refer to Google Sheet API Python Quickstart for details: + https://developers.google.com/sheets/api/quickstart/python + """ + # Get the key of an existing Google Sheet from the URL. + # Example: https://docs.google.com/spreadsheets/d/[KEY HERE]/edit#gid=111 + SAMPLE_SPREADSHEET_ID = "foo" + + # Google Sheet Range: https://developers.google.com/sheets/api/samples/reading + SAMPLE_RANGE_NAME = "Sheet1!A:A" + + creds, _proj_id = google.auth.default() + service = build("sheets", "v4", credentials=creds) + sheet = service.spreadsheets() + result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID, + range=SAMPLE_RANGE_NAME).execute() + # `values` will be a list of lists (i.e.: [['email1'], ['email2']]) + # and we can access value 'email' using index + values = result.get('values', []) + email = values[0][0] + return email +# [END main_gsheet(request)] + +# [START looker_user_provision] def looker_user_provision(email): user_id = search_users_by_email(email=email) if user_id is not None: @@ -49,7 +101,7 @@ def create_users(email): models_dir_validated=False ) ) - + # Create email credentials for the new user sdk.create_user_credentials_email( user_id=new_user.id, @@ -57,7 +109,8 @@ def create_users(email): email=email, forced_password_reset_at_next_login=False )) - + # Send a welcome/setup email sdk.send_user_credentials_email_password_reset(user_id=new_user["id"]) +# [END looker_user_provision] diff --git a/examples/python/cloud-function-user-provision/requirements.txt b/examples/python/cloud-function-user-provision/requirements.txt index 69c05299c..49a941dba 100644 --- a/examples/python/cloud-function-user-provision/requirements.txt +++ b/examples/python/cloud-function-user-provision/requirements.txt @@ -1,4 +1,6 @@ # Function dependencies, for example: # package>=version looker_sdk -requests +google-api-python-client==1.7.9 +google-auth-httplib2==0.0.3 +google-auth-oauthlib==0.4.0 From 16528bc245f6e447be3d862a4a0115a50aa1a16a Mon Sep 17 00:00:00 2001 From: Lan <53841803+lanlooker@users.noreply.github.com> Date: Wed, 3 Nov 2021 14:57:30 +0900 Subject: [PATCH 3/3] feat: Add JPN agenda.ts and add yarn command in readme.md for hackathon app (#889) Screenshot: https://screenshot.googleplex.com/BKz4dhbhYMoEnFa.png Fixing: b/200085421 --- packages/hackathon/README.md | 6 ++ .../hackathon/src/scenes/HomeScene/agenda.ts | 76 +++++++++++-------- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/packages/hackathon/README.md b/packages/hackathon/README.md index 008563ff8..9eaa4955c 100644 --- a/packages/hackathon/README.md +++ b/packages/hackathon/README.md @@ -59,6 +59,12 @@ application: hackathon_app { Remember to add a model to the project that has a valid connection. +## Specific steps to `yarn` +1. run `yarn install` in sdk-codegen +2. run `yarn build` in sdk-codgen +3. run `yarn start` in examples/access_token_server +4. run `yarn dev:hack` in sdk-codegen to start the development server and connect to the extension + ## Hackathon Personas The active user's persona determines the availability of navigation options and data actions. diff --git a/packages/hackathon/src/scenes/HomeScene/agenda.ts b/packages/hackathon/src/scenes/HomeScene/agenda.ts index bebf5fb8a..68b6204e7 100644 --- a/packages/hackathon/src/scenes/HomeScene/agenda.ts +++ b/packages/hackathon/src/scenes/HomeScene/agenda.ts @@ -48,69 +48,80 @@ export const agenda = [ start: later(day1, -4), // Nov 9th // NOTE: if stop values are not defined, they default to the start of the next agenda item stop: later(day1, -3.5), // Nov 9th - description: { en: '## Welcome APAC', ja_JP: '## 日本 Welcome APAC' }, + description: { + en: '## Welcome APAC', + ja_JP: '## 開会 APAC(ご案内・注意事項など)', + }, }, { start: later(day1, 5), // Nov 10th stop: later(day1, 5.5), // Nov 10th - description: { en: '## Welcome EMEA', ja_JP: '## 日本 Welcome EMEA' }, + description: { + en: '## Welcome EMEA', + ja_JP: '## 開会 EMEA(ご案内・注意事項など)', + }, }, { start: later(day1, 10), stop: later(day1, 10.5), - description: { en: '## Welcome AMER', ja_JP: '## 日本 Welcome AMER' }, + description: { + en: '## Welcome AMER', + ja_JP: '## 開会 AMER(ご案内・注意事項など)', + }, }, { start: later(day1, -3.5), // Nov 9th stop: later(day1, -2), description: { - en: `_Supported hacking hours_ + en: `_Supported hacking hours (ENG/JPN)_ -Use [slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F) to ask Looker staff for assistance +Use [Slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F) to ask Looker staff for assistance See [looker-open-source](https://github.com/looker-open-source) for cool stuff!`, - ja_JP: `_日本 Supported hacking hours_ + ja_JP: `_サポート時間 (対応言語:英・日)_ + +[Slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F)にて日本語での技術サポートを実施しております -Use [slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F) to ask Looker staff for assistance`, +活用事例やコードサンプルについて、[looker-open-source](https://github.com/looker-open-source)でご参考いただけます`, }, }, { start: later(day1, 1.5), // Nov 10th stop: later(day1, 3.5), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG/JPN)_', + ja_JP: '_サポート時間 (対応言語:英・日)_', }, }, { start: later(day1, 5), // Nov 10th stop: later(day1, 7), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG)_', + ja_JP: '_サポート時間 (対応言語:英)_', }, }, { start: later(day1, 10.5), stop: later(day1, 13), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG)_', + ja_JP: '_サポート時間 (対応言語:英)_', }, }, { start: later(day1, 14.5), stop: later(day1, 16), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG/JPN)_', + ja_JP: '_サポート時間 (対応言語:英・日)_', }, }, { start: later(day1, 19), description: { en: '**Hack@Night session**', - ja_JP: '**日本 Hack@Night Session**', + ja_JP: '**Hack@Night Session**', // }, }, { @@ -118,7 +129,7 @@ Use [slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F) to ask Looker st stop: later(day2, -3.5), description: { en: '_Roundtable Check-In APAC_', - ja_JP: '_日本 Roundtable Check-In APAC_', + ja_JP: '_ラウンドテーブル Check-in APAC_', }, }, { @@ -126,7 +137,7 @@ Use [slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F) to ask Looker st stop: later(day2, 5.5), description: { en: '_Roundtable Check-In EMEA_', - ja_JP: '_日本 Roundtable Check-In EMEA_', + ja_JP: '_ラウンドテーブル Check-in EMEA_', }, }, { @@ -134,60 +145,63 @@ Use [slack](https://app.slack.com/client/T0A4R5X0F/C02ELGL644F) to ask Looker st stop: later(day2, 10.5), description: { en: '_Roundtable Check-In AMER_', - ja_JP: '_日本 Roundtable Check-In AMER_', + ja_JP: '_ラウンドテーブル Check-in AMER_', }, }, { start: later(day2, -3.5), stop: later(day2, -2), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG/JPN)_', + ja_JP: '_サポート時間 (対応言語:英・日)_', }, }, { start: later(day2, 1.5), stop: later(day2, 3.5), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG/JPN)_', + ja_JP: '_サポート時間 (対応言語:英・日)_', }, }, { start: later(day2, 5), stop: later(day2, 7), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG)_', + ja_JP: '_サポート時間 (対応言語:英)_', }, }, { start: later(day2, 10.5), stop: later(day2, 13), description: { - en: '_Supported hacking hours_', - ja_JP: '_日本 Supported hacking hours_', + en: '_Supported hacking hours (ENG)_', + ja_JP: '_サポート時間 (対応言語:英・日)_', }, }, { start: later(day2, 13), description: { en: `**Final submissions due**`, - ja_JP: '**日本 Final submissions due**', + ja_JP: '**プロジェクトの提出締め切り**', }, }, { start: later(day2, 14), description: { - en: `## Winner announcements + Demos`, - ja_JP: '## 日本 Winner announcements + Demos', + en: `## Winner announcements & Demos`, + ja_JP: '## 優秀賞発表 & デモ', }, }, // NOTE: All other stop values can default. The final stop value is required. { start: later(day2, 15), stop: later(day2, 17), - description: { en: `## Hacky Hour`, ja_JP: '## 日本 Hacky Hour' }, + description: { + en: `## Hacky Hour (Social Event)`, + ja_JP: '## Hacky Hour (懇親会)', + }, }, ]