mirror of
https://github.com/wasp-lang/open-saas.git
synced 2025-03-29 11:12:19 +01:00
fixes
This commit is contained in:
parent
41bcd70496
commit
8d5ab0d2ee
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,6 +6,6 @@ fly config/fly-client.toml
|
||||
fly config/fly-server.toml
|
||||
fly-client.toml
|
||||
fly-server.toml
|
||||
# TODO: change this before deploy
|
||||
# TODO: create a clean version for the user to fill in
|
||||
# replace with your own Google Analytics service account json file
|
||||
saastemplate-381911-6dc3caae2204.json
|
||||
|
@ -7,10 +7,7 @@ export default defineConfig({
|
||||
integrations: [
|
||||
starlightBlog({
|
||||
title: 'The Best Blog Ever',
|
||||
sidebar: [
|
||||
{
|
||||
}
|
||||
],
|
||||
sidebar: [{}],
|
||||
authors: {
|
||||
vince: {
|
||||
name: 'Vince',
|
||||
@ -22,10 +19,8 @@ export default defineConfig({
|
||||
}),
|
||||
starlight({
|
||||
title: 'Open SaaS Docs',
|
||||
// root: '/start/introdcution/',
|
||||
// site: 'https://www.my-site.dev', // TODO: Change this to your site
|
||||
editLink: {
|
||||
baseUrl: 'https://github.com/withastro/starlight/edit/main/', // TODO: change
|
||||
baseUrl: 'https://github.com/wasp-lang/open-saas/edit/main',
|
||||
},
|
||||
components: {
|
||||
MarkdownContent: 'starlight-blog/overrides/MarkdownContent.astro',
|
||||
@ -33,7 +28,7 @@ export default defineConfig({
|
||||
ThemeSelect: 'starlight-blog/overrides/ThemeSelect.astro',
|
||||
},
|
||||
social: {
|
||||
github: 'https://github.com/wasp-lang',
|
||||
github: 'https://github.com/wasp-lang/open-saas',
|
||||
twitter: 'https://twitter.com/wasp_lang',
|
||||
discord: 'https://discord.gg/aCamt5wCpS',
|
||||
},
|
||||
|
@ -50,9 +50,8 @@ The Admin dashboard is a single place for you to view your most important metric
|
||||
|
||||
For a guide on how to integrate these services, check out the [Stripe](/guides/stripe-integration) and [Analytics guide](/guides/analytics) of the docs.
|
||||
|
||||
<!-- TODO: add repo links -->
|
||||
:::tip[Help us improve]
|
||||
We're always looking to improve the Admin dashboard. If you feel something is missing or could be improved, consider [opening an issue]() or [submitting a pull request]()
|
||||
We're always looking to improve the Admin dashboard. If you feel something is missing or could be improved, consider [opening an issue](https://github.com/wasp-lang/open-saas/issues) or [submitting a pull request](https://github.com/wasp-lang/open-saas/pulls)
|
||||
:::
|
||||
|
||||
### Users
|
||||
|
@ -127,7 +127,7 @@ entity User {=psl
|
||||
//...
|
||||
psl=}
|
||||
```
|
||||
// TODO: add screenshot of user table
|
||||
<!-- TODO: add screenshot of user table -->
|
||||
|
||||
As an Admin, a user has access to the Admin dashboard, along with the user table where they can view and search for users, and edit and update information manually if necessary.
|
||||
|
||||
|
@ -8,7 +8,36 @@ Google Analytics is free, but tends to be more cumbersome to use.
|
||||
Plausible is an open-source, privacy-friendly alternative to Google Analytics. It's also easier to use than Google if you use their hosted service, which is a paid feature. But, it is completely free if you want to self-host it, although this comes with some additional setup steps.
|
||||
|
||||
## Plausible
|
||||
<!-- TODO add plausible -->
|
||||
|
||||
### Hosted Plausible
|
||||
Sign up for a hosted Plausible account [here](https://plausible.io/).
|
||||
|
||||
Once you've signed up, you'll be taken to your dashboard. Create your site by adding your domain. Your domain is also your `PLAUSIBLE_SITE_ID` in your `.env.server` file. Make sure to add it.
|
||||
|
||||
```sh
|
||||
PLAUSIBLE_SITE_ID=<your domain without www>
|
||||
```
|
||||
|
||||
After adding your domain, you'll be taken to a page with your Plausible script tag. Copy and paste this script tag into the `main.wasp` file's head section.
|
||||
|
||||
```js {7}
|
||||
app SaaSTemplate {
|
||||
wasp: {
|
||||
version: "^0.11.6"
|
||||
},
|
||||
title: "My SaaS App",
|
||||
head: [
|
||||
"<your plausible script tag here>",
|
||||
],
|
||||
//...
|
||||
```
|
||||
|
||||
Go back to your Plausible dashboard, click on your username in the top right, and click on the `Settings` tab. Scroll down, find your API key and paste it into your `.env.server` file under the `PLAUSIBLE_API_KEY` variable.
|
||||
|
||||
|
||||
### Self-hosted Plausible
|
||||
|
||||
Plausible, being an open-source project, allows you to self-host your analytics. This is a great option if you want to keep your data private and not pay for the hosted service.
|
||||
|
||||
*coming soon...*
|
||||
*until then, check out the [official documentation](https://plausible.io/docs)*
|
||||
@ -25,7 +54,7 @@ After you sign up for [Google analytics](https://analytics.google.com/), go to y
|
||||
|
||||
Once you've completed the steps to create a new Property, some Installation Instructions will pop up. Select `install manually` and copy and paste the Google script tag into the `main.wasp` file's head section.
|
||||
|
||||
```js
|
||||
```js {7}
|
||||
app SaaSTemplate {
|
||||
wasp: {
|
||||
version: "^0.11.6"
|
||||
@ -52,7 +81,7 @@ Then, set up the Google Analytics API access by following these steps:
|
||||
- Select "JSON", then click “Create” to download your new service account’s JSON key file. Keep this file secure and don't add it to your git repo – it grants access to your Google Analytics data.
|
||||
5. **Update your Google Anayltics Settings:** Go back to your Google Analytics dashboard, and click on the `Admin` section in the left sidebar. Under `Property Settings > Property > Property Access Management` Add the service account email address (the one that ends with `@your-project-id.iam.gserviceaccount.com`) and give it `Viewer` permissions.
|
||||
|
||||
6. **Encode and add the environment variables:** Add the `client_email` and the `private_key` from your JSON Key file into your `.env.server` file. But be careful! Because Google uses a special PEM private key, you need to first convert the key to base64, otherwise you will run into errors parsing the key. To do this, in a terminal window, run the command below and paste the output into your `.env.server` file under the `GOOGLE_ANALYTICS_PRIVATE_KEY` variable:
|
||||
6. **Encode and add the Credentials:** Add the `client_email` and the `private_key` from your JSON Key file into your `.env.server` file. But be careful! Because Google uses a special PEM private key, you need to first convert the key to base64, otherwise you will run into errors parsing the key. To do this, in a terminal window, run the command below and paste the output into your `.env.server` file under the `GOOGLE_ANALYTICS_PRIVATE_KEY` variable:
|
||||
```sh
|
||||
echo -n "PRIVATE_KEY" | base64
|
||||
```
|
||||
|
@ -14,9 +14,8 @@ This template is:
|
||||
2. completely free to use and distribute
|
||||
3. comes with a ton of features out of the box!
|
||||
|
||||
<!-- // TODO: add links -->
|
||||
Try it out here:
|
||||
Check Out the Code:
|
||||
Try it out here: [OpenSaaS.sh](https://opensaas.sh)
|
||||
Check Out the Code: Open SaaS [GitHub Repo](https://github.com/wasp-lang/open-saas)
|
||||
|
||||
## What's inside?
|
||||
|
||||
@ -44,8 +43,7 @@ You also get access to Wasp's diverse, helpful community if you get stuck or nee
|
||||
:::tip["Work In Progress"]
|
||||
We've tried to get as many of the core features of a SaaS app into this template as possible, but there still might be some missing features or functionality.
|
||||
|
||||
We could always use some help tying up loose ends, so consider [contributing]()!
|
||||
<!-- {/* TODO: add link */} -->
|
||||
We could always use some help tying up loose ends, so consider [contributing](https://github.com/wasp-lang/open-saas/blob/main/CONTRIBUTING.md)!
|
||||
:::
|
||||
|
||||
## Getting acquainted with the codebase
|
||||
|
@ -18,11 +18,12 @@ Also install the [Wasp extension for VSCode](https://marketplace.visualstudio.co
|
||||
|
||||
Clone this repo by running this command in your terminal:
|
||||
```sh
|
||||
git clone // TODO ADD REPO LINK
|
||||
git clone https://github.com/wasp-lang/open-saas.git
|
||||
```
|
||||
|
||||
Then position yourself in the root of the project:
|
||||
```sh
|
||||
cd // TODO ADD REPO NAME
|
||||
cd open-saas
|
||||
```
|
||||
|
||||
### Start your DB
|
||||
|
12
main.wasp
12
main.wasp
@ -5,10 +5,10 @@ app SaaSTemplate {
|
||||
title: "My Open SaaS App",
|
||||
head: [
|
||||
"<meta property='og:type' content='website' />",
|
||||
"<meta property='og:url' content='https://mySaaSapp.com' />", // TODO change url
|
||||
"<meta property='og:url' content='https://opensaas.sh' />",
|
||||
"<meta property='og:description' content='I made a SaaS App. Buy my stuff.' />",
|
||||
"<meta property='og:image' content='src/client/static/image.png' />",
|
||||
"<meta name='twitter:image' content='https://mySaaSapp.com/gptsaastemplate.png' />", // TODO change url and image
|
||||
"<meta property='og:image' content='https://opensaas.sh/public-logo.png' />",
|
||||
"<meta name='twitter:image' content='https://opensaas.sh/public-logo.png' />",
|
||||
"<meta name='twitter:image:width' content='800' />",
|
||||
"<meta name='twitter:image:height' content='400' />",
|
||||
"<meta name='twitter:card' content='summary_large_image' />",
|
||||
@ -249,6 +249,12 @@ page AdminChartsPage {
|
||||
component: import AdminCharts from "@client/admin/pages/Chart"
|
||||
}
|
||||
|
||||
route AdminMessagesRoute { path: "/admin/messages", to: AdminMessagesPage }
|
||||
page AdminMessagesPage {
|
||||
authRequired: true,
|
||||
component: import AdminMessages from "@client/admin/pages/Messages"
|
||||
}
|
||||
|
||||
route AdminFormElementsRoute { path: "/admin/forms/form-elements", to: AdminFormElementsPage }
|
||||
page AdminFormElementsPage {
|
||||
authRequired: true,
|
||||
|
@ -3,7 +3,7 @@ import AppNavBar from './components/AppNavBar';
|
||||
import { useMemo, useEffect, ReactNode } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import useAuth from '@wasp/auth/useAuth';
|
||||
import updateCurrentUser from '@wasp/actions/updateCurrentUser'; // TODO fix
|
||||
import updateCurrentUser from '@wasp/actions/updateCurrentUser';
|
||||
|
||||
/**
|
||||
* use this component to wrap all child components
|
||||
@ -25,8 +25,9 @@ export default function App({ children }: { children: ReactNode }) {
|
||||
if (user) {
|
||||
const lastSeenAt = new Date(user.lastActiveTimestamp);
|
||||
const today = new Date();
|
||||
if (lastSeenAt.getDate() === today.getDate()) return;
|
||||
updateCurrentUser({ lastActiveTimestamp: today });
|
||||
if (today.getTime() - lastSeenAt.getTime() > 5 * 60 * 1000) {
|
||||
updateCurrentUser({ lastActiveTimestamp: today });
|
||||
}
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import DarkModeSwitcher from './DarkModeSwitcher';
|
||||
import DropdownMessage from './DropdownMessage';
|
||||
import MessageButton from './MessageButton';
|
||||
import DropdownUser from '../../components/DropdownUser';
|
||||
import type { User } from '@wasp/entities'
|
||||
|
||||
@ -67,7 +67,7 @@ const Header = (props: {
|
||||
{/* <!-- Dark Mode Toggler --> */}
|
||||
|
||||
{/* <!-- Chat Notification Area --> */}
|
||||
<DropdownMessage />
|
||||
<MessageButton />
|
||||
{/* <!-- Chat Notification Area --> */}
|
||||
</ul>
|
||||
|
||||
|
@ -1,17 +1,15 @@
|
||||
// import { useEffect, useRef, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const DropdownMessage = () => {
|
||||
import { Link } from '@wasp/router';
|
||||
|
||||
const MessageButton = () => {
|
||||
|
||||
return (
|
||||
<li className="relative" x-data="{ dropdownOpen: false, notifying: true }">
|
||||
<Link
|
||||
// TODO: add wasp link
|
||||
className="relative flex h-8.5 w-8.5 items-center justify-center rounded-full border-[0.5px] border-stroke bg-gray hover:text-primary dark:border-strokedark dark:bg-meta-4 dark:text-white"
|
||||
to="#"
|
||||
to="/admin/messages"
|
||||
>
|
||||
<span className="absolute -top-0.5 -right-0.5 z-1 h-2 w-2 rounded-full bg-meta-1">
|
||||
{/* TODO: only animate if there are new messages */}
|
||||
<span className="absolute -z-1 inline-flex h-full w-full animate-ping rounded-full bg-meta-1 opacity-75"></span>
|
||||
</span>
|
||||
|
||||
@ -45,4 +43,4 @@ const DropdownMessage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default DropdownMessage;
|
||||
export default MessageButton;
|
10
src/client/admin/pages/Messages.tsx
Normal file
10
src/client/admin/pages/Messages.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
// TODO: Add messages page
|
||||
|
||||
function AdminMessages() {
|
||||
|
||||
return (
|
||||
<div>Hello world!</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AdminMessages
|
Binary file not shown.
Before Width: | Height: | Size: 446 KiB |
BIN
src/client/public/public-logo.png
Normal file
BIN
src/client/public/public-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -86,7 +86,6 @@ export const calculateDailyStats: DailyStatsJob<never, void> = async (_args, con
|
||||
const sources = await getSources();
|
||||
|
||||
for (const source of sources) {
|
||||
console.log('source: ', source);
|
||||
let visitors = source.visitors;
|
||||
if (typeof source.visitors !== 'number') {
|
||||
visitors = parseInt(source.visitors);
|
||||
|
@ -2,7 +2,6 @@ import { BetaAnalyticsDataClient } from '@google-analytics/data';
|
||||
|
||||
const CLIENT_EMAIL = process.env.GOOGLE_ANALYTICS_CLIENT_EMAIL;
|
||||
const PRIVATE_KEY = Buffer.from(process.env.GOOGLE_ANALYTICS_PRIVATE_KEY!, 'base64').toString('utf-8');
|
||||
|
||||
const PROPERTY_ID = process.env.GOOGLE_ANALYTICS_PROPERTY_ID;
|
||||
|
||||
const analyticsDataClient = new BetaAnalyticsDataClient({
|
||||
@ -22,7 +21,6 @@ export async function getSources() {
|
||||
},
|
||||
],
|
||||
// for a list of dimensions and metrics see https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema
|
||||
// get total page views
|
||||
dimensions: [
|
||||
{
|
||||
name: 'source',
|
||||
@ -37,7 +35,6 @@ export async function getSources() {
|
||||
|
||||
let activeUsersPerReferrer: any[] = [];
|
||||
if (response?.rows) {
|
||||
console.log('response.rows (sources): ', response.rows)
|
||||
activeUsersPerReferrer = response.rows.map((row) => {
|
||||
if (row.dimensionValues && row.metricValues) {
|
||||
return {
|
||||
|
Loading…
x
Reference in New Issue
Block a user