commit 29d3775f8cf6bf8e5cc4edb8f7291e754aff3968 Author: Zed A. Shaw Date: Mon Aug 3 14:51:49 2026 -0400 Initial commit, survey laid out. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..70a4b9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# ---> Vim +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +backup +*.exe +*.dll +*.world +coverage +coverage/* +.venv +*.gz +config.json +public +*.idx +*.sqlite3 +webapp +bin +static/style.css +db.* diff --git a/.ozai.json b/.ozai.json new file mode 100644 index 0000000..de400e4 --- /dev/null +++ b/.ozai.json @@ -0,0 +1,25 @@ +{ + "HostPort": ":9999", + "Processes": { + "webapp": { + "URL": "/webapp", + "Command": "./bin/webapp", + "Args": [] + }, + "ssgod": { + "URL": "/ssgod", + "Command": "go", + "Args": ["tool", "ssgod", "watch"] + }, + "mailhog": { + "URL": "/mailhog", + "Command": "MailHog", + "Args": [] + }, + "tailwind": { + "URL": "/tailwind", + "Command": "tailwindcss", + "Args": ["--input", "./static/input_style.css", "--output", "./static/style.css","--watch=always"] + } + } +} diff --git a/.ssgod.json b/.ssgod.json new file mode 100644 index 0000000..0bc609d --- /dev/null +++ b/.ssgod.json @@ -0,0 +1,13 @@ +{ + "views": "pages", + "layout": "views/layouts/main.html", + "target": "public", + "watch_delay": "500ms", + "sync_dir": "static", + "exclude": [ + "pages/layouts/.*" + ], + "meta_files": [ + "pages/sitemap.html" + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d64aa11 --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +It's Copyright. All Rights Reserved. You have no license at all other than permission to view it. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8e36cc3 --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +all: build +ifeq '$(OS)' 'Windows_NT' + powershell -ExecutionPolicy bypass "./tools/restart.ps1" +else + curl http://127.0.0.1:9999/webapp || true +endif + +build: cmds + go build -o bin/ . + +cmds: + go build -o bin/ ./tools/cmd/fgen + go build -o bin/ ./tools/cmd/qmgr + go build -o bin/ ./tools/cmd/mailer + +site: + go tool ssgod + +test: build + mkdir -p bin/tests + go test ./tests/... -c -o bin/tests + ./bin/tests/admin.test + ./bin/tests/auth.test + ./bin/tests/fakepay.test + ./bin/tests/paypal.test + ./bin/tests/shopping.test + + +test_only: cmds site + ./bin/tests.test -test.run $(TEST) + +migrate_up: + goose sqlite3 db.sqlite3 -dir migrations up + +migrate_down: + goose sqlite3 db.sqlite3 -dir migrations down + +docs: + pkgsite --open + +fix_ubuntu_ulimit: + @echo "Run this in your shell:" + @echo "ulimit -n 65536" + +tailwind: + tailwindcss --input ./static/input_style.css --output ./static/style.css + +tailwind_watch: + tailwindcss --input ./static/input_style.css --output ./static/style.css --watch=always + +tailwind_install: + curl -LO https://github.com/tailwindlabs/tailwindcss/releases/download/v4.1.12/tailwindcss-linux-x64 + chmod oug+x tailwindcss-linux-x64 + sudo mv tailwindcss-linux-x64 /usr/local/bin/tailwindcss + +dev: + go tool ozai + +coverage: + go build -cover -o webapp + mkdir -p .coverage + echo "GOCOVERDIR=.coverage ./webapp" + +cover_report: + go tool covdata textfmt -i=.coverage -o coverage.txt + go tool cover -func=coverage.txt + go tool cover -html=coverage.txt -o coverage.html + open coverage.html diff --git a/README.md b/README.md new file mode 100644 index 0000000..55fa180 --- /dev/null +++ b/README.md @@ -0,0 +1,627 @@ +# Go Web Starter Kit + +This is a fairly complete web development starter kit in Go. It tries to be as simple as possible +without leaving out modern features. The goal is to create a setup that a normal person can learn +and study core web technologies like the DOM and web servers. I would classify it as, "Old school +with modern things." + +## The Stack + +Currently I'm using the following components in a tastefully crafted stack similar to a Crepe Cake: + +* [goose](https://github.com/pressly/goose) -- This manages the database migrations. +* [sqlx](https://github.com/jmoiron/sqlx) -- This is the database driver. +* [squirrel](https://github.com/Masterminds/squirrel) -- This is the SQL query generator. +* [Fiber](https://gofiber.io/) -- This is the main web API and does most everything you need. +* [tailwind](https://tailwindcss.com/) -- This makes your sites perty and is easy to use, but I + reject the `@apply` slander and use `@apply` to give you nice things. +* [ssgod](https://lcthw.dev/go/ssgod) -- A static site generator I wrote that _only_ does static site generation and nothing else...unlike Hugo. +* [ozai](https://lcthw.dev/go/ozai) -- A process manager that replaced Air because Air went crazy like Hugo. +* [chromedp](https://github.com/chromedp/chromedp) -- This does your automated testing for you. + +I then add a few little "sweetener" APIs on top of this for simple things like, making the tests +nicer or making it easier to quickly return a page from a view. + +## Getting Started + +First, install a couple tools that'll be used everywhere, and that have huge dependencies you don't +actually need in your project: + +```shell +go install golang.org/x/pkgsite/cmd/pkgsite@latest +go install github.com/pressly/goose/v3/cmd/goose@latest +``` + +To start your own project do this: + +```shell +git clone https://lcthw.dev/go/go-web-starter-kit.git my-project +cd my-project +``` + +Then on Linux/OSX you want to delete the `.git` with this: + +```shell +rm -rf .git +mv LICENSE LICENSE.old # it's MIT +``` + +And on Windows you use the ever more clear and totally easier: + +```shell +rm -recurse -force .git +mv LICENSE LICENSE.old # it's MIT +``` + +Once you have that you can make it your own: + +```shell +git init . +go mod tidy +cp config_example.json config.json +make migrate_up +sqlite3 db.sqlite3 ".read tools/pragmas.sql" +make +make dev +``` + +This gets the site running and ready for development. You only need _to do this once._. The next +day that you want to work, cd to your project and only run `make dev`: + +```shell +make dev +``` + +## Linux Bug? + +I found that on Ubuntu the `tailwindcss` command "wouldn't run." Turns out when `tailwindcss` forks +it does the right thing and closes all possible open file descriptors, _but_ Ubuntu has set the hard +limit to 1 billion: + +```shell +$ ulimit -Hn +1073741816 +``` + +This is a _lot_ of files to try to close, so `tailwindcss` is actually stuck doing that. You can +fix this with: + +```shell +ulimit -n 65536 +``` + +You can pick any reasonable number, and then `tailwindcss` works like expected. + +## Configuration + +There's 3 basic moving parts to the whole system: `webapp`, `ssgod`, `tailwind`, and `ozai`. + +You can configure the `webapp` using the `config.json` which you copied over from `config_example.json`. The options are fairly self-explanatory. + +You can configure [ssgod](https://lcthw.dev/go/ssgod) using the +`ssgod.json` file. You'll notice that there's _two_ layouts with this setup, one for `webapp` +and another for `ssgod`. You can just point `ssgod` at your `views/layouts/main.html` file if you +want, but it seems people want two different layouts for their static site vs. "the app." + +You can configure `tailwind` using the `static/input_style.css` and editing the `Makefile` to have +it run how you want. I use the `@apply` heavily because I'm a programmer and no programmer would +ever tell someone they should sprinkle repetitive bullshit all over their HTML. Resist the +authority. Use `@apply`. + +Finally, you can configure other processes to run with [Ozai](https://lcthw.dev/go/ozai) in the +`.ozai.json` file. Why so many different formats? I'm still learning which is best to use and while +I like TOML I think I may go with `.json` files to reduce dependencies. You tell me though. + +## Ozai Autorestarts + +Ozai is a simpler tool that doesn't do auto restart. Instead it will create a little webserver at +`http://127.0.0.1:9999` with endpoints you can hit with curl to force a restart. Look in the +.ozai.json file to see what's configured. This makes it easy to simple add a `curl` call in your +build process and kick everything over. Look in the `Makefile` for how I do this. + +This works better than the way `Air` does it for a few reasons: + +1. You can run your build like normal in your own IDE or build tool and see your errors directly. + When you use other autobuild tools they have the errors so you can't access them. +2. You get an immediate restart after your build succeeds, rather than waiting for an external tool + to detect you made changes, run the build, and then restart your browser. +3. You avoid the "auto reload deadlock" where you run a build, the server is shutdown, but you hit + refresh too soon, so now your browser waits for an error, then you have to refresh again. Way +easier to just not use any of that. +4. No more silent failures hiding inside your terminal that you can't see. Just manually restart + it. + +For more, checkout the [Ozai Project](https://lcthw.dev/go/ozai"). + +## Tour of Directories + +The directories are organized in a way that separates "App Stuff" from "Content Stuff". + +* `admin` App The code for the built-in database admin tool. +* `bin` App Binaries that run your app like `webapp`. +* `features` App Where you put your features. +* `common`App Common helper functions. +* `config` App The configuration for your site, which is `config.json` loaded into Go structs. +* `data` App Your database stuff. You put your SQL models in here, and then add them to the bottom `Map` to +make them magically show up in the `/admin/table/` tool. +* `migrations` App When you use [goose](https://github.com/pressly/goose) it puts the migrations in here. +* `tests` App Your tests go in here. I use [chromedp](https://github.com/chromedp/chromedp) but the `chromedp` +API is too low level (and weird) to be useful so look in `tests/tools.go` for what I use. +* `tools` App Various admin automation tools go here. +* `views` Content This is where you put the _App_ contents, not the static content. Sadly, this + should be in `features/` but Fiber makes that too difficult. +* `emails` Content This where you put templates for emails you'll send. +* `pages` Content These are templates that are generated once and then served statically. +* `static` Static This is static content like `.js`, images, and `.css`. + +The following directories are considered "build junk" and you _should not_ commit them to your git. + +* `public` Junk This is generated by `ssgod` and then served by your `webapp`. Don't + edit anything in here, and instead edit in `pages` or `static`. +* `tmp` Junk This is made during the build/testing process. + +## Dev Workflow + +The first thing I do is run each of these commands in different terminals, either with tmux or just +using my fingers to run multiple tabs in PowerShell: + +```shell +make dev +``` + +### 1. Create a Feature + +The first step is to create a `feature`, which is nothing more than some files in a directory that +you edit to make your `pages/` actually work. You can create a feature like this: + +```shell +./bin/fgen -name myfeatue +``` + +This will create the files and directories you need to make a new feature: + +`features/myfeature/` +: This contains all of the go code. + +`views/myfeature/` +: This is where your HTML goes. + +`tests/myfeature/` +: This is where your tests go. + +Next you add it to `features/init.go` to enable it: + +```diff +@@ -8,2 +8,3 @@ import ( + "MY/webapp/features/fakepay" ++ "MY/webapp/features/myfeature" + ) +@@ -15,2 +16,3 @@ func Setup(app *fiber.App) { + features_fakepay.Setup(app) ++ features_myfeature.Setup(app) + } +``` + +> __NOTE__: I'm going to automate this in the future, so expect this file to be generated. + +After that run `make` to build everything again and you should have a new feature at +`http://127.0.0.1:7001/myfeature/` +with your browser. + +### 2. Create Initial Views + +The design of this system is that you do _not_ have to edit 16 files just get an idea going. You +can have an idea and create a single `.html` or `.md` file in `views/myfeature` to see it happen. This lets +you work out all of the URLs, page flows, layouts, and basic design before writing any more code. + +This is generally a better way to work than creating the backend models first as it constrains what +you create to only exactly what you need for the UI you'll implement. + +What I do is make a new file in `myfeature/views/`, cook up a quick 2D layout that's mostly what I want, then +make it link to other `myfeature/views/` to figure out the feature. Once I have a rough UI for the feature +worked out I move on to the next step. + +### Using the Tailwind Starter + +I've included [tailwind](https://tailwindcss.com/) in this setup, since it's decent at getting +things working quickly right in the HTML. The only thing I've fully rejected is the idea that +"@apply is bad m'kay." No, `@apply` makes it so I don't rage at all the idiots who think 92 +repeated CSS classes on every `div` is "good practice." + +> __NOTE__ You can view a sample page with all of these in [/examples/sample.html](/examples/sample.html) and you can look at the other files in `examples` to get an idea of what you can do. Some of these just use tailwind, others use my starter kit. + +In my setup there's a `static/input_style.css` that is used to generate a `static/style.css` and it +comes preconfigured with many of the things you'll need to get a page up and running. In theory +you can prototype a first page with just HTML and a bit of tailwind as needed. It also uses many of +the stock HTML tags like `aside` and `mark` so you can keep things nice. + +I've added 4 additional layout tags for you to use: + +* `grid` -- For stuff in a grid. Add `class="grid-cols-2"` from tailwind to change its layout. +* `block` -- A simple pre-configured vertical flex box. Put it around vertical stuff. +* `bar` -- A simple pre-configured horizontal flex box. Pit it around horizontal stuff. +* `stack` -- A simple way to stack stuff on top of other stuff. You know, like in every single 2d compositional system since the 1500s. +* `shape` -- A simple 2d box to use for placeholders where you'll put images. It's a lot quicker to drop a little `shape` than to go find an image. I think it also makes it easier to focus on the design. + + +### 3. Create Fake Data + +Create a fake set of data that comes from your page prototype. For example, if I have a User +Profile page then I might add this: + +```html + +``` + +This will give you something to work with while you sort out how the interactive parts of your page +will work. If you don't have any then you can skip this part. + +### 4. Refine the UI Interactions + +Using the fake data determine the user interactions for the view. Remember that this system is +designed to minimize the amount of work you need on the front-end, so all you're doing here is +simple things like validating a form, getting data, disabling/enabling fields, and anything that +stays _on one page_. If you find yourself trying to cram multiple pages into one then you've gone +too far. + +With my simple use-profile example I could create the function that renders the table on page load: + +```javascript +$boot(async() => { + const tmpl = $id('table-row'); + const target = $id('table-items'); + + for(let key in data) { + $append(target, + $render(tmpl, {key, value: data[key]})); + } +}); +``` + +This comes from my `jzed.js` file that's a minimalist old-school DOM helper. I also include +[lit.js](https://lit.dev/) if you prefer to create little components for things. + +### 5. Move the Fake Data to `api.go` + +You should be spending a lot of time working out the data and interactions in the nice convenience +of the page you're working on, but eventually that data needs to come from the server. To continue +the _User Profile_ example we can create a handler in `api.go` that returns this same fake data: + +```go +package features_myfeature + +import ( + "github.com/gofiber/fiber/v2" +) + +type UserProfile struct { + UserName string + Email string +} + +func GetApiUserProfile(c *fiber.Ctx) error { + profile := UserProfile{ + UserName: "Zed", + Email: "zed@zed.com", + } + + return c.JSON(profile) +} + +func SetupApi(app *fiber.App) { + app.Get("/api/myfeature/user_profile", GetApiUserProfile) +} +``` + +This is just enough code to get a simple JSON API going that we can load from the `index.html` +you've been editing. To grab the data just do this: + +```javascript + const [data, status] = await $get_json('/api/myfeature/user_profile'); + if($no_error(data, status)) { + // use it + } +``` + +In place of your prototype data. Doing that will get the data from the `api.go` code you just +wrote. + +### 6. Store the Data in `db.go` + +Once you've sorted out how the data is going to come from your API you can start to store it in the +database. The first step for that is to move your data into `db.go`: + +```go +package features_myfeature + +type UserProfile struct { + UserName string + Email string +} + +func GetUserProfile(id int) (UserProfile, error) { + profile := UserProfile{ + UserName: "John", + Email: "zed@zed.com", + } + + return profile, nil +} +``` + +The `UserProfile` is removed from `api.go` and placed in `db.go`. You then call your +`GetUserProfile` function to get it: + +```go +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func GetApiUserProfile(c *fiber.Ctx) error { + profile, err := GetUserProfile(1) + if err != nil { return IfErrNil(err, c) } + + return c.JSON(profile) +} +``` + +> __NOTE__: This is intended as a simplified way to _grow_ a feature from idea to working backend. +> Eventually you would want to create a separate module for your data models, create your tests for +> them, and other important design considerations. + +### 7. Move Hard Stuff to `views.go` + +There's some things that are too hard to do in JavaScript, but are very easy to do in `views.go` +usign the basic templates available. An example of this is defining the structure of a `` +tag. Doing this in JavaScript is a massive pain, but doing it with a template in `views.go` is +easy. Another example would be setting the `id` for some data object the page should display. It's +far easier to do that right in the template. + +I won't get into how this is done, but look at any of the examples in `features/` and `admin/` to +see me do this. + +### 8. Put it In The Database + +Once you have your data API worked out you can then use +[squirrel](https://github.com/Masterminds/squirrel), [goose](https://github.com/pressly/goose), and +[sqlx](https://github.com/jmoiron/sqlx) to make it store everything in the database. + +First you create a migration for your data: + +```shell +goose sqlite3 db.sqlite3 create create_user_profile sql -dir migrations +``` + +You then edit the `_create_user_profile.sql` file to create the new table: + +```sql +-- +goose Up +-- +goose StatementBegin +CREATE TABLE user_profile ( + username TEXT + email TEXT +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE user_profile; +-- +goose StatementEnd +``` + +You use `goose` to migrate the database up: + +```shell +goose sqlite3 db.sqlite3 -dir migrations up +``` + +If you make a mistake, you can migrate "down" to undo your last migration: + +```shell +goose sqlite3 db.sqlite3 -dir migrations down +``` + +I also have convenient `Makefile` actions for this: + +```shell +make migrate_up +make migrate_down +``` + +### 9. Rewrite `db.go` to Store It + +The next step needs refinement, so I'll only briefly describe it now: + +1. You have your data, so annotate it with `db: ""` struct tags. +2. Use the `squirrel` and `sqlx` APIs to store it. +3. Add your usual CRUD operations. + +I'm going to improve this so most of this can be automated, so stay tuned. For an example of doing +this look in `admin/table/db.go`. + +### 10. Refine, Refine, Refine + +Finally, nothing in this process is meant to be a lock-step one and done operation. This is simply a +mechanism to help people go from abstract idea to concrete working code with all the stages +necessary. Once you have everything "working" you'll need to refine it. The key to refinement is to +think about how this feature works with other features: + +1. Are you repeating data that some other feature has? Just use that feature's data operations then. +2. Are you repeating components that another feature has? Try making a `lit.js` component you both use. +3. Should you move the data used by many features into a single place? Look at `data/model.go`. + +You should also go over the API and page interactions in your feature, and when it's good move onto +the next feature. The only way to learn this step is to do it a lot, but in general, less is more. +If you've got 10k lines of code in a feature then rethink it. + +## Note on The Process for Pros + +This process is mostly for people who are learning how to build a web application. Once you've done +it this way for a few web apps then you can do it however works best for your idea. + +Some people's ideas are about the data, so starting with the UI like this may not work. If your +idea is about the data, start with the `api.go` and `db.go`, and then work the tests. + +Generally though, I've found that people who start with the backend are mostly only starting there +because that's what they know. They also tend to create glorious crystal palaces that are +completely unnecessary because they aren't grounded in the reality of a UI actual people need to +use. + +When you start with the UI can you can prototype all of the interactions, figure out the data, and +aim for only what you need. Keep doing this and you'll slowly build a nice data model with less +cruft for the application you're creating. + +## Additional Features + +## Sending Emails + +> __WARNING__: The email sending feature is currently very simple. Don't think you can send 200 +> million spam messages with it. + +The email system uses a [Redis]() queue to schedule messages, and an email router to actually +deliver them. The idea is that you don't want to wait for email crafting and delivery in your web +application most of the time. Ideally what you want to do is: + +1. In an `api.go` you receive a form or action from the user that needs an email. Say a password + reset. +2. You use the `common/email` module to craft a simple message and send it to the queue. Your + message at this stage is usually a very simple `struct` with the information your email router + needs to build the email. +3. In your `api.go` file _immediately return rather than wait for email delivery._ +4. Your email router then sits there and processes the email requests. When a new message comes in + it takes the data, queries your database, configures the templates, and finally sends it to the + email server. + +Since email is asynchronous there's no point in your web application waiting around for all of #4 to +be done. Just toss out a message on a queue and move on. + +### Running the `mailer` + +There's a simple router implemented in `tools/cmd/mailer` that you can run to get going. You can +use this to send simple emails but you should probably write a new one that handles your more +sophisticated emails like password resets and receipts. + +You can run it from the command line with: + +```shell +./bin/mailer +``` + +It will require that you install `redis` for it to work. + +### Testing Your Email Locally + +Running an email server locally is kind of a pain, and setting up everything so you can view sent +emails is even harder. That's way the awesome and fabulous [MailHog](https://github.com/mailhog/MailHog) exists. + +You can install it easily (it's written in Go) and then run it: + +```shell +MailHog +``` + +By default it opens an SMTP port on `1025` and a web server at 127.0.0.1:8025. If you point your +browser at 127.0.0.:8025 you'll get a fake email inbox. This inbox will show you both the HTML and +TEXT versions of your email, plus other useful things. + +### How To Send + +Here's an example of sending an email from a form submission in `features/email/api.go`. + +```go +package features_email + +import ( + email "MY/webapp/common/email" + "github.com/gofiber/fiber/v2" +) + +func PostApiEmailSend(c *fiber.Ctx) error { + go email.OneShotSend(email.EmailMessage{ + To: c.FormValue("To"), + From: c.FormValue("From"), + Subject: c.FormValue("Subject"), + Template: c.FormValue("Template"), + }) + + return c.Redirect("/email/") +} + +func SetupApi(app *fiber.App) { + app.Post("/api/email/send", PostApiEmailSend) +} +``` + +### Email Templates + +The templates use the same default `text/template` engine that the rest of the system uses, but you +should use Markdown to write them. This automatically gives you both a nice text format (Markdown +already is like an email) and an HTML output. Look at `emails/signup.md` for a simple example. + +## Receiving Payments + +Coming soon... + +## FAQ + +Here's some questions I get when people see this. + +### What if My Email Templates Need HTML? + +You should be able to work with the code in `common/email` to make it do what you want. I don't +think it's specifically looking for any extension, but I haven't tested it. Try just dropping the +`.html` you want into the `emails/` directory and sending it. + +You should also know that really complex HTML usually get filtered, so it's best to keep it simple +HTML and Markdown will help you stick to that. + +### Isn't Fiber Banned?! + +First off, nobody has the right to "ban" a project. If you're hanging out in the Go discord and +you've seen Fiber on some ban list then whoever did that is a fucking asshole. Just ignore that +bullshit and use the best tech you can. + +Second, if you're only supposed to use the Go standard library then why [is there a whole fucking +document on the official go website explaining how to use Gin to make an API?](https://go.dev/doc/tutorial/web-service-gin). It seems like whoever is claiming that you are only allowed to use the Go standard library is in disagreement with the _actual fucking Go project_. + +Finally, you don't have to do what you're told, especially when the person telling you what to do is +some random asshole hiding in a chat room being a random asshole. Use what you want, and Fiber is +in that sweet spot of being a nice API that isn't slow dogshit like [Gin](https://www.techempower.com/benchmarks/). + +### Why Not Gin? + +Gin is a piece of crap, that's why. Look at the [Techempower Benchmarks](https://www.techempower.com/benchmarks/) to get an idea of how bad Gin is. It's at the _bottom_ of the list, performing even _worse_ that some of the slowest _Ruby_ web frameworks out there. Make a _compiled language_ like Go perform that bad takes a special kind of incompetence. + +### Why Not Only the Go Standard Library? + +Because I like nice things, and while the Go Standard Library has everything you _need_, it +frequently is missing things you _want_. This project is about adding the things you'll probably +want without getting to abstract and far away from learning the core web technologies. + +### Are Your Tags "Accessible"?! What about SEO?! + +Yes, I actually tested all of this with [NV Access](https://www.nvaccess.org/) and the only thing NV +Access seems to have a problem with is the `pre` and `code` tags. That's because apparently those +are deemed as "images" so they get ignored...which is about the dumbest fucking shit I've ever +heard. I'm working on a way to fix that. + +Anyone telling you that my `grid`, `bar`, `block`, or `stack` tags impact accessibility most likely +has never ran NV Access one time so they're just wrong. Additionally, it's better to have these be +_ignored_ by screen readers because they're just 2D layout junk, so they're kind of irrelevant to a +linear 1D screen reader. + +Finally, SEO isn't impacted because Google has literally said HTML quality doesn't matter for SEO +ranking. Think about it, if Google went around dictating exact HTML they would get in so much +Monopoly trouble. Instead they tend to focus more on content and organization, and I believe the +official quote is, "Making everyone use the same HTML would make the web boring." + +However, take this with a grain of salt because the same Google people who've said this also said +that backlinks didn't impact performance and many SEO experts say this is totally not true. Do your +own testing, and if it impacts your SEO than just change them after you get your initial design up. + diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..cc8f8c4 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,3 @@ +* The qmgr needs to actually manage the queue, currently it's just a little testing tool. +* Probably also need an email testing tool that can send sample emails off the cli. +* Try to remove code.js and either bring the functionality to jzed.js or not use it. diff --git a/common/api.go b/common/api.go new file mode 100644 index 0000000..a558d6b --- /dev/null +++ b/common/api.go @@ -0,0 +1,75 @@ +package common + +import ( + "log" + "reflect" + "github.com/gofiber/fiber/v2" + "github.com/go-playground/validator/v10" +) + +type Failure struct { + Message string `json:"message"` + Status int +} + +func IfErrNil(err error, c *fiber.Ctx) error { + if err != nil { + log.Output(10, err.Error()) + status := fiber.StatusInternalServerError + c.SendStatus(status) + return c.JSON(Failure{err.Error(), status}) + } else { + return err + } +} + +func ReceivePost[T any](c *fiber.Ctx) (*T, error) { + var result *T + result = new(T) + + if err := c.BodyParser(result); err != nil { + log.Println(err); + return result, err + } + + var validate *validator.Validate + validate = validator.New(validator.WithRequiredStructEnabled()) + + if err := validate.Struct(result); err != nil { + validationErrors := err.(validator.ValidationErrors) + for _, validerr := range validationErrors { + log.Println(validerr.Field(), validerr.Error()) + } + + return result, err + } + + return result, nil +} + +func ReflectOnPost(typeOf reflect.Type, c *fiber.Ctx) (reflect.Value, error) { + var result_val reflect.Value + + result_val = reflect.New(typeOf) + result := result_val.Interface() + + if err := c.BodyParser(result) + + err != nil { + log.Println(err); + return result_val, err + } + + var validate *validator.Validate + validate = validator.New(validator.WithRequiredStructEnabled()) + + err := validate.Struct(result) + + if err != nil { + validationErrors := err.(validator.ValidationErrors) + log.Println(validationErrors) + return result_val, err + } + + return result_val, nil +} diff --git a/common/auth.go b/common/auth.go new file mode 100644 index 0000000..194ff9b --- /dev/null +++ b/common/auth.go @@ -0,0 +1,39 @@ +package common + +import ( + "errors" + "log" + + "github.com/gofiber/fiber/v2" + _ "github.com/mattn/go-sqlite3" + "github.com/gofiber/fiber/v2/middleware/session" + + "MY/webapp/data" + "MY/webapp/config" +) + +func IsAdmin(user *data.User) bool { + return user.Username == config.Settings.Server.Admin +} + +func AuthCheck(c *fiber.Ctx, needs_admin bool) (*session.Session, error) { + sess, err := STORE.Get(c) + if err != nil { return sess, err } + + // BUG: this has to come from the databse, just temporary + admin := sess.Get("admin") == true + authed := sess.Get("authenticated") == true + + if needs_admin { + authed = admin && authed + log.Printf("after needs_admin block: authed=%v", authed) + } + + if authed { + log.Println("user is authed, return nil and sess") + return sess, nil + } else { + log.Println("user is NOT authed, return error") + return sess, errors.New("Authentication, permission failure") + } +} diff --git a/common/email/api.go b/common/email/api.go new file mode 100644 index 0000000..a6defcb --- /dev/null +++ b/common/email/api.go @@ -0,0 +1,167 @@ +package common_email + +import ( + "github.com/wneessen/go-mail" + "encoding/json" + "context" + "log" + "github.com/redis/go-redis/v9" + "github.com/yuin/goldmark" + "MY/webapp/config" + "path/filepath" + "text/template" + "os" + "strings" +) + +func NewSender(ctx context.Context) (Sender){ + client := redis.NewClient(&redis.Options{ + Addr: config.Settings.Redis.HostPort, + Password: config.Settings.Redis.Password, + DB: config.Settings.Redis.DB, + }) + + return Sender{client, ctx} +} + +func NewRouter(ctx context.Context) (Router, error) { + var router Router + var err error + + router.ctx = ctx + + router.redis_client = redis.NewClient(&redis.Options{ + Addr: config.Settings.Redis.HostPort, + Password: config.Settings.Redis.Password, + DB: config.Settings.Redis.DB, + }) + + router.smtp_client, err = mail.NewClient(config.Settings.Email.Host, + mail.WithPort(config.Settings.Email.Port), + mail.WithTLSPolicy(mail.NoTLS)) + + return router, err +} + +func (router *Router) Close() { + router.redis_client.Close() + router.smtp_client.Close() +} + +func (sender *Sender) Close() { + sender.redis_client.Close() +} + +func (router *Router) Render(tmpl_path string, data any) (string, string, error) { + tmpl_path = filepath.Join(config.Settings.Email.Templates, tmpl_path) + + // load the markdown file + md_file, err := os.ReadFile(tmpl_path) + if err != nil { return "", "", err } + + // template it + tmpl, err := template.New(tmpl_path).Parse(string(md_file)) + if err != nil { return "", "", err } + + out := new(strings.Builder) + err = tmpl.Execute(out, data) + if err != nil { return "", "", err } + text_out := out.String() + + // convert to html + out.Reset() + err = goldmark.Convert([]byte(text_out), out) + if err != nil { return "", "", err } + + html_out := out.String() + + // return the template .md as plain text and .html as html + return string(text_out), string(html_out), nil +} + +func (router *Router) DeliverEmail(msg EmailMessage) error { + email_msg := mail.NewMsg() + err := email_msg.From(msg.From) + if err != nil { return err } + + err = email_msg.To(msg.To) + if err != nil { return err } + + email_msg.Subject(msg.Subject) + + if config.Settings.Email.XMailer != "" { + email_msg.SetGenHeader(mail.HeaderXMailer, config.Settings.Email.XMailer) + } + + if config.Settings.Email.UserAgent != "" { + email_msg.SetGenHeader(mail.HeaderUserAgent, config.Settings.Email.UserAgent) + } + + log.Println("template is", msg.Template) + text, html, err := router.Render(msg.Template, msg) + if err != nil { return err } + + email_msg.SetBodyString(mail.TypeTextHTML, html) + email_msg.AddAlternativeString(mail.TypeTextPlain, text) + + err = router.smtp_client.DialAndSendWithContext(router.ctx, email_msg) + if err != nil { return err } + + return nil +} + +func (router *Router) ReceiveEmail() (EmailMessage, error) { + var msg EmailMessage + + result, err := router.redis_client.BRPop( + router.ctx, 0, + config.Settings.Email.RedisQueue).Result() + if err != nil { return msg, err } + + // NOTE: 0=queue name, 1=message + err = json.Unmarshal([]byte(result[1]), &msg) + if err != nil { return msg, err } + + return msg, nil +} + +func (router *Router) HandleEmailRequest() error { + msg, err := router.ReceiveEmail() + if err != nil { return err } + + err = router.DeliverEmail(msg) + if err != nil { return err } + + return nil +} + +func (sender *Sender) QueueEmail(msg EmailMessage) error { + + log.Println("email msg", msg) + msg_json, err := json.Marshal(msg) + if err != nil { return err } + + _, err = sender.redis_client.LPush( + sender.ctx, + config.Settings.Email.RedisQueue, + string(msg_json)).Result() + if err != nil { return err } + + return nil +} + +// Intended to be fired off on a goroutine and +// forgotten about. +func OneShotSend(msg EmailMessage) { + ctx := context.Background() + + sender := NewSender(ctx) + defer sender.Close() + + err := sender.QueueEmail(msg) + + if err != nil { + log.Print(err) + } +} + diff --git a/common/email/data.go b/common/email/data.go new file mode 100644 index 0000000..058ff20 --- /dev/null +++ b/common/email/data.go @@ -0,0 +1,28 @@ +package common_email + +import ( + "github.com/redis/go-redis/v9" + "github.com/wneessen/go-mail" + "context" + +) + +type EmailMessage struct { + To string + From string + Subject string + Template string + Data any +} + +type Sender struct { + redis_client *redis.Client + ctx context.Context +} + +type Router struct { + redis_client *redis.Client + smtp_client *mail.Client + ctx context.Context +} + diff --git a/common/errors.go b/common/errors.go new file mode 100644 index 0000000..5a18f03 --- /dev/null +++ b/common/errors.go @@ -0,0 +1,29 @@ +package common + +import ( + "log" + "fmt" + "github.com/gofiber/fiber/v2" +) + +func Fail(err error, format string, v ...any) error { + err_format := fmt.Sprintf("ERROR: %v; %s", err, format) + log.Printf(err_format, v...) + return err +} + +func ApiError(c *fiber.Ctx, format string, args ...any) error { + c.Status(500) + + log.Printf(format, args...) + + return c.JSON(fiber.Map{ + "error": fmt.Sprintf(format, args...), + }) +} + +func RenderError(c *fiber.Ctx, format string, args ...any) error { + return c.Render("error", fiber.Map{ + "Error": fmt.Sprintf(format, args...), + }) +} diff --git a/common/web.go b/common/web.go new file mode 100644 index 0000000..e1f8173 --- /dev/null +++ b/common/web.go @@ -0,0 +1,108 @@ +package common + +import ( + "strings" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/session" + "io/fs" + "path/filepath" + "fmt" +) + +var STORE *session.Store + +func GenPageId(path string) string { + return strings.ReplaceAll(path, "/", "-") + "-page" +} + +func AddAuthedPage(app *fiber.App, must_admin bool, url string, view string) { + handler := func(c *fiber.Ctx) error { + _, err := AuthCheck(c, must_admin) + if err != nil { return c.Redirect("/") } + params := c.AllParams() + params["PageId"] = GenPageId(url) + + return c.Render(view, params) + } + + app.Get(url, handler) +} + +func AddPage(app *fiber.App, url string, view string) { + handler := func(c *fiber.Ctx) error { + params := c.AllParams() + params["PageId"] = GenPageId(url) + + return c.Render(view, c.AllParams()) + } + + app.Get(url, handler) +} + +func Page(path string) (func(c *fiber.Ctx) error) { + page_id := GenPageId(path) + + return func (c *fiber.Ctx) error { + return c.Render(path, fiber.Map{"PageId": page_id}) + } +} + +func SplitRouteTemplate(path string) (string, string) { + path = filepath.ToSlash(filepath.Clean(path)) + path, found := strings.CutPrefix(path, "views/") + if !found { + fmt.Println("no views/ prefix?", path) + } + + ext := filepath.Ext(path) + source_name, _ := strings.CutSuffix(path, ext) + split_path := strings.Split(source_name, "/") + + var route string + page := strings.Join(split_path, "/") + last := split_path[len(split_path) - 1] + + if last == "index" { + // it's an index.html so route doesn't include it + // WARN: page already has the leading / + route = fmt.Sprintf("/%s/", filepath.Dir(page)) + } else { + route = fmt.Sprintf("/%s", page) + } + + return route, page +} + +func ConfigViews(app *fiber.App, path string) error { + route_map := make(map[string]string, 10) + + for _, route := range app.GetRoutes() { + if route.Method == "GET" { + route_map[route.Path] = route.Method + } + } + + err := filepath.WalkDir(path, + func(path string, d fs.DirEntry, err error) error { + if err != nil { return err } + + if !d.IsDir() && strings.HasSuffix(path, "html") { + route, page := SplitRouteTemplate(path) + _, exists := route_map[route] + + if exists { + fmt.Println("ROUTE ", route, "Already exists, skipping", page) + } else { + fmt.Println("ROUTE ", route, "does not conflict page", page) + AddPage(app, route, page) + + // update the route map to avoid dupes + route_map[route] = "GET" + } + } + + return nil + }) + + return err +} diff --git a/config/settings.go b/config/settings.go new file mode 100644 index 0000000..f34c281 --- /dev/null +++ b/config/settings.go @@ -0,0 +1,54 @@ +package config + +import ( + "log" + "encoding/json" + "os" +) + +type config struct { + Server struct { + Admin string + Views string + Layouts string + HostPort string + } + Database struct { + Driver string + Url string + } + Redis struct { + HostPort string + Password string + DB int + } + Email struct { + Host string + Port int + XMailer string + UserAgent string + RedisQueue string + Templates string + } + Paypal struct { + ClientID string + SecretID string + URL string + } +} + +var Settings config + +func Load(path string) { + data, err := os.ReadFile(path) + + if err != nil { + log.Fatalf("error loading %s: %v", path, err) + } + + err = json.Unmarshal(data, &Settings) + + if err != nil { + log.Fatalf("error parsing %s: %v", path, err) + } +} diff --git a/config_example.json b/config_example.json new file mode 100644 index 0000000..acad274 --- /dev/null +++ b/config_example.json @@ -0,0 +1,29 @@ +{ + "Server": { + "Admin": "admin", + "Views": "./views", + "Layouts": "layouts/main", + "HostPort": "127.0.0.1:7001" + }, + "Database": { + "Driver": "sqlite3", + "Url": "db.sqlite3" + }, + "Redis": { + "HostPort": "localhost:6379", + "Password": "", + "DB": 0 + }, + "Email": { + "Host": "localhost", + "Port": 1025, + "XMailer": "nunya-business", + "UserAgent": "nunya-business", + "RedisQueue": "email", + "Templates": "emails" + }, + "Paypal": { + "ClientID": "test-client-id", + "SecretID": "test-secret" + } +} diff --git a/data/crud.go b/data/crud.go new file mode 100644 index 0000000..d8eb762 --- /dev/null +++ b/data/crud.go @@ -0,0 +1,59 @@ +package data + +import ( + "log" + "database/sql" + "github.com/gofiber/fiber/v2" + _ "github.com/mattn/go-sqlite3" + "github.com/jmoiron/sqlx" + ) + +var configured bool +var DB *sqlx.DB + +func Setup(driver string, url string) { + if(!configured) { + var err error + + DB, err = sqlx.Connect(driver, url) + if err != nil { + log.Fatalln(err) + } + configured = true; + } +} + +func Shutdown() { + DB.Close() +} + +func SelectJson[T any](c *fiber.Ctx, err error, sql string, args ...interface{}) error { + // BUG: add a precondition that aborts if array of interfaces to avoid "unsupported $1 array of interfaces" + var result []T + if err != nil { goto fail } + + err = DB.Select(&result, sql, args...) + if err != nil { goto fail } + + return c.JSON(&result) + +fail: return err +} + +func GetJson[T any](c *fiber.Ctx, err error, sql string, args ...interface{}) error { + var result T + if err != nil { goto fail } + + err = DB.Get(&result, sql, args...) + if err != nil { goto fail } + + return c.JSON(&result) + +fail: return err +} + +func Exec(err error, sql_query string, args ...interface{}) (sql.Result, error) { + if err != nil { return nil, err } + result, err := DB.Exec(sql_query, args...) + return result, err +} diff --git a/data/models.go b/data/models.go new file mode 100644 index 0000000..88c491d --- /dev/null +++ b/data/models.go @@ -0,0 +1,56 @@ +package data + +import ( + "reflect" + "github.com/guregu/null/v6" +) + +type Login struct { + Username string `db:"username" validate:"required,max=30"` + Password string `db:"password" validate:"required,max=128"` +} + +type User struct { + Id int `db:"id" validate:"numeric"` + Username string `db:"username" validate:"required,max=30"` + Email string `db:"email" validate:"required,email,max=128"` + Password string `db:"password" validate:"required,min=8,max=64"` +} + +/* + * Example of using the null library to do optional fields. + */ +type NullExample struct { + Id int `db:"id" validate:"numeric"` + HasMaybe null.Int `db:"replying_to" validate:"omitempty,numeric"` +} + +type Product struct { + Id int `db:"id" validate:"numeric"` + Title string `db:"title" validate:"required"` + Description string `db:"description" validate:"required"` + Price float64 `db:"price" validate:"required"` + Slug string `db:"slug" validate:"required"` +} + +type CartItem struct { + Id int `db:"id" validate:"numeric"` + UserId int `db:"user_id" validate:"numeric,required"` + ProductId int `db:"product_id" validate:"required"` + Quantity int `db:"quantity" validate:"numeric"` +} + +type Cart struct { + Items []CartItem +} + +func Models() map[string]reflect.Type { + return map[string]reflect.Type{ + "user": reflect.TypeFor[User](), + "product": reflect.TypeFor[Product](), + "cart_item": reflect.TypeFor[CartItem](), + "null_example": reflect.TypeFor[NullExample](), + } +} + + diff --git a/emails/signup.md b/emails/signup.md new file mode 100644 index 0000000..aa2e1f9 --- /dev/null +++ b/emails/signup.md @@ -0,0 +1,10 @@ +Welcome +======= + +Welcome to my website! Here's what you sent: + +* {{ .From }} +* {{ .To }} +* {{ .Data.Name }} +* {{ .Data.Pet }} + diff --git a/features/admin/api.go b/features/admin/api.go new file mode 100644 index 0000000..bca9b08 --- /dev/null +++ b/features/admin/api.go @@ -0,0 +1,155 @@ +package features_admin + +import ( + "maps" + "reflect" + "fmt" + "github.com/gofiber/fiber/v2" + "MY/webapp/data" + . "MY/webapp/common" +) + +func GetApiTableIndex(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + var tables []string + + for k := range maps.Keys(data.Models()) { + tables = append(tables, k) + } + + return c.JSON(tables) +} + +func GetApiSelectAll(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + table := c.Params("table") + if table == "" { + return c.Redirect("/admin/table/") + } + + page := c.QueryInt("page", 0) + if page < 0 { page = 0 } + + search := c.Query("search", "") + var result []any + + if search == "" { + result, err = SelectTable(table, 20, uint64(page)); + if err != nil { return IfErrNil(err, c) } + } else { + // NOTE: need a 404 here when there's no result? or empty list? + result, err = SearchTable(search, table, 20, uint64(page)); + if err != nil { return IfErrNil(err, c) } + } + + return c.JSON(result) +} + +func GetApiSelectOne(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + table := c.Params("table") + id, err := c.ParamsInt("id", -1) + if err != nil || id < 0 { return IfErrNil(err, c) } + + result, err := Get(table, int64(id)) + if err != nil { return IfErrNil(err, c) } + + return c.JSON(result.Interface()) +} + +func PostApiUpdate(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { + return ApiError(c, "Auth required.") + } + + table := c.Params("table") + typeOf, ok := data.Models()[table] + if !ok { + return ApiError(c, "Table does not exist") + } + + obj, err := ReflectOnPost(typeOf, c) + if err != nil { + return ApiError(c, fmt.Sprintf("Invalid format: %v", err)) + } + + id, err := Update(table, obj.Elem()) + if err != nil { + return ApiError(c, "Update failed") + } + + return c.JSON(fiber.Map{"table": table, "id": id}) +} + +func GetApiInsert(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + table := c.Params("table") + // check that this table exists in the model + typeOf, ok := data.Models()[table] + + if !ok { + return ApiError(c, "admin table %s does not exist", table) + } + + result := reflect.New(typeOf) + + return c.JSON(result.Interface()) +} + +func PostApiInsert(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { + return ApiError(c, "login required") + } + + table := c.Params("table") + + typeOf := data.Models()[table] + obj, err := ReflectOnPost(typeOf, c) + + if err != nil { + return ApiError(c, "failed reflect") + } + + id, _, err := Insert(table, obj.Elem()) + + if err != nil { + return ApiError(c, "failed insert") + } + + return c.JSON(fiber.Map{ "id": id, "table": table}) +} + +func DeleteApi(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + table := c.Params("table") + + id, err := c.ParamsInt("id", -1) + if err != nil || id < 0 { return IfErrNil(err, c) } + + err = Delete(table, int64(id)) + if err != nil { return IfErrNil(err, c) } + + return c.JSON(fiber.Map{}) +} + +func SetupApi(app *fiber.App) { + app.Get("/api/admin/table", GetApiTableIndex) + app.Get("/api/admin/table/:table", GetApiSelectAll) + app.Get("/api/admin/table/new/:table", GetApiInsert) + app.Post("/api/admin/table/new/:table", PostApiInsert) + app.Get("/api/admin/table/:table/:id", GetApiSelectOne) + app.Post("/api/admin/table/:table/:id", PostApiUpdate) + app.Delete("/api/admin/table/:table/:id", DeleteApi) +} diff --git a/features/admin/init.go b/features/admin/init.go new file mode 100644 index 0000000..a7b44ae --- /dev/null +++ b/features/admin/init.go @@ -0,0 +1,11 @@ +package features_admin + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupPages(app) +} + diff --git a/features/admin/views.go b/features/admin/views.go new file mode 100644 index 0000000..32ca759 --- /dev/null +++ b/features/admin/views.go @@ -0,0 +1,51 @@ +package features_admin + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func GetPageSelectOne(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + table := c.Params("table") + id, err := c.ParamsInt("id", -1) + + if err != nil || id < 0 { + // make a way to return an error here + return RenderError(c, "Invalid id %d", id) + } + + return c.Render("admin/table/view", fiber.Map{ + "table": table, + "id": id, + }) +} + +func GetPageContent(c *fiber.Ctx) error { + _, err := AuthCheck(c, true) + if err != nil { return c.Redirect("/") } + + table := c.Params("table") + + headers, err := Schema(table) + + if err != nil { + return ApiError(c, "Invalid table") + } + + return c.Render("admin/table/contents", fiber.Map{ + "table": table, + "headers": headers, + }) +} + +func SetupPages(app *fiber.App) { + AddAuthedPage(app, true, "admin/table/", "admin/table/index") + AddAuthedPage(app, true, "admin/table/new/:table/", "admin/table/new") + AddAuthedPage(app, true, "admin/", "admin/index") + + app.Get("admin/table/:table/", GetPageContent) + app.Get("/admin/table/:table/:id/", GetPageSelectOne) +} diff --git a/features/auth/api.go b/features/auth/api.go new file mode 100644 index 0000000..060ee67 --- /dev/null +++ b/features/auth/api.go @@ -0,0 +1,80 @@ +package features_auth + +import ( + "github.com/gofiber/fiber/v2" + _ "github.com/mattn/go-sqlite3" + sq "github.com/Masterminds/squirrel" + "log" + + "MY/webapp/data" + . "MY/webapp/common" +) + +func GetApiAuthCheck(c *fiber.Ctx) error { + _, err := AuthCheck(c, false) + // auth failure or not authed is determined by err, with nil meaning YES AUTHED + return c.JSON(fiber.Map{"is_authed": err == nil}) +} + +func GetApiLogout(c *fiber.Ctx) error { + err := LogoutUser(c) + if err != nil { return IfErrNil(err, c) } + + return c.Redirect("/") +} + +func PostApiRegister(c *fiber.Ctx) error { + user, err := ReceivePost[data.User](c) + if err != nil { return IfErrNil(err, c) } + + err = SetUserPassword(user) + if err != nil { return IfErrNil(err, c) } + + sql, args, err := sq.Insert("user"). + Columns("username", "email", "password"). + Values(user.Username, user.Email, user.Password).ToSql() + + _, err = data.Exec(err, sql, args...) + if err != nil { return IfErrNil(err, c) } + + return c.Redirect("/login/") +} + +func PostApiLogin(c *fiber.Ctx) error { + var user data.User + + login, err := ReceivePost[data.Login](c) + if(err != nil) { + return ApiError(c, "Invalid login form.") + } + + pass_good, err := LoginUser(&user, login) + + if pass_good { + sess, err := STORE.Get(c) + if err != nil { return IfErrNil(err, c) } + + sess.Set("user_id", user.Id) + sess.Set("authenticated", true) + sess.Set("admin", IsAdmin(&user)) + + err = sess.Save() + if err != nil { + return ApiError(c, "Server Failure in Session.") + } + + return c.JSON(fiber.Map{"valid": true}) + } else { + // custom auth error + if(err != nil) { log.Printf("Error in login: %v", err) } + c.Status(401) + return c.JSON(fiber.Map{"error": "Invalid login."}) + } +} + +func SetupApi(app *fiber.App) { + app.Get("/api/authcheck", GetApiAuthCheck) + app.Get("/api/logout", GetApiLogout) + app.Post("/api/register", PostApiRegister) + app.Post("/api/login", PostApiLogin) +} diff --git a/features/auth/init.go b/features/auth/init.go new file mode 100644 index 0000000..185a36d --- /dev/null +++ b/features/auth/init.go @@ -0,0 +1,9 @@ +package features_auth + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) +} diff --git a/features/email/api.go b/features/email/api.go new file mode 100644 index 0000000..81751ab --- /dev/null +++ b/features/email/api.go @@ -0,0 +1,22 @@ +package features_email + +import ( + email "MY/webapp/common/email" + "github.com/gofiber/fiber/v2" +) + + +func PostApiEmailSend(c *fiber.Ctx) error { + go email.OneShotSend(email.EmailMessage{ + To: c.FormValue("To"), + From: c.FormValue("From"), + Subject: c.FormValue("Subject"), + Template: c.FormValue("Template"), + }) + + return c.Redirect("/email/") +} + +func SetupApi(app *fiber.App) { + app.Post("/api/email/send", PostApiEmailSend) +} diff --git a/features/email/init.go b/features/email/init.go new file mode 100644 index 0000000..9911a51 --- /dev/null +++ b/features/email/init.go @@ -0,0 +1,10 @@ +package features_email + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupViews(app) +} diff --git a/features/email/views.go b/features/email/views.go new file mode 100644 index 0000000..bde12eb --- /dev/null +++ b/features/email/views.go @@ -0,0 +1,11 @@ +package features_email + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func SetupViews(app *fiber.App) { + err := ConfigViews(app, "views/email") + if err != nil { panic(err) } +} diff --git a/features/fakepay/api.go b/features/fakepay/api.go new file mode 100644 index 0000000..070e133 --- /dev/null +++ b/features/fakepay/api.go @@ -0,0 +1,13 @@ +package features_fakepay + +import ( + "github.com/gofiber/fiber/v2" +) + +func PostApiPay(c *fiber.Ctx) error { + return c.Redirect("/fakepay/complete") +} + +func SetupApi(app *fiber.App) { + app.Post("/api/fakepay/pay", PostApiPay) +} diff --git a/features/fakepay/init.go b/features/fakepay/init.go new file mode 100644 index 0000000..c96dea7 --- /dev/null +++ b/features/fakepay/init.go @@ -0,0 +1,10 @@ +package features_fakepay + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupViews(app) +} diff --git a/features/fakepay/views.go b/features/fakepay/views.go new file mode 100644 index 0000000..4614a2a --- /dev/null +++ b/features/fakepay/views.go @@ -0,0 +1,11 @@ +package features_fakepay + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func SetupViews(app *fiber.App) { + err := ConfigViews(app, "views/fakepay") + if err != nil { panic(err) } +} diff --git a/features/init.go b/features/init.go new file mode 100644 index 0000000..1a4a6c1 --- /dev/null +++ b/features/init.go @@ -0,0 +1,22 @@ +package features + +import ( + "github.com/gofiber/fiber/v2" + "MY/webapp/features/email" + "MY/webapp/features/paypal" + "MY/webapp/features/shopping" + "MY/webapp/features/fakepay" + "MY/webapp/features/admin" + "MY/webapp/features/auth" + "MY/webapp/features/survey" +) + +func Setup(app *fiber.App) { + features_auth.Setup(app) + features_admin.Setup(app) + features_email.Setup(app) + features_paypal.Setup(app) + features_shopping.Setup(app) + features_fakepay.Setup(app) + features_survey.Setup(app) +} diff --git a/features/paypal/api.go b/features/paypal/api.go new file mode 100644 index 0000000..a55fc30 --- /dev/null +++ b/features/paypal/api.go @@ -0,0 +1,78 @@ +package features_paypal + +import ( + "github.com/gofiber/fiber/v2" + "github.com/plutov/paypal/v4" + "os" + "context" + . "MY/webapp/common" + config "MY/webapp/config" + "fmt" +) + +func CreatePaypal() (*paypal.Client, error) { + return paypal.NewClient( + config.Settings.Paypal.ClientID, + config.Settings.Paypal.SecretID, + config.Settings.Paypal.URL) // or paypal.APIBaseLive +} + +func PostApiOrder(c *fiber.Ctx) error { + pay, err := CreatePaypal() + + if err != nil { return IfErrNil(err, c) } + + pay.SetLog(os.Stdout) + + units := []paypal.PurchaseUnitRequest{ + { + ReferenceID: "myinternalid1", + Amount: &paypal.PurchaseUnitAmount{ + Currency: "USD", + Value: "10.99", + }, + Description: "Product description", + Items: []paypal.Item{ + { + Name: "Learn Go the Hard Way", + UnitAmount: &paypal.Money{ + Currency: "USD", + Value: "10.99", + }, + Quantity: "1", + }, + }, + }, + } + + source := &paypal.PaymentSource{} + appCtx := &paypal.ApplicationContext{} + + order, err := pay.CreateOrder(context.TODO(), paypal.OrderIntentCapture, units, source, appCtx) + + fmt.Println("ORDER", order) + + return c.JSON(order) +} + +func PostApiOrderCapture(c *fiber.Ctx) error { + orderID := c.Params("orderID") + + fmt.Println("POST ORDER CAPTURE", orderID) + pay, err := CreatePaypal() + if err != nil { return IfErrNil(err, c) } + + capture, err := pay.CaptureOrder(context.TODO(), orderID, paypal.CaptureOrderRequest{}) + if err != nil { return IfErrNil(err, c) } + + fmt.Println("CAPTURE", capture) + + return c.JSON(fiber.Map{"status": "ok"}) +} + +func SetupApi(app *fiber.App) { + app.Post("/api/paypal/order", PostApiOrder) + app.Post("/api/paypal/order/:orderID/capture", PostApiOrderCapture) +} + + diff --git a/features/paypal/api.js b/features/paypal/api.js new file mode 100644 index 0000000..f8c704e --- /dev/null +++ b/features/paypal/api.js @@ -0,0 +1,160 @@ +import express from "express"; +import "dotenv/config"; +import { + ApiError, + CheckoutPaymentIntent, + Client, + Environment, + LogLevel, + OrdersController, + PaymentsController, + PaypalExperienceLandingPage, + PaypalExperienceUserAction, + ShippingPreference, +} from "@paypal/paypal-server-sdk"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const { + PAYPAL_CLIENT_ID, + PAYPAL_CLIENT_SECRET, + PORT = 8080, +} = process.env; + +const client = new Client({ + clientCredentialsAuthCredentials: { + oAuthClientId: PAYPAL_CLIENT_ID, + oAuthClientSecret: PAYPAL_CLIENT_SECRET, + }, + timeout: 0, + environment: Environment.Sandbox, + logging: { + logLevel: LogLevel.Info, + logRequest: { logBody: true }, + logResponse: { logHeaders: true }, + }, +}); + +const ordersController = new OrdersController(client); +const paymentsController = new PaymentsController(client); + + +/** + * Create an order to start the transaction. + * @see https://developer.paypal.com/docs/api/orders/v2/#orders_create + */ +const createOrder = async (cart) => { + const collect = { + body: { + intent: "CAPTURE", + purchaseUnits: [ + { + amount: { + currencyCode: "USD", + value: "100", + breakdown: { + itemTotal: { + currencyCode: "USD", + value: "100", + }, + }, + }, + // lookup item details in `cart` from database + items: [ + { + name: "T-Shirt", + unitAmount: { + currencyCode: "USD", + value: "100", + }, + quantity: "1", + description: "Super Fresh Shirt", + sku: "sku01", + }, + ], + }, + ], + }, + prefer: "return=minimal", + }; + + + try { + const { body, ...httpResponse } = await ordersController.createOrder( + collect + ); + // Get more response info... + // const { statusCode, headers } = httpResponse; + return { + jsonResponse: JSON.parse(body), + httpStatusCode: httpResponse.statusCode, + }; + } catch (error) { + if (error instanceof ApiError) { + // const { statusCode, headers } = error; + throw new Error(error.message); + } + } +}; + +// createOrder route +app.post("/api/orders", async (req, res) => { + try { + // use the cart information passed from the front-end to calculate the order amount detals + const { cart } = req.body; + const { jsonResponse, httpStatusCode } = await createOrder(cart); + res.status(httpStatusCode).json(jsonResponse); + } catch (error) { + console.error("Failed to create order:", error); + res.status(500).json({ error: "Failed to create order." }); + } +}); + + +/** + * Capture payment for the created order to complete the transaction. + * @see https://developer.paypal.com/docs/api/orders/v2/#orders_capture + */ +const captureOrder = async (orderID) => { + const collect = { + id: orderID, + prefer: "return=minimal", + }; + + try { + const { body, ...httpResponse } = await ordersController.captureOrder( + collect + ); + // Get more response info... + // const { statusCode, headers } = httpResponse; + return { + jsonResponse: JSON.parse(body), + httpStatusCode: httpResponse.statusCode, + }; + } catch (error) { + if (error instanceof ApiError) { + // const { statusCode, headers } = error; + throw new Error(error.message); + } + } +}; + +// captureOrder route +app.post("/api/orders/:orderID/capture", async (req, res) => { + try { + const { orderID } = req.params; + const { jsonResponse, httpStatusCode } = await captureOrder(orderID); + res.status(httpStatusCode).json(jsonResponse); + } catch (error) { + console.error("Failed to create order:", error); + res.status(500).json({ error: "Failed to capture order." }); + } +}); + + +app.listen(PORT, () => { + console.log(`Node server listening at http://localhost:${PORT}/`); +}); + diff --git a/features/paypal/init.go b/features/paypal/init.go new file mode 100644 index 0000000..0958d4a --- /dev/null +++ b/features/paypal/init.go @@ -0,0 +1,10 @@ +package features_paypal + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupViews(app) +} diff --git a/features/paypal/views.go b/features/paypal/views.go new file mode 100644 index 0000000..4f8f490 --- /dev/null +++ b/features/paypal/views.go @@ -0,0 +1,11 @@ +package features_paypal + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func SetupViews(app *fiber.App) { + err := ConfigViews(app, "views/paypal") + if err != nil { panic(err) } +} diff --git a/features/shopping/api.go b/features/shopping/api.go new file mode 100644 index 0000000..299de2b --- /dev/null +++ b/features/shopping/api.go @@ -0,0 +1,31 @@ +package features_shopping + +import ( + "github.com/gofiber/fiber/v2" + "MY/webapp/data" + _ "github.com/mattn/go-sqlite3" + sq "github.com/Masterminds/squirrel" + "fmt" +) + +func GetApiProducts(c *fiber.Ctx) error { + sql, args, err := sq.Select("*").From("Product").ToSql() + + fmt.Println("SQL:", sql, args, err) + + return data.SelectJson[data.Product](c, err, sql, args...) +} + +func GetApiCart(c *fiber.Ctx) error { + return c.JSON(fiber.Map{}) +} + +func GetApiCartRemove(c *fiber.Ctx) error { + return c.Redirect("/shopping/checkout") +} + +func SetupApi(app *fiber.App) { + app.Get("/api/shopping/products", GetApiProducts) + app.Get("/api/shopping/cart", GetApiCart) + app.Get("/api/shopping/cart/remove/:item_id", GetApiCartRemove) +} diff --git a/features/shopping/init.go b/features/shopping/init.go new file mode 100644 index 0000000..520b0fa --- /dev/null +++ b/features/shopping/init.go @@ -0,0 +1,10 @@ +package features_shopping + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupViews(app) +} diff --git a/features/shopping/views.go b/features/shopping/views.go new file mode 100644 index 0000000..0c8af99 --- /dev/null +++ b/features/shopping/views.go @@ -0,0 +1,11 @@ +package features_shopping + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func SetupViews(app *fiber.App) { + err := ConfigViews(app, "views/shopping") + if err != nil { panic(err) } +} diff --git a/features/survey/api.go b/features/survey/api.go new file mode 100644 index 0000000..d483ec0 --- /dev/null +++ b/features/survey/api.go @@ -0,0 +1,15 @@ +package features_survey + +import ( + "github.com/gofiber/fiber/v2" +) + +func GetApiExample(c *fiber.Ctx) error { + tables := []string{"test", "that"} + + return c.JSON(tables) +} + +func SetupApi(app *fiber.App) { + app.Get("/api/survey/example", GetApiExample) +} diff --git a/features/survey/init.go b/features/survey/init.go new file mode 100644 index 0000000..0c97769 --- /dev/null +++ b/features/survey/init.go @@ -0,0 +1,10 @@ +package features_survey + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupViews(app) +} diff --git a/features/survey/views.go b/features/survey/views.go new file mode 100644 index 0000000..d427558 --- /dev/null +++ b/features/survey/views.go @@ -0,0 +1,11 @@ +package features_survey + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func SetupViews(app *fiber.App) { + err := ConfigViews(app, "views/survey") + if err != nil { panic(err) } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..cbb14fd --- /dev/null +++ b/go.mod @@ -0,0 +1,64 @@ +module MY/webapp + +go 1.26 + +require ( + github.com/Masterminds/squirrel v1.5.4 + github.com/chromedp/chromedp v0.16.0 + github.com/go-playground/validator/v10 v10.30.3 + github.com/gofiber/fiber/v2 v2.52.14 + github.com/gofiber/template/html/v2 v2.1.3 + github.com/guregu/null/v6 v6.0.0 + github.com/jmoiron/sqlx v1.4.0 + github.com/mattn/go-sqlite3 v1.14.49 + github.com/plutov/paypal/v4 v4.17.0 + github.com/redis/go-redis/v9 v9.21.0 + github.com/stretchr/testify v1.11.1 + github.com/wneessen/go-mail v0.8.1 + github.com/yuin/goldmark v1.8.5 + golang.org/x/crypto v0.54.0 +) + +require ( + github.com/andybalholm/brotli v1.2.2 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chromedp/cdproto v0.0.0-20260719223732-95f6af754cfe // indirect + github.com/chromedp/sysutil v1.1.0 // indirect + github.com/clipperhouse/uax29/v2 v2.7.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.15 // indirect + github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-sql-driver/mysql v1.9.3 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.4.0 // indirect + github.com/gofiber/template v1.8.3 // indirect + github.com/gofiber/utils v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.19.1 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect + github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect + github.com/leodido/go-urn v1.5.0 // indirect + github.com/mattn/go-colorable v0.1.15 // indirect + github.com/mattn/go-isatty v0.0.24 // indirect + github.com/mattn/go-runewidth v0.0.27 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.73.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.40.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + lcthw.dev/go/ozai v0.1.0 // indirect + lcthw.dev/go/ssgod v0.2.2 // indirect +) + +tool ( + lcthw.dev/go/ozai + lcthw.dev/go/ssgod +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..56966d3 --- /dev/null +++ b/go.sum @@ -0,0 +1,137 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= +github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/andybalholm/brotli v1.2.2 h1:HzTuoo2ErYQqf5qvcJInB8uvqSVxRttzkFexPWtnceM= +github.com/andybalholm/brotli v1.2.2/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chromedp/cdproto v0.0.0-20260719223732-95f6af754cfe h1:PmhRwLZ8qLtldQCBiydwdPFJI8WVQ936ux1cpgHLRb8= +github.com/chromedp/cdproto v0.0.0-20260719223732-95f6af754cfe/go.mod h1:RwFsSODCtFExll+GhHM6R92SARHR3Z3oipaxLHj46C0= +github.com/chromedp/chromedp v0.16.0 h1:rOO4deOm4CbZgBCa8mD9g2rDyIoNs0BkgvNrlbp5ouk= +github.com/chromedp/chromedp v0.16.0/go.mod h1:rbuGKFT1vMcFcFqKfPIO1GpX/N+2s8onm2qMxZLbU5U= +github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM= +github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8= +github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= +github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= +github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ= +github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68 h1:KZaTBSyshWX3MP5jukJcNSuXDQTO+rNpt0J564dX/eg= +github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8= +github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= +github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= +github.com/gofiber/fiber/v2 v2.52.14 h1:Of3L+9qVFaQNwPlcmEdl5IIodHz8BSE0j37R7rWu4pE= +github.com/gofiber/fiber/v2 v2.52.14/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc= +github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= +github.com/gofiber/template/html/v2 v2.1.3 h1:n1LYBtmr9C0V/k/3qBblXyMxV5B0o/gpb6dFLp8ea+o= +github.com/gofiber/template/html/v2 v2.1.3/go.mod h1:U5Fxgc5KpyujU9OqKzy6Kn6Qup6Tm7zdsISR+VpnHRE= +github.com/gofiber/utils v1.2.0 h1:NCaqd+Efg3khhN++eeUUTyBz+byIxAsmIjpl8kKOMIc= +github.com/gofiber/utils v1.2.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ= +github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0= +github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= +github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= +github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= +github.com/mattn/go-runewidth v0.0.27 h1:Feg/Oou5zI/wnpgDF6omIU0OokC9GxLC/WRknhVlIR0= +github.com/mattn/go-runewidth v0.0.27/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.49 h1:B8jBHC3xhxZgxztrgruTuLucebnULQnx4W7cF7SAE9w= +github.com/mattn/go-sqlite3 v1.14.49/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/plutov/paypal/v4 v4.17.0 h1:FtqBQ/ENdSw40NsoZK2aRW9zWhMNM+TaQhH3dzDtSqg= +github.com/plutov/paypal/v4 v4.17.0/go.mod h1:4N6hzf47wQUGdS3ef94jku6kjiSvFm2hxVlT9CnIHmU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.21.0 h1:FPBE4hhbAke+TLmcY3WkpbDffJEomdqPn3HYiqAtL9E= +github.com/redis/go-redis/v9 v9.21.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.73.0 h1:ocTOORnBWtJ+P8t/6wAjdkchMzdfHmWx2VD/DPbgZ7s= +github.com/valyala/fasthttp v1.73.0/go.mod h1:EtXQDHaR+5P18p8wqDRFpUhxr108Ga9mXvVJXHRrN2k= +github.com/wneessen/go-mail v0.8.1 h1:tVcncj02/QySVFw3zr/kXOzZcuFQqBNT6K+Rbgm/pcM= +github.com/wneessen/go-mail v0.8.1/go.mod h1:dWZ61zadzCIyvB4y1/YzC5O7MrbbzBfPkARmbosdf8w= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA= +github.com/yuin/goldmark v1.8.5/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= +github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= +golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +lcthw.dev/go/ozai v0.1.0 h1:LNuLMZV4m+ciHRjf1atcunR/63Jguvz3puEzD5vmFec= +lcthw.dev/go/ozai v0.1.0/go.mod h1:AwxRrUAb/KtUzSWgKmhv/eBg6ZjJ4tVZ9YA/DlKqtWs= +lcthw.dev/go/ssgod v0.2.2 h1:lvzhxOXDka9iejIQj7Db7ePjruBqYvqe7A5zzxsdank= +lcthw.dev/go/ssgod v0.2.2/go.mod h1:fCe4J/00a3T4pURfpUp6LZlkUeh5eHDpjApvy6HHiPk= diff --git a/main.go b/main.go new file mode 100644 index 0000000..253689e --- /dev/null +++ b/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/logger" + "github.com/gofiber/template/html/v2" + "github.com/gofiber/fiber/v2/middleware/session" + + _ "github.com/mattn/go-sqlite3" + recov "github.com/gofiber/fiber/v2/middleware/recover" + + "MY/webapp/data" + "MY/webapp/config" + "MY/webapp/common" + "MY/webapp/features" +) + +func main() { + config.Load("config.json") + log.Printf("ADMIN is %s", config.Settings.Server.Admin) + + log.SetFlags(log.LstdFlags | log.Lshortfile) + + engine := html.New(config.Settings.Server.Views, ".html") + engine.Reload(true) + + app := fiber.New(fiber.Config{ + Views: engine, + ViewsLayout: config.Settings.Server.Layouts, + CaseSensitive: true, + StrictRouting: true, + }) + + app.Use(logger.New()) + app.Use(recov.New()) + + app.Static("/", "./public", fiber.Static{ + Compress: false, + CacheDuration: -1, // this disables the cache + }) + + common.STORE = session.New() + + data.Setup(config.Settings.Database.Driver, config.Settings.Database.Url) + features.Setup(app) + + // this sets up graceful shutdown + go func() { + if err := app.Listen(config.Settings.Server.HostPort); err != nil { + log.Panic(err) + } + }() + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + + _ = <-c + log.Println("Shutdown now...") + _ = app.Shutdown() + + data.Shutdown() + + log.Println("Done.") +} diff --git a/migrations/20250802154952_init.sql b/migrations/20250802154952_init.sql new file mode 100644 index 0000000..7f0cc42 --- /dev/null +++ b/migrations/20250802154952_init.sql @@ -0,0 +1,9 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE user (id INTEGER PRIMARY KEY, username TEXT UNIQUE NOT NULL, email TEXT UNIQUE, password TEXT NOT NULL); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE user; +-- +goose StatementEnd diff --git a/migrations/20260112190943_shopping_init.sql b/migrations/20260112190943_shopping_init.sql new file mode 100644 index 0000000..07fa190 --- /dev/null +++ b/migrations/20260112190943_shopping_init.sql @@ -0,0 +1,13 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE Product (id INTEGER PRIMARY KEY, + title TEXT, + description TEXT, + price float, + slug TEXT UNIQUE); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE Product; +-- +goose StatementEnd diff --git a/migrations/20260112195518_shopping_cart.sql b/migrations/20260112195518_shopping_cart.sql new file mode 100644 index 0000000..9bd2802 --- /dev/null +++ b/migrations/20260112195518_shopping_cart.sql @@ -0,0 +1,13 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE Cart ( + id INTEGER PRIMARY KEY, + user_id INTEGER NOT NULL, + product_id INTEGER NOT NULL, + quantity INTEGER); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE Cart; +-- +goose StatementEnd diff --git a/pages/about.md b/pages/about.md new file mode 100644 index 0000000..5e35bd4 --- /dev/null +++ b/pages/about.md @@ -0,0 +1,5 @@ +# About Me + +My name is Zed A. Shaw. I'm the author of Learn Python the Hardway, and many other books. I started +making games in 2025 using a variety of languages. What you're seeing here is the result of this +year's work. diff --git a/pages/error/index.html b/pages/error/index.html new file mode 100644 index 0000000..22074d2 --- /dev/null +++ b/pages/error/index.html @@ -0,0 +1,2 @@ +

