diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000000..080112a89a8 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,6 @@ +[report] +exclude_lines = + pragma: no cover + raise NotImplementedError + if TYPE_CHECKING: + if typing.TYPE_CHECKING: diff --git a/.cspell.json b/.cspell.json new file mode 100644 index 00000000000..37c86e11d7b --- /dev/null +++ b/.cspell.json @@ -0,0 +1,730 @@ +{ + "version": "0.2", + "language": "en", + "allowCompoundWords": true, + "ignorePaths": [ + "dashboard/node_modules", + "**/assets", + "*.json", + "**.jinja2", + "**.j2", + "**.service", + "**.yml", + "test_**", + "**.conf", + "requirements.txt", + "press/utils/country_timezone.py" + ], + "words": [ + "2.4.6", + "Aaiun", + "Ababa", + "Adak", + "adblockers", + "Addis", + "aditya", + "Adminstrator", + "aescts", + "afero", + "Agejt", + "aggs", + "Ajkr", + "Akbary", + "Akts", + "Åland", + "Anadyr", + "Andhra", + "ansari", + "Aqtau", + "Aqtobe", + "Araguaina", + "Arunachal", + "Asmera", + "asmfmt", + "asname", + "asrc", + "ATEXT", + "athul", + "Atikokan", + "Atka", + "atleast", + "atotto", + "Atyrau", + "auid", + "awalsh", + "awwzvf", + "aymanbagabas", + "backgound", + "Baja", + "Balamurali", + "Barthelemy", + "Barthélemy", + "Bator", + "behavior", + "behaviour", + "benbjohnson", + "BENTO", + "binlog", + "biosdevname", + "blkid", + "bofq", + "boto", + "Bouvet", + "bouy", + "buildx", + "Busingen", + "Cabo", + "CCONTENT", + "cellbuf", + "cellbug", + "CFWS", + "chdir", + "Chhattisgarh", + "Choibalsan", + "Chuuk", + "chzyer", + "cidata", + "cint", + "clamav", + "clas", + "cli", + "cloudimg", + "CMDLINE", + "CNAME", + "cnsistency", + "CODECOV", + "codespell", + "cofig", + "commitlint", + "Comod", + "COMPATBILITY", + "confs", + "Consolas", + "Containerised", + "coveragerc", + "cpath", + "cpcommerce", + "cpuid", + "cpus", + "creat", + "creds", + "Creston", + "CSpell: Files checked: 14, Issues found: 124 in 2 files.", + "Csvg", + "csvg", + "CTEXT", + "CTPBJ", + "Cuiaba", + "Cunha", + "cust", + "Dacca", + "Dadra", + "Danmarkshavn", + "Darkify", + "dateutil", + "davecgh", + "DAYOFMONTH", + "DAYOFWEEK", + "DAYOFYEAR", + "dbgsym", + "dboptimize", + "dbserver", + "DBUS", + "dcbs", + "DCONTENT", + "ddeb", + "ddebs", + "dearmor", + "devscripts", + "devtmpfs", + "dffx", + "Dgzr", + "Dili", + "dmypy", + "DNOQOHHMYYI", + "dnsmasq", + "dnspython", + "dnsutils", + "doesnt", + "dont", + "DONTNEED", + "dpkg", + "dribbble", + "DSEes", + "DTEXT", + "duckdb", + "DUID", + "Dumont", + "EACCES", + "earlyoom", + "ecommerce", + "EDITMSG", + "Efate", + "efi", + "EHIKF", + "Eirunepe", + "elif", + "elts", + "emaill", + "Ensenada", + "EPERM", + "equivs", + "erikgeiser", + "erpdb", + "erpnext", + "erpnextcom", + "erpnextsmb", + "errgo", + "Eswatini", + "Eucla", + "euid", + "EVHT", + "execv", + "execve", + "exitst", + "Exlude", + "FADV", + "Fakaofo", + "faris", + "Faso", + "fchmod", + "fchmodat", + "fchown", + "fchownat", + "fcrestore", + "Fdvmq", + "FEFF", + "Fffphu", + "filippo", + "Fmbeo", + "Fpww", + "frappeclient", + "frappehr", + "Frappeio", + "frappeui", + "fremovexattr", + "fsetxattr", + "fstype", + "ftrace", + "ftruncate", + "Fung", + "FWUP", + "Fzqt", + "gcore", + "Gekx", + "genproto", + "getdate", + "getitimer", + "gget", + "ghaction", + "ghead", + "githubusercontent", + "glfw", + "glog", + "gmxxxxcom", + "gnueabi", + "GOARCH", + "goasm", + "goccy", + "godebug", + "gofork", + "goidentity", + "gokrb", + "goleak", + "gonum", + "gopkg", + "gotool", + "Gozu", + "Gqttikk", + "grequests", + "gshadow", + "GSSAPI", + "gstin", + "gstinhide", + "gstinshow", + "gtid", + "gunicorn", + "gxzc", + "hakanensari", + "Haryana", + "hase", + "Haveli", + "hdel", + "hdfs", + "hget", + "Himachal", + "honnef", + "hookpy", + "Hovd", + "hrms", + "hrtimers", + "hset", + "hsts", + "htpasswd", + "Hvyanc", + "ibdata", + "Ibhfb", + "ibtmp", + "iceber", + "ifaces", + "Ifalt", + "ifnames", + "ifnull", + "IGST", + "ikxn", + "ILIKE", + "imds", + "Incase", + "innodb", + "innoterra", + "inodes", + "inplace", + "interactjs", + "interner", + "Inuvik", + "invs", + "iour", + "iowait", + "ipaddress", + "IPEYBICE", + "iputils", + "ipython", + "IRET", + "isatty", + "isin", + "isnotnull", + "istable", + "ITIMER", + "Jammu", + "jcmturner", + "jemalloc", + "Jharkhand", + "Jhuj", + "jmespath", + "JMWS", + "Jnsl", + "joomla", + "joxit", + "jscache", + "jsons", + "jstemmer", + "Jujuy", + "JZNG", + "Karnataka", + "kcontinue", + "kdhz", + "KGUJ", + "Khandyga", + "KHTML", + "Kiritimati", + "kisielk", + "Kitts", + "Kolkata", + "kontinue", + "Kralendijk", + "Kuala", + "Kvsc", + "kwarg", + "kwargs", + "Ladakh", + "Lakshadweep", + "Latrh", + "lchown", + "Leste", + "libc", + "libdevel", + "libharfbuzz", + "libpango", + "libpangocairo", + "libsm", + "libstdc", + "libx", + "libxcb", + "libxext", + "libxmuu", + "libxrender", + "Lindeman", + "llen", + "localds", + "logex", + "Longyearbyen", + "LOUAA", + "lpush", + "lqez", + "lrange", + "lremovexattr", + "lsetxattr", + "lucasb", + "Lumpur", + "luxon", + "Maarten", + "Madhya", + "MADKY", + "Mahe", + "makeprg", + "marcboeker", + "MARIADB", + "mariadbd", + "Marino", + "Marketpalce", + "mattn", + "Mayen", + "mbps", + "mccabe", + "Meghalaya", + "Menlo", + "mergify", + "Metlakatla", + "mhpd", + "Mhsc", + "Minh", + "missingok", + "Mizoram", + "mkdir", + "mkisofs", + "Mmckchk", + "mname", + "momentjs", + "Moresby", + "moto", + "Mpesa", + "msgprint", + "msisdn", + "Mtay", + "muieblackcat", + "Murdo", + "mxschmitt", + "myadmin", + "Mycp", + "myisam", + "mypma", + "mypy", + "mysqladmin", + "mysqld", + "mysqldb", + "Mywk", + "Nadu", + "Nagar", + "ncdu", + "nedded", + "NEFT", + "Nera", + "netcfg", + "NFKH", + "NGROK", + "nineth", + "Nipigon", + "nistp", + "njsproj", + "nocompress", + "nofail", + "NOFORK", + "noozm", + "NOPASSWD", + "Noronha", + "Norte", + "notifempty", + "notin", + "nqhxc", + "ntfs", + "ntvs", + "Nuuk", + "nvme", + "Nxzjr", + "objx", + "Occurred", + "OCI", + "ocpu", + "ocpus", + "ocsp", + "Odisha", + "Ojinaga", + "Olgu", + "OLQY", + "onfail", + "oom", + "opasswd", + "OPENBLAS", + "opions", + "overriden", + "OWUVXXW", + "oxxk", + "Paasphrase", + "packagejsons", + "Pago", + "paise", + "Pangnirtung", + "paramiko", + "parentfield", + "parenttype", + "pborman", + "pckj", + "pckjs", + "Pedning", + "Pesa", + "pexpect", + "pfiles", + "pflag", + "Pfrw", + "pgrep", + "phpmyadmin", + "pids", + "Pjpw", + "pkgs", + "pmadb", + "pmezard", + "Pmirojx", + "Pohnpei", + "popperjs", + "pppconfig", + "pppoeconf", + "pprof", + "Pradesh", + "primarys", + "prm", + "probability", + "proces", + "procs", + "promql", + "protoc", + "psync", + "ptype", + "Puducherry", + "Punta", + "Pushkarev", + "pycache", + "pycups", + "pyngrok", + "pypr", + "pyproject", + "pypt", + "pyspy", + "PYTHONUNBUFFERED", + "pytz", + "pyunit", + "Pziu", + "QCONTENT", + "Qostanay", + "Qrcode", + "qrcode", + "QTEXT", + "Qyzylorda", + "rcfile", + "rdata", + "rdatatype", + "recognise", + "redisearch", + "referer", + "Regs", + "Releas", + "removexattr", + "reqd", + "Rerunnability", + "rerunnable", + "Réunion", + "Rhiv", + "Rhxk", + "Rica", + "RIOHXQEHM", + "Rioja", + "rivo", + "rname", + "rnyq", + "rogpeppe", + "rootfs", + "rpush", + "rrset", + "Rsya", + "rtype", + "rutwikhdev", + "ruzy", + "rzgre", + "saas", + "sadd", + "sahilm", + "Santo", + "saurabh", + "sbool", + "Scoresbysund", + "sda", + "sdext", + "sdf", + "sdg", + "sdist", + "sdomain", + "secho", + "Segoe", + "segs", + "seperate", + "serializability", + "setxattr", + "shadrak", + "shuralyov", + "signup", + "SLXVDP", + "smembers", + "SNUBA", + "snuba", + "socketio", + "softirq", + "somes", + "sonner", + "spamd", + "splited", + "sprintf", + "squashfs", + "Srednekolymsk", + "Starke", + "stdc", + "stime", + "stkpush", + "Storge", + "stretchr", + "stripnl", + "Strnm", + "supectl", + "supervisorctl", + "supervisord", + "swapuuid", + "SYMBOLICATOR", + "symbolicator", + "synchronise", + "Syowa", + "Syrus", + "sysrq", + "tanmoy", + "tanmoysrt", + "tanxxxxxxkar", + "Telangana", + "termenv", + "Thgcy", + "tidb", + "Tiraspol", + "Tkndys", + "tldextract", + "Tmate", + "tmpfs", + "Tokelau", + "tomli", + "Tongatapu", + "TOOD", + "TOTP", + "totp", + "tqdm", + "Troso", + "TSZK", + "tupple", + "Tvyn", + "Twillio", + "udiff", + "Udxsrq", + "uefi", + "Uenf", + "Ujung", + "Ulaanbaatar", + "Ulan", + "unarchived", + "Unbilled", + "uncollectible", + "unfollow", + "unindex", + "unindexed", + "unindexing", + "uniseg", + "unlinkat", + "unparse", + "unpatch", + "unplugin", + "Unprovisioned", + "unscrub", + "unsuspended", + "Unsuspending", + "unsuspension", + "updadted", + "urandom", + "uring", + "Urville", + "USEDNS", + "Ushuaia", + "Uttar", + "Uttarakhand", + "Uzhgorod", + "vagrant", + "varkw", + "vasile", + "VBDHE", + "vcpu", + "vcpus", + "vda", + "Velho", + "venv", + "Vetur", + "vetur", + "Vevay", + "vfat", + "vimrc", + "virsh", + "virtualenv", + "Vite", + "vite", + "vitess", + "VMI", + "vmis", + "vnic", + "Vodacom", + "volid", + "vpus", + "vtprotobuf", + "vueuse", + "vxeg", + "Vzzq", + "Wazuh", + "wazuh", + "weasyprint", + "webp", + "Winamac", + "witht", + "Wiue", + "wkhtmlto", + "WKHTMLTOPDF", + "wkhtmltox", + "Wpym", + "xampp", + "xauth", + "xcall", + "xerrors", + "xfonts", + "XHOMZ", + "xitongsys", + "xlink", + "Xpai", + "XPUT", + "Xrwmb", + "xvda", + "xvdf", + "xvdg", + "Xwgt", + "xyproto", + "Xyrw", + "Xzmq", + "Yakutat", + "Yancowinna", + "Yekq", + "Ynel", + "yxei", + "Yzuve", + "zeebo", + "zloirock", + "Zpyihv", + "ZSTD", + "Wazuh", + "DBUS", + "Zvkq", + "reka", + "pydo", + "erpnextv", + "hrmsv", + "Zvkq", + "botocore" + ] +} diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..01bd34f43c7 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,11 @@ +# Regenerate fixtures +9db90c9a790ad8b74e8f476c846898f3450e5c6d + +# Mess up Agent Job Type fixtures +b7d4540c32075cbf569d9c8e256a8ce9898c7115 + +# Fix Agent Job Type fixtures +0c88a71473a906c87c58c94cc11743f79711d240 + +# Generate DocType types +a965b98b90fadf438c5f0a22c5778896743a94e7 \ No newline at end of file diff --git a/.github/helper/install.sh b/.github/helper/install.sh index 29113ed726a..cc79438da03 100644 --- a/.github/helper/install.sh +++ b/.github/helper/install.sh @@ -4,22 +4,12 @@ set -e cd ~ || exit -sudo apt update && sudo apt install redis-server libcups2-dev - pip install frappe-bench -bench init --skip-assets --python "$(which python)" ~/frappe-bench --frappe-path https://github.com/adityahase/frappe --frappe-branch frappe-cloud +bench init --skip-assets --python "$(which python)" ~/frappe-bench --frappe-path https://github.com/balamurali27/frappe --frappe-branch fc-ci mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" -install_whktml() { - wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz - tar -xf /tmp/wkhtmltox.tar.xz -C /tmp - sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf - sudo chmod o+x /usr/local/bin/wkhtmltopdf -} -install_whktml & - cd ~/frappe-bench || exit sed -i 's/watch:/# watch:/g' Procfile @@ -31,9 +21,8 @@ bench get-app press "${GITHUB_WORKSPACE}" bench setup requirements --dev -bench start &> bench_run_logs.txt & -CI=Yes bench build --app frappe & -bench new-site --db-root-password root --admin-password admin test_site +export CI=Yes +bench new-site --mariadb-user-host-login-scope='%' --db-root-password root --admin-password admin test_site bench --site test_site install-app press - - +bench set-config -g server_script_enabled 1 +bench set-config -g http_port 8000 diff --git a/.github/hooks/todo-warning.sh b/.github/hooks/todo-warning.sh new file mode 100755 index 00000000000..fa3b7aab7a8 --- /dev/null +++ b/.github/hooks/todo-warning.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +ORANGE='\033[0;33m' +NC='\033[0m' +BOLD='\033[1m' +NORMAL='\033[0m' + + +echo $GIT_COMMIT + +check_file() { + local file=$1 + local match_pattern=$2 + + local file_changes_with_context=$(git diff -U999999999 -p --cached --color=always -- $file) + local matched_additions=$(echo "$file_changes_with_context" | grep -C4 $'^\e\\[32m\+.*'"$match_pattern") + + if [ -n "$matched_additions" ]; then + echo -e "${ORANGE}[WARNING]${NC} ${BOLD}$file${NORMAL} contains some $match_pattern." + echo "$matched_additions" + echo -e "\n" + fi +} + + +for file in `git diff --cached -p --name-status | cut -c3-`; do + check_file $file 'TODO' +done +exit \ No newline at end of file diff --git a/.github/images/press-cluster.png b/.github/images/press-cluster.png new file mode 100644 index 00000000000..d6a94b8d2ac Binary files /dev/null and b/.github/images/press-cluster.png differ diff --git a/.github/workflows/auto-backport-master-to-develop.yml b/.github/workflows/auto-backport-master-to-develop.yml new file mode 100644 index 00000000000..433a3427f8c --- /dev/null +++ b/.github/workflows/auto-backport-master-to-develop.yml @@ -0,0 +1,90 @@ +name: Auto PR from Master to Develop + +on: + push: + branches: + - master + +permissions: + contents: write + pull-requests: write + +jobs: + create-pr: + runs-on: ubuntu-latest + if: | + !contains(github.event.head_commit.message, 'Merge pull request') && + !contains(github.event.head_commit.message, 'Merge branch') && + !startsWith(github.event.head_commit.message, 'Merge') + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: Prepare backport_master branch (Rebase) + run: | + git fetch origin develop + git fetch origin master + + # Create/update backport_master from develop + git checkout -B backport_master origin/develop + + # Rebase onto master to avoid merge commits + git rebase origin/master || { + echo "Rebase conflict detected, aborting." + git rebase --abort + exit 1 + } + + git push origin backport_master --force-with-lease + + - name: Get commit details + run: | + git fetch origin develop + COMMITS=$(git log origin/develop..origin/backport_master --pretty=format:"- %h %s") + echo "$COMMITS" > commits.txt + + - name: Check if PR already exists + id: check-pr + run: | + EXISTING_PR=$(gh pr list --head backport_master --base develop --state open --json number --jq '.[0].number // empty') + echo "existing_pr=$EXISTING_PR" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Pull Request + if: steps.check-pr.outputs.existing_pr == '' + run: | + COMMITS_LIST=$(cat commits.txt) + PR_DESCRIPTION="**Please perform \`Merge & Commit\` to preserve commit history** + + $COMMITS_LIST" + + gh pr create \ + --title "chore: Sync Changes from Master to Develop" \ + --body "$PR_DESCRIPTION" \ + --head backport_master \ + --base develop + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update existing PR + if: steps.check-pr.outputs.existing_pr != '' + run: | + COMMITS_LIST=$(cat commits.txt) + PR_DESCRIPTION="**Please perform \`Merge & Commit\` to preserve commit history** + + $COMMITS_LIST" + + gh pr edit ${{ steps.check-pr.outputs.existing_pr }} \ + --body "$PR_DESCRIPTION" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8a51f4e9eec..5c8e73f88f4 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -9,45 +9,99 @@ on: - '*' workflow_dispatch: -env: - DB_NAME: test_frappe - DB_USER: test_frappe - DB_PASSWORD: test_frappe - concurrency: group: ${{ github.ref }} cancel-in-progress: true jobs: format: - name: 'Black and Flake8' + name: Lint and Format runs-on: ubuntu-latest + outputs: + changed-python: ${{ steps.changed-python-files.outputs.any_changed }} + changed-json: ${{ steps.changed-json-files.outputs.any_changed }} + changed-js-vue: ${{ steps.changed-js-vue-files.outputs.any_changed }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Cache pip + uses: actions/cache@v4 with: - python-version: 3.11 + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/*dev-requirements.txt, **/*requirements.txt', '**/pyproject.toml', '**/setup.py', '**/setup.cfg') }} + restore-keys: | + ${{ runner.os }}-pip- + ${{ runner.os }}- - name: Install dependencies run: | - pip install flake8 git+https://github.com/adityahase/black - - name: Black Test + pip install -r dev-requirements.txt + + - name: Get changed python files + id: changed-python-files + uses: tj-actions/changed-files@v45 + with: + files: | + **.py + + - name: Get changed json files + id: changed-json-files + uses: tj-actions/changed-files@v45 + with: + files: | + **.json + + - name: Get changed js or vue files + id: changed-js-vue-files + uses: tj-actions/changed-files@v45 + with: + files: | + **.js + **.vue + + - name: List all changed files + if: steps.changed-python-files.outputs.any_changed == 'true' + env: + ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }} run: | - black --check ${GITHUB_WORKSPACE}/press/press - - name: Flake8 Test + for file in ${ALL_CHANGED_FILES}; do + echo "$file was changed" + done + + - name: Lint Check + if: steps.changed-python-files.outputs.any_changed == 'true' + env: + ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }} run: | - flake8 --ignore W191,E501,W503 ${GITHUB_WORKSPACE}/press/press + ruff check --output-format github ${ALL_CHANGED_FILES} + + - name: Format Check + if: steps.changed-python-files.outputs.any_changed == 'true' + env: + ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }} + run: | + ruff format --check ${ALL_CHANGED_FILES} --diff + + - name: Typing Check + if: steps.changed-python-files.outputs.any_changed == 'true' + env: + ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }} + run: | + mypy ${ALL_CHANGED_FILES} semgrep: name: Semgrep Rules runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.10' - name: Run Semgrep rules @@ -55,14 +109,11 @@ jobs: pip install semgrep==1.32 semgrep ci --config ./press-semgrep-rules.yml --config r/python.lang.correctness - tests: + install: + name: Setup Bench + needs: format runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - container: [1, 2] - - name: Server + if: needs.format.outputs.changed-python == 'true' || needs.format.outputs.changed-json == 'true' || needs.format.outputs.changed-js-vue == 'true' services: mariadb: @@ -72,10 +123,12 @@ jobs: ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 + volumes: + - /data/mariadb_data:/var/lib/mysql steps: - name: Clone - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check for valid Python & Merge Conflicts run: | @@ -84,22 +137,44 @@ jobs: then echo "Found merge conflicts" exit 1 fi + - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: '3.10' - name: Setup Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: - node-version: 14 + node-version: 18 check-latest: true + - name: Cache apt + uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: redis-server libcups2-dev + version: 1.0 # Arbitrary version to bust cache when needed + + - name: Cache wkhtmltopdf + id: cache-wkhtmltopdf + uses: actions/cache@v4 + with: + path: /usr/local/bin/wkhtmltopdf + key: ${{ runner.os }}-wkhtmltopdf-0.12.3 + + - name: Install wkhtmltopdf + if: steps.cache-wkhtmltopdf.outputs.cache-hit != 'true' + run: | + wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz + tar -xf /tmp/wkhtmltox.tar.xz -C /tmp + sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf + sudo chmod o+x /usr/local/bin/wkhtmltopdf + - name: Cache pip - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py', '**/setup.cfg') }} + key: ${{ runner.os }}-pip-${{ hashFiles('**/*dev-requirements.txt, **/*requirements.txt', '**/pyproject.toml', '**/setup.py', '**/setup.cfg') }} restore-keys: | ${{ runner.os }}-pip- ${{ runner.os }}- @@ -108,7 +183,8 @@ jobs: id: yarn-cache-dir-path run: 'echo "::set-output name=dir::$(yarn cache dir)"' - - uses: actions/cache@v3 + - name: Cache yarn + uses: actions/cache@v4 id: yarn-cache with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} @@ -119,15 +195,247 @@ jobs: - name: Install run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh + - name: Cache bench directory + uses: actions/cache/save@v4 + with: + key: bench-dir-${{ github.run_id }} + path: /home/runner/frappe-bench + + - name: Stop mariadb service + run: | + docker stop ${{ job.services.mariadb.id }} + + - name: Change ownership of mariadb data directory (for caching) + run: | + sudo chown -R runner:runner /data/mariadb_data + + - name: Cache mariadb data directory + uses: actions/cache/save@v4 + with: + key: mariadb-data-${{ github.run_id }} + path: /data/mariadb_data + + ui-tests: + needs: [format, install] + name: Client + runs-on: ubuntu-latest + env: + PRESS_ADMIN_USER_EMAIL: playwright@example.com + PRESS_ADMIN_USER_PASSWORD: playwright + BASE_URL: http://test_site:8000 + + steps: + - name: Create mariadb data directory + run: | + sudo mkdir -p /data/mariadb_data + + - name: Change ownership of mariadb data directory (for cache restore) + run: | + sudo chown -R runner:runner /data/mariadb_data + + - name: Restore mariadb data directory from cache + uses: actions/cache/restore@v4 + with: + key: mariadb-data-${{ github.run_id }} + path: /data/mariadb_data + + - name: Change ownership of mariadb data directory (post cache restore) + run: | + sudo chown -R 999:systemd-journal /data/mariadb_data + + - name: Start mariadb service + run: | + docker run -d \ + --name mariadb \ + -e MYSQL_ROOT_PASSWORD=root \ + -p 3306:3306 \ + -v /data/mariadb_data:/var/lib/mysql \ + --health-cmd="mysqladmin ping" \ + --health-interval=5s \ + --health-timeout=2s \ + --health-retries=3 \ + mariadb:10.6 + + - name: Clone + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 18 + check-latest: true + + - name: Cache apt + uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: redis-server libcups2-dev + version: 1.0 # Arbitrary version to bust cache when needed + + - name: Cache wkhtmltopdf + id: cache-wkhtmltopdf + uses: actions/cache@v4 + with: + path: /usr/local/bin/wkhtmltopdf + key: ${{ runner.os }}-wkhtmltopdf-0.12.3 + + - name: Install wkhtmltopdf + if: steps.cache-wkhtmltopdf.outputs.cache-hit != 'true' + run: | + wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz + tar -xf /tmp/wkhtmltox.tar.xz -C /tmp + sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf + sudo chmod o+x /usr/local/bin/wkhtmltopdf + + - name: Restore bench directory from cache + uses: actions/cache/restore@v4 + with: + path: /home/runner/frappe-bench + key: bench-dir-${{ github.run_id }} + + - name: Install Bench command + run: pip install frappe-bench + + - name: Don't run unnecessary services + working-directory: /home/runner/frappe-bench + run: | + sed -i 's/watch:/# watch:/g' Procfile + sed -i 's/schedule:/# schedule:/g' Procfile + sed -i 's/socketio:/# socketio:/g' Procfile + sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile + + - name: Start Bench + working-directory: /home/runner/frappe-bench + run: | + bench start &> bench_start_logs.txt & + + - name: Add to Hosts + run: | + echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts + + - name: Expose GitHub Runtime + uses: crazy-max/ghaction-github-runtime@v3 + + - name: Install Playwright browsers + working-directory: /home/runner/frappe-bench/apps/press/dashboard + run: npx playwright install chromium + + - name: Setup Test Users + working-directory: /home/runner/frappe-bench/apps/press/dashboard + run: | + bench --site test_site execute press.press.doctype.team.test_team.create_test_press_admin_team \ + --kwargs "{\"email\": \"${PRESS_ADMIN_USER_EMAIL}\", \"free_account\": True, \"skip_onboarding\": True}" + bench --site test_site set-password "$PRESS_ADMIN_USER_EMAIL" "$PRESS_ADMIN_USER_PASSWORD" + + - name: Run Playwright Tests + working-directory: /home/runner/frappe-bench/apps/press/dashboard + run: npx playwright test --project=chromium + + - name: Generate Coverage Report + working-directory: /home/runner/frappe-bench/apps/press/dashboard + run: npx nyc report --reporter=cobertura --reporter=text --report-dir=./coverage + + - name: Upload Playwright Test report + if: always() + uses: actions/upload-artifact@v4 + with: + name: playwright-report + path: /home/runner/frappe-bench/apps/press/dashboard/playwright-report + + - name: Upload coverage data + uses: codecov/codecov-action@v5 + with: + disable_search: true + files: /home/runner/frappe-bench/apps/press/dashboard/coverage/cobertura-coverage.xml + fail_ci_if_error: false + verbose: true + token: ${{ secrets.CODECOV_TOKEN }} + name: press-dashboard + flags: dashboard + + server-tests: + needs: [format, install] + name: Server + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + container: [1, 2, 3] + if: needs.format.outputs.changed-python == 'true' || needs.format.outputs.changed-json == 'true' + + steps: + - name: Create mariadb data directory + run: | + sudo mkdir -p /data/mariadb_data + + - name: Change ownership of mariadb data directory (for cache restore) + run: | + sudo chown -R runner:runner /data/mariadb_data + + - name: Restore mariadb data directory from cache + uses: actions/cache/restore@v4 + with: + key: mariadb-data-${{ github.run_id }} + path: /data/mariadb_data + + - name: Change ownership of mariadb data directory (post cache restore) + run: | + sudo chown -R 999:systemd-journal /data/mariadb_data + + - name: Start mariadb service + run: | + docker run -d \ + --name mariadb \ + -e MYSQL_ROOT_PASSWORD=root \ + -p 3306:3306 \ + -v /data/mariadb_data:/var/lib/mysql \ + --health-cmd="mysqladmin ping" \ + --health-interval=5s \ + --health-timeout=2s \ + --health-retries=3 \ + mariadb:10.6 + + - name: Clone + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Cache apt + uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: redis-server libcups2-dev + version: 1.0 # Arbitrary version to bust cache when needed + + - name: Restore bench directory from cache + uses: actions/cache/restore@v4 + with: + path: /home/runner/frappe-bench + key: bench-dir-${{ github.run_id }} + + - name: Install Bench command + run: pip install frappe-bench + + - name: Start Bench + working-directory: /home/runner/frappe-bench + run: | + bench start &> bench_start_logs.txt & + - name: Add to Hosts run: | echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts - name: Expose GitHub Runtime - uses: crazy-max/ghaction-github-runtime@v2 + uses: crazy-max/ghaction-github-runtime@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 with: install: true @@ -135,32 +443,40 @@ jobs: working-directory: /home/runner/frappe-bench run: | bench --site test_site set-config allow_tests true - bench --site test_site run-parallel-tests --app press --with-coverage --total-builds 2 --build-number ${{ matrix.container }} - cd apps/press/dashboard && yarn run test + bench --site test_site run-parallel-tests --app press --with-coverage --total-builds 3 --build-number ${{ matrix.container }} env: TYPE: server + COVERAGE_RCFILE: /home/runner/frappe-bench/apps/press/.coveragerc - name: Upload coverage reports to Codecov - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-${{ matrix.container }} path: /home/runner/frappe-bench/sites/coverage.xml if: always() + - name: Upload bench start logs + uses: actions/upload-artifact@v4 + with: + name: bench-start-logs-${{ matrix.container }} + path: /home/runner/frappe-bench/bench_start_logs.txt + if: always() + coverage: name: Coverage Wrap Up - if: always() - needs: tests + needs: server-tests + if: needs.server-tests.result == 'success' || needs.server-tests.result == 'failure' runs-on: ubuntu-latest steps: - name: Clone - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Upload coverage data - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: fail_ci_if_error: false verbose: true + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/validate-pr-title.yaml b/.github/workflows/validate-pr-title.yaml new file mode 100644 index 00000000000..c2455c16590 --- /dev/null +++ b/.github/workflows/validate-pr-title.yaml @@ -0,0 +1,73 @@ +name: Validate PR Title +on: + pull_request: + types: [opened, edited, synchronize] +permissions: + pull-requests: write + contents: read +jobs: + lint: + name: 'Lint' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + - name: Install Commitlint and CSpell + run: npm install --save-dev @commitlint/{config-conventional,cli} cspell + - run: echo "${{ github.event.pull_request.title }}" > pr-title.txt + - name: Run Commitlint + id: commitlint + run: npx commitlint --edit pr-title.txt > commitlint_output.txt 2>&1 + if: github.event.pull_request.user.login != 'mergify[bot]' + - name: Run CSpell + id: cspell + run: npx cspell --config .cspell.json pr-title.txt > cspell_output.txt 2>&1 + if: github.event.pull_request.user.login != 'mergify[bot]' + - name: Delete Old Bot Comments + if: always() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Fetch all comments on the PR + COMMENTS=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments --jq '.[] | select(.user.login == "github-actions[bot]") | .id') + + # Delete comments authored by the bot + for COMMENT_ID in $COMMENTS; do + gh api repos/${{ github.repository }}/issues/comments/$COMMENT_ID -X DELETE + done + - name: Post PR Comment + if: github.event.pull_request.user.login != 'mergify[bot]' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Initialize status messages + STATUS_COMMITLINT="PASSED" + STATUS_CSPELL="PASSED" + COMMITLINT_OUTPUT=$(cat commitlint_output.txt) + CSPELL_OUTPUT=$(cat cspell_output.txt) + COMMENT_BODY="### Found Issues In PR Title\n" + + if [ "${{ steps.commitlint.outcome }}" == "failure" ]; then + STATUS_COMMITLINT="FAILED" + fi + + if [ "${{ steps.cspell.outcome }}" == "failure" ]; then + STATUS_CSPELL="FAILED" + fi + + if [ "$STATUS_COMMITLINT" == "FAILED" ]; then + COMMENT_BODY+="**❌ Conventional Commit Format**\n" + COMMENT_BODY+="\n\`\`\`\n$COMMITLINT_OUTPUT\n\`\`\`\n" + fi + if [ "$STATUS_CSPELL" == "FAILED" ]; then + COMMENT_BODY+="**❌ Spelling Error**\n" + COMMENT_BODY+="\n\`\`\`\n$CSPELL_OUTPUT\n\`\`\`\n" + COMMENT_BODY+="\n> If you believe the spelling error is a false positive, please add the word in **cspell.json** file.\n" + fi + + if [ "$STATUS_COMMITLINT" == "FAILED" ] || [ "$STATUS_CSPELL" == "FAILED" ]; then + # Post the comment + echo -e "$COMMENT_BODY" | gh pr comment ${{ github.event.pull_request.number }} --body-file - + fi + diff --git a/.gitignore b/.gitignore index 884562a2c6c..8f06d3c8c83 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ coverage.xml *.py,cover .hypothesis/ .pytest_cache/ +test-results # Translations *.mo @@ -138,15 +139,22 @@ node_modules press/docs/current press/public/dashboard press/www/dashboard.html +press/www/dashboard-old.html press/public/css/email.css press/public/css/saas-next.css dashboard/tailwind.theme.json +dashboard/components.d.ts + +# Session file +libs/fc_cli/session.json # Backbone artefacts backbone/packer/builds/ backbone/packer/scratch/ backbone/packer/images/ backbone/packer/cloud-init.img +backbone/packer/user-data +backbone/packer/meta-data backbone/packer/cloud-init-scaleway.img # marketplace @@ -156,3 +164,7 @@ press/public/css/marketplace-next.css # Vim .vim .nvimrc + +# IDE +.idea +.vscode \ No newline at end of file diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 00000000000..b5ae304c700 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,42 @@ +pull_request_rules: + - name: Auto-close PRs on stable branch + conditions: + - and: + - and: + - author!=frappe-pr-bot + - author!=mergify[bot] + - author!=github-actions + - or: + - base=master + actions: + comment: + message: | + @{{author}}, thanks for the contribution, but we do not accept pull requests on a master. Please close this PR and raise PR on an develop branch. + + - name: backport to develop + conditions: + - label="backport-develop" + actions: + backport: + branches: + - develop + assignees: + - "{{ author }}" + + - name: backport to master + conditions: + - label="backport-master" + actions: + backport: + branches: + - master + assignees: + - "{{ author }}" + + - name: Label PRs targeting develop with 'backport-master' + conditions: + - base=develop + actions: + label: + add: + - backport-master diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 94a4f18df6c..1c9a6fc2a8a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,17 +1,10 @@ exclude: 'node_modules|.git' -default_stages: [commit] +default_stages: [pre-commit] fail_fast: false repos: - - repo: https://github.com/pycqa/flake8 - rev: 3.9.2 - hooks: - - id: flake8 - args: [--ignore, 'W191,E501,W503'] - additional_dependencies: ['flake8==3.9.2'] - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.9-for-vscode + rev: v4.0.0-alpha.8 hooks: - id: prettier types_or: [javascript, vue] @@ -27,7 +20,7 @@ repos: )$ - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - id: debug-statements - id: trailing-whitespace @@ -39,8 +32,58 @@ repos: - id: check-toml - id: check-yaml - - repo: https://github.com/adityahase/black - rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.13.1 + hooks: + - id: ruff + args: [--fix] + - id: ruff-format + + - repo: local + hooks: + - id: commitlint + name: check commit message format + entry: npx commitlint --edit .git/COMMIT_EDITMSG + language: system + stages: [commit-msg] + always_run: true + + - id: cspell-commit-msg + name: check commit message spelling + entry: npx cspell --config .cspell.json .git/COMMIT_EDITMSG + language: system + stages: [commit-msg] + always_run: true + + - id: cspell-modified-files + name: check spelling of files + entry: sh -c "npx cspell --no-must-find-files --config .cspell.json `git diff --cached -p --name-status | cut -c3- | tr '\n' ' '`" + language: system + stages: [pre-commit] + + - id: todo-warning + name: check todos + entry: .github/hooks/todo-warning.sh + language: script + stages: [pre-commit] + verbose: true + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.18.2 hooks: - - id: black - additional_dependencies: ['click==8.0.4'] + - id: mypy + args: + [ + --ignore-missing-imports, + --follow-imports=skip, + --exclude-gitignore, + --no-warn-no-return, + --disable-error-code=annotation-unchecked, + ] + exclude: ^tests/|test_.*\.py$ # Exclude the 'tests/' directory and files starting with 'test_' + additional_dependencies: + [ + types-requests<2.32, + types-pytz~=2025.2, + types-python-dateutil~=2.9.0, + ] diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index c80ce15d3be..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "path-intellisense.mappings": { - "@": "${workspaceRoot}/dashboard/src" - } -} diff --git a/CODEOWNERS b/CODEOWNERS index 7f4a85e5530..8788841ed67 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -13,11 +13,13 @@ playbooks/ @adityahase @balamurali27 site* @balamurali27 team/ @shadrak98 -dashboard/ @rutwikhdev invoice/ @shadrak98 -marketplace* @rutwikhdev stripe* @shadrak98 razorpay* @shadrak98 subscription/ @shadrak98 +dashboard/ @regdocs saas @rutwikhdev + +deploy* @18alantom +press/Dockerfile @18alantom diff --git a/README.md b/README.md index 29ced6a1b15..5bb02dfa3b4 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,95 @@ -## Press +
+ +Press logo +

