diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index aaee198..bddbadb 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -35,3 +35,8 @@ jobs:
- name: Lint Frontend
run: npx biome check
+
+ - name: Lint TS errors
+ run: |
+ php artisan wayfinder:generate
+ npx vue-tsc --noEmit --checkJs --project tsconfig.json
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 038f158..f0d01f3 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -13,38 +13,47 @@ on:
jobs:
ci:
runs-on: ubuntu-latest
+ services:
+ postgres:
+ image: postgres:15
+ env:
+ POSTGRES_USER: test
+ POSTGRES_PASSWORD: secret
+ POSTGRES_DB: test_db
+ ports:
+ - 5432:5432
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
steps:
- - name: Checkout
- uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
+ - uses: shivammathur/setup-php@v2
with:
php-version: 8.4
tools: composer:v2
coverage: xdebug
- - name: Setup Node
- uses: actions/setup-node@v4
+ - uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- - name: Install Node Dependencies
- run: npm ci
-
- - name: Install Dependencies
- run: composer install --no-interaction --prefer-dist --optimize-autoloader
-
- - name: Copy Environment File
- run: cp .env.example .env
-
- - name: Generate Application Key
- run: php artisan key:generate
-
- - name: Build Assets
- run: npm run build
+ - run: npm ci
+ - run: composer install --no-interaction --prefer-dist --optimize-autoloader
+ - run: cp .env.example .env
+ - run: php artisan key:generate
+ - run: npm run build
- name: Tests
+ env:
+ DB_CONNECTION: pgsql
+ DB_HOST: 127.0.0.1
+ DB_PORT: 5432
+ DB_DATABASE: test_db
+ DB_USERNAME: test
+ DB_PASSWORD: secret
run: ./vendor/bin/pest
diff --git a/app/Console/Commands/LoadProLang.php b/app/Console/Commands/LoadProLang.php
index 1a3ae26..10602ca 100644
--- a/app/Console/Commands/LoadProLang.php
+++ b/app/Console/Commands/LoadProLang.php
@@ -51,9 +51,9 @@ private function saveProLang(array $item) {
'name' => $yearGroup['name'],
),
array(
- 'apiId' => $yearGroup['id'],
- 'position' => $yearGroup['position'],
- 'name' => $yearGroup['name'],
+ 'apiId' => $yearGroup['id'] ?? null,
+ 'position' => $yearGroup['position'] ?? null,
+ 'name' => $yearGroup['name'] ?? null,
));
$updatedLang = ProLang::updateOrCreate(
@@ -118,12 +118,92 @@ private function getLanguages(int $page) {
}
/**
- * Execute the console command.
+ * Add some languages like Phel missing in prolang api
*/
+ private function addProLanguage() {
+ $langToAdd = array(
+ // Data : https://phel-lang.org/ and preums itselft
+ array(
+ 'authors' => array(),
+ 'company' => null,
+ 'id' => uniqid().'_Phel',
+ 'link' => '',
+ 'name' => 'Phel',
+ 'predecessors' => array(),
+ 'yearGroup' => array(
+ 'name' => '2020s',
+ ),
+ 'years' => array(2020),
+ ),
+ // Data : https://janet-lang.org/ and preums itselft
+ array(
+ 'authors' => array(),
+ 'company' => null,
+ 'id' => uniqid().'_Janet',
+ 'link' => '',
+ 'name' => 'Janet',
+ 'predecessors' => array(),
+ 'yearGroup' => array(
+ 'name' => '2010s',
+ ),
+ 'years' => array(2017),
+ ),
+ );
+
+ foreach ($langToAdd as $item) {
+ $this->saveProLang($item);
+ Log::info('action=add_missing_lang, status=succes, lang='.$item['name']);
+ }
+ }
+
+ /**
+ * Add links between languages
+ * - Some data are missing from prolang api
+ * - Ex : Php is Hack's predecessors
+ */
+ private function updateLangFamily() {
+ $langFamilies = array(
+ // Data: https://github.com/janet-lang/janet
+ 'Janet' => array('C'),
+ // Data : https://phel-lang.org/
+ 'Phel' => array('PHP', 'Clojure', 'Janet', 'Lisp'),
+ // https://en.wikipedia.org/wiki/PHP
+ 'PHP' => array('C', 'C++', 'Perl'),
+ // Data : https://en.wikipedia.org/wiki/Hack_(programming_language)
+ 'Hack' => array('PHP', 'OCaml', 'Java', 'Scala', 'Haskell', 'C#'),
+ // Data : https://crystal-lang.org/ and https://en.wikipedia.org/wiki/Crystal_(programming_language)
+ 'Crystal' => array('Ruby', 'Go'),
+ // Data : https://en.wikipedia.org/wiki/Ruby_(programming_language)
+ 'Ruby' => array('Ada', 'Eiffel', 'Lua', 'Dylan'),
+ // Data : https://en.wikipedia.org/wiki/Dylan_(programming_language)
+ 'Dylan' => array('ALGOL 60', 'EuLisp'),
+ // Data : https://en.wikipedia.org/wiki/Lasso_(programming_language)
+ 'Lasso' => array('Dylan', 'Scala'),
+ );
+
+ foreach ($langFamilies as $name => $value) {
+ $lang = ProLang::where('name', $name)->first();
+ if ($lang) {
+ $parents = ProLang::whereIn(
+ 'name', $value
+ )->pluck('id');
+
+ $lang->parents()->sync($parents);
+ $lang->save();
+
+ Log::info("action=save_lang, status=success, lang=$name");
+ } else {
+ Log::info("action=save_lang, status=failed, reason=lang $name not found");
+ }
+ }
+ }
+
public function handle() {
Log::info('action=load_prolang_command, status=started');
$this->getLanguages(1);
+ $this->addProLanguage();
+ $this->updateLangFamily();
Log::info('action=load_prolang_command, status=finished');
}
diff --git a/app/Console/Commands/ProLangAssets.php b/app/Console/Commands/ProLangAssets.php
index 5cd41c7..d6894e1 100644
--- a/app/Console/Commands/ProLangAssets.php
+++ b/app/Console/Commands/ProLangAssets.php
@@ -1117,6 +1117,12 @@ function member
),
'Common Lisp' => array(),
'Windows PowerShell' => array(),
+ 'Phel' => array(
+ 'mainRepository' => 'https://github.com/phel-lang/phel-lang',
+ ),
+ 'Janet' => array(
+ 'mainRepository' => 'https://github.com/janet-lang/janet',
+ ),
);
DB::transaction(function () use ($langsData) {
@@ -1141,9 +1147,10 @@ function member
*/
public function handle() {
Log::info('action=prolang_assets_command, status=started');
- $this->updateAssets();
- Log::info('action=prolang_assets_command, status=finished');
+ $this->updateAssets();
$this->updateLinks();
+
+ Log::info('action=prolang_assets_command, status=finished');
}
}
diff --git a/app/Models/ProLang.php b/app/Models/ProLang.php
index c575573..fead52a 100644
--- a/app/Models/ProLang.php
+++ b/app/Models/ProLang.php
@@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+use Illuminate\Support\Facades\DB;
/**
* @property int $id
@@ -21,6 +22,8 @@
class ProLang extends Model {
protected $guarded = array('id');
+ protected $appends = array('paths');
+
protected $casts = array(
'years' => 'array',
);
@@ -52,4 +55,38 @@ public function authors(): BelongsToMany {
public function authorNames(): array {
return $this->authors()->pluck('name')->toArray();
}
+
+ // paths
+
+ public function getPathsAttribute() {
+ $targetId = DB::table('pro_langs')->where('id', $this->id)->value('id');
+
+ $paths = DB::select("
+ WITH RECURSIVE paths AS (
+ SELECT
+ l.id,
+ l.name,
+ l.name::text AS path
+ FROM pro_langs l
+ WHERE NOT EXISTS (
+ SELECT 1 FROM predecessors p WHERE p.child_id = l.id
+ )
+
+ UNION ALL
+
+ SELECT
+ c.id,
+ c.name,
+ paths.path || ' -> ' || c.name
+ FROM paths
+ JOIN predecessors p ON p.parent_id = paths.id
+ JOIN pro_langs c ON c.id = p.child_id
+ )
+ SELECT path
+ FROM paths
+ WHERE id = ?
+ ", array($targetId));
+
+ return array_map(fn ($r) => $r->path, $paths);
+ }
}
diff --git a/package-lock.json b/package-lock.json
index faf7b7f..0e20858 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,6 @@
"@hackernoon/pixel-icon-library": "^1.0.6",
"@inertiajs/vue3": "^2.2.19",
"@nanostores/vue": "^1.0.1",
- "@tailwindcss/vite": "^4.1.11",
"@vueuse/core": "^12.8.2",
"@yeger/vue-masonry-wall": "^5.1.4",
"chart.js": "^4.5.1",
@@ -43,19 +42,6 @@
"lightningcss-linux-x64-gnu": "^1.29.1"
}
},
- "node_modules/@ampproject/remapping": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/@awesome.me/webawesome": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@awesome.me/webawesome/-/webawesome-3.0.0.tgz",
@@ -734,53 +720,12 @@
"vue": "^3.0.0"
}
},
- "node_modules/@isaacs/fs-minipass": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
- "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^7.0.4"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.12",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
- "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
"license": "MIT"
},
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.29",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
- "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
"node_modules/@kurkle/color": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
@@ -1527,79 +1472,6 @@
"integrity": "sha512-r4C9C/5kSfMBIr0D9imvpRdCNXtUNgyYThc4YlS6K5Hchv1UyxNQ9mxwj+BTRH2i1Neits260sR3OjKMnplsFA==",
"license": "MIT"
},
- "node_modules/@tailwindcss/node": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz",
- "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==",
- "license": "MIT",
- "dependencies": {
- "@ampproject/remapping": "^2.3.0",
- "enhanced-resolve": "^5.18.1",
- "jiti": "^2.4.2",
- "lightningcss": "1.30.1",
- "magic-string": "^0.30.17",
- "source-map-js": "^1.2.1",
- "tailwindcss": "4.1.11"
- }
- },
- "node_modules/@tailwindcss/oxide": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz",
- "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.4",
- "tar": "^7.4.3"
- },
- "engines": {
- "node": ">= 10"
- },
- "optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.1.11",
- "@tailwindcss/oxide-darwin-arm64": "4.1.11",
- "@tailwindcss/oxide-darwin-x64": "4.1.11",
- "@tailwindcss/oxide-freebsd-x64": "4.1.11",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11",
- "@tailwindcss/oxide-linux-arm64-musl": "4.1.11",
- "@tailwindcss/oxide-linux-x64-gnu": "4.1.11",
- "@tailwindcss/oxide-linux-x64-musl": "4.1.11",
- "@tailwindcss/oxide-wasm32-wasi": "4.1.11",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11",
- "@tailwindcss/oxide-win32-x64-msvc": "4.1.11"
- }
- },
- "node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz",
- "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@tailwindcss/vite": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz",
- "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==",
- "license": "MIT",
- "dependencies": {
- "@tailwindcss/node": "4.1.11",
- "@tailwindcss/oxide": "4.1.11",
- "tailwindcss": "4.1.11"
- },
- "peerDependencies": {
- "vite": "^5.2.0 || ^6 || ^7"
- }
- },
"node_modules/@types/conventional-commits-parser": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.2.tgz",
@@ -2177,15 +2049,6 @@
"url": "https://paulmillr.com/funding/"
}
},
- "node_modules/chownr": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
- "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/class-variance-authority": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
@@ -2530,6 +2393,8 @@
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"license": "Apache-2.0",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=8"
}
@@ -2581,19 +2446,6 @@
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
},
- "node_modules/enhanced-resolve": {
- "version": "5.18.2",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
- "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.2.0"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@@ -2916,12 +2768,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -3153,6 +2999,7 @@
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "devOptional": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
@@ -3244,6 +3091,8 @@
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
"license": "MPL-2.0",
+ "optional": true,
+ "peer": true,
"dependencies": {
"detect-libc": "^2.0.3"
},
@@ -3279,6 +3128,7 @@
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3299,6 +3149,7 @@
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3319,6 +3170,7 @@
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3339,6 +3191,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3359,6 +3212,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3379,6 +3233,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3419,6 +3274,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3439,6 +3295,7 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3459,6 +3316,7 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3479,6 +3337,7 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 12.0.0"
},
@@ -3821,48 +3680,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/minizlib": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
- "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
- },
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"license": "MIT"
},
- "node_modules/mkdirp": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
- "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
- "license": "MIT",
- "bin": {
- "mkdirp": "dist/cjs/src/bin.js"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/muggle-string": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
@@ -4875,38 +4698,6 @@
"node": ">=16.0.0"
}
},
- "node_modules/tailwindcss": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
- "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
- "license": "MIT"
- },
- "node_modules/tapable": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz",
- "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tar": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
- "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
- "license": "ISC",
- "dependencies": {
- "@isaacs/fs-minipass": "^4.0.0",
- "chownr": "^3.0.0",
- "minipass": "^7.1.2",
- "minizlib": "^3.0.1",
- "mkdirp": "^3.0.1",
- "yallist": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/text-extensions": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
@@ -5377,15 +5168,6 @@
"node": ">=10"
}
},
- "node_modules/yallist": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
- "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
diff --git a/package.json b/package.json
index 0ef0851..bf2edaf 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,6 @@
"@hackernoon/pixel-icon-library": "^1.0.6",
"@inertiajs/vue3": "^2.2.19",
"@nanostores/vue": "^1.0.1",
- "@tailwindcss/vite": "^4.1.11",
"@vueuse/core": "^12.8.2",
"@yeger/vue-masonry-wall": "^5.1.4",
"chart.js": "^4.5.1",
diff --git a/resources/js/components/prolang/LangCard.vue b/resources/js/components/prolang/LangCard.vue
index 41b66c9..89de930 100644
--- a/resources/js/components/prolang/LangCard.vue
+++ b/resources/js/components/prolang/LangCard.vue
@@ -1,7 +1,7 @@
@@ -89,8 +89,13 @@
- Close
+ Close
+
@@ -145,7 +150,7 @@ import { computed, ref } from "vue"
import type { ProLangLanguage } from "@/types/main"
const code = ref(null)
-const emits = defineEmits(["select-lang"])
+const emits = defineEmits(["select-lang", "close"])
const props = defineProps<{
lang: ProLangLanguage
diff --git a/resources/js/components/repository/RepositoryDetails.vue b/resources/js/components/repository/RepositoryDetails.vue
index 7446e42..a48449a 100644
--- a/resources/js/components/repository/RepositoryDetails.vue
+++ b/resources/js/components/repository/RepositoryDetails.vue
@@ -11,9 +11,9 @@
diff --git a/resources/js/lib/utils.ts b/resources/js/lib/utils.ts
deleted file mode 100644
index 03aaa4b..0000000
--- a/resources/js/lib/utils.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { type ClassValue, clsx } from "clsx"
-import { twMerge } from "tailwind-merge"
-
-export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
-}
diff --git a/resources/js/pages/LangHistory.vue b/resources/js/pages/LangHistory.vue
index 981fb6a..7506cf3 100644
--- a/resources/js/pages/LangHistory.vue
+++ b/resources/js/pages/LangHistory.vue
@@ -56,7 +56,8 @@
@@ -84,12 +85,17 @@ const props = defineProps<{
groups: YearGroup[]
}>()
-function updateSelectedLang(value: string) {
- if (searchLang.value.length > 0) {
+function updateSelectedLang(value: string, forClose: boolean) {
+ if (forClose) {
+ selectedLang.value = ""
+ } else {
+ // if (searchLang.value.length > 0) {
+ // searchLang.value = value
+ // }
+
searchLang.value = value
+ selectedLang.value = value
}
-
- selectedLang.value = value
}
const showGroups = computed(() => {
diff --git a/resources/js/pages/RepositoryHistory.vue b/resources/js/pages/RepositoryHistory.vue
index 9481afd..818f6aa 100644
--- a/resources/js/pages/RepositoryHistory.vue
+++ b/resources/js/pages/RepositoryHistory.vue
@@ -67,10 +67,10 @@ import RepositoryDetails from "@/components/repository/RepositoryDetails.vue"
import RepositoryLanguages from "@/components/repository/RepositoryLanguages.vue"
import RepositoryRelease from "@/components/repository/RepositoryRelease.vue"
import RepositoryTopics from "@/components/repository/RepositoryTopics.vue"
-import type { GithubCommit, GithubCommitActivity, GithubCommitDiff, GithubRelease, GithubSearchResultItem } from "@/types/main"
+import type { GithubCommit, GithubCommitActivity, GithubCommitDiff, GithubRelease, GithubRepository } from "@/types/main"
const props = defineProps<{
- repository: GithubSearchResultItem
+ repository: GithubRepository
commits: {
firstCommit: GithubCommit | null
lastCommit: GithubCommit
diff --git a/resources/js/types/main.d.ts b/resources/js/types/main.d.ts
index 71e7ef0..60558e5 100644
--- a/resources/js/types/main.d.ts
+++ b/resources/js/types/main.d.ts
@@ -112,7 +112,6 @@ export type ProLangAuthor = {
}
export type ProLangLanguage = {
- // TODO: add predecessors in hisotry
id: number
apiId: string
company: string | null
@@ -125,8 +124,9 @@ export type ProLangLanguage = {
codeTitle: string
rawCode: string | null
rawCodeLink: string | null
- children: ProLangLanguage[]
- parents: ProLangLanguage[]
+ children: Array>
+ parents: Array>
+ paths: string[]
}
export type YearGroup = {
diff --git a/tests/Datasets/ProLang.php b/tests/Datasets/ProLang.php
index 2164999..37f3eca 100644
--- a/tests/Datasets/ProLang.php
+++ b/tests/Datasets/ProLang.php
@@ -1,5 +1,8 @@
Http::response(
+ $prolang,
+ 200,
+ ),
+ ));
+
+ (new LoadProLang())->handle();
+}
+
+$proLang = getProLangSample('prolang-api.json');
dataset('prolang', array(
array($proLang))
diff --git a/tests/Unit/Commands/FroozeRepositoriesTest.php b/tests/Unit/Commands/FroozeRepositoriesTest.php
index 44db81b..03e1393 100644
--- a/tests/Unit/Commands/FroozeRepositoriesTest.php
+++ b/tests/Unit/Commands/FroozeRepositoriesTest.php
@@ -15,6 +15,12 @@
200,
),
));
+ Http::fake(array(
+ 'https://api.github.com/repos/*' => Http::response(
+ $repos[0],
+ 200,
+ ),
+ ));
FrozenRepository::insert(array(
'created_at' => Carbon::now(),
diff --git a/tests/Unit/Commands/LoadProLangTest.php b/tests/Unit/Commands/LoadProLangTest.php
index 79a237c..0d94a17 100644
--- a/tests/Unit/Commands/LoadProLangTest.php
+++ b/tests/Unit/Commands/LoadProLangTest.php
@@ -1,23 +1,11 @@
Http::response(
- $prolang,
- 200,
- ),
- ));
-
- (new LoadProLang())->handle();
- }
-
it('should call prolang api', function (array $prolang) {
mockProlangApi($prolang);
@@ -63,7 +51,7 @@ function mockProlangApi(array $prolang) {
expect(
ProLang::all()->count()
- )->toBe(29);
+ )->toBe(30);
expect(
ProLang::where('name', 'Icon')->count()
)->toBe(1);
diff --git a/tests/Unit/Models/ProLangTest.php b/tests/Unit/Models/ProLangTest.php
new file mode 100644
index 0000000..433f39c
--- /dev/null
+++ b/tests/Unit/Models/ProLangTest.php
@@ -0,0 +1,84 @@
+ '',
+ 'name' => '1990',
+ 'position' => 1,
+ ));
+
+ $parents = array_map(function (string $name) use ($group) {
+ $l = ProLang::create(array(
+ 'name' => $name,
+ 'apiId' => '',
+ 'link' => '',
+ 'company' => null,
+ 'years' => '["1990"]',
+ 'yearGroupId' => $group->id,
+ ));
+
+ return $l;
+ }, array('LiveScript', 'Perl'));
+
+ $lang = ProLang::create(array(
+ 'name' => 'JvaScript',
+ 'apiId' => '',
+ 'link' => '',
+ 'company' => null,
+ 'years' => '["1990"]',
+ 'yearGroupId' => $group->id,
+ ));
+
+ $anotherLang = ProLang::create(array(
+ 'name' => 'Awesome',
+ 'apiId' => '',
+ 'link' => '',
+ 'company' => null,
+ 'years' => '["1990"]',
+ 'yearGroupId' => $group->id,
+ ));
+
+ $lang->parents()->sync($parents);
+ $anotherLang->children()->sync(array(
+ $parents[0],
+ ));
+
+ expect(count($lang->paths))->toBe(2);
+ expect($lang->paths)->toContain('Perl -> JvaScript');
+ expect($lang->paths)->toContain('Awesome -> LiveScript -> JvaScript');
+});
+
+it('should be able to detect if it is an orphan lang', function () {
+ $group = YearGroup::create(array(
+ 'apiId' => '',
+ 'name' => '1990',
+ 'position' => 1,
+ ));
+
+ $lang = ProLang::create(array(
+ 'name' => 'JvaScript',
+ 'apiId' => '',
+ 'link' => '',
+ 'company' => null,
+ 'years' => '["1990"]',
+ 'yearGroupId' => $group->id,
+ ));
+
+ $anotherLang = ProLang::create(array(
+ 'name' => 'Awesome',
+ 'apiId' => '',
+ 'link' => '',
+ 'company' => null,
+ 'years' => '["1990"]',
+ 'yearGroupId' => $group->id,
+ ));
+
+ expect($lang->isOrphan())->toBe(true);
+
+ $lang->parents()->sync($anotherLang);
+
+ expect($lang->isOrphan())->toBe(false);
+});