ERROR

+

You have an error.

diff --git a/pages/examples/gitea.html b/pages/examples/gitea.html new file mode 100644 index 0000000..35c886d --- /dev/null +++ b/pages/examples/gitea.html @@ -0,0 +1,91 @@ +
+ + Home + Home + Home + + + +
+ + go / ssgod +
+ + + + + + +
+ + + + + + + + + + + + +

SSG is a Static Site Generator that is only a Static Site Generator. No resumes here! Just a piece of code that generates static files from templates for websites, and can do it live while you develop said templates.

+ +

Manage Topics

+ + 21 Commits + 1 Branch + 0 Tags + 589 KiB + +
+ +
+ + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + + Name + Time + + +
diff --git a/pages/examples/index.html b/pages/examples/index.html new file mode 100644 index 0000000..942158d --- /dev/null +++ b/pages/examples/index.html @@ -0,0 +1,24 @@ + +
+

Copying Popular Websites to Learn Tailwind

+ +

I've advocated for years that copying other websites is the best way to learn web design. Copying is a very common and established way to learn almost any creative discipline including (but not limited to): Painting, Drawing, Writing, Music, Wood Working, Lutherie, Design, and Programming. To demonstrate this I've been doing copies of websites to learn Tailwind. +

+ +

Current Examples

+

Here's the ones I've done so far

+ + + +

View the Code

+

You can view this code at my git repository. The copies can be found in pages/copy and the tool I use to generate the pages is one I wrote called ssgod. +

+ +
diff --git a/pages/examples/linkedin.html b/pages/examples/linkedin.html new file mode 100644 index 0000000..a5ad3b0 --- /dev/null +++ b/pages/examples/linkedin.html @@ -0,0 +1,97 @@ +
+ + + + + + + + + + + Header Image + Avatar + + + +
Zed Shaw
+ I write books and stuff. + Miami Beach, Florida + Shavian Publishing, LLC +
+ + Show More + + + Avatar + + + + + Video + Photo + Write article + + + + Sort by: Top + + + + + Avatar + + Some Dude + Title + 14h Edited + + + + +

Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. Summus brains sit​​, morbo vel maleficia?

+
+ + Some Image + + + + + + + +
+ + + + Avatar + + Some Dude + Title + 14h Edited + + + + +

Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. Summus brains sit​​, morbo vel maleficia?

+
+ + Some Image + + + + + + + +
+ + + + Job search smarter + Zed reactivate this bullshit. + John and millions more use + + + Avatar + +
diff --git a/pages/examples/sample.html b/pages/examples/sample.html new file mode 100644 index 0000000..9b9d3b0 --- /dev/null +++ b/pages/examples/sample.html @@ -0,0 +1,154 @@ +
+

Sample Components

+

This is a list of components I've made for making websites quicker. They're just pre-styled things you commonly need to do HTML first layouts and designs.

+ +

Shapes

+ + + I'm a placeholder. + + +

Grids

+ + +0,0 +1,0 +0,1 +1,1 + + +

Blocks & Bars

+ + +

Use a block to automatically flex content vertically.

+

Like these two lines are done.

+ + Image +

Use a bar to flex things horizontally.

+
+ + + Image + + You can also combine them in arbitrary ways to layout your content. + + + 1 + 2 + 3 + + +
+ +

Stack

+ +

A stack lets you place multiple elements on top of eachother, like with layers in nearly every single layout composition system in existence for the last 500 years.

+ + +I'm on bottom +

Hello

+

There

+
+ +

Code