Press

+ +**Full Service Cloud Hosting For The Frappe Stack - Powers Frappe Cloud** [![codecov](https://codecov.io/gh/frappe/press/branch/master/graph/badge.svg?token=0puvH0jUx9)](https://codecov.io/gh/frappe/press) [![unittests](https://github.com/frappe/press/actions/workflows/main.yaml/badge.svg)](https://github.com/frappe/press/actions/workflows/main.yaml) +
+ +
+ Managed press +
+
+
+ Website + - + Documentation +
+ +## Press + +Press is a 100% open-source cloud hosting for the Frappe stack. + +### Motivation + +We originally hosted our customer sites on an internal cloud platform called "Central," designed to automate creating and hosting sites when customers signed up on our website. Central was primarily built to host ERPNext, our flagship product. However, as our customers' needs evolved, they began requesting the ability to host custom applications, a feature that was not a priority in Central. -This is `press`, a Frappe custom app that runs Frappe Cloud. This app manages infrastructure, subscription, marketplace, SaaS and much more. +Additionally, customers lacked full control over their servers—no SSH access, no ability to manage updates, and limited flexibility in interacting with their environment. This led us to launch Frappe Cloud, to build a self-serve cloud platform that would empower our customers with complete control over their hosting experience. -> press: "I have a brother, without which I cannot live, agent" +### Key Features -The other half of the Frappe Cloud infrastructure is [agent](https://github.com/frappe/agent). Which is a flask application that runs on every server in a typical cluster and carries out tasks on HTTP requests. Creating a new site, installing an app, updating a site, creating a bench and everything in between is just a request (`Agent Job`) away. +- **Multitenancy Made Easy**: Press simplifies multi-tenancy by enabling multiple sites on a single platform, each with its app version, allowing independent updates and minimal downtime, even for large sites. +- **Dashboard**: The dashboard provides a centralized interface to manage apps, servers, sites, billing, backups, and updates, offering real-time insights and streamlined control of complex operations. -> Note that, this README is in a very early WIP state and only covers a tiny bit of FC. More to come! +- **Permissions**: Granular access controls let team owners manage roles and resources efficiently, ensuring users have access only to relevant information and actions for their roles. -## Typical FC Cluster +- **Simplified Management**: Press streamlines site management with automated backups, real-time monitoring, role-based access, and easy scaling, making it ideal for growing Frappe environments. -![FC Cluster Diagram](.github/images/fc-cluster.png) +- **Billing**: Automated billing supports daily or monthly subscriptions, flexible payment methods, wallet credits, and ERP integration, simplifying customer invoicing and payments. -## Prerequisites +- **Marketplace**: The marketplace allows developers to list apps with flexible pricing models, ensures compatibility checks, and provides a streamlined system for sales and payouts. -- Frappe Bench (https://github.com/frappe/bench) -- Docker -- Certbot with route53 plugin -- AWS account (for route53 & S3) -- Digital Ocean account (for [container registry](https://www.digitalocean.com/products/container-registry)) +
+ Screenshots -## Local Setup +![Dashboard](https://github.com/user-attachments/assets/1904fa3e-39aa-4151-8276-d3cc622ed582) +![Permissions](https://github.com/user-attachments/assets/60da6b5e-8f48-4483-99cf-67886ccc8bd6) +![Bench Group Update](https://github.com/user-attachments/assets/2be6b0ee-084d-4949-8d13-218b5a218d3d) +![Marketplace](https://github.com/user-attachments/assets/2f325737-7929-485d-a670-549f986fd07e) -You can find a detailed walkthough for setting up a local FC cluster [here](https://frappecloud.com/docs/local-fc-setup). +
-## Some Core DocTypes +### Under the Hood -- Server -- Database Server -- Proxy Server -- Site -- Release Group -- Deploy Candidate -- Bench -- App -- App Source -- App Release -- TLS Certificate +- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework written in Python and Javascript. The framework provides a robust foundation for building web applications, including a database abstraction layer, user authentication, and a REST API. -## The Front-end +- [**Frappe UI**](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface. The Frappe UI library provides a variety of components that can be used to build single-page applications on top of the Frappe Framework. -You can read more about the VueJS frontend for Frappe Cloud [here](./dashboard/README.md). +- [**Agent**](https://github.com/frappe/agent): A flask app designed to work along with Press. It provides a CLI interface for Press to communicate with the sites and benches. -## Contributing +- [**Docker**](https://www.docker.com): An open-source platform that enables developers to build, package, and deploy applications in lightweight, portable containers. -> Journey of a thousand PRs begins with a single typo fix! +- [**Ansible**](https://www.ansible.com): An open-source IT automation tool that simplifies the management, configuration, and deployment of systems and applications. -You can contribute in many ways, some of which are: +## Setup -1. Reporting Issues: If you find a bug, typo etc. Feel free to raise an issue and we will take it from there. +To self host or to setup Press locally follow the steps in the [Local Development Environment Setup Guide](https://docs.frappe.io/cloud/local-fc-setup) or [this YouTube video](https://www.youtube.com/watch?v=Xb9QHnUrIEk) -2. Feature PRs: You can start by creating an issue with a feature proposal, we can discuss whether we should go ahead with it or not. +### Pre-commit -3. Give us a star! +There's a [pre-commit](https://pre-commit.com/) hook included in the repo. You can set it up by doing -4. Documentation +```bash +pip install pre-commit +pre-commit install +``` +## Learn and connect -#### License +- [Telegram Public Group](https://t.me/frappecloud) +- [Discuss Forum](https://discuss.frappe.io/c/frappe-cloud/77) +- [Documentation](https://docs.frappe.io/cloud) -[GNU Affero General Public License v3.0](https://github.com/frappe/press/blob/master/license.txt) +
+
+
+ + + + Frappe Technologies + + +
diff --git a/arm-builds/RedisearchARMBuild b/arm-builds/RedisearchARMBuild new file mode 100644 index 00000000000..fad03de8a1f --- /dev/null +++ b/arm-builds/RedisearchARMBuild @@ -0,0 +1,32 @@ +# https://github.com/devgeniem/RediSearch/blob/master/Dockerfile + +ARG REDIS_VER=6.2 +ARG REDISEARCH_VER=v2.4.6 +ARG RUST_VER=1.60.0 + +FROM rust:${RUST_VER} AS builder + +ARG REDISEARCH_VER + +RUN apt clean && apt -y update && apt -y install --no-install-recommends \ + clang && rm -rf /var/lib/apt/lists/* + +WORKDIR / + +RUN git clone --recursive --depth 1 --branch ${REDISEARCH_VER} https://github.com/RediSearch/RediSearch.git + +WORKDIR /RediSearch + +RUN make setup + +RUN make build + +# Run module in official Redis +FROM redis:${REDIS_VER} +WORKDIR /data + +RUN mkdir -p /usr/lib/redis/modules +COPY --from=builder /RediSearch/bin/linux-arm64v8-release/search/redisearch.so /usr/lib/redis/modules + +EXPOSE 6379 +CMD ["redis-server", "--loadmodule", "/usr/lib/redis/modules/redisearch.so"] \ No newline at end of file diff --git a/backbone/cli.py b/backbone/cli.py index 4d0ee0a960d..4d0111f614b 100644 --- a/backbone/cli.py +++ b/backbone/cli.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe and contributors # For license information, please see license.txt import click diff --git a/backbone/hypervisor.py b/backbone/hypervisor.py index 54f60d265ab..89b3144d880 100644 --- a/backbone/hypervisor.py +++ b/backbone/hypervisor.py @@ -1,6 +1,6 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe and contributors # For license information, please see license.txt +import platform import subprocess from pathlib import Path @@ -10,44 +10,68 @@ def __init__(self, shell=None): self.shell = shell def setup(self): - self.preinstall() - self.install() - self.verify() + system = platform.system() + if system == "Linux": + self.preinstall() + self.install() + self.verify() + elif system == "Darwin": + self.verify_mac() def build(self, size): + system = platform.system() + if system == "Linux": + self.build_cloud_init_linux() + elif system == "Darwin": + self.build_cloud_init_mac() + self.build_packer("backbone", size=size) + + def build_cloud_init_linux(self): cloud_init_yml = str(Path(__file__).parent.joinpath("packer", "cloud-init.yml")) cloud_init_image = str(Path(__file__).parent.joinpath("packer", "cloud-init.img")) self.shell.execute(f"cloud-localds {cloud_init_image} {cloud_init_yml}") - packer_template = str(Path(__file__).parent.joinpath("packer", "backbone.json")) - packer = self.shell.execute(f"packer build -var 'disk_size={size}' {packer_template}") - if packer.returncode: - raise Exception("Build Failed") + def build_cloud_init_mac(self): + # cloud-localds isn't available on macOS. + # So we do what it does ourselves + # user-data is the same as cloud-init.yml + # https://github.com/canonical/cloud-utils/blob/49e5dd7849ee3c662f3db35e857148d02e72694b/bin/cloud-localds#L168-L187 + cloud_init_yml = str(Path(__file__).parent.joinpath("packer", "cloud-init.yml")) + user_data = str(Path(__file__).parent.joinpath("packer", "user-data")) + self.shell.execute(f"cp {cloud_init_yml} {user_data}") - box = str(Path(__file__).parent.joinpath("packer", "builds", "backbone.box")) - add = self.shell.execute(f"vagrant box add {box} --name backbone --force") - if add.returncode: - raise Exception(f"Cannot add box {box}") + # meta-data has some inconsequential values + # but the file is needed + meta_data = str(Path(__file__).parent.joinpath("packer", "meta-data")) + self.shell.execute(f"touch {meta_data}") - def build_scaleway(self, size): - cloud_init_yml = str( - Path(__file__).parent.joinpath("packer", "cloud-init-scaleway.yml") - ) - cloud_init_image = str( - Path(__file__).parent.joinpath("packer", "cloud-init-scaleway.img") + cloud_init_image = str(Path(__file__).parent.joinpath("packer", "cloud-init.img")) + # Reference: https://github.com/canonical/cloud-utils/blob/49e5dd7849ee3c662f3db35e857148d02e72694b/bin/cloud-localds#L235-L237 + self.shell.execute( + f"mkisofs -joliet -rock -volid cidata -output {cloud_init_image} {user_data} {meta_data}" ) - self.shell.execute(f"cloud-localds {cloud_init_image} {cloud_init_yml}") - packer_template = str(Path(__file__).parent.joinpath("packer", "scaleway.json")) + def build_packer(self, template, size): + packer_template = str(Path(__file__).parent.joinpath("packer", f"{template}.json")) packer = self.shell.execute(f"packer build -var 'disk_size={size}' {packer_template}") if packer.returncode: raise Exception("Build Failed") - box = str(Path(__file__).parent.joinpath("packer", "builds", "scaleway.box")) - add = self.shell.execute(f"vagrant box add {box} --name scaleway --force") + box = str(Path(__file__).parent.joinpath("packer", "builds", f"{template}.box")) + add = self.shell.execute(f"vagrant box add {box} --name {template} --force") if add.returncode: raise Exception(f"Cannot add box {box}") + def build_scaleway(self, size): + self.build_cloud_init_scaleway() + self.build_packer("scaleway", size=size) + + def build_cloud_init_scaleway(self): + cloud_init_yml = str(Path(__file__).parent.joinpath("packer", "cloud-init-scaleway.yml")) + + cloud_init_image = str(Path(__file__).parent.joinpath("packer", "cloud-init-scaleway.img")) + self.shell.execute(f"cloud-localds {cloud_init_image} {cloud_init_yml}") + def up(self): vagrant = self.shell.execute("vagrant init backbone") vagrant = self.shell.execute("vagrant up --provider=libvirt") @@ -77,6 +101,11 @@ def verify(self): if kvm_connect.returncode: raise Exception("Cannot connect to KVM") + def verify_mac(self): + kvm_connect = self.shell.execute("virsh list --all") + if kvm_connect.returncode: + raise Exception("Cannot connect to KVM") + class Shell: def __init__(self, directory=None): @@ -84,7 +113,6 @@ def __init__(self, directory=None): def execute(self, command, directory=None): directory = directory or self.directory - process = subprocess.run( + return subprocess.run( command, check=False, stderr=subprocess.STDOUT, cwd=directory, shell=True, text=True ) - return process diff --git a/backbone/packer/backbone.json b/backbone/packer/backbone.json index 79e3467b0d9..7f0ddb6260e 100644 --- a/backbone/packer/backbone.json +++ b/backbone/packer/backbone.json @@ -18,7 +18,7 @@ "headless": true, "qemuargs": [ [ - "-fda", + "-cdrom", "{{template_dir}}/cloud-init.img" ] ], diff --git a/backbone/setup.py b/backbone/setup.py index 900f2786796..8662211e86d 100644 --- a/backbone/setup.py +++ b/backbone/setup.py @@ -6,9 +6,7 @@ def apt_install(packages): - shell.execute( - f"sudo apt install --yes --no-install-suggests --no-install-recommends {packages}" - ) + shell.execute(f"sudo apt install --yes --no-install-suggests --no-install-recommends {packages}") def main(args): @@ -25,17 +23,15 @@ def prepare(): def setup_vagrant(): - VAGRANT_SERVER = "https://releases.hashicorp.com/vagrant/2.2.10" - VAGRANT_PACKAGE = "vagrant_2.2.10_x86_64.deb" + VAGRANT_SERVER = "https://releases.hashicorp.com/vagrant/2.4.6" + VAGRANT_PACKAGE = "vagrant_2.4.6-1_amd64.deb" shell.execute(f"wget {VAGRANT_SERVER}/{VAGRANT_PACKAGE} -O {VAGRANT_PACKAGE}") shell.execute(f"sudo dpkg -i {VAGRANT_PACKAGE}") def setup_packer(): PACKER_KEY = "https://apt.releases.hashicorp.com/gpg" - PACKER_REPO = ( - '"deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"' - ) + PACKER_REPO = '"deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"' shell.execute(f"curl -fsSL {PACKER_KEY} | sudo apt-key add -") shell.execute(f"sudo apt-add-repository {PACKER_REPO}") apt_install("packer cloud-utils") diff --git a/backbone/setup_mac.py b/backbone/setup_mac.py new file mode 100644 index 00000000000..462f17b282d --- /dev/null +++ b/backbone/setup_mac.py @@ -0,0 +1,57 @@ +import sys + +from backbone.hypervisor import Shell + +shell = Shell() + + +def brew_install(packages): + shell.execute(f"brew install {packages}") + + +def main(args): + prepare() + setup_qemu() + setup_vagrant() + setup_libvirt() + setup_packer() + + +def prepare(): + shell.execute("brew update") + brew_install("cdrtools iproute2mac") + + +def setup_qemu(): + brew_install("qemu") + # We might need to disable a few things + # echo 'security_driver = "none"' >> /opt/homebrew/etc/libvirt/qemu.conf + # echo "dynamic_ownership = 0" >> /opt/homebrew/etc/libvirt/qemu.conf + # echo "remember_owner = 0" >> /opt/homebrew/etc/libvirt/qemu.conf + + +def setup_vagrant(): + # At the time of writing hashicorp tap has older 2.4.2 version + # We need 2.4.3 + # Reference: https://github.com/vagrant-libvirt/vagrant-libvirt/issues/1831 + brew_install("vagrant") + + +def setup_libvirt(): + brew_install("libvirt") + shell.execute("brew services start libvirt") + # Make sure you haven't installed macports + # It overrides pkg-config, and we won't find brew libvirt packages + shell.execute("vagrant plugin install vagrant-libvirt") + shell.execute("vagrant plugin install vagrant-hostmanager") + + +def setup_packer(): + shell.execute("brew tap hashicorp/tap") + brew_install("hashicorp/tap/packer") + shell.execute("packer plugins install github.com/hashicorp/qemu") + shell.execute("packer plugins install github.com/hashicorp/vagrant") + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/backbone/tests/__init__.py b/backbone/tests/__init__.py index 5301bf841f4..559967729fe 100644 --- a/backbone/tests/__init__.py +++ b/backbone/tests/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe and contributors # For license information, please see license.txt import unittest @@ -8,9 +7,7 @@ def run_tests(): - coverage = Coverage( - source=[str(Path(__file__).parent.parent)], omit=["*/tests/*"], branch=True - ) + coverage = Coverage(source=[str(Path(__file__).parent.parent)], omit=["*/tests/*"], branch=True) coverage.start() unittest.main(module=None, argv=["", "discover", "-s", "backbone"], exit=False) coverage.stop() diff --git a/backbone/tests/test_hypervisor.py b/backbone/tests/test_hypervisor.py index 798dba8b6b3..0df28fec4df 100644 --- a/backbone/tests/test_hypervisor.py +++ b/backbone/tests/test_hypervisor.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe and contributors # For license information, please see license.txt -import unittest from unittest.mock import MagicMock +from frappe.tests.utils import FrappeTestCase + from backbone.hypervisor import Hypervisor -class TestHypervisor(unittest.TestCase): +class TestHypervisor(FrappeTestCase): def test_preinstall_pass(self): shell = MagicMock() shell.execute.return_value.returncode = 0 diff --git a/backbone/vagrant/Vagrantfile b/backbone/vagrant/Vagrantfile index a079ece21a7..27ddc2bf5b5 100644 --- a/backbone/vagrant/Vagrantfile +++ b/backbone/vagrant/Vagrantfile @@ -9,6 +9,9 @@ Vagrant.configure("2") do |config| config.vm.provider :libvirt do |libvirt| libvirt.qemu_use_session = false + # Enable qemu_use_session or set this on macOS + # Also run **sudo** brew services start + # libvirt.uri = "qemu:///session" libvirt.driver = "kvm" libvirt.default_prefix = "" # VMs with little disk space may fail to boot diff --git a/codecov.yml b/codecov.yml index 2419002e7cb..5564e53d2b7 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,6 +6,8 @@ coverage: threshold: 0.5% patch: default: - target: 95% + target: 75% threshold: 0% if_ci_failed: ignore + ignore: + - press/press/report/** diff --git a/commitlint.config.js b/commitlint.config.js index 8847564e53c..177f5ab9bb8 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,25 +1,11 @@ -module.exports = { - parserPreset: 'conventional-changelog-conventionalcommits', +export default { + extends: ['@commitlint/config-conventional'], rules: { - 'subject-empty': [2, 'never'], - 'type-case': [2, 'always', 'lower-case'], - 'type-empty': [2, 'never'], - 'type-enum': [ - 2, - 'always', - [ - 'build', - 'chore', - 'ci', - 'docs', - 'feat', - 'fix', - 'perf', - 'refactor', - 'revert', - 'style', - 'test', - ], - ], + 'header-max-length': [2, 'always', 72], + 'subject-case': [2, 'always', 'sentence-case'], + 'scope-case': [2, 'always', 'kebab-case'], + 'body-case': [2, 'always', 'sentence-case'], + 'body-leading-blank': [2, 'always'], + 'footer-leading-blank': [2, 'always'], }, }; diff --git a/dashboard/.gitignore b/dashboard/.gitignore index 7983440f18e..caad334143e 100644 --- a/dashboard/.gitignore +++ b/dashboard/.gitignore @@ -20,3 +20,13 @@ yarn-error.log* *.njsproj *.sln *.sw? + +# Playwright E2E artifacts +playwright-report/ +test-results/ +tests-e2e/.env +tests-e2e/.auth +blob-report/ +playwright/.cache/ +*.trace.zip +.nyc_output/ \ No newline at end of file diff --git a/dashboard/.prettierrc.json b/dashboard/.prettierrc.json index ae0c74589c5..ac6155f8511 100644 --- a/dashboard/.prettierrc.json +++ b/dashboard/.prettierrc.json @@ -1,6 +1,4 @@ { "singleQuote": true, - "useTabs": true, - "trailingComma": "none", - "arrowParens": "avoid" + "useTabs": true } diff --git a/dashboard/README.md b/dashboard/README.md index c935ac63e4b..344465ecbfa 100644 --- a/dashboard/README.md +++ b/dashboard/README.md @@ -12,8 +12,6 @@ Technologies at the heart of dashboard: 4. [Feather Icons](https://feathericons.com/): Those Shiny & Crisp Open Source icons. -5. [Frappe Charts](https://frappe.io/charts): For those beautiful charts. [FrappeChart.vue](./src/components/FrappeChart.vue) is a wrapper Vue component which makes it easy to use Frappe Charts in any other component. - ## Development We use the vite's development server, gives us super-fast hot reload and more. diff --git a/dashboard/auto-imports.d.ts b/dashboard/auto-imports.d.ts new file mode 100644 index 00000000000..9d2400790b5 --- /dev/null +++ b/dashboard/auto-imports.d.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +// biome-ignore lint: disable +export {} +declare global { + +} diff --git a/dashboard/generateThemeConfig.js b/dashboard/generateThemeConfig.js deleted file mode 100644 index 07e584e73fa..00000000000 --- a/dashboard/generateThemeConfig.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * This node script resolves the tailwind config and dumps it as a json in - * tailwind.theme.json which is later imported into the app. - */ -let fs = require('fs'); -let resolveConfig = require('tailwindcss/resolveConfig'); -let config = require('./tailwind.config'); -let { theme } = resolveConfig(config); - -fs.writeFileSync('./tailwind.theme.json', JSON.stringify(theme, null, 2)); diff --git a/dashboard/index.html b/dashboard/index.html index b48e96b1124..b8a3f1a027d 100644 --- a/dashboard/index.html +++ b/dashboard/index.html @@ -1,36 +1,27 @@ - + Frappe Cloud - - + - + -
+
- - diff --git a/dashboard/jsconfig.json b/dashboard/jsconfig.json index 0dd63eb6589..ab3667d764a 100644 --- a/dashboard/jsconfig.json +++ b/dashboard/jsconfig.json @@ -1,5 +1,5 @@ { - "include": ["./src/**/*"], + "include": ["./src/**/*", "src2/components/AddressableErrorDialog.vue"], "compilerOptions": { "baseUrl": ".", "paths": { diff --git a/dashboard/package.json b/dashboard/package.json index 774e1cdbba0..7461f7b0b31 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -2,49 +2,73 @@ "name": "dashboard", "version": "0.1.0", "private": true, + "type": "module", "scripts": { - "dev": "yarn generate-theme-config && vite", - "build": "yarn generate-theme-config && vite build --base=/assets/press/dashboard/ && yarn copy-html-entry", - "copy-html-entry": "cp ../press/public/dashboard/index.html ../press/www/dashboard.html", - "generate-theme-config": "node ./generateThemeConfig.js", + "dev": "vite", + "build": "vite build", "test": "vitest", "coverage": "vitest run --coverage", - "lint": "eslint src" + "lint": "eslint src", + "test:e2e": "playwright test", + "test:e2e:headed": "playwright test --headed", + "test:e2e:report": "playwright show-report", + "postinstall": "patch-package" }, "dependencies": { - "@headlessui/vue": "1.5.0", + "@codemirror/autocomplete": "^6.18.1", + "@codemirror/lang-sql": "^6.8.0", + "@headlessui/vue": "^1.7.14", "@popperjs/core": "^2.11.2", - "@sentry/tracing": "^7.15.0", - "@sentry/vue": "^7.15.0", + "@sentry/vite-plugin": "^2.19.0", + "@sentry/vue": "^8.10.0", "@stripe/stripe-js": "^1.3.0", + "@tailwindcss/container-queries": "^0.1.1", + "@tanstack/vue-table": "^8.20.5", + "@vueuse/components": "^10.7.0", + "@vueuse/core": "^10.3.0", + "codemirror": "^6.0.1", "core-js": "^3.6.4", "dayjs": "^1.10.7", + "echarts": "^5.4.3", "feather-icons": "^4.26.0", "frappe-charts": "2.0.0-rc22", - "frappe-ui": "0.0.103", + "frappe-ui": "0.1.238", "fuse.js": "6.6.2", "libarchive.js": "^1.3.0", "lodash": "^4.17.19", "luxon": "^1.22.0", "markdown-it": "^12.3.2", - "posthog-js": "^1.58.0", + "papaparse": "^5.4.1", + "patch-package": "^8.0.1", + "qrcode": "^1.5.4", "register-service-worker": "^1.6.2", "socket.io-client": "^4.5.1", - "vue": "^3.2.16", - "vue-router": "^4.0.5" + "sql-formatter": "^15.4.10", + "unplugin-icons": "^0.17.0", + "unplugin-vue-components": "^0.25.2", + "vue": "^3.5.15", + "vue-codemirror": "^6.1.1", + "vue-echarts": "^6.6.1", + "vue-qrcode": "^2.2.2", + "vue-router": "^4.1.6", + "vue-sonner": "^1.2.5" }, "devDependencies": { + "@iconify/json": "^2.2.123", + "@playwright/test": "^1.54.2", "@tailwindcss/forms": "^0.4.0", "@tailwindcss/postcss7-compat": "^2.0.2", "@tailwindcss/typography": "^0.5.1", - "@vitejs/plugin-legacy": "^1.3.2", - "@vitejs/plugin-vue": "^2.2.0", + "@vitejs/plugin-legacy": "^4.1.1", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", "@vue/compiler-sfc": "^3.1.0", "@vue/eslint-config-prettier": "^6.0.0", "@vue/test-utils": "^2.0.0-rc.19", "autoprefixer": "^10.4.2", "babel-eslint": "^10.0.3", "c8": "^7.11.0", + "dotenv": "^17.2.3", "eslint": "^6.7.2", "eslint-plugin-prettier": "^3.1.1", "eslint-plugin-vue": "^6.2.2", @@ -56,10 +80,13 @@ "postcss-easy-import": "^4.0.0", "prettier": "^2.5.1", "prettier-plugin-tailwindcss": "^0.1.8", - "tailwindcss": "^3.0.18", - "vite": "^2.9.13", + "tailwindcss": "^3.4", + "typescript": "^5.4.3", + "vite": "5.4.20", "vite-plugin-rewrite-all": "^1.0.1", + "vite-plugin-vue-devtools": "7.6.7", "vitest": "^0.9.3", + "vue-tsc": "^2.0.7", "yorkie": "^2.0.0" }, "gitHooks": { @@ -70,5 +97,25 @@ "yarn lint", "git add" ] + }, + "nyc": { + "include": [ + "src/**/*.vue", + "src/**/*.js" + ], + "extension": [ + ".js", + ".ts", + ".vue" + ], + "reporter": [ + "html", + "text", + "lcov" + ], + "all": true, + "require": [ + "source-map-support/register" + ] } } diff --git a/dashboard/patches/frappe-ui+0.1.238.patch b/dashboard/patches/frappe-ui+0.1.238.patch new file mode 100644 index 00000000000..a534352b3a2 --- /dev/null +++ b/dashboard/patches/frappe-ui+0.1.238.patch @@ -0,0 +1,45 @@ +diff --git a/node_modules/frappe-ui/package.json b/node_modules/frappe-ui/package.json +index 4a652de..826f0a0 100644 +--- a/node_modules/frappe-ui/package.json ++++ b/node_modules/frappe-ui/package.json +@@ -4,6 +4,7 @@ + "description": "A set of components and utilities for rapid UI development", + "type": "module", + "sideEffects": false, ++ "main": "./src/index.ts", + "scripts": { + "test": "vitest --run", + "type-check": "tsc --noEmit", +@@ -17,32 +18,6 @@ + "story:build": "histoire build && cp 404.html .histoire/dist", + "story:preview": "histoire preview" + }, +- "exports": { +- ".": { +- "import": "./src/index.ts", +- "types": "./src/index.ts" +- }, +- "./frappe": { +- "import": "./frappe/index.js" +- }, +- "./icons": { +- "import": "./icons/index.ts" +- }, +- "./tailwind": { +- "import": "./src/tailwind/preset.js", +- "default": "./src/tailwind/preset.js" +- }, +- "./vite": { +- "import": "./vite/index.js" +- }, +- "./style.css": { +- "import": "./src/style.css" +- }, +- "./tsconfig.base.json": { +- "default": "./tsconfig.base.json", +- "types": "./tsconfig.base.json" +- } +- }, + "files": [ + "frappe", + "src", diff --git a/dashboard/playwright.config.ts b/dashboard/playwright.config.ts new file mode 100644 index 00000000000..01275e7de67 --- /dev/null +++ b/dashboard/playwright.config.ts @@ -0,0 +1,39 @@ +import { defineConfig, devices } from '@playwright/test'; +import dotenv from "dotenv"; + +dotenv.config({ path: "./tests-e2e/.env", quiet: true }); + +export default defineConfig({ + testDir: './tests-e2e', + fullyParallel: true, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 4 : undefined, + use: { + baseURL: process.env.BASE_URL || 'http://localhost:8010', + trace: 'retain-on-failure', + screenshot: 'only-on-failure', + video: 'retain-on-failure' + }, + reporter: [['list'], ['html', { open: 'never' }]], + projects: [ + { + name: 'cron', + testMatch: /.*\.cron\.spec\.ts/, + dependencies: undefined + }, + { + name: 'setup', + testMatch: /.*\.setup\.ts/ + }, + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + storageState: 'tests-e2e/.auth/session.json' + }, + // must match all *.test.ts files only + testMatch: /^(?!.*(\.cron|\.setup)\.spec\.ts$).*\.test\.ts$/, + dependencies: ['setup'] + } + ] +}); diff --git a/dashboard/postcss.config.js b/dashboard/postcss.config.cjs similarity index 100% rename from dashboard/postcss.config.js rename to dashboard/postcss.config.cjs diff --git a/dashboard/proxyOptions.js b/dashboard/proxyOptions.js deleted file mode 100644 index 4f6ed36340a..00000000000 --- a/dashboard/proxyOptions.js +++ /dev/null @@ -1,13 +0,0 @@ -const common_site_config = require('../../../sites/common_site_config.json'); -const { webserver_port } = common_site_config; - -module.exports = { - '^/(app|api|assets|files|marketplace)': { - target: `http://localhost:${webserver_port}`, - ws: true, - router: function (req) { - const site_name = req.headers.host.split(':')[0]; - return `http://${site_name}:${webserver_port}`; - } - } -}; diff --git a/dashboard/shims-global.d.ts b/dashboard/shims-global.d.ts new file mode 100644 index 00000000000..653bd0272a0 --- /dev/null +++ b/dashboard/shims-global.d.ts @@ -0,0 +1,7 @@ +declare global { + interface Window { + is_system_user?: boolean; + } +} + +export {}; diff --git a/dashboard/shims.d.ts b/dashboard/shims.d.ts new file mode 100644 index 00000000000..2c0416fa08c --- /dev/null +++ b/dashboard/shims.d.ts @@ -0,0 +1,5 @@ +declare module '~icons/*' { + import { FunctionalComponent, SVGAttributes } from 'vue'; + const component: FunctionalComponent; + export default component; +} diff --git a/dashboard/src/App.vue b/dashboard/src/App.vue index d00402b61d4..9bb4bc76ea1 100644 --- a/dashboard/src/App.vue +++ b/dashboard/src/App.vue @@ -1,78 +1,98 @@ - + diff --git a/dashboard/src/assets/style.css b/dashboard/src/assets/style.css index b38f4038d69..12a13bf482d 100644 --- a/dashboard/src/assets/style.css +++ b/dashboard/src/assets/style.css @@ -1,25 +1,6 @@ -@import './Inter/inter.css'; -@import 'frappe-charts/dist/frappe-charts.min.css'; - -@tailwind base; -@tailwind components; -@tailwind utilities; +@import 'frappe-ui/src/style.css'; @layer components { - .form-input, - .form-textarea, - .form-select { - @apply rounded-md border-0 bg-gray-100 py-1 text-base leading-5 placeholder-gray-700 focus:bg-gray-200 focus:shadow-none focus:ring-0; - } - - .form-checkbox { - @apply rounded-md text-blue-500; - } - - .frappe-chart .line-vertical { - display: none; - } - /* Works on Firefox */ * { scrollbar-width: thin; diff --git a/dashboard/src/components/AccessRequestButton.vue b/dashboard/src/components/AccessRequestButton.vue new file mode 100644 index 00000000000..d7d5df09a56 --- /dev/null +++ b/dashboard/src/components/AccessRequestButton.vue @@ -0,0 +1,88 @@ + + + diff --git a/dashboard/src/components/AccessRequestDialog.vue b/dashboard/src/components/AccessRequestDialog.vue new file mode 100644 index 00000000000..bafdec4aaa6 --- /dev/null +++ b/dashboard/src/components/AccessRequestDialog.vue @@ -0,0 +1,134 @@ + - - diff --git a/dashboard/src/components/FileUploader.vue b/dashboard/src/components/FileUploader.vue index 8a41cd35074..d3f1cb4ae95 100644 --- a/dashboard/src/components/FileUploader.vue +++ b/dashboard/src/components/FileUploader.vue @@ -17,7 +17,7 @@ error, total, success, - openFileSelector + openFileSelector, }" /> @@ -30,7 +30,15 @@ import { trypromise } from '@/utils'; export default { name: 'FileUploader', - props: ['fileTypes', 'uploadArgs', 's3', 'type', 'fileValidator'], + props: [ + 'fileTypes', + 'uploadArgs', + 's3', + 'type', + 'fileValidator', + 'disableAutoUpload', + ], + emits: ['success', 'failure', 'setFile'], data() { return { uploader: null, @@ -40,7 +48,7 @@ export default { message: '', total: 0, file: null, - finishedUploading: false + finishedUploading: false, }; }, computed: { @@ -50,7 +58,7 @@ export default { }, success() { return this.finishedUploading && !this.error; - } + }, }, methods: { openFileSelector() { @@ -58,6 +66,12 @@ export default { }, async onFileAdd(e) { this.error = null; + this.finishedUploading = false; + this.uploading = false; + this.uploaded = 0; + this.total = 0; + this.message = ''; + this.file = e.target.files[0]; if (this.file && this.fileValidator) { @@ -67,11 +81,18 @@ export default { } } - if (!this.error) { - this.uploadFile(this.file); + if (this.error) { + this.$emit('failure', this.error); + return; } + + this.$emit('setFile', this.file); + if (!this.disableAutoUpload) await this.uploadFile(); }, - async uploadFile(file) { + async uploadFile() { + if (this.uploaded || this.finishedUploading || this.error || !this.file) { + return; + } this.error = null; this.uploaded = 0; this.total = 0; @@ -80,7 +101,7 @@ export default { this.uploader.on('start', () => { this.uploading = true; }); - this.uploader.on('progress', data => { + this.uploader.on('progress', (data) => { this.uploaded = data.uploaded; this.total = data.total; }); @@ -93,16 +114,16 @@ export default { this.finishedUploading = true; }); this.uploader - .upload(file, this.uploadArgs || {}) - .then(data => { + .upload(this.file, this.uploadArgs || {}) + .then((data) => { this.$emit('success', data); }) - .catch(error => { + .catch((error) => { this.uploading = false; let errorMessage = 'Error Uploading File'; if (error._server_messages) { errorMessage = JSON.parse( - JSON.parse(error._server_messages)[0] + JSON.parse(error._server_messages)[0], ).message; } else if (error.exc) { errorMessage = JSON.parse(error.exc)[0] @@ -112,7 +133,7 @@ export default { this.error = errorMessage; this.$emit('failure', errorMessage); }); - } - } + }, + }, }; diff --git a/dashboard/src/components/FilterControl.vue b/dashboard/src/components/FilterControl.vue new file mode 100644 index 00000000000..9f4c7737814 --- /dev/null +++ b/dashboard/src/components/FilterControl.vue @@ -0,0 +1,26 @@ + + diff --git a/dashboard/src/components/FoldStep.vue b/dashboard/src/components/FoldStep.vue new file mode 100644 index 00000000000..81c9d561c81 --- /dev/null +++ b/dashboard/src/components/FoldStep.vue @@ -0,0 +1,107 @@ + + diff --git a/dashboard/src/components/Form.vue b/dashboard/src/components/Form.vue index efb272ade4a..19437e6247a 100644 --- a/dashboard/src/components/Form.vue +++ b/dashboard/src/components/Form.vue @@ -6,19 +6,14 @@ v-show="field.condition ? field.condition() : true" >
-
- + diff --git a/dashboard/src/components/FrappeCloudLogo.vue b/dashboard/src/components/FrappeCloudLogo.vue deleted file mode 100644 index cad9fb807df..00000000000 --- a/dashboard/src/components/FrappeCloudLogo.vue +++ /dev/null @@ -1,27 +0,0 @@ - diff --git a/dashboard/src/components/GenericDialog.vue b/dashboard/src/components/GenericDialog.vue new file mode 100644 index 00000000000..f9d03a878e8 --- /dev/null +++ b/dashboard/src/components/GenericDialog.vue @@ -0,0 +1,28 @@ + + diff --git a/dashboard/src/components/GenericDialogField.vue b/dashboard/src/components/GenericDialogField.vue new file mode 100644 index 00000000000..9c4c0d35981 --- /dev/null +++ b/dashboard/src/components/GenericDialogField.vue @@ -0,0 +1,43 @@ + + diff --git a/dashboard/src/components/GenericList.vue b/dashboard/src/components/GenericList.vue new file mode 100644 index 00000000000..870c5f46658 --- /dev/null +++ b/dashboard/src/components/GenericList.vue @@ -0,0 +1,114 @@ + + + diff --git a/dashboard/src/components/GitHubAppSelector.vue b/dashboard/src/components/GitHubAppSelector.vue new file mode 100644 index 00000000000..2b70e215223 --- /dev/null +++ b/dashboard/src/components/GitHubAppSelector.vue @@ -0,0 +1,233 @@ + + + diff --git a/dashboard/src/components/Header.vue b/dashboard/src/components/Header.vue new file mode 100644 index 00000000000..bffea2683ed --- /dev/null +++ b/dashboard/src/components/Header.vue @@ -0,0 +1,19 @@ + + + diff --git a/dashboard/src/components/HomeSummary.vue b/dashboard/src/components/HomeSummary.vue new file mode 100644 index 00000000000..881ccaa5aad --- /dev/null +++ b/dashboard/src/components/HomeSummary.vue @@ -0,0 +1,57 @@ + + diff --git a/dashboard/src/components/ImpersonateTeam.vue b/dashboard/src/components/ImpersonateTeam.vue deleted file mode 100644 index 911c16f1b42..00000000000 --- a/dashboard/src/components/ImpersonateTeam.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - diff --git a/dashboard/src/components/InvoiceTable.vue b/dashboard/src/components/InvoiceTable.vue new file mode 100644 index 00000000000..981e9ed9bf9 --- /dev/null +++ b/dashboard/src/components/InvoiceTable.vue @@ -0,0 +1,228 @@ + + diff --git a/dashboard/src/components/InvoiceUsageCard.vue b/dashboard/src/components/InvoiceUsageCard.vue deleted file mode 100644 index ff7884475a0..00000000000 --- a/dashboard/src/components/InvoiceUsageCard.vue +++ /dev/null @@ -1,39 +0,0 @@ - - diff --git a/dashboard/src/components/InvoiceUsageTable.vue b/dashboard/src/components/InvoiceUsageTable.vue deleted file mode 100644 index 99aa3c98cd4..00000000000 --- a/dashboard/src/components/InvoiceUsageTable.vue +++ /dev/null @@ -1,124 +0,0 @@ - - diff --git a/dashboard/src/components/JobStep.vue b/dashboard/src/components/JobStep.vue new file mode 100644 index 00000000000..040142685ae --- /dev/null +++ b/dashboard/src/components/JobStep.vue @@ -0,0 +1,24 @@ + + diff --git a/dashboard/src/components/Link.vue b/dashboard/src/components/Link.vue new file mode 100644 index 00000000000..8b502923339 --- /dev/null +++ b/dashboard/src/components/Link.vue @@ -0,0 +1,19 @@ + + + diff --git a/dashboard/src/components/LinkControl.vue b/dashboard/src/components/LinkControl.vue new file mode 100644 index 00000000000..1db4b9323ba --- /dev/null +++ b/dashboard/src/components/LinkControl.vue @@ -0,0 +1,112 @@ + + diff --git a/dashboard/src/components/ListSelection.vue b/dashboard/src/components/ListSelection.vue new file mode 100644 index 00000000000..b2d3e1e5186 --- /dev/null +++ b/dashboard/src/components/ListSelection.vue @@ -0,0 +1,9 @@ + + diff --git a/dashboard/src/components/LoginSpinner.vue b/dashboard/src/components/LoginSpinner.vue new file mode 100644 index 00000000000..9a3e55d6b07 --- /dev/null +++ b/dashboard/src/components/LoginSpinner.vue @@ -0,0 +1,51 @@ + diff --git a/dashboard/src/components/ManageSitePlansDialog.vue b/dashboard/src/components/ManageSitePlansDialog.vue new file mode 100644 index 00000000000..e3b932739c8 --- /dev/null +++ b/dashboard/src/components/ManageSitePlansDialog.vue @@ -0,0 +1,260 @@ + + diff --git a/dashboard/src/components/MarketplaceAppCard.vue b/dashboard/src/components/MarketplaceAppCard.vue deleted file mode 100644 index 52ee153f238..00000000000 --- a/dashboard/src/components/MarketplaceAppCard.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - diff --git a/dashboard/src/components/MarketplaceAppDescriptions.vue b/dashboard/src/components/MarketplaceAppDescriptions.vue deleted file mode 100644 index e85313c2df6..00000000000 --- a/dashboard/src/components/MarketplaceAppDescriptions.vue +++ /dev/null @@ -1,188 +0,0 @@ - - - diff --git a/dashboard/src/components/MarketplaceAppLinks.vue b/dashboard/src/components/MarketplaceAppLinks.vue deleted file mode 100644 index 8eb46fb6ec0..00000000000 --- a/dashboard/src/components/MarketplaceAppLinks.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - diff --git a/dashboard/src/components/MarketplaceAppListing.vue b/dashboard/src/components/MarketplaceAppListing.vue new file mode 100644 index 00000000000..aeed72b8f5a --- /dev/null +++ b/dashboard/src/components/MarketplaceAppListing.vue @@ -0,0 +1,328 @@ + + + diff --git a/dashboard/src/components/MarketplaceAppProfile.vue b/dashboard/src/components/MarketplaceAppProfile.vue deleted file mode 100644 index 8dcef34237a..00000000000 --- a/dashboard/src/components/MarketplaceAppProfile.vue +++ /dev/null @@ -1,249 +0,0 @@ - - - diff --git a/dashboard/src/components/MarketplaceAppReleaseList.vue b/dashboard/src/components/MarketplaceAppReleaseList.vue deleted file mode 100644 index f94a47d20e8..00000000000 --- a/dashboard/src/components/MarketplaceAppReleaseList.vue +++ /dev/null @@ -1,330 +0,0 @@ - - - diff --git a/dashboard/src/components/MarketplaceAppScreenshots.vue b/dashboard/src/components/MarketplaceAppScreenshots.vue deleted file mode 100644 index 082dc1a760c..00000000000 --- a/dashboard/src/components/MarketplaceAppScreenshots.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - diff --git a/dashboard/src/components/MobileNav.vue b/dashboard/src/components/MobileNav.vue new file mode 100644 index 00000000000..a190471938d --- /dev/null +++ b/dashboard/src/components/MobileNav.vue @@ -0,0 +1,85 @@ + + diff --git a/dashboard/src/components/MobileNavItem.vue b/dashboard/src/components/MobileNavItem.vue new file mode 100644 index 00000000000..a455b50285e --- /dev/null +++ b/dashboard/src/components/MobileNavItem.vue @@ -0,0 +1,29 @@ + + diff --git a/dashboard/src/components/MobileNavItemGroup.vue b/dashboard/src/components/MobileNavItemGroup.vue new file mode 100644 index 00000000000..67c548d366b --- /dev/null +++ b/dashboard/src/components/MobileNavItemGroup.vue @@ -0,0 +1,49 @@ + + diff --git a/dashboard/src/components/Modal.vue b/dashboard/src/components/Modal.vue deleted file mode 100644 index fe66bc909a8..00000000000 --- a/dashboard/src/components/Modal.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - diff --git a/dashboard/src/components/Navbar.vue b/dashboard/src/components/Navbar.vue deleted file mode 100644 index e8e21aefc51..00000000000 --- a/dashboard/src/components/Navbar.vue +++ /dev/null @@ -1,181 +0,0 @@ - - - diff --git a/dashboard/src/components/NavigationItems.vue b/dashboard/src/components/NavigationItems.vue new file mode 100644 index 00000000000..61a66bb81ce --- /dev/null +++ b/dashboard/src/components/NavigationItems.vue @@ -0,0 +1,243 @@ + + diff --git a/dashboard/src/components/NewAppDialog.vue b/dashboard/src/components/NewAppDialog.vue new file mode 100644 index 00000000000..9c2805e971b --- /dev/null +++ b/dashboard/src/components/NewAppDialog.vue @@ -0,0 +1,286 @@ + + + diff --git a/dashboard/src/components/NewAppRepositories.vue b/dashboard/src/components/NewAppRepositories.vue deleted file mode 100644 index 6933e2d493f..00000000000 --- a/dashboard/src/components/NewAppRepositories.vue +++ /dev/null @@ -1,108 +0,0 @@ - - diff --git a/dashboard/src/components/Notification.vue b/dashboard/src/components/Notification.vue deleted file mode 100644 index be9fdb0445e..00000000000 --- a/dashboard/src/components/Notification.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/dashboard/src/components/NotificationToasts.vue b/dashboard/src/components/NotificationToasts.vue deleted file mode 100644 index f5492d2b989..00000000000 --- a/dashboard/src/components/NotificationToasts.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/dashboard/src/components/ObjectList.vue b/dashboard/src/components/ObjectList.vue new file mode 100644 index 00000000000..d0f81c231e9 --- /dev/null +++ b/dashboard/src/components/ObjectList.vue @@ -0,0 +1,510 @@ + + diff --git a/dashboard/src/components/ObjectListCell.vue b/dashboard/src/components/ObjectListCell.vue new file mode 100644 index 00000000000..f7c5faffbff --- /dev/null +++ b/dashboard/src/components/ObjectListCell.vue @@ -0,0 +1,149 @@ + + diff --git a/dashboard/src/components/ObjectListFilters.vue b/dashboard/src/components/ObjectListFilters.vue new file mode 100644 index 00000000000..d5ca3ebb266 --- /dev/null +++ b/dashboard/src/components/ObjectListFilters.vue @@ -0,0 +1,92 @@ + + diff --git a/dashboard/src/components/Onboarding.vue b/dashboard/src/components/Onboarding.vue new file mode 100644 index 00000000000..63ffbcebf6b --- /dev/null +++ b/dashboard/src/components/Onboarding.vue @@ -0,0 +1,312 @@ + + diff --git a/dashboard/src/components/OnboardingAppSelector.vue b/dashboard/src/components/OnboardingAppSelector.vue new file mode 100644 index 00000000000..73666adcd44 --- /dev/null +++ b/dashboard/src/components/OnboardingAppSelector.vue @@ -0,0 +1,63 @@ + + diff --git a/dashboard/src/components/OnboardingWithoutPayment.vue b/dashboard/src/components/OnboardingWithoutPayment.vue new file mode 100644 index 00000000000..08a0752ba14 --- /dev/null +++ b/dashboard/src/components/OnboardingWithoutPayment.vue @@ -0,0 +1,65 @@ + + diff --git a/dashboard/src/components/PayoutTable.vue b/dashboard/src/components/PayoutTable.vue new file mode 100644 index 00000000000..76debd0d7f5 --- /dev/null +++ b/dashboard/src/components/PayoutTable.vue @@ -0,0 +1,91 @@ + + diff --git a/dashboard/src/components/PlanIcon.vue b/dashboard/src/components/PlanIcon.vue deleted file mode 100644 index 3e8331dd45c..00000000000 --- a/dashboard/src/components/PlanIcon.vue +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/dashboard/src/components/PlansCards.vue b/dashboard/src/components/PlansCards.vue new file mode 100644 index 00000000000..f96bf8f9e63 --- /dev/null +++ b/dashboard/src/components/PlansCards.vue @@ -0,0 +1,129 @@ + + + diff --git a/dashboard/src/components/Popover.vue b/dashboard/src/components/Popover.vue deleted file mode 100644 index 7422a2ff049..00000000000 --- a/dashboard/src/components/Popover.vue +++ /dev/null @@ -1,194 +0,0 @@ - - - - diff --git a/dashboard/src/components/PrepaidCreditsDialog.vue b/dashboard/src/components/PrepaidCreditsDialog.vue deleted file mode 100644 index e346cc613eb..00000000000 --- a/dashboard/src/components/PrepaidCreditsDialog.vue +++ /dev/null @@ -1,196 +0,0 @@ - - diff --git a/dashboard/src/components/PrinterIcon.vue b/dashboard/src/components/PrinterIcon.vue deleted file mode 100644 index e029abcd209..00000000000 --- a/dashboard/src/components/PrinterIcon.vue +++ /dev/null @@ -1,45 +0,0 @@ - diff --git a/dashboard/src/components/ProgressArc.vue b/dashboard/src/components/ProgressArc.vue deleted file mode 100644 index e339943d1df..00000000000 --- a/dashboard/src/components/ProgressArc.vue +++ /dev/null @@ -1,61 +0,0 @@ - - diff --git a/dashboard/src/components/RichSelect.vue b/dashboard/src/components/RichSelect.vue deleted file mode 100644 index dd546552a67..00000000000 --- a/dashboard/src/components/RichSelect.vue +++ /dev/null @@ -1,83 +0,0 @@ - - diff --git a/dashboard/src/components/SelectAppFromGithub.vue b/dashboard/src/components/SelectAppFromGithub.vue deleted file mode 100644 index 7c0c3401047..00000000000 --- a/dashboard/src/components/SelectAppFromGithub.vue +++ /dev/null @@ -1,205 +0,0 @@ - - - diff --git a/dashboard/src/components/SelectableCard.vue b/dashboard/src/components/SelectableCard.vue deleted file mode 100644 index d8fb9538994..00000000000 --- a/dashboard/src/components/SelectableCard.vue +++ /dev/null @@ -1,32 +0,0 @@ - - diff --git a/dashboard/src/components/ServerPlansTable.vue b/dashboard/src/components/ServerPlansTable.vue deleted file mode 100644 index f8802bda70b..00000000000 --- a/dashboard/src/components/ServerPlansTable.vue +++ /dev/null @@ -1,67 +0,0 @@ - - - diff --git a/dashboard/src/components/Sidebar.vue b/dashboard/src/components/Sidebar.vue deleted file mode 100644 index 1ba07b73537..00000000000 --- a/dashboard/src/components/Sidebar.vue +++ /dev/null @@ -1,172 +0,0 @@ - - - diff --git a/dashboard/src/components/SiteActionCell.vue b/dashboard/src/components/SiteActionCell.vue new file mode 100644 index 00000000000..bacb50db4f2 --- /dev/null +++ b/dashboard/src/components/SiteActionCell.vue @@ -0,0 +1,304 @@ + + + diff --git a/dashboard/src/components/SiteActions.vue b/dashboard/src/components/SiteActions.vue new file mode 100644 index 00000000000..75afebb5a2f --- /dev/null +++ b/dashboard/src/components/SiteActions.vue @@ -0,0 +1,55 @@ + + diff --git a/dashboard/src/components/SiteAppUpdates.vue b/dashboard/src/components/SiteAppUpdates.vue deleted file mode 100644 index f71c53b5f45..00000000000 --- a/dashboard/src/components/SiteAppUpdates.vue +++ /dev/null @@ -1,21 +0,0 @@ - - diff --git a/dashboard/src/components/SiteDailyUsage.vue b/dashboard/src/components/SiteDailyUsage.vue new file mode 100644 index 00000000000..b9470fb0c8c --- /dev/null +++ b/dashboard/src/components/SiteDailyUsage.vue @@ -0,0 +1,75 @@ + + diff --git a/dashboard/src/components/SiteDatabaseAccessDialog.vue b/dashboard/src/components/SiteDatabaseAccessDialog.vue new file mode 100644 index 00000000000..e97bd1a19c6 --- /dev/null +++ b/dashboard/src/components/SiteDatabaseAccessDialog.vue @@ -0,0 +1,285 @@ + + diff --git a/dashboard/src/components/SiteDatabaseRestoreDialog.vue b/dashboard/src/components/SiteDatabaseRestoreDialog.vue new file mode 100644 index 00000000000..5cf3a190484 --- /dev/null +++ b/dashboard/src/components/SiteDatabaseRestoreDialog.vue @@ -0,0 +1,155 @@ + + diff --git a/dashboard/src/components/SiteOverview.vue b/dashboard/src/components/SiteOverview.vue new file mode 100644 index 00000000000..2d116d305ea --- /dev/null +++ b/dashboard/src/components/SiteOverview.vue @@ -0,0 +1,488 @@ + + diff --git a/dashboard/src/components/SitePlansCards.vue b/dashboard/src/components/SitePlansCards.vue new file mode 100644 index 00000000000..65d447546fe --- /dev/null +++ b/dashboard/src/components/SitePlansCards.vue @@ -0,0 +1,147 @@ + + + diff --git a/dashboard/src/components/SitePlansTable.vue b/dashboard/src/components/SitePlansTable.vue deleted file mode 100644 index 79866adc6da..00000000000 --- a/dashboard/src/components/SitePlansTable.vue +++ /dev/null @@ -1,63 +0,0 @@ - - - diff --git a/dashboard/src/components/SiteUpdateCard.vue b/dashboard/src/components/SiteUpdateCard.vue deleted file mode 100644 index 5235758dc56..00000000000 --- a/dashboard/src/components/SiteUpdateCard.vue +++ /dev/null @@ -1,60 +0,0 @@ - - - diff --git a/dashboard/src/components/SiteUpdateDialog.vue b/dashboard/src/components/SiteUpdateDialog.vue new file mode 100644 index 00000000000..ee2d64c8aa1 --- /dev/null +++ b/dashboard/src/components/SiteUpdateDialog.vue @@ -0,0 +1,252 @@ + + diff --git a/dashboard/src/components/Steps.vue b/dashboard/src/components/Steps.vue deleted file mode 100644 index 30cf4f5658f..00000000000 --- a/dashboard/src/components/Steps.vue +++ /dev/null @@ -1,90 +0,0 @@ - - diff --git a/dashboard/src/components/StorageBreakupChart.vue b/dashboard/src/components/StorageBreakupChart.vue new file mode 100644 index 00000000000..d76e21b0f84 --- /dev/null +++ b/dashboard/src/components/StorageBreakupChart.vue @@ -0,0 +1,162 @@ + + + diff --git a/dashboard/src/components/StripeCard.vue b/dashboard/src/components/StripeCard.vue index 934a9690f2b..dc4ec41e059 100644 --- a/dashboard/src/components/StripeCard.vue +++ b/dashboard/src/components/StripeCard.vue @@ -2,23 +2,23 @@
- -
@@ -56,7 +56,7 @@ diff --git a/dashboard/src/components/StripeCardDialog.vue b/dashboard/src/components/StripeCardDialog.vue new file mode 100644 index 00000000000..2847dd55b5c --- /dev/null +++ b/dashboard/src/components/StripeCardDialog.vue @@ -0,0 +1,40 @@ + + diff --git a/dashboard/src/components/Summary.vue b/dashboard/src/components/Summary.vue new file mode 100644 index 00000000000..c2d7bd5b3b2 --- /dev/null +++ b/dashboard/src/components/Summary.vue @@ -0,0 +1,29 @@ + + + diff --git a/dashboard/src/components/SupportAccessDialog.vue b/dashboard/src/components/SupportAccessDialog.vue new file mode 100644 index 00000000000..1680c1566c9 --- /dev/null +++ b/dashboard/src/components/SupportAccessDialog.vue @@ -0,0 +1,249 @@ + + + diff --git a/dashboard/src/components/SwitchTeamDialog.vue b/dashboard/src/components/SwitchTeamDialog.vue index d31a2c035ce..d9633da5654 100644 --- a/dashboard/src/components/SwitchTeamDialog.vue +++ b/dashboard/src/components/SwitchTeamDialog.vue @@ -1,34 +1,121 @@