Blog

  • supabase-graphql-example

    Supabase GraphQL Example

    A basic HackerNews-like clone where posts can be submitted with url links and then up and down voted.

    graphql-hn

    Showcase

    Backend

    • CRUD (Query + Mutation Operations)
    • Cursor Based Pagination
    • Authorization / Postgres Row Level Security
    • Supabase – Create a backend in less than 2 minutes. Start your project with a Postgres Database, Authentication, instant APIs, Realtime subscriptions and Storage.
    • pg_graphql – A native PostgreSQL extension adding GraphQL support. The extension keeps schema generation, query parsing, and resolvers all neatly contained on your database server requiring no external services.
    • Postgres Triggers and Postgres Functions – When votes are in, use triggers to invoke a Postgres function that calculates a post score to rank the feed
    • Postgres Enumerated Types – Enums help defined the direction of a vote: UP or DOWN.

    Frontend

    • Next.js – React Framework
    • TypeScript – TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.
    • graphql-code-generator – Generate code from your GraphQL schema and operations with a simple CLI
    • gql-tag-operations-preset – This code gen preset generates typings for your inline gql function usages, without having to manually specify import statements for the documents
    • urql – A highly customizable and versatile GraphQL client
    • Gravatar – Default avatar profile images from Gravatar

    Functionality

    • Registration
    • Get a ranked feed of posts
    • Create Post
    • Delete Post
    • Create Comment
    • Delete Comment
    • Upvote/Downvote Post
    • View Profile (Account)
    • View Profile (Public)
    • Pagination (Posts, Comments)

    QuickStart

    Setup env vars

    Install dependencies, GraphQL codegen, run app

    yarn
    yarn codegen
    yarn workspace app dev

    Deploy to Vercel

    Provide the following settings to deploy a production build to Vercel:

    • BUILD COMMAND: yarn codegen && yarn workspace app build
    • OUTPUT DIRECTORY: ./app/.next
    • INSTALL COMMAND: yarn
    • DEVELOPMENT COMMAND: yarn codegen && yarn workspace app dev --port $PORT

    Development

    1. Fetch latest GraphQL Schema
    yarn codegen:fetch
    1. Generate Types and Watch for Changes
    yarn codegen:watch
    1. Run server
    yarn workspace app dev

    Synchronize the GraphQL schema

    Note: You need to call select graphql.rebuild_schema() manually to synchronize the GraphQL schema with the SQL schema after altering the SQL schema.

    Manage Schema with dbmate

    1. brew install dbmate
    2. Setup .env with DATABASE_URL
    3. Dump Schema
    cd data
    dbmate dump
    

    Note: If pgdump fails due to row locks, a workaround is to grant the postgres role superuser permissions with ALTER USER postgres WITH SUPERUSER. After dumping the schema, you should reset the permissions using ALTER USER postgres WITH NOSUPERUSER. You can run these statements in the Superbase Dashboard SQL Editors.

    Schema (Public)

    • Profile belongs to auth.users

    • Post

    • Comment belongs to Post and Profile

    • Vote belongs to Post (can have a direction of UP/DOWN)

    • direction enum is “UP” or “DOWN”

    Constraints

    • Post url is unique
    • Vote is unique per Profile, Post (ie, you cannot vote more than once — up or down)

    See: ./data/db/schema.sql

    Note: The schema includes the entire Supabase schema with auth, storage, functions, etc.

    Seed Data

    A data file for all Supabase Blog posts from the RSS feed can be found in ./data/seed/blog_posts.csv and can be loaded. Another file for comments is available as well.

    Note: Assumes a known profileId currently.

    GraphQL Schema

    See: ./graphql/schema/schema.graphql

    Example Query

    See: ./graphql/queries/

    Use: https://mvrfvzcivgabojxddwtk.supabase.co/graphql/v1

    Note: Needs headers

    
    Content-Type: application/json
    apiKey: <supabase_anon_key>
    
    

    GraphiQL

    GraphiQL is an in-browser IDE for writing, validating, and testing GraphQL queries.

    Visit http://localhost:3000/api/graphiql for the Yoga GraphiQL Playground where you can experiment with queries and mutations.

    Note: Needs headers

    
    Content-Type: application/json
    apiKey: <supabase_anon_key>
    
    

    Note: In order for the RLS policies authenticate you, you have to pass an authorization header (see example):

    authorization: Bearer <access_token>
    
    

    Ranked Feed

    query {
      rankedFeed: postCollection(orderBy: [{ voteRank: AscNullsFirst }]) {
        edges {
          post: node {
            id
            title
            url
            upVoteTotal
            downVoteTotal
            voteTotal
            voteDelta
            score
            voteRank
            comments: commentCollection {
              edges {
                node {
                  id
                  message
                  profile {
                    id
                    username
                    avatarUrl
                  }
                }
              }
              commentCount: totalCount
            }
          }
        }
      }
    }

    Row Level Security Matrix (RLS)

    You can query all policies via: select * from pg_policies.

    See: Row Level Security Matrix (RLS)

    Read More

    Troubleshooting

    1. dbmate can create schema_migrations tables in schemas. To make sure they are not included in your GraphQL Schema:
    revoke select on table public.schema_migrations from anon, authenticated;
    1. To enable inflection
    comment on schema public is e'@graphql({"inflect_names": true})';
    1. Try the heartbeat to see if pg_graphql can access requests
    select graphql_public.graphql(
    	null,
    	$$ { heartbeat }$$
    )
    

    Returns:

    { "data": { "heartbeat": "2022-07-28T17:07:07.90513" } }
    1. Is the public_graphql schema not exposed properly?

    Getting an 406 status or error message like:

    {
        "message": "The schema must be one of the following: public, storage"
    }
    

    Then be sure to expose the graphql_public in Settings > Project settings > API.

    The schema to expose in your API. Tables, views and stored procedures in this schema will get API endpoints.

    image

    Visit original content creator repository https://github.com/supabase-community/supabase-graphql-example
  • python-sdk

    Thepeer python-sdk

    example workflow PyPI - Downloads PyPI - License PyPI Codecov

    Thepeer’s official python sdk for developers to use in their python projects.

    • To start using this sdk, create an account at https://thepeer.co/ if you haven’t already.
    • You can then retrieve your API keys from your dashboard

    Installation

    To install this sdk, run the command:

    pip install pythepeer

    Usage

    Instantiate Thepeer class like so:

    from thepeer import Thepeer
    
    # create an instance of Thepeer class
    
    thepeer_instance = Thepeer("YOUR_API_KEY_HERE")

    Available methods exposed by the sdk

    Note:

    Indexing a user

    This method describes how to index a user on your account (this is usually the first step before using other methods)

    test = thepeer_instance.index_user("Osagie Iyayi", "iyayiemmanuel1@gmail.com", "iyayiemmanuel1@gmail.com")

    Parameters supported

    Parameters Data type Required Description
    name string true The name of user to be indexed.
    identifier string true the identifier of the account(either email or username).
    email string true the email of the user

    Validating a HMAC signature

    This method validates incoming an hmac signature with the payload and credentials that was passed with it

    Pro Tip: it is used to verify that an incoming webhook event/response is coming from thepeer’s servers

    test = thepeer_instance.validate_signature(data,signature)

    Parameters supported

    Parameters Data type Required Description
    data dictionary true the payload containing the data to be authenticated
    signature string true The HMAC signature

    Get an indexed user

    This method gets the information of an indexed user

    test = thepeer_instance.view_user("3bbb0fbf-82fa-48a0-80eb-d2c0338fe7dd")

    Parameters supported

    Parameters Data type Required Description
    reference string true the unique reference returned when the user was indexed

    Get all indexed users

    This method returns all indexed users for a specific account

    test = thepeer_instance.all_users(1,15)

    Parameters supported

    Parameters Data type Required Description
    page integer false the first page displaying all the indexed users. defaults to 1
    per_page integer false The number of users to display per page. defaults to 15

    Update an indexed user

    This method helps to update the details of an indexed user

    test = thepeer_instance.update_user(reference,**data)

    Parameters supported

    Parameters Data type Required Description
    reference string true the unique reference returned when the user was indexed
    data Any true A keyword argument which contains on or more of the indexed user's email, name or identifier

    Sample

    test = thepeer_instance.update_user("3bbb0fbf-82fa-48a0-80eb-d2c0338fe7dd", identifier="dwave101@yahoo.com",
        name="Edmond Kirsch",
        email="dwave101@gmail.com")

    Remove an indexed user

    This method helps to remove the details of an indexed user from a specific account

    test = thepeer_instance.delete_user("3bbb0fbf-82fa-48a0-80eb-d2c0338fe7dd")

    Parameters supported

    Parameters Data type Required Description
    reference string true the unique reference returned when the user was indexed

    Get Businesses

    This method returns businesses based on the API they integrated.

    test = thepeer_instance.get_businesses("checkout")

    Parameters supported

    Parameters Data type Required Description
    channel string true The specific API to return businesses of. supported values are send, checkout, and direct_charge

    Generate a Checkout

    This method allows you to generate a link for your customer to make a one-time payment with

    test = thepeer_instance.generate_checkout({
        "amount": 1000000,
        "currency": "NGN",
        "redirect_url": "https://esportfolio.netlify.app",
        "email": "jevede6918@muzitp.com",
        "meta":{
            "name": "Eddie Kirsch",
            "identifier": "eddiekirsch",
        }
    })

    Parameters required

    Parameters Data type Required Description
    redirect_url string false The url Thepeer should redirect to after the customer completes payment.
    amount integer true The amount you are debiting the customer. This should be in kobo. The minimum value is 10000
    email string true The customer’s email address
    currency string true The currency the transaction should be carried out in. The supported value is NGN.
    meta dictionary false An object containing additional attributes you will like to have in your transaction response.

    Get user links

    This method returns all linked accounts of a user, the user’s account details, as well as the business the account is on.

    test = thepeer_instance.get_user_links("3bbb0fbf-82fa-48a0-80eb-d2c0338fe7dd")

    Parameters required

    Parameters Data type Required Description
    reference string true the unique reference returned when the user was indexed

    Get single link (linked account)

    This method returns a user’s linked account’s details.

    test = thepeer_instance.get_single_link("da14a90c-61c2-4cf7-a837-e3112a2d0c3d")

    Parameters required

    Parameters Data type Required Description
    link_id string true The link’s identifier

    Charge a link

    This method allows a business to charge a user via their linked account

    test = thepeer_instance.charge_link(link_id, amount, remark, currency)

    Parameters required

    Parameters Data type Required Description
    link_id string true The link’s identifier
    amount integer true the amount of the whole transaction
    remark string true short detail about the transaction
    currency string false The denomination medium of paying (either one of NGN and USD). defaults to NGN

    Authorize charge

    This method allows a business to authorize a direct charge request made by a user

    test = thepeer_instance.authorize_charge(charge_reference, event)

    Parameters required

    Parameters Data type Required Description
    charge_reference string true the reference associated to a pending charge request
    event string true the type of webhook event

    Pro Tip: the various types of webhook events are available here

    Get transaction detail

    This method gets the details of a transaction

    test = thepeer_instance.get_transaction_detail("eda58ee3-4f2c-4aa4-9da7-10a2b8ced453")

    Parameters required

    Parameters Data type Required Description
    transaction_id string true the unique transaction identifier

    Refund transaction

    This method allows a business to refund a transaction back to the user for obvious reasons

    test = thepeer_instance.refund_transaction("28e52edf-16d9-4921-8a54-ef34d7029707", "possible threat actor"):

    Parameters required

    Parameters Data type Required Description
    transaction_id string true the unique transaction identifier
    reason string false a short sentence explaining reasons for the refund
    Visit original content creator repository https://github.com/thepeerstack/python-sdk
  • github-history

    demo status deploy test

    Github History App

    Next.js Typescript Tailwind CSS React Github API Date-fns React-Hot-Toast Vercel Node.js NestJS Swagger Jest

    This app will show you a list of all commits of a github repository. You can search by username, select the repository and branch you want to search and it will show you a list of all commits respectively.

    Demo · Report issue · Suggest something

    Table of Contents

    Features

    • Show a list of all repositories of a Github user.
    • Show a list of all branches of a Github repository.
    • Show a list of all commits of a Github repository.
    • Use Github API to get data of commits, repositories, branches, etc.
    • Backend was developed with NestJS to create a REST API.
    • REST API was documented with Swagger.
    • Frontend was developed with NextJS and consume data from backend.
    • Frontend use Tailwind, a custom css loader and a dark theme.
    • Frontend deployed with Vercel.
    • Backend deployed with Railway.
    • Typescript was used in backend and frontend.
    • Use React-Hot-Toast to show notification messages.

    Tech Stack

    Getting Started

    This is a mono repository project that is divided in two parts, the backend and the frontend. The backend is developed with NestJS and the frontend with NextJS.

    Cloning the repository

    Open a command prompt, and copy the following command, you need to have installed git.

    git clone https://github.com/wrujel/github-history.git
    

    Press Enter to create your local clone.

    Cloning into 'github-history'...
    remote: Enumerating objects: 138, done.
    remote: Counting objects: 100% (138/138), done.
    remote: Compressing objects: 100% (84/84), done.
    remote: Total 138 (delta 54), reused 130 (delta 50), pack-reused 0 eceiving objects:  83%
    Receiving objects: 100% (138/138), 230.03 KiB | 747.00 KiB/s, done.
    Resolving deltas: 100% (54/54), done.
    

    Setup Backend

    Type the following command:

    cd github-history/backend
    

    Installation

    Install all dependencies, you need to have installed nodejs version 16.15.0.

    npm install

    Running server

    Commands to run backend server, use start:dev if you want to automatically reset server after saving changes.

    # development
    npm run start
    
    # watch mode
    npm run start:dev

    The server will start running.

    [Nest] LOG [NestApplication] Nest application successfully started 
    Server running on port 8080
    

    Open your browser and copy following url to see result:

    http://localhost:8080/
    

    Documentation

    You can visit following path to see documentation generated with swagger:

    http://localhost:8080/api/docs
    

    Test

    Commands to test server.

    # unit tests
    npm run test
    
    # e2e tests
    npm run test:e2e

    Setup Frontend

    In the root of project, type the following command:

    cd github-history/frontend
    

    Installation

    Install all dependencies, you need to have installed nodejs version 16.15.0.

    npm install

    Running client

    Run the development server:

    npm run dev
    # or
    yarn dev

    Open http://localhost:3000 with your browser to see the result.

    Try Demo

    The project is deployed with Vercel. Open this link with your browser to see demo:

    demo

    Visit original content creator repository https://github.com/wrujel/github-history
  • github-history

    demo status deploy test

    Github History App

    Next.js Typescript Tailwind CSS React Github API Date-fns React-Hot-Toast Vercel Node.js NestJS Swagger Jest

    This app will show you a list of all commits of a github repository. You can search by username, select the repository and branch you want to search and it will show you a list of all commits respectively.

    Demo · Report issue · Suggest something

    Table of Contents

    Features

    • Show a list of all repositories of a Github user.
    • Show a list of all branches of a Github repository.
    • Show a list of all commits of a Github repository.
    • Use Github API to get data of commits, repositories, branches, etc.
    • Backend was developed with NestJS to create a REST API.
    • REST API was documented with Swagger.
    • Frontend was developed with NextJS and consume data from backend.
    • Frontend use Tailwind, a custom css loader and a dark theme.
    • Frontend deployed with Vercel.
    • Backend deployed with Railway.
    • Typescript was used in backend and frontend.
    • Use React-Hot-Toast to show notification messages.

    Tech Stack

    Getting Started

    This is a mono repository project that is divided in two parts, the backend and the frontend. The backend is developed with NestJS and the frontend with NextJS.

    Cloning the repository

    Open a command prompt, and copy the following command, you need to have installed git.

    git clone https://github.com/wrujel/github-history.git
    

    Press Enter to create your local clone.

    Cloning into 'github-history'...
    remote: Enumerating objects: 138, done.
    remote: Counting objects: 100% (138/138), done.
    remote: Compressing objects: 100% (84/84), done.
    remote: Total 138 (delta 54), reused 130 (delta 50), pack-reused 0 eceiving objects:  83%
    Receiving objects: 100% (138/138), 230.03 KiB | 747.00 KiB/s, done.
    Resolving deltas: 100% (54/54), done.
    

    Setup Backend

    Type the following command:

    cd github-history/backend
    

    Installation

    Install all dependencies, you need to have installed nodejs version 16.15.0.

    npm install

    Running server

    Commands to run backend server, use start:dev if you want to automatically reset server after saving changes.

    # development
    npm run start
    
    # watch mode
    npm run start:dev

    The server will start running.

    [Nest] LOG [NestApplication] Nest application successfully started 
    Server running on port 8080
    

    Open your browser and copy following url to see result:

    http://localhost:8080/
    

    Documentation

    You can visit following path to see documentation generated with swagger:

    http://localhost:8080/api/docs
    

    Test

    Commands to test server.

    # unit tests
    npm run test
    
    # e2e tests
    npm run test:e2e

    Setup Frontend

    In the root of project, type the following command:

    cd github-history/frontend
    

    Installation

    Install all dependencies, you need to have installed nodejs version 16.15.0.

    npm install

    Running client

    Run the development server:

    npm run dev
    # or
    yarn dev

    Open http://localhost:3000 with your browser to see the result.

    Try Demo

    The project is deployed with Vercel. Open this link with your browser to see demo:

    demo

    Visit original content creator repository https://github.com/wrujel/github-history
  • PWABuilder

    PWABuilder

    Hey, everybody!

    The project is https://www.pwabuilder.com/, helping to build a progressive app. You can also test any site https://www.pwabuilder.com/reportcard?site=https://griarsvah.github.io/PWABuilder, but I want to make a project that will give the best results for all tests. pwabuilder 100%


    Manifest

    Required

    "icons": [
      {
        "src": "images/favicons/favicon.ico",
        "sizes": "64x64 32x32 24x24 16x16",
        "type": "image/x-icon"
      },
      {
          "src": "images/vector.svg",
          "type": "image/svg+xml",
          "sizes": "667x667"
      },
    {
          "src": "images/android/launchericon-512.png",
          "type": "image/png",
          "sizes": "512x512"
        },
        {
          "src": "images/android/launchericon-192.png",
          "type": "image/png",
          "sizes": "192x192"
    },
        {
          "src": "images/maskable/icon_x48.png",
          "type": "image/png",
          "sizes": "48x48"
    },
        {
          "src": "images/maskable/icon_x72.png",
          "type": "image/png",
          "sizes": "72x72"
    },
        {
          "src": "images/maskable/icon_x96.png",
          "type": "image/png",
          "sizes": "96x96"
    },
        {
          "src": "images/maskable/icon_x128.png",
          "type": "image/png",
          "sizes": "128x128"
    },
        {
          "src": "images/maskable/icon_x192.png",
          "type": "image/png",
          "sizes": "192x192"
    },
        {
          "src": "images/maskable/icon_x384.png",
          "type": "image/png",
          "sizes": "384x384",
          "purpose": "maskable"
    },
        {
          "src": "images/maskable/icon_x512.png",
          "type": "image/png",
          "sizes": "512x512",
          "purpose": "any"
    }
    ],
    
    
    "name": "Vahe PWA",
    
    "short_name": "Vahe",
    
    "start_url": "https://griarsvah.github.io/PWABuilder/index.html",
    

    Recommended

    "background_color": "#ffffff",
    
    "description": "My portfolio, my page, portfolio about me, my works, my skills",
    
    "display": "fullscreen" ,
    

        {
          "src": "images/maskable/icon_x384.png",
          "type": "image/png",
          "sizes": "384x384",
          "purpose": "maskable"
    },
        {
          "src": "images/maskable/icon_x512.png",
          "type": "image/png",
          "sizes": "512x512",
          "purpose": "any"
    }
    
    "id": "index.html",
    

    "launch_handler": {
      "client_mode": ["focus-existing", "auto"]
    },
    
    "orientation": "any",
    

    "screenshots" : [
      {
        "src": "screenshot1.webp",
        "sizes": "1280x720",
        "type": "image/webp",
        "form_factor": "wide",
        "label": "Homescreen of Awesome App"
      },
      {
        "src": "screenshot2.webp",
        "sizes": "1280x720",
        "type": "image/webp",
        "form_factor": "wide",
        "label": "List of Awesome Resources available in Awesome App"
      }
    ]
    
    "theme_color": "#ffffff",
    

    Optional

    "categories": [
      "education",
      "personalization",
      "productivity"
    ],
    
    "dir": "ltr",
    

    "iarc_rating_id": "e84b072d-71b3-4d3e-86ae-31a8ce4e53b7",
      "share_target": {
          "action": "handle-shared-song",
          "method": "POST",
          "enctype": "multipart/form-data",
          "params": {
              "title": "title",
              "files": [
                  {
                      "name": "audioFiles",
                      "accept": [
                          "audio/wav",
                          "audio/x-wav",
                          "audio/mpeg",
                          "audio/mp4",
                          "audio/aac",
                          "audio/ogg",
                          "application/ogg",
                          "audio/webm",
                          "audio/flac"
                      ]
                  }
              ]
          }
      },
    
    "lang": "en",
    
    "prefer_related_applications": false,
    

    "related_applications": [
      {
          "platform": "webapp",
          "url": "https://griarsvah.github.io/PWABuilder/manifest.webmanifest"
      },
      {
          "platform": "itunes",
          "url": "index.html"
      },
      {
          "platform": "play",
          "url": "index.html"
      },
      {
          "platform": "windows",
          "url": "index.html" 
      }
    ],
    
    "scope": "https://github.com/",
    

    "scope_extensions": [
      {"origin": "index.html"}
    ],
    

    App Capabilities

    display_override

    "display_override": ["fullscreen", "standalone", "minimal-ui", "standalone", "window-controls-overlay"],
    

    edge_side_panel

    "edge_side_panel": {
      "preferred_width": 480
    },
    

    file_handlers

    "file_handlers": [
      {
        "action": "index.html",
        "accept": {
          "text/html": [".htm", ".html"]
        }
      }
    ],
    

    handle_links

    "handle_links": "auto",
    

    protocol_handlers

    "protocol_handlers": [
      {
        "protocol": "web+jngl",
        "url": "/lookup?type=%s"
      },
      {
        "protocol": "web+jnglstore",
        "url": "/shop?for=%s"
      }
    ],
    

    share_target

    "share_target": {
          "action": "handle-shared-song",
          "method": "POST",
          "enctype": "multipart/form-data",
          "params": {
              "title": "title",
              "files": [
                  {
                      "name": "audioFiles",
                      "accept": [
                          "audio/wav",
                          "audio/x-wav",
                          "audio/mpeg",
                          "audio/mp4",
                          "audio/aac",
                          "audio/ogg",
                          "application/ogg",
                          "audio/webm",
                          "audio/flac"
                      ]
                  }
              ]
          }
      },
    

    shortcuts

    "shortcuts": [
      {
        "name": "Open Play Later",
        "short_name": "Play Later",
        "description": "View the list of podcasts you saved for later",
        "url": "index.html",
        "icons": [{ "src": "images/vector.svg", "sizes": "667x667" }]
      },
      {
        "name": "View Subscriptions",
        "short_name": "Subscriptions",
        "description": "View the list of podcasts you listen to",
        "url": "index.html",
        "icons": [{ "src": "images/vector.svg", "sizes": "667x667" }]
      }
    ],
    

    widgets

    "widgets": [
          {
              "name": "PWAmp mini player",
              "short_name": "PWAmp",
              "description": "Widget to control the PWAmp player",
              "tag": "pwamp",
              "ms_ac_template": "widgets/mini-player.json",
              "data": "widgets/mini-player-data.json",
              "screenshots": [
                  {
                      "src": "screenshot-widget.png",
                      "sizes": "600x400",
                      "label": "The PWAmp mini-player widget"
                  }
              ],
              "icons": [
                  {
                      "src": "favicon-48.png",
                      "sizes": "48x48"
                  },
                  {
                      "src": "favicon-96.png",
                      "sizes": "96x96"
                  },
                  {
                      "src": "favicon-128.png",
                      "sizes": "128x128"
                  },
                  {
                      "src": "favicon-256.png",
                      "sizes": "256x256"
                  },
                  {
                      "src": "favicon-512.png",
                      "sizes": "512x512"
                  }
              ],
              "backgrounds": [
                  {
                      "src": "widgets/background.png",
                      "sizes": "600x400"
                  }
              ]
          }
      ]
    

    Service Worker

    Tip

    Для выполнения этого условия нужно иметь в корне сайта файла index.html

    <script>if (typeof navigator.serviceWorker !== 'undefined') {
      	navigator.serviceWorker.register('sw.js')
    }</script>```
    
    • background sync

    • periodic sync

    Tip

    Для выполнения этого условия нужно в файле sw.js

    // Respond to a server push with a user notification.
    self.addEventListener('push', function (event) {
        if (Notification.permission === "granted") {
            let notification_data = JSON.parse(event.data.text());
            const notificationText = notification_data["description"];
            const notification_title = notification_data["notifier_DisplayName"];
            let notificaiotn_timestampt = notification_data["CreatedAt"];
            // Convert the string date to a date object. And unix timestamp to milliseconds
            let notification_timestamp = new Date(notificaiotn_timestampt * 1000);
            // Convert the date object to a string, using the locale language
            let notification_timestamp_string = notification_timestamp.toLocaleString();
            let notificaiton_sid = notification_data["sid"];
    
    
            const showNotification = self.registration.showNotification(notification_title, {
                // title: notification_title,
                body: notificationText,
                icon: '/images/vector.svg',
                tag: notificaiton_sid,
                data: {
                    url: notification_data["url"]
                },
                // actions: [
                //     { action: 'actionName', title: 'Mark as read', icon: '/static/images/Logos/logo.png' },
                //     { action: 'actionName', title: 'Mark as unread', icon: '/static/images/Logos/logo.png' },
                // ],
                timestamp: notification_timestamp_string,
            });
            // Make sure the toast notification is displayed.
            event.waitUntil(showNotification);
        }
    });
    
    // Respond to the user selecting the toast notification.
    self.addEventListener('notificationclick', function (event) {
        event.notification.close(); // Android needs explicit close.
        event.waitUntil(
            clients.openWindow(event.notification.data.url) // This line will open the URL saved in 'data' when the notification was first created.
        );
    });
    

    Visit original content creator repository
    https://github.com/griarsvah/PWABuilder

  • straug

    Data Augmentation for Scene Text Recognition

    (Pronounced as “strog“)

    Paper

    Why it matters?

    Scene Text Recognition (STR) requires data augmentation functions that are different from object recognition. STRAug is data augmentation designed for STR. It offers 36 data augmentation functions that are sorted into 8 groups. Each function supports 3 levels or magnitudes of severity or intensity.

    Given a source image:

    it can be transformed as follows:

    1. warp.py – to generate Curve, Distort, Stretch (or Elastic) deformations
    Curve Distort Stretch
    1. geometry.py – to generate Perspective, Rotation, Shrink deformations
    Perspective Rotation Shrink
    1. pattern.py – to create different grids: Grid, VGrid, HGrid, RectGrid, EllipseGrid
    Grid VGrid HGrid RectGrid EllipseGrid
    1. blur.py – to generate synthetic blur: GaussianBlur, DefocusBlur, MotionBlur, GlassBlur, ZoomBlur
    GaussianBlur DefocusBlur MotionBlur GlassBlur ZoomBlur
    1. noise.py – to add noise: GaussianNoise, ShotNoise, ImpulseNoise, SpeckleNoise
    GaussianNoise ShotNoise ImpulseNoise SpeckleNoise
    1. weather.py – to simulate certain weather conditions: Fog, Snow, Frost, Rain, Shadow
    Fog Snow Frost Rain Shadow
    1. camera.py – to simulate camera sensor tuning and image compression/resizing: Contrast, Brightness, JpegCompression, Pixelate
    Contrast Brightness JpegCompression Pixelate
    1. process.py – all other image processing issues: Posterize, Solarize, Invert, Equalize, AutoContrast, Sharpness, Color
    Posterize Solarize Invert Equalize
    AutoContrast Sharpness Color

    Pip install

    pip3 install straug
    

    How to use

    Command line (e.g. input image is nokia.png):

    >>> from straug.warp import Curve
    >>> from PIL import Image
    >>> img = Image.open("nokia.png")
    >>> img = Curve()(img, mag=3)
    >>> img.save("curved_nokia.png")
    

    Python script (see test.py):

    python3 test.py --image=<target image>

    For example:

    python3 test.py --image=images/telekom.png

    The corrupted images are in results directory.

    If you want to randomly apply only the desired augmentation types among multiple augmentations, see test_random_aug.py

    Reference

    • Image corruptions (eg blur, noise, camera effects, fog, frost, etc) are based on the work of Hendrycks et al.

    Citation

    If you find this work useful, please cite:

    @inproceedings{atienza2021data,
      title={Data Augmentation for Scene Text Recognition},
      author={Atienza, Rowel},
      booktitle={Proceedings of the IEEE/CVF International Conference on Computer Vision},
      pages={1561--1570},
      year={2021}
    }
    
    Visit original content creator repository https://github.com/roatienza/straug
  • straug

    Data Augmentation for Scene Text Recognition

    (Pronounced as “strog“)

    Paper

    Why it matters?

    Scene Text Recognition (STR) requires data augmentation functions that are different from object recognition. STRAug is data augmentation designed for STR. It offers 36 data augmentation functions that are sorted into 8 groups. Each function supports 3 levels or magnitudes of severity or intensity.

    Given a source image:

    it can be transformed as follows:

    1. warp.py – to generate Curve, Distort, Stretch (or Elastic) deformations
    Curve Distort Stretch
    1. geometry.py – to generate Perspective, Rotation, Shrink deformations
    Perspective Rotation Shrink
    1. pattern.py – to create different grids: Grid, VGrid, HGrid, RectGrid, EllipseGrid
    Grid VGrid HGrid RectGrid EllipseGrid
    1. blur.py – to generate synthetic blur: GaussianBlur, DefocusBlur, MotionBlur, GlassBlur, ZoomBlur
    GaussianBlur DefocusBlur MotionBlur GlassBlur ZoomBlur
    1. noise.py – to add noise: GaussianNoise, ShotNoise, ImpulseNoise, SpeckleNoise
    GaussianNoise ShotNoise ImpulseNoise SpeckleNoise
    1. weather.py – to simulate certain weather conditions: Fog, Snow, Frost, Rain, Shadow
    Fog Snow Frost Rain Shadow
    1. camera.py – to simulate camera sensor tuning and image compression/resizing: Contrast, Brightness, JpegCompression, Pixelate
    Contrast Brightness JpegCompression Pixelate
    1. process.py – all other image processing issues: Posterize, Solarize, Invert, Equalize, AutoContrast, Sharpness, Color
    Posterize Solarize Invert Equalize
    AutoContrast Sharpness Color

    Pip install

    pip3 install straug
    

    How to use

    Command line (e.g. input image is nokia.png):

    >>> from straug.warp import Curve
    >>> from PIL import Image
    >>> img = Image.open("nokia.png")
    >>> img = Curve()(img, mag=3)
    >>> img.save("curved_nokia.png")
    

    Python script (see test.py):

    python3 test.py --image=<target image>

    For example:

    python3 test.py --image=images/telekom.png

    The corrupted images are in results directory.

    If you want to randomly apply only the desired augmentation types among multiple augmentations, see test_random_aug.py

    Reference

    • Image corruptions (eg blur, noise, camera effects, fog, frost, etc) are based on the work of Hendrycks et al.

    Citation

    If you find this work useful, please cite:

    @inproceedings{atienza2021data,
      title={Data Augmentation for Scene Text Recognition},
      author={Atienza, Rowel},
      booktitle={Proceedings of the IEEE/CVF International Conference on Computer Vision},
      pages={1561--1570},
      year={2021}
    }
    
    Visit original content creator repository https://github.com/roatienza/straug
  • AsianModelicaConference2022

    Post-event Access Available

    The Asian Modelica Conference 2022 was successfully closed last week. We are happy to announce that the local organizer committee decided to provide post-event free access to the recorded presentation including oral paper presentation and vendor solution presentation. The access period is from 1st to 9th December 2022.

    For the existent attendees who joined the conference last week, you can log in Whova and re-visit the presentation videos and exhibitor booths.

    For the new attendees who were not able to join the conference last week, please create your Whova account first and then access the conference content through following link.

    Important Update

    The Asian Modelica Conference 2022 has been changed to a hybrid event on November 24–25, 2022. It is organized by Modelica Association in cooperation with Sophia University and Modelon K.K.. The conference period keeps the same as before of two days, while a conference venue will be available inside Yotsuya campus of Sophia University Tokyo, Japan. Some other updates are:

    • The deadline for paper submission is extended further to 11, September
    • Industrial paper by tool vendors, discussion paper no less than two pages are acceptable for submission
    • Physical exhibition will be available at the conference venue
    • Conference dinner party will be scheduled for on-site participants

    About the Conference

    The Modelica Conference is the main event for users, library developers, tool vendors and language designers to share their knowledge and learn about the latest scientific and industrial progress related to all of the system simulation standards developed and maintained by the Modelica Association, in particular Modelica, the Functional Mockup Interface (FMI), the System Structure and Parameterization (SSP) standard and the The Distributed Co-simulation Protocol (DCP) standard and the Functional Mock-up Interface for embedded systems (eFMI) standard.

    The program will cover modeling of complex physical and cyber-physical systems, as well as tools, for a wide range of research and industrial applications. More details about the virtual conference platform will be available soon.

    We are looking forward to seeing you online or in-person.

    Scope of the Conference

    Modelica is a freely available, equation-based, object-oriented language for convenient and efficient modeling of complex, multi-domain cyber-physical systems described by ordinary differential, difference and algebraic equations. The Modelica language and the companion Modelica Standard Library have been utilized in demanding industrial applications, including full vehicle dynamics, power systems, robotics, hardware-in-the-loop simulations and embedded control systems, etc. The Functional Mockup Interface (FMI) is an open standard for the tool-independent exchange of models and for co-simulation. It is supported by many Modelica and non-Modelica tools and is the key to utilizing Modelica models in non-Modelica environments.

    The Modelica conference will bring together people using any of the Modelica Association standards for modeling, simulation, and control applications, Modelica language designers, Modelica and/or FMI tool vendors and Modelica library developers. It provides Modelica users the opportunity to stay informed about the latest standards, library, and tool developments, and to get in touch with people working on similar modeling problems. The conference will cover topics such as the following:

    • Multi-engineering modeling and simulation with Modelica
    • Free and commercial Modelica libraries (mechanics, electrical, hydraulics, thermal, fluid, media, chemical, building, automotive, aircraft, …)
    • Automotive applications
    • Thermodynamic and energy systems applications
    • Mechatronics and robotics applications
    • Other industrial applications, such as electric drives, power systems, aerospace, etc.
    • Real-time and hardware-in-the-loop simulation
    • Simulation and code generation for embedded control systems
    • Applications of Modelica for optimization and optimal control
    • Modelica modeling, simulation and design tools
    • Symbolic algorithms and numerical methods for model transformation and simulation
    • New features for future Modelica versions
    • Modelica in other application areas (mathematical programming, databases etc.)
    • Modelica for teaching and education
    • New features of future FMI versions
    • FMI in Modelica and non-Modelica applications and tools
    • Tools and applications using the SSP standard
    • Tool and applications using the DCP standard
    • Digital Twins based on MA technologies

    In addition, the conference will include Vendors’ exhibition, by either virtual or physical means.

    You are encouraged to share your Modelica, FMI and other Modelica Association related work by submitting a paper in English.
    Papers and extended abstracts for presentations can be submitted via the EasyChair conference management system (login is needed first):

    EasyChair AsianModelicaConference 2022

    There, you can also read your reviews and hand in the final paper after the reviewing process has taken place.
    In order to submit a paper, you need to have an EasyChair account.
    Simply follow the provided instructions to create an account.
    The same account can be used for several conferences over several years.
    Once you have logged in, please choose option “enter as an author”.
    You can download the submission templates through easychair or here (abstract, paper), or upload your contribution in the section: “New submissions”.
    Simply follow the instructions.

    The paper submission form includes the option to mark suitable topics for your paper. Please use this feature since it helps us to find suitable reviewers for your paper. Furthermore, there is the option to attach a .zip file to your paper. In this way, you can provide example models that correspond to your paper.
    The conference proceedings will be published by the Modelica Association on its website and by Linköping University Electronic Press. Each paper will be individually referenced by a DOI.

    Exhibition and Sponsorship

    To support the conference, and to get an opportunity to expose their Modelica- and/or FMI-related products and services, vendors will have the opportunity to sponsor the event and to participate in the exhibition. The sponsorship and exhibition will be avialable at the virtual conference as well.

    A decision about the acceptance of sponsors and exhibitors will be based upon Modelica/FMI relevance of products and/or services at the time of application submission.

    Important Dates (further extended)

    • Full papers submission: September 11, 2022
    • Notification of acceptance: October 2, 2022
    • Final papers submission: October 23, 2022
    • Early bird registration: October 23, 2022

    Registration

    Please register the hybrid conference according to your situation: either virtual or physical, general participant or presenter. The early bird ticket in Japanese Yen is available from August 23 to October 23, 2022. In the registration, you will be asked to fill in the form about your information. Please make sure you have consent to the Privacy Policy.

    If you plan to attend the virtual conference, please register from the link below.

    If you plan to attend the physical conference, please register from the link below. Conference dinner fee is included in the ticket.

    For the presenter of the conference paper, please register from the link below. Conference dinner fee is included in the ticket for physical conference attendee.

    Conference venue

    The top floor classroom of Building No.7 at Yotsuya campus, Sophia University will be the main conference venue.
    The address is 7-1 Kioicho, Chiyoda-ku, Tokyo 102-8554 JAPAN.

    You can access the North Gate of the campus through JR Chuo line, Marunouchi subway line, Nanboku subway line / 5 minutes from Yotsuya Station.

    Please refer to the access map for more details.

    Whova platform

    Remote access to the virtual conference is managed using Whova. The participants who registered will receive an email from Whova. You will be notified once the event is ready on the Whova Web and Mobile apps. You will then be able to access the agenda and network with other attendees.

    Organization and Contact

    The conference is organized by Modelica Association in cooperation with Prof. Tielong Shen from Sophia University and Modelon K.K.. For more information and application, please contact the organizer.

    Conference Board

    • Prof. Tielong Shen, Sophia University, Tokyo, Japan
    • Dr. Rui Gao, Modelon K.K., Tokyo, Japan
    • Dr. Yutaka Hirano, Woven Planet Holdings, Inc., Tokyo, Japan
    • Prof. Martin Otter, DLR, Germany
    • Dr. Martin Sjölund, Linköping University, Sweden
    • Dr. Michael Tiller, Xogeny, Michigan, USA
    • Dr. Hubertus Tummescheit, Modelon AB, Lund, Sweden

    Local Organization

    • General chair: Prof. Tielong Shen, Sophia University
    • Program chair: Dr. Yutaka Hirano, Woven Planet Holdings, Inc.
    • Conference co-chair: Dr. Rui Gao, Modelon K.K.

    Privacy Policy & [Release Form](cfp/Asian Modelica Conference 2022 Release Form.pdf)

    Visit original content creator repository
    https://github.com/modelica/AsianModelicaConference2022

  • vuejsOidcClient

    OIDC Client

    Built the project with Vuejs CLI 3.4.0 and then migrated OIDC components from fork.

    Project setup

    npm install
    

    Compiles and hot-reloads for development

    npm run serve
    npm run serve -- --port 5003
    

    Compiles and minifies for production

    npm run build
    

    Run your tests

    npm run test
    

    Lints and fixes files

    npm run lint
    

    Customize configuration

    See Configuration Reference.


    Connection with identity provider

    Change the parameters of the variable mgr of the script [SecurityService.js][2] to the values of your identity provider.

    var mgr = new Oidc.UserManager({
      userStore: new Oidc.WebStorageStateStore(),
      authority: 'https://localhost:44321',
      client_id: 'vuejsclient',
      redirect_uri: window.location.origin + '/static/callback.html',
      response_type: 'id_token token',
      scope: 'openid profile address roles identityserver4api country subscriptionlevel offline_access',
      post_logout_redirect_uri: window.location.origin + '/index.html',
      silent_redirect_uri: window.location.origin + '/static/silent-renew.html',
      accessTokenExpiringNotificationTime: 10,
      automaticSilentRenew: true,
      filterProtocolClaims: true,
      loadUserInfo: true
    })

    The script [SecurityService.js][2] contains triggers and methods from the [oidc-client][3] library.

    API

    The script [ApiService.js][4] is responsible for making requests to an API using the libraries [oidc-client][3] and [axios][5]

    The baseUrl constant receives the static part of the API Url.

    const baseUrl = 'https://localhost:44390/api/';

    More information on fork.

    Visit original content creator repository
    https://github.com/benscabbia/vuejsOidcClient

  • Clientprefs

    Clientprefs for CSSharp

    This plugin exposes some natives for developers to save player data to SQLite / MySQL without actually adding sql code to your plugin giving developers easy access to save player cookie to database.

    Example

    using Clientprefs.API;
    
    private readonly PluginCapability<IClientprefsApi> g_PluginCapability = new("Clientprefs");
    private IClientprefsApi? ClientprefsApi;
    private int g_iCookieID = 0;
    private Dictionary<CCSPlayerController, string> playerCookie = new();
    
    public override void Unload(bool hotReload)
    {
        base.Unload(hotReload);
    
        if (ClientprefsApi == null) return;
    
        ClientprefsApi.OnDatabaseLoaded -= OnClientprefDatabaseReady;
        ClientprefsApi.OnPlayerCookiesCached -= OnPlayerCookiesCached;
    }
    
    public override void OnAllPluginsLoaded(bool hotReload)
    {
        ClientprefsApi = g_PluginCapability.Get();
    
        if (ClientprefsApi == null) return;
    
        ClientprefsApi.OnDatabaseLoaded += OnClientprefDatabaseReady;
        ClientprefsApi.OnPlayerCookiesCached += OnPlayerCookiesCached;
    
        if (hotReload)
        {
            if (ClientprefsApi == null || g_iCookieID == -1) return;
    
            foreach (var player in Utilities.GetPlayers().Where(p => !p.IsBot))
            {
                if (!ClientprefsApi.ArePlayerCookiesCached(player)) continue;
                playerCookie[player] = ClientprefsApi.GetPlayerCookie(player, g_iCookieID);
            }
        }
    }
    
    public void OnClientprefDatabaseReady()
    {
        if (ClientprefsApi == null) return;
        
        g_iCookieID = ClientprefsApi.RegPlayerCookie("example_cookie", "Example cookie description", CookieAccess.CookieAccess_Public);
    
        if(g_iCookieID == -1)
        {
            Logger.LogError("[Clientprefs-Example] Failed to register/load cookie 1");
            return;
        }
    
        Logger.LogInformation($"[Clientprefs-Example] Registered/Loaded cookie with ID: {g_iCookieID}"); // ID: 1
    }
    
    public void OnPlayerCookiesCached(CCSPlayerController player)
    {
        if (ClientprefsApi == null || g_iCookieID == -1) return;
        
        playerCookie[player] = ClientprefsApi.GetPlayerCookie(player, g_iCookieID);
    
        Logger.LogInformation($"[Clientprefs-Example] Cookie value: {cookieValue}");
    }
    
    [ConsoleCommand("css_clientprefs_example", "Saves example clientprefs cookie value")]
    public void OnExampleCommand(CCSPlayerController? caller, CommandInfo _)
    {
        if (caller == null || !caller.IsValid || ClientprefsApi == null || g_iCookieID == -1)
        {
            return;
        }
    
        ClientprefsApi.SetPlayerCookie(caller, g_iCookieID, playerCookie[player]);
    }

    Config

    {
      "TableName": "css_cookies",
      "TableNamePlayerData": "css_cookies_playerdata",
      "DatabaseType": "sqlite",
      "DatabaseHost": "",
      "DatabaseName": "",
      "DatabaseUsername": "",
      "DatabasePassword": "",
      "DatabasePort": 3306,
      "DatabaseSslmode": "",
      "Debug": false,
      "ConfigVersion": 1
    }

    Things left to implement

    [ ] css_settings

    Changelog

    • v1.0.4
      • fix: CreatePlayerCookie native using wrong parameter name.
      • fix: SavePlayerCookie missing not operator.
      • fix: Player preferences not getting saved at map change.
    • v1.0.3
      • fix: Plugin will no longer throw “Native d01e4eb5 was invoked on a non-main thread” on playerConnect.
      • Devs can now save clientpref for player at PlayerDisconnect(HookMode.Post) too as the plugin now saves in database after 0.5 seconds.
      • Added more error logging and added variable in config to enable debug logs.
    • v1.0.2
      • Fixed dictionary errors for players after map change.
    • v1.0.1
      • Changed hook method of OnClientprefDatabaseReady & OnPlayerCookiesCached. Please re-refer ClientprefsExample.

    Visit original content creator repository
    https://github.com/Cruze03/Clientprefs