+ +
if(var != 'string') {
+  console.log("test");
+}
+
+ +

You should type ls -l to list the directory.

+ +if(var != 'string') + +

Highlight/Marking

+ + + + + + + + + +

This is some marked text.

+ +

Details

+ +
+ Details Test + A test of the details thing. +
+ +

Forms

+ +
+ + Test Form + + + + + + + + + + + + + + + + +

Cards

+ +

Cards organize information vertically.

+ + + Image + This shows a top large image with + some text in the middle. + + + +

Header/Nav

+ +

If you put nav inside header it "just works".

+ +
+ +
+ +

That's an example of a header with a nav bar in it.

+ +
diff --git a/pages/examples/starter.html b/pages/examples/starter.html new file mode 100644 index 0000000..46abfc4 --- /dev/null +++ b/pages/examples/starter.html @@ -0,0 +1,3 @@ +
+

Hello

+
diff --git a/pages/examples/stride.html b/pages/examples/stride.html new file mode 100644 index 0000000..b21c570 --- /dev/null +++ b/pages/examples/stride.html @@ -0,0 +1,155 @@ +
+ + STRIDE + + + + + + + + + +

Stride Game Engine

+ +

Stride is a free and open-source cross-platform C# game engine.

+ +

It is fit for both 2D and 3D games, as well as any other interactive content running on desktop and VR.

+ + + + + +
+
+ + + + + + +

Bet on the future

+
    +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
+ + +
+ +
+ +
+ + + + + +

Bet on the future

+
    +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
  • Blah blah blah
  • +
+ + +
+ +
+ +
+ + +

Recent blog posts

+ + + +
A look inside
+ April 09, 2025 + +

Distant Worlds 2, the sequel to the acclaimed 4X strategy game Distant Worlds: Universe, was developed by Code Force and published by Slitherine. In this blog post, the developers answer key questions from the Stride community, offering insights into their experience using the Stride engine to bring their ambitious galaxy-spanning strategy game to life.

+ + +
+ + +
A look inside
+ April 09, 2025 + +

Distant Worlds 2, the sequel to the acclaimed 4X strategy game Distant Worlds: Universe, was developed by Code Force and published by Slitherine. In this blog post, the developers answer key questions from the Stride community, offering insights into their experience using the Stride engine to bring their ambitious galaxy-spanning strategy game to life.

+ + +
+ +
A look inside
+ April 09, 2025 + +

Distant Worlds 2, the sequel to the acclaimed 4X strategy game Distant Worlds: Universe, was developed by Code Force and published by Slitherine. In this blog post, the developers answer key questions from the Stride community, offering insights into their experience using the Stride engine to bring their ambitious galaxy-spanning strategy game to life.

+ + +
+ +
+
+ +
+ + +

Featured Sponsors

+ +

Thanks to our featured sponsors for supporting Stride and empowering creators with the resources they need to bring their visions to life.

+ + + +
 
+ + +

+ A visual live-programming environment that takes you from rapid prototyping to final production. +

+
+
+ +
 
+ + +

+ A visual live-programming environment that takes you from rapid prototyping to final production. +

+
+
+
+
+
+ + + + Content1 + Content2 + Content3 + Content4 + + +
+ + + + + + + + +
+ +
+ Supported by the .NET Foundation + Website v.2.0.0.31 + © .NET Foundation and Contributors +
+
+
diff --git a/pages/examples/twitch.html b/pages/examples/twitch.html new file mode 100644 index 0000000..8d458b6 --- /dev/null +++ b/pages/examples/twitch.html @@ -0,0 +1,203 @@ +
+ + + Browse + + + + + + + + + + + +
+ + + + + Main Video + + + + + + + Live on Twitch + + + Sample Video +
+ Avatar +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+
+ + + Sample Video +
+ Avatar +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+
+ +
+ + + + + Categories we think you'll like + + + + Category +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+ + Category +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+ + Category +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+ + Category +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + Live on Twitch + + + Sample Video +
+ Avatar +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+
+ + + Sample Video +
+ Avatar +
+ Title + Name + Game Title + + Pill + Pill + Pill + Pill + +
+
+
+ +
+ + +

an amazon company

+
+
+
diff --git a/pages/index.html b/pages/index.html new file mode 100644 index 0000000..97dd669 --- /dev/null +++ b/pages/index.html @@ -0,0 +1,39 @@ +

Zed's Survey Site

+ +

La jetée raclette normcore, ascot comme des garçons hyperpop canon event supper club reading series leggings burrata. Canon event listening party carhartt bodega boys black trumpet tarkovsky. Narwhal portland fit lo-fi, migas bauhaus varda oat milk retro activated charcoal tumblr synth polycule iPhone.

+ +

Active Surveys

+ +

Here's a list of currently active and completed surveys.

+ + + Sample Title + +

Street art kettlebell burrata offal portra decolonize are.na akerman shabby chic blue bottle post-ironic breathwork. Roof party natural wine bell hooks cold plunge metrograph granny square ugh dad shoes garum before they sold out zines tahini side hustle. Indigo dye pork belly amaro, post-ironic health goth candle making van life hairpin robert walser.

+ 01/20/23 Active +
+ + + + + +
+ + +

Completed Surveys

+ +

These surveys are no longer running, but you can see the results.

+ + + Sample Finished Survey + +

Street art kettlebell burrata offal portra decolonize are.na akerman shabby chic blue bottle post-ironic breathwork. Roof party natural wine bell hooks cold plunge metrograph granny square ugh dad shoes garum before they sold out zines tahini side hustle. Indigo dye pork belly amaro, post-ironic health goth candle making van life hairpin robert walser.

+ 01/20/23 Finished +
+ + + + + + +
diff --git a/pages/layouts/examples.html b/pages/layouts/examples.html new file mode 100644 index 0000000..5f46292 --- /dev/null +++ b/pages/layouts/examples.html @@ -0,0 +1,15 @@ + + + + + + + + + + MY.com + + + {{embed}} + + diff --git a/pages/login/index.html b/pages/login/index.html new file mode 100644 index 0000000..f49578d --- /dev/null +++ b/pages/login/index.html @@ -0,0 +1,35 @@ + + +
+ + +
+
+ +

Login

+ + + + + + + + + + +
+ + +
diff --git a/pages/register/index.html b/pages/register/index.html new file mode 100644 index 0000000..6f4c67b --- /dev/null +++ b/pages/register/index.html @@ -0,0 +1,20 @@ +
+
+ +

Register

+ + + + + + + + + + + + +
+ + +
diff --git a/pages/sitemap.html b/pages/sitemap.html new file mode 100644 index 0000000..b1517d9 --- /dev/null +++ b/pages/sitemap.html @@ -0,0 +1,9 @@ +

Site Map

