GithubHelp home page GithubHelp logo

area-net-gmbh / contentfly-cms Goto Github PK

View Code? Open in Web Editor NEW
3.0 3.0 2.0 10.25 MB

Mit der Contentfly Plattform können mobile Apps für iOS und Android unter dem Einsatz von nativen und/oder webbasierten Technologien inklusive Synchronisations-Anbindung an ein Backend-System entwickelt werden. Das Contentfly CMS kann aber auch ohne eine App-Anbindung für die Datenhaltung von Websites, Landing-Pages, Individual-Programmierung oder PIM (Product Information System) flexibel genutzt werden.

Home Page: https://www.contentfly-cms.de

License: Other

PHP 51.68% HTML 14.78% JavaScript 28.80% CSS 2.09% Twig 2.66%

contentfly-cms's Introduction

Contentfly CMS

Contentfly.

Die Contentfly Plattform

Einführung

Mit der Contentfly Plattform können Geschäftsprozesse digitalisiert und mobile Apps für iOS und Android unter dem Einsatz von webbasierten Technologien (Ionic Framework) inklusive Synchronisations-Anbindung an einen Server entwickelt werden.

Der Server basiert dabei auf PHP und MySQL und kann auf nahezu jedem Standard-Hosting-Provider eingesetzt werden. Das Ionic SDK unterstützen Entwickler bei der Datenhaltung und Synchronisation (Offline-Apps) mit dem Contentfly CMS.

Für die Entwicklung von Apps mit dem Contentfly Framework sind folgende Kenntnisse erforderlich:

  • Server: PHP und optimalerweise Doctrine ORM und MySQL
  • Ionic: Typescript/Javascript und Kenntnisse im Ionic Framework

Das Contentfly CMS

Mit dem CMS können serverseitig beliebige Inhalte gespeichert und verwaltet werden. Das CMS kann letztendlich auch losgelöst von mobilen Apps betrieben werden. Über eine Schnittstelle kann auf alle im CMS gespeicherten Daten zugegriffen werden. Damit kann das CMS auch zum Beispiel als PIM (Product Information Managament) für eine Webseite in TYPO3 oder Wordpress eingesetzt werden.

Technologien

Installation

Systemvoraussetzungen

  • Apache 2.x ** Follow Symlinks aktiviert/erlaubt
  • PHP 7.1 oder höher
  • PHP-Module (benötigt)
    • open_ssl
    • gd
    • pdo_mysql
  • PHP-Module (empfohlen)
    • imagick
  • MySQL 5.5.0 oder höher
  • Konsolen-/SSH-Zugriff empfohlen

Installation einer Release-Version

(1) Download Contentfly CMS unter http://www.contentfly-cms.de

(2) Installations-Anleitung unter http://www.contentfly-cms.de/docs/cms folgen

Manuelle Installation aus GitHub

(1) Git-Repository laden

git clone https://github.com/area-net-gmbh/contentfly-cms.git

(2) Systemumgebung über Ant-Buildskript im Root-Ordner erstellen

ant

(3) Datenbankzugangsdaten in custom/config.php eintragen

(4) Datenbank über Doctrine im Ordner appcms generieren.

php console.php orm:schema:update --force

(4) Datenbank im Ordner appcms initalisieren/einrichten

php console.php appcms:setup

(4) Webserver (Virtual Host) DocumentRoot auf appcms/public stellen

(5) URL/Host aufrufen und Standard-Login in das Contentfly CMS mit Benutzer admin und Passwort admin

ZIP-Version für Release-Build erstellen

ant zip-release

Dokumentation

Lizenz

Die Contentfly Plattform ist unter eine dualen Lizenz (MIT und properitär) verfügbar. Die genauen Lizenzbedingungen sind in der Datei LICENCE zu finden.

Die Contentfly Plattform ist ein Produkt der AREA-NET GmbH

AREA-NET GmbH Öschstrasse 33 73072 Donzdorf

