sonata-project / entityauditbundle Goto Github PK
View Code? Open in Web Editor NEWAudit for Doctrine Entities
Home Page: https://sonata-project.org
License: MIT License
Audit for Doctrine Entities
Home Page: https://sonata-project.org
License: MIT License
Is this already compatible with SIngle Table Inheritance Mapping?
Thanks,
Malte
When rendering the compare.html.twig view, errors are generated by the following variables which need to be presented as date strings
{{ value.old }}
{{ value.same }}
{{ value.new }}
I have added the Twig date() filter e.g.
{{ value.old|date('jS M Y H:i') }}
However, I still run in to problems with the "value.same" parameter - Twig is reporting
"DateTime::__construct(): Failed to parse time string (556.00) at position 0 (5): Unexpected character"
I am running Symfony 2.5.0 with Doctrine / MySQL / PHP 5.5.9-1
I was working my way through the doc and stumbled across:
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "global_ignore_columns" under "simple_things_entity_audit"
And true enough, the sample config does not show "global_ignore_columns".
./app/console config:dump-reference simple_things_entity_audit
# Default configuration for extension with alias: "simple_things_entity_audit"
simple_things_entity_audit:
audited_entities: []
table_prefix: ''
table_suffix: _audit
revision_field_name: rev
revision_type_field_name: revtype
revision_table_name: revisions
revision_id_field_type: integer
listener:
current_username: true
So this will run:
simple_things_entity_audit:
audited_entities:
- Hn\TrainingBundle\Entity\Trainee
# global_ignore_columns:
# - created_at
# - updated_at
table_prefix: ''
table_suffix: _audit
revision_field_name: rev
revision_type_field_name: revtype
revision_table_name: revisions
revision_id_field_type: integer
listener:
current_username: true
Have I erred somewhere on the way in setting this up, or has the global_ignore_config
been removed?
Hi,
After a long time I found your very good bundle. I did a history audit by myself, but it's not as flexible as I want, that's why I started to look for another solution.
I need to store one more field in a revision table ("is_valid" field - user can change an entity, but it has to be validated by admin). Is there some way how to add it to the revision table?
When finding an Entity at a specific revision with an underscore property I get the following error:
Notice: Undefined index: username_canonical in
/Applications/MAMP/htdocs/xxx/
vendor/simplethings/entity-audit-bundle/src/
SimpleThings/EntityAudit/AuditReader.php line 132
It doesn't work because $this->em->getConnection()->fetchAssoc(...)
returns this field as usernameCanonical
.
When the ManyToOne mapping to $organisation is on the abstract class I get an exception saying the organisation_id field is not mapped. The _audit table for each subclass includes all other fields from the abstract class except for those that are ManyToOne associations.
Adding the abstract class to audited_entities in config.yml does not stop the error. Moving the ManyToOne mapping for to each subclass using a Trait solves the problem.
Although it's a little extra code moving the mapping to the subclass works for all entities, except one that uses a Doctrine Extensions nested tree - I can't move the tree mappings into the subclasses as it throws an error saying there are multiple keys.
#config.yml
simple_things_entity_audit:
audited_entities:
- Umm\ProjectBundle\Entity\Project //Note: adding the abstract parent class here does not solve the problem
//other entities to audit
The abstract class that projects inherit from
/**
* @ORM\Table(name="project_project_abstract")
* @ORM\Entity(repositoryClass="Umm\ProjectBundle\Repository\AbstractProjectRepository")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"project" = "Project", "template" = "ProjectTemplate"})
*/
abstract class AbstractProject extends BaseEntity implements ProjectInterface
{
/**
*
* @ORM\Column(name="title", type="string", length=50)
* @Assert\Length(
* min="3",
* max="50",
* minMessage="project.title.min",
* maxMessage="project.title.max"
* )
* @Assert\NotBlank(
* message="project.title.not_blank"
* )
* @JMS\Groups({"summary", "template", "detail", "timeline", "public_api", "public_api_summary"})
*/
protected $title; //This property is in the _audit table for each subclass
/**
*
* @ORM\Column(name="description", type="string", length=1000, nullable=true)
*
* @Assert\Length(
* min="3",
* max="1000",
* )
* @JMS\Groups({"summary", "template", "detail", "public_api", "public_api_summary"})
*
*/
protected $description; //This property is in the _audit table for each subclass
/**
* @ORM\ManyToOne(targetEntity="Umm\OrganisationBundle\Entity\Organisation")
* @ORM\JoinColumn(nullable=true)
* @JMS\Exclude()
*/
protected $organisation; //This association is NOT in the _audit table for the subclasses
//other properties
}
The sub class:
/**
*
* @ORM\Entity(repositoryClass="Umm\ProjectBundle\Repository\ProjectRepository")
* @ORM\Table(name="project_project")
* @ORM\HasLifecycleCallbacks
*
*/
class Project extends AbstractProject implements TaskableInterface, ProjectTimelineInterface, LoggableStatisticInterface, CommentableInterface
{
//Other mappings
}
Error description:
"I was stocked to see this PR merged as we have a lot of class inheritance but alas it's not working for us on Symfony 2.6-dev with Sonata Admin. I'm using class table inheritance with Project inheriting from Abstract Project but none of the abstract project properties appear in the project_audit table so I get a DBALException and PDOException when saving or updating a project, or loading fixtures. Not sure if it's caused by Sonata as auditing needs to be set to true in each Admin service?"
Code by @mpclarkson
Hi,
when I use EntityAudit and SoftDeleteable on the same entity and I remove this entity, I got this error :
ReflectionException: Method prepareUpdateData does not exist in SimpleThings/EntityAudit/EventListener/LogRevisionsListener.php line 114
Seems that entityAudit is launched two times and the second time I got this error. Also, putting this on line 114 resolves the issue but I don't know the consequences :
if (!$persisterR->hasMethod('prepareUpdateData')) {
continue;
}
Thanks !
I'm trying to use this EntityAudit extension and i'm forking it for using it in a Zend Framework application. But there seems to be one problem, in the Entity_audit table the LogRevisionsListener writes the NEW data into the table and that's not what you want.
I either think that this wasn't ment to because when a audited entity gets updated I see $this->uow->getOriginalEntityData() which you would expect to original data is returned but that's not the case.
I'm trying to debug this but in the UnitOfWork class $this->originalEntityData[$oid] is changed many times so it's hard to find where this happends.
Are you familiair with this problem? Is there already a fix?
I'm using Doctrine 2.1.2 with Zend Framework glued with Bisna.
Can you tag a new release? The current stable is 10 month old and miss a lot of bug fixes and enhancement.
Hi,
I try to use gedmo Slug with your bundle but when i try to create new record i have an constraint error message
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '853-239' for key 'PRIMARY'
Here the debug result message, as you cas see, res_bien_audit is call two times
DEBUG - SELECT r0_.slug AS slug0 FROM res_bien r0_ WHERE (r0_.slug LIKE 'my string to slugify%') AND r0_.discr IN (.)
DEBUG - "START TRANSACTION"
DEBUG - INSERT INTO res_bien (....) VALUES (...)
DEBUG - INSERT INTO revisions (timestamp, username) VALUES (?, ?)
DEBUG - INSERT INTO res_bien_audit (...) VALUES (...)
DEBUG - UPDATE res_bien SET .... WHERE id = ?
DEBUG - INSERT INTO res_bien_audit (...) VALUES (...)
DEBUG - "ROLLBACK"
The error disapear when I do not use Gedmo Slug notation.
Do you have any idea how to get rid of this error ?
regards
Entity with fields to
and from
produces invalid SQL due to not being quoted is the AS part.
Fields on entity are defined as such:
/**
* @var string $to
* @Orm\Column(name="to
", type="string", length=255)
*/
private $to;
SQL errors:
SELECT e.revtype, id AS id, name AS name, to
AS to, from
AS from, subject AS subject, body AS body FROM MailTemplate_audit e WHERE e.rev = ?' with params {"1":"4"}: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'to, from
AS from, subject AS subject, body AS body FROM MailTemplate_audit e W' at line 1 (uncaught exception)
Quick (but untested for side affects) fix is to comment out the end of line 222 of SimpleThings\EntityAudit\AuditReader (https://github.com/simplethings/EntityAudit.git 60a5bcb)
$columnList .= ', ' . $class->getQuotedColumnName($field, $this->platform);// .' AS ' . $field;
EDIT: Correct formatting for clarity (to
and from
was showing as to
and from
)
I have found an error while versioning entities like: (error is while auditing Customer entity)
class Address
{
/**
* @ORM\Column
*/
protected $address_text;
/**
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="addresses")
*/
protected $customer;
}
class Customer
{
/**
* @ORM\OneToMany(targetEntity="Address", mappedBy="customer")
*/
protected $addresses;
/**
* @ORM\OneToOne(targetEntity="Address")
*/
protected $primary_address;
}
the UnitOfWork::getEntityIdentifier throws an notice "Undefined index: ........"
in UnitOfWork::entityIdentifiers array - the hash is different that the stored one
TESTED ON Doctrine 2.1.3 and 2.1.6
I have the following entity definition:
/**
* @var simple_array $items
*
* @Orm\Column(name="items", type="simple_array", nullable=true)
*/
protected $items;
When I try to render the view_datail.html.twig, I got the next error:
An exception has been thrown during the rendering of a template ("Notice: Array to string conversion in ... line xx") in SimpleThingsEntityAuditBundle:Audit:view_detail.html.twig at line 19.
Those lines in the template are:
{% if value.timestamp is defined %}
<td>{{ value|date('m/d/Y') }}</td>
{% else %}
<td>{{ value }}</td> <----- Line 19
{% endif %}
The solution to the issue would be:
{% if value.timestamp is defined %}
<td>{{ value|date('m/d/Y') }}</td>
{% elseif value is iterable %}
<td>
{% for element in value %}
{{ element }}
{% endfor %}
</td>
{% else %}
<td>{{ value }}</td>
{% endif %}
Hi!
Are there any plans to implement auditing entites from another entity manager?
Regards
Hi,
Firstly...thanks in advance for this great bundle!
With today's release (v0.5) I'm having some broken dependencies with composer, if I set composer.json to
"simplethings/entity-audit-bundle": "dev-master"
I'm getting the following error:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for symfony/framework-standard-edition 2.3.x-dev -> satisfiable by symfony/framework-standard-edition[2.3.x-dev].
- Conclusion: remove doctrine/orm 2.3.4
- Conclusion: don't install doctrine/orm 2.3.4
- Conclusion: don't install doctrine/orm 2.3.3
- Conclusion: don't install doctrine/orm 2.3.2
- Installation request for simplethings/entity-audit-bundle dev-master -> satisfiable by simplethings/entity-audit-bundle[dev-master].
- Conclusion: don't install doctrine/orm 2.3.1
- simplethings/entity-audit-bundle dev-master requires doctrine/orm ~2.1.0 -> satisfiable by doctrine/orm[2.1.3, 2.1.4, 2.1.5, 2.1.6, 2.1.7].
- Can only install one of: doctrine/orm[2.2.3, 2.1.3].
- Can only install one of: doctrine/orm[2.2.3, 2.1.4].
- Can only install one of: doctrine/orm[2.2.3, 2.1.5].
- Can only install one of: doctrine/orm[2.2.3, 2.1.6].
- Can only install one of: doctrine/orm[2.2.3, 2.1.7].
- symfony/framework-standard-edition 2.3.x-dev requires doctrine/orm >=2.2.3,<2.4-dev -> satisfiable by doctrine/orm[2.3.4, 2.2.3, 2.3.0, 2.3.1, 2.3.2, 2.3.3].
- Conclusion: don't install doctrine/orm 2.3.0
Setting composer.json to v0.3 fix the problem
"simplethings/entity-audit-bundle": "v0.3"
Thanks for you help
Great extension, thanks!
I'd like to store audit data in a separate database, potentially on a different physical server.
Is such a thing even possible ?
If it's just supplying the config option for new entity manager and using it in LogRevisionsListener, then I can do it and create a pull request, it just seems too easy to not be in there already :)
With a large number of tables in my DB I would like to prefix all the tables related to this bundle. Have attempted to set 'table_prefix' in config but doesn't seem to apply to 'revisions'.
It would be nice to have a particular version tagged similar to git. It doesn't have to be unique.
Then add revertByTag() method to repository class
When comparing revisions of entities containing a DateTime field (e.g. "createdAt"), the field is treated as having changed even though it hasn't.
I assume this is because of line 44 in the ArrayDiff class.
Is there a suggested workaround / fix?
An exception has been thrown during the rendering of a template ("Catchable Fatal Error: Object of class DateTime could not be converted to string in app/cache/dev/twig/32/20/728a51b7c5307253f040a251085b.php line 62") in SimpleThingsEntityAuditBundle::layout.html.twig at line 1.
I suppose I could override the template and deal with the DateTime to string conversion myself. But I'm just playing around with this bundle at the moment.
Current implementation of AuditReader is a bit inflexible (e.g. it's not possible to count revisions, get all history for a particular class - e.g. I want to see all User changes with no id limits, also see #63 and #20).
I'd like to have, at least, following methods:
If this is OK, I'll make a PR.
Is possible add annotation support and a method to get the lasted revision?
So the readme says this is inspired by Hibernate Envers, does this mean it's also compatible with it? If I have a Hibernate based project with a Symfony2 project, will they work together?
We do not want users to directly modify their bank account number. An admin or moderator should confirm every change before the actual database change will be made.
http://stackoverflow.com/questions/24733767/let-admin-confirm-database-change
I'm already making use of this bundle for a while, it is great when it comes to maintaining historic data. So I'd like to improve it with features to allow "future changes".
Where should I start in creating a branch for this feature? Are the listeners the best place to start? I'd hope to make a PR within a couple of weeks.
When we upgraded our application, we are getting the REVISIONS_ID_SEQ is not created and we check the database REVISIONS_SEQ is getting created instead of REVISIONS_ID_SEQ.
After that when we modify the code
$sequenceName = $this->platform->supportsSequences()
? 'REVISIONS_ID_SEQ'
: null;
to
$sequenceName = $this->platform->supportsSequences()
? 'REVISIONS_SEQ'
: null;
Then application is working fine. Please can anyone help me out we are using Oracle as database.
Subj, this is not happening.
I'm trying to use your EntityAudit bundle, but when I ran the schema update command nothing happens. No revision tables were generated at all. The only table that got created is "revisions". I ran this command:
$ php app/console doctrine:schema:update --dump-sql
$ php app/console doctrine:schema:update --force
And of course, never saw anything about creating my selected revision tables. When I say selected, I went into my app/config/config.yml and added these entries:
simple_things_entity_audit:
audited_entities:
- src\MyCompany\EntityBundle\Entity\Name
- src\MyCompany\EntityBundle\Entity\PhoneNumber
- src\MyCompany\EntityBundle\Entity\Avatar
After adding these entries and running the schema update, I should be able to see Name_audit, PhoneNumber_audit, Avatar_audit? correct?
I did also try just adding the entries by just saying "EntityBundle\Entity\Name" as shown in the ReadMe file, but that didn't work at all too.
Any help would be appreciated, many thanks in advance!
I want to use CreateQueryBuilder with Audited Entity
But I did not find the syntax I should use
Can you help me
PostgreSQL 9.1 and sonata-sandbox
Issue in sonata-project
When used PostgreSQL, command sonata:page:update-core-routes
raises an exception:
[PDOException]
SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates
unique constraint "page__page_audit_pkey" DETAIL: Key (id, rev)=(4, 0) already exists.
Before this command run:
`````` doctrine:database:create
doctrine:schema:create```
```doctrine:fixtures:load```
When used MySQL, everything is working properly
Since these are main classes for auditing
Hi,
I understand join table inheritance is not currently implemented in this bundle. Are there any plans to implement it? I would love to use this bundle, but unfortunately, without this implementation, I can't use it :( I am currently trying to implement it myself but not having much luck.
Thanks
Hi, i using translation bundle https://github.com/a2lix/TranslationFormBundle
And Audit bundle don't create any schema for relation tables automatically.
Its work only if i prescribed in the manual as in example
simple_things_entity_audit:
audited_entities:
- MyBundle\Entity\MyEntity
- MyBundle\Entity\MyEntity2
Can you check this, please.
And how to show in SonataAdmin history page with translation field ?
May be have some examples ?
I have some table columns which I don't want to track. It would be nice to ignore some columns and not trigger a revision if only one of these column values changed.
If I have an entity that has 1:M relation with abstract entity (that one defining discriminators, and not with concrete class), auditing fails.
When I use foreign primary key I get
Notice: Undefined index: id in /var/www/ekipazh/vendor/simplethings/entity-audit-bundle/src/SimpleThings/EntityAudit/EventListener/LogRevisionsListener.php line 364
Is possible to extend Revision class with new attribute for storing user description of revision? Thanks
When we load huge 1:M relations, we should have some AuditedCollection instead of fetching all data and loading it into ArrayCollection
I would like to be able to 'snapshot' data by getting all entities as they were at a specific revision number.
One way to achieve this might be to modify AuditReader::find such that a NULL $id parameter results in returning an array of 'latest' (greatest revision number equal to or less then the target revision number and not deleted) entities.
Happy to fork and submit a pull request if this approach sounds do-able and the feature is desirable.
Hi,
Got this error with a fresh install:
"Fatal error: Class 'SimpleThings\EntityAudit\SimpleThingsEntityAuditBundle' not found in /var/www/app/AppKernel.php on line 27"
Had to change my autoload.php file to use this source instead:
'SimpleThings\EntityAudit' => DIR.'/../vendor/bundles/SimpleThings/EntityAudit/src',
It would be nice to have internal events for audit manger (like "before audit write") etc, that could modify audited data (like converting 1234 5678 0000 0000 card number to 1234 **** **** **00).
If this behavior is OK, I'll make a PR.
Notice: Undefined index: titre in MyPath\vendor\simplethings\entity-audit-bundle\src\SimpleThings\EntityAudit\EventListener\LogRevisionsListener.php line 206
Entity User :
/**
* @Orm\OneToOne(targetEntity="MyProject\ReveBundle\Entity\Reve", cascade={"persist", "remove"})
*/
protected $reve;
Action in my Reve repository to remove :
$user->setReve();
$this->_em->persist($user);
$this->_em->remove($reve);
$this->_em->flush();
It's work when the entity is not audit.
Thanks for you help
DBALException: An exception occurred while executing 'SELECT lft AS left, rgt AS right, lvl AS level, global AS global, id AS id FROM su_Template_audit e WHERE e.rev <= ? AND id = ? ORDER BY e.rev DESC' with params [5, "016zsta0f0004ogs4wok"]:
Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'left, rgt AS right, lvl AS level, global AS global, id AS id FROM su_Template_au' at line 1
It never loads 1:M collections if there are items belonging to other classes
Hello ,
I am trying to create ZF2 Module for EntityAudit , in this Repo https://github.com/tawfekov/ZF2EntityAudit
I was able to integrate EntityAudit into ZF2 ,
getting AuditManager would be like ( in controller class )
$auditManager = $this->getServerLocator()->get("auditManager");
and auditReader :
$auditReader = $this->getServerLocator()->get("auditReader");
but when creating the tables using doctrine cli , it doesn't create the version-ed table
can any body suggest a solution ???
after that I will work in the viewing auditing
Every object should start with rev 1, the insert statement.
The next update should give rev 2, not rev 26 if there were 24 other changes to other, unrelated objects of the same type happened inbetween.
Hello,
I just installed the EntityAudit, but when I need save an entity that exists, the LogRevisionsListener
save a new revision with the new version of entity, but I need made a first backup before for the original state.
LogRevisionsListener
in a new class LogRevisions
for create an API usable when we want.I'm having a "little" problem just after declare EntityAuditBundle on AppKernel.php
: I just can't login (using SonataAdmin). If I comment that line, everything works just fine, even if I don't configure it in config.yml
and routing.yml
(I guess there's nothing to do with autoload.php
). Just to put the line new SimpleThings\EntityAudit\SimpleThingsEntityAuditBundle()
on AppKernel.php cause and error after login into the web application.
The thing is the error doesn't say anything useful to solve the problem:
FatalErrorException: Error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 43520197 bytes) in /var/git/mercury/mercury/app/cache/dev/classes.php line 4630
That line only returns a json_encode
value: return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
which belongs to this method:
protected function toJson($data, $ignoreErrors = false)
{
if ($ignoreErrors) {
if (version_compare(PHP_VERSION,'5.4.0','>=')) {
return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
return @json_encode($data);
}
if (version_compare(PHP_VERSION,'5.4.0','>=')) {
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
return json_encode($data);
}
The only thing is missing in the configuration is the autoload.php declaration, but I'm using Symfony 2.3, so that step is obsolete in my case. All the steps has been completed, even the audit tables creation in the database.
I'm using Symfony 2.3.8, EntityAudit 0.5.1 and Doctrine ORM Admin 2.2.5.
Seems like I'm the only one having this weird issue. Any ideas what causes it?
On Oracle database, it is not possible to create the trigger for the table REVISIONS because EntityAudit uses a reserved word (see http://docs.oracle.com/cd/B19306_01/em.102/b40103/app_oracle_reserved_words.htm).
When I try to create the trigger, I obtain this error :
CREATE TRIGGER REVISIONS_AI_PK
BEFORE INSERT
ON REVISIONS
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT REVISIONS_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
IF (:NEW.id IS NULL OR :NEW.id = 0) THEN
SELECT REVISIONS_SEQ.NEXTVAL INTO :NEW.id FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = 'REVISIONS_SEQ';
SELECT :NEW.id INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT REVISIONS_SEQ.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;;
Rapport d'erreur :
ORA-06552: PL/SQL: Compilation unit analysis terminated
ORA-06553: PLS-320: déclaration de type de cette expression est incomplète ou mal structurée
06552. 00000 - "PL/SQL: %s"
*Cause:
*Action:
A solution is to replace the timestamp column name. For details, see http://www.lattimore.id.au/2007/03/09/ora-06552-plsql-compilation-unit-analysis-terminated/
Hi,
I have an entity named Company which has a OneToMany relationship with another called CompanyLot.
The relation is described by the following in my MYDIR\CoreBundle\Entity\Entity\Company.php:
/**
* @ORM\OneToMany(
* targetEntity="MYDIR\CoreBundle\Entity\CompanyLot",
* mappedBy="company",
* cascade={"persist","remove"}
* )
*/
private $companyLot;
Both "Company" and "CompanyLot" are audited, and I see the modifications in xxx_audit
tables.
When I fetch the different revs of Company, I need to get the "CompanyLot"s that where attached to it at the time of the revision.
I'm doing this:
$company = $auditReader->find('MYDIR\CoreBundle\Entity\Company',$id,$rev_number);
$companyLots = $company->getCompanyLot();
But $companyLots
is always empty. Is my coding wrong or maybe I misunderstood some of EntityAudit limits.
Thank in advance you for your help :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.