+ + diff --git a/static/default_theme.css b/static/default_theme.css new file mode 100644 index 0000000..52d447f --- /dev/null +++ b/static/default_theme.css @@ -0,0 +1,462 @@ +@theme default { + --font-sans: + ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; + --font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', + monospace; + + --color-red-50: oklch(97.1% 0.013 17.38); + --color-red-100: oklch(93.6% 0.032 17.717); + --color-red-200: oklch(88.5% 0.062 18.334); + --color-red-300: oklch(80.8% 0.114 19.571); + --color-red-400: oklch(70.4% 0.191 22.216); + --color-red-500: oklch(63.7% 0.237 25.331); + --color-red-600: oklch(57.7% 0.245 27.325); + --color-red-700: oklch(50.5% 0.213 27.518); + --color-red-800: oklch(44.4% 0.177 26.899); + --color-red-900: oklch(39.6% 0.141 25.723); + --color-red-950: oklch(25.8% 0.092 26.042); + + --color-orange-50: oklch(98% 0.016 73.684); + --color-orange-100: oklch(95.4% 0.038 75.164); + --color-orange-200: oklch(90.1% 0.076 70.697); + --color-orange-300: oklch(83.7% 0.128 66.29); + --color-orange-400: oklch(75% 0.183 55.934); + --color-orange-500: oklch(70.5% 0.213 47.604); + --color-orange-600: oklch(64.6% 0.222 41.116); + --color-orange-700: oklch(55.3% 0.195 38.402); + --color-orange-800: oklch(47% 0.157 37.304); + --color-orange-900: oklch(40.8% 0.123 38.172); + --color-orange-950: oklch(26.6% 0.079 36.259); + + --color-amber-50: oklch(98.7% 0.022 95.277); + --color-amber-100: oklch(96.2% 0.059 95.617); + --color-amber-200: oklch(92.4% 0.12 95.746); + --color-amber-300: oklch(87.9% 0.169 91.605); + --color-amber-400: oklch(82.8% 0.189 84.429); + --color-amber-500: oklch(76.9% 0.188 70.08); + --color-amber-600: oklch(66.6% 0.179 58.318); + --color-amber-700: oklch(55.5% 0.163 48.998); + --color-amber-800: oklch(47.3% 0.137 46.201); + --color-amber-900: oklch(41.4% 0.112 45.904); + --color-amber-950: oklch(27.9% 0.077 45.635); + + --color-yellow-50: oklch(98.7% 0.026 102.212); + --color-yellow-100: oklch(97.3% 0.071 103.193); + --color-yellow-200: oklch(94.5% 0.129 101.54); + --color-yellow-300: oklch(90.5% 0.182 98.111); + --color-yellow-400: oklch(85.2% 0.199 91.936); + --color-yellow-500: oklch(79.5% 0.184 86.047); + --color-yellow-600: oklch(68.1% 0.162 75.834); + --color-yellow-700: oklch(55.4% 0.135 66.442); + --color-yellow-800: oklch(47.6% 0.114 61.907); + --color-yellow-900: oklch(42.1% 0.095 57.708); + --color-yellow-950: oklch(28.6% 0.066 53.813); + + --color-lime-50: oklch(98.6% 0.031 120.757); + --color-lime-100: oklch(96.7% 0.067 122.328); + --color-lime-200: oklch(93.8% 0.127 124.321); + --color-lime-300: oklch(89.7% 0.196 126.665); + --color-lime-400: oklch(84.1% 0.238 128.85); + --color-lime-500: oklch(76.8% 0.233 130.85); + --color-lime-600: oklch(64.8% 0.2 131.684); + --color-lime-700: oklch(53.2% 0.157 131.589); + --color-lime-800: oklch(45.3% 0.124 130.933); + --color-lime-900: oklch(40.5% 0.101 131.063); + --color-lime-950: oklch(27.4% 0.072 132.109); + + --color-green-50: oklch(98.2% 0.018 155.826); + --color-green-100: oklch(96.2% 0.044 156.743); + --color-green-200: oklch(92.5% 0.084 155.995); + --color-green-300: oklch(87.1% 0.15 154.449); + --color-green-400: oklch(79.2% 0.209 151.711); + --color-green-500: oklch(72.3% 0.219 149.579); + --color-green-600: oklch(62.7% 0.194 149.214); + --color-green-700: oklch(52.7% 0.154 150.069); + --color-green-800: oklch(44.8% 0.119 151.328); + --color-green-900: oklch(39.3% 0.095 152.535); + --color-green-950: oklch(26.6% 0.065 152.934); + + --color-emerald-50: oklch(97.9% 0.021 166.113); + --color-emerald-100: oklch(95% 0.052 163.051); + --color-emerald-200: oklch(90.5% 0.093 164.15); + --color-emerald-300: oklch(84.5% 0.143 164.978); + --color-emerald-400: oklch(76.5% 0.177 163.223); + --color-emerald-500: oklch(69.6% 0.17 162.48); + --color-emerald-600: oklch(59.6% 0.145 163.225); + --color-emerald-700: oklch(50.8% 0.118 165.612); + --color-emerald-800: oklch(43.2% 0.095 166.913); + --color-emerald-900: oklch(37.8% 0.077 168.94); + --color-emerald-950: oklch(26.2% 0.051 172.552); + + --color-teal-50: oklch(98.4% 0.014 180.72); + --color-teal-100: oklch(95.3% 0.051 180.801); + --color-teal-200: oklch(91% 0.096 180.426); + --color-teal-300: oklch(85.5% 0.138 181.071); + --color-teal-400: oklch(77.7% 0.152 181.912); + --color-teal-500: oklch(70.4% 0.14 182.503); + --color-teal-600: oklch(60% 0.118 184.704); + --color-teal-700: oklch(51.1% 0.096 186.391); + --color-teal-800: oklch(43.7% 0.078 188.216); + --color-teal-900: oklch(38.6% 0.063 188.416); + --color-teal-950: oklch(27.7% 0.046 192.524); + + --color-cyan-50: oklch(98.4% 0.019 200.873); + --color-cyan-100: oklch(95.6% 0.045 203.388); + --color-cyan-200: oklch(91.7% 0.08 205.041); + --color-cyan-300: oklch(86.5% 0.127 207.078); + --color-cyan-400: oklch(78.9% 0.154 211.53); + --color-cyan-500: oklch(71.5% 0.143 215.221); + --color-cyan-600: oklch(60.9% 0.126 221.723); + --color-cyan-700: oklch(52% 0.105 223.128); + --color-cyan-800: oklch(45% 0.085 224.283); + --color-cyan-900: oklch(39.8% 0.07 227.392); + --color-cyan-950: oklch(30.2% 0.056 229.695); + + --color-sky-50: oklch(97.7% 0.013 236.62); + --color-sky-100: oklch(95.1% 0.026 236.824); + --color-sky-200: oklch(90.1% 0.058 230.902); + --color-sky-300: oklch(82.8% 0.111 230.318); + --color-sky-400: oklch(74.6% 0.16 232.661); + --color-sky-500: oklch(68.5% 0.169 237.323); + --color-sky-600: oklch(58.8% 0.158 241.966); + --color-sky-700: oklch(50% 0.134 242.749); + --color-sky-800: oklch(44.3% 0.11 240.79); + --color-sky-900: oklch(39.1% 0.09 240.876); + --color-sky-950: oklch(29.3% 0.066 243.157); + + --color-blue-50: oklch(97% 0.014 254.604); + --color-blue-100: oklch(93.2% 0.032 255.585); + --color-blue-200: oklch(88.2% 0.059 254.128); + --color-blue-300: oklch(80.9% 0.105 251.813); + --color-blue-400: oklch(70.7% 0.165 254.624); + --color-blue-500: oklch(62.3% 0.214 259.815); + --color-blue-600: oklch(54.6% 0.245 262.881); + --color-blue-700: oklch(48.8% 0.243 264.376); + --color-blue-800: oklch(42.4% 0.199 265.638); + --color-blue-900: oklch(37.9% 0.146 265.522); + --color-blue-950: oklch(28.2% 0.091 267.935); + + --color-indigo-50: oklch(96.2% 0.018 272.314); + --color-indigo-100: oklch(93% 0.034 272.788); + --color-indigo-200: oklch(87% 0.065 274.039); + --color-indigo-300: oklch(78.5% 0.115 274.713); + --color-indigo-400: oklch(67.3% 0.182 276.935); + --color-indigo-500: oklch(58.5% 0.233 277.117); + --color-indigo-600: oklch(51.1% 0.262 276.966); + --color-indigo-700: oklch(45.7% 0.24 277.023); + --color-indigo-800: oklch(39.8% 0.195 277.366); + --color-indigo-900: oklch(35.9% 0.144 278.697); + --color-indigo-950: oklch(25.7% 0.09 281.288); + + --color-violet-50: oklch(96.9% 0.016 293.756); + --color-violet-100: oklch(94.3% 0.029 294.588); + --color-violet-200: oklch(89.4% 0.057 293.283); + --color-violet-300: oklch(81.1% 0.111 293.571); + --color-violet-400: oklch(70.2% 0.183 293.541); + --color-violet-500: oklch(60.6% 0.25 292.717); + --color-violet-600: oklch(54.1% 0.281 293.009); + --color-violet-700: oklch(49.1% 0.27 292.581); + --color-violet-800: oklch(43.2% 0.232 292.759); + --color-violet-900: oklch(38% 0.189 293.745); + --color-violet-950: oklch(28.3% 0.141 291.089); + + --color-purple-50: oklch(97.7% 0.014 308.299); + --color-purple-100: oklch(94.6% 0.033 307.174); + --color-purple-200: oklch(90.2% 0.063 306.703); + --color-purple-300: oklch(82.7% 0.119 306.383); + --color-purple-400: oklch(71.4% 0.203 305.504); + --color-purple-500: oklch(62.7% 0.265 303.9); + --color-purple-600: oklch(55.8% 0.288 302.321); + --color-purple-700: oklch(49.6% 0.265 301.924); + --color-purple-800: oklch(43.8% 0.218 303.724); + --color-purple-900: oklch(38.1% 0.176 304.987); + --color-purple-950: oklch(29.1% 0.149 302.717); + + --color-fuchsia-50: oklch(97.7% 0.017 320.058); + --color-fuchsia-100: oklch(95.2% 0.037 318.852); + --color-fuchsia-200: oklch(90.3% 0.076 319.62); + --color-fuchsia-300: oklch(83.3% 0.145 321.434); + --color-fuchsia-400: oklch(74% 0.238 322.16); + --color-fuchsia-500: oklch(66.7% 0.295 322.15); + --color-fuchsia-600: oklch(59.1% 0.293 322.896); + --color-fuchsia-700: oklch(51.8% 0.253 323.949); + --color-fuchsia-800: oklch(45.2% 0.211 324.591); + --color-fuchsia-900: oklch(40.1% 0.17 325.612); + --color-fuchsia-950: oklch(29.3% 0.136 325.661); + + --color-pink-50: oklch(97.1% 0.014 343.198); + --color-pink-100: oklch(94.8% 0.028 342.258); + --color-pink-200: oklch(89.9% 0.061 343.231); + --color-pink-300: oklch(82.3% 0.12 346.018); + --color-pink-400: oklch(71.8% 0.202 349.761); + --color-pink-500: oklch(65.6% 0.241 354.308); + --color-pink-600: oklch(59.2% 0.249 0.584); + --color-pink-700: oklch(52.5% 0.223 3.958); + --color-pink-800: oklch(45.9% 0.187 3.815); + --color-pink-900: oklch(40.8% 0.153 2.432); + --color-pink-950: oklch(28.4% 0.109 3.907); + + --color-rose-50: oklch(96.9% 0.015 12.422); + --color-rose-100: oklch(94.1% 0.03 12.58); + --color-rose-200: oklch(89.2% 0.058 10.001); + --color-rose-300: oklch(81% 0.117 11.638); + --color-rose-400: oklch(71.2% 0.194 13.428); + --color-rose-500: oklch(64.5% 0.246 16.439); + --color-rose-600: oklch(58.6% 0.253 17.585); + --color-rose-700: oklch(51.4% 0.222 16.935); + --color-rose-800: oklch(45.5% 0.188 13.697); + --color-rose-900: oklch(41% 0.159 10.272); + --color-rose-950: oklch(27.1% 0.105 12.094); + + --color-slate-50: oklch(98.4% 0.003 247.858); + --color-slate-100: oklch(96.8% 0.007 247.896); + --color-slate-200: oklch(92.9% 0.013 255.508); + --color-slate-300: oklch(86.9% 0.022 252.894); + --color-slate-400: oklch(70.4% 0.04 256.788); + --color-slate-500: oklch(55.4% 0.046 257.417); + --color-slate-600: oklch(44.6% 0.043 257.281); + --color-slate-700: oklch(37.2% 0.044 257.287); + --color-slate-800: oklch(27.9% 0.041 260.031); + --color-slate-900: oklch(20.8% 0.042 265.755); + --color-slate-950: oklch(12.9% 0.042 264.695); + + --color-gray-50: oklch(98.5% 0.002 247.839); + --color-gray-100: oklch(96.7% 0.003 264.542); + --color-gray-200: oklch(92.8% 0.006 264.531); + --color-gray-300: oklch(87.2% 0.01 258.338); + --color-gray-400: oklch(70.7% 0.022 261.325); + --color-gray-500: oklch(55.1% 0.027 264.364); + --color-gray-600: oklch(44.6% 0.03 256.802); + --color-gray-700: oklch(37.3% 0.034 259.733); + --color-gray-800: oklch(27.8% 0.033 256.848); + --color-gray-900: oklch(21% 0.034 264.665); + --color-gray-950: oklch(13% 0.028 261.692); + + --color-zinc-50: oklch(98.5% 0 0); + --color-zinc-100: oklch(96.7% 0.001 286.375); + --color-zinc-200: oklch(92% 0.004 286.32); + --color-zinc-300: oklch(87.1% 0.006 286.286); + --color-zinc-400: oklch(70.5% 0.015 286.067); + --color-zinc-500: oklch(55.2% 0.016 285.938); + --color-zinc-600: oklch(44.2% 0.017 285.786); + --color-zinc-700: oklch(37% 0.013 285.805); + --color-zinc-800: oklch(27.4% 0.006 286.033); + --color-zinc-900: oklch(21% 0.006 285.885); + --color-zinc-950: oklch(14.1% 0.005 285.823); + + --color-neutral-50: oklch(98.5% 0 0); + --color-neutral-100: oklch(97% 0 0); + --color-neutral-200: oklch(92.2% 0 0); + --color-neutral-300: oklch(87% 0 0); + --color-neutral-400: oklch(70.8% 0 0); + --color-neutral-500: oklch(55.6% 0 0); + --color-neutral-600: oklch(43.9% 0 0); + --color-neutral-700: oklch(37.1% 0 0); + --color-neutral-800: oklch(26.9% 0 0); + --color-neutral-900: oklch(20.5% 0 0); + --color-neutral-950: oklch(14.5% 0 0); + + --color-stone-50: oklch(98.5% 0.001 106.423); + --color-stone-100: oklch(97% 0.001 106.424); + --color-stone-200: oklch(92.3% 0.003 48.717); + --color-stone-300: oklch(86.9% 0.005 56.366); + --color-stone-400: oklch(70.9% 0.01 56.259); + --color-stone-500: oklch(55.3% 0.013 58.071); + --color-stone-600: oklch(44.4% 0.011 73.639); + --color-stone-700: oklch(37.4% 0.01 67.558); + --color-stone-800: oklch(26.8% 0.007 34.298); + --color-stone-900: oklch(21.6% 0.006 56.043); + --color-stone-950: oklch(14.7% 0.004 49.25); + + --color-black: #000; + --color-white: #fff; + + --spacing: 0.25rem; + + --breakpoint-sm: 40rem; + --breakpoint-md: 48rem; + --breakpoint-lg: 64rem; + --breakpoint-xl: 80rem; + --breakpoint-2xl: 96rem; + + --container-3xs: 16rem; + --container-2xs: 18rem; + --container-xs: 20rem; + --container-sm: 24rem; + --container-md: 28rem; + --container-lg: 32rem; + --container-xl: 36rem; + --container-2xl: 42rem; + --container-3xl: 48rem; + --container-4xl: 56rem; + --container-5xl: 64rem; + --container-6xl: 72rem; + --container-7xl: 80rem; + + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-base: 1rem; + --text-base--line-height: calc(1.5 / 1); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --text-5xl: 3rem; + --text-5xl--line-height: 1; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --text-7xl: 4.5rem; + --text-7xl--line-height: 1; + --text-8xl: 6rem; + --text-8xl--line-height: 1; + --text-9xl: 8rem; + --text-9xl--line-height: 1; + + --font-weight-thin: 100; + --font-weight-extralight: 200; + --font-weight-light: 300; + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --font-weight-extrabold: 800; + --font-weight-black: 900; + + --tracking-tighter: -0.05em; + --tracking-tight: -0.025em; + --tracking-normal: 0em; + --tracking-wide: 0.025em; + --tracking-wider: 0.05em; + --tracking-widest: 0.1em; + + --leading-tight: 1.25; + --leading-snug: 1.375; + --leading-normal: 1.5; + --leading-relaxed: 1.625; + --leading-loose: 2; + + --radius-xs: 0.125rem; + --radius-sm: 0.25rem; + --radius-md: 0.375rem; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --radius-2xl: 1rem; + --radius-3xl: 1.5rem; + --radius-4xl: 2rem; + + --shadow-2xs: 0 1px rgb(0 0 0 / 0.05); + --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); + + --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05); + --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05); + --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05); + + --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05); + --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15); + --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12); + --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15); + --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1); + --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15); + + --text-shadow-2xs: 0px 1px 0px rgb(0 0 0 / 0.15); + --text-shadow-xs: 0px 1px 1px rgb(0 0 0 / 0.2); + --text-shadow-sm: + 0px 1px 0px rgb(0 0 0 / 0.075), 0px 1px 1px rgb(0 0 0 / 0.075), 0px 2px 2px rgb(0 0 0 / 0.075); + --text-shadow-md: + 0px 1px 1px rgb(0 0 0 / 0.1), 0px 1px 2px rgb(0 0 0 / 0.1), 0px 2px 4px rgb(0 0 0 / 0.1); + --text-shadow-lg: + 0px 1px 2px rgb(0 0 0 / 0.1), 0px 3px 2px rgb(0 0 0 / 0.1), 0px 4px 8px rgb(0 0 0 / 0.1); + + --ease-in: cubic-bezier(0.4, 0, 1, 1); + --ease-out: cubic-bezier(0, 0, 0.2, 1); + --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); + + --animate-spin: spin 1s linear infinite; + --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + --animate-bounce: bounce 1s infinite; + + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + @keyframes ping { + 75%, + 100% { + transform: scale(2); + opacity: 0; + } + } + + @keyframes pulse { + 50% { + opacity: 0.5; + } + } + + @keyframes bounce { + 0%, + 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + + 50% { + transform: none; + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } + } + + --blur-xs: 4px; + --blur-sm: 8px; + --blur-md: 12px; + --blur-lg: 16px; + --blur-xl: 24px; + --blur-2xl: 40px; + --blur-3xl: 64px; + + --perspective-dramatic: 100px; + --perspective-near: 300px; + --perspective-normal: 500px; + --perspective-midrange: 800px; + --perspective-distant: 1200px; + + --aspect-video: 16 / 9; + + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: --theme(--font-sans, initial); + --default-font-feature-settings: --theme(--font-sans--font-feature-settings, initial); + --default-font-variation-settings: --theme(--font-sans--font-variation-settings, initial); + --default-mono-font-family: --theme(--font-mono, initial); + --default-mono-font-feature-settings: --theme(--font-mono--font-feature-settings, initial); + --default-mono-font-variation-settings: --theme(--font-mono--font-variation-settings, initial); +} + +/* Deprecated */ +@theme default inline reference { + --blur: 8px; + --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); + --drop-shadow: 0 1px 2px rgb(0 0 0 / 0.1), 0 1px 1px rgb(0 0 0 / 0.06); + --radius: 0.25rem; + --max-width-prose: 65ch; +} diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..7cf06c4 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/icons/LICENSE b/static/icons/LICENSE new file mode 100644 index 0000000..f9e4672 --- /dev/null +++ b/static/icons/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Icons are Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/static/icons/accessibility.svg b/static/icons/accessibility.svg new file mode 100644 index 0000000..758ff89 --- /dev/null +++ b/static/icons/accessibility.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/activity.svg b/static/icons/activity.svg new file mode 100644 index 0000000..2eccd9c --- /dev/null +++ b/static/icons/activity.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/air-vent.svg b/static/icons/air-vent.svg new file mode 100644 index 0000000..0b705dc --- /dev/null +++ b/static/icons/air-vent.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/airplay.svg b/static/icons/airplay.svg new file mode 100644 index 0000000..efa8ec3 --- /dev/null +++ b/static/icons/airplay.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/alarm-check.svg b/static/icons/alarm-check.svg new file mode 100644 index 0000000..c806f73 --- /dev/null +++ b/static/icons/alarm-check.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/alarm-clock-off.svg b/static/icons/alarm-clock-off.svg new file mode 100644 index 0000000..2c675ff --- /dev/null +++ b/static/icons/alarm-clock-off.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/alarm-clock.svg b/static/icons/alarm-clock.svg new file mode 100644 index 0000000..73bed01 --- /dev/null +++ b/static/icons/alarm-clock.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/alarm-minus.svg b/static/icons/alarm-minus.svg new file mode 100644 index 0000000..fc7b396 --- /dev/null +++ b/static/icons/alarm-minus.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/alarm-plus.svg b/static/icons/alarm-plus.svg new file mode 100644 index 0000000..07d8d98 --- /dev/null +++ b/static/icons/alarm-plus.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/album.svg b/static/icons/album.svg new file mode 100644 index 0000000..2d56097 --- /dev/null +++ b/static/icons/album.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/alert-circle.svg b/static/icons/alert-circle.svg new file mode 100644 index 0000000..57fbe36 --- /dev/null +++ b/static/icons/alert-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/alert-octagon.svg b/static/icons/alert-octagon.svg new file mode 100644 index 0000000..6cb9665 --- /dev/null +++ b/static/icons/alert-octagon.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/alert-triangle.svg b/static/icons/alert-triangle.svg new file mode 100644 index 0000000..a90c7c8 --- /dev/null +++ b/static/icons/alert-triangle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-center-horizontal.svg b/static/icons/align-center-horizontal.svg new file mode 100644 index 0000000..f77f047 --- /dev/null +++ b/static/icons/align-center-horizontal.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/align-center-vertical.svg b/static/icons/align-center-vertical.svg new file mode 100644 index 0000000..a378004 --- /dev/null +++ b/static/icons/align-center-vertical.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/align-center.svg b/static/icons/align-center.svg new file mode 100644 index 0000000..ef63a63 --- /dev/null +++ b/static/icons/align-center.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-end-horizontal.svg b/static/icons/align-end-horizontal.svg new file mode 100644 index 0000000..56f5fae --- /dev/null +++ b/static/icons/align-end-horizontal.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-end-vertical.svg b/static/icons/align-end-vertical.svg new file mode 100644 index 0000000..c5219f8 --- /dev/null +++ b/static/icons/align-end-vertical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-horizontal-distribute-center.svg b/static/icons/align-horizontal-distribute-center.svg new file mode 100644 index 0000000..928045d --- /dev/null +++ b/static/icons/align-horizontal-distribute-center.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/align-horizontal-distribute-end.svg b/static/icons/align-horizontal-distribute-end.svg new file mode 100644 index 0000000..8537be6 --- /dev/null +++ b/static/icons/align-horizontal-distribute-end.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/align-horizontal-distribute-start.svg b/static/icons/align-horizontal-distribute-start.svg new file mode 100644 index 0000000..7424192 --- /dev/null +++ b/static/icons/align-horizontal-distribute-start.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/align-horizontal-justify-center.svg b/static/icons/align-horizontal-justify-center.svg new file mode 100644 index 0000000..a53129d --- /dev/null +++ b/static/icons/align-horizontal-justify-center.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-horizontal-justify-end.svg b/static/icons/align-horizontal-justify-end.svg new file mode 100644 index 0000000..2850b0c --- /dev/null +++ b/static/icons/align-horizontal-justify-end.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-horizontal-justify-start.svg b/static/icons/align-horizontal-justify-start.svg new file mode 100644 index 0000000..45befff --- /dev/null +++ b/static/icons/align-horizontal-justify-start.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-horizontal-space-around.svg b/static/icons/align-horizontal-space-around.svg new file mode 100644 index 0000000..70e2a80 --- /dev/null +++ b/static/icons/align-horizontal-space-around.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-horizontal-space-between.svg b/static/icons/align-horizontal-space-between.svg new file mode 100644 index 0000000..e38bc34 --- /dev/null +++ b/static/icons/align-horizontal-space-between.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/align-justify.svg b/static/icons/align-justify.svg new file mode 100644 index 0000000..bd9cc4e --- /dev/null +++ b/static/icons/align-justify.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-left.svg b/static/icons/align-left.svg new file mode 100644 index 0000000..c776bae --- /dev/null +++ b/static/icons/align-left.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-right.svg b/static/icons/align-right.svg new file mode 100644 index 0000000..779e275 --- /dev/null +++ b/static/icons/align-right.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-start-horizontal.svg b/static/icons/align-start-horizontal.svg new file mode 100644 index 0000000..d80d2bf --- /dev/null +++ b/static/icons/align-start-horizontal.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-start-vertical.svg b/static/icons/align-start-vertical.svg new file mode 100644 index 0000000..7fbab04 --- /dev/null +++ b/static/icons/align-start-vertical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-vertical-distribute-center.svg b/static/icons/align-vertical-distribute-center.svg new file mode 100644 index 0000000..2e227da --- /dev/null +++ b/static/icons/align-vertical-distribute-center.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/align-vertical-distribute-end.svg b/static/icons/align-vertical-distribute-end.svg new file mode 100644 index 0000000..a43fc0d --- /dev/null +++ b/static/icons/align-vertical-distribute-end.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/align-vertical-distribute-start.svg b/static/icons/align-vertical-distribute-start.svg new file mode 100644 index 0000000..ca342c3 --- /dev/null +++ b/static/icons/align-vertical-distribute-start.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/align-vertical-justify-center.svg b/static/icons/align-vertical-justify-center.svg new file mode 100644 index 0000000..c1ffbe8 --- /dev/null +++ b/static/icons/align-vertical-justify-center.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-vertical-justify-end.svg b/static/icons/align-vertical-justify-end.svg new file mode 100644 index 0000000..cd78255 --- /dev/null +++ b/static/icons/align-vertical-justify-end.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-vertical-justify-start.svg b/static/icons/align-vertical-justify-start.svg new file mode 100644 index 0000000..4f4bf69 --- /dev/null +++ b/static/icons/align-vertical-justify-start.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-vertical-space-around.svg b/static/icons/align-vertical-space-around.svg new file mode 100644 index 0000000..4ee0ec8 --- /dev/null +++ b/static/icons/align-vertical-space-around.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/align-vertical-space-between.svg b/static/icons/align-vertical-space-between.svg new file mode 100644 index 0000000..d6a6ca3 --- /dev/null +++ b/static/icons/align-vertical-space-between.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/anchor.svg b/static/icons/anchor.svg new file mode 100644 index 0000000..696a416 --- /dev/null +++ b/static/icons/anchor.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/angry.svg b/static/icons/angry.svg new file mode 100644 index 0000000..f2b05eb --- /dev/null +++ b/static/icons/angry.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/annoyed.svg b/static/icons/annoyed.svg new file mode 100644 index 0000000..3279b66 --- /dev/null +++ b/static/icons/annoyed.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/aperture.svg b/static/icons/aperture.svg new file mode 100644 index 0000000..15652da --- /dev/null +++ b/static/icons/aperture.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/apple.svg b/static/icons/apple.svg new file mode 100644 index 0000000..2d593c3 --- /dev/null +++ b/static/icons/apple.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/archive-restore.svg b/static/icons/archive-restore.svg new file mode 100644 index 0000000..95b7a27 --- /dev/null +++ b/static/icons/archive-restore.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/archive.svg b/static/icons/archive.svg new file mode 100644 index 0000000..12695a6 --- /dev/null +++ b/static/icons/archive.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/armchair.svg b/static/icons/armchair.svg new file mode 100644 index 0000000..3938cf7 --- /dev/null +++ b/static/icons/armchair.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/arrow-big-down.svg b/static/icons/arrow-big-down.svg new file mode 100644 index 0000000..af3f172 --- /dev/null +++ b/static/icons/arrow-big-down.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/arrow-big-left.svg b/static/icons/arrow-big-left.svg new file mode 100644 index 0000000..a8cacaf --- /dev/null +++ b/static/icons/arrow-big-left.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/arrow-big-right.svg b/static/icons/arrow-big-right.svg new file mode 100644 index 0000000..31a8473 --- /dev/null +++ b/static/icons/arrow-big-right.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/arrow-big-up.svg b/static/icons/arrow-big-up.svg new file mode 100644 index 0000000..c7f7865 --- /dev/null +++ b/static/icons/arrow-big-up.svg @@ -0,0 +1,14 @@ + + + diff --git a/static/icons/arrow-down-circle.svg b/static/icons/arrow-down-circle.svg new file mode 100644 index 0000000..eb9f1a0 --- /dev/null +++ b/static/icons/arrow-down-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/arrow-down-left.svg b/static/icons/arrow-down-left.svg new file mode 100644 index 0000000..b9c6b8b --- /dev/null +++ b/static/icons/arrow-down-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-down-right.svg b/static/icons/arrow-down-right.svg new file mode 100644 index 0000000..2294d9b --- /dev/null +++ b/static/icons/arrow-down-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-down.svg b/static/icons/arrow-down.svg new file mode 100644 index 0000000..708e35f --- /dev/null +++ b/static/icons/arrow-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-left-circle.svg b/static/icons/arrow-left-circle.svg new file mode 100644 index 0000000..c1ba4a2 --- /dev/null +++ b/static/icons/arrow-left-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/arrow-left-right.svg b/static/icons/arrow-left-right.svg new file mode 100644 index 0000000..2216947 --- /dev/null +++ b/static/icons/arrow-left-right.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/arrow-left.svg b/static/icons/arrow-left.svg new file mode 100644 index 0000000..ce06f88 --- /dev/null +++ b/static/icons/arrow-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-right-circle.svg b/static/icons/arrow-right-circle.svg new file mode 100644 index 0000000..55bec77 --- /dev/null +++ b/static/icons/arrow-right-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/arrow-right.svg b/static/icons/arrow-right.svg new file mode 100644 index 0000000..5c5494f --- /dev/null +++ b/static/icons/arrow-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-up-circle.svg b/static/icons/arrow-up-circle.svg new file mode 100644 index 0000000..fd794fb --- /dev/null +++ b/static/icons/arrow-up-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/arrow-up-down.svg b/static/icons/arrow-up-down.svg new file mode 100644 index 0000000..5861a33 --- /dev/null +++ b/static/icons/arrow-up-down.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/arrow-up-left.svg b/static/icons/arrow-up-left.svg new file mode 100644 index 0000000..170f9cc --- /dev/null +++ b/static/icons/arrow-up-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-up-right.svg b/static/icons/arrow-up-right.svg new file mode 100644 index 0000000..e2568f7 --- /dev/null +++ b/static/icons/arrow-up-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/arrow-up.svg b/static/icons/arrow-up.svg new file mode 100644 index 0000000..f1ff621 --- /dev/null +++ b/static/icons/arrow-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/asterisk.svg b/static/icons/asterisk.svg new file mode 100644 index 0000000..9629c6d --- /dev/null +++ b/static/icons/asterisk.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/at-sign.svg b/static/icons/at-sign.svg new file mode 100644 index 0000000..0b7fdfb --- /dev/null +++ b/static/icons/at-sign.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/award.svg b/static/icons/award.svg new file mode 100644 index 0000000..6b51368 --- /dev/null +++ b/static/icons/award.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/axe.svg b/static/icons/axe.svg new file mode 100644 index 0000000..2a67e4d --- /dev/null +++ b/static/icons/axe.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/axis-3d.svg b/static/icons/axis-3d.svg new file mode 100644 index 0000000..7185ef6 --- /dev/null +++ b/static/icons/axis-3d.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/baby.svg b/static/icons/baby.svg new file mode 100644 index 0000000..0939ba7 --- /dev/null +++ b/static/icons/baby.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/backpack.svg b/static/icons/backpack.svg new file mode 100644 index 0000000..217a28d --- /dev/null +++ b/static/icons/backpack.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/baggage-claim.svg b/static/icons/baggage-claim.svg new file mode 100644 index 0000000..6e858a5 --- /dev/null +++ b/static/icons/baggage-claim.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/banana.svg b/static/icons/banana.svg new file mode 100644 index 0000000..4156613 --- /dev/null +++ b/static/icons/banana.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/banknote.svg b/static/icons/banknote.svg new file mode 100644 index 0000000..af14b58 --- /dev/null +++ b/static/icons/banknote.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bar-chart-2.svg b/static/icons/bar-chart-2.svg new file mode 100644 index 0000000..5463d30 --- /dev/null +++ b/static/icons/bar-chart-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bar-chart-3.svg b/static/icons/bar-chart-3.svg new file mode 100644 index 0000000..f049a03 --- /dev/null +++ b/static/icons/bar-chart-3.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bar-chart-4.svg b/static/icons/bar-chart-4.svg new file mode 100644 index 0000000..f44017f --- /dev/null +++ b/static/icons/bar-chart-4.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bar-chart-horizontal.svg b/static/icons/bar-chart-horizontal.svg new file mode 100644 index 0000000..886f6b4 --- /dev/null +++ b/static/icons/bar-chart-horizontal.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bar-chart.svg b/static/icons/bar-chart.svg new file mode 100644 index 0000000..103ce11 --- /dev/null +++ b/static/icons/bar-chart.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/baseline.svg b/static/icons/baseline.svg new file mode 100644 index 0000000..976c18b --- /dev/null +++ b/static/icons/baseline.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bath.svg b/static/icons/bath.svg new file mode 100644 index 0000000..707ea59 --- /dev/null +++ b/static/icons/bath.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/battery-charging.svg b/static/icons/battery-charging.svg new file mode 100644 index 0000000..d7fa254 --- /dev/null +++ b/static/icons/battery-charging.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/battery-full.svg b/static/icons/battery-full.svg new file mode 100644 index 0000000..032e316 --- /dev/null +++ b/static/icons/battery-full.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/battery-low.svg b/static/icons/battery-low.svg new file mode 100644 index 0000000..1e8c86c --- /dev/null +++ b/static/icons/battery-low.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/battery-medium.svg b/static/icons/battery-medium.svg new file mode 100644 index 0000000..77ed447 --- /dev/null +++ b/static/icons/battery-medium.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/battery.svg b/static/icons/battery.svg new file mode 100644 index 0000000..b3546de --- /dev/null +++ b/static/icons/battery.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/beaker.svg b/static/icons/beaker.svg new file mode 100644 index 0000000..e6f7bb2 --- /dev/null +++ b/static/icons/beaker.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bean-off.svg b/static/icons/bean-off.svg new file mode 100644 index 0000000..17dcccc --- /dev/null +++ b/static/icons/bean-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bean.svg b/static/icons/bean.svg new file mode 100644 index 0000000..e9135e1 --- /dev/null +++ b/static/icons/bean.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/bed-double.svg b/static/icons/bed-double.svg new file mode 100644 index 0000000..e47647d --- /dev/null +++ b/static/icons/bed-double.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bed-single.svg b/static/icons/bed-single.svg new file mode 100644 index 0000000..903361e --- /dev/null +++ b/static/icons/bed-single.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bed.svg b/static/icons/bed.svg new file mode 100644 index 0000000..492513b --- /dev/null +++ b/static/icons/bed.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/beer.svg b/static/icons/beer.svg new file mode 100644 index 0000000..5a8a575 --- /dev/null +++ b/static/icons/beer.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/bell-minus.svg b/static/icons/bell-minus.svg new file mode 100644 index 0000000..7551dcf --- /dev/null +++ b/static/icons/bell-minus.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bell-off.svg b/static/icons/bell-off.svg new file mode 100644 index 0000000..582b5b4 --- /dev/null +++ b/static/icons/bell-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/bell-plus.svg b/static/icons/bell-plus.svg new file mode 100644 index 0000000..08dc7f5 --- /dev/null +++ b/static/icons/bell-plus.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bell-ring.svg b/static/icons/bell-ring.svg new file mode 100644 index 0000000..f1d0213 --- /dev/null +++ b/static/icons/bell-ring.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/bell.svg b/static/icons/bell.svg new file mode 100644 index 0000000..464fce5 --- /dev/null +++ b/static/icons/bell.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/bike.svg b/static/icons/bike.svg new file mode 100644 index 0000000..d932cac --- /dev/null +++ b/static/icons/bike.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/binary.svg b/static/icons/binary.svg new file mode 100644 index 0000000..b92a397 --- /dev/null +++ b/static/icons/binary.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/bitcoin.svg b/static/icons/bitcoin.svg new file mode 100644 index 0000000..e7346fa --- /dev/null +++ b/static/icons/bitcoin.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/bluetooth-connected.svg b/static/icons/bluetooth-connected.svg new file mode 100644 index 0000000..508ad44 --- /dev/null +++ b/static/icons/bluetooth-connected.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bluetooth-off.svg b/static/icons/bluetooth-off.svg new file mode 100644 index 0000000..633256d --- /dev/null +++ b/static/icons/bluetooth-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bluetooth-searching.svg b/static/icons/bluetooth-searching.svg new file mode 100644 index 0000000..001e6d5 --- /dev/null +++ b/static/icons/bluetooth-searching.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bluetooth.svg b/static/icons/bluetooth.svg new file mode 100644 index 0000000..e759115 --- /dev/null +++ b/static/icons/bluetooth.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/bold.svg b/static/icons/bold.svg new file mode 100644 index 0000000..42bc5f1 --- /dev/null +++ b/static/icons/bold.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/bomb.svg b/static/icons/bomb.svg new file mode 100644 index 0000000..0021680 --- /dev/null +++ b/static/icons/bomb.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bone.svg b/static/icons/bone.svg new file mode 100644 index 0000000..bba0135 --- /dev/null +++ b/static/icons/bone.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/book-open-check.svg b/static/icons/book-open-check.svg new file mode 100644 index 0000000..f376746 --- /dev/null +++ b/static/icons/book-open-check.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/book-open.svg b/static/icons/book-open.svg new file mode 100644 index 0000000..c0a279d --- /dev/null +++ b/static/icons/book-open.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/book.svg b/static/icons/book.svg new file mode 100644 index 0000000..3becfa4 --- /dev/null +++ b/static/icons/book.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/bookmark-minus.svg b/static/icons/bookmark-minus.svg new file mode 100644 index 0000000..30e1398 --- /dev/null +++ b/static/icons/bookmark-minus.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/bookmark-plus.svg b/static/icons/bookmark-plus.svg new file mode 100644 index 0000000..1fffdf5 --- /dev/null +++ b/static/icons/bookmark-plus.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/bookmark.svg b/static/icons/bookmark.svg new file mode 100644 index 0000000..d38d42d --- /dev/null +++ b/static/icons/bookmark.svg @@ -0,0 +1,14 @@ + + + diff --git a/static/icons/bot.svg b/static/icons/bot.svg new file mode 100644 index 0000000..4bce681 --- /dev/null +++ b/static/icons/bot.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/box-select.svg b/static/icons/box-select.svg new file mode 100644 index 0000000..f0822a3 --- /dev/null +++ b/static/icons/box-select.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + diff --git a/static/icons/box.svg b/static/icons/box.svg new file mode 100644 index 0000000..4f7fca3 --- /dev/null +++ b/static/icons/box.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/boxes.svg b/static/icons/boxes.svg new file mode 100644 index 0000000..fddb08c --- /dev/null +++ b/static/icons/boxes.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + diff --git a/static/icons/briefcase.svg b/static/icons/briefcase.svg new file mode 100644 index 0000000..4178c4e --- /dev/null +++ b/static/icons/briefcase.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/brush.svg b/static/icons/brush.svg new file mode 100644 index 0000000..6613483 --- /dev/null +++ b/static/icons/brush.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/bug.svg b/static/icons/bug.svg new file mode 100644 index 0000000..f4be113 --- /dev/null +++ b/static/icons/bug.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/building-2.svg b/static/icons/building-2.svg new file mode 100644 index 0000000..a9161eb --- /dev/null +++ b/static/icons/building-2.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/building.svg b/static/icons/building.svg new file mode 100644 index 0000000..1a010d7 --- /dev/null +++ b/static/icons/building.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/static/icons/bus.svg b/static/icons/bus.svg new file mode 100644 index 0000000..dd21ed1 --- /dev/null +++ b/static/icons/bus.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/cake.svg b/static/icons/cake.svg new file mode 100644 index 0000000..175b143 --- /dev/null +++ b/static/icons/cake.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/calculator.svg b/static/icons/calculator.svg new file mode 100644 index 0000000..c10484d --- /dev/null +++ b/static/icons/calculator.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/calendar-check-2.svg b/static/icons/calendar-check-2.svg new file mode 100644 index 0000000..7fbce61 --- /dev/null +++ b/static/icons/calendar-check-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/calendar-check.svg b/static/icons/calendar-check.svg new file mode 100644 index 0000000..11de0fd --- /dev/null +++ b/static/icons/calendar-check.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/calendar-clock.svg b/static/icons/calendar-clock.svg new file mode 100644 index 0000000..a1c19bd --- /dev/null +++ b/static/icons/calendar-clock.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/calendar-days.svg b/static/icons/calendar-days.svg new file mode 100644 index 0000000..c7b2667 --- /dev/null +++ b/static/icons/calendar-days.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/calendar-heart.svg b/static/icons/calendar-heart.svg new file mode 100644 index 0000000..18bb1f7 --- /dev/null +++ b/static/icons/calendar-heart.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/calendar-minus.svg b/static/icons/calendar-minus.svg new file mode 100644 index 0000000..1cb7cd2 --- /dev/null +++ b/static/icons/calendar-minus.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/calendar-off.svg b/static/icons/calendar-off.svg new file mode 100644 index 0000000..b3aaa40 --- /dev/null +++ b/static/icons/calendar-off.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/calendar-plus.svg b/static/icons/calendar-plus.svg new file mode 100644 index 0000000..b8d6946 --- /dev/null +++ b/static/icons/calendar-plus.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/calendar-range.svg b/static/icons/calendar-range.svg new file mode 100644 index 0000000..b4cf879 --- /dev/null +++ b/static/icons/calendar-range.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/calendar-search.svg b/static/icons/calendar-search.svg new file mode 100644 index 0000000..5ad25ae --- /dev/null +++ b/static/icons/calendar-search.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/calendar-x-2.svg b/static/icons/calendar-x-2.svg new file mode 100644 index 0000000..bd86174 --- /dev/null +++ b/static/icons/calendar-x-2.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/calendar-x.svg b/static/icons/calendar-x.svg new file mode 100644 index 0000000..0cbb311 --- /dev/null +++ b/static/icons/calendar-x.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/calendar.svg b/static/icons/calendar.svg new file mode 100644 index 0000000..c002b85 --- /dev/null +++ b/static/icons/calendar.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/camera-off.svg b/static/icons/camera-off.svg new file mode 100644 index 0000000..db9ba74 --- /dev/null +++ b/static/icons/camera-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/camera.svg b/static/icons/camera.svg new file mode 100644 index 0000000..155a04c --- /dev/null +++ b/static/icons/camera.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/candy-off.svg b/static/icons/candy-off.svg new file mode 100644 index 0000000..0416ba4 --- /dev/null +++ b/static/icons/candy-off.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/candy.svg b/static/icons/candy.svg new file mode 100644 index 0000000..a59286c --- /dev/null +++ b/static/icons/candy.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/car.svg b/static/icons/car.svg new file mode 100644 index 0000000..2e89572 --- /dev/null +++ b/static/icons/car.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/carrot.svg b/static/icons/carrot.svg new file mode 100644 index 0000000..6cad8b2 --- /dev/null +++ b/static/icons/carrot.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/cast.svg b/static/icons/cast.svg new file mode 100644 index 0000000..51249e5 --- /dev/null +++ b/static/icons/cast.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/cat.svg b/static/icons/cat.svg new file mode 100644 index 0000000..c4f2b75 --- /dev/null +++ b/static/icons/cat.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/check-check.svg b/static/icons/check-check.svg new file mode 100644 index 0000000..f1c28ab --- /dev/null +++ b/static/icons/check-check.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/check-circle-2.svg b/static/icons/check-circle-2.svg new file mode 100644 index 0000000..903d759 --- /dev/null +++ b/static/icons/check-circle-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/check-circle.svg b/static/icons/check-circle.svg new file mode 100644 index 0000000..418f300 --- /dev/null +++ b/static/icons/check-circle.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/check-square.svg b/static/icons/check-square.svg new file mode 100644 index 0000000..7f8fe6b --- /dev/null +++ b/static/icons/check-square.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/check.svg b/static/icons/check.svg new file mode 100644 index 0000000..80aaf84 --- /dev/null +++ b/static/icons/check.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/chef-hat.svg b/static/icons/chef-hat.svg new file mode 100644 index 0000000..ac18b7b --- /dev/null +++ b/static/icons/chef-hat.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cherry.svg b/static/icons/cherry.svg new file mode 100644 index 0000000..e713ce1 --- /dev/null +++ b/static/icons/cherry.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/chevron-down.svg b/static/icons/chevron-down.svg new file mode 100644 index 0000000..bda8e89 --- /dev/null +++ b/static/icons/chevron-down.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/chevron-first.svg b/static/icons/chevron-first.svg new file mode 100644 index 0000000..b34973c --- /dev/null +++ b/static/icons/chevron-first.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevron-last.svg b/static/icons/chevron-last.svg new file mode 100644 index 0000000..2204009 --- /dev/null +++ b/static/icons/chevron-last.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevron-left.svg b/static/icons/chevron-left.svg new file mode 100644 index 0000000..5af8840 --- /dev/null +++ b/static/icons/chevron-left.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/chevron-right.svg b/static/icons/chevron-right.svg new file mode 100644 index 0000000..fde2d64 --- /dev/null +++ b/static/icons/chevron-right.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/chevron-up.svg b/static/icons/chevron-up.svg new file mode 100644 index 0000000..085188c --- /dev/null +++ b/static/icons/chevron-up.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/chevrons-down-up.svg b/static/icons/chevrons-down-up.svg new file mode 100644 index 0000000..955914e --- /dev/null +++ b/static/icons/chevrons-down-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-down.svg b/static/icons/chevrons-down.svg new file mode 100644 index 0000000..fac1aef --- /dev/null +++ b/static/icons/chevrons-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-left-right.svg b/static/icons/chevrons-left-right.svg new file mode 100644 index 0000000..c19b695 --- /dev/null +++ b/static/icons/chevrons-left-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-left.svg b/static/icons/chevrons-left.svg new file mode 100644 index 0000000..712f4bc --- /dev/null +++ b/static/icons/chevrons-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-right-left.svg b/static/icons/chevrons-right-left.svg new file mode 100644 index 0000000..b60920f --- /dev/null +++ b/static/icons/chevrons-right-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-right.svg b/static/icons/chevrons-right.svg new file mode 100644 index 0000000..1794243 --- /dev/null +++ b/static/icons/chevrons-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-up-down.svg b/static/icons/chevrons-up-down.svg new file mode 100644 index 0000000..bd8833d --- /dev/null +++ b/static/icons/chevrons-up-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chevrons-up.svg b/static/icons/chevrons-up.svg new file mode 100644 index 0000000..7e38fb5 --- /dev/null +++ b/static/icons/chevrons-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/chrome.svg b/static/icons/chrome.svg new file mode 100644 index 0000000..7b4bc1a --- /dev/null +++ b/static/icons/chrome.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/cigarette-off.svg b/static/icons/cigarette-off.svg new file mode 100644 index 0000000..84b00b0 --- /dev/null +++ b/static/icons/cigarette-off.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/cigarette.svg b/static/icons/cigarette.svg new file mode 100644 index 0000000..eade385 --- /dev/null +++ b/static/icons/cigarette.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/circle-dot.svg b/static/icons/circle-dot.svg new file mode 100644 index 0000000..357549b --- /dev/null +++ b/static/icons/circle-dot.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/circle-ellipsis.svg b/static/icons/circle-ellipsis.svg new file mode 100644 index 0000000..5efa1b3 --- /dev/null +++ b/static/icons/circle-ellipsis.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/circle-slashed.svg b/static/icons/circle-slashed.svg new file mode 100644 index 0000000..fc6a046 --- /dev/null +++ b/static/icons/circle-slashed.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/circle.svg b/static/icons/circle.svg new file mode 100644 index 0000000..1717bb4 --- /dev/null +++ b/static/icons/circle.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/citrus.svg b/static/icons/citrus.svg new file mode 100644 index 0000000..1bc6580 --- /dev/null +++ b/static/icons/citrus.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/clapperboard.svg b/static/icons/clapperboard.svg new file mode 100644 index 0000000..3f91059 --- /dev/null +++ b/static/icons/clapperboard.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/clipboard-check.svg b/static/icons/clipboard-check.svg new file mode 100644 index 0000000..8d6bcb6 --- /dev/null +++ b/static/icons/clipboard-check.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/clipboard-copy.svg b/static/icons/clipboard-copy.svg new file mode 100644 index 0000000..83f6954 --- /dev/null +++ b/static/icons/clipboard-copy.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/clipboard-edit.svg b/static/icons/clipboard-edit.svg new file mode 100644 index 0000000..ee8f55f --- /dev/null +++ b/static/icons/clipboard-edit.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/clipboard-list.svg b/static/icons/clipboard-list.svg new file mode 100644 index 0000000..0ae6032 --- /dev/null +++ b/static/icons/clipboard-list.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/clipboard-signature.svg b/static/icons/clipboard-signature.svg new file mode 100644 index 0000000..5dfd4df --- /dev/null +++ b/static/icons/clipboard-signature.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/clipboard-type.svg b/static/icons/clipboard-type.svg new file mode 100644 index 0000000..95e6897 --- /dev/null +++ b/static/icons/clipboard-type.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/clipboard-x.svg b/static/icons/clipboard-x.svg new file mode 100644 index 0000000..e5641c3 --- /dev/null +++ b/static/icons/clipboard-x.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/clipboard.svg b/static/icons/clipboard.svg new file mode 100644 index 0000000..f61cea7 --- /dev/null +++ b/static/icons/clipboard.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-1.svg b/static/icons/clock-1.svg new file mode 100644 index 0000000..154c5b7 --- /dev/null +++ b/static/icons/clock-1.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-10.svg b/static/icons/clock-10.svg new file mode 100644 index 0000000..ca654e2 --- /dev/null +++ b/static/icons/clock-10.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-11.svg b/static/icons/clock-11.svg new file mode 100644 index 0000000..7d015ad --- /dev/null +++ b/static/icons/clock-11.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-12.svg b/static/icons/clock-12.svg new file mode 100644 index 0000000..910bccf --- /dev/null +++ b/static/icons/clock-12.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-2.svg b/static/icons/clock-2.svg new file mode 100644 index 0000000..75c848a --- /dev/null +++ b/static/icons/clock-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-3.svg b/static/icons/clock-3.svg new file mode 100644 index 0000000..4a25e0f --- /dev/null +++ b/static/icons/clock-3.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-4.svg b/static/icons/clock-4.svg new file mode 100644 index 0000000..8ce25b2 --- /dev/null +++ b/static/icons/clock-4.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-5.svg b/static/icons/clock-5.svg new file mode 100644 index 0000000..0f9081a --- /dev/null +++ b/static/icons/clock-5.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-6.svg b/static/icons/clock-6.svg new file mode 100644 index 0000000..5b0f26f --- /dev/null +++ b/static/icons/clock-6.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-7.svg b/static/icons/clock-7.svg new file mode 100644 index 0000000..7fd365a --- /dev/null +++ b/static/icons/clock-7.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-8.svg b/static/icons/clock-8.svg new file mode 100644 index 0000000..602695f --- /dev/null +++ b/static/icons/clock-8.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock-9.svg b/static/icons/clock-9.svg new file mode 100644 index 0000000..8e6e3fa --- /dev/null +++ b/static/icons/clock-9.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clock.svg b/static/icons/clock.svg new file mode 100644 index 0000000..8ce25b2 --- /dev/null +++ b/static/icons/clock.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cloud-cog.svg b/static/icons/cloud-cog.svg new file mode 100644 index 0000000..2c3a938 --- /dev/null +++ b/static/icons/cloud-cog.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/cloud-drizzle.svg b/static/icons/cloud-drizzle.svg new file mode 100644 index 0000000..01670e3 --- /dev/null +++ b/static/icons/cloud-drizzle.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/cloud-fog.svg b/static/icons/cloud-fog.svg new file mode 100644 index 0000000..aee9fc0 --- /dev/null +++ b/static/icons/cloud-fog.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/cloud-hail.svg b/static/icons/cloud-hail.svg new file mode 100644 index 0000000..3158de5 --- /dev/null +++ b/static/icons/cloud-hail.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/cloud-lightning.svg b/static/icons/cloud-lightning.svg new file mode 100644 index 0000000..3f11bb3 --- /dev/null +++ b/static/icons/cloud-lightning.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cloud-moon-rain.svg b/static/icons/cloud-moon-rain.svg new file mode 100644 index 0000000..d76f103 --- /dev/null +++ b/static/icons/cloud-moon-rain.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/cloud-moon.svg b/static/icons/cloud-moon.svg new file mode 100644 index 0000000..0d205e8 --- /dev/null +++ b/static/icons/cloud-moon.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cloud-off.svg b/static/icons/cloud-off.svg new file mode 100644 index 0000000..6bc830e --- /dev/null +++ b/static/icons/cloud-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/cloud-rain-wind.svg b/static/icons/cloud-rain-wind.svg new file mode 100644 index 0000000..f6a4560 --- /dev/null +++ b/static/icons/cloud-rain-wind.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/cloud-rain.svg b/static/icons/cloud-rain.svg new file mode 100644 index 0000000..2a79fcf --- /dev/null +++ b/static/icons/cloud-rain.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/cloud-snow.svg b/static/icons/cloud-snow.svg new file mode 100644 index 0000000..53a3ffa --- /dev/null +++ b/static/icons/cloud-snow.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/cloud-sun-rain.svg b/static/icons/cloud-sun-rain.svg new file mode 100644 index 0000000..b3de2ba --- /dev/null +++ b/static/icons/cloud-sun-rain.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/cloud-sun.svg b/static/icons/cloud-sun.svg new file mode 100644 index 0000000..8d7705d --- /dev/null +++ b/static/icons/cloud-sun.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/cloud.svg b/static/icons/cloud.svg new file mode 100644 index 0000000..96c52fc --- /dev/null +++ b/static/icons/cloud.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/cloudy.svg b/static/icons/cloudy.svg new file mode 100644 index 0000000..088fa86 --- /dev/null +++ b/static/icons/cloudy.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/clover.svg b/static/icons/clover.svg new file mode 100644 index 0000000..9880c30 --- /dev/null +++ b/static/icons/clover.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/code-2.svg b/static/icons/code-2.svg new file mode 100644 index 0000000..74f2299 --- /dev/null +++ b/static/icons/code-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/code.svg b/static/icons/code.svg new file mode 100644 index 0000000..da0f522 --- /dev/null +++ b/static/icons/code.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/codepen.svg b/static/icons/codepen.svg new file mode 100644 index 0000000..2f350f1 --- /dev/null +++ b/static/icons/codepen.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/codesandbox.svg b/static/icons/codesandbox.svg new file mode 100644 index 0000000..db203af --- /dev/null +++ b/static/icons/codesandbox.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/coffee.svg b/static/icons/coffee.svg new file mode 100644 index 0000000..c1aa9cf --- /dev/null +++ b/static/icons/coffee.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/cog.svg b/static/icons/cog.svg new file mode 100644 index 0000000..5db1c80 --- /dev/null +++ b/static/icons/cog.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/static/icons/coins.svg b/static/icons/coins.svg new file mode 100644 index 0000000..063bdb2 --- /dev/null +++ b/static/icons/coins.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/columns.svg b/static/icons/columns.svg new file mode 100644 index 0000000..9bc777f --- /dev/null +++ b/static/icons/columns.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/command.svg b/static/icons/command.svg new file mode 100644 index 0000000..0817c6c --- /dev/null +++ b/static/icons/command.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/compass.svg b/static/icons/compass.svg new file mode 100644 index 0000000..5550490 --- /dev/null +++ b/static/icons/compass.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/component.svg b/static/icons/component.svg new file mode 100644 index 0000000..e7f1b43 --- /dev/null +++ b/static/icons/component.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/concierge-bell.svg b/static/icons/concierge-bell.svg new file mode 100644 index 0000000..0f49fa9 --- /dev/null +++ b/static/icons/concierge-bell.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/contact.svg b/static/icons/contact.svg new file mode 100644 index 0000000..6c8d8f8 --- /dev/null +++ b/static/icons/contact.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/contrast.svg b/static/icons/contrast.svg new file mode 100644 index 0000000..334f528 --- /dev/null +++ b/static/icons/contrast.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cookie.svg b/static/icons/cookie.svg new file mode 100644 index 0000000..1bdedba --- /dev/null +++ b/static/icons/cookie.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/copy.svg b/static/icons/copy.svg new file mode 100644 index 0000000..c8d4956 --- /dev/null +++ b/static/icons/copy.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/copyleft.svg b/static/icons/copyleft.svg new file mode 100644 index 0000000..7048bbb --- /dev/null +++ b/static/icons/copyleft.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/copyright.svg b/static/icons/copyright.svg new file mode 100644 index 0000000..d151d9e --- /dev/null +++ b/static/icons/copyright.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-down-left.svg b/static/icons/corner-down-left.svg new file mode 100644 index 0000000..71696a4 --- /dev/null +++ b/static/icons/corner-down-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-down-right.svg b/static/icons/corner-down-right.svg new file mode 100644 index 0000000..dd9f7a4 --- /dev/null +++ b/static/icons/corner-down-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-left-down.svg b/static/icons/corner-left-down.svg new file mode 100644 index 0000000..5c44b7d --- /dev/null +++ b/static/icons/corner-left-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-left-up.svg b/static/icons/corner-left-up.svg new file mode 100644 index 0000000..cd75292 --- /dev/null +++ b/static/icons/corner-left-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-right-down.svg b/static/icons/corner-right-down.svg new file mode 100644 index 0000000..aa4690a --- /dev/null +++ b/static/icons/corner-right-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-right-up.svg b/static/icons/corner-right-up.svg new file mode 100644 index 0000000..fd80c2c --- /dev/null +++ b/static/icons/corner-right-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-up-left.svg b/static/icons/corner-up-left.svg new file mode 100644 index 0000000..76b5bfb --- /dev/null +++ b/static/icons/corner-up-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/corner-up-right.svg b/static/icons/corner-up-right.svg new file mode 100644 index 0000000..755cbfd --- /dev/null +++ b/static/icons/corner-up-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cpu.svg b/static/icons/cpu.svg new file mode 100644 index 0000000..8aa6bb9 --- /dev/null +++ b/static/icons/cpu.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/credit-card.svg b/static/icons/credit-card.svg new file mode 100644 index 0000000..5a081c9 --- /dev/null +++ b/static/icons/credit-card.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/croissant.svg b/static/icons/croissant.svg new file mode 100644 index 0000000..7fea7ea --- /dev/null +++ b/static/icons/croissant.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/crop.svg b/static/icons/crop.svg new file mode 100644 index 0000000..4ca1e6f --- /dev/null +++ b/static/icons/crop.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/cross.svg b/static/icons/cross.svg new file mode 100644 index 0000000..c0eb300 --- /dev/null +++ b/static/icons/cross.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/crosshair.svg b/static/icons/crosshair.svg new file mode 100644 index 0000000..2c44849 --- /dev/null +++ b/static/icons/crosshair.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/crown.svg b/static/icons/crown.svg new file mode 100644 index 0000000..d61ac2d --- /dev/null +++ b/static/icons/crown.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/cup-soda.svg b/static/icons/cup-soda.svg new file mode 100644 index 0000000..f745c7a --- /dev/null +++ b/static/icons/cup-soda.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/curly-braces.svg b/static/icons/curly-braces.svg new file mode 100644 index 0000000..d56b1dc --- /dev/null +++ b/static/icons/curly-braces.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/currency.svg b/static/icons/currency.svg new file mode 100644 index 0000000..928a9e2 --- /dev/null +++ b/static/icons/currency.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/database.svg b/static/icons/database.svg new file mode 100644 index 0000000..0afca6b --- /dev/null +++ b/static/icons/database.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/delete.svg b/static/icons/delete.svg new file mode 100644 index 0000000..53858ee --- /dev/null +++ b/static/icons/delete.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/diamond.svg b/static/icons/diamond.svg new file mode 100644 index 0000000..87581fe --- /dev/null +++ b/static/icons/diamond.svg @@ -0,0 +1,20 @@ + + + diff --git a/static/icons/dice-1.svg b/static/icons/dice-1.svg new file mode 100644 index 0000000..cd1846a --- /dev/null +++ b/static/icons/dice-1.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/dice-2.svg b/static/icons/dice-2.svg new file mode 100644 index 0000000..09e2066 --- /dev/null +++ b/static/icons/dice-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/dice-3.svg b/static/icons/dice-3.svg new file mode 100644 index 0000000..46e7f1b --- /dev/null +++ b/static/icons/dice-3.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/dice-4.svg b/static/icons/dice-4.svg new file mode 100644 index 0000000..53495a9 --- /dev/null +++ b/static/icons/dice-4.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/dice-5.svg b/static/icons/dice-5.svg new file mode 100644 index 0000000..256ee64 --- /dev/null +++ b/static/icons/dice-5.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/dice-6.svg b/static/icons/dice-6.svg new file mode 100644 index 0000000..3106d1c --- /dev/null +++ b/static/icons/dice-6.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/dices.svg b/static/icons/dices.svg new file mode 100644 index 0000000..e5f4b0d --- /dev/null +++ b/static/icons/dices.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/diff.svg b/static/icons/diff.svg new file mode 100644 index 0000000..ac0307b --- /dev/null +++ b/static/icons/diff.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/disc.svg b/static/icons/disc.svg new file mode 100644 index 0000000..df07c00 --- /dev/null +++ b/static/icons/disc.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/divide-circle.svg b/static/icons/divide-circle.svg new file mode 100644 index 0000000..fc1b2ae --- /dev/null +++ b/static/icons/divide-circle.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/divide-square.svg b/static/icons/divide-square.svg new file mode 100644 index 0000000..bec8c4a --- /dev/null +++ b/static/icons/divide-square.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/divide.svg b/static/icons/divide.svg new file mode 100644 index 0000000..1f4b79d --- /dev/null +++ b/static/icons/divide.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/dna-off.svg b/static/icons/dna-off.svg new file mode 100644 index 0000000..70653e1 --- /dev/null +++ b/static/icons/dna-off.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/static/icons/dna.svg b/static/icons/dna.svg new file mode 100644 index 0000000..4b496b8 --- /dev/null +++ b/static/icons/dna.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/static/icons/dog.svg b/static/icons/dog.svg new file mode 100644 index 0000000..ad6591a --- /dev/null +++ b/static/icons/dog.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/dollar-sign.svg b/static/icons/dollar-sign.svg new file mode 100644 index 0000000..6987c9b --- /dev/null +++ b/static/icons/dollar-sign.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/download-cloud.svg b/static/icons/download-cloud.svg new file mode 100644 index 0000000..045af58 --- /dev/null +++ b/static/icons/download-cloud.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/download.svg b/static/icons/download.svg new file mode 100644 index 0000000..6865ea3 --- /dev/null +++ b/static/icons/download.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/dribbble.svg b/static/icons/dribbble.svg new file mode 100644 index 0000000..18d2e1f --- /dev/null +++ b/static/icons/dribbble.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/droplet.svg b/static/icons/droplet.svg new file mode 100644 index 0000000..36aa334 --- /dev/null +++ b/static/icons/droplet.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/droplets.svg b/static/icons/droplets.svg new file mode 100644 index 0000000..b531e9c --- /dev/null +++ b/static/icons/droplets.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/drumstick.svg b/static/icons/drumstick.svg new file mode 100644 index 0000000..259fd75 --- /dev/null +++ b/static/icons/drumstick.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/dumbbell.svg b/static/icons/dumbbell.svg new file mode 100644 index 0000000..9a8c14e --- /dev/null +++ b/static/icons/dumbbell.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/ear-off.svg b/static/icons/ear-off.svg new file mode 100644 index 0000000..6500235 --- /dev/null +++ b/static/icons/ear-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/ear.svg b/static/icons/ear.svg new file mode 100644 index 0000000..1d2b7fb --- /dev/null +++ b/static/icons/ear.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/edit-2.svg b/static/icons/edit-2.svg new file mode 100644 index 0000000..dcd4409 --- /dev/null +++ b/static/icons/edit-2.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/edit-3.svg b/static/icons/edit-3.svg new file mode 100644 index 0000000..70cfb53 --- /dev/null +++ b/static/icons/edit-3.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/edit.svg b/static/icons/edit.svg new file mode 100644 index 0000000..559141b --- /dev/null +++ b/static/icons/edit.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/egg-fried.svg b/static/icons/egg-fried.svg new file mode 100644 index 0000000..240883b --- /dev/null +++ b/static/icons/egg-fried.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/egg-off.svg b/static/icons/egg-off.svg new file mode 100644 index 0000000..e06179f --- /dev/null +++ b/static/icons/egg-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/egg.svg b/static/icons/egg.svg new file mode 100644 index 0000000..357deaf --- /dev/null +++ b/static/icons/egg.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/equal-not.svg b/static/icons/equal-not.svg new file mode 100644 index 0000000..9525f33 --- /dev/null +++ b/static/icons/equal-not.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/equal.svg b/static/icons/equal.svg new file mode 100644 index 0000000..2358e0a --- /dev/null +++ b/static/icons/equal.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/eraser.svg b/static/icons/eraser.svg new file mode 100644 index 0000000..4ff842c --- /dev/null +++ b/static/icons/eraser.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/euro.svg b/static/icons/euro.svg new file mode 100644 index 0000000..9889770 --- /dev/null +++ b/static/icons/euro.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/expand.svg b/static/icons/expand.svg new file mode 100644 index 0000000..2fd8475 --- /dev/null +++ b/static/icons/expand.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/external-link.svg b/static/icons/external-link.svg new file mode 100644 index 0000000..537b731 --- /dev/null +++ b/static/icons/external-link.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/eye-off.svg b/static/icons/eye-off.svg new file mode 100644 index 0000000..feabed1 --- /dev/null +++ b/static/icons/eye-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/eye.svg b/static/icons/eye.svg new file mode 100644 index 0000000..663693c --- /dev/null +++ b/static/icons/eye.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/facebook.svg b/static/icons/facebook.svg new file mode 100644 index 0000000..8be7109 --- /dev/null +++ b/static/icons/facebook.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/factory.svg b/static/icons/factory.svg new file mode 100644 index 0000000..fd673ee --- /dev/null +++ b/static/icons/factory.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/fan.svg b/static/icons/fan.svg new file mode 100644 index 0000000..5b1ecb8 --- /dev/null +++ b/static/icons/fan.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/fast-forward.svg b/static/icons/fast-forward.svg new file mode 100644 index 0000000..6c8409c --- /dev/null +++ b/static/icons/fast-forward.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/feather.svg b/static/icons/feather.svg new file mode 100644 index 0000000..40d7ef8 --- /dev/null +++ b/static/icons/feather.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/figma.svg b/static/icons/figma.svg new file mode 100644 index 0000000..cfc932a --- /dev/null +++ b/static/icons/figma.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-archive.svg b/static/icons/file-archive.svg new file mode 100644 index 0000000..00486c0 --- /dev/null +++ b/static/icons/file-archive.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/file-audio-2.svg b/static/icons/file-audio-2.svg new file mode 100644 index 0000000..5386d89 --- /dev/null +++ b/static/icons/file-audio-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-audio.svg b/static/icons/file-audio.svg new file mode 100644 index 0000000..51a8950 --- /dev/null +++ b/static/icons/file-audio.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-axis-3d.svg b/static/icons/file-axis-3d.svg new file mode 100644 index 0000000..e3add4a --- /dev/null +++ b/static/icons/file-axis-3d.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-badge-2.svg b/static/icons/file-badge-2.svg new file mode 100644 index 0000000..5aef3c4 --- /dev/null +++ b/static/icons/file-badge-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-badge.svg b/static/icons/file-badge.svg new file mode 100644 index 0000000..a5c68e9 --- /dev/null +++ b/static/icons/file-badge.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-bar-chart-2.svg b/static/icons/file-bar-chart-2.svg new file mode 100644 index 0000000..db3a136 --- /dev/null +++ b/static/icons/file-bar-chart-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-bar-chart.svg b/static/icons/file-bar-chart.svg new file mode 100644 index 0000000..40f679a --- /dev/null +++ b/static/icons/file-bar-chart.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-box.svg b/static/icons/file-box.svg new file mode 100644 index 0000000..f96a3fb --- /dev/null +++ b/static/icons/file-box.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/file-check-2.svg b/static/icons/file-check-2.svg new file mode 100644 index 0000000..b8b8211 --- /dev/null +++ b/static/icons/file-check-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-check.svg b/static/icons/file-check.svg new file mode 100644 index 0000000..111eeb5 --- /dev/null +++ b/static/icons/file-check.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-clock.svg b/static/icons/file-clock.svg new file mode 100644 index 0000000..217b647 --- /dev/null +++ b/static/icons/file-clock.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-code.svg b/static/icons/file-code.svg new file mode 100644 index 0000000..913eb0a --- /dev/null +++ b/static/icons/file-code.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-cog-2.svg b/static/icons/file-cog-2.svg new file mode 100644 index 0000000..688e5b5 --- /dev/null +++ b/static/icons/file-cog-2.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/file-cog.svg b/static/icons/file-cog.svg new file mode 100644 index 0000000..01f804a --- /dev/null +++ b/static/icons/file-cog.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/static/icons/file-diff.svg b/static/icons/file-diff.svg new file mode 100644 index 0000000..2706d2a --- /dev/null +++ b/static/icons/file-diff.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-digit.svg b/static/icons/file-digit.svg new file mode 100644 index 0000000..745fbae --- /dev/null +++ b/static/icons/file-digit.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-down.svg b/static/icons/file-down.svg new file mode 100644 index 0000000..bb06695 --- /dev/null +++ b/static/icons/file-down.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-edit.svg b/static/icons/file-edit.svg new file mode 100644 index 0000000..805577a --- /dev/null +++ b/static/icons/file-edit.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-heart.svg b/static/icons/file-heart.svg new file mode 100644 index 0000000..7e0ac99 --- /dev/null +++ b/static/icons/file-heart.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-image.svg b/static/icons/file-image.svg new file mode 100644 index 0000000..ba9f50e --- /dev/null +++ b/static/icons/file-image.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-input.svg b/static/icons/file-input.svg new file mode 100644 index 0000000..2e25fd3 --- /dev/null +++ b/static/icons/file-input.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-json-2.svg b/static/icons/file-json-2.svg new file mode 100644 index 0000000..82cc38c --- /dev/null +++ b/static/icons/file-json-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-json.svg b/static/icons/file-json.svg new file mode 100644 index 0000000..a4ade48 --- /dev/null +++ b/static/icons/file-json.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-key-2.svg b/static/icons/file-key-2.svg new file mode 100644 index 0000000..e640838 --- /dev/null +++ b/static/icons/file-key-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-key.svg b/static/icons/file-key.svg new file mode 100644 index 0000000..e849483 --- /dev/null +++ b/static/icons/file-key.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-line-chart.svg b/static/icons/file-line-chart.svg new file mode 100644 index 0000000..b8bf128 --- /dev/null +++ b/static/icons/file-line-chart.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-lock-2.svg b/static/icons/file-lock-2.svg new file mode 100644 index 0000000..c736d16 --- /dev/null +++ b/static/icons/file-lock-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-lock.svg b/static/icons/file-lock.svg new file mode 100644 index 0000000..a9433ed --- /dev/null +++ b/static/icons/file-lock.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-minus-2.svg b/static/icons/file-minus-2.svg new file mode 100644 index 0000000..f3d869f --- /dev/null +++ b/static/icons/file-minus-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-minus.svg b/static/icons/file-minus.svg new file mode 100644 index 0000000..607b5d6 --- /dev/null +++ b/static/icons/file-minus.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-output.svg b/static/icons/file-output.svg new file mode 100644 index 0000000..4bf81f9 --- /dev/null +++ b/static/icons/file-output.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-pie-chart.svg b/static/icons/file-pie-chart.svg new file mode 100644 index 0000000..137da77 --- /dev/null +++ b/static/icons/file-pie-chart.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-plus-2.svg b/static/icons/file-plus-2.svg new file mode 100644 index 0000000..d5976a8 --- /dev/null +++ b/static/icons/file-plus-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-plus.svg b/static/icons/file-plus.svg new file mode 100644 index 0000000..ba5161f --- /dev/null +++ b/static/icons/file-plus.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-question.svg b/static/icons/file-question.svg new file mode 100644 index 0000000..721e75a --- /dev/null +++ b/static/icons/file-question.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-scan.svg b/static/icons/file-scan.svg new file mode 100644 index 0000000..0aa2ed5 --- /dev/null +++ b/static/icons/file-scan.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/file-search-2.svg b/static/icons/file-search-2.svg new file mode 100644 index 0000000..da61de3 --- /dev/null +++ b/static/icons/file-search-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-search.svg b/static/icons/file-search.svg new file mode 100644 index 0000000..036f59f --- /dev/null +++ b/static/icons/file-search.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-signature.svg b/static/icons/file-signature.svg new file mode 100644 index 0000000..b4cd452 --- /dev/null +++ b/static/icons/file-signature.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-spreadsheet.svg b/static/icons/file-spreadsheet.svg new file mode 100644 index 0000000..78635bb --- /dev/null +++ b/static/icons/file-spreadsheet.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/file-symlink.svg b/static/icons/file-symlink.svg new file mode 100644 index 0000000..05b7b0a --- /dev/null +++ b/static/icons/file-symlink.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-terminal.svg b/static/icons/file-terminal.svg new file mode 100644 index 0000000..148b75e --- /dev/null +++ b/static/icons/file-terminal.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-text.svg b/static/icons/file-text.svg new file mode 100644 index 0000000..7d30acf --- /dev/null +++ b/static/icons/file-text.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-type-2.svg b/static/icons/file-type-2.svg new file mode 100644 index 0000000..c3f5ecb --- /dev/null +++ b/static/icons/file-type-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-type.svg b/static/icons/file-type.svg new file mode 100644 index 0000000..67d7da3 --- /dev/null +++ b/static/icons/file-type.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-up.svg b/static/icons/file-up.svg new file mode 100644 index 0000000..ad6e941 --- /dev/null +++ b/static/icons/file-up.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-video-2.svg b/static/icons/file-video-2.svg new file mode 100644 index 0000000..8d36f0d --- /dev/null +++ b/static/icons/file-video-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-video.svg b/static/icons/file-video.svg new file mode 100644 index 0000000..d41a0fe --- /dev/null +++ b/static/icons/file-video.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-volume-2.svg b/static/icons/file-volume-2.svg new file mode 100644 index 0000000..edab47c --- /dev/null +++ b/static/icons/file-volume-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/file-volume.svg b/static/icons/file-volume.svg new file mode 100644 index 0000000..f6c27b1 --- /dev/null +++ b/static/icons/file-volume.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-warning.svg b/static/icons/file-warning.svg new file mode 100644 index 0000000..51f8b1c --- /dev/null +++ b/static/icons/file-warning.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/file-x-2.svg b/static/icons/file-x-2.svg new file mode 100644 index 0000000..47d5932 --- /dev/null +++ b/static/icons/file-x-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file-x.svg b/static/icons/file-x.svg new file mode 100644 index 0000000..c68afae --- /dev/null +++ b/static/icons/file-x.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/file.svg b/static/icons/file.svg new file mode 100644 index 0000000..534d34d --- /dev/null +++ b/static/icons/file.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/files.svg b/static/icons/files.svg new file mode 100644 index 0000000..0470ba8 --- /dev/null +++ b/static/icons/files.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/film.svg b/static/icons/film.svg new file mode 100644 index 0000000..a9f5b15 --- /dev/null +++ b/static/icons/film.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/filter.svg b/static/icons/filter.svg new file mode 100644 index 0000000..adc513c --- /dev/null +++ b/static/icons/filter.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/fingerprint.svg b/static/icons/fingerprint.svg new file mode 100644 index 0000000..99e4e7d --- /dev/null +++ b/static/icons/fingerprint.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/flag-off.svg b/static/icons/flag-off.svg new file mode 100644 index 0000000..a0ba907 --- /dev/null +++ b/static/icons/flag-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/flag-triangle-left.svg b/static/icons/flag-triangle-left.svg new file mode 100644 index 0000000..732b7fa --- /dev/null +++ b/static/icons/flag-triangle-left.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/flag-triangle-right.svg b/static/icons/flag-triangle-right.svg new file mode 100644 index 0000000..5415554 --- /dev/null +++ b/static/icons/flag-triangle-right.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/flag.svg b/static/icons/flag.svg new file mode 100644 index 0000000..8100a2f --- /dev/null +++ b/static/icons/flag.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/flame.svg b/static/icons/flame.svg new file mode 100644 index 0000000..0abb88a --- /dev/null +++ b/static/icons/flame.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/flashlight-off.svg b/static/icons/flashlight-off.svg new file mode 100644 index 0000000..8390dcf --- /dev/null +++ b/static/icons/flashlight-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/flashlight.svg b/static/icons/flashlight.svg new file mode 100644 index 0000000..db03439 --- /dev/null +++ b/static/icons/flashlight.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/flask-conical-off.svg b/static/icons/flask-conical-off.svg new file mode 100644 index 0000000..51553e5 --- /dev/null +++ b/static/icons/flask-conical-off.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/flask-conical.svg b/static/icons/flask-conical.svg new file mode 100644 index 0000000..f069951 --- /dev/null +++ b/static/icons/flask-conical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/flask-round.svg b/static/icons/flask-round.svg new file mode 100644 index 0000000..58751f1 --- /dev/null +++ b/static/icons/flask-round.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/flip-horizontal-2.svg b/static/icons/flip-horizontal-2.svg new file mode 100644 index 0000000..7e0459d --- /dev/null +++ b/static/icons/flip-horizontal-2.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/flip-horizontal.svg b/static/icons/flip-horizontal.svg new file mode 100644 index 0000000..5319777 --- /dev/null +++ b/static/icons/flip-horizontal.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/flip-vertical-2.svg b/static/icons/flip-vertical-2.svg new file mode 100644 index 0000000..26b0775 --- /dev/null +++ b/static/icons/flip-vertical-2.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/flip-vertical.svg b/static/icons/flip-vertical.svg new file mode 100644 index 0000000..5678c27 --- /dev/null +++ b/static/icons/flip-vertical.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/flower-2.svg b/static/icons/flower-2.svg new file mode 100644 index 0000000..7d89e5e --- /dev/null +++ b/static/icons/flower-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/flower.svg b/static/icons/flower.svg new file mode 100644 index 0000000..9eedfe8 --- /dev/null +++ b/static/icons/flower.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/focus.svg b/static/icons/focus.svg new file mode 100644 index 0000000..c04d45a --- /dev/null +++ b/static/icons/focus.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/folder-archive.svg b/static/icons/folder-archive.svg new file mode 100644 index 0000000..3bd6201 --- /dev/null +++ b/static/icons/folder-archive.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/folder-check.svg b/static/icons/folder-check.svg new file mode 100644 index 0000000..c2a4689 --- /dev/null +++ b/static/icons/folder-check.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/folder-clock.svg b/static/icons/folder-clock.svg new file mode 100644 index 0000000..7260da8 --- /dev/null +++ b/static/icons/folder-clock.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-closed.svg b/static/icons/folder-closed.svg new file mode 100644 index 0000000..79a18d5 --- /dev/null +++ b/static/icons/folder-closed.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/folder-cog-2.svg b/static/icons/folder-cog-2.svg new file mode 100644 index 0000000..7ca430d --- /dev/null +++ b/static/icons/folder-cog-2.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/folder-cog.svg b/static/icons/folder-cog.svg new file mode 100644 index 0000000..419c6f5 --- /dev/null +++ b/static/icons/folder-cog.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/folder-down.svg b/static/icons/folder-down.svg new file mode 100644 index 0000000..c4ac0ca --- /dev/null +++ b/static/icons/folder-down.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-edit.svg b/static/icons/folder-edit.svg new file mode 100644 index 0000000..a5cbf02 --- /dev/null +++ b/static/icons/folder-edit.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/folder-heart.svg b/static/icons/folder-heart.svg new file mode 100644 index 0000000..a3f86d5 --- /dev/null +++ b/static/icons/folder-heart.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/folder-input.svg b/static/icons/folder-input.svg new file mode 100644 index 0000000..31df454 --- /dev/null +++ b/static/icons/folder-input.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-key.svg b/static/icons/folder-key.svg new file mode 100644 index 0000000..82756ad --- /dev/null +++ b/static/icons/folder-key.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/folder-lock.svg b/static/icons/folder-lock.svg new file mode 100644 index 0000000..4c2993a --- /dev/null +++ b/static/icons/folder-lock.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-minus.svg b/static/icons/folder-minus.svg new file mode 100644 index 0000000..ad247ae --- /dev/null +++ b/static/icons/folder-minus.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/folder-open.svg b/static/icons/folder-open.svg new file mode 100644 index 0000000..1135501 --- /dev/null +++ b/static/icons/folder-open.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/folder-output.svg b/static/icons/folder-output.svg new file mode 100644 index 0000000..422b1a7 --- /dev/null +++ b/static/icons/folder-output.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-plus.svg b/static/icons/folder-plus.svg new file mode 100644 index 0000000..34dfa27 --- /dev/null +++ b/static/icons/folder-plus.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-search-2.svg b/static/icons/folder-search-2.svg new file mode 100644 index 0000000..6c75150 --- /dev/null +++ b/static/icons/folder-search-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-search.svg b/static/icons/folder-search.svg new file mode 100644 index 0000000..92d43a7 --- /dev/null +++ b/static/icons/folder-search.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-symlink.svg b/static/icons/folder-symlink.svg new file mode 100644 index 0000000..2b9fd7f --- /dev/null +++ b/static/icons/folder-symlink.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-tree.svg b/static/icons/folder-tree.svg new file mode 100644 index 0000000..8f9564e --- /dev/null +++ b/static/icons/folder-tree.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/folder-up.svg b/static/icons/folder-up.svg new file mode 100644 index 0000000..2381511 --- /dev/null +++ b/static/icons/folder-up.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder-x.svg b/static/icons/folder-x.svg new file mode 100644 index 0000000..331c4fa --- /dev/null +++ b/static/icons/folder-x.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/folder.svg b/static/icons/folder.svg new file mode 100644 index 0000000..6e46360 --- /dev/null +++ b/static/icons/folder.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/folders.svg b/static/icons/folders.svg new file mode 100644 index 0000000..9e71c62 --- /dev/null +++ b/static/icons/folders.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/form-input.svg b/static/icons/form-input.svg new file mode 100644 index 0000000..0546ed8 --- /dev/null +++ b/static/icons/form-input.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/forward.svg b/static/icons/forward.svg new file mode 100644 index 0000000..c722387 --- /dev/null +++ b/static/icons/forward.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/frame.svg b/static/icons/frame.svg new file mode 100644 index 0000000..fc2144d --- /dev/null +++ b/static/icons/frame.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/framer.svg b/static/icons/framer.svg new file mode 100644 index 0000000..f8eeb8c --- /dev/null +++ b/static/icons/framer.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/frown.svg b/static/icons/frown.svg new file mode 100644 index 0000000..5a24d7d --- /dev/null +++ b/static/icons/frown.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/fuel.svg b/static/icons/fuel.svg new file mode 100644 index 0000000..d6bc1ec --- /dev/null +++ b/static/icons/fuel.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/function-square.svg b/static/icons/function-square.svg new file mode 100644 index 0000000..eed6935 --- /dev/null +++ b/static/icons/function-square.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/gamepad-2.svg b/static/icons/gamepad-2.svg new file mode 100644 index 0000000..7a90a81 --- /dev/null +++ b/static/icons/gamepad-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/gamepad.svg b/static/icons/gamepad.svg new file mode 100644 index 0000000..7f9cfb6 --- /dev/null +++ b/static/icons/gamepad.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/gauge.svg b/static/icons/gauge.svg new file mode 100644 index 0000000..16219c6 --- /dev/null +++ b/static/icons/gauge.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/gavel.svg b/static/icons/gavel.svg new file mode 100644 index 0000000..91f1874 --- /dev/null +++ b/static/icons/gavel.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/gem.svg b/static/icons/gem.svg new file mode 100644 index 0000000..d455b4f --- /dev/null +++ b/static/icons/gem.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/ghost.svg b/static/icons/ghost.svg new file mode 100644 index 0000000..3226449 --- /dev/null +++ b/static/icons/ghost.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/gift.svg b/static/icons/gift.svg new file mode 100644 index 0000000..df02c7f --- /dev/null +++ b/static/icons/gift.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/git-branch-plus.svg b/static/icons/git-branch-plus.svg new file mode 100644 index 0000000..6dc8ddb --- /dev/null +++ b/static/icons/git-branch-plus.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/git-branch.svg b/static/icons/git-branch.svg new file mode 100644 index 0000000..17d903f --- /dev/null +++ b/static/icons/git-branch.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/git-commit.svg b/static/icons/git-commit.svg new file mode 100644 index 0000000..ceeb9f9 --- /dev/null +++ b/static/icons/git-commit.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/git-compare.svg b/static/icons/git-compare.svg new file mode 100644 index 0000000..38c3296 --- /dev/null +++ b/static/icons/git-compare.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/git-fork.svg b/static/icons/git-fork.svg new file mode 100644 index 0000000..5d4a51a --- /dev/null +++ b/static/icons/git-fork.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/git-merge.svg b/static/icons/git-merge.svg new file mode 100644 index 0000000..02d4dc0 --- /dev/null +++ b/static/icons/git-merge.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/git-pull-request-closed.svg b/static/icons/git-pull-request-closed.svg new file mode 100644 index 0000000..d6d40f1 --- /dev/null +++ b/static/icons/git-pull-request-closed.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/git-pull-request-draft.svg b/static/icons/git-pull-request-draft.svg new file mode 100644 index 0000000..bd26c86 --- /dev/null +++ b/static/icons/git-pull-request-draft.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/git-pull-request.svg b/static/icons/git-pull-request.svg new file mode 100644 index 0000000..cab3581 --- /dev/null +++ b/static/icons/git-pull-request.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/github.svg b/static/icons/github.svg new file mode 100644 index 0000000..60c011f --- /dev/null +++ b/static/icons/github.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/gitlab.svg b/static/icons/gitlab.svg new file mode 100644 index 0000000..10ee9ea --- /dev/null +++ b/static/icons/gitlab.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/glass-water.svg b/static/icons/glass-water.svg new file mode 100644 index 0000000..3db6743 --- /dev/null +++ b/static/icons/glass-water.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/glasses.svg b/static/icons/glasses.svg new file mode 100644 index 0000000..42f0387 --- /dev/null +++ b/static/icons/glasses.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/globe-2.svg b/static/icons/globe-2.svg new file mode 100644 index 0000000..ac5498e --- /dev/null +++ b/static/icons/globe-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/globe.svg b/static/icons/globe.svg new file mode 100644 index 0000000..a9c820f --- /dev/null +++ b/static/icons/globe.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/grab.svg b/static/icons/grab.svg new file mode 100644 index 0000000..e8d5c74 --- /dev/null +++ b/static/icons/grab.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/graduation-cap.svg b/static/icons/graduation-cap.svg new file mode 100644 index 0000000..464ae8f --- /dev/null +++ b/static/icons/graduation-cap.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/grape.svg b/static/icons/grape.svg new file mode 100644 index 0000000..d31456c --- /dev/null +++ b/static/icons/grape.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/grid.svg b/static/icons/grid.svg new file mode 100644 index 0000000..17bbc84 --- /dev/null +++ b/static/icons/grid.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/grip-horizontal.svg b/static/icons/grip-horizontal.svg new file mode 100644 index 0000000..033a60b --- /dev/null +++ b/static/icons/grip-horizontal.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/grip-vertical.svg b/static/icons/grip-vertical.svg new file mode 100644 index 0000000..2cbd8aa --- /dev/null +++ b/static/icons/grip-vertical.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/hammer.svg b/static/icons/hammer.svg new file mode 100644 index 0000000..838fe6a --- /dev/null +++ b/static/icons/hammer.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/hand-metal.svg b/static/icons/hand-metal.svg new file mode 100644 index 0000000..5eb2b4b --- /dev/null +++ b/static/icons/hand-metal.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/hand.svg b/static/icons/hand.svg new file mode 100644 index 0000000..a5bc9ed --- /dev/null +++ b/static/icons/hand.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/hard-drive.svg b/static/icons/hard-drive.svg new file mode 100644 index 0000000..ebbde07 --- /dev/null +++ b/static/icons/hard-drive.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/hard-hat.svg b/static/icons/hard-hat.svg new file mode 100644 index 0000000..f1f7723 --- /dev/null +++ b/static/icons/hard-hat.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/hash.svg b/static/icons/hash.svg new file mode 100644 index 0000000..9cc4f15 --- /dev/null +++ b/static/icons/hash.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/haze.svg b/static/icons/haze.svg new file mode 100644 index 0000000..c4480cc --- /dev/null +++ b/static/icons/haze.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/heading-1.svg b/static/icons/heading-1.svg new file mode 100644 index 0000000..9c2d8e6 --- /dev/null +++ b/static/icons/heading-1.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/heading-2.svg b/static/icons/heading-2.svg new file mode 100644 index 0000000..8f29e37 --- /dev/null +++ b/static/icons/heading-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/heading-3.svg b/static/icons/heading-3.svg new file mode 100644 index 0000000..11a32e5 --- /dev/null +++ b/static/icons/heading-3.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/heading-4.svg b/static/icons/heading-4.svg new file mode 100644 index 0000000..2f6cc2b --- /dev/null +++ b/static/icons/heading-4.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/heading-5.svg b/static/icons/heading-5.svg new file mode 100644 index 0000000..df659b7 --- /dev/null +++ b/static/icons/heading-5.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/heading-6.svg b/static/icons/heading-6.svg new file mode 100644 index 0000000..b8fd857 --- /dev/null +++ b/static/icons/heading-6.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/heading.svg b/static/icons/heading.svg new file mode 100644 index 0000000..e0eea76 --- /dev/null +++ b/static/icons/heading.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/headphones.svg b/static/icons/headphones.svg new file mode 100644 index 0000000..f9c1cbd --- /dev/null +++ b/static/icons/headphones.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/heart-crack.svg b/static/icons/heart-crack.svg new file mode 100644 index 0000000..21786fc --- /dev/null +++ b/static/icons/heart-crack.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/heart-handshake.svg b/static/icons/heart-handshake.svg new file mode 100644 index 0000000..cbfc5cd --- /dev/null +++ b/static/icons/heart-handshake.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/heart-off.svg b/static/icons/heart-off.svg new file mode 100644 index 0000000..2b44283 --- /dev/null +++ b/static/icons/heart-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/heart-pulse.svg b/static/icons/heart-pulse.svg new file mode 100644 index 0000000..e1e6121 --- /dev/null +++ b/static/icons/heart-pulse.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/heart.svg b/static/icons/heart.svg new file mode 100644 index 0000000..29add65 --- /dev/null +++ b/static/icons/heart.svg @@ -0,0 +1,14 @@ + + + diff --git a/static/icons/help-circle.svg b/static/icons/help-circle.svg new file mode 100644 index 0000000..dab1358 --- /dev/null +++ b/static/icons/help-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/hexagon.svg b/static/icons/hexagon.svg new file mode 100644 index 0000000..522c2e3 --- /dev/null +++ b/static/icons/hexagon.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/highlighter.svg b/static/icons/highlighter.svg new file mode 100644 index 0000000..ce0937c --- /dev/null +++ b/static/icons/highlighter.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/history.svg b/static/icons/history.svg new file mode 100644 index 0000000..8226ef3 --- /dev/null +++ b/static/icons/history.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/home.svg b/static/icons/home.svg new file mode 100644 index 0000000..772edd7 --- /dev/null +++ b/static/icons/home.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/hop-off.svg b/static/icons/hop-off.svg new file mode 100644 index 0000000..48799ce --- /dev/null +++ b/static/icons/hop-off.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/hop.svg b/static/icons/hop.svg new file mode 100644 index 0000000..5eac5f1 --- /dev/null +++ b/static/icons/hop.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/hourglass.svg b/static/icons/hourglass.svg new file mode 100644 index 0000000..97a2081 --- /dev/null +++ b/static/icons/hourglass.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/ice-cream.svg b/static/icons/ice-cream.svg new file mode 100644 index 0000000..913b539 --- /dev/null +++ b/static/icons/ice-cream.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/image-minus.svg b/static/icons/image-minus.svg new file mode 100644 index 0000000..e4b3625 --- /dev/null +++ b/static/icons/image-minus.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/image-off.svg b/static/icons/image-off.svg new file mode 100644 index 0000000..37538b9 --- /dev/null +++ b/static/icons/image-off.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/image-plus.svg b/static/icons/image-plus.svg new file mode 100644 index 0000000..ab9ab9b --- /dev/null +++ b/static/icons/image-plus.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/image.svg b/static/icons/image.svg new file mode 100644 index 0000000..e6d86fa --- /dev/null +++ b/static/icons/image.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/import.svg b/static/icons/import.svg new file mode 100644 index 0000000..bcc91e7 --- /dev/null +++ b/static/icons/import.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/inbox.svg b/static/icons/inbox.svg new file mode 100644 index 0000000..c1f6868 --- /dev/null +++ b/static/icons/inbox.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/indent.svg b/static/icons/indent.svg new file mode 100644 index 0000000..c6c1952 --- /dev/null +++ b/static/icons/indent.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/indian-rupee.svg b/static/icons/indian-rupee.svg new file mode 100644 index 0000000..15b042e --- /dev/null +++ b/static/icons/indian-rupee.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/infinity.svg b/static/icons/infinity.svg new file mode 100644 index 0000000..4c0e56d --- /dev/null +++ b/static/icons/infinity.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/info.svg b/static/icons/info.svg new file mode 100644 index 0000000..9fbefeb --- /dev/null +++ b/static/icons/info.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/inspect.svg b/static/icons/inspect.svg new file mode 100644 index 0000000..4592513 --- /dev/null +++ b/static/icons/inspect.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/instagram.svg b/static/icons/instagram.svg new file mode 100644 index 0000000..d76b412 --- /dev/null +++ b/static/icons/instagram.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/italic.svg b/static/icons/italic.svg new file mode 100644 index 0000000..9dfd524 --- /dev/null +++ b/static/icons/italic.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/japanese-yen.svg b/static/icons/japanese-yen.svg new file mode 100644 index 0000000..632ea64 --- /dev/null +++ b/static/icons/japanese-yen.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/joystick.svg b/static/icons/joystick.svg new file mode 100644 index 0000000..d948ff1 --- /dev/null +++ b/static/icons/joystick.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/key.svg b/static/icons/key.svg new file mode 100644 index 0000000..d2cd46a --- /dev/null +++ b/static/icons/key.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/keyboard.svg b/static/icons/keyboard.svg new file mode 100644 index 0000000..980a608 --- /dev/null +++ b/static/icons/keyboard.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/lamp-ceiling.svg b/static/icons/lamp-ceiling.svg new file mode 100644 index 0000000..8673f73 --- /dev/null +++ b/static/icons/lamp-ceiling.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/lamp-desk.svg b/static/icons/lamp-desk.svg new file mode 100644 index 0000000..536a803 --- /dev/null +++ b/static/icons/lamp-desk.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/lamp-floor.svg b/static/icons/lamp-floor.svg new file mode 100644 index 0000000..a051439 --- /dev/null +++ b/static/icons/lamp-floor.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/lamp-wall-down.svg b/static/icons/lamp-wall-down.svg new file mode 100644 index 0000000..2197096 --- /dev/null +++ b/static/icons/lamp-wall-down.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/lamp-wall-up.svg b/static/icons/lamp-wall-up.svg new file mode 100644 index 0000000..b3f1a3e --- /dev/null +++ b/static/icons/lamp-wall-up.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/lamp.svg b/static/icons/lamp.svg new file mode 100644 index 0000000..4c0a674 --- /dev/null +++ b/static/icons/lamp.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/landmark.svg b/static/icons/landmark.svg new file mode 100644 index 0000000..f3875f5 --- /dev/null +++ b/static/icons/landmark.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/languages.svg b/static/icons/languages.svg new file mode 100644 index 0000000..c3c1486 --- /dev/null +++ b/static/icons/languages.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/laptop-2.svg b/static/icons/laptop-2.svg new file mode 100644 index 0000000..18c5e3c --- /dev/null +++ b/static/icons/laptop-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/laptop.svg b/static/icons/laptop.svg new file mode 100644 index 0000000..e4006cd --- /dev/null +++ b/static/icons/laptop.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/lasso-select.svg b/static/icons/lasso-select.svg new file mode 100644 index 0000000..d577704 --- /dev/null +++ b/static/icons/lasso-select.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/lasso.svg b/static/icons/lasso.svg new file mode 100644 index 0000000..857820d --- /dev/null +++ b/static/icons/lasso.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/laugh.svg b/static/icons/laugh.svg new file mode 100644 index 0000000..f4b6320 --- /dev/null +++ b/static/icons/laugh.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/layers.svg b/static/icons/layers.svg new file mode 100644 index 0000000..43b3255 --- /dev/null +++ b/static/icons/layers.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/layout-dashboard.svg b/static/icons/layout-dashboard.svg new file mode 100644 index 0000000..1ee7f7e --- /dev/null +++ b/static/icons/layout-dashboard.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/layout-grid.svg b/static/icons/layout-grid.svg new file mode 100644 index 0000000..1c0b49a --- /dev/null +++ b/static/icons/layout-grid.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/layout-list.svg b/static/icons/layout-list.svg new file mode 100644 index 0000000..936d214 --- /dev/null +++ b/static/icons/layout-list.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/layout-template.svg b/static/icons/layout-template.svg new file mode 100644 index 0000000..e9d887c --- /dev/null +++ b/static/icons/layout-template.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/layout.svg b/static/icons/layout.svg new file mode 100644 index 0000000..80c5066 --- /dev/null +++ b/static/icons/layout.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/leaf.svg b/static/icons/leaf.svg new file mode 100644 index 0000000..f322ef0 --- /dev/null +++ b/static/icons/leaf.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/library.svg b/static/icons/library.svg new file mode 100644 index 0000000..bb6f673 --- /dev/null +++ b/static/icons/library.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/life-buoy.svg b/static/icons/life-buoy.svg new file mode 100644 index 0000000..b171b39 --- /dev/null +++ b/static/icons/life-buoy.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/lightbulb-off.svg b/static/icons/lightbulb-off.svg new file mode 100644 index 0000000..2b773d5 --- /dev/null +++ b/static/icons/lightbulb-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/lightbulb.svg b/static/icons/lightbulb.svg new file mode 100644 index 0000000..01c7b7f --- /dev/null +++ b/static/icons/lightbulb.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/line-chart.svg b/static/icons/line-chart.svg new file mode 100644 index 0000000..4d6df0b --- /dev/null +++ b/static/icons/line-chart.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/link-2-off.svg b/static/icons/link-2-off.svg new file mode 100644 index 0000000..15581d7 --- /dev/null +++ b/static/icons/link-2-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/link-2.svg b/static/icons/link-2.svg new file mode 100644 index 0000000..516fa23 --- /dev/null +++ b/static/icons/link-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/link.svg b/static/icons/link.svg new file mode 100644 index 0000000..645e746 --- /dev/null +++ b/static/icons/link.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/linkedin.svg b/static/icons/linkedin.svg new file mode 100644 index 0000000..a5e423b --- /dev/null +++ b/static/icons/linkedin.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/list-checks.svg b/static/icons/list-checks.svg new file mode 100644 index 0000000..93906f4 --- /dev/null +++ b/static/icons/list-checks.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/list-end.svg b/static/icons/list-end.svg new file mode 100644 index 0000000..4e70739 --- /dev/null +++ b/static/icons/list-end.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/list-minus.svg b/static/icons/list-minus.svg new file mode 100644 index 0000000..d5ab955 --- /dev/null +++ b/static/icons/list-minus.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/list-music.svg b/static/icons/list-music.svg new file mode 100644 index 0000000..186caae --- /dev/null +++ b/static/icons/list-music.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/list-ordered.svg b/static/icons/list-ordered.svg new file mode 100644 index 0000000..6201c84 --- /dev/null +++ b/static/icons/list-ordered.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/list-plus.svg b/static/icons/list-plus.svg new file mode 100644 index 0000000..acc00c4 --- /dev/null +++ b/static/icons/list-plus.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/list-start.svg b/static/icons/list-start.svg new file mode 100644 index 0000000..e2b4e72 --- /dev/null +++ b/static/icons/list-start.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/list-video.svg b/static/icons/list-video.svg new file mode 100644 index 0000000..44d11ff --- /dev/null +++ b/static/icons/list-video.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/list-x.svg b/static/icons/list-x.svg new file mode 100644 index 0000000..c568a93 --- /dev/null +++ b/static/icons/list-x.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/list.svg b/static/icons/list.svg new file mode 100644 index 0000000..382b821 --- /dev/null +++ b/static/icons/list.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/loader-2.svg b/static/icons/loader-2.svg new file mode 100644 index 0000000..cc065ca --- /dev/null +++ b/static/icons/loader-2.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/loader.svg b/static/icons/loader.svg new file mode 100644 index 0000000..0b4bb93 --- /dev/null +++ b/static/icons/loader.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/locate-fixed.svg b/static/icons/locate-fixed.svg new file mode 100644 index 0000000..7db097b --- /dev/null +++ b/static/icons/locate-fixed.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/locate-off.svg b/static/icons/locate-off.svg new file mode 100644 index 0000000..8d4939f --- /dev/null +++ b/static/icons/locate-off.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/locate.svg b/static/icons/locate.svg new file mode 100644 index 0000000..91d179c --- /dev/null +++ b/static/icons/locate.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/lock.svg b/static/icons/lock.svg new file mode 100644 index 0000000..cd6b7f6 --- /dev/null +++ b/static/icons/lock.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/log-in.svg b/static/icons/log-in.svg new file mode 100644 index 0000000..af19cf8 --- /dev/null +++ b/static/icons/log-in.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/static/icons/log-out.svg b/static/icons/log-out.svg new file mode 100644 index 0000000..c6e2f9e --- /dev/null +++ b/static/icons/log-out.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/static/icons/luggage.svg b/static/icons/luggage.svg new file mode 100644 index 0000000..8ce3799 --- /dev/null +++ b/static/icons/luggage.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/magnet.svg b/static/icons/magnet.svg new file mode 100644 index 0000000..337f517 --- /dev/null +++ b/static/icons/magnet.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/mail-check.svg b/static/icons/mail-check.svg new file mode 100644 index 0000000..375a058 --- /dev/null +++ b/static/icons/mail-check.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/mail-minus.svg b/static/icons/mail-minus.svg new file mode 100644 index 0000000..e180e79 --- /dev/null +++ b/static/icons/mail-minus.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/mail-open.svg b/static/icons/mail-open.svg new file mode 100644 index 0000000..0cb2603 --- /dev/null +++ b/static/icons/mail-open.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/mail-plus.svg b/static/icons/mail-plus.svg new file mode 100644 index 0000000..31243a5 --- /dev/null +++ b/static/icons/mail-plus.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/mail-question.svg b/static/icons/mail-question.svg new file mode 100644 index 0000000..3b16ae7 --- /dev/null +++ b/static/icons/mail-question.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/mail-search.svg b/static/icons/mail-search.svg new file mode 100644 index 0000000..87cc431 --- /dev/null +++ b/static/icons/mail-search.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/mail-warning.svg b/static/icons/mail-warning.svg new file mode 100644 index 0000000..ac3a395 --- /dev/null +++ b/static/icons/mail-warning.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/mail-x.svg b/static/icons/mail-x.svg new file mode 100644 index 0000000..6b3393c --- /dev/null +++ b/static/icons/mail-x.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/mail.svg b/static/icons/mail.svg new file mode 100644 index 0000000..d211c87 --- /dev/null +++ b/static/icons/mail.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/mails.svg b/static/icons/mails.svg new file mode 100644 index 0000000..03659eb --- /dev/null +++ b/static/icons/mails.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/map-pin-off.svg b/static/icons/map-pin-off.svg new file mode 100644 index 0000000..fd91b11 --- /dev/null +++ b/static/icons/map-pin-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/map-pin.svg b/static/icons/map-pin.svg new file mode 100644 index 0000000..5af81c8 --- /dev/null +++ b/static/icons/map-pin.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/map.svg b/static/icons/map.svg new file mode 100644 index 0000000..627b3c9 --- /dev/null +++ b/static/icons/map.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/martini.svg b/static/icons/martini.svg new file mode 100644 index 0000000..31dc459 --- /dev/null +++ b/static/icons/martini.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/maximize-2.svg b/static/icons/maximize-2.svg new file mode 100644 index 0000000..abfa104 --- /dev/null +++ b/static/icons/maximize-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/maximize.svg b/static/icons/maximize.svg new file mode 100644 index 0000000..f78ca32 --- /dev/null +++ b/static/icons/maximize.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/medal.svg b/static/icons/medal.svg new file mode 100644 index 0000000..977e7f2 --- /dev/null +++ b/static/icons/medal.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/megaphone-off.svg b/static/icons/megaphone-off.svg new file mode 100644 index 0000000..f90dcab --- /dev/null +++ b/static/icons/megaphone-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/megaphone.svg b/static/icons/megaphone.svg new file mode 100644 index 0000000..ee83043 --- /dev/null +++ b/static/icons/megaphone.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/meh.svg b/static/icons/meh.svg new file mode 100644 index 0000000..04a7982 --- /dev/null +++ b/static/icons/meh.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/menu.svg b/static/icons/menu.svg new file mode 100644 index 0000000..2368627 --- /dev/null +++ b/static/icons/menu.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/message-circle.svg b/static/icons/message-circle.svg new file mode 100644 index 0000000..0ac1044 --- /dev/null +++ b/static/icons/message-circle.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/message-square.svg b/static/icons/message-square.svg new file mode 100644 index 0000000..5cd9c73 --- /dev/null +++ b/static/icons/message-square.svg @@ -0,0 +1,14 @@ + + + diff --git a/static/icons/mic-2.svg b/static/icons/mic-2.svg new file mode 100644 index 0000000..fb317da --- /dev/null +++ b/static/icons/mic-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/mic-off.svg b/static/icons/mic-off.svg new file mode 100644 index 0000000..5acbb4b --- /dev/null +++ b/static/icons/mic-off.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/mic.svg b/static/icons/mic.svg new file mode 100644 index 0000000..62e62c3 --- /dev/null +++ b/static/icons/mic.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/microscope.svg b/static/icons/microscope.svg new file mode 100644 index 0000000..149a7a9 --- /dev/null +++ b/static/icons/microscope.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/microwave.svg b/static/icons/microwave.svg new file mode 100644 index 0000000..54825da --- /dev/null +++ b/static/icons/microwave.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/milestone.svg b/static/icons/milestone.svg new file mode 100644 index 0000000..c7550e0 --- /dev/null +++ b/static/icons/milestone.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/milk-off.svg b/static/icons/milk-off.svg new file mode 100644 index 0000000..a7126d3 --- /dev/null +++ b/static/icons/milk-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/milk.svg b/static/icons/milk.svg new file mode 100644 index 0000000..caec132 --- /dev/null +++ b/static/icons/milk.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/minimize-2.svg b/static/icons/minimize-2.svg new file mode 100644 index 0000000..cb6c3a8 --- /dev/null +++ b/static/icons/minimize-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/minimize.svg b/static/icons/minimize.svg new file mode 100644 index 0000000..13eb99c --- /dev/null +++ b/static/icons/minimize.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/minus-circle.svg b/static/icons/minus-circle.svg new file mode 100644 index 0000000..92a2ed6 --- /dev/null +++ b/static/icons/minus-circle.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/minus-square.svg b/static/icons/minus-square.svg new file mode 100644 index 0000000..3d03133 --- /dev/null +++ b/static/icons/minus-square.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/minus.svg b/static/icons/minus.svg new file mode 100644 index 0000000..38b1ffc --- /dev/null +++ b/static/icons/minus.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/monitor-off.svg b/static/icons/monitor-off.svg new file mode 100644 index 0000000..f03db2c --- /dev/null +++ b/static/icons/monitor-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/monitor-smartphone.svg b/static/icons/monitor-smartphone.svg new file mode 100644 index 0000000..46d46c7 --- /dev/null +++ b/static/icons/monitor-smartphone.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/monitor-speaker.svg b/static/icons/monitor-speaker.svg new file mode 100644 index 0000000..859cf39 --- /dev/null +++ b/static/icons/monitor-speaker.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/monitor.svg b/static/icons/monitor.svg new file mode 100644 index 0000000..d983a85 --- /dev/null +++ b/static/icons/monitor.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/moon.svg b/static/icons/moon.svg new file mode 100644 index 0000000..ce4a59d --- /dev/null +++ b/static/icons/moon.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/more-horizontal.svg b/static/icons/more-horizontal.svg new file mode 100644 index 0000000..68456c3 --- /dev/null +++ b/static/icons/more-horizontal.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/more-vertical.svg b/static/icons/more-vertical.svg new file mode 100644 index 0000000..1de6160 --- /dev/null +++ b/static/icons/more-vertical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/mountain-snow.svg b/static/icons/mountain-snow.svg new file mode 100644 index 0000000..399e24c --- /dev/null +++ b/static/icons/mountain-snow.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/mountain.svg b/static/icons/mountain.svg new file mode 100644 index 0000000..b6691e7 --- /dev/null +++ b/static/icons/mountain.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/mouse-pointer-2.svg b/static/icons/mouse-pointer-2.svg new file mode 100644 index 0000000..26541f9 --- /dev/null +++ b/static/icons/mouse-pointer-2.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/mouse-pointer-click.svg b/static/icons/mouse-pointer-click.svg new file mode 100644 index 0000000..1df3480 --- /dev/null +++ b/static/icons/mouse-pointer-click.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/mouse-pointer.svg b/static/icons/mouse-pointer.svg new file mode 100644 index 0000000..7312adc --- /dev/null +++ b/static/icons/mouse-pointer.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/mouse.svg b/static/icons/mouse.svg new file mode 100644 index 0000000..39a62ad --- /dev/null +++ b/static/icons/mouse.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/move-3d.svg b/static/icons/move-3d.svg new file mode 100644 index 0000000..c86f871 --- /dev/null +++ b/static/icons/move-3d.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/move-diagonal-2.svg b/static/icons/move-diagonal-2.svg new file mode 100644 index 0000000..469dc3c --- /dev/null +++ b/static/icons/move-diagonal-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/move-diagonal.svg b/static/icons/move-diagonal.svg new file mode 100644 index 0000000..66ce964 --- /dev/null +++ b/static/icons/move-diagonal.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/move-horizontal.svg b/static/icons/move-horizontal.svg new file mode 100644 index 0000000..29992b4 --- /dev/null +++ b/static/icons/move-horizontal.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/move-vertical.svg b/static/icons/move-vertical.svg new file mode 100644 index 0000000..bcef50b --- /dev/null +++ b/static/icons/move-vertical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/move.svg b/static/icons/move.svg new file mode 100644 index 0000000..40de93c --- /dev/null +++ b/static/icons/move.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/music-2.svg b/static/icons/music-2.svg new file mode 100644 index 0000000..9b1aa29 --- /dev/null +++ b/static/icons/music-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/music-3.svg b/static/icons/music-3.svg new file mode 100644 index 0000000..02cb44c --- /dev/null +++ b/static/icons/music-3.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/music-4.svg b/static/icons/music-4.svg new file mode 100644 index 0000000..911a724 --- /dev/null +++ b/static/icons/music-4.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/music.svg b/static/icons/music.svg new file mode 100644 index 0000000..dd9faac --- /dev/null +++ b/static/icons/music.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/navigation-2-off.svg b/static/icons/navigation-2-off.svg new file mode 100644 index 0000000..688ec1b --- /dev/null +++ b/static/icons/navigation-2-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/navigation-2.svg b/static/icons/navigation-2.svg new file mode 100644 index 0000000..febc406 --- /dev/null +++ b/static/icons/navigation-2.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/navigation-off.svg b/static/icons/navigation-off.svg new file mode 100644 index 0000000..f2d91b3 --- /dev/null +++ b/static/icons/navigation-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/navigation.svg b/static/icons/navigation.svg new file mode 100644 index 0000000..b2be022 --- /dev/null +++ b/static/icons/navigation.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/network.svg b/static/icons/network.svg new file mode 100644 index 0000000..0809c07 --- /dev/null +++ b/static/icons/network.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/newspaper.svg b/static/icons/newspaper.svg new file mode 100644 index 0000000..d4e95b3 --- /dev/null +++ b/static/icons/newspaper.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/nut-off.svg b/static/icons/nut-off.svg new file mode 100644 index 0000000..b9508eb --- /dev/null +++ b/static/icons/nut-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/nut.svg b/static/icons/nut.svg new file mode 100644 index 0000000..9e232b5 --- /dev/null +++ b/static/icons/nut.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/octagon.svg b/static/icons/octagon.svg new file mode 100644 index 0000000..8a550f1 --- /dev/null +++ b/static/icons/octagon.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/option.svg b/static/icons/option.svg new file mode 100644 index 0000000..d8ca90f --- /dev/null +++ b/static/icons/option.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/outdent.svg b/static/icons/outdent.svg new file mode 100644 index 0000000..bed6981 --- /dev/null +++ b/static/icons/outdent.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/package-2.svg b/static/icons/package-2.svg new file mode 100644 index 0000000..dbe5a5f --- /dev/null +++ b/static/icons/package-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/package-check.svg b/static/icons/package-check.svg new file mode 100644 index 0000000..2263dda --- /dev/null +++ b/static/icons/package-check.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/package-minus.svg b/static/icons/package-minus.svg new file mode 100644 index 0000000..5a3a3f6 --- /dev/null +++ b/static/icons/package-minus.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/package-open.svg b/static/icons/package-open.svg new file mode 100644 index 0000000..43cba38 --- /dev/null +++ b/static/icons/package-open.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/package-plus.svg b/static/icons/package-plus.svg new file mode 100644 index 0000000..e3dcea7 --- /dev/null +++ b/static/icons/package-plus.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/package-search.svg b/static/icons/package-search.svg new file mode 100644 index 0000000..a4a2875 --- /dev/null +++ b/static/icons/package-search.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/package-x.svg b/static/icons/package-x.svg new file mode 100644 index 0000000..8e0beb0 --- /dev/null +++ b/static/icons/package-x.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/package.svg b/static/icons/package.svg new file mode 100644 index 0000000..9e03077 --- /dev/null +++ b/static/icons/package.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/paint-bucket.svg b/static/icons/paint-bucket.svg new file mode 100644 index 0000000..56967be --- /dev/null +++ b/static/icons/paint-bucket.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/paintbrush-2.svg b/static/icons/paintbrush-2.svg new file mode 100644 index 0000000..2a05fbd --- /dev/null +++ b/static/icons/paintbrush-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/paintbrush.svg b/static/icons/paintbrush.svg new file mode 100644 index 0000000..b1b2dfa --- /dev/null +++ b/static/icons/paintbrush.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/palette.svg b/static/icons/palette.svg new file mode 100644 index 0000000..113ebe1 --- /dev/null +++ b/static/icons/palette.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/palmtree.svg b/static/icons/palmtree.svg new file mode 100644 index 0000000..6d82389 --- /dev/null +++ b/static/icons/palmtree.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/paperclip.svg b/static/icons/paperclip.svg new file mode 100644 index 0000000..047382d --- /dev/null +++ b/static/icons/paperclip.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/party-popper.svg b/static/icons/party-popper.svg new file mode 100644 index 0000000..4d3dafd --- /dev/null +++ b/static/icons/party-popper.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/pause-circle.svg b/static/icons/pause-circle.svg new file mode 100644 index 0000000..39ce681 --- /dev/null +++ b/static/icons/pause-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/pause-octagon.svg b/static/icons/pause-octagon.svg new file mode 100644 index 0000000..fc9521a --- /dev/null +++ b/static/icons/pause-octagon.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/pause.svg b/static/icons/pause.svg new file mode 100644 index 0000000..756b604 --- /dev/null +++ b/static/icons/pause.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/pen-tool.svg b/static/icons/pen-tool.svg new file mode 100644 index 0000000..be52e6d --- /dev/null +++ b/static/icons/pen-tool.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/pencil.svg b/static/icons/pencil.svg new file mode 100644 index 0000000..49ab50e --- /dev/null +++ b/static/icons/pencil.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/percent.svg b/static/icons/percent.svg new file mode 100644 index 0000000..3d18ed1 --- /dev/null +++ b/static/icons/percent.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/person-standing.svg b/static/icons/person-standing.svg new file mode 100644 index 0000000..2af3f24 --- /dev/null +++ b/static/icons/person-standing.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/phone-call.svg b/static/icons/phone-call.svg new file mode 100644 index 0000000..ce5f80b --- /dev/null +++ b/static/icons/phone-call.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/phone-forwarded.svg b/static/icons/phone-forwarded.svg new file mode 100644 index 0000000..7a86479 --- /dev/null +++ b/static/icons/phone-forwarded.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/phone-incoming.svg b/static/icons/phone-incoming.svg new file mode 100644 index 0000000..9493b36 --- /dev/null +++ b/static/icons/phone-incoming.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/phone-missed.svg b/static/icons/phone-missed.svg new file mode 100644 index 0000000..876970c --- /dev/null +++ b/static/icons/phone-missed.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/phone-off.svg b/static/icons/phone-off.svg new file mode 100644 index 0000000..0d8390f --- /dev/null +++ b/static/icons/phone-off.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/phone-outgoing.svg b/static/icons/phone-outgoing.svg new file mode 100644 index 0000000..3065330 --- /dev/null +++ b/static/icons/phone-outgoing.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/phone.svg b/static/icons/phone.svg new file mode 100644 index 0000000..b1972e9 --- /dev/null +++ b/static/icons/phone.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/pie-chart.svg b/static/icons/pie-chart.svg new file mode 100644 index 0000000..f128b88 --- /dev/null +++ b/static/icons/pie-chart.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/piggy-bank.svg b/static/icons/piggy-bank.svg new file mode 100644 index 0000000..54e0139 --- /dev/null +++ b/static/icons/piggy-bank.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/pin-off.svg b/static/icons/pin-off.svg new file mode 100644 index 0000000..ca54194 --- /dev/null +++ b/static/icons/pin-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/pin.svg b/static/icons/pin.svg new file mode 100644 index 0000000..0d2c2b3 --- /dev/null +++ b/static/icons/pin.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/pipette.svg b/static/icons/pipette.svg new file mode 100644 index 0000000..c57e264 --- /dev/null +++ b/static/icons/pipette.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/pizza.svg b/static/icons/pizza.svg new file mode 100644 index 0000000..9a0b1ad --- /dev/null +++ b/static/icons/pizza.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/plane.svg b/static/icons/plane.svg new file mode 100644 index 0000000..6f843bf --- /dev/null +++ b/static/icons/plane.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/play-circle.svg b/static/icons/play-circle.svg new file mode 100644 index 0000000..f814cfd --- /dev/null +++ b/static/icons/play-circle.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/play.svg b/static/icons/play.svg new file mode 100644 index 0000000..d1e20e2 --- /dev/null +++ b/static/icons/play.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/plug-2.svg b/static/icons/plug-2.svg new file mode 100644 index 0000000..04a756b --- /dev/null +++ b/static/icons/plug-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/plug-zap.svg b/static/icons/plug-zap.svg new file mode 100644 index 0000000..c58f547 --- /dev/null +++ b/static/icons/plug-zap.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/plug.svg b/static/icons/plug.svg new file mode 100644 index 0000000..16bb1e7 --- /dev/null +++ b/static/icons/plug.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/plus-circle.svg b/static/icons/plus-circle.svg new file mode 100644 index 0000000..413fb48 --- /dev/null +++ b/static/icons/plus-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/plus-square.svg b/static/icons/plus-square.svg new file mode 100644 index 0000000..c8f4798 --- /dev/null +++ b/static/icons/plus-square.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/plus.svg b/static/icons/plus.svg new file mode 100644 index 0000000..1e1b1c5 --- /dev/null +++ b/static/icons/plus.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/pocket.svg b/static/icons/pocket.svg new file mode 100644 index 0000000..00376f4 --- /dev/null +++ b/static/icons/pocket.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/podcast.svg b/static/icons/podcast.svg new file mode 100644 index 0000000..555039f --- /dev/null +++ b/static/icons/podcast.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/pointer.svg b/static/icons/pointer.svg new file mode 100644 index 0000000..6431931 --- /dev/null +++ b/static/icons/pointer.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/pound-sterling.svg b/static/icons/pound-sterling.svg new file mode 100644 index 0000000..4bbf3d3 --- /dev/null +++ b/static/icons/pound-sterling.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/power-off.svg b/static/icons/power-off.svg new file mode 100644 index 0000000..3f7ffbd --- /dev/null +++ b/static/icons/power-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/power.svg b/static/icons/power.svg new file mode 100644 index 0000000..cc03e38 --- /dev/null +++ b/static/icons/power.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/printer.svg b/static/icons/printer.svg new file mode 100644 index 0000000..5df50ae --- /dev/null +++ b/static/icons/printer.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/puzzle.svg b/static/icons/puzzle.svg new file mode 100644 index 0000000..11822cf --- /dev/null +++ b/static/icons/puzzle.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/qr-code.svg b/static/icons/qr-code.svg new file mode 100644 index 0000000..b09a10d --- /dev/null +++ b/static/icons/qr-code.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + diff --git a/static/icons/quote.svg b/static/icons/quote.svg new file mode 100644 index 0000000..de2fa25 --- /dev/null +++ b/static/icons/quote.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/radio-receiver.svg b/static/icons/radio-receiver.svg new file mode 100644 index 0000000..1156035 --- /dev/null +++ b/static/icons/radio-receiver.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/radio.svg b/static/icons/radio.svg new file mode 100644 index 0000000..a141545 --- /dev/null +++ b/static/icons/radio.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/rectangle-horizontal.svg b/static/icons/rectangle-horizontal.svg new file mode 100644 index 0000000..3b67813 --- /dev/null +++ b/static/icons/rectangle-horizontal.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/rectangle-vertical.svg b/static/icons/rectangle-vertical.svg new file mode 100644 index 0000000..9395a8d --- /dev/null +++ b/static/icons/rectangle-vertical.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/recycle.svg b/static/icons/recycle.svg new file mode 100644 index 0000000..bd207b3 --- /dev/null +++ b/static/icons/recycle.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/redo-2.svg b/static/icons/redo-2.svg new file mode 100644 index 0000000..157ff12 --- /dev/null +++ b/static/icons/redo-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/redo.svg b/static/icons/redo.svg new file mode 100644 index 0000000..6e585d0 --- /dev/null +++ b/static/icons/redo.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/refresh-ccw.svg b/static/icons/refresh-ccw.svg new file mode 100644 index 0000000..7933c31 --- /dev/null +++ b/static/icons/refresh-ccw.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/refresh-cw.svg b/static/icons/refresh-cw.svg new file mode 100644 index 0000000..a08d94d --- /dev/null +++ b/static/icons/refresh-cw.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/static/icons/refrigerator.svg b/static/icons/refrigerator.svg new file mode 100644 index 0000000..4884513 --- /dev/null +++ b/static/icons/refrigerator.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/regex.svg b/static/icons/regex.svg new file mode 100644 index 0000000..1b0287b --- /dev/null +++ b/static/icons/regex.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/repeat-1.svg b/static/icons/repeat-1.svg new file mode 100644 index 0000000..4b7fa56 --- /dev/null +++ b/static/icons/repeat-1.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/repeat.svg b/static/icons/repeat.svg new file mode 100644 index 0000000..b8dccd7 --- /dev/null +++ b/static/icons/repeat.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/reply-all.svg b/static/icons/reply-all.svg new file mode 100644 index 0000000..d6380ed --- /dev/null +++ b/static/icons/reply-all.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/reply.svg b/static/icons/reply.svg new file mode 100644 index 0000000..a9ee123 --- /dev/null +++ b/static/icons/reply.svg @@ -0,0 +1,15 @@ + + + + diff --git a/static/icons/rewind.svg b/static/icons/rewind.svg new file mode 100644 index 0000000..749f98d --- /dev/null +++ b/static/icons/rewind.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/rocket.svg b/static/icons/rocket.svg new file mode 100644 index 0000000..4ca5ac0 --- /dev/null +++ b/static/icons/rocket.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/rocking-chair.svg b/static/icons/rocking-chair.svg new file mode 100644 index 0000000..b7d5d25 --- /dev/null +++ b/static/icons/rocking-chair.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/rotate-3d.svg b/static/icons/rotate-3d.svg new file mode 100644 index 0000000..e701674 --- /dev/null +++ b/static/icons/rotate-3d.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/rotate-ccw.svg b/static/icons/rotate-ccw.svg new file mode 100644 index 0000000..f308977 --- /dev/null +++ b/static/icons/rotate-ccw.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/rotate-cw.svg b/static/icons/rotate-cw.svg new file mode 100644 index 0000000..12fe2bf --- /dev/null +++ b/static/icons/rotate-cw.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/rss.svg b/static/icons/rss.svg new file mode 100644 index 0000000..7cec310 --- /dev/null +++ b/static/icons/rss.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/static/icons/ruler.svg b/static/icons/ruler.svg new file mode 100644 index 0000000..a2123f5 --- /dev/null +++ b/static/icons/ruler.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/russian-ruble.svg b/static/icons/russian-ruble.svg new file mode 100644 index 0000000..dc1295b --- /dev/null +++ b/static/icons/russian-ruble.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/sailboat.svg b/static/icons/sailboat.svg new file mode 100644 index 0000000..5749a41 --- /dev/null +++ b/static/icons/sailboat.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/save.svg b/static/icons/save.svg new file mode 100644 index 0000000..ddf6bf3 --- /dev/null +++ b/static/icons/save.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/scale-3d.svg b/static/icons/scale-3d.svg new file mode 100644 index 0000000..0c96b48 --- /dev/null +++ b/static/icons/scale-3d.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/scale.svg b/static/icons/scale.svg new file mode 100644 index 0000000..ae70a27 --- /dev/null +++ b/static/icons/scale.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/scaling.svg b/static/icons/scaling.svg new file mode 100644 index 0000000..d214cb9 --- /dev/null +++ b/static/icons/scaling.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/scan-face.svg b/static/icons/scan-face.svg new file mode 100644 index 0000000..d1227a0 --- /dev/null +++ b/static/icons/scan-face.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/scan-line.svg b/static/icons/scan-line.svg new file mode 100644 index 0000000..5d7a75d --- /dev/null +++ b/static/icons/scan-line.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/scan.svg b/static/icons/scan.svg new file mode 100644 index 0000000..33d067b --- /dev/null +++ b/static/icons/scan.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/scissors.svg b/static/icons/scissors.svg new file mode 100644 index 0000000..1bf1774 --- /dev/null +++ b/static/icons/scissors.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/screen-share-off.svg b/static/icons/screen-share-off.svg new file mode 100644 index 0000000..1fafd2c --- /dev/null +++ b/static/icons/screen-share-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/screen-share.svg b/static/icons/screen-share.svg new file mode 100644 index 0000000..bb3a854 --- /dev/null +++ b/static/icons/screen-share.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/scroll.svg b/static/icons/scroll.svg new file mode 100644 index 0000000..5f75973 --- /dev/null +++ b/static/icons/scroll.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/search.svg b/static/icons/search.svg new file mode 100644 index 0000000..89a8636 --- /dev/null +++ b/static/icons/search.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/send.svg b/static/icons/send.svg new file mode 100644 index 0000000..715d37c --- /dev/null +++ b/static/icons/send.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/separator-horizontal.svg b/static/icons/separator-horizontal.svg new file mode 100644 index 0000000..d9075fd --- /dev/null +++ b/static/icons/separator-horizontal.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/separator-vertical.svg b/static/icons/separator-vertical.svg new file mode 100644 index 0000000..76d5367 --- /dev/null +++ b/static/icons/separator-vertical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/server-cog.svg b/static/icons/server-cog.svg new file mode 100644 index 0000000..7d977a0 --- /dev/null +++ b/static/icons/server-cog.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + diff --git a/static/icons/server-crash.svg b/static/icons/server-crash.svg new file mode 100644 index 0000000..cc86d31 --- /dev/null +++ b/static/icons/server-crash.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/server-off.svg b/static/icons/server-off.svg new file mode 100644 index 0000000..7d32fed --- /dev/null +++ b/static/icons/server-off.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/server.svg b/static/icons/server.svg new file mode 100644 index 0000000..b48d693 --- /dev/null +++ b/static/icons/server.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/settings-2.svg b/static/icons/settings-2.svg new file mode 100644 index 0000000..ad6f98d --- /dev/null +++ b/static/icons/settings-2.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/settings.svg b/static/icons/settings.svg new file mode 100644 index 0000000..cdd0cda --- /dev/null +++ b/static/icons/settings.svg @@ -0,0 +1,15 @@ + + + + diff --git a/static/icons/share-2.svg b/static/icons/share-2.svg new file mode 100644 index 0000000..704394f --- /dev/null +++ b/static/icons/share-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/share.svg b/static/icons/share.svg new file mode 100644 index 0000000..69208c3 --- /dev/null +++ b/static/icons/share.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/sheet.svg b/static/icons/sheet.svg new file mode 100644 index 0000000..0617394 --- /dev/null +++ b/static/icons/sheet.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/shield-alert.svg b/static/icons/shield-alert.svg new file mode 100644 index 0000000..deccbb9 --- /dev/null +++ b/static/icons/shield-alert.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shield-check.svg b/static/icons/shield-check.svg new file mode 100644 index 0000000..fc67169 --- /dev/null +++ b/static/icons/shield-check.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/shield-close.svg b/static/icons/shield-close.svg new file mode 100644 index 0000000..abc2515 --- /dev/null +++ b/static/icons/shield-close.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shield-off.svg b/static/icons/shield-off.svg new file mode 100644 index 0000000..9f0cfde --- /dev/null +++ b/static/icons/shield-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shield.svg b/static/icons/shield.svg new file mode 100644 index 0000000..343c137 --- /dev/null +++ b/static/icons/shield.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/shirt.svg b/static/icons/shirt.svg new file mode 100644 index 0000000..90bba75 --- /dev/null +++ b/static/icons/shirt.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/shopping-bag.svg b/static/icons/shopping-bag.svg new file mode 100644 index 0000000..bcead53 --- /dev/null +++ b/static/icons/shopping-bag.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shopping-cart.svg b/static/icons/shopping-cart.svg new file mode 100644 index 0000000..6d9f884 --- /dev/null +++ b/static/icons/shopping-cart.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shovel.svg b/static/icons/shovel.svg new file mode 100644 index 0000000..cb7dbdc --- /dev/null +++ b/static/icons/shovel.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shower-head.svg b/static/icons/shower-head.svg new file mode 100644 index 0000000..5c2ccd6 --- /dev/null +++ b/static/icons/shower-head.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/shrink.svg b/static/icons/shrink.svg new file mode 100644 index 0000000..0c6ce11 --- /dev/null +++ b/static/icons/shrink.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/shrub.svg b/static/icons/shrub.svg new file mode 100644 index 0000000..93bbbf8 --- /dev/null +++ b/static/icons/shrub.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/shuffle.svg b/static/icons/shuffle.svg new file mode 100644 index 0000000..a2282eb --- /dev/null +++ b/static/icons/shuffle.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/sidebar-close.svg b/static/icons/sidebar-close.svg new file mode 100644 index 0000000..d6895c7 --- /dev/null +++ b/static/icons/sidebar-close.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/sidebar-open.svg b/static/icons/sidebar-open.svg new file mode 100644 index 0000000..e9a5730 --- /dev/null +++ b/static/icons/sidebar-open.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/sidebar.svg b/static/icons/sidebar.svg new file mode 100644 index 0000000..25f0449 --- /dev/null +++ b/static/icons/sidebar.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/sigma.svg b/static/icons/sigma.svg new file mode 100644 index 0000000..254859a --- /dev/null +++ b/static/icons/sigma.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/signal-high.svg b/static/icons/signal-high.svg new file mode 100644 index 0000000..9e12de5 --- /dev/null +++ b/static/icons/signal-high.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/signal-low.svg b/static/icons/signal-low.svg new file mode 100644 index 0000000..3393764 --- /dev/null +++ b/static/icons/signal-low.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/signal-medium.svg b/static/icons/signal-medium.svg new file mode 100644 index 0000000..4245f67 --- /dev/null +++ b/static/icons/signal-medium.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/signal-zero.svg b/static/icons/signal-zero.svg new file mode 100644 index 0000000..188042a --- /dev/null +++ b/static/icons/signal-zero.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/signal.svg b/static/icons/signal.svg new file mode 100644 index 0000000..5e3726e --- /dev/null +++ b/static/icons/signal.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/siren.svg b/static/icons/siren.svg new file mode 100644 index 0000000..527976a --- /dev/null +++ b/static/icons/siren.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/skip-back.svg b/static/icons/skip-back.svg new file mode 100644 index 0000000..1dfebcf --- /dev/null +++ b/static/icons/skip-back.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/skip-forward.svg b/static/icons/skip-forward.svg new file mode 100644 index 0000000..dcc0b54 --- /dev/null +++ b/static/icons/skip-forward.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/skull.svg b/static/icons/skull.svg new file mode 100644 index 0000000..6009869 --- /dev/null +++ b/static/icons/skull.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/slack.svg b/static/icons/slack.svg new file mode 100644 index 0000000..0c5bd14 --- /dev/null +++ b/static/icons/slack.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/slash.svg b/static/icons/slash.svg new file mode 100644 index 0000000..56f6123 --- /dev/null +++ b/static/icons/slash.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/slice.svg b/static/icons/slice.svg new file mode 100644 index 0000000..3809180 --- /dev/null +++ b/static/icons/slice.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/sliders-horizontal.svg b/static/icons/sliders-horizontal.svg new file mode 100644 index 0000000..db5329e --- /dev/null +++ b/static/icons/sliders-horizontal.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/sliders.svg b/static/icons/sliders.svg new file mode 100644 index 0000000..e7fb94c --- /dev/null +++ b/static/icons/sliders.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/smartphone-charging.svg b/static/icons/smartphone-charging.svg new file mode 100644 index 0000000..cb49409 --- /dev/null +++ b/static/icons/smartphone-charging.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/smartphone.svg b/static/icons/smartphone.svg new file mode 100644 index 0000000..0f005b9 --- /dev/null +++ b/static/icons/smartphone.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/smile-plus.svg b/static/icons/smile-plus.svg new file mode 100644 index 0000000..c189090 --- /dev/null +++ b/static/icons/smile-plus.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/smile.svg b/static/icons/smile.svg new file mode 100644 index 0000000..41bc8f1 --- /dev/null +++ b/static/icons/smile.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/snowflake.svg b/static/icons/snowflake.svg new file mode 100644 index 0000000..9a3763a --- /dev/null +++ b/static/icons/snowflake.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/sofa.svg b/static/icons/sofa.svg new file mode 100644 index 0000000..9b26edc --- /dev/null +++ b/static/icons/sofa.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/sort-asc.svg b/static/icons/sort-asc.svg new file mode 100644 index 0000000..ab52fab --- /dev/null +++ b/static/icons/sort-asc.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/sort-desc.svg b/static/icons/sort-desc.svg new file mode 100644 index 0000000..59528b7 --- /dev/null +++ b/static/icons/sort-desc.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/speaker.svg b/static/icons/speaker.svg new file mode 100644 index 0000000..6f6fef3 --- /dev/null +++ b/static/icons/speaker.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/spline.svg b/static/icons/spline.svg new file mode 100644 index 0000000..6a2b782 --- /dev/null +++ b/static/icons/spline.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/sprout.svg b/static/icons/sprout.svg new file mode 100644 index 0000000..bb82fed --- /dev/null +++ b/static/icons/sprout.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/square.svg b/static/icons/square.svg new file mode 100644 index 0000000..f6ad269 --- /dev/null +++ b/static/icons/square.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/star-half.svg b/static/icons/star-half.svg new file mode 100644 index 0000000..7236c07 --- /dev/null +++ b/static/icons/star-half.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/star-off.svg b/static/icons/star-off.svg new file mode 100644 index 0000000..d993f91 --- /dev/null +++ b/static/icons/star-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/star.svg b/static/icons/star.svg new file mode 100644 index 0000000..47e496c --- /dev/null +++ b/static/icons/star.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/stethoscope.svg b/static/icons/stethoscope.svg new file mode 100644 index 0000000..0bc41fb --- /dev/null +++ b/static/icons/stethoscope.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/sticker.svg b/static/icons/sticker.svg new file mode 100644 index 0000000..cef1427 --- /dev/null +++ b/static/icons/sticker.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/sticky-note.svg b/static/icons/sticky-note.svg new file mode 100644 index 0000000..4012b89 --- /dev/null +++ b/static/icons/sticky-note.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/stop-circle.svg b/static/icons/stop-circle.svg new file mode 100644 index 0000000..8376238 --- /dev/null +++ b/static/icons/stop-circle.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/stretch-horizontal.svg b/static/icons/stretch-horizontal.svg new file mode 100644 index 0000000..3950cfe --- /dev/null +++ b/static/icons/stretch-horizontal.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/stretch-vertical.svg b/static/icons/stretch-vertical.svg new file mode 100644 index 0000000..e085640 --- /dev/null +++ b/static/icons/stretch-vertical.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/strikethrough.svg b/static/icons/strikethrough.svg new file mode 100644 index 0000000..3581a43 --- /dev/null +++ b/static/icons/strikethrough.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/subscript.svg b/static/icons/subscript.svg new file mode 100644 index 0000000..b201152 --- /dev/null +++ b/static/icons/subscript.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/sun-dim.svg b/static/icons/sun-dim.svg new file mode 100644 index 0000000..693057c --- /dev/null +++ b/static/icons/sun-dim.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/sun-medium.svg b/static/icons/sun-medium.svg new file mode 100644 index 0000000..9852e70 --- /dev/null +++ b/static/icons/sun-medium.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/sun-moon.svg b/static/icons/sun-moon.svg new file mode 100644 index 0000000..3a9239b --- /dev/null +++ b/static/icons/sun-moon.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/sun-snow.svg b/static/icons/sun-snow.svg new file mode 100644 index 0000000..b29b6cc --- /dev/null +++ b/static/icons/sun-snow.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/static/icons/sun.svg b/static/icons/sun.svg new file mode 100644 index 0000000..3ecadd6 --- /dev/null +++ b/static/icons/sun.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/sunrise.svg b/static/icons/sunrise.svg new file mode 100644 index 0000000..11c3f5b --- /dev/null +++ b/static/icons/sunrise.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/sunset.svg b/static/icons/sunset.svg new file mode 100644 index 0000000..5e899c5 --- /dev/null +++ b/static/icons/sunset.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/superscript.svg b/static/icons/superscript.svg new file mode 100644 index 0000000..b07c36a --- /dev/null +++ b/static/icons/superscript.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/swiss-franc.svg b/static/icons/swiss-franc.svg new file mode 100644 index 0000000..4e263b4 --- /dev/null +++ b/static/icons/swiss-franc.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/switch-camera.svg b/static/icons/switch-camera.svg new file mode 100644 index 0000000..8efaa2c --- /dev/null +++ b/static/icons/switch-camera.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/sword.svg b/static/icons/sword.svg new file mode 100644 index 0000000..ddb9735 --- /dev/null +++ b/static/icons/sword.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/swords.svg b/static/icons/swords.svg new file mode 100644 index 0000000..12fa5ef --- /dev/null +++ b/static/icons/swords.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/syringe.svg b/static/icons/syringe.svg new file mode 100644 index 0000000..c343360 --- /dev/null +++ b/static/icons/syringe.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/table-2.svg b/static/icons/table-2.svg new file mode 100644 index 0000000..a60705c --- /dev/null +++ b/static/icons/table-2.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/table.svg b/static/icons/table.svg new file mode 100644 index 0000000..e70fd9d --- /dev/null +++ b/static/icons/table.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/tablet.svg b/static/icons/tablet.svg new file mode 100644 index 0000000..c2c0a87 --- /dev/null +++ b/static/icons/tablet.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/tag.svg b/static/icons/tag.svg new file mode 100644 index 0000000..efbbdb0 --- /dev/null +++ b/static/icons/tag.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/tags.svg b/static/icons/tags.svg new file mode 100644 index 0000000..d3c3a11 --- /dev/null +++ b/static/icons/tags.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/target.svg b/static/icons/target.svg new file mode 100644 index 0000000..260624a --- /dev/null +++ b/static/icons/target.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/tent.svg b/static/icons/tent.svg new file mode 100644 index 0000000..c1fd205 --- /dev/null +++ b/static/icons/tent.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/terminal-square.svg b/static/icons/terminal-square.svg new file mode 100644 index 0000000..beef5d3 --- /dev/null +++ b/static/icons/terminal-square.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/terminal.svg b/static/icons/terminal.svg new file mode 100644 index 0000000..fc7b7bf --- /dev/null +++ b/static/icons/terminal.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/text-cursor-input.svg b/static/icons/text-cursor-input.svg new file mode 100644 index 0000000..c21bd27 --- /dev/null +++ b/static/icons/text-cursor-input.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/text-cursor.svg b/static/icons/text-cursor.svg new file mode 100644 index 0000000..748a20a --- /dev/null +++ b/static/icons/text-cursor.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/thermometer-snowflake.svg b/static/icons/thermometer-snowflake.svg new file mode 100644 index 0000000..76f4085 --- /dev/null +++ b/static/icons/thermometer-snowflake.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/thermometer-sun.svg b/static/icons/thermometer-sun.svg new file mode 100644 index 0000000..be25fc8 --- /dev/null +++ b/static/icons/thermometer-sun.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/thermometer.svg b/static/icons/thermometer.svg new file mode 100644 index 0000000..808334d --- /dev/null +++ b/static/icons/thermometer.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/thumbs-down.svg b/static/icons/thumbs-down.svg new file mode 100644 index 0000000..1243b64 --- /dev/null +++ b/static/icons/thumbs-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/thumbs-up.svg b/static/icons/thumbs-up.svg new file mode 100644 index 0000000..5a5fcd9 --- /dev/null +++ b/static/icons/thumbs-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/ticket.svg b/static/icons/ticket.svg new file mode 100644 index 0000000..1361c6c --- /dev/null +++ b/static/icons/ticket.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/timer-off.svg b/static/icons/timer-off.svg new file mode 100644 index 0000000..e6854e4 --- /dev/null +++ b/static/icons/timer-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/timer-reset.svg b/static/icons/timer-reset.svg new file mode 100644 index 0000000..db90462 --- /dev/null +++ b/static/icons/timer-reset.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/timer.svg b/static/icons/timer.svg new file mode 100644 index 0000000..77bade6 --- /dev/null +++ b/static/icons/timer.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/toggle-left.svg b/static/icons/toggle-left.svg new file mode 100644 index 0000000..8d7c6da --- /dev/null +++ b/static/icons/toggle-left.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/toggle-right.svg b/static/icons/toggle-right.svg new file mode 100644 index 0000000..652658c --- /dev/null +++ b/static/icons/toggle-right.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/tornado.svg b/static/icons/tornado.svg new file mode 100644 index 0000000..1f69168 --- /dev/null +++ b/static/icons/tornado.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/toy-brick.svg b/static/icons/toy-brick.svg new file mode 100644 index 0000000..bed2415 --- /dev/null +++ b/static/icons/toy-brick.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/train.svg b/static/icons/train.svg new file mode 100644 index 0000000..a3a1a66 --- /dev/null +++ b/static/icons/train.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/trash-2.svg b/static/icons/trash-2.svg new file mode 100644 index 0000000..e34831f --- /dev/null +++ b/static/icons/trash-2.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/trash.svg b/static/icons/trash.svg new file mode 100644 index 0000000..74b6684 --- /dev/null +++ b/static/icons/trash.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/tree-deciduous.svg b/static/icons/tree-deciduous.svg new file mode 100644 index 0000000..24bfadd --- /dev/null +++ b/static/icons/tree-deciduous.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/tree-pine.svg b/static/icons/tree-pine.svg new file mode 100644 index 0000000..2dbd307 --- /dev/null +++ b/static/icons/tree-pine.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/trees.svg b/static/icons/trees.svg new file mode 100644 index 0000000..b1b4474 --- /dev/null +++ b/static/icons/trees.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/trello.svg b/static/icons/trello.svg new file mode 100644 index 0000000..bc39307 --- /dev/null +++ b/static/icons/trello.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/trending-down.svg b/static/icons/trending-down.svg new file mode 100644 index 0000000..e379601 --- /dev/null +++ b/static/icons/trending-down.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/trending-up.svg b/static/icons/trending-up.svg new file mode 100644 index 0000000..20e5225 --- /dev/null +++ b/static/icons/trending-up.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/triangle.svg b/static/icons/triangle.svg new file mode 100644 index 0000000..ca0b789 --- /dev/null +++ b/static/icons/triangle.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/trophy.svg b/static/icons/trophy.svg new file mode 100644 index 0000000..2854a6b --- /dev/null +++ b/static/icons/trophy.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/truck.svg b/static/icons/truck.svg new file mode 100644 index 0000000..49b2311 --- /dev/null +++ b/static/icons/truck.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/tv-2.svg b/static/icons/tv-2.svg new file mode 100644 index 0000000..f5a05b9 --- /dev/null +++ b/static/icons/tv-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/tv.svg b/static/icons/tv.svg new file mode 100644 index 0000000..cdfcfad --- /dev/null +++ b/static/icons/tv.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/twitch.svg b/static/icons/twitch.svg new file mode 100644 index 0000000..5d49c52 --- /dev/null +++ b/static/icons/twitch.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/twitter.svg b/static/icons/twitter.svg new file mode 100644 index 0000000..a3e00b1 --- /dev/null +++ b/static/icons/twitter.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/type.svg b/static/icons/type.svg new file mode 100644 index 0000000..6128bdd --- /dev/null +++ b/static/icons/type.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/umbrella.svg b/static/icons/umbrella.svg new file mode 100644 index 0000000..82613f6 --- /dev/null +++ b/static/icons/umbrella.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/underline.svg b/static/icons/underline.svg new file mode 100644 index 0000000..f2827da --- /dev/null +++ b/static/icons/underline.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/undo-2.svg b/static/icons/undo-2.svg new file mode 100644 index 0000000..5ed8daf --- /dev/null +++ b/static/icons/undo-2.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/undo.svg b/static/icons/undo.svg new file mode 100644 index 0000000..a647749 --- /dev/null +++ b/static/icons/undo.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/unlink-2.svg b/static/icons/unlink-2.svg new file mode 100644 index 0000000..dd01893 --- /dev/null +++ b/static/icons/unlink-2.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/unlink.svg b/static/icons/unlink.svg new file mode 100644 index 0000000..e82005f --- /dev/null +++ b/static/icons/unlink.svg @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/static/icons/unlock.svg b/static/icons/unlock.svg new file mode 100644 index 0000000..0e6fc78 --- /dev/null +++ b/static/icons/unlock.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/upload-cloud.svg b/static/icons/upload-cloud.svg new file mode 100644 index 0000000..8742ec6 --- /dev/null +++ b/static/icons/upload-cloud.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/upload.svg b/static/icons/upload.svg new file mode 100644 index 0000000..2f861e6 --- /dev/null +++ b/static/icons/upload.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/usb.svg b/static/icons/usb.svg new file mode 100644 index 0000000..1daba79 --- /dev/null +++ b/static/icons/usb.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/user-check.svg b/static/icons/user-check.svg new file mode 100644 index 0000000..8fb3156 --- /dev/null +++ b/static/icons/user-check.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/user-cog.svg b/static/icons/user-cog.svg new file mode 100644 index 0000000..c6f9c95 --- /dev/null +++ b/static/icons/user-cog.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/user-minus.svg b/static/icons/user-minus.svg new file mode 100644 index 0000000..747a34c --- /dev/null +++ b/static/icons/user-minus.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/user-plus.svg b/static/icons/user-plus.svg new file mode 100644 index 0000000..c2cd7fa --- /dev/null +++ b/static/icons/user-plus.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/static/icons/user-x.svg b/static/icons/user-x.svg new file mode 100644 index 0000000..0929815 --- /dev/null +++ b/static/icons/user-x.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/user.svg b/static/icons/user.svg new file mode 100644 index 0000000..8e61592 --- /dev/null +++ b/static/icons/user.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/users.svg b/static/icons/users.svg new file mode 100644 index 0000000..1dcebab --- /dev/null +++ b/static/icons/users.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/utensils-crossed.svg b/static/icons/utensils-crossed.svg new file mode 100644 index 0000000..470edbe --- /dev/null +++ b/static/icons/utensils-crossed.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/utensils.svg b/static/icons/utensils.svg new file mode 100644 index 0000000..d51eda8 --- /dev/null +++ b/static/icons/utensils.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/vegan.svg b/static/icons/vegan.svg new file mode 100644 index 0000000..39030a0 --- /dev/null +++ b/static/icons/vegan.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/venetian-mask.svg b/static/icons/venetian-mask.svg new file mode 100644 index 0000000..a1db42e --- /dev/null +++ b/static/icons/venetian-mask.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/verified.svg b/static/icons/verified.svg new file mode 100644 index 0000000..0226c9b --- /dev/null +++ b/static/icons/verified.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/vibrate-off.svg b/static/icons/vibrate-off.svg new file mode 100644 index 0000000..f7484d4 --- /dev/null +++ b/static/icons/vibrate-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/vibrate.svg b/static/icons/vibrate.svg new file mode 100644 index 0000000..2bce33f --- /dev/null +++ b/static/icons/vibrate.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/video-off.svg b/static/icons/video-off.svg new file mode 100644 index 0000000..79967eb --- /dev/null +++ b/static/icons/video-off.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/video.svg b/static/icons/video.svg new file mode 100644 index 0000000..e6dcc9b --- /dev/null +++ b/static/icons/video.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/view.svg b/static/icons/view.svg new file mode 100644 index 0000000..f4d1850 --- /dev/null +++ b/static/icons/view.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/voicemail.svg b/static/icons/voicemail.svg new file mode 100644 index 0000000..6c346cc --- /dev/null +++ b/static/icons/voicemail.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/volume-1.svg b/static/icons/volume-1.svg new file mode 100644 index 0000000..c6f9a5b --- /dev/null +++ b/static/icons/volume-1.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/volume-2.svg b/static/icons/volume-2.svg new file mode 100644 index 0000000..b1622de --- /dev/null +++ b/static/icons/volume-2.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/volume-x.svg b/static/icons/volume-x.svg new file mode 100644 index 0000000..6a67192 --- /dev/null +++ b/static/icons/volume-x.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/volume.svg b/static/icons/volume.svg new file mode 100644 index 0000000..bdeeb83 --- /dev/null +++ b/static/icons/volume.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/wallet.svg b/static/icons/wallet.svg new file mode 100644 index 0000000..0031bac --- /dev/null +++ b/static/icons/wallet.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/wand-2.svg b/static/icons/wand-2.svg new file mode 100644 index 0000000..5a756e4 --- /dev/null +++ b/static/icons/wand-2.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/wand.svg b/static/icons/wand.svg new file mode 100644 index 0000000..3544b98 --- /dev/null +++ b/static/icons/wand.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/static/icons/watch.svg b/static/icons/watch.svg new file mode 100644 index 0000000..b129d06 --- /dev/null +++ b/static/icons/watch.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/waves.svg b/static/icons/waves.svg new file mode 100644 index 0000000..67bdab1 --- /dev/null +++ b/static/icons/waves.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/webcam.svg b/static/icons/webcam.svg new file mode 100644 index 0000000..f846af3 --- /dev/null +++ b/static/icons/webcam.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/webhook.svg b/static/icons/webhook.svg new file mode 100644 index 0000000..a73e537 --- /dev/null +++ b/static/icons/webhook.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/wheat-off.svg b/static/icons/wheat-off.svg new file mode 100644 index 0000000..0f83244 --- /dev/null +++ b/static/icons/wheat-off.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/static/icons/wheat.svg b/static/icons/wheat.svg new file mode 100644 index 0000000..30bb265 --- /dev/null +++ b/static/icons/wheat.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/static/icons/wifi-off.svg b/static/icons/wifi-off.svg new file mode 100644 index 0000000..379dab3 --- /dev/null +++ b/static/icons/wifi-off.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/static/icons/wifi.svg b/static/icons/wifi.svg new file mode 100644 index 0000000..f0ad5eb --- /dev/null +++ b/static/icons/wifi.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/wind.svg b/static/icons/wind.svg new file mode 100644 index 0000000..4299161 --- /dev/null +++ b/static/icons/wind.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/wine-off.svg b/static/icons/wine-off.svg new file mode 100644 index 0000000..108a9cc --- /dev/null +++ b/static/icons/wine-off.svg @@ -0,0 +1,17 @@ + + + + + + + diff --git a/static/icons/wine.svg b/static/icons/wine.svg new file mode 100644 index 0000000..fbddb1d --- /dev/null +++ b/static/icons/wine.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/wrap-text.svg b/static/icons/wrap-text.svg new file mode 100644 index 0000000..bfc9e74 --- /dev/null +++ b/static/icons/wrap-text.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/wrench.svg b/static/icons/wrench.svg new file mode 100644 index 0000000..7a3c0e0 --- /dev/null +++ b/static/icons/wrench.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/x-circle.svg b/static/icons/x-circle.svg new file mode 100644 index 0000000..0e28b25 --- /dev/null +++ b/static/icons/x-circle.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/x-octagon.svg b/static/icons/x-octagon.svg new file mode 100644 index 0000000..77c4f6e --- /dev/null +++ b/static/icons/x-octagon.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/x-square.svg b/static/icons/x-square.svg new file mode 100644 index 0000000..f343ec1 --- /dev/null +++ b/static/icons/x-square.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/icons/x.svg b/static/icons/x.svg new file mode 100644 index 0000000..559b116 --- /dev/null +++ b/static/icons/x.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/youtube.svg b/static/icons/youtube.svg new file mode 100644 index 0000000..24d82a7 --- /dev/null +++ b/static/icons/youtube.svg @@ -0,0 +1,14 @@ + + + + diff --git a/static/icons/zap-off.svg b/static/icons/zap-off.svg new file mode 100644 index 0000000..238fbcd --- /dev/null +++ b/static/icons/zap-off.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/zap.svg b/static/icons/zap.svg new file mode 100644 index 0000000..c5d0d35 --- /dev/null +++ b/static/icons/zap.svg @@ -0,0 +1,13 @@ + + + diff --git a/static/icons/zoom-in.svg b/static/icons/zoom-in.svg new file mode 100644 index 0000000..0a15151 --- /dev/null +++ b/static/icons/zoom-in.svg @@ -0,0 +1,16 @@ + + + + + + diff --git a/static/icons/zoom-out.svg b/static/icons/zoom-out.svg new file mode 100644 index 0000000..049de6c --- /dev/null +++ b/static/icons/zoom-out.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/input_style.css b/static/input_style.css new file mode 100644 index 0000000..1ee8c62 --- /dev/null +++ b/static/input_style.css @@ -0,0 +1,270 @@ +@import "tailwindcss"; +@import "./theme.css" layer(theme); + +body { + @apply text-gray-950 dark:text-gray-50; +} + +main { + @apply flex flex-col justify-stretch items-center gap-4 p-0 min-h-screen bg-gray-200 text-black dark:bg-gray-900 dark:text-gray-50; +} + +header { + @apply flex flex-col justify-stretch items-center bg-gray-950; +} + +footer { + @apply bg-gray-950 text-gray-50 text-lg flex justify-center p-1; +} + +@utility sticky-bottom { + @apply w-full sticky bottom-0 left-0; +} + +nav { + @apply flex lg:w-4xl justify-center items-center *:text-gray-50 *:flex-1 *:text-xl w-full justify-evenly; +} + +a { + @apply underline; +} + +nav > a { + @apply flex justify-center items-center pt-1; +} + +code { + speak-as: literal-punctuation; + @apply inline-block bg-gray-800 text-gray-50; +} + +pre { + @apply bg-gray-950 border-1 border-gray-600 mb-4 p-1; +} + +pre > code { + @apply !bg-gray-950 p-1; +} + + +h1 { + @apply text-5xl mb-2 mt-4 sm:text-6xl; +} + +h2 { + @apply text-4xl mb-2 mt-4 sm:text-5xl; +} + +h3 { + @apply text-3xl mb-2 mt-4 sm:text-4xl; +} + +h4 { + @apply text-2xl mb-2 mt-4 sm:text-3xl; +} + +h5 { + @apply text-2xl mb-2 mt-4 sm:text-2xl; +} + +details { + @apply rounded-lg bg-gray-200 text-gray-950 p-2 text-xl; +} + +aside { + @apply flex rounded-none flex-col p-4 gap-4 bg-gray-300 text-gray-950 text-2xl dark:text-gray-50 font-semibold dark:bg-gray-800; +} + +aside > mark { + @apply p-1 rounded-sm bg-gray-300; +} + +aside > mark.info { + @apply bg-purple-300; +} + +aside > mark.warning { + @apply bg-yellow-300; +} + +aside > mark.alert { + @apply bg-red-300; +} + +card { + @apply flex flex-col bg-gray-200 dark:bg-gray-800 dark:text-gray-100 max-w-md rounded-lg shadow-lg outline; +} + +card > top { + @apply text-3xl font-bold text-center dark:text-gray-50; +} + +card > top > img { + @apply rounded-t-lg; +} + +card > top > shape { + @apply rounded-t-lg; +} + +card > bottom { + @apply flex text-gray-50 p-3 justify-stretch *:flex-1 gap-2; +} + +card > middle { + @apply flex flex-col text-xl p-4 gap-4; +} + +label { + @apply font-bold text-gray-950 dark:text-gray-100; +} + +input { + @apply shadow-sm outline rounded-sm p-1 bg-gray-200 text-gray-950 dark:text-gray-950; +} + +input::placeholder { + @apply text-gray-700 dark:text-gray-700; +} + +button { + @apply rounded-sm shadow-sm bg-gray-600 text-gray-50 dark:bg-gray-300 dark:text-gray-950 p-3; +} + +blockquote { + @apply border-l-5 border-gray-800 dark:border-black bg-gray-200 text-black dark:bg-gray-700 dark:text-white p-2; +} + +@utility btn-hover { + @apply !bg-gray-900 !text-gray-50; +} + +@utility btn-alert { + @apply !bg-red-800 !text-gray-50; +} + +@utility btn-warning { + @apply !bg-yellow-800 !text-gray-50; +} + +@utility btn-primary { + @apply !bg-teal-300 !text-gray-950; +} + +shape { + @apply bg-gray-300 flex flex-col justify-center items-center aspect-square p-1 text-gray-950; +} + +shape.tiny { + @apply min-w-15 w-15 max-w-15 p-0; +} + +shape.xxs { + @apply min-w-30 w-30 max-w-30 p-0; +} + +shape.xs { + @apply min-w-xs w-xs max-w-xs; +} + +shape.sm { + @apply min-w-sm w-sm max-w-sm; +} + +shape.md { + @apply min-w-md w-md max-w-md; +} + +shape.lg { + @apply min-w-lg w-lg max-w-lg; +} + +shape.xl { + @apply min-w-xl w-xl max-w-xl; +} + +shape.video { + @apply w-full aspect-video; +} + +block { + @apply flex flex-col p-4 gap-4; +} + +block.center-horizontal { + @apply items-center; +} + +block.center-vertical { + @apply justify-center; +} + +bar { + @apply flex flex-col sm:flex-row p-4 gap-4; +} + +bar.center-horizontal { + @apply justify-center; +} + +bar.center-vertical { + @apply items-center; +} + +stack { + display: grid; + grid-template-rows: 1fr; + grid-template-columns: 1fr; + grid-template-areas: "cover"; +} + +stack > * { + width: 100%; + height: 100%; + position: relative; + grid-area: cover; +} + +stack > .top { + z-index: 10; +} + +grid { + @apply grid gap-2 p-4; +} + +hr { + visibility: hidden; +} + +form { + @apply flex flex-col; +} + +form > button-group { + @apply flex text-gray-50 p-3 justify-stretch *:flex-1 gap-2; +} + +select { + @apply text-red-50 bg-gray-800 rounded-lg border-1 border-gray-600 p-1; +} + +table { + @apply bg-gray-200 dark:bg-gray-800 shadow-lg rounded-sm; +} + +@utility table-header { + @apply text-gray-50 bg-gray-950 *:border-x *:border-black; +} + +@utility table-row { + @apply *:border-2 *:border-black *:p-1 hover:bg-gray-100 hover:text-gray-950; +} + +@utility two-panel { + @apply grid-rows-2 grid-cols-1 sm:grid-cols-2 sm:grid-rows-1; +} + +@utility debug { + @apply !border-1 !border-red-900; +} diff --git a/static/js/code.js b/static/js/code.js new file mode 100644 index 0000000..504ce54 --- /dev/null +++ b/static/js/code.js @@ -0,0 +1,89 @@ +class PaginateTable { + constructor(url) { + this.page = 0; + this.items = []; + this.url = url; + this.headers = []; + this.search_query=""; + } + + async contents() { + console.log("CONTENTS RUN"); + if(this.page < 0) this.page = 0; + + let url = `${this.url}?page=${this.page}`; + + if(this.search_query !== "") { + this.page = 0; + url += `&search=${this.search_query}` + } + + const resp = await fetch(url); + console.assert(resp.status == 200, "failed to get it"); + + const items = await resp.json(); + + if(items) { + this.items = items; + this.headers = Object.keys(this.items[0]); + } + + return this.items; + } +} + +class ForeverScroll { + constructor(url) { + this.page = 0; + this.items = []; + this.url = url; + this.end = false; + } + + async init() { + const resp = await fetch(this.url); + console.assert(resp.status == 200, "failed to get it"); + + const items = await resp.json(); + if(items) this.items = items; + + return items; + } + + async load() { + this.page += 1 + let url = `${this.url}?page=${this.page}`; + + const resp = await fetch(url); + console.assert(resp.status == 200, "failed to get it"); + + const items = await resp.json(); + + if(items) { + this.items.push(...items); + } else { + this.end = true; + } + } +} + +const ConfirmDelete = async (table, obj_id) => { + if(confirm("Are you sure?")) { + await fetch("/api/admin/table/" + table + "/" + obj_id, + { method: "DELETE" }); + window.location = "/admin/table/" + table; + } else { + return false; + } +} + +const UrlId = () => { + let url = new URL(window.location.href); + let parts = url.pathname.split("/"); + + if(window.location.href.endsWith("/")) { + return parts[parts.length - 2]; + } else { + return parts[parts.length - 1]; + } +} diff --git a/static/js/jzed.js b/static/js/jzed.js new file mode 100644 index 0000000..23965cd --- /dev/null +++ b/static/js/jzed.js @@ -0,0 +1,319 @@ +const $boot = (cb) => { + document.addEventListener("DOMContentLoaded", cb); +} + +const $sanitize = (badHTML) => { + // this Option hack courtesy of stackoverflow + return new Option(badHTML).innerHTML; +} + +const validate_sanitized = (sanitized) => { + const check = JSON.stringify(sanitized); + console.assert(!check.includes("<"), + "YOU BEEN HACKED! Send Zed this:", sanitized); +} + +const $sanitize_data = (data) => { + const sanitized = $sanitize(JSON.stringify(data)); + validate_sanitized(sanitized); + return JSON.parse(sanitized); +} + +const $render = (template, data={}) => { + const sanitized = $sanitize_data(data); + + const args = Object.keys(sanitized); + const values = Object.values(sanitized) + + const render_func = new Function(...args, + `return \`${template.innerHTML}\``) + + const text = render_func(...values); + + return $html(text); +} + +const $render_data = (template_id, target_id, data) => { + const target = $id(target_id); + const template = $id(template_id); + let new_data = []; + + if(Array.isArray(data)) { + new_data = data.map((item, i) => { + return $render(template, {i, item}); + }); + } else if(data instanceof Object) { + new_data.push($render(template, data)); + } else { + console.error("$render only works with {} or [] data", data); + new_data.push($html("ERROR LOOK IN CONSOLE")); + } + + $replace_with(target, new_data); +} + +const $get = (name, inChildren) => { + if(inChildren) { + return inChildren.querySelector(name); + } else { + return document.querySelector(name); + } +} + +const $all = (name, inChildren) => { + if(inChildren) { + return inChildren.querySelectorAll(name); + } else { + return document.querySelectorAll(name); + } +} + +const $id = (name, inChildren) => { + if(inChildren) { + return inChildren.children.namedItem(name); + } else { + return document.getElementById(name); + } +} + +const $class = (name) => { + return document.getElementsByClassName(name); +} + +const $name = (name) => { + return document.getElementsByTagName(name); +} + +const $filter = (nodes, fn) => { + return Array.prototype.filter.call(nodes, fn); +} + +const $next = (node) => { + return node.nextElementSibling; +} + +const $previous = (node) => { + return node.previousElementSibling; +} + +const $siblings = (node) => { + return $filter(node.parentNode.children, + child => { return child !== node; }); +} + +const $style_toggle = (node, className) => { + node.classList.toggle(className); +} + +const $style_add = (node, className) => { + node.classList.add(className); +} + +const $style_del = (node, className) => { + node.classList.remove(className); +} + +const $style_of = (node, ruleName) => { + return getComputedStyle(node)[ruleName] +} + +const $new = (tag, id, html) => { + let new_tag = document.createElement(tag); + new_tag.id = id; + new_tag.innerHTML = html; + return new_tag.cloneNode(true); +} + +const $append = (parent, child) => { + parent.appendChild(child); +} + +const $prepend = (parent, node) => { + parent.insertBefore(node, parent.firstChild); +} + +const $remove = (parent, child) => { + parent.removeChild(child); +} + +const $clone = (node) => { + return node.cloneNode(true); +} + +const $contains = (node, child) => { + return node !== child && node.contains(child); +} + +const $has = (node, selector) => { + return node.querySelector(selector) !== null; +} + +const $empty = (node) => { + return node.innerHTML == ''; +} + +const $attribute_of = (node, name) => { + return node.getAttribute(name); +} + +const $attribute = (node, name, value) => { + return node.setAttribute(name, value); +} + +const $contents_of = (node) => { + return node.innerHTML; +} + +const $contents = (node, newhtml) => { + node.innerHTML = newhtml; +} + +const $has_class = (node, className) => { + return node.classList.contains(className); +} + +const $outer_html = (node) => { + return node.outerHTML; +} + +const $replace_with = (node, newNodes) => { + if(Array.isArray(newNodes)) { + node.replaceChildren(...newNodes); + } else { + node.replaceChildren(newNodes); + } +} + +const $matches = (node, selector) => { + return node.matches(selector); +} + +const $parent = (node) => { + return node.parentNode; +} + +const $text_of = (node) => { + return node.textContent; +} + +const $text = (node, newtext) => { + node.textContent = newtext; +} + +const $off = (node, eventName, eventHandler) => { + node.removeEventListener(eventName, eventHandler); +} + +const $on = (node, eventName, eventHandler) => { + node.addEventListener(eventName, eventHandler); +} + +const $now = () => { + return Date.now(); +} + +const $html = (htmlString) => { + const temp = document.createElement('template'); + temp.innerHTML = htmlString; + return temp.content; +} + +const $observe = (node_id, cb) => { + const options = { + root: document, + rootMargin: "0px", + scrollMargin: "0px", + threshold: 1.0, + delay: 200, + }; + + const callback = (entries, observer) => { + cb(); + } + + const observer = new IntersectionObserver(callback, options); + observer.observe($id(node_id)); +} + +const $switch = (template_id, data) => { + let tmpl = $id(template_id); + + let to_replace = $render(tmpl).children; + + for(let child of to_replace) { + let when = JSON.parse($attribute_of(child, 'x-when')); + if(when === data) { + return child; + } + } + + return null; +} + +const $render_error = (data) => { + const target = $id('error'); + + if(!target) { + console.error("No id=error to display the error."); + return; + } + + const templ = $id('error-template'); + + if(!templ) { + console.error("template with id=error-template to display error."); + return; + } + + $replace_with(target, $render(templ, data)); +} + +const $has_error = (data, err) => { + if(err === 200) { + return false; + } else { + $render_error(data); + return true; + } +} + +const $no_error = (data, err) => { + return !$has_error(data, err); +} + +const $redirect = (url, replace=false) => { + window.location.replace(url); +} + +const $form_submit = async (form_id, event) => { + event.preventDefault(); + + const form = event.target; + const fd = new FormData(form); + + const resp = await fetch(form.action, + {method: form.method, body: fd}); + const data = await resp.json(); + + return [data, resp.status]; +} + +const $handle_form = (form_id, cb) => { + const form = $id(form_id); + if(!form) { + console.error("There's no form named", form_id); + return; + } + + const submitter = async (event) => { + const [data, status] = await $form_submit(form_id, event); + cb(data, status); + } + + form.addEventListener('submit', submitter); +} + +const $get_json = async (url) => { + const resp = await fetch(url); + return [await resp.json(), resp.status]; +} diff --git a/static/js/paypal_app.js b/static/js/paypal_app.js new file mode 100644 index 0000000..bfc40aa --- /dev/null +++ b/static/js/paypal_app.js @@ -0,0 +1,113 @@ +const paypalButtons = window.paypal.Buttons({ + style: { + shape: "rect", + layout: "vertical", + color: "gold", + label: "pay", + }, + message: { + amount: 100, + }, + async createOrder() { + try { + const response = await fetch("/api/paypal/order", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + // use the "body" param to optionally pass additional order information + // like product ids and quantities + // body: JSON.stringify({ + // cart: [ + // { + // id: "YOUR_PRODUCT_ID", + // quantity: "YOUR_PRODUCT_QUANTITY", + // }, + // ], + // }), + }); + + const orderData = await response.json(); + + if (orderData.id) { + return orderData.id; + } + const errorDetail = orderData?.details?.[0]; + const errorMessage = errorDetail + ? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})` + : JSON.stringify(orderData); + + throw new Error(errorMessage); + } catch (error) { + console.error(error); + // resultMessage(`Could not initiate PayPal Checkout...

${error}`); + } + }, + async onApprove(data, actions) { + try { + const response = await fetch( + `/api/paypal/order/${data.orderID}/capture`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + } + ); + + const orderData = await response.json(); + // Three cases to handle: + // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart() + // (2) Other non-recoverable errors -> Show a failure message + // (3) Successful transaction -> Show confirmation or thank you message + + const errorDetail = orderData?.details?.[0]; + + if (errorDetail?.issue === "INSTRUMENT_DECLINED") { + // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart() + // recoverable state, per + // https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/ + return actions.restart(); + } else if (errorDetail) { + // (2) Other non-recoverable errors -> Show a failure message + throw new Error( + `${errorDetail.description} (${orderData.debug_id})` + ); + } else if (!orderData.purchase_units) { + throw new Error(JSON.stringify(orderData)); + } else { + // (3) Successful transaction -> Show confirmation or thank you message + // Or go to another URL: actions.redirect('thank_you.html'); + const transaction = + orderData?.purchase_units?.[0]?.payments?.captures?.[0] || + orderData?.purchase_units?.[0]?.payments + ?.authorizations?.[0]; + resultMessage( + `Transaction ${transaction.status}: ${transaction.id}
+
See console for all available details` + ); + console.log( + "Capture result", + orderData, + JSON.stringify(orderData, null, 2) + ); + } + } catch (error) { + console.error(error); + resultMessage( + `Sorry, your transaction could not be processed...

${error}` + ); + } + }, + + +}); +paypalButtons.render("#paypal-button-container"); + + +// Example function to show a result to the user. Your site's UI library can be used instead. +function resultMessage(message) { + const container = document.querySelector("#result-message"); + container.innerHTML = message; +} + diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..02fbe44 Binary files /dev/null and b/static/logo.png differ diff --git a/static/theme.css b/static/theme.css new file mode 100644 index 0000000..57284c0 --- /dev/null +++ b/static/theme.css @@ -0,0 +1,462 @@ +@theme default { + --font-sans: + ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; + --font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', + monospace; + + --color-red-50: oklch(97.1% 0.013 17.38); + --color-red-100: oklch(93.6% 0.032 17.717); + --color-red-200: oklch(88.5% 0.062 18.334); + --color-red-300: oklch(80.8% 0.114 19.571); + --color-red-400: oklch(70.4% 0.191 22.216); + --color-red-500: oklch(63.7% 0.237 25.331); + --color-red-600: oklch(57.7% 0.245 27.325); + --color-red-700: oklch(50.5% 0.213 27.518); + --color-red-800: oklch(44.4% 0.177 26.899); + --color-red-900: oklch(39.6% 0.141 25.723); + --color-red-950: oklch(25.8% 0.092 26.042); + + --color-orange-50: oklch(98% 0.016 73.684); + --color-orange-100: oklch(95.4% 0.038 75.164); + --color-orange-200: oklch(90.1% 0.076 70.697); + --color-orange-300: oklch(83.7% 0.128 66.29); + --color-orange-400: oklch(75% 0.183 55.934); + --color-orange-500: oklch(70.5% 0.213 47.604); + --color-orange-600: oklch(64.6% 0.222 41.116); + --color-orange-700: oklch(55.3% 0.195 38.402); + --color-orange-800: oklch(47% 0.157 37.304); + --color-orange-900: oklch(40.8% 0.123 38.172); + --color-orange-950: oklch(26.6% 0.079 36.259); + + --color-amber-50: oklch(98.7% 0.022 95.277); + --color-amber-100: oklch(96.2% 0.059 95.617); + --color-amber-200: oklch(92.4% 0.12 95.746); + --color-amber-300: oklch(87.9% 0.169 91.605); + --color-amber-400: oklch(82.8% 0.189 84.429); + --color-amber-500: oklch(76.9% 0.188 70.08); + --color-amber-600: oklch(66.6% 0.179 58.318); + --color-amber-700: oklch(55.5% 0.163 48.998); + --color-amber-800: oklch(47.3% 0.137 46.201); + --color-amber-900: oklch(41.4% 0.112 45.904); + --color-amber-950: oklch(27.9% 0.077 45.635); + + --color-yellow-50: oklch(98.7% 0.026 102.212); + --color-yellow-100: oklch(97.3% 0.071 103.193); + --color-yellow-200: oklch(94.5% 0.129 101.54); + --color-yellow-300: oklch(90.5% 0.182 98.111); + --color-yellow-400: oklch(85.2% 0.199 91.936); + --color-yellow-500: oklch(79.5% 0.184 86.047); + --color-yellow-600: oklch(68.1% 0.162 75.834); + --color-yellow-700: oklch(55.4% 0.135 66.442); + --color-yellow-800: oklch(47.6% 0.114 61.907); + --color-yellow-900: oklch(42.1% 0.095 57.708); + --color-yellow-950: oklch(28.6% 0.066 53.813); + + --color-lime-50: oklch(98.6% 0.031 120.757); + --color-lime-100: oklch(96.7% 0.067 122.328); + --color-lime-200: oklch(93.8% 0.127 124.321); + --color-lime-300: oklch(89.7% 0.196 126.665); + --color-lime-400: oklch(84.1% 0.238 128.85); + --color-lime-500: oklch(76.8% 0.233 130.85); + --color-lime-600: oklch(64.8% 0.2 131.684); + --color-lime-700: oklch(53.2% 0.157 131.589); + --color-lime-800: oklch(45.3% 0.124 130.933); + --color-lime-900: oklch(40.5% 0.101 131.063); + --color-lime-950: oklch(27.4% 0.072 132.109); + + --color-green-50: oklch(98.2% 0.018 155.826); + --color-green-100: oklch(96.2% 0.044 156.743); + --color-green-200: oklch(92.5% 0.084 155.995); + --color-green-300: oklch(87.1% 0.15 154.449); + --color-green-400: oklch(79.2% 0.209 151.711); + --color-green-500: oklch(72.3% 0.219 149.579); + --color-green-600: oklch(62.7% 0.194 149.214); + --color-green-700: oklch(52.7% 0.154 150.069); + --color-green-800: oklch(44.8% 0.119 151.328); + --color-green-900: oklch(39.3% 0.095 152.535); + --color-green-950: oklch(26.6% 0.065 152.934); + + --color-emerald-50: oklch(97.9% 0.021 166.113); + --color-emerald-100: oklch(95% 0.052 163.051); + --color-emerald-200: oklch(90.5% 0.093 164.15); + --color-emerald-300: oklch(84.5% 0.143 164.978); + --color-emerald-400: oklch(76.5% 0.177 163.223); + --color-emerald-500: oklch(69.6% 0.17 162.48); + --color-emerald-600: oklch(59.6% 0.145 163.225); + --color-emerald-700: oklch(50.8% 0.118 165.612); + --color-emerald-800: oklch(43.2% 0.095 166.913); + --color-emerald-900: oklch(37.8% 0.077 168.94); + --color-emerald-950: oklch(26.2% 0.051 172.552); + + --color-teal-50: oklch(98.4% 0.014 180.72); + --color-teal-100: oklch(95.3% 0.051 180.801); + --color-teal-200: oklch(91% 0.096 180.426); + --color-teal-300: oklch(85.5% 0.138 181.071); + --color-teal-400: oklch(77.7% 0.152 181.912); + --color-teal-500: oklch(70.4% 0.14 182.503); + --color-teal-600: oklch(60% 0.118 184.704); + --color-teal-700: oklch(51.1% 0.096 186.391); + --color-teal-800: oklch(43.7% 0.078 188.216); + --color-teal-900: oklch(38.6% 0.063 188.416); + --color-teal-950: oklch(27.7% 0.046 192.524); + + --color-cyan-50: oklch(98.4% 0.019 200.873); + --color-cyan-100: oklch(95.6% 0.045 203.388); + --color-cyan-200: oklch(91.7% 0.08 205.041); + --color-cyan-300: oklch(86.5% 0.127 207.078); + --color-cyan-400: oklch(78.9% 0.154 211.53); + --color-cyan-500: oklch(71.5% 0.143 215.221); + --color-cyan-600: oklch(60.9% 0.126 221.723); + --color-cyan-700: oklch(52% 0.105 223.128); + --color-cyan-800: oklch(45% 0.085 224.283); + --color-cyan-900: oklch(39.8% 0.07 227.392); + --color-cyan-950: oklch(30.2% 0.056 229.695); + + --color-sky-50: oklch(97.7% 0.013 236.62); + --color-sky-100: oklch(95.1% 0.026 236.824); + --color-sky-200: oklch(90.1% 0.058 230.902); + --color-sky-300: oklch(82.8% 0.111 230.318); + --color-sky-400: oklch(74.6% 0.16 232.661); + --color-sky-500: oklch(68.5% 0.169 237.323); + --color-sky-600: oklch(58.8% 0.158 241.966); + --color-sky-700: oklch(50% 0.134 242.749); + --color-sky-800: oklch(44.3% 0.11 240.79); + --color-sky-900: oklch(39.1% 0.09 240.876); + --color-sky-950: oklch(29.3% 0.066 243.157); + + --color-blue-50: oklch(97% 0.014 254.604); + --color-blue-100: oklch(93.2% 0.032 255.585); + --color-blue-200: oklch(88.2% 0.059 254.128); + --color-blue-300: oklch(80.9% 0.105 251.813); + --color-blue-400: oklch(70.7% 0.165 254.624); + --color-blue-500: oklch(62.3% 0.214 259.815); + --color-blue-600: oklch(54.6% 0.245 262.881); + --color-blue-700: oklch(48.8% 0.243 264.376); + --color-blue-800: oklch(42.4% 0.199 265.638); + --color-blue-900: oklch(37.9% 0.146 265.522); + --color-blue-950: oklch(28.2% 0.091 267.935); + + --color-indigo-50: oklch(96.2% 0.018 272.314); + --color-indigo-100: oklch(93% 0.034 272.788); + --color-indigo-200: oklch(87% 0.065 274.039); + --color-indigo-300: oklch(78.5% 0.115 274.713); + --color-indigo-400: oklch(67.3% 0.182 276.935); + --color-indigo-500: oklch(58.5% 0.233 277.117); + --color-indigo-600: oklch(51.1% 0.262 276.966); + --color-indigo-700: oklch(45.7% 0.24 277.023); + --color-indigo-800: oklch(39.8% 0.195 277.366); + --color-indigo-900: oklch(35.9% 0.144 278.697); + --color-indigo-950: oklch(25.7% 0.09 281.288); + + --color-violet-50: oklch(96.9% 0.016 293.756); + --color-violet-100: oklch(94.3% 0.029 294.588); + --color-violet-200: oklch(89.4% 0.057 293.283); + --color-violet-300: oklch(81.1% 0.111 293.571); + --color-violet-400: oklch(70.2% 0.183 293.541); + --color-violet-500: oklch(60.6% 0.25 292.717); + --color-violet-600: oklch(54.1% 0.281 293.009); + --color-violet-700: oklch(49.1% 0.27 292.581); + --color-violet-800: oklch(43.2% 0.232 292.759); + --color-violet-900: oklch(38% 0.189 293.745); + --color-violet-950: oklch(28.3% 0.141 291.089); + + --color-purple-50: oklch(97.7% 0.014 308.299); + --color-purple-100: oklch(94.6% 0.033 307.174); + --color-purple-200: oklch(90.2% 0.063 306.703); + --color-purple-300: oklch(82.7% 0.119 306.383); + --color-purple-400: oklch(71.4% 0.203 305.504); + --color-purple-500: oklch(62.7% 0.265 303.9); + --color-purple-600: oklch(55.8% 0.288 302.321); + --color-purple-700: oklch(49.6% 0.265 301.924); + --color-purple-800: oklch(43.8% 0.218 303.724); + --color-purple-900: oklch(38.1% 0.176 304.987); + --color-purple-950: oklch(29.1% 0.149 302.717); + + --color-fuchsia-50: oklch(97.7% 0.017 320.058); + --color-fuchsia-100: oklch(95.2% 0.037 318.852); + --color-fuchsia-200: oklch(90.3% 0.076 319.62); + --color-fuchsia-300: oklch(83.3% 0.145 321.434); + --color-fuchsia-400: oklch(74% 0.238 322.16); + --color-fuchsia-500: oklch(66.7% 0.295 322.15); + --color-fuchsia-600: oklch(59.1% 0.293 322.896); + --color-fuchsia-700: oklch(51.8% 0.253 323.949); + --color-fuchsia-800: oklch(45.2% 0.211 324.591); + --color-fuchsia-900: oklch(40.1% 0.17 325.612); + --color-fuchsia-950: oklch(29.3% 0.136 325.661); + + --color-pink-50: oklch(97.1% 0.014 343.198); + --color-pink-100: oklch(94.8% 0.028 342.258); + --color-pink-200: oklch(89.9% 0.061 343.231); + --color-pink-300: oklch(82.3% 0.12 346.018); + --color-pink-400: oklch(71.8% 0.202 349.761); + --color-pink-500: oklch(65.6% 0.241 354.308); + --color-pink-600: oklch(59.2% 0.249 0.584); + --color-pink-700: oklch(52.5% 0.223 3.958); + --color-pink-800: oklch(45.9% 0.187 3.815); + --color-pink-900: oklch(40.8% 0.153 2.432); + --color-pink-950: oklch(28.4% 0.109 3.907); + + --color-rose-50: oklch(96.9% 0.015 12.422); + --color-rose-100: oklch(94.1% 0.03 12.58); + --color-rose-200: oklch(89.2% 0.058 10.001); + --color-rose-300: oklch(81% 0.117 11.638); + --color-rose-400: oklch(71.2% 0.194 13.428); + --color-rose-500: oklch(64.5% 0.246 16.439); + --color-rose-600: oklch(58.6% 0.253 17.585); + --color-rose-700: oklch(51.4% 0.222 16.935); + --color-rose-800: oklch(45.5% 0.188 13.697); + --color-rose-900: oklch(41% 0.159 10.272); + --color-rose-950: oklch(27.1% 0.105 12.094); + + --color-slate-50: oklch(98.4% 0.003 247.858); + --color-slate-100: oklch(96.8% 0.007 247.896); + --color-slate-200: oklch(92.9% 0.013 255.508); + --color-slate-300: oklch(86.9% 0.022 252.894); + --color-slate-400: oklch(70.4% 0.04 256.788); + --color-slate-500: oklch(55.4% 0.046 257.417); + --color-slate-600: oklch(44.6% 0.043 257.281); + --color-slate-700: oklch(37.2% 0.044 257.287); + --color-slate-800: oklch(27.9% 0.041 260.031); + --color-slate-900: oklch(20.8% 0.042 265.755); + --color-slate-950: oklch(12.9% 0.042 264.695); + + --color-gray-50: oklch(98.5% 0.0 247.839); + --color-gray-100: oklch(96.7% 0.0 264.542); + --color-gray-200: oklch(92.8% 0.0 264.531); + --color-gray-300: oklch(87.2% 0.0 258.338); + --color-gray-400: oklch(70.7% 0.0 261.325); + --color-gray-500: oklch(55.1% 0.0 264.364); + --color-gray-600: oklch(44.6% 0.0 256.802); + --color-gray-700: oklch(37.3% 0.0 259.733); + --color-gray-800: oklch(27.8% 0.0 256.848); + --color-gray-900: oklch(21% 0.0 264.665); + --color-gray-950: oklch(13% 0.0 261.692); + + --color-zinc-50: oklch(98.5% 0 0); + --color-zinc-100: oklch(96.7% 0.001 286.375); + --color-zinc-200: oklch(92% 0.004 286.32); + --color-zinc-300: oklch(87.1% 0.006 286.286); + --color-zinc-400: oklch(70.5% 0.015 286.067); + --color-zinc-500: oklch(55.2% 0.016 285.938); + --color-zinc-600: oklch(44.2% 0.017 285.786); + --color-zinc-700: oklch(37% 0.013 285.805); + --color-zinc-800: oklch(27.4% 0.006 286.033); + --color-zinc-900: oklch(21% 0.006 285.885); + --color-zinc-950: oklch(14.1% 0.005 285.823); + + --color-neutral-50: oklch(98.5% 0 0); + --color-neutral-100: oklch(97% 0 0); + --color-neutral-200: oklch(92.2% 0 0); + --color-neutral-300: oklch(87% 0 0); + --color-neutral-400: oklch(70.8% 0 0); + --color-neutral-500: oklch(55.6% 0 0); + --color-neutral-600: oklch(43.9% 0 0); + --color-neutral-700: oklch(37.1% 0 0); + --color-neutral-800: oklch(26.9% 0 0); + --color-neutral-900: oklch(20.5% 0 0); + --color-neutral-950: oklch(14.5% 0 0); + + --color-stone-50: oklch(98.5% 0.001 106.423); + --color-stone-100: oklch(97% 0.001 106.424); + --color-stone-200: oklch(92.3% 0.003 48.717); + --color-stone-300: oklch(86.9% 0.005 56.366); + --color-stone-400: oklch(70.9% 0.01 56.259); + --color-stone-500: oklch(55.3% 0.013 58.071); + --color-stone-600: oklch(44.4% 0.011 73.639); + --color-stone-700: oklch(37.4% 0.01 67.558); + --color-stone-800: oklch(26.8% 0.007 34.298); + --color-stone-900: oklch(21.6% 0.006 56.043); + --color-stone-950: oklch(14.7% 0.004 49.25); + + --color-black: #000; + --color-white: #fff; + + --spacing: 0.25rem; + + --breakpoint-sm: 40rem; + --breakpoint-md: 48rem; + --breakpoint-lg: 64rem; + --breakpoint-xl: 80rem; + --breakpoint-2xl: 96rem; + + --container-3xs: 16rem; + --container-2xs: 18rem; + --container-xs: 20rem; + --container-sm: 24rem; + --container-md: 28rem; + --container-lg: 32rem; + --container-xl: 36rem; + --container-2xl: 42rem; + --container-3xl: 48rem; + --container-4xl: 56rem; + --container-5xl: 64rem; + --container-6xl: 72rem; + --container-7xl: 80rem; + + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-base: 1rem; + --text-base--line-height: calc(1.5 / 1); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --text-5xl: 3rem; + --text-5xl--line-height: 1; + --text-6xl: 3.75rem; + --text-6xl--line-height: 1; + --text-7xl: 4.5rem; + --text-7xl--line-height: 1; + --text-8xl: 6rem; + --text-8xl--line-height: 1; + --text-9xl: 8rem; + --text-9xl--line-height: 1; + + --font-weight-thin: 100; + --font-weight-extralight: 200; + --font-weight-light: 300; + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --font-weight-extrabold: 800; + --font-weight-black: 900; + + --tracking-tighter: -0.05em; + --tracking-tight: -0.025em; + --tracking-normal: 0em; + --tracking-wide: 0.025em; + --tracking-wider: 0.05em; + --tracking-widest: 0.1em; + + --leading-tight: 1.25; + --leading-snug: 1.375; + --leading-normal: 1.5; + --leading-relaxed: 1.625; + --leading-loose: 2; + + --radius-xs: 0.125rem; + --radius-sm: 0.25rem; + --radius-md: 0.375rem; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --radius-2xl: 1rem; + --radius-3xl: 1.5rem; + --radius-4xl: 2rem; + + --shadow-2xs: 0 1px rgb(0 0 0 / 0.05); + --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); + + --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05); + --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05); + --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05); + + --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05); + --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15); + --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12); + --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15); + --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1); + --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15); + + --text-shadow-2xs: 0px 1px 0px rgb(0 0 0 / 0.15); + --text-shadow-xs: 0px 1px 1px rgb(0 0 0 / 0.2); + --text-shadow-sm: + 0px 1px 0px rgb(0 0 0 / 0.075), 0px 1px 1px rgb(0 0 0 / 0.075), 0px 2px 2px rgb(0 0 0 / 0.075); + --text-shadow-md: + 0px 1px 1px rgb(0 0 0 / 0.1), 0px 1px 2px rgb(0 0 0 / 0.1), 0px 2px 4px rgb(0 0 0 / 0.1); + --text-shadow-lg: + 0px 1px 2px rgb(0 0 0 / 0.1), 0px 3px 2px rgb(0 0 0 / 0.1), 0px 4px 8px rgb(0 0 0 / 0.1); + + --ease-in: cubic-bezier(0.4, 0, 1, 1); + --ease-out: cubic-bezier(0, 0, 0.2, 1); + --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); + + --animate-spin: spin 1s linear infinite; + --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + --animate-bounce: bounce 1s infinite; + + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + @keyframes ping { + 75%, + 100% { + transform: scale(2); + opacity: 0; + } + } + + @keyframes pulse { + 50% { + opacity: 0.5; + } + } + + @keyframes bounce { + 0%, + 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + + 50% { + transform: none; + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } + } + + --blur-xs: 4px; + --blur-sm: 8px; + --blur-md: 12px; + --blur-lg: 16px; + --blur-xl: 24px; + --blur-2xl: 40px; + --blur-3xl: 64px; + + --perspective-dramatic: 100px; + --perspective-near: 300px; + --perspective-normal: 500px; + --perspective-midrange: 800px; + --perspective-distant: 1200px; + + --aspect-video: 16 / 9; + + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: --theme(--font-sans, initial); + --default-font-feature-settings: --theme(--font-sans--font-feature-settings, initial); + --default-font-variation-settings: --theme(--font-sans--font-variation-settings, initial); + --default-mono-font-family: --theme(--font-mono, initial); + --default-mono-font-feature-settings: --theme(--font-mono--font-feature-settings, initial); + --default-mono-font-variation-settings: --theme(--font-mono--font-variation-settings, initial); +} + +/* Deprecated */ +@theme default inline reference { + --blur: 8px; + --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); + --drop-shadow: 0 1px 2px rgb(0 0 0 / 0.1), 0 1px 1px rgb(0 0 0 / 0.06); + --radius: 0.25rem; + --max-width-prose: 65ch; +} diff --git a/tests/admin/admin_test.go b/tests/admin/admin_test.go new file mode 100644 index 0000000..c60224d --- /dev/null +++ b/tests/admin/admin_test.go @@ -0,0 +1,82 @@ +package tests_admin + +import ( + "testing" + "fmt" + "strings" + "reflect" + "github.com/stretchr/testify/require" + "MY/webapp/data" + admin "MY/webapp/features/admin" + sq "github.com/Masterminds/squirrel" + "os" +) + +func TestAdminIndexPage(t *testing.T) { + assert := require.New(t) + models := data.Models() + table := "user" + model := models[table] + + fields := reflect.VisibleFields(model) + + for _, field := range fields { + assert.NotEqual(field.Name, "") + assert.NotEqual(field.Tag, "") + } + + for i := 0; i < 87; i++ { + val := reflect.New(model).Elem() + email := fmt.Sprintf("test%d@test.com", i) + val.FieldByName("Email").SetString(email) + val.FieldByName("Username").SetString(fmt.Sprintf("zed%d", i)) + val.FieldByName("Password").SetString("garbage") + + sql_query, args, err := sq.Delete(table).Where(sq.Eq{"email": email}).ToSql() + assert.NoError(err) + + _, err = data.DB.Exec(sql_query, args...) + assert.NoError(err) + + id, count, err := admin.Insert(table, val) + assert.Equal(count, int64(1)) + assert.NotEqual(id, int64(0)) + assert.NoError(err, email) + } + + all_rows, err := admin.SelectTable(table, 20, 2) + assert.NoError(err) + assert.Equal(20, len(all_rows)) + + first_row := all_rows[0].(*data.User) + + result, err := admin.Get(table, int64(first_row.Id)) + if err != nil { fmt.Println("ERROR", err) } + + id := result.FieldByName("Id") + result, err = admin.Get(table, id.Int()) + assert.NoError(err) + + username := result.FieldByName("Username").String() + + // only remove test users + if strings.HasPrefix(username, "test") { + result.FieldByName("Username").SetString("joeblow") + result.FieldByName("Email").SetString("what@what.com") + + update_id, err := admin.Update(table, result) + assert.NoError(err) + assert.Equal(id.Int(), update_id) + + err = admin.Delete(table, update_id) + assert.NoError(err) + } +} + +func TestMain(m *testing.M) { + data.Setup("sqlite3", "./db.sqlite3") + defer data.Shutdown() + + code := m.Run() + os.Exit(code) +} diff --git a/tests/admin/admin_ui_test.go b/tests/admin/admin_ui_test.go new file mode 100644 index 0000000..d7fc022 --- /dev/null +++ b/tests/admin/admin_ui_test.go @@ -0,0 +1,28 @@ +package tests_admin + +import ( + "testing" + "time" + // "github.com/stretchr/testify/require" + // "MY/webapp/data" + // sq "github.com/Masterminds/squirrel" + . "MY/webapp/tests/tools" +) + +func TestTableListing(t *testing.T) { + z, cancel := Setup(t, 2 * time.Second); + defer cancel(); + + // confirm redirect if not logged in + z.GoTo("/admin/table/", `[data-testid="index-page"]`) + + // now log in and go to admin + + z.GoTo("/login/", `[data-testid="login-index-page"]`) + z.TypeIn(`#username`, `admin`) + z.TypeIn(`#password`, `testing123`) + z.ClickOn(`#login-submit`) + z.WaitFor(`[data-testid="index-page"]`) + + z.GoTo("/admin/table/", `[data-testid="admin-table--page"]`) +} diff --git a/tests/auth/login_test.go b/tests/auth/login_test.go new file mode 100644 index 0000000..df0282b --- /dev/null +++ b/tests/auth/login_test.go @@ -0,0 +1,44 @@ +package tests_auth + +import ( + "testing" + // "github.com/stretchr/testify/require" + "MY/webapp/data" + sq "github.com/Masterminds/squirrel" + . "MY/webapp/tests/tools" +) + +func deleteTestUser(username string) { + sql, args, err := sq.Delete("user").Where("username=?", username).ToSql() + data.Exec(err, sql, args...) +} + +func TestLogin(t *testing.T) { + deleteTestUser("testerzed") + z, cancel := Setup(t, 5000) + defer cancel() + + z.GoTo("/register/", `[data-testid="register-index-page"]`) + z.TypeIn(`#username`, `testerzed`) + z.TypeIn(`#email`, `zed@test.com`) + z.TypeIn(`#password`, `iamdumbass`) + z.ClickOn(`#register-submit`) + z.WaitFor(`[data-testid="login-index-page"]`) + + z.GoTo("/login/", `[data-testid="login-index-page"]`) + z.TypeIn(`#username`, `testerzed`) + z.TypeIn(`#password`, `iamdumbass`) + z.ClickOn(`#login-submit`) + z.WaitFor(`[data-testid="index-page"]`) + + /// delete the user here + deleteTestUser("testerzed") +} + +func TestMain(m *testing.M) { + data.Setup("sqlite3", "./db.sqlite3") + + m.Run() + + data.Shutdown() +} diff --git a/tests/fakepay/example_test.go b/tests/fakepay/example_test.go new file mode 100644 index 0000000..7c70add --- /dev/null +++ b/tests/fakepay/example_test.go @@ -0,0 +1,16 @@ +package tests + +import ( + "testing" + assert "github.com/stretchr/testify/require" + "os" +) + +func TestLogin(t *testing.T) { + assert.Equal(t, true, true) +} + +func TestMain(m *testing.M) { + code := m.Run() + os.Exit(code) +} diff --git a/tests/main.go b/tests/main.go new file mode 100644 index 0000000..d3aa15f --- /dev/null +++ b/tests/main.go @@ -0,0 +1,16 @@ +package tests + +import ( + "testing" + // "github.com/stretchr/testify/require" + "MY/webapp/data" + "os" +) + +func TestMain(m *testing.M) { + data.Setup("sqlite3", "./db.sqlite3") + defer data.Shutdown() + + code := m.Run() + os.Exit(code) +} diff --git a/tests/paypal/example_test.go b/tests/paypal/example_test.go new file mode 100644 index 0000000..7c70add --- /dev/null +++ b/tests/paypal/example_test.go @@ -0,0 +1,16 @@ +package tests + +import ( + "testing" + assert "github.com/stretchr/testify/require" + "os" +) + +func TestLogin(t *testing.T) { + assert.Equal(t, true, true) +} + +func TestMain(m *testing.M) { + code := m.Run() + os.Exit(code) +} diff --git a/tests/shopping/example_test.go b/tests/shopping/example_test.go new file mode 100644 index 0000000..7c70add --- /dev/null +++ b/tests/shopping/example_test.go @@ -0,0 +1,16 @@ +package tests + +import ( + "testing" + assert "github.com/stretchr/testify/require" + "os" +) + +func TestLogin(t *testing.T) { + assert.Equal(t, true, true) +} + +func TestMain(m *testing.M) { + code := m.Run() + os.Exit(code) +} diff --git a/tests/survey/example_test.go b/tests/survey/example_test.go new file mode 100644 index 0000000..44130d7 --- /dev/null +++ b/tests/survey/example_test.go @@ -0,0 +1,16 @@ +package tests + +import ( + "testing" + assert "github.com/stretchr/testify/require" + "os" +) + +func TestLogin(t *testing.T) { + assert.Equal(t, true, false) +} + +func TestMain(m *testing.M) { + code := m.Run() + os.Exit(code) +} diff --git a/tests/tools/helpers.go b/tests/tools/helpers.go new file mode 100644 index 0000000..148809e --- /dev/null +++ b/tests/tools/helpers.go @@ -0,0 +1,84 @@ +package tests + +import ( + "testing" + "context" + "fmt" + "log" + "time" + "runtime" + "github.com/stretchr/testify/require" + browser "github.com/chromedp/chromedp" + "MY/webapp/config" +) + +func init() { + config.Load("config.json") +} + +type ZedBrowser struct { + ctx context.Context + require *require.Assertions +} + +func (z *ZedBrowser) ClickOn(id string) { + err := browser.Run(z.ctx, browser.WaitVisible(id),) + z.require.NoError(err) + + resp, err := browser.RunResponse(z.ctx, + browser.WaitVisible(id), + browser.Click(id)) + + z.require.NoError(err) + z.require.Equal(int64(200), resp.Status) +} + +func (z *ZedBrowser) GoTo(path string, expect string) { + url := fmt.Sprintf(`http://%s%s`, config.Settings.Server.HostPort, path) + + fmt.Println("URL: ", url) + + err := browser.Run(z.ctx, + browser.Navigate(url), + browser.WaitVisible(`body > footer`), + browser.WaitVisible(expect)) + z.require.NoError(err) +} + +func (z *ZedBrowser) WaitFor(expect string) { + err := browser.Run(z.ctx, browser.WaitVisible(expect)) + z.require.NoError(err) +} + +func (z *ZedBrowser) ExpectText(target string, expect string) { + var extracted string + err := browser.Run(z.ctx, browser.Text(target, &extracted)) + z.require.NoError(err) + z.require.Equal(expect, extracted) +} + +func (z *ZedBrowser) Run(actions ...browser.Action) { + err := browser.Run(z.ctx, actions...) + z.require.NoError(err) +} + +func (z *ZedBrowser) TypeIn(id string, text string) { + z.WaitFor(id) + err := browser.Run(z.ctx, browser.SendKeys(id, text)) + z.require.NoError(err) +} + +func Setup(t *testing.T, timeout time.Duration) (*ZedBrowser, context.CancelFunc) { + opts := append(browser.DefaultExecAllocatorOptions[:], + browser.Flag("headless", runtime.GOOS == "windows"),) + + ctx, cancel := browser.NewExecAllocator(context.Background(), opts...) + + ctx, _ = browser.NewContext(ctx, browser.WithLogf(log.Printf)) + + ctx, _ = context.WithTimeout(ctx, timeout * time.Second) + + req := require.New(t) + + return &ZedBrowser{ctx, req}, cancel +} diff --git a/tools/cmd/fgen/main.go b/tools/cmd/fgen/main.go new file mode 100644 index 0000000..483f603 --- /dev/null +++ b/tools/cmd/fgen/main.go @@ -0,0 +1,87 @@ +package main + +import ( + "embed" + "fmt" + "io/fs" + "flag" + "path/filepath" + "text/template" + "strings" + "os" +) + +//go:embed templates +var templates embed.FS + +type Config struct { + Name string +} + +func WriteTemplate(config Config, from string, to string) error { + fmt.Println("CREATE", to) + source, err := templates.ReadFile(from) + if err != nil { return err } + + t := template.Must(template.New(from).Parse(string(source))) + + out, err := os.Create(to) + if err != nil { return err } + + err = t.Execute(out, config) + if err != nil { panic(err) } + + return nil +} + +func main() { + var config Config + + flag.StringVar(&config.Name, "name", "", "name of the feature to generate") + flag.Parse() + + if config.Name == "" { + fmt.Println("USAGE: fgen -name name") + return + } + + feature_dir := filepath.Join("features", config.Name) + view_dir := filepath.Join("views", config.Name) + tests_dir := filepath.Join("tests", config.Name) + + err := os.MkdirAll(feature_dir, 0755) + if err != nil { panic(err) } + + err = os.MkdirAll(view_dir, 0755) + if err != nil { panic(err) } + + err = os.MkdirAll(tests_dir, 0755) + if err != nil { panic(err) } + + err = fs.WalkDir(templates, "templates", + func(path string, d fs.DirEntry, err error) error { + if err != nil { return err } + target := filepath.Base(path) + + if !d.IsDir() { + switch { + case strings.HasPrefix(path, "templates/views"): + out_path := filepath.Join("views", config.Name, target) + err := WriteTemplate(config, path, out_path) + if err != nil { panic(err) } + case strings.HasPrefix(path, "templates/feature"): + out_path := filepath.Join("features", config.Name, target) + err := WriteTemplate(config, path, out_path) + if err != nil { panic(err) } + case strings.HasPrefix(path, "templates/tests"): + out_path := filepath.Join("tests", config.Name, target) + err := WriteTemplate(config, path, out_path) + if err != nil { panic(err) } + } + } + + return nil + }) + + if err != nil { panic(err) } +} diff --git a/tools/cmd/fgen/templates/feature/api.go b/tools/cmd/fgen/templates/feature/api.go new file mode 100644 index 0000000..040ed75 --- /dev/null +++ b/tools/cmd/fgen/templates/feature/api.go @@ -0,0 +1,15 @@ +package features_{{ .Name }} + +import ( + "github.com/gofiber/fiber/v2" +) + +func GetApiExample(c *fiber.Ctx) error { + tables := []string{"test", "that"} + + return c.JSON(tables) +} + +func SetupApi(app *fiber.App) { + app.Get("/api/{{ .Name }}/example", GetApiExample) +} diff --git a/tools/cmd/fgen/templates/feature/init.go b/tools/cmd/fgen/templates/feature/init.go new file mode 100644 index 0000000..b76fcd6 --- /dev/null +++ b/tools/cmd/fgen/templates/feature/init.go @@ -0,0 +1,10 @@ +package features_{{ .Name }} + +import ( + "github.com/gofiber/fiber/v2" +) + +func Setup(app *fiber.App) { + SetupApi(app) + SetupViews(app) +} diff --git a/tools/cmd/fgen/templates/feature/views.go b/tools/cmd/fgen/templates/feature/views.go new file mode 100644 index 0000000..013267b --- /dev/null +++ b/tools/cmd/fgen/templates/feature/views.go @@ -0,0 +1,11 @@ +package features_{{ .Name }} + +import ( + "github.com/gofiber/fiber/v2" + . "MY/webapp/common" +) + +func SetupViews(app *fiber.App) { + err := ConfigViews(app, "views/{{ .Name }}") + if err != nil { panic(err) } +} diff --git a/tools/cmd/fgen/templates/tests/example_test.go b/tools/cmd/fgen/templates/tests/example_test.go new file mode 100644 index 0000000..44130d7 --- /dev/null +++ b/tools/cmd/fgen/templates/tests/example_test.go @@ -0,0 +1,16 @@ +package tests + +import ( + "testing" + assert "github.com/stretchr/testify/require" + "os" +) + +func TestLogin(t *testing.T) { + assert.Equal(t, true, false) +} + +func TestMain(m *testing.M) { + code := m.Run() + os.Exit(code) +} diff --git a/tools/cmd/fgen/templates/views/index.html b/tools/cmd/fgen/templates/views/index.html new file mode 100644 index 0000000..874e5c9 --- /dev/null +++ b/tools/cmd/fgen/templates/views/index.html @@ -0,0 +1,3 @@ +

{{ .Name }}

+ +

Replace me.

diff --git a/tools/cmd/mailer/main.go b/tools/cmd/mailer/main.go new file mode 100644 index 0000000..e3d1e8c --- /dev/null +++ b/tools/cmd/mailer/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + "MY/webapp/config" + email "MY/webapp/common/email" +) + +func EmailReceiver(router *email.Router) { + for { + err := router.HandleEmailRequest() + fmt.Println("EMAIL ROUTED!") + + if err != nil { + fmt.Println(err) + } + } +} + +func main() { + config.Load("config.json") + + ctx := context.Background() + + router, err := email.NewRouter(ctx) + if err != nil { panic(err) } + defer router.Close() + + go EmailReceiver(&router) + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + + _ = <-c + fmt.Println("Shutdown now...") +} + diff --git a/tools/cmd/qmgr/main.go b/tools/cmd/qmgr/main.go new file mode 100644 index 0000000..893bfce --- /dev/null +++ b/tools/cmd/qmgr/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "MY/webapp/config" + email "MY/webapp/common/email" + "context" + "fmt" +) + +type Person struct { + Name string + Pet string +} + +func main() { + config.Load("config.json") + + ctx := context.Background() + + msg := email.EmailMessage{ + To: "tina.recip@example.com", + From: "toni.sender@example.com", + Subject: "This is my first mail.", + Template: "signup.md", + Data: Person{ + Name: "Zed", + Pet: "None", + }, + } + + fmt.Println("sending", msg) + + sender := email.NewSender(ctx) + defer sender.Close() + + err := sender.QueueEmail(msg) + if err != nil { panic(err) } +} diff --git a/tools/pragmas.sql b/tools/pragmas.sql new file mode 100644 index 0000000..17cfaf0 --- /dev/null +++ b/tools/pragmas.sql @@ -0,0 +1,6 @@ +PRAGMA foreign_keys = ON; +PRAGMA journal_mode = WAL; +PRAGMA synchronous = NORMAL; +PRAGMA mmap_size = 134217728; -- 128 megabytes +PRAGMA journal_size_limig = 67108864; -- 64 megabytes +PRAGMA cache_size = 2000; diff --git a/tools/restart.ps1 b/tools/restart.ps1 new file mode 100644 index 0000000..9da1d6c --- /dev/null +++ b/tools/restart.ps1 @@ -0,0 +1 @@ +curl http://127.0.0.1:9999/webapp *> $null diff --git a/views/admin/index.html b/views/admin/index.html new file mode 100644 index 0000000..17fe39a --- /dev/null +++ b/views/admin/index.html @@ -0,0 +1,8 @@ +

