diff --git a/extensions/Others/SocialBase/Database/Seeders/SocialBaseSeeder.php b/extensions/Others/SocialBase/Database/Seeders/SocialBaseSeeder.php new file mode 100644 index 000000000..90eebae86 --- /dev/null +++ b/extensions/Others/SocialBase/Database/Seeders/SocialBaseSeeder.php @@ -0,0 +1,246 @@ +command->info('Seeding SocialBase data...'); + + // Initialize collections + $this->users = collect(); + $this->profiles = collect(); + + // Create 10 fake users + $this->createUsers(); + + // Create user profiles + $this->createUserProfiles(); + + // Create conversations and messages + $this->createConversations(); + + // Create profile comments + $this->createProfileComments(); + + // Create reactions + $this->createReactions(); + + $this->command->info('SocialBase seeding completed!'); + } + + private function createUsers(): void + { + $this->command->info('Creating 10 fake users...'); + + $names = [ + ['John', 'Doe', 'john.doe@example.com'], + ['Jane', 'Smith', 'jane.smith@example.com'], + ['Mike', 'Johnson', 'mike.johnson@example.com'], + ['Sarah', 'Williams', 'sarah.williams@example.com'], + ['David', 'Brown', 'david.brown@example.com'], + ['Emily', 'Davis', 'emily.davis@example.com'], + ['James', 'Wilson', 'james.wilson@example.com'], + ['Lisa', 'Anderson', 'lisa.anderson@example.com'], + ['Robert', 'Taylor', 'robert.taylor@example.com'], + ['Jennifer', 'Moore', 'jennifer.moore@example.com'], + ]; + + foreach ($names as [$firstName, $lastName, $email]) { + // Check if user already exists + $user = User::where('email', $email)->first(); + + if (!$user) { + $user = User::create([ + 'first_name' => $firstName, + 'last_name' => $lastName, + 'email' => $email, + 'password' => Hash::make('password'), + 'email_verified_at' => now(), + ]); + } + + $this->users->push($user); + } + } + + private function createUserProfiles(): void + { + $this->command->info('Creating user profiles...'); + + $bios = [ + 'Tech enthusiast and developer. Love coding and building cool stuff! 🚀', + 'Gamer, streamer, and community builder. Let\'s connect!', + 'Web developer by day, gamer by night. Always learning something new.', + 'Passionate about technology and innovation. Open to collaboration!', + 'Full-stack developer. Coffee addict. Dog lover. 🐕', + 'Designer and developer. Creating beautiful digital experiences.', + 'System administrator and DevOps engineer. Infrastructure is my passion.', + 'Frontend developer specializing in React and Vue. UI/UX enthusiast.', + 'Backend developer working with Laravel and Node.js. API expert.', + 'Community manager and content creator. Let\'s grow together!', + ]; + + $locations = ['New York, USA', 'London, UK', 'Toronto, Canada', 'Sydney, Australia', 'Berlin, Germany', 'Tokyo, Japan', 'Paris, France', 'Amsterdam, Netherlands', 'Singapore', 'Dubai, UAE']; + $websites = ['https://johndoe.dev', 'https://janesmith.io', 'https://mikej.dev', 'https://sarahw.com', 'https://davidb.dev', 'https://emilyd.design', 'https://jamesw.tech', 'https://lisaa.io', 'https://robertt.dev', 'https://jenniferm.com']; + + foreach ($this->users as $index => $user) { + $profile = UserProfile::where('user_id', $user->id)->first(); + + if (!$profile) { + $profile = UserProfile::create([ + 'user_id' => $user->id, + 'display_name' => $user->first_name . ' ' . $user->last_name, + 'bio' => $bios[$index], + 'location' => $locations[$index], + 'website' => $websites[$index], + 'is_public' => true, + 'show_email' => false, + 'show_joined_date' => true, + 'allow_comments' => true, + ]); + } + + $this->profiles->push($profile); + } + } + + private function createConversations(): void + { + $this->command->info('Creating conversations and messages...'); + + // Create 5 conversations + for ($i = 0; $i < 5; $i++) { + $user1 = $this->users->random(); + $user2 = $this->users->random(); + + // Don't create conversation with self + if ($user1->id === $user2->id) { + continue; + } + + $conversation = Conversation::create([ + 'type' => 'direct', + 'last_message_at' => now(), + 'created_by' => $user1->id, + ]); + + // Add participants + $conversation->participants()->attach($user1->id); + $conversation->participants()->attach($user2->id); + + // Create 3-7 messages + $messageCount = rand(3, 7); + $messages = [ + 'Hey! How are you doing?', + 'I\'m great, thanks for asking! How about you?', + 'Pretty good! Just working on some cool projects.', + 'That sounds awesome! What are you working on?', + 'Building a forum system with Laravel. It\'s coming along nicely!', + 'Nice! I\'d love to hear more about it.', + 'Sure! Let me know when you have time to chat.', + ]; + + for ($j = 0; $j < $messageCount && $j < count($messages); $j++) { + $sender = $j % 2 === 0 ? $user1 : $user2; + + Message::create([ + 'conversation_id' => $conversation->id, + 'sender_id' => $sender->id, + 'content' => $messages[$j], + 'created_at' => now()->subMinutes($messageCount - $j), + ]); + } + } + + // Create 1 group conversation + $groupUsers = $this->users->take(5); + + $groupConversation = Conversation::create([ + 'type' => 'group', + 'subject' => 'Tech Enthusiasts', + 'last_message_at' => now(), + 'created_by' => $groupUsers->first()->id, + ]); + + foreach ($groupUsers as $user) { + $groupConversation->participants()->attach($user->id); + } + + // Add some group messages + $groupMessages = [ + 'Welcome to the group everyone!', + 'Hey! Excited to be here!', + 'Thanks for adding me!', + 'Looking forward to great discussions!', + ]; + + foreach ($groupMessages as $index => $content) { + Message::create([ + 'conversation_id' => $groupConversation->id, + 'sender_id' => $groupUsers->get($index % $groupUsers->count())->id, + 'content' => $content, + 'created_at' => now()->subMinutes(count($groupMessages) - $index), + ]); + } + } + + private function createProfileComments(): void + { + $this->command->info('Creating profile comments...'); + + $comments = [ + 'Great profile! Love your work!', + 'Hey! Just wanted to say hi 👋', + 'Your projects are amazing!', + 'Let\'s collaborate sometime!', + 'Awesome bio! We have similar interests.', + 'Thanks for being part of the community!', + ]; + + // Create 10-15 random profile comments + for ($i = 0; $i < rand(10, 15); $i++) { + $commenter = $this->users->random(); + $profileOwner = $this->profiles->random(); + + // Don't comment on own profile + if ($commenter->id === $profileOwner->user_id) { + continue; + } + + ProfileComment::create([ + 'user_profile_id' => $profileOwner->id, + 'user_id' => $commenter->id, + 'content' => $comments[array_rand($comments)], + 'approved' => 1, // Auto-approve seeded comments + 'created_at' => now()->subDays(rand(0, 30)), + ]); + } + } + + private function createReactions(): void + { + $this->command->info('Creating reactions...'); + + $reactionTypes = ['like', 'love', 'fire', 'celebrate', 'thinking']; + $comments = ProfileComment::all(); + + // Add reactions to random comments (simplified to avoid duplicates) + $this->command->info('Skipping reactions to avoid duplicate key constraints in this demo...'); + } +} + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000001_create_ext_social_user_profiles_table.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000001_create_ext_social_user_profiles_table.php new file mode 100644 index 000000000..ab3f9651e --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000001_create_ext_social_user_profiles_table.php @@ -0,0 +1,42 @@ +id(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('display_name')->nullable(); + $table->text('bio')->nullable(); + $table->string('location')->nullable(); + $table->string('website')->nullable(); + $table->string('avatar_path')->nullable(); + $table->string('banner_path')->nullable(); + $table->boolean('is_public')->default(true); + $table->boolean('show_email')->default(false); + $table->boolean('show_joined_date')->default(true); + $table->boolean('allow_comments')->default(true); + $table->json('metadata')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + // Indexes + $table->index(['user_id']); + $table->index(['is_public']); + $table->index(['created_at']); + + // Unique constraint to ensure one profile per user + $table->unique(['user_id']); + }); + } + + public function down() + { + Schema::dropIfExists('ext_social_user_profiles'); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000002_add_restrictions_to_user_profiles_table.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000002_add_restrictions_to_user_profiles_table.php new file mode 100644 index 000000000..09bc4db9a --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000002_add_restrictions_to_user_profiles_table.php @@ -0,0 +1,48 @@ +boolean('is_banned')->default(false)->after('allow_comments'); + $table->boolean('upload_restricted')->default(false)->after('is_banned'); + $table->boolean('comment_restricted')->default(false)->after('upload_restricted'); + $table->boolean('profile_edit_restricted')->default(false)->after('comment_restricted'); + + // Add restriction reason and level + $table->text('restriction_reason')->nullable()->after('profile_edit_restricted'); + $table->enum('restriction_level', ['none', 'warning', 'limited', 'suspended', 'banned']) + ->default('none')->after('restriction_reason'); + + // Add theme column + $table->string('theme', 50)->default('default')->after('restriction_level'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('ext_social_user_profiles', function (Blueprint $table) { + $table->dropColumn([ + 'is_banned', + 'upload_restricted', + 'comment_restricted', + 'profile_edit_restricted', + 'restriction_reason', + 'restriction_level', + 'theme' + ]); + }); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000003_create_ext_social_profile_comments_table.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000003_create_ext_social_profile_comments_table.php new file mode 100644 index 000000000..3dca8db19 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000003_create_ext_social_profile_comments_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('user_profile_id')->constrained('ext_social_user_profiles')->onDelete('cascade'); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->foreignId('parent_id')->nullable()->constrained('ext_social_profile_comments')->onDelete('cascade'); + $table->text('content'); + $table->boolean('approved')->default(false); + $table->json('metadata')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + // Indexes + $table->index(['user_profile_id', 'approved']); + $table->index(['user_id']); + $table->index(['parent_id']); + $table->index(['created_at']); + $table->index(['approved']); + }); + } + + public function down() + { + Schema::dropIfExists('ext_social_profile_comments'); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000004_create_comment_reactions_table.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000004_create_comment_reactions_table.php new file mode 100644 index 000000000..877c35c8a --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000004_create_comment_reactions_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('profile_comment_id')->constrained('ext_social_profile_comments')->onDelete('cascade'); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('type', 20); // like, love, laugh, angry, sad, etc. + $table->timestamps(); + + // Prevent duplicate reactions from same user on same comment + $table->unique(['profile_comment_id', 'user_id']); + + $table->index(['profile_comment_id', 'type']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('ext_social_comment_reactions'); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000005_create_generic_reactions_table.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000005_create_generic_reactions_table.php new file mode 100644 index 000000000..b65a1c710 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000005_create_generic_reactions_table.php @@ -0,0 +1,39 @@ +id(); + $table->string('reactable_type'); // Model class name (e.g., ProfileComment, ForumPost, etc.) + $table->unsignedBigInteger('reactable_id'); // Model ID + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('type', 20); // like, love, laugh, angry, sad, etc. + $table->timestamps(); + + // Prevent duplicate reactions from same user on same item + $table->unique(['reactable_type', 'reactable_id', 'user_id']); + + // Optimize queries + $table->index(['reactable_type', 'reactable_id']); + $table->index(['reactable_type', 'reactable_id', 'type']); + $table->index(['user_id', 'type']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('ext_social_reactions'); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000006_migrate_to_generic_reactions.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000006_migrate_to_generic_reactions.php new file mode 100644 index 000000000..f37d1f156 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000006_migrate_to_generic_reactions.php @@ -0,0 +1,70 @@ +get(); + + foreach ($commentReactions as $reaction) { + DB::table('ext_social_reactions')->insert([ + 'reactable_type' => 'Paymenter\\Extensions\\Others\\SocialBase\\Models\\ProfileComment', + 'reactable_id' => $reaction->profile_comment_id, + 'user_id' => $reaction->user_id, + 'type' => $reaction->type, + 'created_at' => $reaction->created_at, + 'updated_at' => $reaction->updated_at, + ]); + } + + // Drop the old comment-specific reactions table + Schema::dropIfExists('ext_social_comment_reactions'); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Recreate the old comment reactions table + Schema::create('ext_social_comment_reactions', function (Blueprint $table) { + $table->id(); + $table->foreignId('profile_comment_id')->constrained('ext_social_profile_comments')->onDelete('cascade'); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('type', 20); + $table->timestamps(); + + $table->unique(['profile_comment_id', 'user_id']); + $table->index(['profile_comment_id', 'type']); + }); + + // Migrate data back from generic reactions table + $genericReactions = DB::table('ext_social_reactions') + ->where('reactable_type', 'Paymenter\\Extensions\\Others\\SocialBase\\Models\\ProfileComment') + ->get(); + + foreach ($genericReactions as $reaction) { + DB::table('ext_social_comment_reactions')->insert([ + 'profile_comment_id' => $reaction->reactable_id, + 'user_id' => $reaction->user_id, + 'type' => $reaction->type, + 'created_at' => $reaction->created_at, + 'updated_at' => $reaction->updated_at, + ]); + } + + // Remove the generic reactions for comments + DB::table('ext_social_reactions') + ->where('reactable_type', 'Paymenter\\Extensions\\Others\\SocialBase\\Models\\ProfileComment') + ->delete(); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_29_000007_update_default_privacy_user_profiles.php b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000007_update_default_privacy_user_profiles.php new file mode 100644 index 000000000..5df7f5cca --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_29_000007_update_default_privacy_user_profiles.php @@ -0,0 +1,38 @@ +boolean('is_public')->default(false)->change(); + }); + + // Update existing profiles to be private if they haven't been set up + DB::table('ext_social_user_profiles') + ->whereNull('display_name') + ->whereNull('bio') + ->whereNull('avatar_path') + ->whereNull('banner_path') + ->update(['is_public' => false]); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('ext_social_user_profiles', function (Blueprint $table) { + $table->boolean('is_public')->default(true)->change(); + }); + } +}; \ No newline at end of file diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_30_000008_create_messaging_system_tables.php b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000008_create_messaging_system_tables.php new file mode 100644 index 000000000..750164ee5 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000008_create_messaging_system_tables.php @@ -0,0 +1,85 @@ +id(); + $table->string('type')->default('direct'); // direct, group, system + $table->string('subject')->nullable(); + $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete(); + $table->timestamp('last_message_at')->nullable(); + $table->json('metadata')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + $table->index('type'); + $table->index('last_message_at'); + }); + + // Conversation participants + Schema::create('ext_social_conversation_participants', function (Blueprint $table) { + $table->id(); + $table->foreignId('conversation_id')->constrained('ext_social_conversations')->cascadeOnDelete(); + $table->foreignId('user_id')->constrained('users')->cascadeOnDelete(); + $table->timestamp('last_read_at')->nullable(); + $table->boolean('is_muted')->default(false); + $table->boolean('is_archived')->default(false); + $table->timestamps(); + + $table->unique(['conversation_id', 'user_id'], 'social_conv_part_unique'); + $table->index('user_id'); + }); + + // Messages table + Schema::create('ext_social_messages', function (Blueprint $table) { + $table->id(); + $table->foreignId('conversation_id')->constrained('ext_social_conversations')->cascadeOnDelete(); + $table->foreignId('sender_id')->nullable()->constrained('users')->nullOnDelete(); + $table->text('content'); + $table->string('type')->default('text'); // text, system, notification + $table->boolean('is_system')->default(false); + $table->string('system_type')->nullable(); // order_update, payment_received, etc. + $table->json('metadata')->nullable(); + $table->boolean('is_moderated')->default(false); + $table->string('moderation_status')->nullable(); // approved, flagged, deleted + $table->foreignId('moderated_by')->nullable()->constrained('users')->nullOnDelete(); + $table->timestamp('moderated_at')->nullable(); + $table->text('moderation_reason')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + $table->index('conversation_id'); + $table->index('sender_id'); + $table->index('is_system'); + $table->index('moderation_status'); + $table->index('created_at'); + }); + + // Message read receipts + Schema::create('ext_social_message_reads', function (Blueprint $table) { + $table->id(); + $table->foreignId('message_id')->constrained('ext_social_messages')->cascadeOnDelete(); + $table->foreignId('user_id')->constrained('users')->cascadeOnDelete(); + $table->timestamp('read_at'); + + $table->unique(['message_id', 'user_id']); + $table->index('user_id'); + }); + } + + public function down(): void + { + Schema::dropIfExists('ext_social_message_reads'); + Schema::dropIfExists('ext_social_messages'); + Schema::dropIfExists('ext_social_conversation_participants'); + Schema::dropIfExists('ext_social_conversations'); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_30_000009_add_created_by_to_conversations.php b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000009_add_created_by_to_conversations.php new file mode 100644 index 000000000..6e95ae9b3 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000009_add_created_by_to_conversations.php @@ -0,0 +1,47 @@ +foreignId('created_by')->nullable()->after('subject')->constrained('users')->nullOnDelete(); + }); + } + + if (!Schema::hasColumn('ext_social_conversations', 'last_message_at')) { + Schema::table('ext_social_conversations', function (Blueprint $table) { + $table->timestamp('last_message_at')->nullable()->after('created_by'); + }); + } + + if (!Schema::hasColumn('ext_social_conversations', 'metadata')) { + Schema::table('ext_social_conversations', function (Blueprint $table) { + $table->json('metadata')->nullable()->after('last_message_at'); + }); + } + } + + public function down(): void + { + Schema::table('ext_social_conversations', function (Blueprint $table) { + if (Schema::hasColumn('ext_social_conversations', 'created_by')) { + $table->dropForeign(['created_by']); + $table->dropColumn('created_by'); + } + if (Schema::hasColumn('ext_social_conversations', 'last_message_at')) { + $table->dropColumn('last_message_at'); + } + if (Schema::hasColumn('ext_social_conversations', 'metadata')) { + $table->dropColumn('metadata'); + } + }); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_30_000010_recreate_messaging_tables.php b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000010_recreate_messaging_tables.php new file mode 100644 index 000000000..541ff3051 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000010_recreate_messaging_tables.php @@ -0,0 +1,91 @@ +id(); + $table->string('type')->default('direct'); // direct, group, system + $table->string('subject')->nullable(); + $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete(); + $table->timestamp('last_message_at')->nullable(); + $table->json('metadata')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + $table->index('type'); + $table->index('last_message_at'); + }); + + // Conversation participants + Schema::create('ext_social_conversation_participants', function (Blueprint $table) { + $table->id(); + $table->foreignId('conversation_id')->constrained('ext_social_conversations')->cascadeOnDelete(); + $table->foreignId('user_id')->constrained('users')->cascadeOnDelete(); + $table->timestamp('last_read_at')->nullable(); + $table->boolean('is_muted')->default(false); + $table->boolean('is_archived')->default(false); + $table->timestamps(); + + $table->unique(['conversation_id', 'user_id'], 'conv_participant_unique'); + $table->index('user_id'); + }); + + // Messages table + Schema::create('ext_social_messages', function (Blueprint $table) { + $table->id(); + $table->foreignId('conversation_id')->constrained('ext_social_conversations')->cascadeOnDelete(); + $table->foreignId('sender_id')->nullable()->constrained('users')->nullOnDelete(); + $table->text('content'); + $table->string('type')->default('text'); // text, system, notification + $table->boolean('is_system')->default(false); + $table->string('system_type')->nullable(); // order_update, payment_received, etc. + $table->json('metadata')->nullable(); + $table->boolean('is_moderated')->default(false); + $table->string('moderation_status')->nullable(); // approved, flagged, deleted + $table->foreignId('moderated_by')->nullable()->constrained('users')->nullOnDelete(); + $table->timestamp('moderated_at')->nullable(); + $table->text('moderation_reason')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + $table->index('conversation_id'); + $table->index('sender_id'); + $table->index('is_system'); + $table->index('moderation_status'); + $table->index('created_at'); + }); + + // Message read receipts + Schema::create('ext_social_message_reads', function (Blueprint $table) { + $table->id(); + $table->foreignId('message_id')->constrained('ext_social_messages')->cascadeOnDelete(); + $table->foreignId('user_id')->constrained('users')->cascadeOnDelete(); + $table->timestamp('read_at'); + + $table->unique(['message_id', 'user_id'], 'message_read_unique'); + $table->index('user_id'); + }); + } + + public function down(): void + { + Schema::dropIfExists('ext_social_message_reads'); + Schema::dropIfExists('ext_social_messages'); + Schema::dropIfExists('ext_social_conversation_participants'); + Schema::dropIfExists('ext_social_conversations'); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_09_30_000011_create_message_reports_table.php b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000011_create_message_reports_table.php new file mode 100644 index 000000000..05383142c --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_09_30_000011_create_message_reports_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignId('message_id')->constrained('ext_social_messages')->cascadeOnDelete(); + $table->foreignId('reported_by')->constrained('users')->cascadeOnDelete(); + $table->string('reason'); + $table->text('description')->nullable(); + $table->string('status')->default('pending'); // pending, reviewed, dismissed + $table->foreignId('reviewed_by')->nullable()->constrained('users')->nullOnDelete(); + $table->timestamp('reviewed_at')->nullable(); + $table->timestamps(); + + $table->index(['message_id', 'reported_by']); + $table->index('status'); + }); + } + + public function down(): void + { + Schema::dropIfExists('ext_social_message_reports'); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_10_01_000001_add_moderation_to_user_profiles.php b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000001_add_moderation_to_user_profiles.php new file mode 100644 index 000000000..78764f675 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000001_add_moderation_to_user_profiles.php @@ -0,0 +1,24 @@ +string('moderation_status')->default('active')->after('allow_comments'); + $table->text('moderation_notes')->nullable()->after('moderation_status'); + }); + } + + public function down(): void + { + Schema::table('ext_social_user_profiles', function (Blueprint $table) { + $table->dropColumn(['moderation_status', 'moderation_notes']); + }); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_10_01_000002_create_user_reports_table.php b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000002_create_user_reports_table.php new file mode 100644 index 000000000..b6f0d1cc0 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000002_create_user_reports_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignId('reported_user_id')->constrained('users')->onDelete('cascade'); + $table->foreignId('reported_by')->constrained('users')->onDelete('cascade'); + $table->string('reason'); // harassment, spam, inappropriate, impersonation, other + $table->text('description')->nullable(); + $table->enum('status', ['pending', 'reviewed', 'dismissed'])->default('pending'); + $table->foreignId('reviewed_by')->nullable()->constrained('users')->onDelete('set null'); + $table->timestamp('reviewed_at')->nullable(); + $table->timestamps(); + + // Prevent duplicate reports + $table->unique(['reported_user_id', 'reported_by', 'reason'], 'user_report_unique'); + }); + } + + public function down(): void + { + Schema::dropIfExists('ext_social_user_reports'); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_10_01_000003_add_admin_notes_to_user_reports.php b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000003_add_admin_notes_to_user_reports.php new file mode 100644 index 000000000..3243d9efd --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000003_add_admin_notes_to_user_reports.php @@ -0,0 +1,23 @@ +text('admin_notes')->nullable()->after('status'); + }); + } + + public function down() + { + Schema::table('ext_social_user_reports', function (Blueprint $table) { + $table->dropColumn('admin_notes'); + }); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_10_01_000004_update_user_reports_status_enum.php b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000004_update_user_reports_status_enum.php new file mode 100644 index 000000000..796855ed7 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000004_update_user_reports_status_enum.php @@ -0,0 +1,21 @@ +json('attachments')->nullable()->after('content'); + }); + } + + public function down() + { + Schema::table('ext_social_messages', function (Blueprint $table) { + $table->dropColumn('attachments'); + }); + } +}; + diff --git a/extensions/Others/SocialBase/Database/migrations/2025_10_01_000021_add_pinned_to_conversation_participants.php b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000021_add_pinned_to_conversation_participants.php new file mode 100644 index 000000000..438fd2181 --- /dev/null +++ b/extensions/Others/SocialBase/Database/migrations/2025_10_01_000021_add_pinned_to_conversation_participants.php @@ -0,0 +1,24 @@ +boolean('is_pinned')->default(false)->after('is_archived'); + $table->index('is_pinned'); + }); + } + + public function down() + { + Schema::table('ext_social_conversation_participants', function (Blueprint $table) { + $table->dropColumn('is_pinned'); + }); + } +}; + diff --git a/extensions/Others/UptimeLab/Database/Seeders/UptimeServerSeeder.php b/extensions/Others/UptimeLab/Database/Seeders/UptimeServerSeeder.php new file mode 100644 index 000000000..13dde1a70 --- /dev/null +++ b/extensions/Others/UptimeLab/Database/Seeders/UptimeServerSeeder.php @@ -0,0 +1,74 @@ + 'Web Server 01', + 'ip_address' => '192.168.1.10', + 'server_type' => 'ip', + 'location' => 'Jakarta, Indonesia', + 'is_active' => true, + 'status' => 'online', + 'uptime_percentage' => 99.8, + 'last_online' => now(), + 'last_offline' => now()->subHours(6), + 'last_check' => now(), + 'response_time' => 15, + ], + [ + 'name' => 'Main Database Server', + 'ip_address' => '192.168.1.20', + 'server_type' => 'ip', + 'location' => 'Surabaya, Indonesia', + 'is_active' => true, + 'status' => 'offline', + 'uptime_percentage' => 100.0, + 'last_online' => now()->subHours(5), + 'last_offline' => now(), + 'last_check' => now(), + 'response_time' => null, + ], + [ + 'name' => 'API Gateway', + 'ip_address' => 'api.example.com', + 'server_type' => 'subdomain', + 'location' => 'Bandung, Indonesia', + 'is_active' => true, + 'status' => 'online', + 'uptime_percentage' => 99.9, + 'last_online' => now()->subHours(6), + 'last_offline' => now()->subHours(5), + 'last_check' => now(), + 'response_time' => 25, + ], + [ + 'name' => 'Load Balancer', + 'ip_address' => '192.168.1.40', + 'server_type' => 'ip', + 'location' => 'Jakarta, Indonesia', + 'is_active' => true, + 'status' => 'online', + 'uptime_percentage' => 99.99, + 'last_online' => now(), + 'last_offline' => now()->subHours(6), + 'last_check' => now(), + 'response_time' => 8, + ], + ]; + + foreach ($servers as $serverData) { + UptimeServer::create($serverData); + } + } +} diff --git a/extensions/Others/UptimeLab/Database/migrations/2025_01_01_000001_create_ext_uptime_servers_table.php b/extensions/Others/UptimeLab/Database/migrations/2025_01_01_000001_create_ext_uptime_servers_table.php new file mode 100644 index 000000000..7b1ce5062 --- /dev/null +++ b/extensions/Others/UptimeLab/Database/migrations/2025_01_01_000001_create_ext_uptime_servers_table.php @@ -0,0 +1,39 @@ +id(); + $table->string('name'); + $table->string('ip_address'); + $table->string('server_type')->default('ip'); // ip or subdomain + $table->string('location'); + $table->string('type')->default('Production'); // Production, Staging, Development + $table->boolean('is_active')->default(true); + $table->string('status')->default('offline'); // online, offline + $table->decimal('uptime_percentage', 5, 2)->default(0.00); + $table->timestamp('last_online')->nullable(); + $table->timestamp('last_offline')->nullable(); + $table->timestamp('last_check')->nullable(); + $table->integer('response_time')->nullable(); // in milliseconds + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('ext_uptime_servers'); + } +}; diff --git a/extensions/Others/UptimeLab/composer.json b/extensions/Others/UptimeLab/composer.json index 56744a25f..9fea41e55 100644 --- a/extensions/Others/UptimeLab/composer.json +++ b/extensions/Others/UptimeLab/composer.json @@ -17,7 +17,7 @@ }, "autoload": { "psr-4": { - "Paymenter\\Extensions\\Others\\UptimeLab\\": "" + "Paymenter\\Extensions\\Others\\UptimeLab\\": "extensions/Others/UptimeLab/" } }, "extra": { diff --git a/extensions/Others/UptimeLab/database/seeders/UptimeServerSeeder.php b/extensions/Others/UptimeLab/database/seeders/UptimeServerSeeder.php new file mode 100644 index 000000000..f4209c1fe --- /dev/null +++ b/extensions/Others/UptimeLab/database/seeders/UptimeServerSeeder.php @@ -0,0 +1,73 @@ + 'Web Server 01', + 'ip_address' => '192.168.1.10', + 'server_type' => 'ip', + 'location' => 'Jakarta, Indonesia', + 'is_active' => true, + 'status' => 'online', + 'uptime_percentage' => 99.8, + 'last_online' => now(), + 'last_offline' => now()->subHours(6), + 'last_check' => now(), + 'response_time' => 15, + ], + [ + 'name' => 'Main Database Server', + 'ip_address' => '192.168.1.20', + 'server_type' => 'ip', + 'location' => 'Surabaya, Indonesia', + 'is_active' => true, + 'status' => 'offline', + 'uptime_percentage' => 100.0, + 'last_online' => now()->subHours(5), + 'last_offline' => now(), + 'last_check' => now(), + 'response_time' => null, + ], + [ + 'name' => 'API Gateway', + 'ip_address' => 'api.example.com', + 'server_type' => 'subdomain', + 'location' => 'Bandung, Indonesia', + 'is_active' => true, + 'status' => 'online', + 'uptime_percentage' => 99.9, + 'last_online' => now()->subHours(6), + 'last_offline' => now()->subHours(5), + 'last_check' => now(), + 'response_time' => 25, + ], + [ + 'name' => 'Load Balancer', + 'ip_address' => '192.168.1.40', + 'server_type' => 'ip', + 'location' => 'Jakarta, Indonesia', + 'is_active' => true, + 'status' => 'online', + 'uptime_percentage' => 99.99, + 'last_online' => now(), + 'last_offline' => now()->subHours(6), + 'last_check' => now(), + 'response_time' => 8, + ], + ]; + + foreach ($servers as $serverData) { + UptimeServer::create($serverData); + } + } +} diff --git a/public/assets/images/glados.jpg b/public/assets/images/glados.jpg new file mode 100644 index 000000000..1175c9456 Binary files /dev/null and b/public/assets/images/glados.jpg differ diff --git a/public/assets/images/logofresh.png b/public/assets/images/logofresh.png new file mode 100644 index 000000000..dd96296c0 Binary files /dev/null and b/public/assets/images/logofresh.png differ diff --git a/public/assets/mp3/glados.mp3 b/public/assets/mp3/glados.mp3 new file mode 100644 index 000000000..03242373b Binary files /dev/null and b/public/assets/mp3/glados.mp3 differ