├── .formatter.exs
├── .github
├── CODEOWNERS
├── dependabot.yml
└── workflows
│ ├── ci.yml
│ ├── v3.yml
│ └── v4.yml
├── .gitignore
├── .tool-versions
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── UPGRADING.md
├── assets
├── .nvmrc
├── css
│ ├── base.sass
│ ├── base
│ │ ├── components
│ │ │ ├── _account-info.sass
│ │ │ ├── _nav.sass
│ │ │ └── _table.sass
│ │ ├── globals
│ │ │ └── _global.sass
│ │ └── settings
│ │ │ └── _grid.sass
│ ├── shared
│ │ ├── bourbon
│ │ │ ├── _bourbon.scss
│ │ │ ├── helpers
│ │ │ │ ├── _buttons-list.scss
│ │ │ │ ├── _scales.scss
│ │ │ │ └── _text-inputs-list.scss
│ │ │ ├── library
│ │ │ │ ├── _border-color.scss
│ │ │ │ ├── _border-radius.scss
│ │ │ │ ├── _border-style.scss
│ │ │ │ ├── _border-width.scss
│ │ │ │ ├── _buttons.scss
│ │ │ │ ├── _clearfix.scss
│ │ │ │ ├── _contrast-switch.scss
│ │ │ │ ├── _ellipsis.scss
│ │ │ │ ├── _font-face.scss
│ │ │ │ ├── _font-stacks.scss
│ │ │ │ ├── _hide-text.scss
│ │ │ │ ├── _hide-visually.scss
│ │ │ │ ├── _margin.scss
│ │ │ │ ├── _modular-scale.scss
│ │ │ │ ├── _overflow-wrap.scss
│ │ │ │ ├── _padding.scss
│ │ │ │ ├── _position.scss
│ │ │ │ ├── _prefixer.scss
│ │ │ │ ├── _shade.scss
│ │ │ │ ├── _size.scss
│ │ │ │ ├── _strip-unit.scss
│ │ │ │ ├── _text-inputs.scss
│ │ │ │ ├── _timing-functions.scss
│ │ │ │ ├── _tint.scss
│ │ │ │ ├── _triangle.scss
│ │ │ │ └── _value-prefixer.scss
│ │ │ ├── settings
│ │ │ │ └── _settings.scss
│ │ │ ├── utilities
│ │ │ │ ├── _assign-inputs.scss
│ │ │ │ ├── _compact-shorthand.scss
│ │ │ │ ├── _contrast-ratio.scss
│ │ │ │ ├── _directional-property.scss
│ │ │ │ ├── _fetch-bourbon-setting.scss
│ │ │ │ ├── _font-source-declaration.scss
│ │ │ │ ├── _gamma.scss
│ │ │ │ ├── _lightness.scss
│ │ │ │ └── _unpack-shorthand.scss
│ │ │ └── validators
│ │ │ │ ├── _contains-falsy.scss
│ │ │ │ ├── _contains.scss
│ │ │ │ ├── _is-color.scss
│ │ │ │ ├── _is-length.scss
│ │ │ │ ├── _is-number.scss
│ │ │ │ └── _is-size.scss
│ │ ├── flex-grid
│ │ │ ├── README.md
│ │ │ ├── _fg_breakpoint.scss
│ │ │ ├── _fg_grid.scss
│ │ │ └── _flex-grid.sass
│ │ ├── reset
│ │ │ └── _reset.scss
│ │ └── settings
│ │ │ ├── _colors.sass
│ │ │ └── _fonts.sass
│ ├── theme.sass
│ └── theme
│ │ ├── _extends
│ │ ├── _buttons.sass
│ │ ├── _label.sass
│ │ ├── _select-input.sass
│ │ ├── _text-input.sass
│ │ └── _typography.sass
│ │ ├── components
│ │ ├── _account-info.sass
│ │ ├── _datepicker.sass
│ │ ├── _filters.sass
│ │ ├── _flash-messages.sass
│ │ ├── _form.sass
│ │ ├── _header-and-content.sass
│ │ ├── _nav.sass
│ │ ├── _pagination.sass
│ │ ├── _panel.sass
│ │ ├── _table.sass
│ │ └── _toolbar.sass
│ │ ├── globals
│ │ └── _global.sass
│ │ ├── pages
│ │ ├── _edit.sass
│ │ ├── _index.sass
│ │ ├── _new.sass
│ │ └── _show.sass
│ │ └── settings
│ │ └── _grid.sass
├── images
│ ├── down-arrow.png
│ └── torch-logo.png
├── js
│ └── torch.js
├── package-lock.json
├── package.json
└── static
│ └── images
│ ├── down-arrow.png
│ └── torch-logo.png
├── bin
├── coverage
├── release
├── setup
└── test
├── config
├── .credo.exs
└── config.exs
├── coveralls.json
├── lib
├── gettext.ex
├── mix
│ ├── tasks
│ │ ├── torch.gen.html.ex
│ │ ├── torch.install.ex
│ │ └── torch.uninstall.ex
│ └── torch.ex
├── torch.ex
└── torch
│ ├── component.ex
│ ├── config.ex
│ ├── helpers.ex
│ ├── i18n.ex
│ ├── i18n
│ └── backend.ex
│ ├── pagination.ex
│ └── views
│ ├── filter_view.ex
│ ├── flash_view.ex
│ ├── page_view.ex
│ ├── pagination_view.ex
│ └── table_view.ex
├── mix.exs
├── mix.lock
├── priv
├── gettext
│ ├── de
│ │ └── LC_MESSAGES
│ │ │ └── default.po
│ ├── default.pot
│ ├── en
│ │ └── LC_MESSAGES
│ │ │ └── default.po
│ ├── es
│ │ └── LC_MESSAGES
│ │ │ └── default.po
│ ├── ja
│ │ └── LC_MESSAGES
│ │ │ └── default.po
│ ├── pt_BR
│ │ └── LC_MESSAGES
│ │ │ └── default.po
│ ├── ru
│ │ └── LC_MESSAGES
│ │ │ └── default.po
│ └── vi
│ │ └── LC_MESSAGES
│ │ └── default.po
├── static
│ ├── base.css
│ ├── base.css.map
│ ├── down-arrow.e17911d3.png
│ ├── theme.css
│ ├── theme.css.map
│ ├── torch-logo.a963df87.png
│ ├── torch.js
│ ├── torch.js.LICENSE.txt
│ └── torch.js.map
└── templates
│ ├── phx.gen.context
│ ├── _grid.sass
│ ├── access_no_schema.ex
│ ├── context.ex
│ ├── context_test.exs
│ ├── schema_access.ex
│ └── test_cases.exs
│ ├── phx.gen.html
│ ├── controller.ex
│ ├── controller_test.exs
│ ├── edit.html.heex
│ ├── edit_1_7_0.html.heex
│ ├── html.ex
│ ├── index.html.heex
│ ├── new.html.heex
│ ├── new_1_7_0.html.heex
│ ├── resource_form.html.heex
│ └── show.html.heex
│ └── torch.install
│ └── layout.html.heex
└── test
├── mix
├── tasks
│ ├── torch.gen.html_test.exs
│ ├── torch.install_test.exs
│ └── torch.uninstall_test.exs
└── test_helper.exs
├── support
├── apps
│ └── phx1_7
│ │ ├── .formatter.exs
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── assets
│ │ ├── css
│ │ │ └── app.css
│ │ ├── js
│ │ │ └── app.js
│ │ ├── tailwind.config.js
│ │ └── vendor
│ │ │ └── topbar.js
│ │ ├── bin
│ │ └── test
│ │ ├── config
│ │ ├── config.exs
│ │ ├── dev.exs
│ │ ├── prod.exs
│ │ ├── runtime.exs
│ │ └── test.exs
│ │ ├── lib
│ │ ├── phx1_7.ex
│ │ ├── phx1_7
│ │ │ ├── application.ex
│ │ │ ├── mailer.ex
│ │ │ └── repo.ex
│ │ ├── phx1_7_web.ex
│ │ └── phx1_7_web
│ │ │ ├── components
│ │ │ ├── core_components.ex
│ │ │ ├── layouts.ex
│ │ │ └── layouts
│ │ │ │ ├── app.html.heex
│ │ │ │ └── root.html.heex
│ │ │ ├── controllers
│ │ │ ├── error_html.ex
│ │ │ ├── error_json.ex
│ │ │ ├── page_controller.ex
│ │ │ ├── page_html.ex
│ │ │ └── page_html
│ │ │ │ └── home.html.heex
│ │ │ ├── endpoint.ex
│ │ │ ├── gettext.ex
│ │ │ ├── router.ex
│ │ │ ├── router.ex.orig
│ │ │ └── telemetry.ex
│ │ ├── mix.exs
│ │ ├── mix.lock
│ │ ├── priv
│ │ ├── gettext
│ │ │ ├── en
│ │ │ │ └── LC_MESSAGES
│ │ │ │ │ └── errors.po
│ │ │ └── errors.pot
│ │ ├── repo
│ │ │ ├── migrations
│ │ │ │ └── .formatter.exs
│ │ │ └── seeds.exs
│ │ └── static
│ │ │ ├── favicon.ico
│ │ │ └── robots.txt
│ │ └── test
│ │ ├── phx1_7_web
│ │ └── controllers
│ │ │ ├── error_html_test.exs
│ │ │ ├── error_json_test.exs
│ │ │ └── page_controller_test.exs
│ │ ├── support
│ │ ├── conn_case.ex
│ │ └── data_case.ex
│ │ └── test_helper.exs
├── cases
│ └── mix_case.ex
└── patches
│ ├── install-route.diff
│ └── install-torch.diff
└── torch
├── helpers_test.exs
├── i18n_test.exs
├── pagination_test.exs
├── test_helper.exs
├── torch_test.exs
└── views
├── filter_view_test.exs
├── flash_view_test.exs
├── page_view_test.exs
├── pagination_view_test.exs
└── table_view_test.exs
/.formatter.exs:
--------------------------------------------------------------------------------
1 | # Used by "mix format"
2 | [
3 | inputs: ["mix.exs", "{config,lib}/**/*.{ex,exs}", "test/{mix,torch}/**/*.{ex,exs}"],
4 | locals_without_parens: [
5 | # Phoenix
6 | plug: 2,
7 | plug: 1,
8 | pipe_through: 1,
9 | get: 3,
10 | post: 3,
11 | patch: 3,
12 | put: 3,
13 | forward: 3
14 | ]
15 | ]
16 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | @cpjolicoeur
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: mix
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | open-pull-requests-limit: 10
8 | reviewers:
9 | - cpjolicoeur
10 | ignore:
11 | - dependency-name: phoenix
12 | versions:
13 | - ">= 1.4.a, < 1.5"
14 | - dependency-name: phoenix_html
15 | versions:
16 | - ">= 2.14.a, < 2.15"
17 | - dependency-name: timex
18 | versions:
19 | - 3.6.4
20 | - 3.7.3
21 | - package-ecosystem: npm
22 | directory: "/assets"
23 | schedule:
24 | interval: weekly
25 | - package-ecosystem: "github-actions"
26 | directory: "/"
27 | schedule:
28 | interval: "weekly"
29 |
--------------------------------------------------------------------------------
/.github/workflows/v3.yml:
--------------------------------------------------------------------------------
1 | name: Torch v3 CI
2 |
3 | on:
4 | pull_request:
5 | branches: [v1, v2, v3]
6 | types: [opened, edited, reopened, synchronize]
7 | push:
8 | branches: [v3]
9 | tags:
10 | - v[1-3].[0-9]+.[0-9]+
11 |
12 | jobs:
13 | mix_test:
14 | name: mix test (Elixir ${{matrix.elixir}} | OTP ${{matrix.otp}})
15 | runs-on: ubuntu-latest
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | include:
21 | - elixir: 1.10.x
22 | otp: 21.3.8.21
23 | - elixir: 1.10.x
24 | otp: 22.3.4.16
25 | - elixir: 1.10.x
26 | otp: 23.2.7
27 | warnings_as_errors: true
28 | static_analysis: false
29 | - elixir: 1.11.x
30 | otp: 21.3.8.21
31 | - elixir: 1.11.x
32 | otp: 22.3.4.16
33 | - elixir: 1.11.x
34 | otp: 23.2.7
35 | warnings_as_errors: true
36 | static_analysis: false
37 | - elixir: 1.12.x
38 | otp: 22.x
39 | - elixir: 1.12.x
40 | otp: 23.x
41 | - elixir: 1.12.x
42 | otp: 24.x
43 |
44 | services:
45 | db:
46 | image: postgres:10.1-alpine
47 | env:
48 | POSTGRES_USER: postgres
49 | POSTGRES_DB: example_test
50 | POSTGRES_PASSWORD: ""
51 | ports: ["5432:5432"]
52 | options: >-
53 | --health-cmd pg_isready
54 | --health-interval 10s
55 | --health-timeout 5s
56 | --health-retries 5
57 |
58 | env:
59 | MIX_ENV: test
60 | DATABASE_POSTGRESQL_USERNAME: postgres
61 | PGHOST: postgres
62 | PGUSER: postgres
63 |
64 | steps:
65 | - uses: actions/checkout@v4
66 | - uses: actions/setup-node@v4
67 | with:
68 | node-version: '14'
69 | cache: 'npm'
70 | cache-dependency-path: assets/package-lock.json
71 | - uses: erlef/setup-elixir@v1
72 | with:
73 | otp-version: ${{matrix.otp}}
74 | elixir-version: ${{matrix.elixir}}
75 | - name: Get Deps cache
76 | uses: actions/cache@v4
77 | with:
78 | path: deps/
79 | key: deps-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
80 | - name: Get BUILD cache
81 | uses: actions/cache@v4
82 | with:
83 | path: _build/test/
84 | key: build-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
85 | - name: Cache build artifacts
86 | uses: actions/cache@v4
87 | with:
88 | path: |
89 | $HOME/.hex
90 | $HOME/.mix
91 | key: artifacts-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
92 | - name: Install Deps
93 | run: |
94 | mix local.hex --force
95 | mix local.rebar --force
96 | mix deps.get --only test
97 | - run: mix compile --warnings-as-errors
98 | if: matrix.warnings_as_errors
99 | - name: Run tests
100 | run: bin/setup
101 | - name: coveralls
102 | run: mix coveralls.github
103 | env:
104 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105 | - run: mix dialyzer --halt-exist-status
106 | if: matrix.static_analysis
107 |
--------------------------------------------------------------------------------
/.github/workflows/v4.yml:
--------------------------------------------------------------------------------
1 | name: Torch v4 CI
2 |
3 | on:
4 | pull_request:
5 | branches: [v4]
6 | types: [opened, edited, reopened, synchronize]
7 | push:
8 | branches: [v4]
9 | tags:
10 | - v4.[0-9]+.[0-9]+
11 |
12 | jobs:
13 | mix_test:
14 | name: mix test (Elixir ${{matrix.elixir}} | OTP ${{matrix.otp}})
15 | runs-on: ubuntu-22.04
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | include:
21 | - elixir: 1.12.x
22 | otp: 22.x
23 | - elixir: 1.13.x
24 | otp: 22.x
25 | - elixir: 1.12.x
26 | otp: 23.x
27 | - elixir: 1.13.x
28 | otp: 23.x
29 | - elixir: 1.12.x
30 | otp: 24.x
31 | - elixir: 1.13.x
32 | otp: 24.x
33 | - elixir: 1.14.x
34 | otp: 23.x
35 | - elixir: 1.14.x
36 | otp: 24.x
37 | - elixir: 1.14.x
38 | otp: 25.x
39 |
40 | services:
41 | db:
42 | image: postgres:latest
43 | env:
44 | POSTGRES_DB: example_test
45 | POSTGRES_USER: postgres
46 | POSTGRES_PASSWORD: postgres
47 | ports: ["5432:5432"]
48 | options: >-
49 | --health-cmd pg_isready
50 | --health-interval 10s
51 | --health-timeout 5s
52 | --health-retries 5
53 |
54 | env:
55 | MIX_ENV: test
56 | DATABASE_POSTGRESQL_USERNAME: postgres
57 | DATABASE_POSTGRESQL_PASSWORD: postgres
58 | PGHOST: postgres
59 | PGUSER: postgres
60 | ImageOS: ubuntu22 # run on ubuntu-22.04 (which supports Erlang/OTP 24.2-27)
61 |
62 | steps:
63 | - uses: actions/checkout@v4
64 | - uses: actions/setup-node@v4
65 | with:
66 | node-version: "14"
67 | cache: "npm"
68 | cache-dependency-path: assets/package-lock.json
69 | - uses: erlef/setup-beam@v1
70 | with:
71 | otp-version: ${{matrix.otp}}
72 | elixir-version: ${{matrix.elixir}}
73 | - name: Get Deps cache
74 | uses: actions/cache@v4
75 | with:
76 | path: deps/
77 | key: deps-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
78 | - name: Get BUILD cache
79 | uses: actions/cache@v4
80 | with:
81 | path: _build/test/
82 | key: build-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
83 | - name: Cache build artifacts
84 | uses: actions/cache@v4
85 | with:
86 | path: |
87 | $HOME/.hex
88 | $HOME/.mix
89 | key: artifacts-${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('**/mix.lock') }}
90 | - name: Install Deps
91 | run: |
92 | mix local.hex --force
93 | mix local.rebar --force
94 | mix deps.get --only test
95 | - run: mix compile --warnings-as-errors
96 | if: matrix.warnings_as_errors
97 | - name: Run tests
98 | run: bin/setup
99 | - name: coveralls
100 | run: mix coveralls.github
101 | env:
102 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
103 | - run: mix dialyzer --halt-exist-status
104 | if: matrix.static_analysis
105 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where 3rd-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Ignore package tarball (built via "mix hex.build").
23 | torch-*.tar
24 |
25 | .elixir_ls/*
26 | node_modules/
27 | .DS_Store
28 | assets/.parcel-cache
29 |
30 | .dir-locals.el
31 | .env
32 |
33 | # Translation .mo files
34 | /priv/gettext/*/LC_MESSAGES/*.mo
35 |
36 | shell.nix
37 |
38 | test/support/apps/phx1_3
39 | test/support/apps/phx1_4
40 | test/support/apps/phx1_5
41 | test/support/apps/phx1_6*
42 | test/support/apps/phx1_7_torch_v4
43 |
--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | elixir 1.16.3-otp-26
2 | erlang 26.2.5
3 | nodejs lts-hydrogen
4 | python 2.7.18
5 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at craig@mojotech.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Original work Copyright (c) 2016 Infinite Red, Inc.
4 | Modifed work Copyright (c) 2019 MojoTech, LLC.
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/UPGRADING.md:
--------------------------------------------------------------------------------
1 | # Upgrading
2 |
3 | ### Torch v4 to Torch v5
4 |
5 | Torch v5 **IS NOT ** fully backwards compatible with Torch v4. Due to Phoenix 1.7 dropping the inclusion
6 | of `Phoenix.View` in the core SDK, the way the templates are created, and the content of the templates
7 | generated by Torch have changed significantly.
8 |
9 | There is no automatic upgrade path for existing files that were generated with previous versions of Torch.
10 | If you encounter issues using Torch v5 with existing templates, you can either continue to use Torch v4,
11 | or manually update your existing Torch templates to the new unified function component style
12 | provided by `Torch.Component`.
13 |
14 | Templates that were generated with Torch v4 _should_ still funtion, if you manaully included `:phoenix_view`
15 | in your projects mix dependencies, but your results may vary. For templates generated with Torch v4, you
16 | would also need to make the manual updates described below in the "Torch v3 to Torch v4" section.
17 |
18 | #### Slime support dropped
19 |
20 | Torch v5 has dropped support for Slime templates. Only heex templates
21 | are now supported.
22 |
23 | ### Torch v3 to Torch v4
24 |
25 | Torch v4 **IS NOT** fully backwards compatible with Torch v3. In particular, the templates have changed
26 | in a manner that affect the generated DOM and CSS rules used.
27 |
28 | To manually update your existing templates to the new v4 DOM do the following:
29 |
30 | #### show.html.*
31 |
32 | * `
` becomes ``
33 | * `` list for model properties becomes ``
34 |
35 | #### form.html.*
36 |
37 | Inside `
40 | <%= label %>
41 | <%= input %>
42 | <%= error %>
43 |
44 |
45 | becomes:
46 |
47 |
54 |
55 |
56 | Another option to "upgrade" is to just generate new templates again via the Torch v4 generators. Run the same
57 | generator commands as the first time and overwrite your existing files. Then resolve any customization previously
58 | made to your Torch v3 templates by re-applying those change to the newly generated Torch v4 templates.
59 |
--------------------------------------------------------------------------------
/assets/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/fermium
2 |
--------------------------------------------------------------------------------
/assets/css/base.sass:
--------------------------------------------------------------------------------
1 | // setup & base
2 | @import 'shared/bourbon/bourbon'
3 | @import 'shared/reset/reset'
4 | @import 'base/settings/grid'
5 | @import 'shared/flex-grid/flex-grid'
6 | @import "~pikaday/scss/pikaday.scss"
7 |
8 | // global styles
9 | @import 'shared/settings/colors'
10 | @import 'shared/settings/fonts'
11 | @import 'base/settings/grid'
12 | @import 'base/globals/global'
13 | @import 'base/components/account-info'
14 | @import 'base/components/nav'
15 |
--------------------------------------------------------------------------------
/assets/css/base/components/_account-info.sass:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/css/base/components/_account-info.sass
--------------------------------------------------------------------------------
/assets/css/base/components/_nav.sass:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/css/base/components/_nav.sass
--------------------------------------------------------------------------------
/assets/css/base/components/_table.sass:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/css/base/components/_table.sass
--------------------------------------------------------------------------------
/assets/css/base/globals/_global.sass:
--------------------------------------------------------------------------------
1 | html
2 | background: $gallery-gray
3 | font-family: $helvetica-neue
4 | font-weight: normal
5 | min-height: 100vh
6 |
7 | body
8 | min-height: 100vh
9 |
10 | a
11 | text-decoration: none
12 |
13 | .torch-container
14 | flex: 1
15 | margin: 0 auto
16 | padding-right: 15px
17 | padding-left: 15px
18 |
--------------------------------------------------------------------------------
/assets/css/base/settings/_grid.sass:
--------------------------------------------------------------------------------
1 | // default grid
2 | $fg_gutter: 36
3 | $fg_padding: 0
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/_bourbon.scss:
--------------------------------------------------------------------------------
1 | // Bourbon 5.0.0
2 | // http://bourbon.io
3 | // Copyright 2011-2018 thoughtbot, inc.
4 | // MIT License
5 |
6 | @import "helpers/buttons-list";
7 | @import "helpers/scales";
8 | @import "helpers/text-inputs-list";
9 |
10 | @import "settings/settings";
11 |
12 | @import "validators/contains";
13 | @import "validators/contains-falsy";
14 | @import "validators/is-color";
15 | @import "validators/is-length";
16 | @import "validators/is-number";
17 | @import "validators/is-size";
18 |
19 | @import "utilities/assign-inputs";
20 | @import "utilities/compact-shorthand";
21 | @import "utilities/directional-property";
22 | @import "utilities/fetch-bourbon-setting";
23 | @import "utilities/font-source-declaration";
24 | @import "utilities/gamma";
25 | @import "utilities/lightness";
26 | @import "utilities/contrast-ratio";
27 | @import "utilities/unpack-shorthand";
28 |
29 | @import "library/border-color";
30 | @import "library/border-radius";
31 | @import "library/border-style";
32 | @import "library/border-width";
33 | @import "library/buttons";
34 | @import "library/clearfix";
35 | @import "library/contrast-switch";
36 | @import "library/ellipsis";
37 | @import "library/font-face";
38 | @import "library/font-stacks";
39 | @import "library/hide-text";
40 | @import "library/hide-visually";
41 | @import "library/margin";
42 | @import "library/modular-scale";
43 | @import "library/overflow-wrap";
44 | @import "library/padding";
45 | @import "library/position";
46 | @import "library/prefixer";
47 | @import "library/shade";
48 | @import "library/size";
49 | @import "library/strip-unit";
50 | @import "library/text-inputs";
51 | @import "library/timing-functions";
52 | @import "library/tint";
53 | @import "library/triangle";
54 | @import "library/value-prefixer";
55 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/helpers/_buttons-list.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// A list of all HTML button elements.
4 | ///
5 | /// @type list
6 | ///
7 | /// @access private
8 |
9 | $_buttons-list: (
10 | "button",
11 | "[type='button']",
12 | "[type='reset']",
13 | "[type='submit']",
14 | );
15 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/helpers/_scales.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | ////
4 | /// Pre-defined scales for use with the `modular-scale` function.
5 | ///
6 | /// @type number (unitless)
7 | ///
8 | /// @see {function} modular-scale
9 | ////
10 |
11 | $minor-second: 1.067;
12 | $major-second: 1.125;
13 | $minor-third: 1.2;
14 | $major-third: 1.25;
15 | $perfect-fourth: 1.333;
16 | $augmented-fourth: 1.414;
17 | $perfect-fifth: 1.5;
18 | $minor-sixth: 1.6;
19 | $golden: 1.618;
20 | $major-sixth: 1.667;
21 | $minor-seventh: 1.778;
22 | $major-seventh: 1.875;
23 | $octave: 2;
24 | $major-tenth: 2.5;
25 | $major-eleventh: 2.667;
26 | $major-twelfth: 3;
27 | $double-octave: 4;
28 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/helpers/_text-inputs-list.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// A list of all _text-based_ HTML inputs.
4 | ///
5 | /// @type list
6 | ///
7 | /// @access private
8 |
9 | $_text-inputs-list: (
10 | "[type='color']",
11 | "[type='date']",
12 | "[type='datetime']",
13 | "[type='datetime-local']",
14 | "[type='email']",
15 | "[type='month']",
16 | "[type='number']",
17 | "[type='password']",
18 | "[type='search']",
19 | "[type='tel']",
20 | "[type='text']",
21 | "[type='time']",
22 | "[type='url']",
23 | "[type='week']",
24 | "input:not([type])",
25 | "textarea",
26 | );
27 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_border-color.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise, one-line method for setting `border-color` on specific
4 | /// edges of a box. Use a `null` value to “skip” edges of the box with standard
5 | /// CSS shorthand.
6 | ///
7 | /// @argument {list} $values
8 | /// List of colors; accepts CSS shorthand.
9 | ///
10 | /// @example scss
11 | /// .element {
12 | /// @include border-color(#a60b55 #76cd9c null #e8ae1a);
13 | /// }
14 | ///
15 | /// // CSS Output
16 | /// .element {
17 | /// border-left-color: #e8ae1a;
18 | /// border-right-color: #76cd9c;
19 | /// border-top-color: #a60b55;
20 | /// }
21 | ///
22 | /// @require {mixin} _directional-property
23 |
24 | @mixin border-color($values) {
25 | @include _directional-property(border, color, $values);
26 | }
27 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_border-radius.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise, one-line method for setting `border-radius` on both the
4 | /// top-left and top-right of a box.
5 | ///
6 | /// @argument {number (with unit)} $radii
7 | ///
8 | /// @example scss
9 | /// .element {
10 | /// @include border-top-radius(4px);
11 | /// }
12 | ///
13 | /// // CSS Output
14 | /// .element {
15 | /// border-top-left-radius: 4px;
16 | /// border-top-right-radius: 4px;
17 | /// }
18 |
19 | @mixin border-top-radius($radii) {
20 | border-top-left-radius: $radii;
21 | border-top-right-radius: $radii;
22 | }
23 |
24 | /// Provides a concise, one-line method for setting `border-radius` on both the
25 | /// top-right and bottom-right of a box.
26 | ///
27 | /// @argument {number (with unit)} $radii
28 | ///
29 | /// @example scss
30 | /// .element {
31 | /// @include border-right-radius(3px);
32 | /// }
33 | ///
34 | /// // CSS Output
35 | /// .element {
36 | /// border-bottom-right-radius: 3px;
37 | /// border-top-right-radius: 3px;
38 | /// }
39 |
40 | @mixin border-right-radius($radii) {
41 | border-bottom-right-radius: $radii;
42 | border-top-right-radius: $radii;
43 | }
44 |
45 | /// Provides a concise, one-line method for setting `border-radius` on both the
46 | /// bottom-left and bottom-right of a box.
47 | ///
48 | /// @argument {number (with unit)} $radii
49 | ///
50 | /// @example scss
51 | /// .element {
52 | /// @include border-bottom-radius(2px);
53 | /// }
54 | ///
55 | /// // CSS Output
56 | /// .element {
57 | /// border-bottom-left-radius: 2px;
58 | /// border-bottom-right-radius: 2px;
59 | /// }
60 |
61 | @mixin border-bottom-radius($radii) {
62 | border-bottom-left-radius: $radii;
63 | border-bottom-right-radius: $radii;
64 | }
65 |
66 | /// Provides a concise, one-line method for setting `border-radius` on both the
67 | /// top-left and bottom-left of a box.
68 | ///
69 | /// @argument {number (with unit)} $radii
70 | ///
71 | /// @example scss
72 | /// .element {
73 | /// @include border-left-radius(1px);
74 | /// }
75 | ///
76 | /// // CSS Output
77 | /// .element {
78 | /// border-bottom-left-radius: 1px;
79 | /// border-top-left-radius: 1px;
80 | /// }
81 |
82 | @mixin border-left-radius($radii) {
83 | border-bottom-left-radius: $radii;
84 | border-top-left-radius: $radii;
85 | }
86 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_border-style.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise, one-line method for setting `border-style` on specific
4 | /// edges of a box. Use a `null` value to “skip” edges of the box with standard
5 | /// CSS shorthand.
6 | ///
7 | /// @argument {list} $values
8 | /// List of border styles; accepts CSS shorthand.
9 | ///
10 | /// @example scss
11 | /// .element {
12 | /// @include border-style(dashed null solid);
13 | /// }
14 | ///
15 | /// // CSS Output
16 | /// .element {
17 | /// border-bottom-style: solid;
18 | /// border-top-style: dashed;
19 | /// }
20 | ///
21 | /// @require {mixin} _directional-property
22 |
23 | @mixin border-style($values) {
24 | @include _directional-property(border, style, $values);
25 | }
26 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_border-width.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise, one-line method for setting `border-width` on specific
4 | /// edges of a box. Use a `null` value to “skip” edges of the box with standard
5 | /// CSS shorthand.
6 | ///
7 | /// @argument {list} $values
8 | /// List of border widths; accepts CSS shorthand.
9 | ///
10 | /// @example scss
11 | /// .element {
12 | /// @include border-width(1em null 20px);
13 | /// }
14 | ///
15 | /// // CSS Output
16 | /// .element {
17 | /// border-bottom-width: 20px;
18 | /// border-top-width: 1em;
19 | /// }
20 | ///
21 | /// @require {mixin} _directional-property
22 |
23 | @mixin border-width($values) {
24 | @include _directional-property(border, width, $values);
25 | }
26 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_buttons.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | ////
4 | /// @type list
5 | ///
6 | /// @require {function} _assign-inputs
7 | ///
8 | /// @require {variable} $_buttons-list
9 | ////
10 |
11 | /// A list of all HTML button elements. Please note that you must interpolate
12 | /// the variable (`#{}`) to use it as a selector.
13 | ///
14 | /// @example scss
15 | /// #{$all-buttons} {
16 | /// background-color: #f00;
17 | /// }
18 | ///
19 | /// // CSS Output
20 | /// button,
21 | /// [type='button'],
22 | /// [type='reset'],
23 | /// [type='submit'] {
24 | /// background-color: #f00;
25 | /// }
26 |
27 | $all-buttons: _assign-inputs($_buttons-list);
28 |
29 | /// A list of all HTML button elements with the `:active` pseudo-class applied.
30 | /// Please note that you must interpolate the variable (`#{}`) to use it as a
31 | /// selector.
32 | ///
33 | /// @example scss
34 | /// #{$all-buttons-active} {
35 | /// background-color: #00f;
36 | /// }
37 | ///
38 | /// // CSS Output
39 | /// button:active,
40 | /// [type='button']:active,
41 | /// [type='reset']:active,
42 | /// [type='submit']:active {
43 | /// background-color: #00f;
44 | /// }
45 |
46 | $all-buttons-active: _assign-inputs($_buttons-list, active);
47 |
48 | /// A list of all HTML button elements with the `:focus` pseudo-class applied.
49 | /// Please note that you must interpolate the variable (`#{}`) to use it as a
50 | /// selector.
51 | ///
52 | /// @example scss
53 | /// #{$all-buttons-focus} {
54 | /// background-color: #0f0;
55 | /// }
56 | ///
57 | /// // CSS Output
58 | /// button:focus,
59 | /// [type='button']:focus,
60 | /// [type='reset']:focus,
61 | /// [type='submit']:focus {
62 | /// background-color: #0f0;
63 | /// }
64 |
65 | $all-buttons-focus: _assign-inputs($_buttons-list, focus);
66 |
67 | /// A list of all HTML button elements with the `:hover` pseudo-class applied.
68 | /// Please note that you must interpolate the variable (`#{}`) to use it as a
69 | /// selector.
70 | ///
71 | /// @example scss
72 | /// #{$all-buttons-hover} {
73 | /// background-color: #0f0;
74 | /// }
75 | ///
76 | /// // CSS Output
77 | /// button:hover,
78 | /// [type='button']:hover,
79 | /// [type='reset']:hover,
80 | /// [type='submit']:hover {
81 | /// background-color: #0f0;
82 | /// }
83 |
84 | $all-buttons-hover: _assign-inputs($_buttons-list, hover);
85 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_clearfix.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides an easy way to include a clearfix for containing floats.
4 | ///
5 | /// @link https://goo.gl/yP5hiZ
6 | ///
7 | /// @example scss
8 | /// .element {
9 | /// @include clearfix;
10 | /// }
11 | ///
12 | /// // CSS Output
13 | /// .element::after {
14 | /// clear: both;
15 | /// content: "";
16 | /// display: block;
17 | /// }
18 |
19 | @mixin clearfix {
20 | &::after {
21 | clear: both;
22 | content: "";
23 | display: block;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_contrast-switch.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Switches between two colors based on the contrast to another color. It’s
4 | /// like a [ternary operator] for color contrast and can be useful for building
5 | /// a button system.
6 | ///
7 | /// The calculation of the contrast ratio is based on the [WCAG 2.0
8 | /// specification]. However, we cannot guarantee full compliance, though all of
9 | /// our manual testing passed.
10 | ///
11 | /// [ternary operator]: https://goo.gl/ccfLqi
12 | /// [WCAG 2.0 specification]: https://goo.gl/zhQuYA
13 | ///
14 | /// @argument {color} $base-color
15 | /// The color to evaluate lightness against.
16 | ///
17 | /// @argument {color} $dark-color [#000]
18 | /// The color to be output when `$base-color` is light. Can also be set
19 | /// globally using the `contrast-switch-dark-color` key in the
20 | /// Bourbon settings.
21 | ///
22 | /// @argument {color} $light-color [#fff]
23 | /// The color to be output when `$base-color` is dark. Can also be set
24 | /// globally using the `contrast-switch-light-color` key in the
25 | /// Bourbon settings.
26 | ///
27 | /// @return {color}
28 | ///
29 | /// @example scss
30 | /// .element {
31 | /// color: contrast-switch(#bae6e6);
32 | /// }
33 | ///
34 | /// // CSS Output
35 | /// .element {
36 | /// color: #000;
37 | /// }
38 | ///
39 | /// @example scss
40 | /// .element {
41 | /// $button-color: #2d72d9;
42 | /// background-color: $button-color;
43 | /// color: contrast-switch($button-color, #222, #eee);
44 | /// }
45 | ///
46 | /// // CSS Output
47 | /// .element {
48 | /// background-color: #2d72d9;
49 | /// color: #eee;
50 | /// }
51 | ///
52 | /// @require {function} _fetch-bourbon-setting
53 | ///
54 | /// @require {function} _is-color
55 | ///
56 | /// @require {function} _contrast-ratio
57 | ///
58 | /// @since 5.0.0
59 |
60 | @function contrast-switch(
61 | $base-color,
62 | $dark-color: _fetch-bourbon-setting("contrast-switch-dark-color"),
63 | $light-color: _fetch-bourbon-setting("contrast-switch-light-color")
64 | ) {
65 | @if not _is-color($base-color) {
66 | @error "`#{$base-color}` is not a valid color for the `$base-color` " +
67 | "argument in the `contrast-switch` function.";
68 | } @else if not _is-color($dark-color) {
69 | @error "`#{$dark-color}` is not a valid color for the `$dark-color` " +
70 | "argument in the `contrast-switch` function.";
71 | } @else if not _is-color($light-color) {
72 | @error "`#{$light-color}` is not a valid color for the `$light-color` " +
73 | "argument in the `contrast-switch` function.";
74 | } @else {
75 | $-contrast-to-dark: _contrast-ratio($base-color, $dark-color);
76 | $-contrast-to-light: _contrast-ratio($base-color, $light-color);
77 | $-prefer-dark: $-contrast-to-dark >= $-contrast-to-light;
78 |
79 | @return if($-prefer-dark, $dark-color, $light-color);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_ellipsis.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Truncates text and adds an ellipsis to represent overflow.
4 | ///
5 | /// @argument {number} $width [100%]
6 | /// The `max-width` for the string to respect before being truncated.
7 | ///
8 | /// @argument {string} $display [inline-block]
9 | /// Sets the display-value of the element.
10 | ///
11 | /// @example scss
12 | /// .element {
13 | /// @include ellipsis;
14 | /// }
15 | ///
16 | /// // CSS Output
17 | /// .element {
18 | /// display: inline-block;
19 | /// max-width: 100%;
20 | /// overflow: hidden;
21 | /// text-overflow: ellipsis;
22 | /// white-space: nowrap;
23 | /// word-wrap: normal;
24 | /// }
25 |
26 | @mixin ellipsis(
27 | $width: 100%,
28 | $display: inline-block
29 | ) {
30 | display: $display;
31 | max-width: $width;
32 | overflow: hidden;
33 | text-overflow: ellipsis;
34 | white-space: nowrap;
35 | word-wrap: normal;
36 | }
37 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_font-face.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Generates an `@font-face` declaration. You can choose the specific file
4 | /// formats you need to output; the mixin supports `eot`, `ttf`, `svg`, `woff2`
5 | /// and `woff`. The mixin also supports usage with the Rails Asset Pipeline,
6 | /// which you can enable per use, or globally in the `$bourbon()` settings.
7 | ///
8 | /// @argument {string} $font-family
9 | ///
10 | /// @argument {string} $file-path
11 | ///
12 | /// @argument {string} $asset-pipeline [false]
13 | /// Set to `true` if you’re using the Rails Asset Pipeline (place the fonts
14 | /// in `app/assets/fonts/`). Can also be set globally using the
15 | /// `rails-asset-pipeline` key in the Bourbon settings.
16 | ///
17 | /// @argument {string | list} $file-formats [("ttf", "woff2", "woff")]
18 | /// List of the font file formats to include. Can also be set globally using
19 | /// the `global-font-file-formats` key in the Bourbon settings.
20 | ///
21 | /// @content
22 | /// Any additional CSS properties that are included in the `@include`
23 | /// directive will be output within the `@font-face` declaration, e.g. you can
24 | /// pass in `font-weight`, `font-style` and/or `unicode-range`.
25 | ///
26 | /// @example scss
27 | /// @include font-face(
28 | /// "source-sans-pro",
29 | /// "fonts/source-sans-pro-regular",
30 | /// ("woff2", "woff")
31 | /// ) {
32 | /// font-style: normal;
33 | /// font-weight: 400;
34 | /// }
35 | ///
36 | /// // CSS Output
37 | /// @font-face {
38 | /// font-family: "source-sans-pro";
39 | /// src: url("fonts/source-sans-pro-regular.woff2") format("woff2"),
40 | /// url("fonts/source-sans-pro-regular.woff") format("woff");
41 | /// font-style: normal;
42 | /// font-weight: 400;
43 | /// }
44 | ///
45 | /// @require {function} _font-source-declaration
46 | ///
47 | /// @require {function} _fetch-bourbon-setting
48 |
49 | @mixin font-face(
50 | $font-family,
51 | $file-path,
52 | $file-formats: _fetch-bourbon-setting("global-font-file-formats"),
53 | $asset-pipeline: _fetch-bourbon-setting("rails-asset-pipeline")
54 | ) {
55 | @font-face {
56 | font-family: $font-family;
57 | src: _font-source-declaration(
58 | $font-family,
59 | $file-path,
60 | $asset-pipeline,
61 | $file-formats
62 | );
63 | @content;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_hide-text.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Hides the text in an element, commonly used to show an image instead. Some
4 | /// elements will need block-level styles applied.
5 | ///
6 | /// @link https://goo.gl/EvLRIu
7 | ///
8 | /// @example scss
9 | /// .element {
10 | /// @include hide-text;
11 | /// }
12 | ///
13 | /// // CSS Output
14 | /// .element {
15 | /// overflow: hidden;
16 | /// text-indent: 101%;
17 | /// white-space: nowrap;
18 | /// }
19 |
20 | @mixin hide-text {
21 | overflow: hidden;
22 | text-indent: 101%;
23 | white-space: nowrap;
24 | }
25 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_hide-visually.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Hides an element visually while still allowing the content to be accessible
4 | /// to assistive technology, e.g. screen readers. Passing `unhide` will reverse
5 | /// the affects of the hiding, which is handy for showing the element on focus,
6 | /// for example.
7 | ///
8 | /// @link https://goo.gl/Vf1TGn
9 | ///
10 | /// @argument {string} $toggle [hide]
11 | /// Accepts `hide` or `unhide`. `unhide` reverses the affects of `hide`.
12 | ///
13 | /// @example scss
14 | /// .element {
15 | /// @include hide-visually;
16 | ///
17 | /// &:active,
18 | /// &:focus {
19 | /// @include hide-visually("unhide");
20 | /// }
21 | /// }
22 | ///
23 | /// // CSS Output
24 | /// .element {
25 | /// border: 0;
26 | /// clip: rect(1px, 1px, 1px, 1px);
27 | /// clip-path: inset(100%);
28 | /// height: 1px;
29 | /// overflow: hidden;
30 | /// padding: 0;
31 | /// position: absolute;
32 | /// width: 1px;
33 | /// }
34 | ///
35 | /// .hide-visually:active,
36 | /// .hide-visually:focus {
37 | /// clip: auto;
38 | /// clip-path: none;
39 | /// height: auto;
40 | /// overflow: visible;
41 | /// position: static;
42 | /// width: auto;
43 | /// }
44 | ///
45 | /// @since 5.0.0
46 |
47 | @mixin hide-visually($toggle: "hide") {
48 | @if not index("hide" "unhide", $toggle) {
49 | @error "`#{$toggle}` is not a valid value for the `$toggle` argument in " +
50 | "the `hide-visually` mixin. Must be either `hide` or `unhide`.";
51 | } @else if $toggle == "hide" {
52 | border: 0;
53 | clip: rect(1px, 1px, 1px, 1px);
54 | clip-path: inset(100%);
55 | height: 1px;
56 | overflow: hidden;
57 | padding: 0;
58 | position: absolute;
59 | white-space: nowrap;
60 | width: 1px;
61 | } @else if $toggle == "unhide" {
62 | clip: auto;
63 | clip-path: none;
64 | height: auto;
65 | overflow: visible;
66 | position: static;
67 | white-space: inherit;
68 | width: auto;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_margin.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise, one-line method for setting `margin` on specific edges
4 | /// of a box. Use a `null` value to “skip” edges of the box with standard
5 | /// CSS shorthand.
6 | ///
7 | /// @argument {list} $values
8 | /// List of margin values; accepts CSS shorthand.
9 | ///
10 | /// @example scss
11 | /// .element {
12 | /// @include margin(null auto);
13 | /// }
14 | ///
15 | /// // CSS Output
16 | /// .element {
17 | /// margin-left: auto;
18 | /// margin-right: auto;
19 | /// }
20 | ///
21 | /// @example scss
22 | /// .element {
23 | /// @include margin(10px 3em 20vh null);
24 | /// }
25 | ///
26 | /// // CSS Output
27 | /// .element {
28 | /// margin-bottom: 20vh;
29 | /// margin-right: 3em;
30 | /// margin-top: 10px;
31 | /// }
32 | ///
33 | /// @require {mixin} _directional-property
34 |
35 | @mixin margin($values) {
36 | @include _directional-property(margin, null, $values);
37 | }
38 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_modular-scale.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Increments up or down a defined scale and returns an adjusted value. This
4 | /// helps establish consistent measurements and spacial relationships throughout
5 | /// your project. We provide a list of commonly used scales as
6 | /// [pre-defined variables][scales].
7 | ///
8 | /// [scales]: https://github.com/thoughtbot/bourbon/blob/master/core/bourbon/settings/_scales.scss
9 | ///
10 | /// @argument {number (unitless)} $increment
11 | /// How many steps to increment up or down the scale.
12 | ///
13 | /// @argument {number (with unit) | list} $value [1em]
14 | /// The base value the scale starts at. Can also be set globally using the
15 | /// `modular-scale-base` key in the Bourbon settings.
16 | ///
17 | /// @argument {number (unitless)} $ratio [1.25]
18 | /// The ratio the scale is built on. Can also be set globally using the
19 | /// `modular-scale-ratio` key in the Bourbon settings.
20 | ///
21 | /// @return {number (with unit)}
22 | ///
23 | /// @example scss
24 | /// .element {
25 | /// font-size: modular-scale(2);
26 | /// }
27 | ///
28 | /// // CSS Output
29 | /// .element {
30 | /// font-size: 1.5625em;
31 | /// }
32 | ///
33 | /// @example scss
34 | /// .element {
35 | /// margin-right: modular-scale(3, 2em);
36 | /// }
37 | ///
38 | /// // CSS Output
39 | /// .element {
40 | /// margin-right: 3.90625em;
41 | /// }
42 | ///
43 | /// @example scss
44 | /// .element {
45 | /// font-size: modular-scale(3, 1em 1.6em, $major-seventh);
46 | /// }
47 | ///
48 | /// // CSS Output
49 | /// .element {
50 | /// font-size: 3em;
51 | /// }
52 | ///
53 | /// @example scss
54 | /// // Globally change the base ratio
55 | /// $bourbon: (
56 | /// "modular-scale-ratio": 1.2,
57 | /// );
58 | ///
59 | /// .element {
60 | /// font-size: modular-scale(3);
61 | /// }
62 | ///
63 | /// // CSS Output
64 | /// .element {
65 | /// font-size: 1.728em;
66 | /// }
67 | ///
68 | /// @require {function} _fetch-bourbon-setting
69 |
70 | @function modular-scale(
71 | $increment,
72 | $value: _fetch-bourbon-setting("modular-scale-base"),
73 | $ratio: _fetch-bourbon-setting("modular-scale-ratio")
74 | ) {
75 | $v1: nth($value, 1);
76 | $v2: nth($value, length($value));
77 | $value: $v1;
78 |
79 | // scale $v2 to just above $v1
80 | @while $v2 > $v1 {
81 | $v2: ($v2 / $ratio); // will be off-by-1
82 | }
83 | @while $v2 < $v1 {
84 | $v2: ($v2 * $ratio); // will fix off-by-1
85 | }
86 |
87 | // check AFTER scaling $v2 to prevent double-counting corner-case
88 | $double-stranded: $v2 > $v1;
89 |
90 | @if $increment > 0 {
91 | @for $i from 1 through $increment {
92 | @if $double-stranded and ($v1 * $ratio) > $v2 {
93 | $value: $v2;
94 | $v2: ($v2 * $ratio);
95 | } @else {
96 | $v1: ($v1 * $ratio);
97 | $value: $v1;
98 | }
99 | }
100 | }
101 |
102 | @if $increment < 0 {
103 | // adjust $v2 to just below $v1
104 | @if $double-stranded {
105 | $v2: ($v2 / $ratio);
106 | }
107 |
108 | @for $i from $increment through -1 {
109 | @if $double-stranded and ($v1 / $ratio) < $v2 {
110 | $value: $v2;
111 | $v2: ($v2 / $ratio);
112 | } @else {
113 | $v1: ($v1 / $ratio);
114 | $value: $v1;
115 | }
116 | }
117 | }
118 |
119 | @return $value;
120 | }
121 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_overflow-wrap.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Outputs the `overflow-wrap` property and its legacy name `word-wrap` to
4 | /// support browsers that do not yet use `overflow-wrap`.
5 | ///
6 | /// @argument {string} $wrap [break-word]
7 | /// Accepted CSS values are `normal`, `break-word`, `inherit`, `initial`,
8 | /// or `unset`.
9 | ///
10 | /// @example scss
11 | /// .wrapper {
12 | /// @include overflow-wrap;
13 | /// }
14 | ///
15 | /// // CSS Output
16 | /// .wrapper {
17 | /// word-wrap: break-word;
18 | /// overflow-wrap: break-word;
19 | /// }
20 |
21 | @mixin overflow-wrap($wrap: break-word) {
22 | word-wrap: $wrap;
23 | overflow-wrap: $wrap;
24 | }
25 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_padding.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise method for targeting `padding` on specific sides of a
4 | /// box. Use a `null` value to “skip” a side.
5 | ///
6 | /// @argument {list} $values
7 | /// List of padding values; accepts CSS shorthand.
8 | ///
9 | /// @example scss
10 | /// .element-one {
11 | /// @include padding(null 1rem);
12 | /// }
13 | ///
14 | /// // CSS Output
15 | /// .element-one {
16 | /// padding-left: 1rem;
17 | /// padding-right: 1rem;
18 | /// }
19 | ///
20 | /// @example scss
21 | /// .element-two {
22 | /// @include padding(10vh null 10px 5%);
23 | /// }
24 | ///
25 | /// // CSS Output
26 | /// .element-two {
27 | /// padding-bottom: 10px;
28 | /// padding-left: 5%;
29 | /// padding-top: 10vh;
30 | /// }
31 | ///
32 | /// @require {mixin} _directional-property
33 |
34 | @mixin padding($values) {
35 | @include _directional-property(padding, null, $values);
36 | }
37 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_position.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Provides a concise, one-line method for setting an element’s positioning
4 | /// properties: `position`, `top`, `right`, `bottom` and `left`. Use a `null`
5 | /// value to “skip” an edge of the box.
6 | ///
7 | /// @argument {string} $position
8 | /// A CSS position value.
9 | ///
10 | /// @argument {list} $box-edge-values
11 | /// List of lengths; accepts CSS shorthand.
12 | ///
13 | /// @example scss
14 | /// .element {
15 | /// @include position(relative, 0 null null 10em);
16 | /// }
17 | ///
18 | /// // CSS Output
19 | /// .element {
20 | /// left: 10em;
21 | /// position: relative;
22 | /// top: 0;
23 | /// }
24 | ///
25 | /// @example scss
26 | /// .element {
27 | /// @include position(absolute, 0);
28 | /// }
29 | ///
30 | /// // CSS Output
31 | /// .element {
32 | /// position: absolute;
33 | /// top: 0;
34 | /// right: 0;
35 | /// bottom: 0;
36 | /// left: 0;
37 | /// }
38 | ///
39 | /// @require {function} _is-length
40 | ///
41 | /// @require {function} _unpack-shorthand
42 |
43 | @mixin position(
44 | $position,
45 | $box-edge-values
46 | ) {
47 | $box-edge-values: _unpack-shorthand($box-edge-values);
48 | $offsets: (
49 | top: nth($box-edge-values, 1),
50 | right: nth($box-edge-values, 2),
51 | bottom: nth($box-edge-values, 3),
52 | left: nth($box-edge-values, 4),
53 | );
54 |
55 | position: $position;
56 |
57 | @each $offset, $value in $offsets {
58 | @if _is-length($value) {
59 | #{$offset}: $value;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_prefixer.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Generates vendor prefixes.
4 | ///
5 | /// @argument {string} $property
6 | /// Property to prefix.
7 | ///
8 | /// @argument {string} $value
9 | /// Value to use.
10 | ///
11 | /// @argument {list} $prefixes
12 | /// Vendor prefixes to output.
13 | ///
14 | /// @example scss
15 | /// .element {
16 | /// @include prefixer(appearance, none, ("webkit", "moz"));
17 | /// }
18 | ///
19 | /// // CSS Output
20 | /// .element {
21 | /// -webkit-appearance: none;
22 | /// -moz-appearance: none;
23 | /// appearance: none;
24 | /// }
25 | ///
26 | /// @author Hugo Giraudel
27 |
28 | @mixin prefixer(
29 | $property,
30 | $value,
31 | $prefixes: ()
32 | ) {
33 | @each $prefix in $prefixes {
34 | #{"-" + $prefix + "-" + $property}: $value;
35 | }
36 | #{$property}: $value;
37 | }
38 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_shade.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Mixes a color with black.
4 | ///
5 | /// @argument {color} $color
6 | ///
7 | /// @argument {number (percentage)} $percent
8 | /// The amount of black to be mixed in.
9 | ///
10 | /// @return {color}
11 | ///
12 | /// @example scss
13 | /// .element {
14 | /// background-color: shade(#ffbb52, 60%);
15 | /// }
16 | ///
17 | /// // CSS Output
18 | /// .element {
19 | /// background-color: #664a20;
20 | /// }
21 |
22 | @function shade(
23 | $color,
24 | $percent
25 | ) {
26 | @if not _is-color($color) {
27 | @error "`#{$color}` is not a valid color for the `$color` argument in " +
28 | "the `shade` mixin.";
29 | } @else {
30 | @return mix(#000, $color, $percent);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_size.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Sets the `width` and `height` of the element in one statement.
4 | ///
5 | /// @argument {number (with unit) | string} $width
6 | ///
7 | /// @argument {number (with unit) | string} $height [$width]
8 | ///
9 | /// @example scss
10 | /// .first-element {
11 | /// @include size(2em);
12 | /// }
13 | ///
14 | /// // CSS Output
15 | /// .first-element {
16 | /// width: 2em;
17 | /// height: 2em;
18 | /// }
19 | ///
20 | /// @example scss
21 | /// .second-element {
22 | /// @include size(auto, 10em);
23 | /// }
24 | ///
25 | /// // CSS Output
26 | /// .second-element {
27 | /// width: auto;
28 | /// height: 10em;
29 | /// }
30 | ///
31 | /// @require {function} _is-size
32 |
33 | @mixin size(
34 | $width,
35 | $height: $width
36 | ) {
37 | @if _is-size($height) {
38 | height: $height;
39 | } @else {
40 | @error "`#{$height}` is not a valid length for the `$height` argument " +
41 | "in the `size` mixin.";
42 | }
43 |
44 | @if _is-size($width) {
45 | width: $width;
46 | } @else {
47 | @error "`#{$width}` is not a valid length for the `$width` argument " +
48 | "in the `size` mixin.";
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_strip-unit.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Strips the unit from a number.
4 | ///
5 | /// @argument {number} $value
6 | ///
7 | /// @return {number (unitless)}
8 | ///
9 | /// @example scss
10 | /// $dimension: strip-unit(10em);
11 | ///
12 | /// // Output
13 | /// $dimension: 10;
14 |
15 | @function strip-unit($value) {
16 | @return ($value / ($value * 0 + 1));
17 | }
18 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_timing-functions.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | // scss-lint:disable SpaceAfterComma, UnnecessaryMantissa, TrailingZero
4 |
5 | ////
6 | /// CSS cubic-bezier timing functions.
7 | ///
8 | /// @link https://goo.gl/p8u6SK
9 | ///
10 | /// @type string
11 | ////
12 |
13 | $ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530);
14 | $ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190);
15 | $ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220);
16 | $ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060);
17 | $ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715);
18 | $ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035);
19 | $ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335);
20 | $ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045);
21 |
22 | $ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940);
23 | $ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000);
24 | $ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000);
25 | $ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000);
26 | $ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000);
27 | $ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000);
28 | $ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000);
29 | $ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275);
30 |
31 | $ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955);
32 | $ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000);
33 | $ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000);
34 | $ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000);
35 | $ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950);
36 | $ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000);
37 | $ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860);
38 | $ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550);
39 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_tint.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Mixes a color with white.
4 | ///
5 | /// @argument {color} $color
6 | ///
7 | /// @argument {number (percentage)} $percent
8 | /// The amount of white to be mixed in.
9 | ///
10 | /// @return {color}
11 | ///
12 | /// @example scss
13 | /// .element {
14 | /// background-color: tint(#6ecaa6, 40%);
15 | /// }
16 | ///
17 | /// // CSS Output
18 | /// .element {
19 | /// background-color: #a8dfc9;
20 | /// }
21 |
22 | @function tint(
23 | $color,
24 | $percent
25 | ) {
26 | @if not _is-color($color) {
27 | @error "`#{$color}` is not a valid color for the `$color` argument in " +
28 | "the `tint` mixin.";
29 | } @else {
30 | @return mix(#fff, $color, $percent);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_triangle.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Generates a triangle pointing in a specified direction.
4 | ///
5 | /// @argument {string} $direction
6 | /// The direction the triangle should point. Accepts `up`, `up-right`,
7 | /// `right`, `down-right`, `down`, `down-left`, `left` or `up-left`.
8 | ///
9 | /// @argument {number (with unit)} $width
10 | /// Width of the triangle.
11 | ///
12 | /// @argument {number (with unit)} $height
13 | /// Height of the triangle.
14 | ///
15 | /// @argument {color} $color
16 | /// Color of the triangle.
17 | ///
18 | /// @example scss
19 | /// .element {
20 | /// &::before {
21 | /// @include triangle("up", 2rem, 1rem, #b25c9c);
22 | /// content: "";
23 | /// }
24 | /// }
25 | ///
26 | /// // CSS Output
27 | /// .element::before {
28 | /// border-style: solid;
29 | /// height: 0;
30 | /// width: 0;
31 | /// border-color: transparent transparent #b25c9c;
32 | /// border-width: 0 1rem 1rem;
33 | /// content: "";
34 | /// }
35 |
36 | @mixin triangle(
37 | $direction,
38 | $width,
39 | $height,
40 | $color
41 | ) {
42 | @if not index(
43 | "up" "up-right" "right" "down-right" "down" "down-left" "left" "up-left",
44 | $direction
45 | ) {
46 | @error "Direction must be `up`, `up-right`, `right`, `down-right`, " +
47 | "`down`, `down-left`, `left` or `up-left`.";
48 | } @else if not _is-color($color) {
49 | @error "`#{$color}` is not a valid color for the `$color` argument in " +
50 | "the `triangle` mixin.";
51 | } @else {
52 | border-style: solid;
53 | height: 0;
54 | width: 0;
55 |
56 | @if $direction == "up" {
57 | border-color: transparent transparent $color;
58 | border-width: 0 ($width / 2) $height;
59 | } @else if $direction == "up-right" {
60 | border-color: transparent $color transparent transparent;
61 | border-width: 0 $width $width 0;
62 | } @else if $direction == "right" {
63 | border-color: transparent transparent transparent $color;
64 | border-width: ($height / 2) 0 ($height / 2) $width;
65 | } @else if $direction == "down-right" {
66 | border-color: transparent transparent $color;
67 | border-width: 0 0 $width $width;
68 | } @else if $direction == "down" {
69 | border-color: $color transparent transparent;
70 | border-width: $height ($width / 2) 0;
71 | } @else if $direction == "down-left" {
72 | border-color: transparent transparent transparent $color;
73 | border-width: $width 0 0 $width;
74 | } @else if $direction == "left" {
75 | border-color: transparent $color transparent transparent;
76 | border-width: ($height / 2) $width ($height / 2) 0;
77 | } @else if $direction == "up-left" {
78 | border-color: $color transparent transparent;
79 | border-width: $width $width 0 0;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/library/_value-prefixer.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Generates vendor prefixes for values.
4 | ///
5 | /// @argument {string} $property
6 | /// Property to use.
7 | ///
8 | /// @argument {string} $value
9 | /// Value to prefix.
10 | ///
11 | /// @argument {list} $prefixes
12 | /// Vendor prefixes to output.
13 | ///
14 | /// @example scss
15 | /// .element {
16 | /// @include value-prefixer(cursor, grab, ("webkit", "moz"));
17 | /// }
18 | ///
19 | /// // CSS Output
20 | /// .element {
21 | /// cursor: -webkit-grab;
22 | /// cursor: -moz-grab;
23 | /// cursor: grab;
24 | /// }
25 | ///
26 | /// @author Matthew Tobiasz
27 |
28 | @mixin value-prefixer(
29 | $property,
30 | $value,
31 | $prefixes: ()
32 | ) {
33 | @each $prefix in $prefixes {
34 | #{$property}: #{"-" + $prefix + "-" + $value};
35 | }
36 | #{$property}: $value;
37 | }
38 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/settings/_settings.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Default global Bourbon settings. Values in this map are overwritten by any
4 | /// values set in the `$bourbon` map.
5 | ///
6 | /// @type map
7 | ///
8 | /// @property {color} contrast-switch-dark-color [#000]
9 | /// Global dark color for the `contrast-switch` function.
10 | ///
11 | /// @property {color} contrast-switch-light-color [#fff]
12 | /// Global light color for the `contrast-switch` function.
13 | ///
14 | /// @property {list} global-font-file-formats [("ttf", "woff2", "woff")]
15 | /// Global font file formats for the `font-face` mixin.
16 | ///
17 | /// @property {number (with unit)} modular-scale-base [1em]
18 | /// Global base value for the `modular-scale` function.
19 | ///
20 | /// @property {number (unitless)} modular-scale-ratio [$major-third (1.25)]
21 | /// Global base ratio for the `modular-scale` function.
22 | ///
23 | /// @property {boolean} rails-asset-pipeline [false]
24 | /// Set this to `true` when using the Rails Asset Pipeline and Bourbon will
25 | /// write asset paths using
26 | /// [sass-rails’ asset helpers](https://github.com/rails/sass-rails#asset-helpers).
27 | ///
28 | /// @access private
29 |
30 | $_bourbon-defaults: (
31 | "contrast-switch-dark-color": #000,
32 | "contrast-switch-light-color": #fff,
33 | "global-font-file-formats": ("ttf", "woff2", "woff"),
34 | "modular-scale-base": 1em,
35 | "modular-scale-ratio": $major-third,
36 | "rails-asset-pipeline": false,
37 | );
38 |
39 | /// Global Bourbon settings.
40 | ///
41 | /// @name Settings
42 | ///
43 | /// @type map
44 | ///
45 | /// @property {color} contrast-switch-dark-color [#000]
46 | /// Global dark color for the `contrast-switch` function.
47 | ///
48 | /// @property {color} contrast-switch-light-color [#fff]
49 | /// Global light color for the `contrast-switch` function.
50 | ///
51 | /// @property {list} global-font-file-formats [("ttf", "woff2", "woff")]
52 | /// Global font file formats for the `font-face` mixin.
53 | ///
54 | /// @property {number (with unit)} modular-scale-base [1em]
55 | /// Global base value for the `modular-scale` function.
56 | ///
57 | /// @property {number (unitless)} modular-scale-ratio [$major-third (1.25)]
58 | /// Global base ratio for the `modular-scale` function.
59 | ///
60 | /// @property {boolean} rails-asset-pipeline [false]
61 | /// Set this to `true` when using the Rails Asset Pipeline and Bourbon will
62 | /// write asset paths using
63 | /// [sass-rails’ asset helpers](https://github.com/rails/sass-rails#asset-helpers).
64 | ///
65 | /// @example scss
66 | /// $bourbon: (
67 | /// "contrast-switch-dark-color": #000,
68 | /// "contrast-switch-light-color": #fff,
69 | /// "global-font-file-formats": ("ttf", "woff2", "woff"),
70 | /// "modular-scale-base": 1em,
71 | /// "modular-scale-ratio": $major-third,
72 | /// "rails-asset-pipeline": false,
73 | /// );
74 |
75 | $bourbon: () !default;
76 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_assign-inputs.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Append pseudo-classes to a selector(s).
4 | ///
5 | /// @argument {list | string} $inputs
6 | /// A selector, or list of selectors, to apply the pseudo-class to.
7 | ///
8 | /// @argument {pseudo-class} $pseudo [null]
9 | /// The pseudo-class to be appended.
10 | ///
11 | /// @return {list}
12 | ///
13 | /// @access private
14 |
15 | @function _assign-inputs(
16 | $inputs,
17 | $pseudo: null
18 | ) {
19 | $list: ();
20 |
21 | @each $input in $inputs {
22 | $input: unquote($input);
23 | $input: if($pseudo, $input + ":" + $pseudo, $input);
24 | $list: append($list, $input, comma);
25 | }
26 |
27 | @return $list;
28 | }
29 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_compact-shorthand.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | // scss-lint:disable ElsePlacement
4 |
5 | /// Transforms shorthand to its shortest possible form.
6 | ///
7 | /// @argument {list} $values
8 | /// List of directional values.
9 | ///
10 | /// @example scss
11 | /// $values: _compact-shorthand(10px 20px 10px 20px);
12 | ///
13 | /// // Output
14 | /// $values: 10px 20px;
15 | ///
16 | /// @return {list}
17 | ///
18 | /// @access private
19 |
20 | @function _compact-shorthand($values) {
21 | $output: null;
22 |
23 | $a: nth($values, 1);
24 | $b: if(length($values) < 2, $a, nth($values, 2));
25 | $c: if(length($values) < 3, $a, nth($values, 3));
26 | $d: if(length($values) < 2, $a, nth($values, if(length($values) < 4, 2, 4)));
27 |
28 | @if $a == 0 { $a: 0; }
29 | @if $b == 0 { $b: 0; }
30 | @if $c == 0 { $c: 0; }
31 | @if $d == 0 { $d: 0; }
32 |
33 | @if $a == $b and $a == $c and $a == $d { $output: $a; }
34 | @else if $a == $c and $b == $d { $output: $a $b; }
35 | @else if $b == $d { $output: $a $b $c; }
36 | @else { $output: $a $b $c $d; }
37 |
38 | @return $output;
39 | }
40 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_contrast-ratio.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Programatically determines the contrast ratio between two colors.
4 | ///
5 | /// Note that the alpha channel is ignored.
6 | ///
7 | /// @link https://goo.gl/54htLV
8 | ///
9 | /// @argument {color (hex)} $color-1
10 | ///
11 | /// @argument {color (hex)} $color-2
12 | ///
13 | /// @return {number (1-21)}
14 | ///
15 | /// @example scss
16 | /// _contrast-ratio(black, white)
17 | ///
18 | /// @require {function} _lightness
19 | ///
20 | /// @access private
21 |
22 | @function _contrast-ratio($color-1, $color-2) {
23 | $-local-lightness-1: _lightness($color-1) + 0.05;
24 | $-local-lightness-2: _lightness($color-2) + 0.05;
25 |
26 | @if $-local-lightness-1 > $-local-lightness-2 {
27 | @return $-local-lightness-1 / $-local-lightness-2;
28 | } @else {
29 | @return $-local-lightness-2 / $-local-lightness-1;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_directional-property.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | // scss-lint:disable SpaceAroundOperator
4 |
5 | /// Builds directional properties by parsing CSS shorthand values. For example,
6 | /// a value of `10px null` will output top and bottom directional properties,
7 | /// but the `null` skips left and right from being output.
8 | ///
9 | /// @argument {string} $property
10 | /// Base property.
11 | ///
12 | /// @argument {string} $suffix
13 | /// Suffix to append. Use `null` to omit.
14 | ///
15 | /// @argument {list} $values
16 | /// List of values to set for the property.
17 | ///
18 | /// @example scss
19 | /// .element {
20 | /// @include _directional-property(border, width, null 5px);
21 | /// }
22 | ///
23 | /// // CSS Output
24 | /// .element {
25 | /// border-right-width: 5px;
26 | /// border-left-width: 5px;
27 | /// }
28 | ///
29 | /// @require {function} _compact-shorthand
30 | ///
31 | /// @require {function} _contains-falsy
32 | ///
33 | /// @access private
34 |
35 | @mixin _directional-property(
36 | $property,
37 | $suffix,
38 | $values
39 | ) {
40 | $top: $property + "-top" + if($suffix, "-#{$suffix}", "");
41 | $bottom: $property + "-bottom" + if($suffix, "-#{$suffix}", "");
42 | $left: $property + "-left" + if($suffix, "-#{$suffix}", "");
43 | $right: $property + "-right" + if($suffix, "-#{$suffix}", "");
44 | $all: $property + if($suffix, "-#{$suffix}", "");
45 |
46 | $values: _compact-shorthand($values);
47 |
48 | @if _contains-falsy($values) {
49 | @if nth($values, 1) { #{$top}: nth($values, 1); }
50 |
51 | @if length($values) == 1 {
52 | @if nth($values, 1) { #{$right}: nth($values, 1); }
53 | } @else {
54 | @if nth($values, 2) { #{$right}: nth($values, 2); }
55 | }
56 |
57 | @if length($values) == 2 {
58 | @if nth($values, 1) { #{$bottom}: nth($values, 1); }
59 | @if nth($values, 2) { #{$left}: nth($values, 2); }
60 | } @else if length($values) == 3 {
61 | @if nth($values, 3) { #{$bottom}: nth($values, 3); }
62 | @if nth($values, 2) { #{$left}: nth($values, 2); }
63 | } @else if length($values) == 4 {
64 | @if nth($values, 3) { #{$bottom}: nth($values, 3); }
65 | @if nth($values, 4) { #{$left}: nth($values, 4); }
66 | }
67 | } @else {
68 | #{$all}: $values;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_fetch-bourbon-setting.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Return a Bourbon setting.
4 | ///
5 | /// @argument {string} $setting
6 | ///
7 | /// @return {boolean | color | list | number | string}
8 | ///
9 | /// @example scss
10 | /// _fetch-bourbon-setting(rails-asset-pipeline)
11 | ///
12 | /// @access private
13 |
14 | @function _fetch-bourbon-setting($setting) {
15 | @return map-get(map-merge($_bourbon-defaults, $bourbon), $setting);
16 | }
17 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_font-source-declaration.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Builds the `src` list for an `@font-face` declaration.
4 | ///
5 | /// @link https://goo.gl/Ru1bKP
6 | ///
7 | /// @argument {string} $font-family
8 | ///
9 | /// @argument {string} $file-path
10 | ///
11 | /// @argument {boolean} $asset-pipeline
12 | ///
13 | /// @argument {list} $file-formats
14 | ///
15 | /// @return {list}
16 | ///
17 | /// @require {function} _contains
18 | ///
19 | /// @access private
20 |
21 | @function _font-source-declaration(
22 | $font-family,
23 | $file-path,
24 | $asset-pipeline,
25 | $file-formats
26 | ) {
27 | $src: ();
28 |
29 | $formats-map: (
30 | eot: "#{$file-path}.eot?#iefix" format("embedded-opentype"),
31 | woff2: "#{$file-path}.woff2" format("woff2"),
32 | woff: "#{$file-path}.woff" format("woff"),
33 | ttf: "#{$file-path}.ttf" format("truetype"),
34 | svg: "#{$file-path}.svg##{$font-family}" format("svg"),
35 | );
36 |
37 | @each $key, $values in $formats-map {
38 | @if _contains($file-formats, $key) {
39 | $file-path: nth($values, 1);
40 | $font-format: nth($values, 2);
41 |
42 | @if $asset-pipeline == true {
43 | $src: append($src, font-url($file-path) $font-format, comma);
44 | } @else {
45 | $src: append($src, url($file-path) $font-format, comma);
46 | }
47 | }
48 | }
49 |
50 | @return $src;
51 | }
52 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_gamma.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Performs gamma correction on a single color channel.
4 | ///
5 | /// Note that Sass does not have a `pow()` function, so the calculation
6 | /// is approximate.
7 | ///
8 | /// @argument {number (0-1)} $channel
9 | ///
10 | /// @return {number (0-1)}
11 | ///
12 | /// @access private
13 |
14 | @function _gamma($channel) {
15 | @if $channel < 0.03928 {
16 | @return $channel / 12.92;
17 | } @else {
18 | $c: ($channel + 0.055) / 1.055;
19 | @return (133 * $c * $c * $c + 155 * $c * $c) / 288;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_lightness.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Programatically determines the lightness of a color.
4 | ///
5 | /// @argument {color (hex)} $hex-color
6 | ///
7 | /// @return {number (0-1)}
8 | ///
9 | /// @example scss
10 | /// _lightness($color)
11 | ///
12 | /// @access private
13 |
14 | @function _lightness($hex-color) {
15 | $-local-red-raw: red(rgba($hex-color, 1));
16 | $-local-green-raw: green(rgba($hex-color, 1));
17 | $-local-blue-raw: blue(rgba($hex-color, 1));
18 |
19 | $-local-red: _gamma($-local-red-raw / 255);
20 | $-local-green: _gamma($-local-green-raw / 255);
21 | $-local-blue: _gamma($-local-blue-raw / 255);
22 |
23 | @return $-local-red * 0.2126 + $-local-green * 0.7152 + $-local-blue * 0.0722;
24 | }
25 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/utilities/_unpack-shorthand.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Transforms shorthand that can range from 1-to-4 values to be 4 values.
4 | ///
5 | /// @argument {list} $shorthand
6 | ///
7 | /// @example scss
8 | /// .element {
9 | /// margin: _unpack-shorthand(1em 2em);
10 | /// }
11 | ///
12 | /// // CSS Output
13 | /// .element {
14 | /// margin: 1em 2em 1em 2em;
15 | /// }
16 | ///
17 | /// @access private
18 |
19 | @function _unpack-shorthand($shorthand) {
20 | @if length($shorthand) == 1 {
21 | @return nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1);
22 | } @else if length($shorthand) == 2 {
23 | @return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 1) nth($shorthand, 2);
24 | } @else if length($shorthand) == 3 {
25 | @return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 3) nth($shorthand, 2);
26 | } @else {
27 | @return $shorthand;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/validators/_contains-falsy.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Checks if a list does not contain any values.
4 | ///
5 | /// @argument {list} $list
6 | /// The list to check against.
7 | ///
8 | /// @return {boolean}
9 | ///
10 | /// @access private
11 |
12 | @function _contains-falsy($list) {
13 | @each $item in $list {
14 | @if not $item {
15 | @return true;
16 | }
17 | }
18 |
19 | @return false;
20 | }
21 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/validators/_contains.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Checks if a list contains a value(s).
4 | ///
5 | /// @argument {list} $list
6 | /// The list to check against.
7 | ///
8 | /// @argument {list} $values
9 | /// A single value or list of values to check for.
10 | ///
11 | /// @return {boolean}
12 | ///
13 | /// @access private
14 |
15 | @function _contains(
16 | $list,
17 | $values...
18 | ) {
19 | @each $value in $values {
20 | @if type-of(index($list, $value)) != "number" {
21 | @return false;
22 | }
23 | }
24 |
25 | @return true;
26 | }
27 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/validators/_is-color.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Checks for a valid CSS color.
4 | ///
5 | /// @argument {string} $color
6 | ///
7 | /// @return {boolean}
8 | ///
9 | /// @access private
10 |
11 | @function _is-color($color) {
12 | @return (type-of($color) == color) or ($color == "currentColor");
13 | }
14 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/validators/_is-length.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Checks for a valid CSS length.
4 | ///
5 | /// @argument {string} $value
6 | ///
7 | /// @return {boolean}
8 | ///
9 | /// @access private
10 |
11 | @function _is-length($value) {
12 | @return type-of($value) != "null" and (str-slice($value + "", 1, 4) == "calc"
13 | or index(auto inherit initial 0, $value)
14 | or (type-of($value) == "number" and not(unitless($value))));
15 | }
16 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/validators/_is-number.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Checks for a valid number.
4 | ///
5 | /// @argument {number} $value
6 | ///
7 | /// @require {function} _contains
8 | ///
9 | /// @return {boolean}
10 | ///
11 | /// @access private
12 |
13 | @function _is-number($value) {
14 | @return _contains("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" 0 1 2 3 4 5 6 7 8 9, $value);
15 | }
16 |
--------------------------------------------------------------------------------
/assets/css/shared/bourbon/validators/_is-size.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /// Checks for a valid CSS size.
4 | ///
5 | /// @argument {string} $value
6 | ///
7 | /// @return {boolean}
8 | ///
9 | /// @require {function} _contains
10 | ///
11 | /// @require {function} _is-length
12 | ///
13 | /// @access private
14 |
15 | @function _is-size($value) {
16 | @return _is-length($value)
17 | or _contains("fill" "fit-content" "min-content" "max-content", $value);
18 | }
19 |
--------------------------------------------------------------------------------
/assets/css/shared/flex-grid/_fg_breakpoint.scss:
--------------------------------------------------------------------------------
1 | //Override as required.
2 | $_fg_small: 768 !default; // up to "tablet" size
3 | $_fg_medium: 1024 !default; // up to "desktop" size
4 | $_fg_large: 1280 !default; // up to bigger desktop size
5 |
6 | @mixin _fg_breakpoint($_fg_media) {
7 | @if $_fg_media == small {
8 | @media only screen and (min-width: $_fg_small*1px) { @content; }
9 | }
10 | @else if $_fg_media == medium {
11 | @media only screen and (min-width: $_fg_medium*1px) { @content; }
12 | }
13 | @else if $_fg_media == large {
14 | @media only screen and (min-width: $_fg_large*1px) { @content; }
15 | }
16 |
17 | @else if type-of($_fg_media) == number {
18 | @media only screen and (min-width: $_fg_media*1px) { @content; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/assets/css/shared/flex-grid/_fg_grid.scss:
--------------------------------------------------------------------------------
1 | // Global variables:
2 | // Unitless, interpreted as pixels
3 | $_fg_gutter: 24 !default; // gutter between columns. Set as desired.
4 | $_fg_padding: 12 !default; // padding for column boxes. Set as desired, can override for individual columns.
5 |
6 |
7 | // *** Main mixin to create a per-row layout *** //
8 | @mixin _fg($colList, $gutter: $_fg_gutter, $padding: $_fg_padding) {
9 | @if type-of($colList) == number { // call _fg_grid() directly
10 | @include _fg_grid($colList, $gutter, $padding);
11 |
12 | } @else if type-of($colList) == list and length($colList) > 1 {
13 |
14 | // Count how many columns there are altogether
15 | $columnCount: 0;
16 | @each $i in $colList {
17 | $columnCount: $columnCount + $i;
18 | }
19 |
20 | @include _fg_grid($columnCount, $gutter, $padding);
21 |
22 | @for $i from 1 through length($colList) { // set child items widths using nth:child()
23 | $c: nth($colList, $i);
24 | & > :nth-child(#{length($colList)}n+#{$i}) {
25 | @include _fg_width($c/$columnCount, $gutter);
26 | }
27 | }
28 | }
29 | }
30 |
31 |
32 | // *** Set up grid with equal width columns *** //
33 | @mixin _fg_grid($cols: 0, $gutter: $_fg_gutter, $padding: $_fg_padding) {
34 | box-sizing: border-box;
35 | display: flex;
36 | flex-wrap: wrap;
37 | margin-left: (-1 * $gutter) * 1px;
38 |
39 | > * {
40 | @if $padding != 0 {
41 | padding: $padding * 1px;
42 | }
43 | margin-left: $gutter * 1px;
44 | box-sizing: border-box;
45 | }
46 |
47 | $calc_percent: (1/$cols) * 100%;
48 | $calc_gutter_allowance: $gutter * 1px;
49 |
50 | > * { width: calc(#{$calc_percent} - #{$calc_gutter_allowance}); }
51 | }
52 |
53 |
54 | // *** width override for a column *** //
55 | @mixin _fg_width($ratio, $gutter: $_fg_gutter) {
56 | $calc_percent: $ratio * 100%;
57 | $calc_gutter: $gutter * 1px;
58 | width: calc(#{$calc_percent} - #{$calc_gutter});
59 | };
60 |
--------------------------------------------------------------------------------
/assets/css/shared/flex-grid/_flex-grid.sass:
--------------------------------------------------------------------------------
1 | @import './fg_grid'
2 | @import './fg_breakpoint'
--------------------------------------------------------------------------------
/assets/css/shared/reset/_reset.scss:
--------------------------------------------------------------------------------
1 | /* BORROWED FROM: https://gist.github.com/hcatlin/1027867
2 | http://meyerweb.com/eric/tools/css/reset/
3 | v2.0 | 20110126
4 | License: none (public domain)
5 | */
6 |
7 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
8 | margin: 0;
9 | padding: 0;
10 | border: 0;
11 | font-size: 100%;
12 | font: inherit;
13 | vertical-align: baseline; }
14 |
15 | /* HTML5 display-role reset for older browsers */
16 |
17 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
18 | display: block; }
19 |
20 | body {
21 | line-height: 1; }
22 |
23 | ol, ul {
24 | list-style: none; }
25 |
26 | blockquote, q {
27 | quotes: none; }
28 |
29 | blockquote {
30 | &:before, &:after {
31 | content: '';
32 | content: none; } }
33 |
34 | q {
35 | &:before, &:after {
36 | content: '';
37 | content: none; } }
38 |
39 | table {
40 | border-collapse: collapse;
41 | border-spacing: 0; }
--------------------------------------------------------------------------------
/assets/css/shared/settings/_colors.sass:
--------------------------------------------------------------------------------
1 | $white: #FFFFFF
2 | $gallery-gray: #EEEEEE
3 | $alabaster-gray: #FAFAFA
4 | $dark-gray: #666666
5 | $ir-red: #e73536
6 | $green: #70ca63
7 | $orange: #f6bb42
8 | $warning-red: #e9573f
9 | $blue: #4a89dc
10 |
--------------------------------------------------------------------------------
/assets/css/shared/settings/_fonts.sass:
--------------------------------------------------------------------------------
1 | $helvetica-neue: "Helvetica Neue",Helvetica,Arial,sans-serif
--------------------------------------------------------------------------------
/assets/css/theme.sass:
--------------------------------------------------------------------------------
1 | // setup & base
2 | @import 'shared/bourbon/bourbon'
3 | @import 'shared/reset/reset'
4 | @import 'theme/settings/grid'
5 | @import 'shared/flex-grid/flex-grid'
6 | @import "~pikaday/scss/pikaday.scss"
7 |
8 | // global styles
9 | @import 'shared/settings/colors'
10 | @import 'shared/settings/fonts'
11 | @import 'theme/globals/global'
12 |
13 | // component styles
14 | @import 'theme/_extends/typography'
15 | @import 'theme/_extends/buttons'
16 | @import 'theme/_extends/select-input'
17 | @import 'theme/_extends/label'
18 | @import 'theme/_extends/text-input'
19 |
20 | @import 'theme/components/account-info'
21 | @import 'theme/components/nav'
22 | @import 'theme/components/table'
23 | @import 'theme/components/toolbar'
24 | @import 'theme/components/filters'
25 | @import 'theme/components/pagination'
26 | @import 'theme/components/header-and-content'
27 | @import 'theme/components/form'
28 | @import 'theme/components/panel'
29 | @import 'theme/components/datepicker'
30 | @import 'theme/components/flash-messages'
31 |
32 | // page styles
33 | @import 'theme/pages/index'
34 | @import 'theme/pages/show'
35 | @import 'theme/pages/edit'
36 | @import 'theme/pages/new'
37 |
--------------------------------------------------------------------------------
/assets/css/theme/_extends/_buttons.sass:
--------------------------------------------------------------------------------
1 | %base-button-styles
2 | transition: all 250ms ease-in-out
3 | font-family: $helvetica-neue
4 | font-size: 14px
5 | padding: 9px 12px
6 | cursor: pointer
7 | background-color: $gallery-gray
8 | color: $dark-gray
9 | border: 1px solid transparent
10 | text-transform: capitalize
11 |
12 | %default-button
13 | @extend %base-button-styles
14 | border-color: rgba(0, 0, 0, 0.1)
15 |
16 | &:hover
17 | background-color: darken($gallery-gray, 15%)
18 |
19 | %red-button
20 | @extend %base-button-styles
21 | background-color: $ir-red
22 | color: $white
23 |
24 | &:hover
25 | background-color: darken($ir-red, 15%)
26 |
27 | %add-button
28 | &:before
29 | content: "+"
30 | display: inline-block
31 | font-size: 20px
32 | line-height: 10px
33 | font-weight: bold
34 | margin-right: 3px
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/assets/css/theme/_extends/_label.sass:
--------------------------------------------------------------------------------
1 | %base-label
2 | color: $dark-gray
3 | padding: 10px 0
4 | font-size: 14px
5 | display: block
6 |
--------------------------------------------------------------------------------
/assets/css/theme/_extends/_select-input.sass:
--------------------------------------------------------------------------------
1 | %select-input
2 | transition: all 350ms ease-in-out
3 | appearance: none
4 | outline: 0
5 | margin: 0
6 | display: block
7 | border: 1px solid darken($gallery-gray, 10%)
8 | border-radius: 0px
9 | padding: 9px 25px 9px 10px
10 | font-family: $helvetica-neue
11 | font-size: 14px
12 | background: url('../images/down-arrow.png') no-repeat 97% 50% $white
13 | background-size: 17px
14 | background-position: 94%
15 | color: $dark-gray
16 |
17 | &:focus,
18 | &:hover
19 | border-color: $dark-gray
20 |
--------------------------------------------------------------------------------
/assets/css/theme/_extends/_text-input.sass:
--------------------------------------------------------------------------------
1 | %text-input
2 | transition: all 350ms ease-in-out
3 | appearance: none
4 | outline: none
5 | background: none
6 | margin: 0
7 | padding: 10px
8 | font-family: $helvetica-neue
9 | font-size: 14px
10 | color: $dark-gray
11 | border: 1px solid darken($gallery-gray, 10%)
12 | display: block
13 | background-color: $white
14 |
15 | &:focus,
16 | &:hover
17 | border-color: $dark-gray
18 | border-width: 1px
19 |
--------------------------------------------------------------------------------
/assets/css/theme/_extends/_typography.sass:
--------------------------------------------------------------------------------
1 | %h3-text
2 | font-size: 16px
3 | font-weight: bold
4 | font-family: $helvetica-neue
5 |
6 | %h3-gray-text
7 | @extend %h3-text
8 | color: $dark-gray
--------------------------------------------------------------------------------
/assets/css/theme/components/_account-info.sass:
--------------------------------------------------------------------------------
1 | section#torch-account-info
2 | background-color: $ir-red
3 | text-align: right
4 |
5 | a
6 | margin: 6px 0
7 | display: inline-block
8 | padding: 0 10px
9 | border-right: 1px solid $white
10 | color: $white
11 | font-family: $helvetica-neue
12 | font-size: 14px
13 |
14 | .torch-container
15 | a
16 | &:last-child
17 | border-right: 0px
18 |
19 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_datepicker.sass:
--------------------------------------------------------------------------------
1 | .torch-datepicker
2 | .is-today
3 | &:not(.is-selected)
4 | .pika-button
5 | color: $ir-red
6 |
7 | .pika-button
8 | &:hover
9 | background: $ir-red
10 | color: $white !important
11 |
12 | .is-selected
13 | .pika-button
14 | background: $ir-red
15 | box-shadow: none
16 |
17 | &:hover
18 | background: $ir-red
--------------------------------------------------------------------------------
/assets/css/theme/components/_filters.sass:
--------------------------------------------------------------------------------
1 | section#torch-filters
2 | background-color: $alabaster-gray
3 | padding: 20px
4 |
5 | h3
6 | @extend %h3-gray-text
7 | text-transform: capitalize
8 |
9 | hr
10 | appearance: none
11 | border: none
12 | border-bottom: 1px solid darken($gallery-gray, 10%)
13 | margin: 20px 0 10px
14 |
15 | .field
16 | display: flex
17 | flex-wrap: wrap
18 |
19 | label
20 | @extend %base-label
21 | flex: 1
22 | flex-basis: 100%
23 |
24 | select
25 | @extend %select-input
26 | flex: 1
27 | margin-right: 20px
28 | max-width: 30%
29 |
30 | input[type="number"]
31 | @extend %text-input
32 | flex: 3
33 |
34 | input[type="text"]
35 | @extend %text-input
36 | flex: 3
37 |
38 | &.datepicker
39 | width: calc(50% - 10px)
40 |
41 | &.start
42 | margin-right: 20px
43 |
44 | button
45 | @extend %default-button
46 | margin-top: 10px
47 |
48 | a
49 | margin-left: 20px
50 | color: $ir-red
51 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_flash-messages.sass:
--------------------------------------------------------------------------------
1 | section#torch-flash-messages
2 | margin-bottom: 20px
3 |
4 | .torch-flash
5 | padding: 8px
6 | text-align: center
7 | color: $white
8 |
9 | &.error
10 | background-color: $orange
11 |
12 | &.info
13 | background-color: $blue
14 |
15 | &.success
16 | background-color: $green
17 |
18 | .torch-flash-close
19 | appearance: none
20 | background-color: inherit
21 | border: 1px solid $white
22 | color: $white
23 | border-radius: 50%
24 | width: 22px
25 | height: 22px
26 | cursor: pointer
27 |
28 | &:focus
29 | outline: none
--------------------------------------------------------------------------------
/assets/css/theme/components/_form.sass:
--------------------------------------------------------------------------------
1 | form#torch-form
2 | background-color: $white
3 | display: flex
4 | padding: 20px
5 |
6 | .torch-form-error
7 | background-color: $orange
8 | color: $white
9 | margin-bottom: 20px
10 | padding: 5px
11 | text-align: center
12 |
13 | .torch-form-group
14 | align-items: center
15 | display: flex
16 | flex-wrap: wrap
17 | margin-bottom: 20px
18 |
19 | label
20 | display: flex
21 | align-items: center
22 | justify-content: flex-end
23 | font-size: 15px
24 | font-family: $helvetica-neue
25 | color: $dark-gray
26 | flex: 1
27 | text-align: right
28 | margin-right: 20px
29 |
30 | input[type="text"],
31 | input[type="password"],
32 | textarea
33 | @extend %text-input
34 | flex: 1
35 |
36 | input[type="number"],
37 | input[type="datetime-local"]
38 | @extend %text-input
39 |
40 | select
41 | @extend %select-input
42 |
43 | .help-block
44 | margin-left: calc(30% + 12px)
45 | width: 70%
46 | text-transform: capitalize
47 | color: $orange
48 | font-size: 14px
49 |
50 | .torch-form-group-input
51 | align-items: center
52 | display: flex
53 | flex: 3
54 | flex-wrap: wrap
55 |
56 | select:first-child
57 | margin-left: 0
58 |
59 | select
60 | margin-right: 0.5em
61 | margin-left: 0.5em
62 |
63 | .form-field-error
64 | border: 1px solid red !important
65 |
66 | .invalid-feedback
67 | flex: 1
68 | margin-left: 1rem
69 | color: red
70 |
71 | .torch-submit-form
72 | display: flex
73 | justify-content: flex-end
74 |
75 | .torch-submit-button
76 | @extend %red-button
77 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_header-and-content.sass:
--------------------------------------------------------------------------------
1 | section#torch-header-and-content
2 | .header
3 | background-color: $alabaster-gray
4 | padding: 15px 20px
5 | border-top: 4px solid $ir-red
6 | border-radius: 3px
7 | border-bottom: 1px solid $gallery-gray
8 |
9 | h3
10 | @extend %h3-gray-text
11 |
12 | ul
13 | padding: 20px
14 | background-color: $white
15 |
16 |
17 | li
18 | display: flex
19 | padding: 10px 0
20 |
21 | .torch-show-label
22 | width: 20%
23 | text-align: center
24 |
25 | .torch-show-data
26 | width: 80%
27 |
28 |
29 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_nav.sass:
--------------------------------------------------------------------------------
1 | section#torch-nav
2 | background-color: $alabaster-gray
3 |
4 | .torch-container
5 | display: flex
6 |
7 | .torch-logo
8 | padding: 6px 0px
9 |
10 | a
11 | display: flex
12 |
13 | h3
14 | color: $ir-red
15 | font-family: $helvetica-neue
16 | text-transform: uppercase
17 | font-size: 18px
18 | font-weight: bold
19 | margin: 15px 10px
20 |
21 | &:before
22 | content: " "
23 | display: block
24 | background-image: url("../images/torch-logo.png")
25 | width: 50px
26 | height: 50px
27 | background-size: contain
28 | background-repeat: no-repeat
29 |
30 | .torch-nav
31 | display: flex
32 |
33 | a
34 | display: block
35 | font-size: 16px
36 | padding: 22px 10px 19px 10px
37 | border-bottom: 3px solid transparent
38 | color: lighten($dark-gray, 25%)
39 |
40 | &:hover
41 | color: $dark-gray
42 |
43 | &.active
44 | border-color: $ir_red
45 | color: $dark-gray
46 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_pagination.sass:
--------------------------------------------------------------------------------
1 | section#torch-pagination
2 | ul
3 | display: flex
4 |
5 | li
6 | a
7 | display: block
8 | padding: 10px 15px
9 | color: $ir-red
10 | text-decoration: none
11 | background-color: $white
12 | border: 1px solid $gallery-gray
13 | margin-left: -1px
14 |
15 | &:hover
16 | background-color: $alabaster-gray
17 |
18 | &.active
19 | background-color: $ir-red
20 | color: $white
21 |
22 | &:first-child
23 | a
24 | margin-left: 0px
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_panel.sass:
--------------------------------------------------------------------------------
1 | .torch-panel
2 | border: 2px solid $gallery-gray
3 | padding: 25px
4 | flex: 1
5 |
6 | legend
7 | @extend %h3-gray-text
8 | padding: 0 6px
9 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_table.sass:
--------------------------------------------------------------------------------
1 | section#torch-table
2 | overflow-x: auto
3 |
4 | .torch-no-data
5 | text-transform: capitalize
6 | color: $dark-gray
7 |
8 | table
9 | color: $dark-gray
10 | font-size: 14px
11 | font-family: $helvetica-neue
12 | width: 100%
13 | background-color: $white
14 |
15 | th
16 | border-top: 1px solid $gallery-gray
17 | border-bottom: 1px solid $gallery-gray
18 | background-color: $alabaster-gray
19 | padding: 0
20 | color: $dark-gray
21 | vertical-align: middle
22 |
23 | &:hover
24 | background-color: darken($alabaster-gray, 15%)
25 |
26 | &:first-child
27 | border-left: 1px solid $gallery-gray
28 |
29 | &:last-child
30 | border-right: 1px solid $gallery-gray
31 |
32 | .caret
33 | border-left: 5px solid transparent
34 | border-right: 5px solid transparent
35 | display: inline-block
36 | height: 0
37 | margin-left: 5px
38 | margin-top: 5px
39 | position: absolute
40 | right: 10px
41 | top: 12px
42 | width: 0
43 |
44 | a,
45 | span:not(.caret)
46 | position: relative
47 | text-decoration: none
48 | color: $dark-gray
49 | padding: 12px 10px
50 | display: block
51 |
52 | a.active.desc
53 | .caret
54 | border-top: 5px solid $dark-gray
55 |
56 | a.active.asc
57 | .caret
58 | border-bottom: 5px solid $dark-gray
59 |
60 | td
61 | overflow: hidden
62 | text-overflow: ellipsis
63 | border-top: 1px solid $gallery-gray
64 | border-bottom: 1px solid $gallery-gray
65 | vertical-align: middle
66 | padding: 15px 10px
67 | max-width: 300px
68 |
69 | &:first-child
70 | border-left: 1px solid $gallery-gray
71 |
72 | &:last-child
73 | border-right: 1px solid $gallery-gray
74 |
75 | a
76 | color: $ir-red
77 | text-decoration: none
78 |
79 | img
80 | max-height: 30px
81 | max-width: 30px
82 |
83 | button
84 | @extend %red-button
85 |
--------------------------------------------------------------------------------
/assets/css/theme/components/_toolbar.sass:
--------------------------------------------------------------------------------
1 | section#torch-toolbar
2 | .torch-container
3 | display: flex
4 | justify-content: flex-end
5 |
6 | a
7 | @extend %default-button
8 | margin-right: 20px
9 |
10 | &:last-child
11 | margin-right: 0px
--------------------------------------------------------------------------------
/assets/css/theme/globals/_global.sass:
--------------------------------------------------------------------------------
1 | html
2 | background: $gallery-gray
3 | font-family: $helvetica-neue
4 | font-weight: normal
5 | min-height: 100vh
6 |
7 | body
8 | min-height: 100vh
9 |
10 | a
11 | text-decoration: none
12 |
13 | .torch-container
14 | margin: 0 auto
15 | padding-right: 15px
16 | padding-left: 15px
17 |
--------------------------------------------------------------------------------
/assets/css/theme/pages/_edit.sass:
--------------------------------------------------------------------------------
1 | body.torch-edit,
2 | body.torch-update
3 | header
4 | margin-bottom: 20px
5 |
6 | section#torch-toolbar
7 | margin-bottom: 20px
--------------------------------------------------------------------------------
/assets/css/theme/pages/_index.sass:
--------------------------------------------------------------------------------
1 | body.torch-index
2 | section#torch-nav
3 | margin-bottom: 20px
4 |
5 | section#torch-toolbar
6 | margin-bottom: 20px
7 |
8 | section#torch-index-content
9 | .torch-container
10 | display: flex
11 |
12 | section#torch-filters
13 | flex: 1
14 | margin-left: 35px
15 | order: 2
16 |
17 | section#torch-table
18 | flex: 3
19 | order: 1
20 | width: 70%
21 |
22 | table
23 | margin-bottom: 20px
24 |
25 | th
26 | text-align: left
27 |
28 | th:last-child
29 | text-align: right
30 |
31 | .torch-actions
32 | text-align: right
33 |
34 | section#torch-pagination
35 | display: flex
36 | justify-content: center
37 | margin-bottom: 20px
38 |
--------------------------------------------------------------------------------
/assets/css/theme/pages/_new.sass:
--------------------------------------------------------------------------------
1 | body.torch-new,
2 | body.torch-create
3 | header
4 | margin-bottom: 20px
5 |
6 | section#torch-toolbar
7 | margin-bottom: 20px
--------------------------------------------------------------------------------
/assets/css/theme/pages/_show.sass:
--------------------------------------------------------------------------------
1 | body.torch-show
2 | header
3 | margin-bottom: 20px
4 |
5 | section#torch-toolbar
6 | margin-bottom: 20px
7 |
8 | .torch-container header
9 | margin-bottom: 0
10 |
11 | .torch-show-details
12 | padding: 20px
13 | background-color: $white
14 |
15 | .torch-show-attribute
16 | display: flex
17 | padding: 0.5rem 0
18 |
19 | .torch-show-label
20 | border-right: 1px solid $dark-gray
21 | flex: 1
22 | margin-right: 1rem
23 | padding-right: 1rem
24 | text-align: right
25 |
26 | .torch-show-data
27 | flex: 4
28 |
--------------------------------------------------------------------------------
/assets/css/theme/settings/_grid.sass:
--------------------------------------------------------------------------------
1 | // default grid
2 | $_fg_gutter: 36
3 | $_fg_padding: 0
--------------------------------------------------------------------------------
/assets/images/down-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/images/down-arrow.png
--------------------------------------------------------------------------------
/assets/images/torch-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/images/torch-logo.png
--------------------------------------------------------------------------------
/assets/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "repository": {},
3 | "dependencies": {
4 | "path": "^0.12.7",
5 | "phoenix": "file:../deps/phoenix",
6 | "phoenix_html": "file:../deps/phoenix_html",
7 | "pikaday": "1.8.2"
8 | },
9 | "devDependencies": {
10 | "@parcel/transformer-sass": "^2.8.3",
11 | "node-sass": "^9.0.0",
12 | "parcel": "^2.8.3",
13 | "standard": "^17.0.0"
14 | },
15 | "browserslist": [
16 | "defaults",
17 | "not IE 11"
18 | ],
19 | "target": [
20 | "web",
21 | "es5"
22 | ],
23 | "engines": {
24 | "node": ">14 <20"
25 | },
26 | "scripts": {
27 | "compile": "npm run compile:js && npm run compile:css",
28 | "compile:js": "npx parcel build --dist-dir ../priv/static ./js/torch.js",
29 | "compile:css": "npx parcel build --dist-dir ../priv/static ./css/*.sass"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/assets/static/images/down-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/static/images/down-arrow.png
--------------------------------------------------------------------------------
/assets/static/images/torch-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/assets/static/images/torch-logo.png
--------------------------------------------------------------------------------
/bin/coverage:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Generates code coverage statistics and opens it in your browser
3 |
4 | mix coveralls.html || {
5 | echo 'Tests failed!'
6 | exit 1
7 | }
8 | open cover/excoveralls.html
9 |
--------------------------------------------------------------------------------
/bin/release:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | puts 'What version number do you want to release?'
5 | print '> '
6 | version = gets.gsub(/\n/, '')
7 |
8 | continue = system "git commit -am \"Release version #{version}\""
9 | continue = system "git tag v#{version}" if continue
10 | continue = system 'git push' if continue
11 | continue = system "git push -f origin v#{version}" if continue
12 | continue = system 'mix deps.get' if continue
13 | continue = system 'mix hex.publish package' if continue
14 | continue = system 'mix hex.publish docs' if continue
15 | continue = system 'github_changelog_generator -u mojotech -p torch' if continue
16 | continue = system "git commit -am \"Update changelog for version #{version}\"" if continue
17 | continue = system 'git push' if continue
18 |
19 | if continue
20 | puts "Version #{version} was successfully released!"
21 | else
22 | puts "Version #{version} failed release process!"
23 | end
24 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Ensure Elixir is installed
4 | command -v elixir >/dev/null 2>&1 || {
5 | echo "This app requires Elixir, but it was not found on your system."
6 | echo "Install it using the instructions at http://elixir-lang.org"
7 | exit 1
8 | }
9 |
10 | # Ensure Node.js is installed
11 | command -v npm >/dev/null 2>&1 || {
12 | echo "This app requires Node.js to build assets, but it was not found on your system."
13 | echo "Install it using the instructions at http://nodejs.org"
14 | exit 1
15 | }
16 |
17 | # Ensure Npm is installed
18 | command -v npm >/dev/null 2>&1 || {
19 | echo "This app requires NPM package manager, but it was not found on your system."
20 | exit 1
21 | }
22 |
23 | echo "----------------------------------------------------------"
24 | echo "Running Tests..."
25 | echo "----------------------------------------------------------"
26 |
27 | bin/test
28 |
--------------------------------------------------------------------------------
/bin/test:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | TEST_ROOT="$(pwd)/test"
4 | ASSETS_ROOT="$(pwd)/assets"
5 |
6 | # Run integration tests
7 | iexCurrentVersion="$(iex -v | tail -n 1 | cut -d " " -f2)"
8 | echo "[DEBUG] Current Elixir Version: $iexCurrentVersion"
9 | otpCurrentVersion="$(erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell | sed 's/\"//g')"
10 | echo "[DEBUG] Current OTP Version: $otpCurrentVersion"
11 |
12 | requiredMinVersion="23"
13 | if [ "$(printf '%s\n' "$requiredMinVersion" "$otpCurrentVersion" | sort -Vr | head -n1)" = "$requiredMinVersion" ]; then
14 | echo '[Skipping] OTP 23+ is required for Phoenix 1.7+'
15 | else
16 | cd "$TEST_ROOT/support/apps/phx1_7" && {
17 | bin/test || {
18 | echo 'Integration tests on regular Phoenix 1.7 project failed!'
19 | exit 1
20 | }
21 | }
22 | fi
23 |
--------------------------------------------------------------------------------
/config/config.exs:
--------------------------------------------------------------------------------
1 | # This file is responsible for configuring your application
2 | # and its dependencies with the aid of the Mix.Config module.
3 | import Config
4 |
5 | # This configuration is loaded before any dependency and is restricted
6 | # to this project. If another project depends on this project, this
7 | # file won't be loaded nor affect the parent project. For this reason,
8 | # if you want to provide default values for your application for
9 | # 3rd-party users, it should be done in your "mix.exs" file.
10 |
11 | # You can configure your application as:
12 | #
13 | # config :torch, key: :value
14 | #
15 | # and access this configuration in your application as:
16 | #
17 | # Application.get_env(:torch, :key)
18 | #
19 | # You can also configure a 3rd-party app:
20 | #
21 | # config :logger, level: :info
22 | #
23 |
24 | # It is also possible to import configuration files, relative to this
25 | # directory. For example, you can emulate configuration per environment
26 | # by uncommenting the line below and defining dev.exs, test.exs and such.
27 | # Configuration from the imported file will override the ones defined
28 | # here (which is why it is important to import them last).
29 | #
30 | # import_config "#{Mix.env}.exs"
31 |
--------------------------------------------------------------------------------
/coveralls.json:
--------------------------------------------------------------------------------
1 | {
2 | "skip_files": [],
3 | "coverage_options": {
4 | "treat_no_relevant_lines_as_covered": true
5 | }
6 | }
--------------------------------------------------------------------------------
/lib/gettext.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.Gettext do
2 | @moduledoc """
3 | A module providing Internationalization with a gettext-based API.
4 | By using [Gettext](https://hexdocs.pm/gettext),
5 | your module gains a set of macros for translations, for example:
6 | import ExchangeWeb.Gettext
7 | # Simple translation
8 | gettext("Here is the string to translate")
9 | # Plural translation
10 | ngettext("Here is the string to translate",
11 | "Here are the strings to translate",
12 | 3)
13 | # Domain-based translation
14 | dgettext("errors", "Here is the error message to translate")
15 | See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
16 | """
17 | use Gettext.Backend, otp_app: :torch
18 | end
19 |
--------------------------------------------------------------------------------
/lib/mix/tasks/torch.gen.html.ex:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Torch.Gen.Html do
2 | @moduledoc """
3 | Light wrapper module around `mix phx.gen.html` which generates slightly
4 | modified HTML.
5 |
6 | Takes all the same params as the `phx.gen.html` task.
7 |
8 | ## Example
9 |
10 | mix torch.gen.html Accounts User users --no-schema
11 | """
12 |
13 | @commands ~w[phx.gen.html phx.gen.context]
14 |
15 | def run(args) do
16 | if Mix.Project.umbrella?() do
17 | Mix.raise("mix torch.gen.html can only be run inside an application directory")
18 | end
19 |
20 | Mix.Torch.ensure_phoenix_is_loaded!("torch.gen.html")
21 |
22 | phoenix_version = :phoenix |> Application.spec(:vsn) |> to_string()
23 |
24 | if Version.match?(phoenix_version, "< 1.7.0") do
25 | Mix.raise(
26 | "Torch v5 Mix tasks will only run on Phoenix 1.7+. Phoenix version detected: #{phoenix_version}"
27 | )
28 | end
29 |
30 | # First, backup the projects existing templates if they exist
31 | Enum.each(@commands, &Mix.Torch.backup_project_templates/1)
32 |
33 | # Inject the torch templates for the generator into the priv/
34 | # directory so they will be picked up by the Phoenix generator
35 | Enum.each(@commands, &Mix.Torch.inject_templates/1)
36 |
37 | Mix.Task.run("phx.gen.html", args)
38 |
39 | # Remove the injected templates from priv/ so they will not
40 | # affect future Phoenix generator commands
41 | Enum.each(@commands, &Mix.Torch.remove_templates/1)
42 |
43 | # Restore the projects existing templates if present
44 | Enum.each(@commands, &Mix.Torch.restore_project_templates/1)
45 |
46 | Mix.shell().info("""
47 | Ensure the following is added to your endpoint.ex:
48 |
49 | plug(
50 | Plug.Static,
51 | at: "/torch",
52 | from: {:torch, "priv/static"},
53 | gzip: true,
54 | cache_control_for_etags: "public, max-age=86400",
55 | headers: [{"access-control-allow-origin", "*"}]
56 | )
57 | """)
58 |
59 | Mix.shell().info("""
60 | Also don't forget to add a link to layouts/torch.html if desired.
61 |
62 |
65 | """)
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/lib/mix/tasks/torch.install.ex:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Torch.Install do
2 | @moduledoc """
3 | Installs torch layout to your `_web/templates` directory.
4 |
5 | ## Configuration
6 |
7 | config :torch,
8 | otp_app: :my_app
9 |
10 | ## Example
11 |
12 | Running without options will read configuration from your `config.exs` file,
13 | as shown above.
14 |
15 | mix torch.install
16 |
17 | Also accepts the `--app` option:
18 |
19 | mix torch.install --app my_app
20 | """
21 |
22 | def run(args) do
23 | if Mix.Project.umbrella?() do
24 | Mix.raise("mix torch.install can only be run inside an application directory")
25 | end
26 |
27 | %{otp_app: otp_app} = Mix.Torch.parse_config!("torch.install", args)
28 |
29 | Mix.Torch.ensure_phoenix_is_loaded!("torch.install")
30 |
31 | phoenix_version = :phoenix |> Application.spec(:vsn) |> to_string()
32 |
33 | if Version.match?(phoenix_version, "< 1.7.0") do
34 | Mix.raise(
35 | "Torch v5 Mix tasks will only run on Phoenix 1.7+. Phoenix version detected: #{phoenix_version}"
36 | )
37 | end
38 |
39 | Mix.Torch.copy_from("priv/templates/torch.install", [
40 | {"layout.html.heex", "lib/#{otp_app}_web/components/layouts/torch.html.heex"}
41 | ])
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/mix/tasks/torch.uninstall.ex:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Torch.Uninstall do
2 | @moduledoc """
3 | Uninstalls torch layout.
4 |
5 | ## Example
6 |
7 | mix torch.uninstall
8 |
9 | Also accepts the `--app` option:
10 |
11 | mix torch.uninstall --app my_app
12 | """
13 |
14 | def run(args) do
15 | if Mix.Project.umbrella?() do
16 | Mix.raise("mix torch.uninstall can only be run inside an application directory")
17 | end
18 |
19 | %{otp_app: otp_app} = Mix.Torch.parse_config!("torch.uninstall", args)
20 |
21 | Mix.Torch.ensure_phoenix_is_loaded!("torch.uninstall")
22 |
23 | phoenix_version = :phoenix |> Application.spec(:vsn) |> to_string()
24 |
25 | if Version.match?(phoenix_version, "< 1.7.0") do
26 | Mix.raise(
27 | "Torch v5 Mix tasks will only run on Phoenix 1.7+. Phoenix version detected: #{phoenix_version}"
28 | )
29 | end
30 |
31 | paths = [
32 | "lib/#{otp_app}_web/components/layouts/torch.html.heex"
33 | ]
34 |
35 | Enum.each(paths, &File.rm/1)
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/torch.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch do
2 | @moduledoc """
3 | Documentation for Torch.
4 | """
5 | end
6 |
--------------------------------------------------------------------------------
/lib/torch/config.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.Config do
2 | @moduledoc """
3 | Application config for torch.
4 | """
5 |
6 | def otp_app do
7 | Application.get_env(:torch, :otp_app)
8 | end
9 |
10 | def i18n_backend do
11 | Application.get_env(:torch, :i18n_backend, Torch.I18n.Backend)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/torch/i18n.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.I18n do
2 | @moduledoc """
3 | Provides internationalization support for Torch apps using standard
4 | Gettext features as a default, but also allows Torch users to customize
5 | their own "messaging backends" for custom i18n support.
6 | """
7 |
8 | def message(text_key), do: Torch.Config.i18n_backend().message(text_key)
9 | end
10 |
--------------------------------------------------------------------------------
/lib/torch/i18n/backend.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.I18n.Backend do
2 | @moduledoc """
3 | Provides messages for different parts of the package. Can
4 | also be overridden to include custom translations.
5 | """
6 |
7 | use Gettext, backend: Torch.Gettext
8 |
9 | def message("Contains"), do: dgettext("default", "Contains")
10 | def message("Equals"), do: dgettext("default", "Equals")
11 | def message("Choose one"), do: dgettext("default", "Choose one")
12 | def message("Before"), do: dgettext("default", "Before")
13 | def message("After"), do: dgettext("default", "After")
14 | def message("Greater Than"), do: dgettext("default", "Greater Than")
15 | def message("Greater Than Or Equal"), do: dgettext("default", "Greater Than Or Equal")
16 | def message("Less Than"), do: dgettext("default", "Less Than")
17 | def message("start"), do: dgettext("default", "start")
18 | def message("end"), do: dgettext("default", "end")
19 | def message("Select Date"), do: dgettext("default", "Select Date")
20 | def message("Select Start Date"), do: dgettext("default", "Select Start Date")
21 | def message("Select End Date"), do: dgettext("default", "Select End Date")
22 | def message("< Prev"), do: dgettext("default", "< Prev")
23 | def message("Next >"), do: dgettext("default", "Next >")
24 | def message("Any"), do: dgettext("default", "Any")
25 | def message("True"), do: dgettext("default", "True")
26 | def message("False"), do: dgettext("default", "False")
27 | def message("Cancel"), do: dgettext("default", "Cancel")
28 | def message("Submit"), do: dgettext("default", "Submit")
29 | def message("Back"), do: dgettext("default", "Back")
30 | def message("Edit"), do: dgettext("default", "Edit")
31 | def message("Show"), do: dgettext("default", "Show")
32 | def message("Delete"), do: dgettext("default", "Delete")
33 | def message("Are you sure?"), do: dgettext("default", "Are you sure?")
34 | end
35 |
--------------------------------------------------------------------------------
/lib/torch/views/flash_view.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.FlashView do
2 | @moduledoc """
3 | Contains functions for dealing with flash messages.
4 | """
5 | @moduledoc deprecated: "This module will be fully removed in Torch 6.0"
6 |
7 | use Phoenix.Component
8 |
9 | @doc """
10 | DEPRECATED: Use Torch.Components.flash_messages/1 component instead
11 |
12 | Returns a formatted group of all flash messages available.
13 |
14 | ## Parameters
15 |
16 | - `assigns`: The current `Plug.Conn.assigns` map.
17 |
18 | ## Example
19 |
20 | iex> conn = %Plug.Conn{assigns: %{flash: %{"error" => "Error Message", "info" => "Info Message", "custom" => "Custom flash key"}}}
21 | ...> flash_messages(conn.assigns) |> Phoenix.HTML.Safe.to_iodata() |> IO.iodata_to_binary()
22 | "\\n \\n
Custom flash key
Error Message
Info Message
\\n
\\n"
23 | """
24 | @spec flash_messages(%{assigns: %{flash: map}}) :: Phoenix.LiveView.Rendered.t()
25 | @deprecated "Use Torch.Components.flash_messages/1 instead"
26 | def flash_messages(assigns), do: Torch.Component.flash_messages(assigns)
27 | end
28 |
--------------------------------------------------------------------------------
/lib/torch/views/page_view.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.PageView do
2 | @moduledoc deprecated: "This module will be fully removed in Torch 6.0"
3 | @doc """
4 | DEPRECATED: Use Torch.Helpers.body_classes/1 instead
5 |
6 | Takes the controller action name and appends it to the torch- prefix.
7 |
8 | ## Example
9 |
10 | iex> body_classes(%Plug.Conn{private: %{phoenix_action: :create}})
11 | "torch-create"
12 |
13 | iex> body_classes(%Plug.Conn{private: %{phoenix_action: :custom_action}})
14 | "torch-custom-action"
15 | """
16 |
17 | @spec body_classes(Plug.Conn.t()) :: String.t()
18 | @deprecated "Use Torch.Helpers.body_classes/1 instead"
19 | def body_classes(conn), do: Torch.Helpers.body_classes(conn)
20 | end
21 |
--------------------------------------------------------------------------------
/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule Torch.MixProject do
2 | use Mix.Project
3 |
4 | @source_url "https://github.com/mojotech/torch"
5 | @version "5.5.0"
6 |
7 | def project do
8 | [
9 | app: :torch,
10 | version: @version,
11 | elixir: "~> 1.14",
12 | start_permanent: Mix.env() == :prod,
13 | name: "Torch",
14 | description: "Rapid admin generator for Phoenix",
15 | source_url: @source_url,
16 | homepage_url: @source_url,
17 | test_paths: ["test/mix", "test/torch"],
18 | test_coverage: [tool: ExCoveralls],
19 | preferred_cli_env: [
20 | coveralls: :test,
21 | "coveralls.detail": :test,
22 | "coveralls.post": :test,
23 | "coveralls.html": :test
24 | ],
25 | elixirc_paths: elixirc_paths(Mix.env()),
26 | package: package(),
27 | docs: docs(),
28 | deps: deps()
29 | ]
30 | end
31 |
32 | defp elixirc_paths(:test), do: ["lib", "test/support/cases"]
33 | defp elixirc_paths(_env), do: ["lib"]
34 |
35 | # Run "mix help compile.app" to learn about applications.
36 | def application do
37 | [
38 | extra_applications: [:logger]
39 | ]
40 | end
41 |
42 | # Run "mix help deps" to learn about dependencies.
43 | defp deps do
44 | [
45 | {:phoenix, "~> 1.7"},
46 | {:phoenix_live_view, "~> 1.0 or ~> 0.20"},
47 | {:phoenix_html, "~> 4.1"},
48 | {:phoenix_html_helpers, "~> 1.0"},
49 | {:gettext, "~> 0.16"},
50 | {:scrivener_ecto, "~> 3.0"},
51 | {:filtrex, "~> 0.4.1"},
52 | {:jason, "~> 1.2", only: [:dev, :test]},
53 | {:excoveralls, ">= 0.0.0", only: [:dev, :test]},
54 | {:credo, "~> 1.1", only: [:dev, :test]},
55 | {:ex_doc, ">= 0.0.0", only: [:dev, :test], runtime: false},
56 | {:ex_unit_notifier, "~> 1.0", only: [:test]},
57 | {:mix_test_watch, "~> 1.0", only: [:dev], runtime: false}
58 | ]
59 | end
60 |
61 | defp package do
62 | [
63 | maintainers: ["MojoTech"],
64 | licenses: ["MIT"],
65 | files: ~w(lib priv mix.exs README.md LICENSE CHANGELOG.md CODE_OF_CONDUCT.md UPGRADING.md),
66 | links: %{
67 | "Github" => @source_url
68 | }
69 | ]
70 | end
71 |
72 | defp docs do
73 | [
74 | extras: [
75 | "CHANGELOG.md": [title: "Changelog"],
76 | "CODE_OF_CONDUCT.md": [title: "Code of Conduct"],
77 | LICENSE: [title: "License"],
78 | "README.md": [title: "Overview"],
79 | "UPGRADING.md": [title: "Upgrading"]
80 | ],
81 | main: "readme",
82 | source_ref: "v#{@version}",
83 | formatters: ["html"]
84 | ]
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/priv/gettext/de/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | # # "msgid"s in this file come from POT (.pot) files.
2 | # #
3 | # # Do not add, change, or remove "msgid"s manually here as
4 | # # they're tied to the ones in the corresponding POT file
5 | # # (with the same domain).
6 | # #
7 | # # Use "mix gettext.extract --merge" or "mix gettext.merge"
8 | # # to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: de_CH\n"
12 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
13 | "Project-Id-Version: Torch\n"
14 | "POT-Creation-Date: \n"
15 | "PO-Revision-Date: \n"
16 | "Last-Translator: \n"
17 | "Language-Team: https://github.com/mojotech/torch\n"
18 | "MIME-Version: 1.0\n"
19 | "Content-Type: text/plain; charset=UTF-8\n"
20 | "Content-Transfer-Encoding: 8bit\n"
21 | "X-Generator: Poedit 2.4.1\n"
22 | "X-Poedit-SourceCharset: UTF-8\n"
23 |
24 | #: lib/torch/i18n/backend.ex:22
25 | #, elixir-autogen
26 | msgid "< Prev"
27 | msgstr "< Zurück"
28 |
29 | #: lib/torch/i18n/backend.ex:23
30 | #, elixir-autogen
31 | msgid "Next >"
32 | msgstr "> Vorwärts"
33 |
34 | #: lib/torch/i18n/backend.ex:11
35 | #, elixir-autogen
36 | msgid "Choose one"
37 | msgstr "Wählen Sie eine"
38 |
39 | #: lib/torch/i18n/backend.ex:10
40 | #, elixir-autogen
41 | msgid "Equals"
42 | msgstr "Ist gleich"
43 |
44 | #: lib/torch/i18n/backend.ex:9
45 | #, elixir-autogen
46 | msgid "Contains"
47 | msgstr "Beinhaltet"
48 |
49 | #: lib/torch/i18n/backend.ex:14
50 | #, elixir-autogen
51 | msgid "Greater Than"
52 | msgstr "Grösser als"
53 |
54 | #: lib/torch/i18n/backend.ex:15
55 | #, elixir-autogen
56 | msgid "Greater Than Or Equal"
57 | msgstr "Grösser als oder gleich"
58 |
59 | #: lib/torch/i18n/backend.ex:16
60 | #, elixir-autogen
61 | msgid "Less Than"
62 | msgstr "Kleiner als"
63 |
64 | #: lib/torch/i18n/backend.ex:17
65 | #, elixir-autogen
66 | msgid "start"
67 | msgstr "Start"
68 |
69 | #: lib/torch/i18n/backend.ex:18
70 | #, elixir-autogen
71 | msgid "end"
72 | msgstr "Ende"
73 |
74 | #: lib/torch/i18n/backend.ex:20
75 | #, elixir-autogen
76 | msgid "Select Start Date"
77 | msgstr "Startdatum auswählen"
78 |
79 | #: lib/torch/i18n/backend.ex:21
80 | #, elixir-autogen
81 | msgid "Select End Date"
82 | msgstr "Enddatum auswählen"
83 |
84 | #: lib/torch/i18n/backend.ex:13
85 | #, elixir-autogen
86 | msgid "After"
87 | msgstr "Danach"
88 |
89 | #: lib/torch/i18n/backend.ex:12
90 | #, elixir-autogen
91 | msgid "Before"
92 | msgstr "Davor"
93 |
94 | #: lib/torch/i18n/backend.ex:19
95 | #, elixir-autogen
96 | msgid "Select Date"
97 | msgstr "Datum wählen"
98 |
99 | #: lib/torch/i18n/backend.ex:24
100 | #, elixir-autogen, elixir-format
101 | msgid "Any"
102 | msgstr "Jeder"
103 |
104 | #: lib/torch/i18n/backend.ex:26
105 | #, elixir-autogen, elixir-format
106 | msgid "False"
107 | msgstr "Falsch"
108 |
109 | #: lib/torch/i18n/backend.ex:25
110 | #, elixir-autogen, elixir-format
111 | msgid "True"
112 | msgstr "Wahr"
113 |
114 | #: lib/torch/i18n/backend.ex:33
115 | #, elixir-autogen, elixir-format
116 | msgid "Are you sure?"
117 | msgstr "Bist du dir sicher?"
118 |
119 | #: lib/torch/i18n/backend.ex:29
120 | #, elixir-autogen, elixir-format
121 | msgid "Back"
122 | msgstr "Geh zurück"
123 |
124 | #: lib/torch/i18n/backend.ex:27
125 | #, elixir-autogen, elixir-format
126 | msgid "Cancel"
127 | msgstr "Stornieren"
128 |
129 | #: lib/torch/i18n/backend.ex:32
130 | #, elixir-autogen, elixir-format
131 | msgid "Delete"
132 | msgstr "Löschen"
133 |
134 | #: lib/torch/i18n/backend.ex:30
135 | #, elixir-autogen, elixir-format
136 | msgid "Edit"
137 | msgstr "Bearbeiten"
138 |
139 | #: lib/torch/i18n/backend.ex:31
140 | #, elixir-autogen, elixir-format
141 | msgid "Show"
142 | msgstr "Zeigen"
143 |
144 | #: lib/torch/i18n/backend.ex:28
145 | #, elixir-autogen, elixir-format
146 | msgid "Submit"
147 | msgstr "Einreichen"
148 |
--------------------------------------------------------------------------------
/priv/gettext/default.pot:
--------------------------------------------------------------------------------
1 | # # This file is a PO Template file.
2 | # #
3 | # # `msgid`s here are often extracted from source code.
4 | # # Add new translations manually only if they're dynamic
5 | # # translations that can't be statically extracted.
6 | # #
7 | # # Run `mix gettext.extract` to bring this file up to
8 | # # date. Leave `msgstr`s empty as changing them here as no
9 | # # effect: edit them in PO (`.po`) files instead.
10 | msgid ""
11 | msgstr ""
12 | "Project-Id-Version: Torch\n"
13 | "POT-Creation-Date: \n"
14 | "PO-Revision-Date: \n"
15 | "Last-Translator: \n"
16 | "Language-Team: https://github.com/mojotech/torch\n"
17 | "MIME-Version: 1.0\n"
18 | "Content-Type: text/plain; charset=UTF-8\n"
19 | "Content-Transfer-Encoding: 8bit\n"
20 | "X-Generator: Poedit 2.4.1\n"
21 | "X-Poedit-SourceCharset: UTF-8\n"
22 |
23 | #: lib/torch/i18n/backend.ex:22
24 | #, elixir-autogen
25 | msgid "< Prev"
26 | msgstr ""
27 |
28 | #: lib/torch/i18n/backend.ex:23
29 | #, elixir-autogen
30 | msgid "Next >"
31 | msgstr ""
32 |
33 | #: lib/torch/i18n/backend.ex:11
34 | #, elixir-autogen
35 | msgid "Choose one"
36 | msgstr ""
37 |
38 | #: lib/torch/i18n/backend.ex:10
39 | #, elixir-autogen
40 | msgid "Equals"
41 | msgstr ""
42 |
43 | #: lib/torch/i18n/backend.ex:9
44 | #, elixir-autogen
45 | msgid "Contains"
46 | msgstr ""
47 |
48 | #: lib/torch/i18n/backend.ex:14
49 | #, elixir-autogen
50 | msgid "Greater Than"
51 | msgstr ""
52 |
53 | #: lib/torch/i18n/backend.ex:15
54 | #, elixir-autogen
55 | msgid "Greater Than Or Equal"
56 | msgstr ""
57 |
58 | #: lib/torch/i18n/backend.ex:16
59 | #, elixir-autogen
60 | msgid "Less Than"
61 | msgstr ""
62 |
63 | #: lib/torch/i18n/backend.ex:17
64 | #, elixir-autogen
65 | msgid "start"
66 | msgstr ""
67 |
68 | #: lib/torch/i18n/backend.ex:18
69 | #, elixir-autogen
70 | msgid "end"
71 | msgstr ""
72 |
73 | #: lib/torch/i18n/backend.ex:20
74 | #, elixir-autogen
75 | msgid "Select Start Date"
76 | msgstr ""
77 |
78 | #: lib/torch/i18n/backend.ex:21
79 | #, elixir-autogen
80 | msgid "Select End Date"
81 | msgstr ""
82 |
83 | #: lib/torch/i18n/backend.ex:13
84 | #, elixir-autogen
85 | msgid "After"
86 | msgstr ""
87 |
88 | #: lib/torch/i18n/backend.ex:12
89 | #, elixir-autogen
90 | msgid "Before"
91 | msgstr ""
92 |
93 | #: lib/torch/i18n/backend.ex:19
94 | #, elixir-autogen
95 | msgid "Select Date"
96 | msgstr ""
97 |
98 | #: lib/torch/i18n/backend.ex:24
99 | #, elixir-autogen, elixir-format
100 | msgid "Any"
101 | msgstr ""
102 |
103 | #: lib/torch/i18n/backend.ex:26
104 | #, elixir-autogen, elixir-format
105 | msgid "False"
106 | msgstr ""
107 |
108 | #: lib/torch/i18n/backend.ex:25
109 | #, elixir-autogen, elixir-format
110 | msgid "True"
111 | msgstr ""
112 |
113 | #: lib/torch/i18n/backend.ex:33
114 | #, elixir-autogen, elixir-format
115 | msgid "Are you sure?"
116 | msgstr ""
117 |
118 | #: lib/torch/i18n/backend.ex:29
119 | #, elixir-autogen, elixir-format
120 | msgid "Back"
121 | msgstr ""
122 |
123 | #: lib/torch/i18n/backend.ex:27
124 | #, elixir-autogen, elixir-format
125 | msgid "Cancel"
126 | msgstr ""
127 |
128 | #: lib/torch/i18n/backend.ex:32
129 | #, elixir-autogen, elixir-format
130 | msgid "Delete"
131 | msgstr ""
132 |
133 | #: lib/torch/i18n/backend.ex:30
134 | #, elixir-autogen, elixir-format
135 | msgid "Edit"
136 | msgstr ""
137 |
138 | #: lib/torch/i18n/backend.ex:31
139 | #, elixir-autogen, elixir-format
140 | msgid "Show"
141 | msgstr ""
142 |
143 | #: lib/torch/i18n/backend.ex:28
144 | #, elixir-autogen, elixir-format
145 | msgid "Submit"
146 | msgstr ""
147 |
--------------------------------------------------------------------------------
/priv/gettext/en/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
4 | "Project-Id-Version: Torch\n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: \n"
7 | "Last-Translator: \n"
8 | "Language-Team: https://github.com/mojotech/torch\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Language: en\n"
13 | "X-Generator: Poedit 2.4.1\n"
14 | "X-Poedit-SourceCharset: UTF-8\n"
15 |
16 | #: lib/torch/i18n/backend.ex:22
17 | #, elixir-autogen
18 | msgid "< Prev"
19 | msgstr ""
20 |
21 | #: lib/torch/i18n/backend.ex:23
22 | #, elixir-autogen
23 | msgid "Next >"
24 | msgstr ""
25 |
26 | #: lib/torch/i18n/backend.ex:11
27 | #, elixir-autogen
28 | msgid "Choose one"
29 | msgstr ""
30 |
31 | #: lib/torch/i18n/backend.ex:10
32 | #, elixir-autogen
33 | msgid "Equals"
34 | msgstr ""
35 |
36 | #: lib/torch/i18n/backend.ex:9
37 | #, elixir-autogen
38 | msgid "Contains"
39 | msgstr ""
40 |
41 | #: lib/torch/i18n/backend.ex:14
42 | #, elixir-autogen
43 | msgid "Greater Than"
44 | msgstr ""
45 |
46 | #: lib/torch/i18n/backend.ex:15
47 | #, elixir-autogen
48 | msgid "Greater Than Or Equal"
49 | msgstr ""
50 |
51 | #: lib/torch/i18n/backend.ex:16
52 | #, elixir-autogen
53 | msgid "Less Than"
54 | msgstr ""
55 |
56 | #: lib/torch/i18n/backend.ex:17
57 | #, elixir-autogen
58 | msgid "start"
59 | msgstr ""
60 |
61 | #: lib/torch/i18n/backend.ex:18
62 | #, elixir-autogen
63 | msgid "end"
64 | msgstr ""
65 |
66 | #: lib/torch/i18n/backend.ex:20
67 | #, elixir-autogen
68 | msgid "Select Start Date"
69 | msgstr ""
70 |
71 | #: lib/torch/i18n/backend.ex:21
72 | #, elixir-autogen
73 | msgid "Select End Date"
74 | msgstr ""
75 |
76 | #: lib/torch/i18n/backend.ex:13
77 | #, elixir-autogen
78 | msgid "After"
79 | msgstr ""
80 |
81 | #: lib/torch/i18n/backend.ex:12
82 | #, elixir-autogen
83 | msgid "Before"
84 | msgstr ""
85 |
86 | #: lib/torch/i18n/backend.ex:19
87 | #, elixir-autogen
88 | msgid "Select Date"
89 | msgstr ""
90 |
91 | #: lib/torch/i18n/backend.ex:24
92 | #, elixir-autogen, elixir-format
93 | msgid "Any"
94 | msgstr ""
95 |
96 | #: lib/torch/i18n/backend.ex:26
97 | #, elixir-autogen, elixir-format
98 | msgid "False"
99 | msgstr ""
100 |
101 | #: lib/torch/i18n/backend.ex:25
102 | #, elixir-autogen, elixir-format
103 | msgid "True"
104 | msgstr ""
105 |
106 | #: lib/torch/i18n/backend.ex:33
107 | #, elixir-autogen, elixir-format
108 | msgid "Are you sure?"
109 | msgstr ""
110 |
111 | #: lib/torch/i18n/backend.ex:29
112 | #, elixir-autogen, elixir-format
113 | msgid "Back"
114 | msgstr ""
115 |
116 | #: lib/torch/i18n/backend.ex:27
117 | #, elixir-autogen, elixir-format
118 | msgid "Cancel"
119 | msgstr ""
120 |
121 | #: lib/torch/i18n/backend.ex:32
122 | #, elixir-autogen, elixir-format
123 | msgid "Delete"
124 | msgstr ""
125 |
126 | #: lib/torch/i18n/backend.ex:30
127 | #, elixir-autogen, elixir-format
128 | msgid "Edit"
129 | msgstr ""
130 |
131 | #: lib/torch/i18n/backend.ex:31
132 | #, elixir-autogen, elixir-format
133 | msgid "Show"
134 | msgstr ""
135 |
136 | #: lib/torch/i18n/backend.ex:28
137 | #, elixir-autogen, elixir-format
138 | msgid "Submit"
139 | msgstr ""
140 |
--------------------------------------------------------------------------------
/priv/gettext/es/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | # # "msgid"s in this file come from POT (.pot) files.
2 | # #
3 | # # Do not add, change, or remove "msgid"s manually here as
4 | # # they're tied to the ones in the corresponding POT file
5 | # # (with the same domain).
6 | # #
7 | # # Use "mix gettext.extract --merge" or "mix gettext.merge"
8 | # # to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: es\n"
12 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
13 | "Project-Id-Version: Torch\n"
14 | "POT-Creation-Date: \n"
15 | "PO-Revision-Date: \n"
16 | "Last-Translator: \n"
17 | "Language-Team: https://github.com/mojotech/torch\n"
18 | "MIME-Version: 1.0\n"
19 | "Content-Type: text/plain; charset=UTF-8\n"
20 | "Content-Transfer-Encoding: 8bit\n"
21 | "X-Generator: Poedit 2.4.1\n"
22 | "X-Poedit-SourceCharset: UTF-8\n"
23 |
24 | #: lib/torch/i18n/backend.ex:22
25 | #, elixir-autogen
26 | msgid "< Prev"
27 | msgstr "< Prev"
28 |
29 | #: lib/torch/i18n/backend.ex:23
30 | #, elixir-autogen
31 | msgid "Next >"
32 | msgstr "Sig >"
33 |
34 | #: lib/torch/i18n/backend.ex:11
35 | #, elixir-autogen
36 | msgid "Choose one"
37 | msgstr "Elija uno"
38 |
39 | #: lib/torch/i18n/backend.ex:10
40 | #, elixir-autogen
41 | msgid "Equals"
42 | msgstr "Igual a"
43 |
44 | #: lib/torch/i18n/backend.ex:9
45 | #, elixir-autogen
46 | msgid "Contains"
47 | msgstr "Contiene"
48 |
49 | #: lib/torch/i18n/backend.ex:14
50 | #, elixir-autogen
51 | msgid "Greater Than"
52 | msgstr "Mayor a"
53 |
54 | #: lib/torch/i18n/backend.ex:15
55 | #, elixir-autogen
56 | msgid "Greater Than Or Equal"
57 | msgstr "Mayor o igual a"
58 |
59 | #: lib/torch/i18n/backend.ex:16
60 | #, elixir-autogen
61 | msgid "Less Than"
62 | msgstr "Menor a"
63 |
64 | #: lib/torch/i18n/backend.ex:17
65 | #, elixir-autogen
66 | msgid "start"
67 | msgstr "inicio"
68 |
69 | #: lib/torch/i18n/backend.ex:18
70 | #, elixir-autogen
71 | msgid "end"
72 | msgstr "fin"
73 |
74 | #: lib/torch/i18n/backend.ex:20
75 | #, elixir-autogen
76 | msgid "Select Start Date"
77 | msgstr "Seleccione fecha de inicio"
78 |
79 | #: lib/torch/i18n/backend.ex:21
80 | #, elixir-autogen
81 | msgid "Select End Date"
82 | msgstr "Seleccione fecha de fin"
83 |
84 | #: lib/torch/i18n/backend.ex:13
85 | #, elixir-autogen
86 | msgid "After"
87 | msgstr "Después de"
88 |
89 | #: lib/torch/i18n/backend.ex:12
90 | #, elixir-autogen
91 | msgid "Before"
92 | msgstr "Antes de"
93 |
94 | #: lib/torch/i18n/backend.ex:19
95 | #, elixir-autogen
96 | msgid "Select Date"
97 | msgstr "Seleccione fecha de fin"
98 |
99 | #: lib/torch/i18n/backend.ex:24
100 | #, elixir-autogen, elixir-format
101 | msgid "Any"
102 | msgstr "Todo"
103 |
104 | #: lib/torch/i18n/backend.ex:26
105 | #, elixir-autogen, elixir-format
106 | msgid "False"
107 | msgstr "Falso"
108 |
109 | #: lib/torch/i18n/backend.ex:25
110 | #, elixir-autogen, elixir-format
111 | msgid "True"
112 | msgstr "Verdad"
113 |
114 | #: lib/torch/i18n/backend.ex:33
115 | #, elixir-autogen, elixir-format
116 | msgid "Are you sure?"
117 | msgstr "Estas seguro"
118 |
119 | #: lib/torch/i18n/backend.ex:29
120 | #, elixir-autogen, elixir-format
121 | msgid "Back"
122 | msgstr "Regresa"
123 |
124 | #: lib/torch/i18n/backend.ex:27
125 | #, elixir-autogen, elixir-format
126 | msgid "Cancel"
127 | msgstr "Cancelar"
128 |
129 | #: lib/torch/i18n/backend.ex:32
130 | #, elixir-autogen, elixir-format
131 | msgid "Delete"
132 | msgstr "Borrar"
133 |
134 | #: lib/torch/i18n/backend.ex:30
135 | #, elixir-autogen, elixir-format
136 | msgid "Edit"
137 | msgstr "Editar"
138 |
139 | #: lib/torch/i18n/backend.ex:31
140 | #, elixir-autogen, elixir-format
141 | msgid "Show"
142 | msgstr "Mostrar"
143 |
144 | #: lib/torch/i18n/backend.ex:28
145 | #, elixir-autogen, elixir-format
146 | msgid "Submit"
147 | msgstr "Enviar"
148 |
--------------------------------------------------------------------------------
/priv/gettext/ja/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
4 | "Project-Id-Version: Torch\n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: \n"
7 | "Last-Translator: \n"
8 | "Language-Team: https://github.com/mojotech/torch\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Language: ja\n"
13 | "X-Generator: Poedit 2.4.1\n"
14 | "X-Poedit-SourceCharset: UTF-8\n"
15 |
16 | #: lib/torch/i18n/backend.ex:22
17 | #, elixir-autogen
18 | msgid "< Prev"
19 | msgstr "前へ"
20 |
21 | #: lib/torch/i18n/backend.ex:23
22 | #, elixir-autogen
23 | msgid "Next >"
24 | msgstr "次へ"
25 |
26 | #: lib/torch/i18n/backend.ex:11
27 | #, elixir-autogen
28 | msgid "Choose one"
29 | msgstr "一つ選択"
30 |
31 | #: lib/torch/i18n/backend.ex:10
32 | #, elixir-autogen
33 | msgid "Equals"
34 | msgstr "等しい"
35 |
36 | #: lib/torch/i18n/backend.ex:9
37 | #, elixir-autogen
38 | msgid "Contains"
39 | msgstr "含む"
40 |
41 | #: lib/torch/i18n/backend.ex:14
42 | #, elixir-autogen
43 | msgid "Greater Than"
44 | msgstr "より大きい"
45 |
46 | #: lib/torch/i18n/backend.ex:15
47 | #, elixir-autogen
48 | msgid "Greater Than Or Equal"
49 | msgstr "以上"
50 |
51 | #: lib/torch/i18n/backend.ex:16
52 | #, elixir-autogen
53 | msgid "Less Than"
54 | msgstr "より小さい"
55 |
56 | #: lib/torch/i18n/backend.ex:17
57 | #, elixir-autogen
58 | msgid "start"
59 | msgstr "開始"
60 |
61 | #: lib/torch/i18n/backend.ex:18
62 | #, elixir-autogen
63 | msgid "end"
64 | msgstr "修了"
65 |
66 | #: lib/torch/i18n/backend.ex:20
67 | #, elixir-autogen
68 | msgid "Select Start Date"
69 | msgstr "開始日を選択"
70 |
71 | #: lib/torch/i18n/backend.ex:21
72 | #, elixir-autogen
73 | msgid "Select End Date"
74 | msgstr "終了日を選択"
75 |
76 | #: lib/torch/i18n/backend.ex:13
77 | #, elixir-autogen
78 | msgid "After"
79 | msgstr "後"
80 |
81 | #: lib/torch/i18n/backend.ex:12
82 | #, elixir-autogen
83 | msgid "Before"
84 | msgstr "前"
85 |
86 | #: lib/torch/i18n/backend.ex:19
87 | #, elixir-autogen
88 | msgid "Select Date"
89 | msgstr "日付を選択"
90 |
91 | #: lib/torch/i18n/backend.ex:24
92 | #, elixir-autogen, elixir-format
93 | msgid "Any"
94 | msgstr "任意"
95 |
96 | #: lib/torch/i18n/backend.ex:26
97 | #, elixir-autogen, elixir-format
98 | msgid "False"
99 | msgstr "偽"
100 |
101 | #: lib/torch/i18n/backend.ex:25
102 | #, elixir-autogen, elixir-format
103 | msgid "True"
104 | msgstr "真"
105 |
106 | #: lib/torch/i18n/backend.ex:33
107 | #, elixir-autogen, elixir-format
108 | msgid "Are you sure?"
109 | msgstr "本当によろしいですか?"
110 |
111 | #: lib/torch/i18n/backend.ex:29
112 | #, elixir-autogen, elixir-format
113 | msgid "Back"
114 | msgstr "戻る"
115 |
116 | #: lib/torch/i18n/backend.ex:27
117 | #, elixir-autogen, elixir-format
118 | msgid "Cancel"
119 | msgstr "キャンセル"
120 |
121 | #: lib/torch/i18n/backend.ex:32
122 | #, elixir-autogen, elixir-format
123 | msgid "Delete"
124 | msgstr "削除"
125 |
126 | #: lib/torch/i18n/backend.ex:30
127 | #, elixir-autogen, elixir-format
128 | msgid "Edit"
129 | msgstr "編集"
130 |
131 | #: lib/torch/i18n/backend.ex:31
132 | #, elixir-autogen, elixir-format
133 | msgid "Show"
134 | msgstr "閲覧"
135 |
136 | #: lib/torch/i18n/backend.ex:28
137 | #, elixir-autogen, elixir-format
138 | msgid "Submit"
139 | msgstr "送信"
140 |
--------------------------------------------------------------------------------
/priv/gettext/pt_BR/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | ## "msgid"s in this file come from POT (.pot) files.
2 | ###
3 | ### Do not add, change, or remove "msgid"s manually here as
4 | ### they're tied to the ones in the corresponding POT file
5 | ### (with the same domain).
6 | ###
7 | ### Use "mix gettext.extract --merge" or "mix gettext.merge"
8 | ### to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: pt_BR\n"
12 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
13 | "Project-Id-Version: Torch\n"
14 | "POT-Creation-Date: \n"
15 | "PO-Revision-Date: \n"
16 | "Last-Translator: \n"
17 | "Language-Team: https://github.com/mojotech/torch\n"
18 | "MIME-Version: 1.0\n"
19 | "Content-Type: text/plain; charset=UTF-8\n"
20 | "Content-Transfer-Encoding: 8bit\n"
21 | "X-Generator: Poedit 2.4.1\n"
22 | "X-Poedit-SourceCharset: UTF-8\n"
23 |
24 | #: lib/torch/i18n/backend.ex:22
25 | #, elixir-autogen
26 | msgid "< Prev"
27 | msgstr "< Anterior"
28 |
29 | #: lib/torch/i18n/backend.ex:23
30 | #, elixir-autogen
31 | msgid "Next >"
32 | msgstr "Próximo >"
33 |
34 | #: lib/torch/i18n/backend.ex:11
35 | #, elixir-autogen
36 | msgid "Choose one"
37 | msgstr "Escolha um"
38 |
39 | #: lib/torch/i18n/backend.ex:10
40 | #, elixir-autogen
41 | msgid "Equals"
42 | msgstr "Igual"
43 |
44 | #: lib/torch/i18n/backend.ex:9
45 | #, elixir-autogen
46 | msgid "Contains"
47 | msgstr "Contém"
48 |
49 | #: lib/torch/i18n/backend.ex:14
50 | #, elixir-autogen
51 | msgid "Greater Than"
52 | msgstr "Maior que"
53 |
54 | #: lib/torch/i18n/backend.ex:15
55 | #, elixir-autogen
56 | msgid "Greater Than Or Equal"
57 | msgstr "Maior que ou igual"
58 |
59 | #: lib/torch/i18n/backend.ex:16
60 | #, elixir-autogen
61 | msgid "Less Than"
62 | msgstr "Menor que"
63 |
64 | #: lib/torch/i18n/backend.ex:17
65 | #, elixir-autogen
66 | msgid "start"
67 | msgstr "início"
68 |
69 | #: lib/torch/i18n/backend.ex:18
70 | #, elixir-autogen
71 | msgid "end"
72 | msgstr "final"
73 |
74 | #: lib/torch/i18n/backend.ex:20
75 | #, elixir-autogen
76 | msgid "Select Start Date"
77 | msgstr "Selecione a Data de Início"
78 |
79 | #: lib/torch/i18n/backend.ex:21
80 | #, elixir-autogen
81 | msgid "Select End Date"
82 | msgstr "Selecione a Data Final"
83 |
84 | #: lib/torch/i18n/backend.ex:13
85 | #, elixir-autogen
86 | msgid "After"
87 | msgstr "Após"
88 |
89 | #: lib/torch/i18n/backend.ex:12
90 | #, elixir-autogen
91 | msgid "Before"
92 | msgstr "Anterior"
93 |
94 | #: lib/torch/i18n/backend.ex:19
95 | #, elixir-autogen
96 | msgid "Select Date"
97 | msgstr "Selecione a Data"
98 |
99 | #: lib/torch/i18n/backend.ex:24
100 | #, elixir-autogen, elixir-format
101 | msgid "Any"
102 | msgstr "Qualquer"
103 |
104 | #: lib/torch/i18n/backend.ex:26
105 | #, elixir-autogen, elixir-format
106 | msgid "False"
107 | msgstr "Falso"
108 |
109 | #: lib/torch/i18n/backend.ex:25
110 | #, elixir-autogen, elixir-format
111 | msgid "True"
112 | msgstr "Verdadeiro"
113 |
114 | #: lib/torch/i18n/backend.ex:33
115 | #, elixir-autogen, elixir-format
116 | msgid "Are you sure?"
117 | msgstr "Você tem certeza?"
118 |
119 | #: lib/torch/i18n/backend.ex:29
120 | #, elixir-autogen, elixir-format
121 | msgid "Back"
122 | msgstr "Voltar"
123 |
124 | #: lib/torch/i18n/backend.ex:27
125 | #, elixir-autogen, elixir-format
126 | msgid "Cancel"
127 | msgstr "Cancelar"
128 |
129 | #: lib/torch/i18n/backend.ex:32
130 | #, elixir-autogen, elixir-format
131 | msgid "Delete"
132 | msgstr "Remover"
133 |
134 | #: lib/torch/i18n/backend.ex:30
135 | #, elixir-autogen, elixir-format
136 | msgid "Edit"
137 | msgstr "Editar"
138 |
139 | #: lib/torch/i18n/backend.ex:31
140 | #, elixir-autogen, elixir-format
141 | msgid "Show"
142 | msgstr "Exibir"
143 |
144 | #: lib/torch/i18n/backend.ex:28
145 | #, elixir-autogen, elixir-format
146 | msgid "Submit"
147 | msgstr "Enviar"
148 |
--------------------------------------------------------------------------------
/priv/gettext/ru/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
4 | "Project-Id-Version: Torch\n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: \n"
7 | "Last-Translator: \n"
8 | "Language-Team: https://github.com/mojotech/torch\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Language: ru\n"
13 | "X-Generator: Poedit 2.4.1\n"
14 | "X-Poedit-SourceCharset: UTF-8\n"
15 |
16 | #: lib/torch/i18n/backend.ex:22
17 | #, elixir-autogen
18 | msgid "< Prev"
19 | msgstr "< Предыдущая"
20 |
21 | #: lib/torch/i18n/backend.ex:23
22 | #, elixir-autogen
23 | msgid "Next >"
24 | msgstr "Следующая >"
25 |
26 | #: lib/torch/i18n/backend.ex:11
27 | #, elixir-autogen
28 | msgid "Choose one"
29 | msgstr "Выберите один элемент"
30 |
31 | #: lib/torch/i18n/backend.ex:10
32 | #, elixir-autogen
33 | msgid "Equals"
34 | msgstr "Равно"
35 |
36 | #: lib/torch/i18n/backend.ex:9
37 | #, elixir-autogen
38 | msgid "Contains"
39 | msgstr "Содержит"
40 |
41 | #: lib/torch/i18n/backend.ex:14
42 | #, elixir-autogen
43 | msgid "Greater Than"
44 | msgstr "Больше"
45 |
46 | #: lib/torch/i18n/backend.ex:15
47 | #, elixir-autogen
48 | msgid "Greater Than Or Equal"
49 | msgstr "Больше или равно"
50 |
51 | #: lib/torch/i18n/backend.ex:16
52 | #, elixir-autogen
53 | msgid "Less Than"
54 | msgstr "Меньше"
55 |
56 | #: lib/torch/i18n/backend.ex:17
57 | #, elixir-autogen
58 | msgid "start"
59 | msgstr "начало"
60 |
61 | #: lib/torch/i18n/backend.ex:18
62 | #, elixir-autogen
63 | msgid "end"
64 | msgstr "конец"
65 |
66 | #: lib/torch/i18n/backend.ex:20
67 | #, elixir-autogen
68 | msgid "Select Start Date"
69 | msgstr "Выберите дату начала"
70 |
71 | #: lib/torch/i18n/backend.ex:21
72 | #, elixir-autogen
73 | msgid "Select End Date"
74 | msgstr "Выберите дату окончания"
75 |
76 | #: lib/torch/i18n/backend.ex:13
77 | #, elixir-autogen
78 | msgid "After"
79 | msgstr ""
80 |
81 | #: lib/torch/i18n/backend.ex:12
82 | #, elixir-autogen
83 | msgid "Before"
84 | msgstr ""
85 |
86 | #: lib/torch/i18n/backend.ex:19
87 | #, elixir-autogen
88 | msgid "Select Date"
89 | msgstr "Выберите дату окончания"
90 |
91 | #: lib/torch/i18n/backend.ex:24
92 | #, elixir-autogen, elixir-format
93 | msgid "Any"
94 | msgstr "Любые"
95 |
96 | #: lib/torch/i18n/backend.ex:26
97 | #, elixir-autogen, elixir-format
98 | msgid "False"
99 | msgstr "ЛОЖЬ"
100 |
101 | #: lib/torch/i18n/backend.ex:25
102 | #, elixir-autogen, elixir-format
103 | msgid "True"
104 | msgstr "истинный"
105 |
106 | #: lib/torch/i18n/backend.ex:33
107 | #, elixir-autogen, elixir-format
108 | msgid "Are you sure?"
109 | msgstr "Вы уверены?"
110 |
111 | #: lib/torch/i18n/backend.ex:29
112 | #, elixir-autogen, elixir-format
113 | msgid "Back"
114 | msgstr "Вернуться"
115 |
116 | #: lib/torch/i18n/backend.ex:27
117 | #, elixir-autogen, elixir-format
118 | msgid "Cancel"
119 | msgstr "Отмена"
120 |
121 | #: lib/torch/i18n/backend.ex:32
122 | #, elixir-autogen, elixir-format
123 | msgid "Delete"
124 | msgstr "Удалить"
125 |
126 | #: lib/torch/i18n/backend.ex:30
127 | #, elixir-autogen, elixir-format
128 | msgid "Edit"
129 | msgstr "Редактировать"
130 |
131 | #: lib/torch/i18n/backend.ex:31
132 | #, elixir-autogen, elixir-format
133 | msgid "Show"
134 | msgstr "Показать"
135 |
136 | #: lib/torch/i18n/backend.ex:28
137 | #, elixir-autogen, elixir-format
138 | msgid "Submit"
139 | msgstr "Отправить"
140 |
--------------------------------------------------------------------------------
/priv/gettext/vi/LC_MESSAGES/default.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Plural-Forms: nplurals=2; plural=(n != 1);\n"
4 | "Project-Id-Version: Torch\n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: \n"
7 | "Last-Translator: \n"
8 | "Language-Team: https://github.com/mojotech/torch\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Language: vi\n"
13 | "X-Generator: Poedit 2.4.1\n"
14 | "X-Poedit-SourceCharset: UTF-8\n"
15 |
16 | #: lib/torch/i18n/backend.ex:22
17 | #, elixir-autogen
18 | msgid "< Prev"
19 | msgstr "< Trước"
20 |
21 | #: lib/torch/i18n/backend.ex:23
22 | #, elixir-autogen
23 | msgid "Next >"
24 | msgstr "Kế tiếp >"
25 |
26 | #: lib/torch/i18n/backend.ex:11
27 | #, elixir-autogen
28 | msgid "Choose one"
29 | msgstr "Chọn một mục"
30 |
31 | #: lib/torch/i18n/backend.ex:10
32 | #, elixir-autogen
33 | msgid "Equals"
34 | msgstr "Bằng"
35 |
36 | #: lib/torch/i18n/backend.ex:9
37 | #, elixir-autogen
38 | msgid "Contains"
39 | msgstr "Chứa"
40 |
41 | #: lib/torch/i18n/backend.ex:14
42 | #, elixir-autogen
43 | msgid "Greater Than"
44 | msgstr "Lớn hơn"
45 |
46 | #: lib/torch/i18n/backend.ex:15
47 | #, elixir-autogen
48 | msgid "Greater Than Or Equal"
49 | msgstr "Lớn hơn hoặc bằng"
50 |
51 | #: lib/torch/i18n/backend.ex:16
52 | #, elixir-autogen
53 | msgid "Less Than"
54 | msgstr "Nhỏ hơn"
55 |
56 | #: lib/torch/i18n/backend.ex:17
57 | #, elixir-autogen
58 | msgid "start"
59 | msgstr "bắt đầu"
60 |
61 | #: lib/torch/i18n/backend.ex:18
62 | #, elixir-autogen
63 | msgid "end"
64 | msgstr "kết thúc"
65 |
66 | #: lib/torch/i18n/backend.ex:20
67 | #, elixir-autogen
68 | msgid "Select Start Date"
69 | msgstr "Chọn ngày bắt đầu"
70 |
71 | #: lib/torch/i18n/backend.ex:21
72 | #, elixir-autogen
73 | msgid "Select End Date"
74 | msgstr "Chọn ngày kết thúc"
75 |
76 | #: lib/torch/i18n/backend.ex:13
77 | #, elixir-autogen
78 | msgid "After"
79 | msgstr "Sau"
80 |
81 | #: lib/torch/i18n/backend.ex:12
82 | #, elixir-autogen
83 | msgid "Before"
84 | msgstr "Trước"
85 |
86 | #: lib/torch/i18n/backend.ex:19
87 | #, elixir-autogen
88 | msgid "Select Date"
89 | msgstr "Chọn ngày"
90 |
91 | #: lib/torch/i18n/backend.ex:24
92 | #, elixir-autogen, elixir-format
93 | msgid "Any"
94 | msgstr "không tí nào"
95 |
96 | #: lib/torch/i18n/backend.ex:26
97 | #, elixir-autogen, elixir-format
98 | msgid "False"
99 | msgstr "Sai"
100 |
101 | #: lib/torch/i18n/backend.ex:25
102 | #, elixir-autogen, elixir-format
103 | msgid "True"
104 | msgstr "Thật"
105 |
106 | #: lib/torch/i18n/backend.ex:33
107 | #, elixir-autogen, elixir-format
108 | msgid "Are you sure?"
109 | msgstr "Bạn có chắc không?"
110 |
111 | #: lib/torch/i18n/backend.ex:29
112 | #, elixir-autogen, elixir-format
113 | msgid "Back"
114 | msgstr "Quay lại"
115 |
116 | #: lib/torch/i18n/backend.ex:27
117 | #, elixir-autogen, elixir-format
118 | msgid "Cancel"
119 | msgstr "Hủy bỏ"
120 |
121 | #: lib/torch/i18n/backend.ex:32
122 | #, elixir-autogen, elixir-format
123 | msgid "Delete"
124 | msgstr "Xóa bỏ"
125 |
126 | #: lib/torch/i18n/backend.ex:30
127 | #, elixir-autogen, elixir-format
128 | msgid "Edit"
129 | msgstr "Chỉnh sửa"
130 |
131 | #: lib/torch/i18n/backend.ex:31
132 | #, elixir-autogen, elixir-format
133 | msgid "Show"
134 | msgstr "Hiển thị"
135 |
136 | #: lib/torch/i18n/backend.ex:28
137 | #, elixir-autogen, elixir-format
138 | msgid "Submit"
139 | msgstr "Gửi"
140 |
--------------------------------------------------------------------------------
/priv/static/down-arrow.e17911d3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/priv/static/down-arrow.e17911d3.png
--------------------------------------------------------------------------------
/priv/static/torch-logo.a963df87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/priv/static/torch-logo.a963df87.png
--------------------------------------------------------------------------------
/priv/static/torch.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | * Pikaday
3 | *
4 | * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/Pikaday/Pikaday
5 | */
6 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.context/_grid.sass:
--------------------------------------------------------------------------------
1 | // default grid
2 | $fg_gutter: 36
3 | $fg_padding: 0
--------------------------------------------------------------------------------
/priv/templates/phx.gen.context/context.ex:
--------------------------------------------------------------------------------
1 | defmodule <%= inspect context.module %> do
2 | @moduledoc """
3 | The <%= context.name %> context.
4 | """
5 |
6 | import Ecto.Query, warn: false
7 | alias <%= inspect schema.repo %>
8 | end
--------------------------------------------------------------------------------
/priv/templates/phx.gen.context/context_test.exs:
--------------------------------------------------------------------------------
1 | defmodule <%= inspect context.module %>Test do
2 | use <%= inspect context.base_module %>.DataCase
3 |
4 | alias <%= inspect context.module %>
5 | end
--------------------------------------------------------------------------------
/priv/templates/phx.gen.context/schema_access.ex:
--------------------------------------------------------------------------------
1 |
2 | alias <%= inspect schema.module %>
3 |
4 | use Torch.Pagination,
5 | repo: <%= inspect schema.repo %>,
6 | model: <%= inspect schema.module %>,
7 | name: <%= inspect String.to_atom(schema.plural) %>
8 |
9 |
10 | @doc """
11 | Returns the list of <%= schema.plural %>.
12 |
13 | ## Examples
14 |
15 | iex> list_<%= schema.plural %>()
16 | [%<%= inspect schema.alias %>{}, ...]
17 |
18 | """
19 | def list_<%= schema.plural %> do
20 | Repo.all(<%= inspect schema.alias %>)
21 | end
22 |
23 | @doc """
24 | Gets a single <%= schema.singular %>.
25 |
26 | Raises `Ecto.NoResultsError` if the <%= schema.human_singular %> does not exist.
27 |
28 | ## Examples
29 |
30 | iex> get_<%= schema.singular %>!(123)
31 | %<%= inspect schema.alias %>{}
32 |
33 | iex> get_<%= schema.singular %>!(456)
34 | ** (Ecto.NoResultsError)
35 |
36 | """
37 | def get_<%= schema.singular %>!(id), do: Repo.get!(<%= inspect schema.alias %>, id)
38 |
39 | @doc """
40 | Creates a <%= schema.singular %>.
41 |
42 | ## Examples
43 |
44 | iex> create_<%= schema.singular %>(%{field: value})
45 | {:ok, %<%= inspect schema.alias %>{}}
46 |
47 | iex> create_<%= schema.singular %>(%{field: bad_value})
48 | {:error, %Ecto.Changeset{}}
49 |
50 | """
51 | def create_<%= schema.singular %>(attrs \\ %{}) do
52 | %<%= inspect schema.alias %>{}
53 | |> <%= inspect schema.alias %>.changeset(attrs)
54 | |> Repo.insert()
55 | end
56 |
57 | @doc """
58 | Updates a <%= schema.singular %>.
59 |
60 | ## Examples
61 |
62 | iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: new_value})
63 | {:ok, %<%= inspect schema.alias %>{}}
64 |
65 | iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: bad_value})
66 | {:error, %Ecto.Changeset{}}
67 |
68 | """
69 | def update_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
70 | <%= schema.singular %>
71 | |> <%= inspect schema.alias %>.changeset(attrs)
72 | |> Repo.update()
73 | end
74 |
75 | @doc """
76 | Deletes a <%= inspect schema.alias %>.
77 |
78 | ## Examples
79 |
80 | iex> delete_<%= schema.singular %>(<%= schema.singular %>)
81 | {:ok, %<%= inspect schema.alias %>{}}
82 |
83 | iex> delete_<%= schema.singular %>(<%= schema.singular %>)
84 | {:error, %Ecto.Changeset{}}
85 |
86 | """
87 | def delete_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
88 | Repo.delete(<%= schema.singular %>)
89 | end
90 |
91 | @doc """
92 | Returns an `%Ecto.Changeset{}` for tracking <%= schema.singular %> changes.
93 |
94 | ## Examples
95 |
96 | iex> change_<%= schema.singular %>(<%= schema.singular %>)
97 | %Ecto.Changeset{source: %<%= inspect schema.alias %>{}}
98 |
99 | """
100 | def change_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs \\ %{}) do
101 | <%= inspect schema.alias %>.changeset(<%= schema.singular %>, attrs)
102 | end
103 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/controller.ex:
--------------------------------------------------------------------------------
1 | defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Controller do
2 | use <%= inspect context.web_module %>, :controller
3 |
4 | alias <%= inspect context.module %>
5 | alias <%= inspect schema.module %>
6 |
7 | plug(:put_root_layout, {<%= inspect context.web_module %>.Layouts, "torch.html"})
8 | plug(:put_layout, false)
9 |
10 | def index(conn, params) do
11 | case <%= inspect context.alias %>.paginate_<%= schema.plural %>(params) do
12 | {:ok, assigns} ->
13 | render(conn, :index, assigns)
14 | {:error, error} ->
15 | conn
16 | |> put_flash(:error, "There was an error rendering <%= schema.human_plural %>. #{inspect(error)}")
17 | |> redirect(to: ~p"<%= schema.route_prefix %>")
18 | end
19 | end
20 |
21 | def new(conn, _params) do
22 | changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(%<%= inspect schema.alias %>{})
23 | render(conn, :new, changeset: changeset)
24 | end
25 |
26 | def create(conn, %{<%= inspect schema.singular %> => <%= schema.singular %>_params}) do
27 | case <%= inspect context.alias %>.create_<%= schema.singular %>(<%= schema.singular %>_params) do
28 | {:ok, <%= schema.singular %>} ->
29 | conn
30 | |> put_flash(:info, "<%= schema.human_singular %> created successfully.")
31 | |> redirect(to: ~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}")
32 | {:error, %Ecto.Changeset{} = changeset} ->
33 | render(conn, :new, changeset: changeset)
34 | end
35 | end
36 |
37 | def show(conn, %{"id" => id}) do
38 | <%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
39 | render(conn, :show, <%= schema.singular %>: <%= schema.singular %>)
40 | end
41 |
42 | def edit(conn, %{"id" => id}) do
43 | <%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
44 | changeset = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
45 | render(conn, :edit, <%= schema.singular %>: <%= schema.singular %>, changeset: changeset)
46 | end
47 |
48 | def update(conn, %{"id" => id, <%= inspect schema.singular %> => <%= schema.singular %>_params}) do
49 | <%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
50 |
51 | case <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, <%= schema.singular %>_params) do
52 | {:ok, <%= schema.singular %>} ->
53 | conn
54 | |> put_flash(:info, "<%= schema.human_singular %> updated successfully.")
55 | |> redirect(to: ~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}")
56 | {:error, %Ecto.Changeset{} = changeset} ->
57 | render(conn, :edit, <%= schema.singular %>: <%= schema.singular %>, changeset: changeset)
58 | end
59 | end
60 |
61 | def delete(conn, %{"id" => id}) do
62 | <%= schema.singular %> = <%= inspect context.alias %>.get_<%= schema.singular %>!(id)
63 | {:ok, _<%= schema.singular %>} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
64 |
65 | conn
66 | |> put_flash(:info, "<%= schema.human_singular %> deleted successfully.")
67 | |> redirect(to: ~p"<%= schema.route_prefix %>")
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/edit.html.heex:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
12 | <.<%= schema.singular %>_form changeset={@changeset} action={~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}"} />
13 |
14 |
15 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/edit_1_7_0.html.heex:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
12 | <.form :let={f} for={@changeset} action={~p"<%= schema.route_prefix %>/#{@<%= schema.singular %>}"} id="torch-form" enctype="multipart/form-data">
13 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/html.ex:
--------------------------------------------------------------------------------
1 | defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>HTML do
2 | use <%= inspect context.web_module %>, :html
3 |
4 | import Phoenix.HTML.Form
5 | use PhoenixHTMLHelpers
6 |
7 | import Torch.TableView
8 | import Torch.FilterView
9 | import Torch.Component
10 |
11 | def error_tag(form, field) do
12 | Enum.map(Keyword.get_values(form.errors, field), fn error ->
13 | content_tag(:span, Torch.Component.translate_error(error),
14 | class: "invalid-feedback",
15 | phx_feedback_for: input_name(form, field)
16 | )
17 | end)
18 | end
19 |
20 | embed_templates "<%= schema.singular %>_html/*"
21 | end
22 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/index.html.heex:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | Find <%= schema.human_plural %>
10 | <%%= form_tag @conn.request_path, method: :get, id: "torch-filters-form" do %>
11 | <%= for {key, type} <- schema.attrs, type in [:string, :text] do %>
12 |
13 |
14 | <%%= filter_select(:<%= schema.singular %>, :<%= key %>, @conn.params) %>
15 | <%%= filter_string_input(:<%= schema.singular %>, :<%= key %>, @conn.params) %>
16 |
17 | <% end %>
18 | <%= for {key, type} <- schema.attrs, type in [:boolean] do %>
19 |
20 |
21 | <%%= filter_boolean_input(:<%= schema.singular %>, :<%= key %>, @conn.params) %>
22 |
23 | <% end %>
24 | <%= for {key, type} <- schema.attrs, type in [:date, :datetime, :utc_datetime, :naive_datetime] do %>
25 |
26 |
27 | <%%= filter_date_input(:<%= schema.singular %>, :<%= key %>, @conn.params) %>
28 |
29 | <% end %>
30 | <%= for {key, type} <- schema.attrs, type in [:number, :integer] do %>
31 |
32 |
33 | <%%= number_filter_select(:<%= schema.singular %>, :<%= key %>, @conn.params) %>
34 | <%%= filter_number_input(:<%= schema.singular %>, :<%= key %>, @conn.params) %>
35 |
36 | <% end %>
37 |
38 | <%%= link "Clear Filters", to: ~p"<%= schema.route_prefix %>" %>
39 | <%% end %>
40 |
41 |
42 |
43 |
44 | <%%= if length(@<%= schema.plural %>) > 0 do %>
45 |
46 |
47 |
48 | <%= for {k, _} <- schema.attrs do %>
49 | <%%= table_link(@conn, "<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>", <%= inspect(k) %>) %> |
50 | <% end %>
51 | Actions |
52 |
53 |
54 |
55 | <%%= for <%= schema.singular %> <- @<%= schema.plural %> do %>
56 |
57 | <%= for {k, _} <- schema.attrs do %>
58 | <%%= <%= schema.singular %>.<%= k %> %> |
59 | <% end %>
60 |
61 | <.link href={~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}"}><%%= Torch.I18n.message("Show") %>
62 | <.link href={~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}/edit"}><%%= Torch.I18n.message("Edit") %>
63 | <.link href={~p"<%= schema.route_prefix %>/#{<%= schema.singular %>}"} method="delete" data-confirm={Torch.I18n.message("Are you sure?")}><%%= Torch.I18n.message("Delete") %>
64 | |
65 |
66 | <%% end %>
67 |
68 |
69 | <%%= Torch.PaginationView.pagination(@conn) %>
70 | <%% else %>
71 | No <%= schema.human_plural %> match your search.
72 | <%% end %>
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/new.html.heex:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
12 | <.<%= schema.singular %>_form changeset={@changeset} action={~p"<%= schema.route_prefix %>"} />
13 |
14 |
15 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/new_1_7_0.html.heex:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
12 | <.form :let={f} for={@changeset} action={~p"<%= schema.route_prefix %>"} id="torch-form" enctype="multipart/form-data">
13 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/resource_form.html.heex:
--------------------------------------------------------------------------------
1 | <.form :let={f} for={@changeset} action={@action} id="torch-form" enctype="multipart/form-data">
2 |
14 |
15 |
--------------------------------------------------------------------------------
/priv/templates/phx.gen.html/show.html.heex:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
13 |
14 | <%= for {k, _} <- schema.attrs do %>
15 |
16 |
<%= Phoenix.Naming.humanize(Atom.to_string(k)) %>:
17 |
<%%= @<%= schema.singular %>.<%= k %> %>
18 |
19 | <% end %>
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/priv/templates/torch.install/layout.html.heex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | <%= PhoenixHTMLHelpers.Tag.csrf_meta_tag() %>
8 | Torch Admin
9 |
10 |
11 |
12 |
13 |
14 |
15 |
36 |
37 |
38 | <%= @inner_content %>
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/test/mix/tasks/torch.gen.html_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Torch.Gen.HtmlTest do
2 | use Torch.MixCase, async: false
3 |
4 | describe ".run/1" do
5 | # FIXME: this is not needed an invalid as of Phx 1.7?
6 | # test_mix_config_errors("torch.gen.html")
7 |
8 | # TODO: Add integration test for umbrella app
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/test/mix/tasks/torch.install_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Torch.InstallTest do
2 | use Torch.MixCase
3 |
4 | describe ".run/1" do
5 | test_mix_config_errors("torch.install")
6 |
7 | # TODO: add test for umbrella project
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test/mix/tasks/torch.uninstall_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Mix.Tasks.Torch.UninstallTest do
2 | use Torch.MixCase
3 |
4 | describe ".run/1" do
5 | test_mix_config_errors("torch.uninstall")
6 |
7 | Mix.Task.rerun("torch.install", ["--app", "my_app"])
8 | Mix.Task.rerun("torch.uninstall", ["--app", "my_app"])
9 |
10 | # TODO: add test for umbrella project
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test/mix/test_helper.exs:
--------------------------------------------------------------------------------
1 | if System.get_env("CI") do
2 | ExUnit.configure(formatters: [ExUnit.CLIFormatter])
3 | else
4 | ExUnit.configure(formatters: [ExUnit.CLIFormatter, ExUnitNotifier])
5 | end
6 |
7 | ExUnit.start()
8 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/.formatter.exs:
--------------------------------------------------------------------------------
1 | [
2 | import_deps: [:ecto, :ecto_sql, :phoenix],
3 | subdirectories: ["priv/*/migrations"],
4 | plugins: [Phoenix.LiveView.HTMLFormatter],
5 | inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
6 | ]
7 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where 3rd-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Temporary files, for example, from tests.
23 | /tmp/
24 |
25 | # Ignore package tarball (built via "mix hex.build").
26 | phx1_7-*.tar
27 |
28 | # Ignore assets that are produced by build tools.
29 | /priv/static/assets/
30 |
31 | # Ignore digested assets cache.
32 | /priv/static/cache_manifest.json
33 |
34 | # In case you use Node.js/npm, you want to ignore these.
35 | npm-debug.log
36 | /assets/node_modules/
37 |
38 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/README.md:
--------------------------------------------------------------------------------
1 | # Phx17
2 |
3 | To start your Phoenix server:
4 |
5 | * Run `mix setup` to install and setup dependencies
6 | * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
7 |
8 | Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
9 |
10 | Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
11 |
12 | ## Learn more
13 |
14 | * Official website: https://www.phoenixframework.org/
15 | * Guides: https://hexdocs.pm/phoenix/overview.html
16 | * Docs: https://hexdocs.pm/phoenix
17 | * Forum: https://elixirforum.com/c/phoenix-forum
18 | * Source: https://github.com/phoenixframework/phoenix
19 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/assets/css/app.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss/base";
2 | @import "tailwindcss/components";
3 | @import "tailwindcss/utilities";
4 |
5 | /* This file is for your main application CSS */
6 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/assets/js/app.js:
--------------------------------------------------------------------------------
1 | // If you want to use Phoenix channels, run `mix help phx.gen.channel`
2 | // to get started and then uncomment the line below.
3 | // import "./user_socket.js"
4 |
5 | // You can include dependencies in two ways.
6 | //
7 | // The simplest option is to put them in assets/vendor and
8 | // import them using relative paths:
9 | //
10 | // import "../vendor/some-package.js"
11 | //
12 | // Alternatively, you can `npm install some-package --prefix assets` and import
13 | // them using a path starting with the package name:
14 | //
15 | // import "some-package"
16 | //
17 |
18 | // Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
19 | import "phoenix_html"
20 | // Establish Phoenix Socket and LiveView configuration.
21 | import {Socket} from "phoenix"
22 | import {LiveSocket} from "phoenix_live_view"
23 | import topbar from "../vendor/topbar"
24 |
25 | let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
26 | let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
27 |
28 | // Show progress bar on live navigation and form submits
29 | topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
30 | window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
31 | window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
32 |
33 | // connect if there are any LiveViews on the page
34 | liveSocket.connect()
35 |
36 | // expose liveSocket on window for web console debug logs and latency simulation:
37 | // >> liveSocket.enableDebug()
38 | // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
39 | // >> liveSocket.disableLatencySim()
40 | window.liveSocket = liveSocket
41 |
42 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/assets/tailwind.config.js:
--------------------------------------------------------------------------------
1 | // See the Tailwind configuration guide for advanced usage
2 | // https://tailwindcss.com/docs/configuration
3 |
4 | const plugin = require("tailwindcss/plugin")
5 |
6 | module.exports = {
7 | content: [
8 | "./js/**/*.js",
9 | "../lib/*_web.ex",
10 | "../lib/*_web/**/*.*ex"
11 | ],
12 | theme: {
13 | extend: {
14 | colors: {
15 | brand: "#FD4F00",
16 | }
17 | },
18 | },
19 | plugins: [
20 | require("@tailwindcss/forms"),
21 | plugin(({addVariant}) => addVariant("phx-no-feedback", [".phx-no-feedback&", ".phx-no-feedback &"])),
22 | plugin(({addVariant}) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
23 | plugin(({addVariant}) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
24 | plugin(({addVariant}) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"]))
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/bin/test:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Clean up generated files
4 | function cleanup() {
5 | rm -rf priv/templates
6 | rm -rf priv/repo/migrations/*.exs
7 | rm -rf lib/phx1_7/blog.ex
8 | rm -rf lib/phx1_7/blog
9 | rm -rf test/phx1_7/blog_test.exs
10 | rm -rf lib/phx1_7_web/controllers/post_controller.ex
11 | rm -rf lib/phx1_7_web/templates/layout/torch.html.heex
12 | rm -rf lib/phx1_7_web/templates/post/
13 | rm -rf lib/phx1_7_web/views/post_view.ex
14 | rm -rf test/phx1_7_web/controllers/post_controller_test.exs
15 | rm -rf test/support/fixtures/
16 | rm -rf lib/phx1_7_web/components/layouts/torch.html.heex
17 | rm -rf lib/phx1_7_web/controllers/post_html.ex
18 | rm -rf lib/phx1_7_web/controllers/post_html/
19 |
20 | patch -i ../../patches/install-torch.diff -p 1 -R
21 | patch -i ../../patches/install-route.diff -p 1 -R
22 | }
23 |
24 | patch -i ../../patches/install-torch.diff -p 1
25 | mix deps.get || { cleanup; echo 'Dependencies could not be fetched!'; exit 1; }
26 | MIX_ENV=test mix ecto.drop || { cleanup; echo 'Database could not be dropped'; exit 1; }
27 | MIX_ENV=test mix torch.install || { cleanup; echo 'Torch could not be installed!'; exit 1; }
28 | MIX_ENV=test mix torch.gen.html Blog Post posts title:string published:boolean published_at:datetime views:integer || { echo 'Torch files not generated!'; exit 1; }
29 | patch -i ../../patches/install-route.diff -p 1
30 | MIX_ENV=test mix ecto.setup || { cleanup; echo 'Torch database could not be setup!'; exit 1; }
31 | MIX_ENV=test mix test || { echo 'Tests failed!'; cleanup; exit 1; }
32 |
33 | # Ensure that put_root_layout is used by default on > Phx 1.5
34 | if ! grep -q "plug(:put_root_layout" lib/phx1_7_web/controllers/post_controller.ex ; then
35 | echo 'Generated Phoenix controller not using `put_root_layout` syntax'
36 | cleanup
37 | exit 1;
38 | fi
39 |
40 | cleanup
41 |
42 | echo 'Tests succeeded!'
43 | exit 0
44 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/config/config.exs:
--------------------------------------------------------------------------------
1 | # This file is responsible for configuring your application
2 | # and its dependencies with the aid of the Config module.
3 | #
4 | # This configuration file is loaded before any dependency and
5 | # is restricted to this project.
6 |
7 | # General application configuration
8 | import Config
9 |
10 | config :phx1_7,
11 | ecto_repos: [Phx17.Repo]
12 |
13 | # Configures the endpoint
14 | config :phx1_7, Phx17Web.Endpoint,
15 | url: [host: "localhost"],
16 | render_errors: [
17 | formats: [html: Phx17Web.ErrorHTML, json: Phx17Web.ErrorJSON],
18 | layout: false
19 | ],
20 | pubsub_server: Phx17.PubSub,
21 | live_view: [signing_salt: "8b3KX+rn"]
22 |
23 | # Configures the mailer
24 | #
25 | # By default it uses the "Local" adapter which stores the emails
26 | # locally. You can see the emails in your browser, at "/dev/mailbox".
27 | #
28 | # For production it's recommended to configure a different adapter
29 | # at the `config/runtime.exs`.
30 | config :phx1_7, Phx17.Mailer, adapter: Swoosh.Adapters.Local
31 |
32 | # Configure esbuild (the version is required)
33 | config :esbuild,
34 | version: "0.14.41",
35 | default: [
36 | args:
37 | ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
38 | cd: Path.expand("../assets", __DIR__),
39 | env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
40 | ]
41 |
42 | # Configure tailwind (the version is required)
43 | config :tailwind,
44 | version: "3.2.4",
45 | default: [
46 | args: ~w(
47 | --config=tailwind.config.js
48 | --input=css/app.css
49 | --output=../priv/static/assets/app.css
50 | ),
51 | cd: Path.expand("../assets", __DIR__)
52 | ]
53 |
54 | # Configures Elixir's Logger
55 | config :logger, :console,
56 | format: "$time $metadata[$level] $message\n",
57 | metadata: [:request_id]
58 |
59 | # Use Jason for JSON parsing in Phoenix
60 | config :phoenix, :json_library, Jason
61 |
62 | # Import environment specific config. This must remain at the bottom
63 | # of this file so it overrides the configuration defined above.
64 | import_config "#{config_env()}.exs"
65 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/config/dev.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # Configure your database
4 | config :phx1_7, Phx17.Repo,
5 | username: "postgres",
6 | password: "postgres",
7 | hostname: "localhost",
8 | database: "phx1_7_dev",
9 | stacktrace: true,
10 | show_sensitive_data_on_connection_error: true,
11 | pool_size: 10
12 |
13 | # For development, we disable any cache and enable
14 | # debugging and code reloading.
15 | #
16 | # The watchers configuration can be used to run external
17 | # watchers to your application. For example, we use it
18 | # with esbuild to bundle .js and .css sources.
19 | config :phx1_7, Phx17Web.Endpoint,
20 | # Binding to loopback ipv4 address prevents access from other machines.
21 | # Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
22 | http: [ip: {127, 0, 0, 1}, port: 4000],
23 | check_origin: false,
24 | code_reloader: true,
25 | debug_errors: true,
26 | secret_key_base: "19IzTkNsmuimyLpuAG1foyIGCFGux/qM5o+9Po75mKTogJIXlKESYuliyjzqLDFD",
27 | watchers: [
28 | esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
29 | tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}
30 | ]
31 |
32 | # ## SSL Support
33 | #
34 | # In order to use HTTPS in development, a self-signed
35 | # certificate can be generated by running the following
36 | # Mix task:
37 | #
38 | # mix phx.gen.cert
39 | #
40 | # Run `mix help phx.gen.cert` for more information.
41 | #
42 | # The `http:` config above can be replaced with:
43 | #
44 | # https: [
45 | # port: 4001,
46 | # cipher_suite: :strong,
47 | # keyfile: "priv/cert/selfsigned_key.pem",
48 | # certfile: "priv/cert/selfsigned.pem"
49 | # ],
50 | #
51 | # If desired, both `http:` and `https:` keys can be
52 | # configured to run both http and https servers on
53 | # different ports.
54 |
55 | # Watch static and templates for browser reloading.
56 | config :phx1_7, Phx17Web.Endpoint,
57 | live_reload: [
58 | patterns: [
59 | ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
60 | ~r"priv/gettext/.*(po)$",
61 | ~r"lib/phx1_7_web/(controllers|live|components)/.*(ex|heex)$"
62 | ]
63 | ]
64 |
65 | # Enable dev routes for dashboard and mailbox
66 | config :phx1_7, dev_routes: true
67 |
68 | # Do not include metadata nor timestamps in development logs
69 | config :logger, :console, format: "[$level] $message\n"
70 |
71 | # Set a higher stacktrace during development. Avoid configuring such
72 | # in production as building large stacktraces may be expensive.
73 | config :phoenix, :stacktrace_depth, 20
74 |
75 | # Initialize plugs at runtime for faster development compilation
76 | config :phoenix, :plug_init_mode, :runtime
77 |
78 | # Disable swoosh api client as it is only required for production adapters.
79 | config :swoosh, :api_client, false
80 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/config/prod.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # For production, don't forget to configure the url host
4 | # to something meaningful, Phoenix uses this information
5 | # when generating URLs.
6 |
7 | # Note we also include the path to a cache manifest
8 | # containing the digested version of static files. This
9 | # manifest is generated by the `mix phx.digest` task,
10 | # which you should run after static files are built and
11 | # before starting your production server.
12 | config :phx1_7, Phx17Web.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json"
13 |
14 | # Configures Swoosh API Client
15 | config :swoosh, api_client: Swoosh.ApiClient.Finch, finch_name: Phx17.Finch
16 |
17 | # Do not print debug messages in production
18 | config :logger, level: :info
19 |
20 | # Runtime production configuration, including reading
21 | # of environment variables, is done on config/runtime.exs.
22 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/config/test.exs:
--------------------------------------------------------------------------------
1 | import Config
2 |
3 | # Configure your database
4 | #
5 | # The MIX_TEST_PARTITION environment variable can be used
6 | # to provide built-in test partitioning in CI environment.
7 | # Run `mix help test` for more information.
8 | config :phx1_7, Phx17.Repo,
9 | username: "postgres",
10 | password: "postgres",
11 | hostname: "localhost",
12 | database: "phx1_7_test#{System.get_env("MIX_TEST_PARTITION")}",
13 | pool: Ecto.Adapters.SQL.Sandbox,
14 | pool_size: 10
15 |
16 | # We don't run a server during test. If one is required,
17 | # you can enable the server option below.
18 | config :phx1_7, Phx17Web.Endpoint,
19 | http: [ip: {127, 0, 0, 1}, port: 4002],
20 | secret_key_base: "uYFVmobYDpSImRi+J3xTBoQkUKiSXLdFIKocI31psYeQna4iIaluILDsjFYa56h6",
21 | server: false
22 |
23 | # In test we don't send emails.
24 | config :phx1_7, Phx17.Mailer, adapter: Swoosh.Adapters.Test
25 |
26 | # Disable swoosh api client as it is only required for production adapters.
27 | config :swoosh, :api_client, false
28 |
29 | # Print only warnings and errors during test
30 | config :logger, level: :warning
31 |
32 | # Initialize plugs at runtime for faster test compilation
33 | config :phoenix, :plug_init_mode, :runtime
34 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17 do
2 | @moduledoc """
3 | Phx17 keeps the contexts that define your domain
4 | and business logic.
5 |
6 | Contexts are also responsible for managing your data, regardless
7 | if it comes from the database, an external API or others.
8 | """
9 | end
10 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7/application.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17.Application do
2 | # See https://hexdocs.pm/elixir/Application.html
3 | # for more information on OTP Applications
4 | @moduledoc false
5 |
6 | use Application
7 |
8 | @impl true
9 | def start(_type, _args) do
10 | children = [
11 | # Start the Telemetry supervisor
12 | Phx17Web.Telemetry,
13 | # Start the Ecto repository
14 | Phx17.Repo,
15 | # Start the PubSub system
16 | {Phoenix.PubSub, name: Phx17.PubSub},
17 | # Start Finch
18 | {Finch, name: Phx17.Finch},
19 | # Start the Endpoint (http/https)
20 | Phx17Web.Endpoint
21 | # Start a worker by calling: Phx17.Worker.start_link(arg)
22 | # {Phx17.Worker, arg}
23 | ]
24 |
25 | # See https://hexdocs.pm/elixir/Supervisor.html
26 | # for other strategies and supported options
27 | opts = [strategy: :one_for_one, name: Phx17.Supervisor]
28 | Supervisor.start_link(children, opts)
29 | end
30 |
31 | # Tell Phoenix to update the endpoint configuration
32 | # whenever the application is updated.
33 | @impl true
34 | def config_change(changed, _new, removed) do
35 | Phx17Web.Endpoint.config_change(changed, removed)
36 | :ok
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7/mailer.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17.Mailer do
2 | use Swoosh.Mailer, otp_app: :phx1_7
3 | end
4 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7/repo.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17.Repo do
2 | use Ecto.Repo,
3 | otp_app: :phx1_7,
4 | adapter: Ecto.Adapters.Postgres
5 | end
6 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web do
2 | @moduledoc """
3 | The entrypoint for defining your web interface, such
4 | as controllers, components, channels, and so on.
5 |
6 | This can be used in your application as:
7 |
8 | use Phx17Web, :controller
9 | use Phx17Web, :html
10 |
11 | The definitions below will be executed for every controller,
12 | component, etc, so keep them short and clean, focused
13 | on imports, uses and aliases.
14 |
15 | Do NOT define functions inside the quoted expressions
16 | below. Instead, define additional modules and import
17 | those modules here.
18 | """
19 |
20 | def static_paths, do: ~w(assets fonts images favicon.ico robots.txt)
21 |
22 | def router do
23 | quote do
24 | use Phoenix.Router, helpers: false
25 |
26 | # Import common connection and controller functions to use in pipelines
27 | import Plug.Conn
28 | import Phoenix.Controller
29 | import Phoenix.LiveView.Router
30 | end
31 | end
32 |
33 | def channel do
34 | quote do
35 | use Phoenix.Channel
36 | end
37 | end
38 |
39 | def controller do
40 | quote do
41 | use Phoenix.Controller,
42 | formats: [:html, :json],
43 | layouts: [html: Phx17Web.Layouts]
44 |
45 | import Plug.Conn
46 | import Phx17Web.Gettext
47 |
48 | unquote(verified_routes())
49 | end
50 | end
51 |
52 | def live_view do
53 | quote do
54 | use Phoenix.LiveView,
55 | layout: {Phx17Web.Layouts, :app}
56 |
57 | unquote(html_helpers())
58 | end
59 | end
60 |
61 | def live_component do
62 | quote do
63 | use Phoenix.LiveComponent
64 |
65 | unquote(html_helpers())
66 | end
67 | end
68 |
69 | def html do
70 | quote do
71 | use Phoenix.Component
72 |
73 | # Import convenience functions from controllers
74 | import Phoenix.Controller,
75 | only: [get_csrf_token: 0, view_module: 1, view_template: 1]
76 |
77 | # Include general helpers for rendering HTML
78 | unquote(html_helpers())
79 | end
80 | end
81 |
82 | defp html_helpers do
83 | quote do
84 | # HTML escaping functionality
85 | import Phoenix.HTML
86 | # Core UI components and translation
87 | import Phx17Web.CoreComponents
88 | import Phx17Web.Gettext
89 |
90 | # Shortcut for generating JS commands
91 | alias Phoenix.LiveView.JS
92 |
93 | # Routes generation with the ~p sigil
94 | unquote(verified_routes())
95 | end
96 | end
97 |
98 | def verified_routes do
99 | quote do
100 | use Phoenix.VerifiedRoutes,
101 | endpoint: Phx17Web.Endpoint,
102 | router: Phx17Web.Router,
103 | statics: Phx17Web.static_paths()
104 | end
105 | end
106 |
107 | @doc """
108 | When used, dispatch to the appropriate controller/view/etc.
109 | """
110 | defmacro __using__(which) when is_atom(which) do
111 | apply(__MODULE__, which, [])
112 | end
113 | end
114 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/components/layouts.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.Layouts do
2 | use Phx17Web, :html
3 |
4 | embed_templates "layouts/*"
5 | end
6 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/components/layouts/root.html.heex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | <.live_title suffix=" · Phoenix Framework">
8 | <%= assigns[:page_title] || "Phx17" %>
9 |
10 |
11 |
13 |
14 |
15 | <%= @inner_content %>
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/controllers/error_html.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.ErrorHTML do
2 | use Phx17Web, :html
3 |
4 | # If you want to customize your error pages,
5 | # uncomment the embed_templates/1 call below
6 | # and add pages to the error directory:
7 | #
8 | # * lib/phx1_7_web/controllers/error_html/404.html.heex
9 | # * lib/phx1_7_web/controllers/error_html/500.html.heex
10 | #
11 | # embed_templates "error_html/*"
12 |
13 | # The default is to render a plain text page based on
14 | # the template name. For example, "404.html" becomes
15 | # "Not Found".
16 | def render(template, _assigns) do
17 | Phoenix.Controller.status_message_from_template(template)
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/controllers/error_json.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.ErrorJSON do
2 | # If you want to customize a particular status code,
3 | # you may add your own clauses, such as:
4 | #
5 | # def render("500.json", _assigns) do
6 | # %{errors: %{detail: "Internal Server Error"}}
7 | # end
8 |
9 | # By default, Phoenix returns the status message from
10 | # the template name. For example, "404.json" becomes
11 | # "Not Found".
12 | def render(template, _assigns) do
13 | %{errors: %{detail: Phoenix.Controller.status_message_from_template(template)}}
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/controllers/page_controller.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.PageController do
2 | use Phx17Web, :controller
3 |
4 | def home(conn, _params) do
5 | # The home page is often custom made,
6 | # so skip the default app layout.
7 | render(conn, :home, layout: false)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/controllers/page_html.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.PageHTML do
2 | use Phx17Web, :html
3 |
4 | embed_templates "page_html/*"
5 | end
6 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/endpoint.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.Endpoint do
2 | use Phoenix.Endpoint, otp_app: :phx1_7
3 |
4 | # The session will be stored in the cookie and signed,
5 | # this means its contents can be read but not tampered with.
6 | # Set :encryption_salt if you would also like to encrypt it.
7 | @session_options [
8 | store: :cookie,
9 | key: "_phx1_7_key",
10 | signing_salt: "3jDgYIOc",
11 | same_site: "Lax"
12 | ]
13 |
14 | socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
15 |
16 | # Serve at "/" the static files from "priv/static" directory.
17 | #
18 | # You should set gzip to true if you are running phx.digest
19 | # when deploying your static files in production.
20 | plug Plug.Static,
21 | at: "/",
22 | from: :phx1_7,
23 | gzip: false,
24 | only: Phx17Web.static_paths()
25 |
26 | # Code reloading can be explicitly enabled under the
27 | # :code_reloader configuration of your endpoint.
28 | if code_reloading? do
29 | socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
30 | plug Phoenix.LiveReloader
31 | plug Phoenix.CodeReloader
32 | plug Phoenix.Ecto.CheckRepoStatus, otp_app: :phx1_7
33 | end
34 |
35 | plug Phoenix.LiveDashboard.RequestLogger,
36 | param_key: "request_logger",
37 | cookie_key: "request_logger"
38 |
39 | plug Plug.RequestId
40 | plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
41 |
42 | plug Plug.Parsers,
43 | parsers: [:urlencoded, :multipart, :json],
44 | pass: ["*/*"],
45 | json_decoder: Phoenix.json_library()
46 |
47 | plug Plug.MethodOverride
48 | plug Plug.Head
49 | plug Plug.Session, @session_options
50 | plug Phx17Web.Router
51 | end
52 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/gettext.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.Gettext do
2 | @moduledoc """
3 | A module providing Internationalization with a gettext-based API.
4 |
5 | By using [Gettext](https://hexdocs.pm/gettext),
6 | your module gains a set of macros for translations, for example:
7 |
8 | import Phx17Web.Gettext
9 |
10 | # Simple translation
11 | gettext("Here is the string to translate")
12 |
13 | # Plural translation
14 | ngettext("Here is the string to translate",
15 | "Here are the strings to translate",
16 | 3)
17 |
18 | # Domain-based translation
19 | dgettext("errors", "Here is the error message to translate")
20 |
21 | See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
22 | """
23 | use Gettext, otp_app: :phx1_7
24 | end
25 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/router.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.Router do
2 | use Phx17Web, :router
3 |
4 | pipeline :browser do
5 | plug :accepts, ["html"]
6 | plug :fetch_session
7 | plug :fetch_live_flash
8 | plug :put_root_layout, {Phx17Web.Layouts, :root}
9 | plug :protect_from_forgery
10 | plug :put_secure_browser_headers
11 | end
12 |
13 | pipeline :api do
14 | plug :accepts, ["json"]
15 | end
16 |
17 | scope "/", Phx17Web do
18 | pipe_through :browser
19 |
20 | get "/", PageController, :home
21 | end
22 |
23 | # Other scopes may use custom stacks.
24 | # scope "/api", Phx17Web do
25 | # pipe_through :api
26 | # end
27 |
28 | # Enable LiveDashboard and Swoosh mailbox preview in development
29 | if Application.compile_env(:phx1_7, :dev_routes) do
30 | # If you want to use the LiveDashboard in production, you should put
31 | # it behind authentication and allow only admins to access it.
32 | # If your application does not have an admins-only section yet,
33 | # you can use Plug.BasicAuth to set up some basic authentication
34 | # as long as you are also using SSL (which you should anyway).
35 | import Phoenix.LiveDashboard.Router
36 |
37 | scope "/dev" do
38 | pipe_through :browser
39 |
40 | live_dashboard "/dashboard", metrics: Phx17Web.Telemetry
41 | forward "/mailbox", Plug.Swoosh.MailboxPreview
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/router.ex.orig:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.Router do
2 | use Phx17Web, :router
3 |
4 | pipeline :browser do
5 | plug :accepts, ["html"]
6 | plug :fetch_session
7 | plug :fetch_live_flash
8 | plug :put_root_layout, {Phx17Web.Layouts, :root}
9 | plug :protect_from_forgery
10 | plug :put_secure_browser_headers
11 | end
12 |
13 | pipeline :api do
14 | plug :accepts, ["json"]
15 | end
16 |
17 | scope "/", Phx17Web do
18 | pipe_through :browser
19 |
20 | get "/", PageController, :home
21 | end
22 |
23 | # Other scopes may use custom stacks.
24 | # scope "/api", Phx17Web do
25 | # pipe_through :api
26 | # end
27 |
28 | # Enable LiveDashboard and Swoosh mailbox preview in development
29 | if Application.compile_env(:phx1_7, :dev_routes) do
30 | # If you want to use the LiveDashboard in production, you should put
31 | # it behind authentication and allow only admins to access it.
32 | # If your application does not have an admins-only section yet,
33 | # you can use Plug.BasicAuth to set up some basic authentication
34 | # as long as you are also using SSL (which you should anyway).
35 | import Phoenix.LiveDashboard.Router
36 |
37 | scope "/dev" do
38 | pipe_through :browser
39 |
40 | live_dashboard "/dashboard", metrics: Phx17Web.Telemetry
41 | forward "/mailbox", Plug.Swoosh.MailboxPreview
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/lib/phx1_7_web/telemetry.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.Telemetry do
2 | use Supervisor
3 | import Telemetry.Metrics
4 |
5 | def start_link(arg) do
6 | Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
7 | end
8 |
9 | @impl true
10 | def init(_arg) do
11 | children = [
12 | # Telemetry poller will execute the given period measurements
13 | # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
14 | {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
15 | # Add reporters as children of your supervision tree.
16 | # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
17 | ]
18 |
19 | Supervisor.init(children, strategy: :one_for_one)
20 | end
21 |
22 | def metrics do
23 | [
24 | # Phoenix Metrics
25 | summary("phoenix.endpoint.start.system_time",
26 | unit: {:native, :millisecond}
27 | ),
28 | summary("phoenix.endpoint.stop.duration",
29 | unit: {:native, :millisecond}
30 | ),
31 | summary("phoenix.router_dispatch.start.system_time",
32 | tags: [:route],
33 | unit: {:native, :millisecond}
34 | ),
35 | summary("phoenix.router_dispatch.exception.duration",
36 | tags: [:route],
37 | unit: {:native, :millisecond}
38 | ),
39 | summary("phoenix.router_dispatch.stop.duration",
40 | tags: [:route],
41 | unit: {:native, :millisecond}
42 | ),
43 | summary("phoenix.socket_connected.duration",
44 | unit: {:native, :millisecond}
45 | ),
46 | summary("phoenix.channel_join.duration",
47 | unit: {:native, :millisecond}
48 | ),
49 | summary("phoenix.channel_handled_in.duration",
50 | tags: [:event],
51 | unit: {:native, :millisecond}
52 | ),
53 |
54 | # Database Metrics
55 | summary("phx1_7.repo.query.total_time",
56 | unit: {:native, :millisecond},
57 | description: "The sum of the other measurements"
58 | ),
59 | summary("phx1_7.repo.query.decode_time",
60 | unit: {:native, :millisecond},
61 | description: "The time spent decoding the data received from the database"
62 | ),
63 | summary("phx1_7.repo.query.query_time",
64 | unit: {:native, :millisecond},
65 | description: "The time spent executing the query"
66 | ),
67 | summary("phx1_7.repo.query.queue_time",
68 | unit: {:native, :millisecond},
69 | description: "The time spent waiting for a database connection"
70 | ),
71 | summary("phx1_7.repo.query.idle_time",
72 | unit: {:native, :millisecond},
73 | description:
74 | "The time the connection spent waiting before being checked out for the query"
75 | ),
76 |
77 | # VM Metrics
78 | summary("vm.memory.total", unit: {:byte, :kilobyte}),
79 | summary("vm.total_run_queue_lengths.total"),
80 | summary("vm.total_run_queue_lengths.cpu"),
81 | summary("vm.total_run_queue_lengths.io")
82 | ]
83 | end
84 |
85 | defp periodic_measurements do
86 | [
87 | # A module, function and arguments to be invoked periodically.
88 | # This function must call :telemetry.execute/3 and a metric must be added above.
89 | # {Phx17Web, :count_users, []}
90 | ]
91 | end
92 | end
93 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule Phx17.MixProject do
2 | use Mix.Project
3 |
4 | def project do
5 | [
6 | app: :phx1_7,
7 | version: "0.1.0",
8 | elixir: "~> 1.14",
9 | elixirc_paths: elixirc_paths(Mix.env()),
10 | start_permanent: Mix.env() == :prod,
11 | aliases: aliases(),
12 | deps: deps()
13 | ]
14 | end
15 |
16 | # Configuration for the OTP application.
17 | #
18 | # Type `mix help compile.app` for more information.
19 | def application do
20 | [
21 | mod: {Phx17.Application, []},
22 | extra_applications: [:logger, :runtime_tools]
23 | ]
24 | end
25 |
26 | # Specifies which paths to compile per environment.
27 | defp elixirc_paths(:test), do: ["lib", "test/support"]
28 | defp elixirc_paths(_), do: ["lib"]
29 |
30 | # Specifies your project dependencies.
31 | #
32 | # Type `mix help deps` for examples and options.
33 | defp deps do
34 | [
35 | {:phoenix, "~> 1.7"},
36 | {:phoenix_ecto, "~> 4.6"},
37 | {:ecto_sql, "~> 3.6"},
38 | {:postgrex, ">= 0.0.0"},
39 | {:phoenix_html, "~> 4.0"},
40 | {:phoenix_html_helpers, "~> 1.0"},
41 | {:phoenix_live_reload, "~> 1.2", only: :dev},
42 | {:phoenix_live_view, "~> 1.0"},
43 | {:heroicons, "~> 0.5"},
44 | {:floki, ">= 0.37.0", only: :test},
45 | {:phoenix_live_dashboard, "~> 0.8.6"},
46 | {:esbuild, "~> 0.5", runtime: Mix.env() == :dev},
47 | {:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev},
48 | {:swoosh, "~> 1.3"},
49 | {:finch, "~> 0.13"},
50 | {:telemetry_metrics, "~> 0.6"},
51 | {:telemetry_poller, "~> 1.0"},
52 | {:gettext, "~> 0.20"},
53 | {:jason, "~> 1.2"},
54 | {:plug_cowboy, "~> 2.5"}
55 | ]
56 | end
57 |
58 | # Aliases are shortcuts or tasks specific to the current project.
59 | # For example, to install project dependencies and perform other setup tasks, run:
60 | #
61 | # $ mix setup
62 | #
63 | # See the documentation for `Mix` for more info on aliases.
64 | defp aliases do
65 | [
66 | setup: ["deps.get", "ecto.setup", "assets.setup", "assets.build"],
67 | "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
68 | "ecto.reset": ["ecto.drop", "ecto.setup"],
69 | test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
70 | "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
71 | "assets.build": ["tailwind default", "esbuild default"],
72 | "assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]
73 | ]
74 | end
75 | end
76 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/priv/gettext/en/LC_MESSAGES/errors.po:
--------------------------------------------------------------------------------
1 | ## `msgid`s in this file come from POT (.pot) files.
2 | ##
3 | ## Do not add, change, or remove `msgid`s manually here as
4 | ## they're tied to the ones in the corresponding POT file
5 | ## (with the same domain).
6 | ##
7 | ## Use `mix gettext.extract --merge` or `mix gettext.merge`
8 | ## to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: en\n"
12 |
13 | ## From Ecto.Changeset.cast/4
14 | msgid "can't be blank"
15 | msgstr ""
16 |
17 | ## From Ecto.Changeset.unique_constraint/3
18 | msgid "has already been taken"
19 | msgstr ""
20 |
21 | ## From Ecto.Changeset.put_change/3
22 | msgid "is invalid"
23 | msgstr ""
24 |
25 | ## From Ecto.Changeset.validate_acceptance/3
26 | msgid "must be accepted"
27 | msgstr ""
28 |
29 | ## From Ecto.Changeset.validate_format/3
30 | msgid "has invalid format"
31 | msgstr ""
32 |
33 | ## From Ecto.Changeset.validate_subset/3
34 | msgid "has an invalid entry"
35 | msgstr ""
36 |
37 | ## From Ecto.Changeset.validate_exclusion/3
38 | msgid "is reserved"
39 | msgstr ""
40 |
41 | ## From Ecto.Changeset.validate_confirmation/3
42 | msgid "does not match confirmation"
43 | msgstr ""
44 |
45 | ## From Ecto.Changeset.no_assoc_constraint/3
46 | msgid "is still associated with this entry"
47 | msgstr ""
48 |
49 | msgid "are still associated with this entry"
50 | msgstr ""
51 |
52 | ## From Ecto.Changeset.validate_length/3
53 | msgid "should have %{count} item(s)"
54 | msgid_plural "should have %{count} item(s)"
55 | msgstr[0] ""
56 | msgstr[1] ""
57 |
58 | msgid "should be %{count} character(s)"
59 | msgid_plural "should be %{count} character(s)"
60 | msgstr[0] ""
61 | msgstr[1] ""
62 |
63 | msgid "should be %{count} byte(s)"
64 | msgid_plural "should be %{count} byte(s)"
65 | msgstr[0] ""
66 | msgstr[1] ""
67 |
68 | msgid "should have at least %{count} item(s)"
69 | msgid_plural "should have at least %{count} item(s)"
70 | msgstr[0] ""
71 | msgstr[1] ""
72 |
73 | msgid "should be at least %{count} character(s)"
74 | msgid_plural "should be at least %{count} character(s)"
75 | msgstr[0] ""
76 | msgstr[1] ""
77 |
78 | msgid "should be at least %{count} byte(s)"
79 | msgid_plural "should be at least %{count} byte(s)"
80 | msgstr[0] ""
81 | msgstr[1] ""
82 |
83 | msgid "should have at most %{count} item(s)"
84 | msgid_plural "should have at most %{count} item(s)"
85 | msgstr[0] ""
86 | msgstr[1] ""
87 |
88 | msgid "should be at most %{count} character(s)"
89 | msgid_plural "should be at most %{count} character(s)"
90 | msgstr[0] ""
91 | msgstr[1] ""
92 |
93 | msgid "should be at most %{count} byte(s)"
94 | msgid_plural "should be at most %{count} byte(s)"
95 | msgstr[0] ""
96 | msgstr[1] ""
97 |
98 | ## From Ecto.Changeset.validate_number/3
99 | msgid "must be less than %{number}"
100 | msgstr ""
101 |
102 | msgid "must be greater than %{number}"
103 | msgstr ""
104 |
105 | msgid "must be less than or equal to %{number}"
106 | msgstr ""
107 |
108 | msgid "must be greater than or equal to %{number}"
109 | msgstr ""
110 |
111 | msgid "must be equal to %{number}"
112 | msgstr ""
113 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/priv/gettext/errors.pot:
--------------------------------------------------------------------------------
1 | ## This is a PO Template file.
2 | ##
3 | ## `msgid`s here are often extracted from source code.
4 | ## Add new translations manually only if they're dynamic
5 | ## translations that can't be statically extracted.
6 | ##
7 | ## Run `mix gettext.extract` to bring this file up to
8 | ## date. Leave `msgstr`s empty as changing them here has no
9 | ## effect: edit them in PO (`.po`) files instead.
10 |
11 | ## From Ecto.Changeset.cast/4
12 | msgid "can't be blank"
13 | msgstr ""
14 |
15 | ## From Ecto.Changeset.unique_constraint/3
16 | msgid "has already been taken"
17 | msgstr ""
18 |
19 | ## From Ecto.Changeset.put_change/3
20 | msgid "is invalid"
21 | msgstr ""
22 |
23 | ## From Ecto.Changeset.validate_acceptance/3
24 | msgid "must be accepted"
25 | msgstr ""
26 |
27 | ## From Ecto.Changeset.validate_format/3
28 | msgid "has invalid format"
29 | msgstr ""
30 |
31 | ## From Ecto.Changeset.validate_subset/3
32 | msgid "has an invalid entry"
33 | msgstr ""
34 |
35 | ## From Ecto.Changeset.validate_exclusion/3
36 | msgid "is reserved"
37 | msgstr ""
38 |
39 | ## From Ecto.Changeset.validate_confirmation/3
40 | msgid "does not match confirmation"
41 | msgstr ""
42 |
43 | ## From Ecto.Changeset.no_assoc_constraint/3
44 | msgid "is still associated with this entry"
45 | msgstr ""
46 |
47 | msgid "are still associated with this entry"
48 | msgstr ""
49 |
50 | ## From Ecto.Changeset.validate_length/3
51 | msgid "should have %{count} item(s)"
52 | msgid_plural "should have %{count} item(s)"
53 | msgstr[0] ""
54 | msgstr[1] ""
55 |
56 | msgid "should be %{count} character(s)"
57 | msgid_plural "should be %{count} character(s)"
58 | msgstr[0] ""
59 | msgstr[1] ""
60 |
61 | msgid "should be %{count} byte(s)"
62 | msgid_plural "should be %{count} byte(s)"
63 | msgstr[0] ""
64 | msgstr[1] ""
65 |
66 | msgid "should have at least %{count} item(s)"
67 | msgid_plural "should have at least %{count} item(s)"
68 | msgstr[0] ""
69 | msgstr[1] ""
70 |
71 | msgid "should be at least %{count} character(s)"
72 | msgid_plural "should be at least %{count} character(s)"
73 | msgstr[0] ""
74 | msgstr[1] ""
75 |
76 | msgid "should be at least %{count} byte(s)"
77 | msgid_plural "should be at least %{count} byte(s)"
78 | msgstr[0] ""
79 | msgstr[1] ""
80 |
81 | msgid "should have at most %{count} item(s)"
82 | msgid_plural "should have at most %{count} item(s)"
83 | msgstr[0] ""
84 | msgstr[1] ""
85 |
86 | msgid "should be at most %{count} character(s)"
87 | msgid_plural "should be at most %{count} character(s)"
88 | msgstr[0] ""
89 | msgstr[1] ""
90 |
91 | msgid "should be at most %{count} byte(s)"
92 | msgid_plural "should be at most %{count} byte(s)"
93 | msgstr[0] ""
94 | msgstr[1] ""
95 |
96 | ## From Ecto.Changeset.validate_number/3
97 | msgid "must be less than %{number}"
98 | msgstr ""
99 |
100 | msgid "must be greater than %{number}"
101 | msgstr ""
102 |
103 | msgid "must be less than or equal to %{number}"
104 | msgstr ""
105 |
106 | msgid "must be greater than or equal to %{number}"
107 | msgstr ""
108 |
109 | msgid "must be equal to %{number}"
110 | msgstr ""
111 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/priv/repo/migrations/.formatter.exs:
--------------------------------------------------------------------------------
1 | [
2 | import_deps: [:ecto_sql],
3 | inputs: ["*.exs"]
4 | ]
5 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/priv/repo/seeds.exs:
--------------------------------------------------------------------------------
1 | # Script for populating the database. You can run it as:
2 | #
3 | # mix run priv/repo/seeds.exs
4 | #
5 | # Inside the script, you can read and write to any of your
6 | # repositories directly:
7 | #
8 | # Phx17.Repo.insert!(%Phx17.SomeSchema{})
9 | #
10 | # We recommend using the bang functions (`insert!`, `update!`
11 | # and so on) as they will fail if something goes wrong.
12 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/priv/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mojotech/torch/26ac2f942d7ab89cf2cd27caa01d3b11340540f8/test/support/apps/phx1_7/priv/static/favicon.ico
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/priv/static/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/test/phx1_7_web/controllers/error_html_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.ErrorHTMLTest do
2 | use Phx17Web.ConnCase, async: true
3 |
4 | # Bring render_to_string/4 for testing custom views
5 | import Phoenix.Template
6 |
7 | test "renders 404.html" do
8 | assert render_to_string(Phx17Web.ErrorHTML, "404", "html", []) == "Not Found"
9 | end
10 |
11 | test "renders 500.html" do
12 | assert render_to_string(Phx17Web.ErrorHTML, "500", "html", []) == "Internal Server Error"
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/test/phx1_7_web/controllers/error_json_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.ErrorJSONTest do
2 | use Phx17Web.ConnCase, async: true
3 |
4 | test "renders 404" do
5 | assert Phx17Web.ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}}
6 | end
7 |
8 | test "renders 500" do
9 | assert Phx17Web.ErrorJSON.render("500.json", %{}) ==
10 | %{errors: %{detail: "Internal Server Error"}}
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/test/phx1_7_web/controllers/page_controller_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.PageControllerTest do
2 | use Phx17Web.ConnCase
3 |
4 | test "GET /", %{conn: conn} do
5 | conn = get(conn, ~p"/")
6 | assert html_response(conn, 200) =~ "Peace of mind from prototype to production"
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/test/support/conn_case.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17Web.ConnCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | tests that require setting up a connection.
5 |
6 | Such tests rely on `Phoenix.ConnTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | we enable the SQL sandbox, so changes done to the database
12 | are reverted at the end of every test. If you are using
13 | PostgreSQL, you can even run database tests asynchronously
14 | by setting `use Phx17Web.ConnCase, async: true`, although
15 | this option is not recommended for other databases.
16 | """
17 |
18 | use ExUnit.CaseTemplate
19 |
20 | using do
21 | quote do
22 | # The default endpoint for testing
23 | @endpoint Phx17Web.Endpoint
24 |
25 | use Phx17Web, :verified_routes
26 |
27 | # Import conveniences for testing with connections
28 | import Plug.Conn
29 | import Phoenix.ConnTest
30 | import Phx17Web.ConnCase
31 | end
32 | end
33 |
34 | setup tags do
35 | Phx17.DataCase.setup_sandbox(tags)
36 | {:ok, conn: Phoenix.ConnTest.build_conn()}
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/test/support/data_case.ex:
--------------------------------------------------------------------------------
1 | defmodule Phx17.DataCase do
2 | @moduledoc """
3 | This module defines the setup for tests requiring
4 | access to the application's data layer.
5 |
6 | You may define functions here to be used as helpers in
7 | your tests.
8 |
9 | Finally, if the test case interacts with the database,
10 | we enable the SQL sandbox, so changes done to the database
11 | are reverted at the end of every test. If you are using
12 | PostgreSQL, you can even run database tests asynchronously
13 | by setting `use Phx17.DataCase, async: true`, although
14 | this option is not recommended for other databases.
15 | """
16 |
17 | use ExUnit.CaseTemplate
18 |
19 | using do
20 | quote do
21 | alias Phx17.Repo
22 |
23 | import Ecto
24 | import Ecto.Changeset
25 | import Ecto.Query
26 | import Phx17.DataCase
27 | end
28 | end
29 |
30 | setup tags do
31 | Phx17.DataCase.setup_sandbox(tags)
32 | :ok
33 | end
34 |
35 | @doc """
36 | Sets up the sandbox based on the test tags.
37 | """
38 | def setup_sandbox(tags) do
39 | pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Phx17.Repo, shared: not tags[:async])
40 | on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
41 | end
42 |
43 | @doc """
44 | A helper that transforms changeset errors into a map of messages.
45 |
46 | assert {:error, changeset} = Accounts.create_user(%{password: "short"})
47 | assert "password is too short" in errors_on(changeset).password
48 | assert %{password: ["password is too short"]} = errors_on(changeset)
49 |
50 | """
51 | def errors_on(changeset) do
52 | Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
53 | Regex.replace(~r"%{(\w+)}", message, fn _, key ->
54 | opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
55 | end)
56 | end)
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/test/support/apps/phx1_7/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 | Ecto.Adapters.SQL.Sandbox.mode(Phx17.Repo, :manual)
3 |
--------------------------------------------------------------------------------
/test/support/cases/mix_case.ex:
--------------------------------------------------------------------------------
1 | defmodule Torch.MixCase do
2 | @moduledoc false
3 |
4 | use ExUnit.CaseTemplate
5 |
6 | using do
7 | quote do
8 | import Torch.MixCase
9 | end
10 | end
11 |
12 | @doc false
13 | # Generates tests on the given mix task to ensure it handles errors properly
14 | defmacro test_mix_config_errors(task) do
15 | quote location: :keep do
16 | test "raises error if :otp_app not specified" do
17 | assert_raise Mix.Error,
18 | """
19 | You need to specify an OTP app to generate files within. Either
20 | configure it as shown below or pass it in via the `--app` option.
21 |
22 | config :torch,
23 | otp_app: :my_app
24 |
25 | # Alternatively
26 | mix #{unquote(task)} --app my_app
27 | """,
28 | fn ->
29 | Mix.Task.rerun(unquote(task), ["--format", "eex"])
30 | end
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/test/support/patches/install-route.diff:
--------------------------------------------------------------------------------
1 | diff --git a/lib/phx1_7_web/router.ex b/lib/phx1_7_web/router.ex
2 | index 437a6d3..5625ebb 100644
3 | --- a/lib/phx1_7_web/router.ex
4 | +++ b/lib/phx1_7_web/router.ex
5 | @@ -18,6 +18,7 @@ defmodule Phx17Web.Router do
6 | pipe_through :browser
7 |
8 | get "/", PageController, :home
9 | + resources "/posts", PostController
10 | end
11 |
12 | # Other scopes may use custom stacks.
13 |
--------------------------------------------------------------------------------
/test/support/patches/install-torch.diff:
--------------------------------------------------------------------------------
1 | diff --git a/config/config.exs b/config/config.exs
2 | index f58eb52..a3022e3 100644
3 | --- a/config/config.exs
4 | +++ b/config/config.exs
5 | @@ -59,6 +59,9 @@ config :logger, :console,
6 | # Use Jason for JSON parsing in Phoenix
7 | config :phoenix, :json_library, Jason
8 |
9 | +config :torch,
10 | + otp_app: :phx1_7
11 | +
12 | # Import environment specific config. This must remain at the bottom
13 | # of this file so it overrides the configuration defined above.
14 | import_config "#{config_env()}.exs"
15 | diff --git a/lib/phx1_7_web/endpoint.ex b/lib/phx1_7_web/endpoint.ex
16 | index 622d5e1..804a311 100644
17 | --- a/lib/phx1_7_web/endpoint.ex
18 | +++ b/lib/phx1_7_web/endpoint.ex
19 | @@ -23,6 +23,12 @@ defmodule Phx17Web.Endpoint do
20 | gzip: false,
21 | only: Phx17Web.static_paths()
22 |
23 | + plug Plug.Static,
24 | + at: "/torch",
25 | + from: {:torch, "priv/static"},
26 | + gzip: true,
27 | + cache_control_for_etags: "public, max-age=86400"
28 | +
29 | # Code reloading can be explicitly enabled under the
30 | # :code_reloader configuration of your endpoint.
31 | if code_reloading? do
32 | diff --git a/mix.exs b/mix.exs
33 | index 34ce721..257007a 100644
34 | --- a/mix.exs
35 | +++ b/mix.exs
36 | @@ -51,6 +51,8 @@ defmodule Phx17.MixProject do
37 | {:telemetry_poller, "~> 1.0"},
38 | {:gettext, "~> 0.20"},
39 | {:jason, "~> 1.2"},
40 | - {:plug_cowboy, "~> 2.5"}
41 | + {:plug_cowboy, "~> 2.5"},
42 | + {:ssl_verify_fun, manager: :rebar3, runtime: false, override: true},
43 | + {:torch, path: "../../../../"}
44 | ]
45 | end
46 |
--------------------------------------------------------------------------------
/test/torch/helpers_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Torch.HelpersTest do
2 | use ExUnit.Case, async: true
3 |
4 | doctest Torch.Helpers, import: true
5 | end
6 |
--------------------------------------------------------------------------------
/test/torch/i18n_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Torch.I18nTest do
2 | use ExUnit.Case
3 |
4 | defmodule CustomI18nBackend do
5 | def message("Contains"), do: "** CUSTOMIZED **"
6 | def message(t), do: Torch.I18n.Backend.message(t)
7 | end
8 |
9 | setup_all do
10 | on_exit(fn ->
11 | Application.put_env(:torch, :i18n_backend, Torch.I18n.Backend)
12 | end)
13 |
14 | [i18n_backend: Torch.Config.i18n_backend()]
15 | end
16 |
17 | test "uses a default backend if none configured", context do
18 | Application.put_env(:torch, :i18n_backend, context[:i18n_backend])
19 |
20 | assert Torch.I18n.Backend == Torch.Config.i18n_backend()
21 | assert "Contains" == Torch.I18n.message("Contains")
22 | end
23 |
24 | test "allows a custom backend to be defined" do
25 | Application.put_env(:torch, :i18n_backend, CustomI18nBackend)
26 |
27 | assert CustomI18nBackend == Torch.Config.i18n_backend()
28 | assert "** CUSTOMIZED **" == Torch.I18n.message("Contains")
29 | assert "Equals" == Torch.I18n.message("Equals")
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/test/torch/test_helper.exs:
--------------------------------------------------------------------------------
1 | if System.get_env("CI") do
2 | ExUnit.configure(formatters: [ExUnit.CLIFormatter])
3 | else
4 | ExUnit.configure(formatters: [ExUnit.CLIFormatter, ExUnitNotifier])
5 | end
6 |
7 | ExUnit.start()
8 |
--------------------------------------------------------------------------------
/test/torch/torch_test.exs:
--------------------------------------------------------------------------------
1 | defmodule TorchTest do
2 | use ExUnit.Case
3 |
4 | doctest Torch
5 | end
6 |
--------------------------------------------------------------------------------
/test/torch/views/flash_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Torch.FlashViewTest do
2 | use ExUnit.Case
3 |
4 | doctest Torch.FlashView, import: true
5 | end
6 |
--------------------------------------------------------------------------------
/test/torch/views/page_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Torch.PageViewTest do
2 | use ExUnit.Case
3 |
4 | doctest Torch.PageView, import: true
5 | end
6 |
--------------------------------------------------------------------------------
/test/torch/views/table_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule Torch.TableViewTest do
2 | use ExUnit.Case
3 |
4 | import Phoenix.HTML, only: [safe_to_string: 1]
5 |
6 | doctest Torch.TableView, import: true
7 | end
8 |
--------------------------------------------------------------------------------