Admin

+ +

You have to be logged in:

+ +
    +
  1. Admin the Database
  2. +
  3. Your Admin Here
  4. +
diff --git a/views/admin/table/contents.html b/views/admin/table/contents.html new file mode 100644 index 0000000..6ba3ba2 --- /dev/null +++ b/views/admin/table/contents.html @@ -0,0 +1,48 @@ + + +

« Admin {{ .table }}

+ + + + + + + + + +
+ + + {{ range $header := .headers }} + + {{ end }} + + + + +
{{ $header }}
+ + + diff --git a/views/admin/table/index.html b/views/admin/table/index.html new file mode 100644 index 0000000..02f04a2 --- /dev/null +++ b/views/admin/table/index.html @@ -0,0 +1,29 @@ + + +
+

Admin Rows

+ + +
    + +
+
+
diff --git a/views/admin/table/new.html b/views/admin/table/new.html new file mode 100644 index 0000000..a121554 --- /dev/null +++ b/views/admin/table/new.html @@ -0,0 +1,52 @@ + + +

«Admin {{ .table }}

+ + +
+ + +
+ +

New {{ .table }}

+ + + + + + + + + + +
+
+
diff --git a/views/admin/table/view.html b/views/admin/table/view.html new file mode 100644 index 0000000..4742d5c --- /dev/null +++ b/views/admin/table/view.html @@ -0,0 +1,50 @@ + + +