Kontakt

Geschäftsführer Gaugler Stephan, Köller Holger, Schmid Markus

Handelsregister HRB 541303 Ulm Sitz der Gesellschaft: Donzdorf UST-ID: DE208051892

contentfly-cms's People

Contributors

areanet-foschmid avatar areanet-patzak avatar areanet-schmid avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

contentfly-cms's Issues

Update auf Symfony 4

  • Silex-Support endet Juni 2018
  • Update/Migration Routes/Controller
  • Update/Migration DI
  • Update/Migration Middleware/Events

PHP Sessions absichern

ini_set('session.cookie_httponly', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_secure', 1);

Bigint/Smallint-Unterstützung

IntegerType.php
return ($annotation->type == 'integer' || $annotation->type == 'bigint' || $annotation->type == 'smallint');

$DB_ID_INTEGER_TYPE = 'integer'

bootstrap.php

if (Config\Adapter::getConfig()->DB_GUID_STRATEGY) {
        define('APPCMS_ID_TYPE', 'string');
        define('APPCMS_ID_STRATEGY', 'UUID');
    } else {
        define('APPCMS_ID_TYPE', Config\Adapter::getConfig()->DB_ID_INTEGER_TYPE );
        define('APPCMS_ID_STRATEGY', 'AUTO');
    }`

Multi-Checkbox mit pflegbaren Optionswerten für Many2Many

(1) Neue Entitäten

  • PIM\Option
    • id, group, value
  • PIM\OptionGroup
    • id, name (unique)

(2) Neuer Typ "Checkbox"

  • Neue Annotation
    • @ORM\ManyToMany(targetEntity="Areanet\PIM\Entity\Options")
      @ORM\JoinTable(name="join_table_name", joinColumns {@ORM\JoinColumn(onDelete="CASCADE")})
      @PIM\Checkbox() // oder @PIM\Checkbox(group='gruppenname')
  • Bei der Schema-Erstellung "Types/CheckboxType->processSchema()" entweder group (wenn gesetzt) oder "Entitätname/Feldname" in OptionGroup speichern

** (3) Neuer Frontendtyp "Checkbox"**

  • Analog Multijoin

API-Aufrufe auslagern

API-Aufrufe vom ApiController in API-Klasse auslagern (siehe singleAction), um innerhalb eigener Programmierung direkt auf die API zugreifen zu können.

Fehler bei api/query und Permission=OWN

An exception occurred while executing 'SELECT * FROM TABLE WHERE userCreated = ? OR FIND_IN_SET(?, users) = 1' with params [{}]:\n\nSQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

Z.B. Zeile classes/api.php 1252ff.:

$queryBuilder->andWhere("$entityAlias.userCreated = ? OR FIND_IN_SET(?, $entityAlias.users) = 1");
$queryBuildr->setParameter($paramCount, $this->app['auth.user']);
$paramCount++;

in

$queryBuilder->andWhere("$entityAlias.usercreated_id = ? OR FIND_IN_SET(?, $entityAlias.users) = 1");
$queryBuilder->setParameter($paramCount, $this->app['auth.user']->getId());
$paramCount++;
$queryBuildr->setParameter($paramCount, $this->app['auth.user']->getId());
$paramCount++;

Cronjob-Manager

Implementierung eines Cronjob-Managers. Aufruf eines einzigen Cronjobs, über z.B.

console.php appcms:cronjobs --run

Registrierung von beliebigen Befehlen/"Sub-Cronjobs", die über das Backend verwaltet werden können:

  • Aktivieren/Deaktivieren
  • Intervall (alle 5 Minuten, alle 30 Minuten, jede Stunde,...)

Vergleiche Shopware Cronjobs:
https://community.shopware.com/Cronjobs_detail_1102.html

Login-Fehler

Nach dem Login in das Backend, wird der Token nicht korrekt gespeichert. Es muss einmalig ein erneutes Login durchgeführt werden.

Neue Events/Hooks für Schema-Generierung

pim.schema.after.classAnnotation
Wird aufgerufen, nachdem eine Klassen-Annotation verarbeitet wurde. Kann genutzt werden, um benutzerdefinierte Annotationen in das Schema aufzunehmen:

Parameter

  • Name: classAnnotation
    • Typ: Doctrine\Common\Annotations\Annotation
  • Name: settings
    • Typ: Array
    • Bisherige Schema-Eigenschaften der Entität, wird wieder zurückgeschrieben (muss dafür im Eventhandler mit $event->setProperty('settings', $settings) gesetzt werden)

pim.schema.after.propertyAnnotation
Wird aufgerufen, nachdem eine Property-Annotation verarbeitet wurde. Kann genutzt werden, um benutzerdefinierte Annotationen in das Schema aufzunehmen:

Parameter

  • Name: propertyAnnotation
    • Typ: Doctrine\Common\Annotations\Annotation
  • Name: properties
    • Typ: Array
    • Bisherige benutzerdefinierte Schema-Eigenschaften zur Property, wird wieder zurückgeschrieben (muss dafür im Eventhandler mit $event->setProperty('properties', $properties) gesetzt werden)

HTTP-Authentifizierung für CGI

Anpassung der .htaccess und der index.php, um die HTTP-Authentifizierung auch für PHP als CGI-Modul aktivieren zu können.

Fehler bei Installation: Couldn't find constant APP_CMS_SHOW_ID_IN_LIST, property Areanet\PIM\Entity\Base::$id.

[Semantical Error] Couldn't find constant APP_CMS_SHOW_ID_IN_LIST, property Areanet\PIM\Entity\Base::$id. #0 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php(102): Doctrine\Common\Annotations\AnnotationException::semanticalError('Couldn't find c...') #1 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(973): Doctrine\Common\Annotations\AnnotationException::semanticalErrorConstants('APP_CMS_SHOW_ID...', 'property Areane...') #2 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(1039): Doctrine\Common\Annotations\DocParser->Constant() #3 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(1087): Doctrine\Common\Annotations\DocParser->PlainValue() #4 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(1017): Doctrine\Common\Annotations\DocParser->FieldAssignment() #5 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(884): Doctrine\Common\Annotations\DocParser->Value() #6 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(859): Doctrine\Common\Annotations\DocParser->Values() #7 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(770): Doctrine\Common\Annotations\DocParser->MethodCall() #8 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(663): Doctrine\Common\Annotations\DocParser->Annotation() #9 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(354): Doctrine\Common\Annotations\DocParser->Annotations() #10 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php(250): Doctrine\Common\Annotations\DocParser->parse('/**\n * @ORM...', 'property Areane...') #11 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php(113): Doctrine\Common\Annotations\AnnotationReader->getPropertyAnnotations(Object(ReflectionProperty)) #12 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php(125): Doctrine\Common\Annotations\CachedReader->getPropertyAnnotations(Object(ReflectionProperty)) #13 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php(280): Doctrine\Common\Annotations\CachedReader->getPropertyAnnotation(Object(ReflectionProperty), 'Doctrine\\ORM\\Ma...') #14 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php(102): Doctrine\ORM\Mapping\Driver\AnnotationDriver->loadMetadataForClass('Areanet\\PIM\\Ent...', Object(Doctrine\ORM\Mapping\ClassMetadata)) #15 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(151): Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain->loadMetadataForClass('Areanet\\PIM\\Ent...', Object(Doctrine\ORM\Mapping\ClassMetadata)) #16 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(332): Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata(Object(Doctrine\ORM\Mapping\ClassMetadata), Object(Doctrine\ORM\Mapping\ClassMetadata), false, Array) #17 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php(78): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata('Areanet\\PIM\\Ent...') #18 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(216): Doctrine\ORM\Mapping\ClassMetadataFactory->loadMetadata('Areanet\\PIM\\Ent...') #19 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(115): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor('Areanet\\PIM\\Ent...') #20 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/areanet/PIM/Controller/InstallController.php(183): Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getAllMetadata() #21 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/areanet/PIM/Controller/InstallController.php(44): Areanet\PIM\Controller\InstallController->executeInstallation(Object(Symfony\Component\HttpFoundation\Request)) #22 [internal function]: Areanet\PIM\Controller\InstallController->submitAction(Object(Symfony\Component\HttpFoundation\Request)) #23 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/symfony/http-kernel/HttpKernel.php(144): call_user_func_array(Array, Array) #24 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/symfony/http-kernel/HttpKernel.php(64): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #25 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/silex/silex/src/Silex/Application.php(586): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/vendor/silex/silex/src/Silex/Application.php(563): Silex\Application->handle(Object(Symfony\Component\HttpFoundation\Request)) #27 /Applications/XAMPP/xamppfiles/htdocs/7gradplus/anzeigen/appcms/public/index.php(121): Silex\Application->run() #28 {main}

HTTP-Security-Headers setzen

Bei Force-SSL-Konfiguration:
header("Strict-Transport-Security:max-age=63072000");

Allgemein
header('Content-Security-Policy: default-src 'self unsafe-inline'');
header('X-Content-Type-Options: nosniff');
header("X-Frame-Options: SAMEORIGIN");
header("X-XSS-Protection: 1; mode=block");

Push-Notifications aus Core entfernen

  • Nicht mehr an Entität binden
  • Eigene Klasse, bzw. Silex-Service $app['push]->send() für mehr Flexibilität
  • Native Push über Firebase Cloud Messaging (Android / iOS)
    • Channel-Unterstützung
    • benutzerdefiniert für Apple Push-Service erweiterar/optional
  • Webpush / Browser-Notifications

One2One-Joins

Anzeige und Speicherung von One2One-Joins funktioniert nicht richtig.

  • Felder wie Besitzer, etc. ausblenden
  • Besitzer, etc. automatisch setzen

Benutzerdefinierte Berichte/Listen

  • Definition der Abfrage auf Basis api/query - kann vom Administrator im Backend in Entität "PIM\Reports" erstellt werden
    • Name des Berichts
    • Abfrage
    • Button/s + Aktion (z.B. Öffnen von Edit-Formular)
  • Auflistungen aller Reports für Benutzer
  • Liste und Filter wird automatisch generiert - Anzeige wie bisherige Entitäten-Auflistungen

Datenexport als Excel/CSV/XML

Automatischer Datenexport einer Entität/Liste/Report (inklusive Beachtung der Filter) als Excel, CSV und/oder XML. Download über Dropdown-Button z.B. neben Filter-Button

Zweiter Anzeigemodus in Liste und Formular

Konfigurierbar über Entity-Klassen-Annotation:
`/**

  • @Orm\Entity
  • @Orm\Table(name="produkt")
  • @pim\Config(label="Produkt", viewMode=1")
    */`

viewMode = 0
Standard wie bisher

viewMode = 1
In der Liste wird der Löschen-Button nicht dargestellt, dafür ein Anzeige-Button, mit dem das Objekt lesend geöffnet/angezeigt werden kann.
Der Löschen-Button wird dafür im Bearbeitungsformular links unten angezeigt.

Erweiterung Authentifizierung um LoginManager

Erweiterung um die Authentifizierung auch gegen Drittsysteme (z.B. ERP) durchzuführen.

API-Methode auth/login um zusätzlichen, optionalen Parameter "loginManager" ergänzen
Wenn dieser gesetzt ist, die entsprechende loginManager-Klasse laden.
loginManager->auth() aufrufen und entsprechenden User zurückgeben

Der User muss in der benutzerdefinierten loginManager-Klasse entsprechend gesetzt werden. Beispielsweise durch Überprüfen von Benutzername und Passwort per Curl gegen ein Drittsystem und Erstellen eines Benutzer im System.

API: /auth/login

{
  loginProvider: 'ERPLoginProvider',
  user: 'username',
  pass: 'pass'
}

Custom/Classes/ERPLoginProvider.php

 namespace Custom\Classes;

    namespace Custom\Classes;
    use Areanet\PIM\Classes\Manager\LoginManager;
    class ERPLoginProvider extends LoginManager
    {
    public function auth(){
        $username = $this->request->get('user');
        $password = $this->request->get('pass');
        if(!$this->erpAuth($username, $password)){
            throw new Exception('Authentifizeriung fehlgeschlagen.');
        }
        return $this->createManagedUser($username);
    }

    protected function erpAuth(){
        //Prüfe gegen ERP-Drittsystem per Curl
        return true;
    }
 }

Alternativer Webroot-Ordner

Möglichkeit, um einen alternativen, individuellen Webroot-Ordner anzulegen:

  • Standard appcms/public weiterhin mit ausliefern
  • Zusätliche Möglichkeit einen eigenen Webroot-Ordner anzuelegen, z.B.
    • appcms
    • custom
    • public
      • index.php
      • .htaccess

Bedingungen/Funktionen

(1) index.php (und .htaccess) muss manuell erstellt werden, mit Einbindung einer Bootstrap-Datei:
<?php require_once('../appcms/web-bootstrap.php);

(2) Symbolische Ordner-Verweise müssen aut. zur Laufzeit erstellt werden

Vorteile

  • Anpassungen an index.php/.htaccess möglich (z.B. Server-Errors), ohne Update-Problematik
  • Eigene Dateien/Unterordner (z.B. Ionic-Webapp), ohne Update-Problematik

Modul-Unterstützung

Aufteilung (oder als zusätzliche Option) des custom-Ordners in Modulen, um bei größeren Projekten die Übersichtlichkeit zu bewahren.

  • custom
  • modules
    ** modul1
    ** modul2
    ** ...

Jedes Modul besitzt dabei den gleichen/ähnlichen Aufbau/Logik wie der custom-Ordner, plus zusätzlich einer Installationsroutine, um z.B. assets-Ordner freizugeben (Symlink in public-Ordner).

Erweiterter API-Endpoint /api/query

Erweiterter API-Endpoint, um beliebige Abfragen analog zur DBAL-QueryBuilder http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html stellen zu können.

Beispiele /apiv2/query

{
	select: ['field1', 'field2', 'COUNT(id) AS users'],
	from: entity
	where: {field: value},
	groupBy: field,
	having: {field: value},
	orderBy: {field1: 'ASC'},
	addOrderBy: {field2: 'DESC'},
	setFirstResult: 10, //Offfset
	setMaxResults: 20, //Limit
}

{
	select: ['alias1.field1', 'alias1.field2'],
	from: {entity1: alias1},
	innerJoin:['alias1', 'table2', 'alias2', 'alias1.id = alias2.field_id']
	where: {field: value},
	groupBy: field,
	having: {field: value}
}

{
	select: ['alias1.field1', 'alias1.field2'],
	from: {entity1: alias1},
	innerJoin:['alias1', 'table2', 'alias2', 'alias1.id = alias2.field_id']
	where: {'field1 = ? OR field2 = ?': [value1, value2]},
	andWhere: {field3: value3}
	groupBy: field,
	having: {field: value}
}

Symlinks zur Laufzeit überprüfen

Beim Upload des APP-CMS per FTP werden teilweise die Symlinks falsch übertragen. Daher ist eine Überprüfung und Erstellung zur Laufzeit sinnvoll, da sonst das APP-CMS nicht lauffähig ist.

Syntax Error "got 'PIM\\File" bei api/all

[Syntax Error] line 0, col 7: Error: Expected IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | \"(\" Subselect \")\" | CaseExpression, got 'PIM\\File'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.