«Admin {{ .table }}

+ +
+ + + +
+ +

{{ .table }} : {{ .id }}

+ + + + + + + + +
+
+
diff --git a/views/email/index.html b/views/email/index.html new file mode 100644 index 0000000..8712fd2 --- /dev/null +++ b/views/email/index.html @@ -0,0 +1,21 @@ +

Send An Email

+ + +
+ + + + + + + + + + + + + + + + +
diff --git a/views/error.html b/views/error.html new file mode 100644 index 0000000..ba21ac7 --- /dev/null +++ b/views/error.html @@ -0,0 +1,7 @@ +

Error

+ +

There has been an error. Please contact the site administrator.

+ + diff --git a/views/fakepay/complete.html b/views/fakepay/complete.html new file mode 100644 index 0000000..9a7da7f --- /dev/null +++ b/views/fakepay/complete.html @@ -0,0 +1,6 @@ +

Thank You!

+ +

Your payment has been accepted and you should receive an email with your receipt.

+ +

Log In To Your Account

+ diff --git a/views/fakepay/index.html b/views/fakepay/index.html new file mode 100644 index 0000000..c1bde3d --- /dev/null +++ b/views/fakepay/index.html @@ -0,0 +1,29 @@ + + + +

FakePay

+
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+
diff --git a/views/layouts/main.html b/views/layouts/main.html new file mode 100644 index 0000000..a2df154 --- /dev/null +++ b/views/layouts/main.html @@ -0,0 +1,84 @@ + + + + + + + + + + + + + Go Web Dev Starter Kit + + + +
+ +
+ +
+ + {{embed}} + +
+ + + + diff --git a/views/paypal/index.html b/views/paypal/index.html new file mode 100644 index 0000000..91fef5f --- /dev/null +++ b/views/paypal/index.html @@ -0,0 +1,21 @@ +

Pay with Paypal

+ + +

Form goes here:

+ +
+ +

+ + + + + + + diff --git a/views/shopping/checkout.html b/views/shopping/checkout.html new file mode 100644 index 0000000..ece8913 --- /dev/null +++ b/views/shopping/checkout.html @@ -0,0 +1,66 @@ + + + + +

Checkout

+ + + + + + + + + + + +
Subtotal:$100.00
Total:
+ + + + + diff --git a/views/shopping/index.html b/views/shopping/index.html new file mode 100644 index 0000000..2c7b17e --- /dev/null +++ b/views/shopping/index.html @@ -0,0 +1,102 @@ + + + + +

Products

+ + + + + + + +
+ diff --git a/views/survey/finalize.html b/views/survey/finalize.html new file mode 100644 index 0000000..6d5474d --- /dev/null +++ b/views/survey/finalize.html @@ -0,0 +1,7 @@ +

Thank You!

+ +

Solarpunk moka pot ceramics jean shorts. Cold-pressed fashion axe normcore four tet bandcamp ascot dad shoes bitters try-hard. Brooklyn slugging marxism XOXO gorpcore granny square humblebrag live-edge, fitzcarraldo mercury retrograde sound bath kickstarter van life freegan. Tilde tacos mlkshk bell hooks. Selvage deep v jawn, akerman breathwork direct trade etsy blackbird spyplane danish modern woke.

+ +

+View More Surveys +

diff --git a/views/survey/index.html b/views/survey/index.html new file mode 100644 index 0000000..fa3fa24 --- /dev/null +++ b/views/survey/index.html @@ -0,0 +1,30 @@ +

Sample Survey

+ +

Solarpunk moka pot ceramics jean shorts. Cold-pressed fashion axe normcore four tet bandcamp ascot dad shoes bitters try-hard. Brooklyn slugging marxism XOXO gorpcore granny square humblebrag live-edge, fitzcarraldo mercury retrograde sound bath kickstarter van life freegan. Tilde tacos mlkshk bell hooks. Selvage deep v jawn, akerman breathwork direct trade etsy blackbird spyplane danish modern woke.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/views/survey/results.html b/views/survey/results.html new file mode 100644 index 0000000..38ed0d6 --- /dev/null +++ b/views/survey/results.html @@ -0,0 +1,33 @@ +

Results of Survey "Sample Finished Survey"

+ + +

Street art kettlebell burrata offal portra decolonize are.na akerman shabby chic blue bottle post-ironic breathwork. Roof party natural wine bell hooks cold plunge metrograph granny square ugh dad shoes garum before they sold out zines tahini side hustle. Indigo dye pork belly amaro, post-ironic health goth candle making van life hairpin robert walser.

+ + 01/20/23 Finished + Respondents: 200 + +
+ +

Questions

+ + + + 50% + + + 50% + + + 50% + + + 50% + + + 50% + + + 50% + + +View More Surveys diff --git a/views/survey/submit.html b/views/survey/submit.html new file mode 100644 index 0000000..48e5ebe --- /dev/null +++ b/views/survey/submit.html @@ -0,0 +1,28 @@ +

Verify Your Answers

+ +

Please verify your answers are what you would like to say on this survey.

+ + + + YES + + + YES + + + YES + + + NO + + + YES + + + YES + + + + + +