diff --git a/custom/public/css/git.openi.css b/custom/public/css/git.openi.css
index c6ada7b28..a4920eec0 100644
--- a/custom/public/css/git.openi.css
+++ b/custom/public/css/git.openi.css
@@ -44,12 +44,6 @@
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
-.ui.label{
- font-weight: normal;
-}
-.active {
- color: #0366D6 !important;
-}
.opacity5{ opacity:0.5;}
.radius15{ border-radius:1.5rem !important; }
@@ -287,70 +281,6 @@
position: relative;
}
-/**seach**/
-/**搜索导航条适配窄屏**/
-.seachnav{
- overflow-x: auto;
- overflow-y: hidden;
- scrollbar-width: none; /* firefox */
- -ms-overflow-style: none; /* IE 10+ */
-}
-.seachnav::-webkit-scrollbar {
- display: none; /* Chrome Safari */
-}
-.ui.green.button, .ui.green.buttons .button{
- background-color: #5BB973;
-}
-.seach .repos--seach{
- padding-bottom: 0;
- border-bottom: none;
-}
-.seach .ui.secondary.pointing.menu{
- border-bottom: none;
-}
-.seach .ui.secondary.pointing.menu .item > i{
- margin-right: 5px;
-}
-.seach .ui.secondary.pointing.menu .active.item{
- border-bottom-width: 2px;
- margin: 0 0 -1px;
-}
-.seach .ui.menu .active.item>.label {
- background: #1684FC;
- color: #FFF;
-}
-.seach .ui.menu .item>.label:not(.active.item>.label) {
- background: #e8e8e8;
- color: rgba(0,0,0,.6);
-}
-
-.highlight{
- color: red;
-}
-.ui.list .list>.item>img.image+.content, .ui.list>.item>img.image+.content {
- width: calc(100% - 3.0em);
- margin-left: 0;
-}
-
-.seach .ui.list .list>.item .header, .seach .ui.list>.item .header{
- margin-bottom: 0.5em;
- font-size: 1.4rem !important;
- font-weight: normal;
-}
-.seach .time, .seach .time a{
- font-size: 12px;
- color: grey;
-}
-
-.seach .list .item.members .ui.avatar.image {
- width: 3.2em;
- height: 3.2em;
-}
-.ui.list .list>.item.members>img.image+.content, .ui.list>.item.members>img.image+.content {
- width: calc(100% - 4.0em);
- margin-left: 0;
-}
-
@media only screen and (max-width: 767px) {
.am-mt-30{ margin-top: 1.5rem !important;}
.ui.secondary.hometop.segment{
diff --git a/models/dbsql/dataset_foreigntable_for_es.sql b/models/dbsql/dataset_foreigntable_for_es.sql
new file mode 100644
index 000000000..815b89d02
--- /dev/null
+++ b/models/dbsql/dataset_foreigntable_for_es.sql
@@ -0,0 +1,186 @@
+DROP FOREIGN TABLE public.dataset_es;
+CREATE FOREIGN TABLE public.dataset_es
+(
+ id bigint NOT NULL,
+ title character varying(255),
+ status integer,
+ category character varying(255),
+ description text,
+ download_times bigint,
+ license character varying(255),
+ task character varying(255),
+ release_id bigint,
+ user_id bigint,
+ repo_id bigint,
+ created_unix bigint,
+ updated_unix bigint,
+ file_name text,
+ file_desc text
+)SERVER multicorn_es
+OPTIONS
+ (
+ host '192.168.207.94',
+ port '9200',
+ index 'dataset-es-index',
+ rowid_column 'id',
+ default_sort '_id'
+ )
+;
+DELETE FROM public.dataset_es;
+ INSERT INTO public.dataset_es(
+ id,
+ title,
+ status,
+ category,
+ description,
+ download_times,
+ license, task,
+ release_id,
+ user_id,
+ repo_id,
+ created_unix,
+ updated_unix,
+ file_name,
+ file_desc
+ )
+ SELECT
+ b.id,
+ b.title,
+ b.status,
+ b.category,
+ b.description,
+ b.download_times,
+ b.license,
+ b.task,
+ b.release_id,
+ b.user_id,
+ b.repo_id,
+ b.created_unix,
+ b.updated_unix,
+ (select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false),
+ (select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment a where a.dataset_id=b.id and a.is_private=false)
+ FROM public.dataset b,public.repository c where b.repo_id=c.id and c.is_private=false;
+
+
+DROP TRIGGER IF EXISTS es_insert_dataset on public.dataset;
+
+CREATE OR REPLACE FUNCTION public.insert_dataset_data() RETURNS trigger AS
+$def$
+ DECLARE
+ privateValue boolean=false;
+ BEGIN
+ select into privateValue is_private from public.repository where id=NEW.repo_id;
+ if not privateValue then
+ INSERT INTO public.dataset_es(
+ id,
+ title,
+ status,
+ category,
+ description,
+ download_times,
+ license,
+ task,
+ release_id,
+ user_id,
+ repo_id,
+ created_unix,
+ updated_unix)
+ VALUES (
+ NEW.id,
+ NEW.title,
+ NEW.status,
+ NEW.category,
+ NEW.description,
+ NEW.download_times,
+ NEW.license,
+ NEW.task,
+ NEW.release_id,
+ NEW.user_id,
+ NEW.repo_id,
+ NEW.created_unix,
+ NEW.updated_unix
+ );
+ end if;
+ RETURN NEW;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+
+
+CREATE TRIGGER es_insert_dataset
+ AFTER INSERT ON public.dataset
+ FOR EACH ROW EXECUTE PROCEDURE insert_dataset_data();
+
+ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_insert_dataset;
+
+
+DROP TRIGGER IF EXISTS es_udpate_dataset_file_name on public.attachment;
+
+CREATE OR REPLACE FUNCTION public.udpate_dataset_file_name() RETURNS trigger AS
+$def$
+ BEGIN
+ if (TG_OP = 'UPDATE') then
+ update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id;
+ elsif (TG_OP = 'INSERT') then
+ update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.dataset_id and is_private=false) where id=NEW.dataset_id;
+ elsif (TG_OP = 'DELETE') then
+ update public.dataset_es SET file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id;
+ update public.dataset_es SET file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=OLD.dataset_id and is_private=false) where id=OLD.dataset_id;
+ end if;
+ return NEW;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+
+CREATE TRIGGER es_udpate_dataset_file_name
+ AFTER INSERT OR UPDATE OR DELETE ON public.attachment
+ FOR EACH ROW EXECUTE PROCEDURE udpate_dataset_file_name();
+
+ALTER TABLE public.attachment ENABLE ALWAYS TRIGGER es_udpate_dataset_file_name;
+
+DROP TRIGGER IF EXISTS es_update_dataset on public.dataset;
+
+CREATE OR REPLACE FUNCTION public.update_dataset() RETURNS trigger AS
+$def$
+ BEGIN
+ UPDATE public.dataset_es
+ SET description=NEW.description,
+ title=NEW.title,
+ category=NEW.category,
+ task=NEW.task,
+ download_times=NEW.download_times,
+ updated_unix=NEW.updated_unix,
+ file_name=(select array_to_string(array_agg(name order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false),
+ file_desc=(select array_to_string(array_agg(description order by created_unix desc),'-#,#-') from public.attachment where dataset_id=NEW.id and is_private=false)
+ where id=NEW.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+CREATE TRIGGER es_update_dataset
+ AFTER UPDATE ON public.dataset
+ FOR EACH ROW EXECUTE PROCEDURE update_dataset();
+
+ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_update_dataset;
+
+DROP TRIGGER IF EXISTS es_delete_dataset on public.dataset;
+
+CREATE OR REPLACE FUNCTION public.delete_dataset() RETURNS trigger AS
+$def$
+ declare
+ BEGIN
+ DELETE FROM public.dataset_es where id=OLD.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+
+CREATE TRIGGER es_delete_dataset
+ AFTER DELETE ON public.dataset
+ FOR EACH ROW EXECUTE PROCEDURE delete_dataset();
+
+ALTER TABLE public.dataset ENABLE ALWAYS TRIGGER es_delete_dataset;
diff --git a/models/dbsql/issue_foreigntable_for_es.sql b/models/dbsql/issue_foreigntable_for_es.sql
new file mode 100644
index 000000000..bb5c1634e
--- /dev/null
+++ b/models/dbsql/issue_foreigntable_for_es.sql
@@ -0,0 +1,215 @@
+DROP FOREIGN TABLE public.issue_es;
+CREATE FOREIGN TABLE public.issue_es
+(
+ id bigint NOT NULL,
+ repo_id bigint,
+ index bigint,
+ poster_id bigint,
+ original_author character varying(255),
+ original_author_id bigint,
+ name character varying(255) ,
+ content text,
+ comment text,
+ milestone_id bigint,
+ priority integer,
+ is_closed boolean,
+ is_pull boolean,
+ pr_id bigint,
+ num_comments integer,
+ ref character varying(255),
+ deadline_unix bigint,
+ created_unix bigint,
+ updated_unix bigint,
+ closed_unix bigint,
+ is_locked boolean NOT NULL,
+ amount bigint,
+ is_transformed boolean NOT NULL
+)SERVER multicorn_es
+OPTIONS
+ (
+ host '192.168.207.94',
+ port '9200',
+ index 'issue-es-index',
+ rowid_column 'id',
+ default_sort '_id'
+ )
+;
+
+delete from public.issue_es;
+INSERT INTO public.issue_es(
+ id,
+ repo_id,
+ index,
+ poster_id,
+ original_author,
+ original_author_id,
+ name,
+ content,
+ milestone_id,
+ priority,
+ is_closed,
+ is_pull,
+ num_comments,
+ ref,
+ deadline_unix,
+ created_unix,
+ updated_unix,
+ closed_unix,
+ is_locked,
+ amount,
+ is_transformed,comment,pr_id)
+ SELECT
+ b.id,
+ b.repo_id,
+ b.index,
+ b.poster_id,
+ b.original_author,
+ b.original_author_id,
+ b.name,
+ b.content,
+ b.milestone_id,
+ b.priority,
+ b.is_closed,
+ b.is_pull,
+ b.num_comments,
+ b.ref,
+ b.deadline_unix,
+ b.created_unix,
+ b.updated_unix,
+ b.closed_unix,
+ b.is_locked,
+ b.amount,
+ b.is_transformed,
+ (select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id),
+ (select id from public.pull_request d where b.id=d.issue_id and b.is_pull=true)
+ FROM public.issue b,public.repository c where b.repo_id=c.id and c.is_private=false;
+
+
+CREATE OR REPLACE FUNCTION public.insert_issue_data() RETURNS trigger AS
+$def$
+ DECLARE
+ privateValue boolean=false;
+ BEGIN
+ select into privateValue is_private from public.repository where id=NEW.repo_id;
+ if not privateValue then
+ INSERT INTO public.issue_es(
+ id,
+ repo_id,
+ index,
+ poster_id,
+ original_author,
+ original_author_id,
+ name,
+ content,
+ milestone_id,
+ priority,
+ is_closed,
+ is_pull,
+ num_comments,
+ ref,
+ deadline_unix,
+ created_unix,
+ updated_unix,
+ closed_unix,
+ is_locked,
+ amount,
+ is_transformed)
+ VALUES (
+ NEW.id,
+ NEW.repo_id,
+ NEW.index,
+ NEW.poster_id,
+ NEW.original_author,
+ NEW.original_author_id,
+ NEW.name,
+ NEW.content,
+ NEW.milestone_id,
+ NEW.priority,
+ NEW.is_closed,
+ NEW.is_pull,
+ NEW.num_comments,
+ NEW.ref,
+ NEW.deadline_unix,
+ NEW.created_unix,
+ NEW.updated_unix,
+ NEW.closed_unix,
+ NEW.is_locked,
+ NEW.amount,
+ NEW.is_transformed
+ );
+ end if;
+ RETURN NEW;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS es_insert_issue on public.issue;
+
+CREATE TRIGGER es_insert_issue
+ AFTER INSERT ON public.issue
+ FOR EACH ROW EXECUTE PROCEDURE insert_issue_data();
+
+ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_insert_issue;
+
+CREATE OR REPLACE FUNCTION public.udpate_issue_comment() RETURNS trigger AS
+$def$
+ BEGIN
+ if (TG_OP = 'DELETE') then
+ update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=OLD.issue_id) where id=OLD.issue_id;
+ elsif (TG_OP = 'UPDATE') then
+ update public.issue_es SET comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.issue_id) where id=NEW.issue_id;
+ end if;
+
+ return null;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS es_udpate_issue_comment on public.comment;
+CREATE TRIGGER es_udpate_issue_comment
+ AFTER DELETE OR UPDATE ON public.comment
+ FOR EACH ROW EXECUTE PROCEDURE udpate_issue_comment();
+
+ALTER TABLE public.comment ENABLE ALWAYS TRIGGER es_udpate_issue_comment;
+
+
+CREATE OR REPLACE FUNCTION public.update_issue() RETURNS trigger AS
+$def$
+ declare
+ BEGIN
+ UPDATE public.issue_es
+ SET content=NEW.content,
+ name=NEW.name,
+ is_closed=NEW.is_closed,
+ num_comments=NEW.num_comments,
+ comment=(select array_to_string(array_agg(content order by created_unix desc),',') from public.comment where issue_id=NEW.id)
+ where id=NEW.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS es_update_issue on public.issue;
+
+CREATE TRIGGER es_update_issue
+ AFTER UPDATE ON public.issue
+ FOR EACH ROW EXECUTE PROCEDURE update_issue();
+
+ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_update_issue;
+
+CREATE OR REPLACE FUNCTION public.delete_issue() RETURNS trigger AS
+$def$
+ declare
+ BEGIN
+ DELETE FROM public.issue_es where id=OLD.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+DROP TRIGGER IF EXISTS es_delete_issue on public.issue;
+CREATE TRIGGER es_delete_issue
+ AFTER DELETE ON public.issue
+ FOR EACH ROW EXECUTE PROCEDURE delete_issue();
+
+ALTER TABLE public.issue ENABLE ALWAYS TRIGGER es_delete_issue;
\ No newline at end of file
diff --git a/models/dbsql/repo_foreigntable_for_es.sql b/models/dbsql/repo_foreigntable_for_es.sql
new file mode 100644
index 000000000..f51155ccf
--- /dev/null
+++ b/models/dbsql/repo_foreigntable_for_es.sql
@@ -0,0 +1,532 @@
+-- 要处理项目从私有变为公有,并且从公有变成私有的情况
+DROP FOREIGN table if exists public.repository_es;
+CREATE FOREIGN TABLE public.repository_es (
+ id bigint NOT NULL,
+ owner_id bigint,
+ owner_name character varying(255),
+ lower_name character varying(255) NOT NULL,
+ name character varying(255) NOT NULL,
+ description text,
+ website character varying(2048),
+ original_service_type integer,
+ original_url character varying(2048),
+ default_branch character varying(255),
+ num_watches integer,
+ num_stars integer,
+ num_forks integer,
+ num_issues integer,
+ num_closed_issues integer,
+ num_pulls integer,
+ num_closed_pulls integer,
+ num_milestones integer DEFAULT 0 NOT NULL,
+ num_closed_milestones integer DEFAULT 0 NOT NULL,
+ is_private boolean,
+ is_empty boolean,
+ is_archived boolean,
+ is_mirror boolean,
+ status integer DEFAULT 0 NOT NULL,
+ is_fork boolean DEFAULT false NOT NULL,
+ fork_id bigint,
+ is_template boolean DEFAULT false NOT NULL,
+ template_id bigint,
+ size bigint DEFAULT 0 NOT NULL,
+ is_fsck_enabled boolean DEFAULT true NOT NULL,
+ close_issues_via_commit_in_any_branch boolean DEFAULT false NOT NULL,
+ topics text,
+ avatar character varying(64),
+ created_unix bigint,
+ updated_unix bigint,
+ contract_address character varying(255),
+ block_chain_status integer DEFAULT 0 NOT NULL,
+ balance character varying(255) DEFAULT '0'::character varying NOT NULL,
+ clone_cnt bigint DEFAULT 0 NOT NULL,
+ license character varying(100),
+ download_cnt bigint DEFAULT 0 NOT NULL,
+ num_commit bigint DEFAULT 0 NOT NULL,
+ git_clone_cnt bigint DEFAULT 0 NOT NULL,
+ creator_id bigint NOT NULL DEFAULT 0,
+ repo_type integer NOT NULL DEFAULT 0,
+ lang character varying(2048),
+ alias character varying(255),
+ lower_alias character varying(255)
+) SERVER multicorn_es
+OPTIONS
+ (
+ host '192.168.207.94',
+ port '9200',
+ index 'repository-es-index',
+ rowid_column 'id',
+ default_sort '_id'
+ )
+;
+delete from public.repository_es;
+ INSERT INTO public.repository_es (id,
+ owner_id,
+ owner_name,
+ lower_name,
+ name,
+ description,
+ website,
+ original_service_type,
+ original_url,
+ default_branch,
+ num_watches,
+ num_stars,
+ num_forks,
+ num_issues,
+ num_closed_issues,
+ num_pulls,
+ num_closed_pulls,
+ num_milestones,
+ num_closed_milestones,
+ is_private,
+ is_empty,
+ is_archived,
+ is_mirror,
+ status,
+ is_fork,
+ fork_id,
+ is_template,
+ template_id,
+ size,
+ is_fsck_enabled,
+ close_issues_via_commit_in_any_branch,
+ topics,
+ avatar,
+ created_unix,
+ updated_unix,
+ contract_address,
+ block_chain_status,
+ balance,
+ clone_cnt,
+ num_commit,
+ git_clone_cnt,
+ creator_id,
+ repo_type,
+ lang,
+ alias,
+ lower_alias
+ )
+ SELECT
+ id,
+ owner_id,
+ owner_name,
+ lower_name,
+ name,
+ description,
+ website,
+ original_service_type,
+ original_url,
+ default_branch,
+ num_watches,
+ num_stars,
+ num_forks,
+ num_issues,
+ num_closed_issues,
+ num_pulls,
+ num_closed_pulls,
+ num_milestones,
+ num_closed_milestones,
+ is_private,
+ is_empty,
+ is_archived,
+ is_mirror,
+ status,
+ is_fork,
+ fork_id,
+ is_template,
+ template_id,
+ size,
+ is_fsck_enabled,
+ close_issues_via_commit_in_any_branch,
+ topics,
+ avatar,
+ created_unix,
+ updated_unix,
+ contract_address,
+ block_chain_status,
+ balance,
+ clone_cnt,
+ num_commit,
+ git_clone_cnt,
+ creator_id,
+ repo_type,
+ (select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id),
+ alias,
+ lower_alias
+ FROM public.repository b where b.is_private=false;
+
+DROP TRIGGER IF EXISTS es_insert_repository on public.repository;
+
+CREATE OR REPLACE FUNCTION public.insert_repository_data() RETURNS trigger AS
+$def$
+ BEGIN
+ if not NEW.is_private then
+ INSERT INTO public.repository_es (id,
+ owner_id,
+ owner_name,
+ lower_name,
+ name,
+ description,
+ website,
+ original_service_type,
+ original_url,
+ default_branch,
+ num_watches,
+ num_stars,
+ num_forks,
+ num_issues,
+ num_closed_issues,
+ num_pulls,
+ num_closed_pulls,
+ num_milestones,
+ num_closed_milestones,
+ is_private,
+ is_empty,
+ is_archived,
+ is_mirror,
+ status,
+ is_fork,
+ fork_id,
+ is_template,
+ template_id,
+ size,
+ is_fsck_enabled,
+ close_issues_via_commit_in_any_branch,
+ topics,
+ avatar,
+ created_unix,
+ updated_unix,
+ contract_address,
+ block_chain_status,
+ balance,
+ clone_cnt,
+ num_commit,
+ git_clone_cnt,
+ creator_id,
+ repo_type,
+ alias,
+ lower_alias) VALUES
+ (NEW.id,
+ NEW.owner_id,
+ NEW.owner_name,
+ NEW.lower_name,
+ NEW.name,
+ NEW.description,
+ NEW.website,
+ NEW.original_service_type,
+ NEW.original_url,
+ NEW.default_branch,
+ NEW.num_watches,
+ NEW.num_stars,
+ NEW.num_forks,
+ NEW.num_issues,
+ NEW.num_closed_issues,
+ NEW.num_pulls,
+ NEW.num_closed_pulls,
+ NEW.num_milestones,
+ NEW.num_closed_milestones,
+ NEW.is_private,
+ NEW.is_empty,
+ NEW.is_archived,
+ NEW.is_mirror,
+ NEW.status,
+ NEW.is_fork,
+ NEW.fork_id,
+ NEW.is_template,
+ NEW.template_id,
+ NEW.size,
+ NEW.is_fsck_enabled,
+ NEW.close_issues_via_commit_in_any_branch,
+ NEW.topics,
+ NEW.avatar,
+ NEW.created_unix,
+ NEW.updated_unix,
+ NEW.contract_address,
+ NEW.block_chain_status,
+ NEW.balance,
+ NEW.clone_cnt,
+ NEW.num_commit,
+ NEW.git_clone_cnt,
+ NEW.creator_id,
+ NEW.repo_type,
+ NEW.alias,
+ NEW.lower_alias);
+ end if;
+ RETURN NEW;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+
+CREATE TRIGGER es_insert_repository
+ AFTER INSERT ON public.repository
+ FOR EACH ROW EXECUTE PROCEDURE insert_repository_data();
+
+ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_insert_repository;
+
+DROP TRIGGER IF EXISTS es_update_repository on public.repository;
+
+CREATE OR REPLACE FUNCTION public.update_repository() RETURNS trigger AS
+$def$
+ BEGIN
+ if OLD.is_private != NEW.is_private then
+ if OLD.is_private and not NEW.is_private then
+ --insert
+ INSERT INTO public.repository_es (id,
+ owner_id,
+ owner_name,
+ lower_name,
+ name,
+ description,
+ website,
+ original_service_type,
+ original_url,
+ default_branch,
+ num_watches,
+ num_stars,
+ num_forks,
+ num_issues,
+ num_closed_issues,
+ num_pulls,
+ num_closed_pulls,
+ num_milestones,
+ num_closed_milestones,
+ is_private,
+ is_empty,
+ is_archived,
+ is_mirror,
+ status,
+ is_fork,
+ fork_id,
+ is_template,
+ template_id,
+ size,
+ is_fsck_enabled,
+ close_issues_via_commit_in_any_branch,
+ topics,
+ avatar,
+ created_unix,
+ updated_unix,
+ contract_address,
+ block_chain_status,
+ balance,
+ clone_cnt,
+ num_commit,
+ git_clone_cnt,
+ creator_id,
+ repo_type,
+ lang,
+ alias,
+ lower_alias)
+ SELECT
+ id,
+ owner_id,
+ owner_name,
+ lower_name,
+ name,
+ description,
+ website,
+ original_service_type,
+ original_url,
+ default_branch,
+ num_watches,
+ num_stars,
+ num_forks,
+ num_issues,
+ num_closed_issues,
+ num_pulls,
+ num_closed_pulls,
+ num_milestones,
+ num_closed_milestones,
+ is_private,
+ is_empty,
+ is_archived,
+ is_mirror,
+ status,
+ is_fork,
+ fork_id,
+ is_template,
+ template_id,
+ size,
+ is_fsck_enabled,
+ close_issues_via_commit_in_any_branch,
+ topics,
+ avatar,
+ created_unix,
+ updated_unix,
+ contract_address,
+ block_chain_status,
+ balance,
+ clone_cnt,
+ num_commit,
+ git_clone_cnt,
+ creator_id,
+ repo_type,
+ (select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat a where a.repo_id=b.id),
+ alias,
+ lower_alias
+ FROM public.repository b where b.id=NEW.id;
+ INSERT INTO public.dataset_es(
+ id,
+ title,
+ status,
+ category,
+ description,
+ download_times,
+ license, task,
+ release_id,
+ user_id,
+ repo_id,
+ created_unix,
+ updated_unix,file_name)
+ SELECT
+ b.id,
+ b.title,
+ b.status,
+ b.category,
+ b.description,
+ b.download_times,
+ b.license,
+ b.task,
+ b.release_id,
+ b.user_id,
+ b.repo_id,
+ b.created_unix,
+ b.updated_unix,(select array_to_string(array_agg(name order by created_unix desc),',') from public.attachment a where a.dataset_id=b.id and a.is_private=false)
+ FROM public.dataset b where b.repo_id=NEW.id;
+
+ INSERT INTO public.issue_es(
+ id,
+ repo_id,
+ index,
+ poster_id,
+ original_author,
+ original_author_id,
+ name,
+ content,
+ milestone_id,
+ priority,
+ is_closed,
+ is_pull,
+ num_comments,
+ ref,
+ deadline_unix,
+ created_unix,
+ updated_unix,
+ closed_unix,
+ is_locked,
+ amount,
+ is_transformed,comment,pr_id)
+ SELECT
+ b.id,
+ b.repo_id,
+ b.index,
+ b.poster_id,
+ b.original_author,
+ b.original_author_id,
+ b.name,
+ b.content,
+ b.milestone_id,
+ b.priority,
+ b.is_closed,
+ b.is_pull,
+ b.num_comments,
+ b.ref,
+ b.deadline_unix,
+ b.created_unix,
+ b.updated_unix,
+ b.closed_unix,
+ b.is_locked,
+ b.amount,
+ b.is_transformed,
+ (select array_to_string(array_agg(content order by created_unix desc),',') from public.comment a where a.issue_id=b.id),
+ (select id from public.pull_request d where d.issue_id=b.id)
+ FROM public.issue b where b.repo_id=NEW.id;
+
+ end if;
+
+ if not OLD.is_private and NEW.is_private then
+ delete from public.issue_es where repo_id=NEW.id;
+ delete from public.dataset_es where repo_id=NEW.id;
+ delete from public.repository_es where id=NEW.id;
+ end if;
+
+ end if;
+
+ if not NEW.is_private then
+ raise notice 'update repo,the updated_unix is %',NEW.updated_unix;
+ update public.repository_es SET description=NEW.description,
+ name=NEW.name,
+ lower_name=NEW.lower_name,
+ owner_name=NEW.owner_name,
+ website=NEW.website,
+ updated_unix=NEW.updated_unix,
+ num_watches=NEW.num_watches,
+ num_stars=NEW.num_stars,
+ num_forks=NEW.num_forks,
+ topics=NEW.topics,
+ alias = NEW.alias,
+ lower_alias = NEW.lower_alias,
+ avatar=NEW.avatar
+ where id=NEW.id;
+ end if;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+CREATE TRIGGER es_update_repository
+ AFTER UPDATE ON public.repository
+ FOR EACH ROW EXECUTE PROCEDURE update_repository();
+
+ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_update_repository;
+
+
+DROP TRIGGER IF EXISTS es_delete_repository on public.repository;
+
+CREATE OR REPLACE FUNCTION public.delete_repository() RETURNS trigger AS
+$def$
+ declare
+ BEGIN
+ delete from public.issue_es where repo_id=OLD.id;
+ delete from public.dataset_es where repo_id=OLD.id;
+ DELETE FROM public.repository_es where id=OLD.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+
+CREATE TRIGGER es_delete_repository
+ AFTER DELETE ON public.repository
+ FOR EACH ROW EXECUTE PROCEDURE delete_repository();
+
+ALTER TABLE public.repository ENABLE ALWAYS TRIGGER es_delete_repository;
+
+
+
+DROP TRIGGER IF EXISTS es_udpate_repository_lang on public.language_stat;
+
+CREATE OR REPLACE FUNCTION public.udpate_repository_lang() RETURNS trigger AS
+$def$
+ BEGIN
+ if (TG_OP = 'UPDATE') then
+ update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
+ elsif (TG_OP = 'INSERT') then
+ update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=NEW.repo_id) where id=NEW.repo_id;
+ elsif (TG_OP = 'DELETE') then
+ if exists(select 1 from public.repository where id=OLD.repo_id) then
+ update public.repository_es SET lang=(select array_to_string(array_agg(language order by percentage desc),',') from public.language_stat where repo_id=OLD.repo_id) where id=OLD.repo_id;
+ end if;
+ end if;
+ return null;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+CREATE TRIGGER es_udpate_repository_lang
+ AFTER INSERT OR UPDATE OR DELETE ON public.language_stat
+ FOR EACH ROW EXECUTE PROCEDURE udpate_repository_lang();
+
+ALTER TABLE public.language_stat ENABLE ALWAYS TRIGGER es_udpate_repository_lang;
\ No newline at end of file
diff --git a/models/dbsql/user_foreigntable_for_es.sql b/models/dbsql/user_foreigntable_for_es.sql
new file mode 100644
index 000000000..c3d21b92a
--- /dev/null
+++ b/models/dbsql/user_foreigntable_for_es.sql
@@ -0,0 +1,308 @@
+DROP FOREIGN table if exists public.user_es;
+CREATE FOREIGN TABLE public.user_es
+(
+ id bigint NOT NULL ,
+ lower_name character varying(255) NULL,
+ name character varying(255) NULL,
+ full_name character varying(255),
+ email character varying(255),
+ keep_email_private boolean,
+ email_notifications_preference character varying(20) ,
+ passwd character varying(255) ,
+ passwd_hash_algo character varying(255) ,
+ must_change_password boolean NOT NULL DEFAULT false,
+ login_type integer,
+ login_source bigint NOT NULL DEFAULT 0,
+ login_name character varying(255) ,
+ type integer,
+ location character varying(255),
+ website character varying(255),
+ rands character varying(10),
+ salt character varying(10),
+ language character varying(5),
+ description character varying(255),
+ created_unix bigint,
+ updated_unix bigint,
+ last_login_unix bigint,
+ last_repo_visibility boolean,
+ max_repo_creation integer,
+ is_active boolean,
+ is_admin boolean,
+ is_restricted boolean NOT NULL DEFAULT false,
+ allow_git_hook boolean,
+ allow_import_local boolean,
+ allow_create_organization boolean DEFAULT true,
+ prohibit_login boolean NOT NULL DEFAULT false,
+ avatar character varying(2048) ,
+ avatar_email character varying(255),
+ use_custom_avatar boolean,
+ num_followers integer,
+ num_following integer NOT NULL DEFAULT 0,
+ num_stars integer,
+ num_repos integer,
+ num_teams integer,
+ num_members integer,
+ visibility integer NOT NULL DEFAULT 0,
+ repo_admin_change_team_access boolean NOT NULL DEFAULT false,
+ diff_view_style character varying(255),
+ theme character varying(255),
+ token character varying(1024) ,
+ public_key character varying(255),
+ private_key character varying(255),
+ is_operator boolean NOT NULL DEFAULT false,
+ num_dataset_stars integer NOT NULL DEFAULT 0
+) SERVER multicorn_es
+OPTIONS
+ (
+ host '192.168.207.94',
+ port '9200',
+ index 'user-es-index',
+ rowid_column 'id',
+ default_sort '_id'
+ )
+;
+delete from public.user_es;
+ INSERT INTO public.user_es(
+ id,
+ lower_name,
+ name,
+ full_name,
+ email,
+ keep_email_private,
+ email_notifications_preference,
+ must_change_password,
+ login_type,
+ login_source,
+ login_name,
+ type,
+ location,
+ website,
+ rands,
+ language,
+ description,
+ created_unix,
+ updated_unix,
+ last_login_unix,
+ last_repo_visibility,
+ max_repo_creation,
+ is_active,
+ is_restricted,
+ allow_git_hook,
+ allow_import_local,
+ allow_create_organization,
+ prohibit_login,
+ avatar,
+ avatar_email,
+ use_custom_avatar,
+ num_followers,
+ num_following,
+ num_stars,
+ num_repos,
+ num_teams,
+ num_members,
+ visibility,
+ repo_admin_change_team_access,
+ diff_view_style,
+ theme,
+ is_operator,
+ num_dataset_stars)
+ SELECT
+ id,
+ lower_name,
+ name,
+ full_name,
+ email,
+ keep_email_private,
+ email_notifications_preference,
+ must_change_password,
+ login_type,
+ login_source,
+ login_name,
+ type,
+ location,
+ website,
+ rands,
+ language,
+ description,
+ created_unix,
+ updated_unix,
+ last_login_unix,
+ last_repo_visibility,
+ max_repo_creation,
+ is_active,
+ is_restricted,
+ allow_git_hook,
+ allow_import_local,
+ allow_create_organization,
+ prohibit_login,
+ avatar,
+ avatar_email,
+ use_custom_avatar,
+ num_followers,
+ num_following,
+ num_stars,
+ num_repos,
+ num_teams,
+ num_members,
+ visibility,
+ repo_admin_change_team_access,
+ diff_view_style,
+ theme,
+ is_operator,
+ num_dataset_stars
+ FROM public.user;
+
+DROP TRIGGER IF EXISTS es_insert_user on public.user;
+
+CREATE OR REPLACE FUNCTION public.insert_user_data() RETURNS trigger AS
+$def$
+ BEGIN
+ INSERT INTO public."user_es"(
+ id,
+ lower_name,
+ name,
+ full_name,
+ email,
+ keep_email_private,
+ email_notifications_preference,
+ must_change_password,
+ login_type,
+ login_source,
+ login_name,
+ type,
+ location,
+ website,
+ rands,
+ language,
+ description,
+ created_unix,
+ updated_unix,
+ last_login_unix,
+ last_repo_visibility,
+ max_repo_creation,
+ is_active,
+ is_restricted,
+ allow_git_hook,
+ allow_import_local,
+ allow_create_organization,
+ prohibit_login,
+ avatar,
+ avatar_email,
+ use_custom_avatar,
+ num_followers,
+ num_following,
+ num_stars,
+ num_repos,
+ num_teams,
+ num_members,
+ visibility,
+ repo_admin_change_team_access,
+ diff_view_style,
+ theme,
+ is_operator,
+ num_dataset_stars)
+ VALUES (
+ NEW.id,
+ NEW.lower_name,
+ NEW.name,
+ NEW.full_name,
+ NEW.email,
+ NEW.keep_email_private,
+ NEW.email_notifications_preference,
+ NEW.must_change_password,
+ NEW.login_type,
+ NEW.login_source,
+ NEW.login_name,
+ NEW.type,
+ NEW.location,
+ NEW.website,
+ NEW.rands,
+ NEW.language,
+ NEW.description,
+ NEW.created_unix,
+ NEW.updated_unix,
+ NEW.last_login_unix,
+ NEW.last_repo_visibility,
+ NEW.max_repo_creation,
+ NEW.is_active,
+ NEW.is_restricted,
+ NEW.allow_git_hook,
+ NEW.allow_import_local,
+ NEW.allow_create_organization,
+ NEW.prohibit_login,
+ NEW.avatar,
+ NEW.avatar_email,
+ NEW.use_custom_avatar,
+ NEW.num_followers,
+ NEW.num_following,
+ NEW.num_stars,
+ NEW.num_repos,
+ NEW.num_teams,
+ NEW.num_members,
+ NEW.visibility,
+ NEW.repo_admin_change_team_access,
+ NEW.diff_view_style,
+ NEW.theme,
+ NEW.is_operator,
+ NEW.num_dataset_stars
+ );
+
+ RETURN NEW;
+ END;
+$def$
+LANGUAGE plpgsql;
+
+
+
+CREATE TRIGGER es_insert_user
+ AFTER INSERT ON public.user
+ FOR EACH ROW EXECUTE PROCEDURE insert_user_data();
+
+ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_insert_user;
+
+DROP TRIGGER IF EXISTS es_update_user on public.user;
+
+CREATE OR REPLACE FUNCTION public.update_user() RETURNS trigger AS
+$def$
+ BEGIN
+ UPDATE public.user_es
+ SET description=NEW.description,
+ name=NEW.name,
+ full_name=NEW.full_name,
+ location=NEW.location,
+ website=NEW.website,
+ email=NEW.email,
+ num_dataset_stars=NEW.num_dataset_stars,
+ updated_unix=NEW.updated_unix
+ where id=NEW.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+
+
+CREATE TRIGGER es_update_user
+ AFTER UPDATE ON public.user
+ FOR EACH ROW EXECUTE PROCEDURE update_user();
+
+ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_update_user;
+
+DROP TRIGGER IF EXISTS es_delete_user on public.user;
+
+CREATE OR REPLACE FUNCTION public.delete_user() RETURNS trigger AS
+$def$
+ declare
+ BEGIN
+ DELETE FROM public.user_es where id=OLD.id;
+ return new;
+ END
+$def$
+LANGUAGE plpgsql;
+
+
+CREATE TRIGGER es_delete_user
+ AFTER DELETE ON public.user
+ FOR EACH ROW EXECUTE PROCEDURE delete_user();
+
+ALTER TABLE public.user ENABLE ALWAYS TRIGGER es_delete_user;
\ No newline at end of file
diff --git a/models/models.go b/models/models.go
index 36527f78d..362d46618 100755
--- a/models/models.go
+++ b/models/models.go
@@ -138,6 +138,7 @@ func init() {
new(OfficialTag),
new(OfficialTagRepos),
new(WechatBindLog),
+ new(SearchRecord),
)
tablesStatistic = append(tablesStatistic,
diff --git a/models/repo.go b/models/repo.go
index 42e350fbe..b5d4921e4 100755
--- a/models/repo.go
+++ b/models/repo.go
@@ -6,13 +6,14 @@
package models
import (
- "code.gitea.io/gitea/modules/git"
"context"
"crypto/md5"
"errors"
"fmt"
"html/template"
"math/rand"
+
+ "code.gitea.io/gitea/modules/git"
"xorm.io/xorm"
"code.gitea.io/gitea/modules/blockchain"
diff --git a/models/repo_list.go b/models/repo_list.go
index 6fb9380de..5bf0ecf03 100755
--- a/models/repo_list.go
+++ b/models/repo_list.go
@@ -190,7 +190,8 @@ type SearchRepoOptions struct {
// None -> include all repos
// True -> include just courses
// False -> include just no courses
- Course util.OptionalBool
+ Course util.OptionalBool
+ OnlySearchPrivate bool
}
//SearchOrderBy is used to sort the result
@@ -219,12 +220,15 @@ const (
SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC"
SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC"
SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC"
+ SearchOrderByWatches SearchOrderBy = "num_watches DESC"
)
// SearchRepositoryCondition creates a query condition according search repository options
func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
var cond = builder.NewCond()
-
+ if opts.OnlySearchPrivate {
+ cond = cond.And(builder.Eq{"is_private": true})
+ }
if opts.Private {
if opts.Actor != nil && !opts.Actor.IsAdmin && opts.Actor.ID != opts.OwnerID {
// OK we're in the context of a User
@@ -337,7 +341,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
if !opts.TopicOnly {
var likes = builder.NewCond()
for _, v := range strings.Split(opts.Keyword, ",") {
- likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
+ likes = likes.Or(builder.Like{"lower_alias", strings.ToLower(v)})
likes = likes.Or(builder.Like{"alias", v})
if opts.IncludeDescription {
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)})
diff --git a/models/search_record.go b/models/search_record.go
new file mode 100644
index 000000000..d9d85a591
--- /dev/null
+++ b/models/search_record.go
@@ -0,0 +1,83 @@
+package models
+
+import (
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/timeutil"
+ "xorm.io/xorm"
+)
+
+type SearchRecord struct {
+ ID int64 `xorm:"pk autoincr"`
+ //user
+ Keyword string `xorm:"NOT NULL"`
+ //
+ CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
+}
+
+func SaveSearchKeywordToDb(keyword string) error {
+ record := &SearchRecord{
+ Keyword: keyword,
+ }
+ sess := x.NewSession()
+ defer sess.Close()
+ _, err := sess.Insert(record)
+ if err != nil {
+ log.Info("insert error." + err.Error())
+ return err
+ }
+ return nil
+}
+
+func setIssueQueryCondition(sess *xorm.Session, Keyword string, isPull bool, userId int64) {
+ sess.And("issue.poster_id=?", userId)
+ sess.And("issue.is_pull=?", isPull)
+ sess.And("(issue.name like '%" + Keyword + "%' or issue.content like '%" + Keyword + "%')")
+ sess.Join("INNER", "repository", "issue.repo_id = repository.id").And("repository.is_private = ?", true)
+}
+
+func SearchPrivateIssueOrPr(Page int, PageSize int, Keyword string, isPull bool, userId int64) ([]*Issue, int64, error) {
+ sess := x.NewSession()
+ defer sess.Close()
+ setIssueQueryCondition(sess, Keyword, isPull, userId)
+ count, err := sess.Count(new(Issue))
+ if err != nil {
+ return nil, 0, err
+ }
+
+ setIssueQueryCondition(sess, Keyword, isPull, userId)
+ sess.Desc("issue.created_unix")
+ sess.Limit(PageSize, (Page-1)*PageSize)
+ issues := make([]*Issue, 0)
+ if err := sess.Find(&issues); err != nil {
+ return nil, 0, err
+ } else {
+ return issues, count, nil
+ }
+}
+
+func setDataSetQueryCondition(sess *xorm.Session, Keyword string, userId int64) {
+ sess.And("dataset.user_id=?", userId)
+ sess.And("(dataset.title like '%" + Keyword + "%' or dataset.description like '%" + Keyword + "%')")
+ sess.Join("INNER", "repository", "dataset.repo_id = repository.id").And("repository.is_private = ?", true)
+}
+
+func SearchDatasetBySQL(Page int, PageSize int, Keyword string, userId int64) ([]*Dataset, int64, error) {
+ sess := x.NewSession()
+ defer sess.Close()
+ setDataSetQueryCondition(sess, Keyword, userId)
+ count, err := sess.Count(new(Dataset))
+ if err != nil {
+ return nil, 0, err
+ }
+
+ setDataSetQueryCondition(sess, Keyword, userId)
+ sess.Desc("dataset.created_unix")
+ sess.Limit(PageSize, (Page-1)*PageSize)
+ datasets := make([]*Dataset, 0)
+ if err := sess.Find(&datasets); err != nil {
+ return nil, 0, err
+ } else {
+ return datasets, count, nil
+ }
+
+}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 3fc66c426..26f068193 100755
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -437,7 +437,7 @@ var (
//home page
RecommentRepoAddr string
-
+ ESSearchURL string
//notice config
UserNameOfNoticeRepo string
RepoNameOfNoticeRepo string
@@ -1267,6 +1267,7 @@ func NewContext() {
sec = Cfg.Section("homepage")
RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/")
+ ESSearchURL = sec.Key("ESSearchURL").MustString("http://192.168.207.94:9200")
sec = Cfg.Section("notice")
UserNameOfNoticeRepo = sec.Key("USER_NAME").MustString("OpenIOSSG")
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index c715ba8ce..09bb5015f 100755
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -254,6 +254,18 @@ page_dev_yunlao_desc3=Developers can freely choose the corresponding computing r
page_dev_yunlao_desc4=If your model requires more computing resources, you can also apply for it separately.
page_dev_yunlao_apply=Apply Separately
+search=Search
+search_repo=Repository
+search_dataset=DataSet
+search_issue=Issue
+search_pr=Pull Request
+search_user=User
+search_org=Organization
+search_finded=Find
+search_related=related
+search_maybe=maybe
+search_ge=
+
[explore]
repos = Repositories
select_repos = Select the project
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index b47a6bafa..d26065363 100755
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -256,6 +256,18 @@ page_dev_yunlao_desc3=开发者可以根据使用需求,自由选择相应计
page_dev_yunlao_desc4=如果您的模型需要更多的计算资源,也可以单独申请
page_dev_yunlao_apply=单独申请
+search=搜索
+search_repo=项目
+search_dataset=数据集
+search_issue=任务
+search_pr=合并请求
+search_user=用户
+search_org=组织
+search_finded=找到
+search_related=相关
+search_maybe=约为
+search_ge=个
+
[explore]
repos=项目
select_repos=精选项目
diff --git a/public/home/search.js b/public/home/search.js
new file mode 100644
index 000000000..70b5d4ef9
--- /dev/null
+++ b/public/home/search.js
@@ -0,0 +1,1281 @@
+var token;
+if(isEmpty(token)){
+ var meta = $("meta[name=_uid]");
+ if(!isEmpty(meta)){
+ token = meta.attr("content");
+ console.log("token is uid:" + token);
+ }
+}
+
+var html =document.documentElement;
+var lang = html.attributes["lang"]
+var isZh = true;
+if(lang != null && lang.nodeValue =="en-US" ){
+ console.log("the language is " + lang.nodeValue);
+ isZh=false;
+}else{
+ console.log("default lang=zh");
+}
+function isEmpty(str){
+ if(typeof str == "undefined" || str == null || str == ""){
+ return true;
+ }
+ return false;
+}
+
+var itemType={
+ "1":"repository",
+ "2":"issue",
+ "3":"user",
+ "4":"org",
+ "5":"dataset",
+ "6":"pr"
+};
+
+var sortBy={
+ "10":"default",
+ "11":"updated_unix.keyword",
+ "12":"num_watches",
+ "13":"num_stars",
+ "14":"num_forks",
+ "20":"default",
+ "21":"updated_unix.keyword",
+ "30":"default",
+ "31":"name.keyword",
+ "32":"name.keyword",
+ "33":"created_unix.keyword",
+ "34":"created_unix.keyword",
+ "40":"default",
+ "41":"name.keyword",
+ "42":"name.keyword",
+ "43":"created_unix.keyword",
+ "44":"created_unix.keyword",
+ "50":"default",
+ "51":"download_times",
+ "60":"default",
+ "61":"updated_unix.keyword"
+};
+
+var sortAscending={
+ "10":"false",
+ "11":"false",
+ "12":"false",
+ "13":"false",
+ "14":"false",
+ "20":"false",
+ "21":"false",
+ "30":"false",
+ "31":"true",
+ "32":"false",
+ "33":"false",
+ "34":"true",
+ "40":"false",
+ "41":"true",
+ "42":"false",
+ "43":"false",
+ "44":"true",
+ "50":"false",
+ "51":"false",
+ "60":"false",
+ "61":"false"
+};
+
+var currentPage = 1;
+var pageSize = 15;
+var currentSearchTableName ="repository";
+var currentSearchKeyword="";
+var currentSearchSortBy="";
+var currentSearchAscending="false";
+var OnlySearchLabel=false;
+var startIndex =1;
+var endIndex = 5;
+var totalPage = 1;
+var totalNum = 0;
+var privateTotal = 0;
+
+function initPageInfo(){
+ currentPage = 1;
+ startIndex =1;
+ endIndex = 5;
+}
+
+function searchItem(type,sortType){
+ console.log("enter item 2.");
+ currentSearchKeyword = document.getElementById("keyword_input").value;
+ if(!isEmpty(currentSearchKeyword)){
+ initPageInfo();
+ currentSearchTableName = itemType[type];
+ currentSearchSortBy = sortBy[sortType];
+ currentSearchAscending = sortAscending[sortType];
+ OnlySearchLabel =false;
+
+ page(currentPage);
+ }
+}
+
+
+
+function search(){
+ console.log("enter here 1.");
+ currentSearchKeyword = document.getElementById("keyword_input").value;
+ if(!isEmpty(currentSearchKeyword)){
+ currentSearchKeyword = currentSearchKeyword.trim();
+ }
+ $('#searchForm').addClass("hiddenSearch");
+ initPageInfo();
+ if(!isEmpty(currentSearchKeyword)){
+ document.getElementById("find_id").innerHTML=getLabel(isZh,"search_finded");
+ currentSearchSortBy = sortBy[10];
+ currentSearchAscending = "false";
+ OnlySearchLabel =false;
+ page(currentPage);
+ if(currentSearchTableName != "repository"){
+ doSearch("repository",currentSearchKeyword,1,pageSize,true,"",false);
+ }
+ if(currentSearchTableName != "issue"){
+ doSearch("issue",currentSearchKeyword,1,pageSize,true,"",false);
+ }
+ if(currentSearchTableName != "user"){
+ doSearch("user",currentSearchKeyword,1,pageSize,true,"",false);
+ }
+ if(currentSearchTableName != "org"){
+ doSearch("org",currentSearchKeyword,1,pageSize,true,"",false);
+ }
+ if(currentSearchTableName != "dataset"){
+ doSearch("dataset",currentSearchKeyword,1,pageSize,true,"",false);
+ }
+ if(currentSearchTableName != "pr"){
+ doSearch("pr",currentSearchKeyword,1,pageSize,true,"",false);
+ }
+ }else{
+ initDiv(false);
+ document.getElementById("find_id").innerHTML=getLabel(isZh,"search_empty");
+ $('#find_title').html("");
+ document.getElementById("sort_type").innerHTML="";
+ document.getElementById("child_search_item").innerHTML="";
+ document.getElementById("page_menu").innerHTML="";
+ $('#repo_total').text("");
+ $('#pr_total').text("");
+ $('#issue_total').text("");
+ $('#dataset_total').text("");
+ $('#user_total').text("");
+ $('#org_total').text("");
+ setActivate(null);
+ }
+}
+
+function initDiv(isSearchLabel=false){
+ if(isSearchLabel){
+ document.getElementById("search_div").style.display="none";
+ document.getElementById("search_label_div").style.display="block";
+ document.getElementById("dataset_item").style.display="none";
+ document.getElementById("issue_item").style.display="none";
+ document.getElementById("pr_item").style.display="none";
+ document.getElementById("user_item").style.display="none";
+ document.getElementById("org_item").style.display="none";
+ document.getElementById("find_id").innerHTML="";
+
+ }else{
+ document.getElementById("search_div").style.display="block";
+ document.getElementById("search_label_div").style.display="none";
+ document.getElementById("dataset_item").style.display="block";
+ document.getElementById("issue_item").style.display="block";
+ document.getElementById("pr_item").style.display="block";
+ document.getElementById("user_item").style.display="block";
+ document.getElementById("org_item").style.display="block";
+ document.getElementById("find_id").innerHTML=getLabel(isZh,"search_finded");
+ }
+}
+
+function doSearchLabel(tableName,keyword,sortBy="",ascending="false"){
+ initDiv(true);
+ //document.getElementById("search_div").style.display="none";
+ //document.getElementById("search_label_div").style.display="block";
+ document.getElementById("search_label_div").innerHTML="
#" + keyword + "
";
+
+ currentSearchKeyword = keyword;
+ initPageInfo();
+ currentSearchTableName = tableName;
+ currentSearchSortBy = sortBy;
+ currentSearchAscending = ascending;
+ OnlySearchLabel =true;
+
+ page(currentPage);
+}
+
+function searchLabel(tableName,keyword,sortBy="",ascending="false"){
+
+ sessionStorage.setItem("keyword",keyword);
+ sessionStorage.setItem("tableName",tableName);
+ sessionStorage.setItem("searchLabel",true);
+ sessionStorage.setItem("sortBy",sortBy);
+ sessionStorage.setItem("ascending",ascending);
+ console.log("enter label search.");
+ window.open("/all/search/");
+}
+
+function doSearch(tableName,keyword,page,pageSize=15,onlyReturnNum=true,sortBy="",OnlySearchLabel=false){
+ var language = "zh-CN";
+ if(!isZh){
+ language="en-US";
+ }
+ $.ajax({
+ type:"GET",
+ url:"/all/dosearch/",
+ headers: {
+ authorization:token,
+ },
+ dataType:"json",
+ data:{
+ 'TableName': tableName,
+ 'Key': keyword,
+ 'Page': page,
+ 'PageSize': pageSize,
+ 'OnlyReturnNum':onlyReturnNum,
+ 'SortBy':sortBy,
+ 'OnlySearchLabel':OnlySearchLabel,
+ 'Ascending':currentSearchAscending,
+ 'WebTotal':totalNum,
+ 'PrivateTotal':privateTotal,
+ 'language':language
+ },
+ async:true,
+ success:function(json){
+ console.log("tableName=" + tableName);
+ console.log(json);
+ displayResult(tableName,page,json,onlyReturnNum,keyword);
+ },
+ error:function(response) {
+ console.log(response);
+ }
+ });
+}
+
+function displayResult(tableName,page,jsonResult,onlyReturnNum,keyword){
+ if(tableName == "repository") {
+ displayRepoResult(page,jsonResult,onlyReturnNum,keyword);
+ } else if (tableName == "issue") {
+ displayIssueResult(page,jsonResult,onlyReturnNum,keyword);
+ } else if (tableName == "user") {
+ displayUserResult(page,jsonResult,onlyReturnNum,keyword);
+ } else if (tableName == "org") {
+ displayOrgResult(page,jsonResult,onlyReturnNum,keyword);
+ } else if (tableName == "dataset") {
+ displayDataSetResult(page,jsonResult,onlyReturnNum,keyword);
+ } else if (tableName == "pr") {
+ displayPrResult(page,jsonResult,onlyReturnNum,keyword);
+ }
+ if(!onlyReturnNum){
+ console.log("set total num." + tableName);
+ totalPage =Math.ceil(jsonResult.Total/pageSize);
+ totalNum = jsonResult.Total;
+ privateTotal = jsonResult.PrivateTotal;
+ setPage(page);
+ }
+
+}
+
+function displayPrResult(page,jsonResult,onlyReturnNum,keyword){
+ var data = jsonResult.Result;
+ var total = jsonResult.Total;
+ $('#pr_total').text(total);
+ if(!onlyReturnNum){
+ setActivate("pr_item");
+ //$('#keyword_desc').text(keyword);
+ //$('#obj_desc').text(getLabel(isZh,"search_pr"));
+ //$('#child_total').text(total);
+ $('#find_title').html(getLabel(isZh,"find_title").replace('{keyword}',keyword).replace('{tablename}',getLabel(isZh,"search_pr")).replace('{total}',total));
+
+ setIssueOrPrInnerHtml(data,"pulls");
+ }
+}
+
+var categoryDesc={
+ "computer_vision":"计算机视觉",
+ "natural_language_processing":"自然语言处理",
+ "speech_processing":"语音处理",
+ "computer_vision_natural_language_processing":"计算机视觉、自然语言处理"
+};
+
+var categoryENDesc={
+ "computer_vision":"computer vision",
+ "natural_language_processing":"natural language processing",
+ "speech_processing":"speech processing",
+ "computer_vision_natural_language_processing":"computer vision and natural language processing"
+};
+
+var taskDesc={
+ "machine_translation":"机器翻译",
+ "question_answering_system":"问答系统",
+ "information_retrieval":"信息检索",
+ "knowledge_graph":"知识图谱",
+ "text_annotation":"文本标注",
+ "text_categorization":"文本分类",
+ "emotion_analysis":"情感分析",
+ "language_modeling":"语言建模",
+ "speech_recognition":"语音识别",
+ "automatic_digest":"自动文摘",
+ "information_extraction":"信息抽取",
+ "description_generation":"说明生成",
+ "image_classification":"图像分类",
+ "face_recognition":"人脸识别",
+ "image_search":"图像搜索",
+ "target_detection":"目标检测",
+ "image_description_generation":"图像描述生成",
+ "vehicle_license_plate_recognition":"车辆车牌识别",
+ "medical_image_analysis":"医学图像分析",
+ "unmanned":"无人驾驶",
+ "unmanned_security":"无人安防",
+ "drone":"无人机",
+ "vr_ar":"VR/AR",
+ "2_d_vision":"2-D视觉",
+ "2_5_d_vision":"2.5-D视觉",
+ "3_d_reconstruction":"3D重构",
+ "image_processing":"图像处理",
+ "video_processing":"视频处理",
+ "visual_input_system":"视觉输入系统",
+ "speech_coding":"语音编码",
+ "speech_enhancement":"语音增强",
+ "speech_recognition":"语音识别",
+ "speech_synthesis":"语音合成"
+};
+
+var taskENDesc={
+ "machine_translation":"machine translation",
+ "question_answering_system":"question answering system",
+ "information_retrieval":"information retrieval",
+ "knowledge_graph":"knowledge graph",
+ "text_annotation":"text annotation",
+ "text_categorization":"text categorization",
+ "emotion_analysis":"emotion analysis",
+ "language_modeling":"language modeling",
+ "speech_recognition":"speech recognition",
+ "automatic_digest":"automatic digest",
+ "information_extraction":"information extraction",
+ "description_generation":"description generation",
+ "image_classification":"image classification",
+ "face_recognition":"face recognition",
+ "image_search":"image search",
+ "target_detection":"target detection",
+ "image_description_generation":"image description generation",
+ "vehicle_license_plate_recognition":"vehicle license plate recognition",
+ "medical_image_analysis":"medical image analysis",
+ "unmanned":"unmanned",
+ "unmanned_security":"unmanned security",
+ "drone":"drone",
+ "vr_ar":"VR/AR",
+ "2_d_vision":"2.D vision",
+ "2.5_d_vision":"2.5D vision",
+ "3_d_reconstruction":"3Dreconstruction",
+ "image_processing":"image processing",
+ "video_processing":"video processing",
+ "visual_input_system":"visual input system",
+ "speech_coding":"speech coding",
+ "speech_enhancement":"speech enhancement",
+ "speech_recognition":"speech recognition",
+ "speech_synthesis":"speech synthesis"
+};
+
+function getCategoryDesc(isZh,key){
+ var re = key;
+ if(isZh){
+ re = categoryDesc[key];
+ }else{
+ re = categoryENDesc[key];
+ }
+ if(isEmpty(re)){
+ return key;
+ }
+ return re;
+}
+
+function getTaskDesc(isZh,key){
+ var re = key;
+ if(isZh){
+ re = taskDesc[key];
+ }else{
+ re = taskENDesc[key];
+ }
+ if(isEmpty(re)){
+ return key;
+ }
+ return re;
+}
+
+function getActiveItem(sort_type){
+ console.log("currentSearchSortBy=" + currentSearchSortBy + " sort_type=" + sortBy[sort_type]);
+ if(currentSearchSortBy == sortBy[sort_type] && currentSearchAscending == sortAscending[sort_type]){
+ return "active ";
+ }else{
+ return "";
+ }
+}
+
+function displayDataSetResult(page,jsonResult,onlyReturnNum,keyword){
+ var data = jsonResult.Result;
+ var total = jsonResult.Total;
+ $('#dataset_total').text(total);
+ if(!onlyReturnNum){
+ setActivate("dataset_item");
+ //$('#keyword_desc').text(keyword);
+ //$('#obj_desc').text(getLabel(isZh,"search_dataset"));
+ //$('#child_total').text(total);
+ $('#find_title').html(getLabel(isZh,"find_title").replace('{keyword}',keyword).replace('{tablename}',getLabel(isZh,"search_dataset")).replace('{total}',total));
+
+ var sortHtml = "";
+ sortHtml +="";
+ sortHtml +="";
+ document.getElementById("sort_type").innerHTML=sortHtml;
+
+ var html = "";
+ var currentTime = new Date().getTime();
+ for(var i = 0; i < data.length;i++){
+ var recordMap = data[i];
+ html += "";
+ html += "
";
+ html += "
" ;
+ if(!isEmpty(recordMap["category"])){
+ html += " " + getCategoryDesc(isZh,recordMap["category"]) + "";
+ }
+ if(!isEmpty(recordMap["task"])){
+ html += " " + getTaskDesc(isZh,recordMap["task"]) + "";
+ }
+ html += " " +recordMap["download_times"] + " ";
+ html +="
";
+ html += "
";
+ html += "
";
+ html += "
" + recordMap["description"] + "
";
+ if(!isEmpty(recordMap["file_name"])){
+ html += "
" + recordMap["file_name"] + "
";
+ }
+ html +="
";
+ html +=" "+ getLabel(isZh,"search_lasted_update") + " " + recordMap["updated_html"];
+ html +="
";
+ html +="
";
+ html +="
";
+ html +="
";
+ }
+ document.getElementById("child_search_item").innerHTML=html;
+ }
+}
+
+function displayOrgResult(page,jsonResult,onlyReturnNum,keyword){
+ var data = jsonResult.Result;
+ var total = jsonResult.Total;
+ $('#org_total').text(total);
+ if(!onlyReturnNum){
+ setActivate("org_item");
+ //$('#keyword_desc').text(keyword);
+ //$('#obj_desc').text(getLabel(isZh,"search_org"));
+ //$('#child_total').text(total);
+ $('#find_title').html(getLabel(isZh,"find_title").replace('{keyword}',keyword).replace('{tablename}',getLabel(isZh,"search_org")).replace('{total}',total));
+
+ var sortHtml = "";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ document.getElementById("sort_type").innerHTML=sortHtml;
+
+ var html = "";
+ var currentTime = new Date().getTime();
+ for(var i = 0; i < data.length;i++){
+ var recordMap = data[i];
+ html += "";
+ html += "

";
+ html += "
";
+ html += "
";
+ html += "
";
+ html += "
" + recordMap["description"] + "
";
+ html +="
";
+ if(!isEmpty(recordMap["location"]) && recordMap["location"] != "null"){
+ html +=" " + recordMap["location"];
+ }
+ html +=" ";
+ if(!isEmpty(recordMap["website"]) && recordMap["website"] != "null"){
+ html +=" " + "" + recordMap["website"] + "";
+ }
+ html +=" "+ getLabel(isZh,"search_add_by") + " ";
+ html += recordMap["add_time"]
+ html +="
";
+ html +="
";
+ html +="
";
+ html +="
";
+ }
+ document.getElementById("child_search_item").innerHTML=html;
+ }
+}
+var monthDisplay=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Spt","Oct","Nov","Dec");
+function displayUserResult(page,jsonResult,onlyReturnNum,keyword){
+ var data = jsonResult.Result;
+ var total = jsonResult.Total;
+ $('#user_total').text(total);
+ if(!onlyReturnNum){
+ setActivate("user_item");
+ //$('#keyword_desc').text(keyword);
+ //$('#obj_desc').text(getLabel(isZh,"search_user"));
+ //$('#child_total').text(total);
+
+ $('#find_title').html(getLabel(isZh,"find_title").replace('{keyword}',keyword).replace('{tablename}',getLabel(isZh,"search_user")).replace('{total}',total));
+
+ var sortHtml = "";//equal user sort by
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+
+ document.getElementById("sort_type").innerHTML=sortHtml;
+
+ var html = "";
+ var currentTime = new Date().getTime();
+ for(var i = 0; i < data.length;i++){
+ var recordMap = data[i];
+ html += "";
+ html += "

";
+ html += "
";
+ html += "
";
+ html += "
";
+ html += "
" + recordMap["description"] + "
";
+ html +="
";
+ if(!isEmpty(recordMap["email"]) && recordMap["email"] != "null"){
+ html +=" " + recordMap["email"] + "";
+ }
+ html +=" "+ getLabel(isZh,"search_add_by") + " ";
+ html += recordMap["add_time"]
+ html +="
";
+ html +="
";
+ html +="
";
+ html +="
";
+ }
+ document.getElementById("child_search_item").innerHTML=html;
+ }
+}
+
+function setIssueOrPrInnerHtml(data,path){
+ var sortHtml = "";
+ if(path =="issues"){
+ sortHtml +="";
+ sortHtml +="";
+ }else{
+ sortHtml +="";
+ sortHtml +="";
+ }
+
+ document.getElementById("sort_type").innerHTML=sortHtml;
+
+ var html = "";
+ var currentTime = new Date().getTime();
+ for(var i = 0; i < data.length;i++){
+ var recordMap = data[i];
+ html += "";
+ html += "
";
+ html += "
";
+ html += "
";
+ html += "
" + recordMap["content"] + "
";
+ html +="
";
+ html +=" ";
+ html +=" " + addBlank(recordMap["repoUrl"]) +" #" + recordMap["index"] + " ";
+ html +=" ";
+ if(recordMap["is_closed"] != null && (!(recordMap["is_closed"]) || recordMap["is_closed"]=="f")){
+ html += getLabel(isZh,"search_open");
+ }else{
+ html += getLabel(isZh,"search_closed");
+ }
+ html +=" " + recordMap["num_comments"];
+
+ html +=" "+ getLabel(isZh,"search_lasted_update") + " "+ recordMap["updated_html"];
+
+ html +="
";
+ html +="
";
+ html +="
";
+ html +="
";
+ }
+ document.getElementById("child_search_item").innerHTML=html;
+}
+
+function addBlank(url){
+ if(url == null){
+ return url;
+ }
+ var tmps = url.split("/");
+ if(tmps.length == 2){
+ return tmps[0] + " / " + tmps[1];
+ }
+ return url;
+}
+
+function displayIssueResult(page,jsonResult,onlyReturnNum,keyword){
+ var data = jsonResult.Result;
+ var total = jsonResult.Total;
+ $('#issue_total').text(total);
+ if(!onlyReturnNum){
+ setActivate("issue_item");
+ //$('#keyword_desc').text(keyword);
+ //$('#obj_desc').text(getLabel(isZh,"search_issue"));
+ //$('#child_total').text(total);
+ $('#find_title').html(getLabel(isZh,"find_title").replace('{keyword}',keyword).replace('{tablename}',getLabel(isZh,"search_issue")).replace('{total}',total));
+
+ setIssueOrPrInnerHtml(data,"issues");
+ }
+}
+
+function setActivate(name){
+ $('#repo_item').removeClass("active");
+ $('#user_item').removeClass("active");
+ $('#issue_item').removeClass("active");
+ $('#dataset_item').removeClass("active");
+ $('#org_item').removeClass("active");
+ $('#pr_item').removeClass("active");
+ if(name==null){
+ return;
+ }
+ var tmp = "#" + name;
+ $(tmp).addClass("active");
+}
+
+function displayRepoResult(page,jsonResult,onlyReturnNum,keyword){
+ var data = jsonResult.Result;
+ var total = jsonResult.Total;
+ $('#repo_total').text(total);
+
+ if(!onlyReturnNum){
+ setActivate("repo_item");
+ // $('#keyword_desc').text(keyword);
+ //$('#obj_desc').text(getLabel(isZh,"search_repo"));
+ //$('#child_total').text(total);
+ $('#find_title').html(getLabel(isZh,"find_title").replace('{keyword}',keyword).replace('{tablename}',getLabel(isZh,"search_repo")).replace('{total}',total));
+
+ var sortHtml = "";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+ sortHtml +="";
+
+ document.getElementById("sort_type").innerHTML=sortHtml;
+
+ var html = "";
+ var currentTime = new Date().getTime();
+ for(var i = 0; i < data.length;i++){
+ var recordMap = data[i];
+ html += "";
+ if(!isEmpty(recordMap['avatar'])){
+ html += "

";
+ }
+ html += "
";
+ html += "
";
+ html += "
";
+ html += "
" + recordMap["description"] + "
";
+ html += "
";
+ if(!isEmpty(recordMap["topics"]) && recordMap["topics"] !="null"){
+ for(var j = 0; j < recordMap["topics"].length;j++){
+ //function searchLabel(tableName,keyword,sortBy="",ascending=false)
+ html +="
"+ recordMap["hightTopics"][j] + "
";
+ }
+ }
+ html +="
";
+ html +="
";
+ html +=" " + recordMap["num_watches"] + " " + recordMap["num_stars"] + " " + recordMap["num_forks"] +" ";
+ html +=" "+ getLabel(isZh,"search_lasted_update") + " " + recordMap["updated_html"];
+ if(!isEmpty(recordMap["lang"])){
+ var lang = recordMap["lang"]
+ var tmpLang = recordMap["lang"].split(",");
+ if(tmpLang.length>0){
+ lang = tmpLang[0]
+ }
+ var backColor = "#3572A5";
+ if(LanguagesColor[lang] != null){
+ backColor = LanguagesColor[lang];
+ }
+ html +=" " + lang + "";
+ }
+ html +="
";
+ html +="
";
+ html +="
";
+ html +="
";
+ }
+
+ document.getElementById("child_search_item").innerHTML=html;
+ }
+}
+
+function getTime(UpdatedUnix,currentTime){
+ UpdatedUnix = UpdatedUnix;
+ currentTime = currentTime / 1000;
+ var timeEscSecond = currentTime - UpdatedUnix;
+ if( timeEscSecond < 0){
+ timeEscSecond = 1;
+ }
+ console.log("currentTime=" + currentTime + " updateUnix=" + UpdatedUnix);
+
+ var hours= Math.floor(timeEscSecond / 3600);
+ //计算相差分钟数
+ var leave2 = Math.floor(timeEscSecond % (3600)); //计算小时数后剩余的秒数
+ var minutes= Math.floor(leave2 / 60);//计算相差分钟数
+
+ var leave3=Math.floor(leave2 % 60); //计算分钟数后剩余的秒数
+ var seconds= leave3;
+
+ if(hours == 0 && minutes == 0){
+ return seconds + getRepoOrOrg(6,isZh);
+ }else{
+ if(hours > 0){
+ if(hours >= 24){
+ var days = Math.ceil(hours/24)
+ if (days >= 30 && days <365){
+ return Math.ceil(days/30) + getRepoOrOrg(8,isZh);
+ }else if(days >= 365){
+ return Math.ceil(days/365) + getRepoOrOrg(9,isZh);
+ }
+ return Math.ceil(hours/24) + getRepoOrOrg(7,isZh);
+ }else{
+ return hours + getRepoOrOrg(4,isZh);
+ }
+ }else{
+ return minutes + getRepoOrOrg(5,isZh);
+ }
+ }
+}
+
+function getRepoOrOrg(key,isZhLang){
+ if(isZhLang){
+ return repoAndOrgZH[key];
+ }else{
+ return repoAndOrgEN[key];
+ }
+}
+
+var repoAndOrgZH={
+ "1":"项目",
+ "2":"成员",
+ "3":"团队",
+ "4":"小时前",
+ "5":"分钟前",
+ "6":"秒前",
+ "7":"天前",
+ "8":"个月前",
+ "9":"年前"
+};
+
+var repoAndOrgEN={
+ "1":"repository",
+ "2":"Members ",
+ "3":"Teams",
+ "4":" hours ago",
+ "5":" minutes ago",
+ "6":" seconds ago",
+ "7":" day ago",
+ "8":" month ago",
+ "9":" year ago"
+};
+
+
+
+
+function page(current){
+
+ currentPage=current;
+ doSearch(currentSearchTableName,currentSearchKeyword,current,pageSize,false,currentSearchSortBy,OnlySearchLabel);
+
+ }
+
+ function nextPage(){
+ currentPage = currentPage+1;
+ console.log("currentPage=" + currentPage);
+ if(currentPage >= endIndex){
+ startIndex=startIndex+1;
+ endIndex = endIndex +1;
+ }
+ page(currentPage);
+ }
+
+ function prePage(){
+ console.log("currentPage=" + currentPage);
+ if(currentPage > 1){
+ currentPage = currentPage-1;
+ if(currentPage <= startIndex && startIndex > 1){
+ startIndex = startIndex -1;
+ endIndex = endIndex - 1;
+ }
+ console.log("currentPage=" + (currentPage));
+ page(currentPage);
+ }
+ }
+
+function getXPosition(e){
+ var x=e.offsetLeft;
+ while(e=e.offsetParent)
+ {
+ x+=e.offsetLeft;
+ }
+ return x+20;//-260防止屏幕超出
+}
+//获取y坐标
+function getYPosition(e){
+ var y=e.offsetTop;
+ while(e=e.offsetParent)
+ {
+ y+=e.offsetTop;
+ }
+ return y+20;//80为input高度
+}
+
+
+ function goPage(event){
+
+ var inputpage = document.getElementById("inputpage_div")
+ var left = getXPosition(event.target);
+ var top = getYPosition(event.target);
+ var goNum = $('#inputpage').val();
+ if (goNum<=0){
+ showTip(getLabel(isZh,"search_input_large_0"),"warning",left+5,top);
+ }
+ else if(goNum<=totalPage){
+ page(goNum);
+ }
+ else{
+ showTip(getLabel(isZh,"search_input_maxed"),"warning",left+5,top);
+ }
+ }
+
+ function showTip(tip, type,left,top) {
+ var $tip = $('#tipmsg');
+ var tipmsg = document.getElementById("tipmsg")
+ var style="z-index:10024;top:" + top + "px;left:" + left + "px;position:absolute;width:200px;height:60px;vertical-align:middle;";
+ console.log(style);
+ tipmsg.style = style;
+ var html ="" + tip + "
"
+ $tip.stop(true).prop('class', 'alert alert-' + type).html(html).fadeIn(500).delay(2000).fadeOut(500);
+ }
+
+ function setPage(currentPage){
+ console.log("totalPage=" + totalPage);
+ var html ="";
+ console.log("currentPage=" + currentPage);
+ console.log("privateTotal=" + privateTotal);
+ // if(totalPage==0){
+ // return;
+ // }
+ html += "" + getLabel(isZh,"search_input_total") + " " + totalNum + " " + getLabel(isZh,"search_srtip") + ""
+ if(currentPage > 1){
+ html += "" + getLabel(isZh,"search_home_page") + "";
+ html += "";
+ }else{
+ html += "" + getLabel(isZh,"search_home_page") + "";
+ html += "";
+ }
+
+ for(var i=startIndex; i <= endIndex; i++){
+ var page_i = i;
+ if(page_i > totalPage){
+ break;
+ }
+ if( page_i == currentPage){
+ html += "" + page_i + "";
+ }else{
+ html += "" + page_i + "";
+ }
+ }
+
+ if(currentPage >=totalPage){
+ html += "";
+ html += "" + getLabel(isZh,"search_last_page") + "";
+ }else{
+ html += "";
+ html += "" + getLabel(isZh,"search_last_page") + "";
+ }
+
+ html +=" " + getLabel(isZh,"search_go_to") + "
" + getLabel(isZh,"search_go_page") + "
";
+ console.log("html=" + html)
+ document.getElementById("page_menu").innerHTML=html;
+ $('#inputpage').on('keypress',function(event){
+ if(event.keyCode == 13){
+ goPage(event);
+ }
+ });
+ }
+
+$('#keyword_input').on('keypress',function(event){
+ if(event.keyCode == 13){
+ search();
+ }
+});
+
+
+
+
+
+var LanguagesColor = {
+ "1C Enterprise": "#814CCC",
+ "ABAP": "#E8274B",
+ "AGS Script": "#B9D9FF",
+ "AMPL": "#E6EFBB",
+ "ANTLR": "#9DC3FF",
+ "API Blueprint": "#2ACCA8",
+ "APL": "#5A8164",
+ "ASP": "#6a40fd",
+ "ATS": "#1ac620",
+ "ActionScript": "#882B0F",
+ "Ada": "#02f88c",
+ "Agda": "#315665",
+ "Alloy": "#64C800",
+ "AngelScript": "#C7D7DC",
+ "AppleScript": "#101F1F",
+ "Arc": "#aa2afe",
+ "AspectJ": "#a957b0",
+ "Assembly": "#6E4C13",
+ "Asymptote": "#4a0c0c",
+ "AutoHotkey": "#6594b9",
+ "AutoIt": "#1C3552",
+ "Ballerina": "#FF5000",
+ "Batchfile": "#C1F12E",
+ "BlitzMax": "#cd6400",
+ "Boo": "#d4bec1",
+ "Brainfuck": "#2F2530",
+ "C": "#555555",
+ "C#": "#178600",
+ "C++": "#f34b7d",
+ "CSS": "#563d7c",
+ "Ceylon": "#dfa535",
+ "Chapel": "#8dc63f",
+ "Cirru": "#ccccff",
+ "Clarion": "#db901e",
+ "Clean": "#3F85AF",
+ "Click": "#E4E6F3",
+ "Clojure": "#db5855",
+ "CoffeeScript": "#244776",
+ "ColdFusion": "#ed2cd6",
+ "Common Lisp": "#3fb68b",
+ "Common Workflow Language": "#B5314C",
+ "Component Pascal": "#B0CE4E",
+ "Crystal": "#000100",
+ "Cuda": "#3A4E3A",
+ "D": "#ba595e",
+ "DM": "#447265",
+ "Dart": "#00B4AB",
+ "DataWeave": "#003a52",
+ "Dhall": "#dfafff",
+ "Dockerfile": "#384d54",
+ "Dogescript": "#cca760",
+ "Dylan": "#6c616e",
+ "E": "#ccce35",
+ "ECL": "#8a1267",
+ "EQ": "#a78649",
+ "Eiffel": "#946d57",
+ "Elixir": "#6e4a7e",
+ "Elm": "#60B5CC",
+ "Emacs Lisp": "#c065db",
+ "EmberScript": "#FFF4F3",
+ "Erlang": "#B83998",
+ "F#": "#b845fc",
+ "F*": "#572e30",
+ "FLUX": "#88ccff",
+ "Factor": "#636746",
+ "Fancy": "#7b9db4",
+ "Fantom": "#14253c",
+ "Faust": "#c37240",
+ "Forth": "#341708",
+ "Fortran": "#4d41b1",
+ "FreeMarker": "#0050b2",
+ "Frege": "#00cafe",
+ "G-code": "#D08CF2",
+ "GAML": "#FFC766",
+ "GDScript": "#355570",
+ "Game Maker Language": "#71b417",
+ "Genie": "#fb855d",
+ "Gherkin": "#5B2063",
+ "Glyph": "#c1ac7f",
+ "Gnuplot": "#f0a9f0",
+ "Go": "#00ADD8",
+ "Golo": "#88562A",
+ "Gosu": "#82937f",
+ "Grammatical Framework": "#79aa7a",
+ "Groovy": "#e69f56",
+ "HTML": "#e34c26",
+ "Hack": "#878787",
+ "Harbour": "#0e60e3",
+ "Haskell": "#5e5086",
+ "Haxe": "#df7900",
+ "HiveQL": "#dce200",
+ "HolyC": "#ffefaf",
+ "Hy": "#7790B2",
+ "IDL": "#a3522f",
+ "IGOR Pro": "#0000cc",
+ "Idris": "#b30000",
+ "Io": "#a9188d",
+ "Ioke": "#078193",
+ "Isabelle": "#FEFE00",
+ "J": "#9EEDFF",
+ "JSONiq": "#40d47e",
+ "Java": "#b07219",
+ "JavaScript": "#f1e05a",
+ "Jolie": "#843179",
+ "Jsonnet": "#0064bd",
+ "Julia": "#a270ba",
+ "Jupyter Notebook": "#DA5B0B",
+ "KRL": "#28430A",
+ "Kotlin": "#F18E33",
+ "LFE": "#4C3023",
+ "LLVM": "#185619",
+ "LOLCODE": "#cc9900",
+ "LSL": "#3d9970",
+ "Lasso": "#999999",
+ "Lex": "#DBCA00",
+ "LiveScript": "#499886",
+ "LookML": "#652B81",
+ "Lua": "#000080",
+ "MATLAB": "#e16737",
+ "MAXScript": "#00a6a6",
+ "MLIR": "#5EC8DB",
+ "MQL4": "#62A8D6",
+ "MQL5": "#4A76B8",
+ "MTML": "#b7e1f4",
+ "Makefile": "#427819",
+ "Mask": "#f97732",
+ "Max": "#c4a79c",
+ "Mercury": "#ff2b2b",
+ "Meson": "#007800",
+ "Metal": "#8f14e9",
+ "Mirah": "#c7a938",
+ "Modula-3": "#223388",
+ "NCL": "#28431f",
+ "Nearley": "#990000",
+ "Nemerle": "#3d3c6e",
+ "NetLinx": "#0aa0ff",
+ "NetLinx+ERB": "#747faa",
+ "NetLogo": "#ff6375",
+ "NewLisp": "#87AED7",
+ "Nextflow": "#3ac486",
+ "Nim": "#37775b",
+ "Nit": "#009917",
+ "Nix": "#7e7eff",
+ "Nu": "#c9df40",
+ "OCaml": "#3be133",
+ "ObjectScript": "#424893",
+ "Objective-C": "#438eff",
+ "Objective-C++": "#6866fb",
+ "Objective-J": "#ff0c5a",
+ "Odin": "#60AFFE",
+ "Omgrofl": "#cabbff",
+ "Opal": "#f7ede0",
+ "OpenQASM": "#AA70FF",
+ "Oxygene": "#cdd0e3",
+ "Oz": "#fab738",
+ "P4": "#7055b5",
+ "PHP": "#4F5D95",
+ "PLSQL": "#dad8d8",
+ "Pan": "#cc0000",
+ "Papyrus": "#6600cc",
+ "Parrot": "#f3ca0a",
+ "Pascal": "#E3F171",
+ "Pawn": "#dbb284",
+ "Pep8": "#C76F5B",
+ "Perl": "#0298c3",
+ "PigLatin": "#fcd7de",
+ "Pike": "#005390",
+ "PogoScript": "#d80074",
+ "PostScript": "#da291c",
+ "PowerBuilder": "#8f0f8d",
+ "PowerShell": "#012456",
+ "Processing": "#0096D8",
+ "Prolog": "#74283c",
+ "Propeller Spin": "#7fa2a7",
+ "Puppet": "#302B6D",
+ "PureBasic": "#5a6986",
+ "PureScript": "#1D222D",
+ "Python": "#3572A5",
+ "QML": "#44a51c",
+ "Quake": "#882233",
+ "R": "#198CE7",
+ "RAML": "#77d9fb",
+ "RUNOFF": "#665a4e",
+ "Racket": "#3c5caa",
+ "Ragel": "#9d5200",
+ "Raku": "#0000fb",
+ "Rascal": "#fffaa0",
+ "Reason": "#ff5847",
+ "Rebol": "#358a5b",
+ "Red": "#f50000",
+ "Ren'Py": "#ff7f7f",
+ "Ring": "#2D54CB",
+ "Riot": "#A71E49",
+ "Roff": "#ecdebe",
+ "Rouge": "#cc0088",
+ "Ruby": "#701516",
+ "Rust": "#dea584",
+ "SAS": "#B34936",
+ "SQF": "#3F3F3F",
+ "SRecode Template": "#348a34",
+ "SaltStack": "#646464",
+ "Scala": "#c22d40",
+ "Scheme": "#1e4aec",
+ "Self": "#0579aa",
+ "Shell": "#89e051",
+ "Shen": "#120F14",
+ "Slash": "#007eff",
+ "Slice": "#003fa2",
+ "SmPL": "#c94949",
+ "Smalltalk": "#596706",
+ "Solidity": "#AA6746",
+ "SourcePawn": "#5c7611",
+ "Squirrel": "#800000",
+ "Stan": "#b2011d",
+ "Standard ML": "#dc566d",
+ "Starlark": "#76d275",
+ "SuperCollider": "#46390b",
+ "Swift": "#ffac45",
+ "SystemVerilog": "#DAE1C2",
+ "TI Program": "#A0AA87",
+ "Tcl": "#e4cc98",
+ "TeX": "#3D6117",
+ "Terra": "#00004c",
+ "Turing": "#cf142b",
+ "TypeScript": "#2b7489",
+ "UnrealScript": "#a54c4d",
+ "V": "#5d87bd",
+ "VBA": "#867db1",
+ "VBScript": "#15dcdc",
+ "VCL": "#148AA8",
+ "VHDL": "#adb2cb",
+ "Vala": "#fbe5cd",
+ "Verilog": "#b2b7f8",
+ "Vim script": "#199f4b",
+ "Visual Basic .NET": "#945db7",
+ "Volt": "#1F1F1F",
+ "Vue": "#2c3e50",
+ "WebAssembly": "#04133b",
+ "Wollok": "#a23738",
+ "X10": "#4B6BEF",
+ "XC": "#99DA07",
+ "XQuery": "#5232e7",
+ "XSLT": "#EB8CEB",
+ "YARA": "#220000",
+ "YASnippet": "#32AB90",
+ "Yacc": "#4B6C4B",
+ "ZAP": "#0d665e",
+ "ZIL": "#dc75e5",
+ "ZenScript": "#00BCD1",
+ "Zephir": "#118f9e",
+ "Zig": "#ec915c",
+ "eC": "#913960",
+ "mIRC Script": "#926059",
+ "mcfunction": "#E22837",
+ "nesC": "#94B0C7",
+ "ooc": "#b0b77e",
+ "q": "#0040cd",
+ "sed": "#64b970",
+ "wdl": "#42f1f4",
+ "wisp": "#7582D1",
+ "xBase": "#403a40",
+}
+
+function getLabel(isZh,key){
+ if(isZh){
+ return zhCN[key]
+ }else{
+ return esUN[key]
+ }
+}
+
+var zhCN={
+ "search":"搜索",
+ "search_repo":"项目",
+ "search_dataset":"数据集",
+ "search_issue":"任务",
+ "search_pr":"合并请求",
+ "search_user":"用户",
+ "search_org":"组织",
+ "search_finded":"找到",
+ "search_matched":"最佳匹配",
+ "search_matched_download":"下载次数",
+ "search_lasted_update":"最后更新于",
+ "search_letter_asc":"字母顺序排序",
+ "search_letter_desc":"字母逆序排序",
+ "search_lasted_create":"最近创建",
+ "search_early_create":"最早创建",
+ "search_add_by":"加入于",
+ "search_lasted":"最近更新",
+ "search_open":"开启中",
+ "search_closed":"已关闭",
+ "search_watched":"关注数",
+ "search_star":"点赞数",
+ "search_fork":"Fork数",
+ "search_input_large_0":"请输入大于0的数值。",
+ "search_input_maxed":"不能超出总页数。",
+ "search_input_total":"共",
+ "search_srtip":"条",
+ "search_home_page":"首页",
+ "search_last_page":"末页",
+ "search_go_to":"前往",
+ "search_go_page":"页",
+ "find_title":"“{keyword}”相关{tablename}约为{total}个",
+ "search_empty":"请输入任意关键字开始搜索。"
+ }
+
+ var esUN={
+ "search":"Search",
+ "search_repo":"Repository",
+ "search_dataset":"DataSet",
+ "search_issue":"Issue",
+ "search_pr":"Pull Request",
+ "search_user":"User",
+ "search_org":"Organization",
+ "search_finded":"Find",
+ "search_matched":"Best Match",
+ "search_matched_download":"Most downloads",
+ "search_lasted_update":"Updated ",
+ "search_letter_asc":"Alphabetically",
+ "search_letter_desc":"Reverse alphabetically",
+ "search_lasted_create":"Recently created",
+ "search_early_create":"First created",
+ "search_add_by":"Joined on",
+ "search_lasted":"Recently updated",
+ "search_open":"Open",
+ "search_closed":"Closed",
+ "search_watched":"Watches",
+ "search_star":"Stars",
+ "search_fork":"Forks",
+ "search_input_large_0":"Please enter a value greater than 0.",
+ "search_input_maxed":"Cannot exceed total pages.",
+ "search_input_total":"Total",
+ "search_srtip":"",
+ "search_home_page":"First",
+ "search_last_page":"Last",
+ "search_go_to":"Go",
+ "search_go_page":"Page",
+ "find_title":" {total} \"{keyword}\" related {tablename}",
+ "search_empty":"Please enter any keyword to start the search."
+ }
+ initDiv(false);
+ document.onreadystatechange = function() {
+ if (document.readyState === "complete") {
+ var tmpSearchLabel = sessionStorage.getItem("searchLabel");
+ console.log("tmpSearchLabel=" + tmpSearchLabel);
+ if(tmpSearchLabel){
+ console.log("search label....");
+ sessionStorage.removeItem("searchLabel");
+ doSearchLabel(sessionStorage.getItem("tableName"),sessionStorage.getItem("keyword"),sessionStorage.getItem("sortBy"),sessionStorage.getItem("ascending"));
+ }else{
+ console.log("normal search....");
+ search();
+ }
+ }
+ }
+
+
diff --git a/public/self/dataset_preview.js b/public/self/dataset_preview.js
index 3c9ded0aa..e6b79dd7d 100644
--- a/public/self/dataset_preview.js
+++ b/public/self/dataset_preview.js
@@ -620,10 +620,10 @@ function showfilelist(){
for (var i=0;i 70){
var tmpIndex = labeltastresult[i].pic_image_field.indexOf("/",70);
- console.log(tmpIndex)
+ //console.log(tmpIndex)
if(tmpIndex != -1){
fname = labeltastresult[i].pic_image_field.substring(tmpIndex + 1);
fname = fname.substring(fname.indexOf('/')+1);
@@ -679,7 +679,7 @@ function breadFiles(){
fname_full_path = tableData[fileindex].pic_image_field.substring(tmp_index + 1);
}
var fname_path = fname_full_path.split('/')
- console.log(fname_path)
+ //console.log(fname_path)
// var filename_text = tableData[fileindex].pic_image_field.substring(tableData[fileindex].pic_image_field.lastIndexOf('/')+1)
var html_breadFile = ''
// var source_name = filename_title+'.zip'
diff --git a/routers/init.go b/routers/init.go
index 8b93b64d8..eab513c78 100755
--- a/routers/init.go
+++ b/routers/init.go
@@ -71,6 +71,8 @@ func NewServices() {
log.Info("decompression.NewContext() succeed.")
labelmsg.Init()
log.Info("labelmsg.Init() succeed.")
+ InitESClient()
+ log.Info("ES Client succeed.")
}
// In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology
diff --git a/routers/routes/routes.go b/routers/routes/routes.go
index b15941dfc..4cffcd10b 100755
--- a/routers/routes/routes.go
+++ b/routers/routes/routes.go
@@ -323,6 +323,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/action/notification", routers.ActionNotification)
m.Get("/recommend/org", routers.RecommendOrgFromPromote)
m.Get("/recommend/repo", routers.RecommendRepoFromPromote)
+ m.Post("/all/search/", routers.Search)
+ m.Get("/all/search/", routers.EmptySearch)
+ m.Get("/all/dosearch/", routers.SearchApi)
m.Get("/home/term", routers.HomeTerm)
m.Group("/explore", func() {
m.Get("", func(ctx *context.Context) {
diff --git a/routers/search.go b/routers/search.go
new file mode 100644
index 000000000..bc1bc5fac
--- /dev/null
+++ b/routers/search.go
@@ -0,0 +1,1190 @@
+package routers
+
+import (
+ "encoding/json"
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/timeutil"
+ "github.com/olivere/elastic/v7"
+)
+
+type SearchRes struct {
+ Total int64
+ Result []map[string]interface{}
+ PrivateTotal int64
+}
+
+var client *elastic.Client
+
+func InitESClient() {
+ ESSearchUrl := setting.ESSearchURL
+ var err error
+ client, err = elastic.NewClient(elastic.SetSniff(false), elastic.SetURL(ESSearchUrl))
+ if err != nil {
+ log.Info("es init error.")
+ //panic(err)
+ }
+}
+
+func EmptySearch(ctx *context.Context) {
+ log.Info("search template.")
+ ctx.Data["Keyword"] = ""
+ ctx.HTML(200, "explore/search_new")
+}
+
+func Search(ctx *context.Context) {
+ log.Info("search template.")
+ keyword := strings.Trim(ctx.Query("q"), " ")
+ ctx.Data["Keyword"] = keyword
+ ctx.Data["SortType"] = "newest"
+ ctx.HTML(200, "explore/search_new")
+}
+
+func SearchApi(ctx *context.Context) {
+ TableName := ctx.Query("TableName")
+ Key := ctx.Query("Key")
+ Page := ctx.QueryInt("Page")
+ PageSize := ctx.QueryInt("PageSize")
+ OnlyReturnNum := ctx.QueryBool("OnlyReturnNum")
+ OnlySearchLabel := ctx.QueryBool("OnlySearchLabel")
+
+ if Page <= 0 {
+ Page = 1
+ }
+ if PageSize <= 0 || PageSize > 200 {
+ PageSize = setting.UI.IssuePagingNum
+ }
+ if Key != "" && !OnlyReturnNum {
+ go models.SaveSearchKeywordToDb(Key)
+ }
+ if TableName == "repository" {
+ if OnlySearchLabel {
+ searchRepoByLabel(ctx, Key, Page, PageSize)
+ } else {
+ searchRepo(ctx, "repository-es-index", Key, Page, PageSize, OnlyReturnNum)
+ }
+ return
+ } else if TableName == "issue" {
+ searchIssueOrPr(ctx, "issue-es-index", Key, Page, PageSize, OnlyReturnNum, "f")
+ return
+ } else if TableName == "user" {
+ searchUserOrOrg(ctx, "user-es-index", Key, Page, PageSize, true, OnlyReturnNum)
+ return
+ } else if TableName == "org" {
+ searchUserOrOrg(ctx, "user-es-index", Key, Page, PageSize, false, OnlyReturnNum)
+ return
+ } else if TableName == "dataset" {
+ searchDataSet(ctx, "dataset-es-index", Key, Page, PageSize, OnlyReturnNum)
+ return
+ } else if TableName == "pr" {
+ searchIssueOrPr(ctx, "issue-es-index", Key, Page, PageSize, OnlyReturnNum, "t")
+ //searchPR(ctx, "issue-es-index", Key, Page, PageSize, OnlyReturnNum)
+ return
+ }
+}
+
+func searchRepoByLabel(ctx *context.Context, Key string, Page int, PageSize int) {
+ /*
+ 项目, ES名称: repository-es-index
+ 搜索:
+ name character varying(255) , 项目名称
+ description text, 项目描述
+ topics json, 标签
+ 排序:
+ updated_unix
+ num_watches,
+ num_stars,
+ num_forks,
+ */
+ SortBy := ctx.Query("SortBy")
+ PrivateTotal := ctx.QueryInt("PrivateTotal")
+ WebTotal := ctx.QueryInt("WebTotal")
+ ascending := ctx.QueryBool("Ascending")
+ language := ctx.Query("language")
+ if language == "" {
+ language = "zh-CN"
+ }
+ from := (Page - 1) * PageSize
+ resultObj := &SearchRes{}
+ log.Info("WebTotal=" + fmt.Sprint(WebTotal))
+ log.Info("PrivateTotal=" + fmt.Sprint(PrivateTotal))
+ resultObj.Result = make([]map[string]interface{}, 0)
+ if from == 0 {
+ WebTotal = 0
+ }
+ if ctx.User != nil && (from < PrivateTotal || from == 0) {
+ orderBy := models.SearchOrderByRecentUpdated
+ switch SortBy {
+ case "updated_unix.keyword":
+ orderBy = models.SearchOrderByRecentUpdated
+ case "num_stars":
+ orderBy = models.SearchOrderByStarsReverse
+ case "num_forks":
+ orderBy = models.SearchOrderByForksReverse
+ case "num_watches":
+ orderBy = models.SearchOrderByWatches
+ }
+ log.Info("actor is null?:" + fmt.Sprint(ctx.User == nil))
+ repos, count, err := models.SearchRepository(&models.SearchRepoOptions{
+ ListOptions: models.ListOptions{
+ Page: Page,
+ PageSize: PageSize,
+ },
+ Actor: ctx.User,
+ OrderBy: orderBy,
+ Private: true,
+ OnlyPrivate: true,
+ TopicOnly: true,
+ TopicName: Key,
+ IncludeDescription: setting.UI.SearchRepoDescription,
+ })
+ if err != nil {
+ ctx.JSON(200, "")
+ return
+ }
+ resultObj.PrivateTotal = count
+ if repos.Len() > 0 {
+ log.Info("Query private repo number is:" + fmt.Sprint(repos.Len()))
+ makePrivateRepo(repos, resultObj, Key, language)
+ } else {
+ log.Info("not found private repo,keyword=" + Key)
+ }
+ if repos.Len() >= PageSize {
+ if WebTotal > 0 {
+ resultObj.Total = int64(WebTotal)
+ ctx.JSON(200, resultObj)
+ return
+ }
+ }
+ } else {
+ if ctx.User == nil {
+ resultObj.PrivateTotal = 0
+ } else {
+ resultObj.PrivateTotal = int64(PrivateTotal)
+ }
+ }
+
+ from = from - PrivateTotal
+ if from < 0 {
+ from = 0
+ }
+ Size := PageSize - len(resultObj.Result)
+
+ log.Info("query searchRepoByLabel start")
+ if Key != "" {
+ boolQ := elastic.NewBoolQuery()
+ topicsQuery := elastic.NewMatchQuery("topics", Key)
+ boolQ.Should(topicsQuery)
+
+ res, err := client.Search("repository-es-index").Query(boolQ).SortBy(getSort(SortBy, ascending)).From(from).Size(Size).Highlight(queryHighlight("topics")).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ esresult := makeRepoResult(res, "", false, language)
+ resultObj.Total = resultObj.PrivateTotal + esresult.Total
+ resultObj.Result = append(resultObj.Result, esresult.Result...)
+ ctx.JSON(200, resultObj)
+ } else {
+ log.Info("query es error," + err.Error())
+ ctx.JSON(200, "")
+ }
+ } else {
+ ctx.JSON(200, "")
+ }
+}
+
+func getSort(SortBy string, ascending bool) elastic.Sorter {
+ var sort elastic.Sorter
+ sort = elastic.NewScoreSort()
+ if SortBy != "" {
+ if SortBy == "default" {
+ return sort
+ }
+ return elastic.NewFieldSort(SortBy).Order(ascending)
+ }
+ return sort
+}
+
+func searchRepo(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool) {
+ /*
+ 项目, ES名称: repository-es-index
+ 搜索:
+ name character varying(255) , 项目名称
+ description text, 项目描述
+ topics json, 标签
+ 排序:
+ updated_unix
+ num_watches,
+ num_stars,
+ num_forks,
+ */
+
+ SortBy := ctx.Query("SortBy")
+ PrivateTotal := ctx.QueryInt("PrivateTotal")
+ WebTotal := ctx.QueryInt("WebTotal")
+ ascending := ctx.QueryBool("Ascending")
+ from := (Page - 1) * PageSize
+ resultObj := &SearchRes{}
+ log.Info("WebTotal=" + fmt.Sprint(WebTotal))
+ log.Info("PrivateTotal=" + fmt.Sprint(PrivateTotal))
+ resultObj.Result = make([]map[string]interface{}, 0)
+ if from == 0 {
+ WebTotal = 0
+ }
+ language := ctx.Query("language")
+ if language == "" {
+ language = "zh-CN"
+ }
+ if ctx.User != nil && (from < PrivateTotal || from == 0) {
+ orderBy := models.SearchOrderByRecentUpdated
+ switch SortBy {
+ case "updated_unix.keyword":
+ orderBy = models.SearchOrderByRecentUpdated
+ case "num_stars":
+ orderBy = models.SearchOrderByStarsReverse
+ case "num_forks":
+ orderBy = models.SearchOrderByForksReverse
+ case "num_watches":
+ orderBy = models.SearchOrderByWatches
+ }
+ log.Info("actor is null?:" + fmt.Sprint(ctx.User == nil))
+ repos, count, err := models.SearchRepository(&models.SearchRepoOptions{
+ ListOptions: models.ListOptions{
+ Page: Page,
+ PageSize: PageSize,
+ },
+ Actor: ctx.User,
+ OrderBy: orderBy,
+ Private: true,
+ OnlyPrivate: true,
+ Keyword: Key,
+ IncludeDescription: setting.UI.SearchRepoDescription,
+ OnlySearchPrivate: true,
+ })
+ if err != nil {
+ ctx.JSON(200, "")
+ return
+ }
+ resultObj.PrivateTotal = count
+ if repos.Len() > 0 {
+ log.Info("Query private repo number is:" + fmt.Sprint(repos.Len()))
+ makePrivateRepo(repos, resultObj, Key, language)
+ } else {
+ log.Info("not found private repo,keyword=" + Key)
+ }
+ if repos.Len() >= PageSize {
+ if WebTotal > 0 {
+ resultObj.Total = int64(WebTotal)
+ ctx.JSON(200, resultObj)
+ return
+ }
+ }
+ } else {
+ if ctx.User == nil {
+ resultObj.PrivateTotal = 0
+ } else {
+ resultObj.PrivateTotal = int64(PrivateTotal)
+ }
+ }
+
+ from = from - PrivateTotal
+ if from < 0 {
+ from = 0
+ }
+ Size := PageSize - len(resultObj.Result)
+
+ log.Info("query searchRepo start")
+ if Key != "" {
+ boolQ := elastic.NewBoolQuery()
+ nameQuery := elastic.NewMatchQuery("alias", Key).Boost(1024).QueryName("f_first")
+ descriptionQuery := elastic.NewMatchQuery("description", Key).Boost(1.5).QueryName("f_second")
+ topicsQuery := elastic.NewMatchQuery("topics", Key).Boost(1).QueryName("f_third")
+ boolQ.Should(nameQuery, descriptionQuery, topicsQuery)
+
+ res, err := client.Search(TableName).Query(boolQ).SortBy(getSort(SortBy, ascending)).From(from).Size(Size).Highlight(queryHighlight("alias", "description", "topics")).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ esresult := makeRepoResult(res, Key, OnlyReturnNum, language)
+ resultObj.Total = resultObj.PrivateTotal + esresult.Total
+ isNeedSort := false
+ if len(resultObj.Result) > 0 {
+ isNeedSort = true
+ }
+ resultObj.Result = append(resultObj.Result, esresult.Result...)
+ if isNeedSort {
+ sortRepo(resultObj.Result, SortBy, ascending)
+ }
+ ctx.JSON(200, resultObj)
+ } else {
+ log.Info("query es error," + err.Error())
+ ctx.JSON(200, "")
+ }
+ } else {
+ log.Info("query all content.")
+ //搜索的属性要指定{"timestamp":{"unmapped_type":"date"}}
+ res, err := client.Search(TableName).SortBy(getSort(SortBy, ascending)).From(from).Size(Size).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ esresult := makeRepoResult(res, "", OnlyReturnNum, language)
+ resultObj.Total = resultObj.PrivateTotal + esresult.Total
+ resultObj.Result = append(resultObj.Result, esresult.Result...)
+ ctx.JSON(200, resultObj)
+ } else {
+ log.Info("query es error," + err.Error())
+ ctx.JSON(200, "")
+ }
+ }
+}
+
+func sortRepo(Result []map[string]interface{}, SortBy string, ascending bool) {
+ orderBy := ""
+ switch SortBy {
+ case "updated_unix.keyword":
+ orderBy = "updated_unix"
+ case "num_stars":
+ orderBy = "num_stars"
+ case "num_forks":
+ orderBy = "num_forks"
+ case "num_watches":
+ orderBy = "num_watches"
+ }
+ sort.Slice(Result, func(i, j int) bool {
+ return getInt(Result[i][orderBy], orderBy) > getInt(Result[j][orderBy], orderBy)
+ })
+}
+
+func getInt(tmp interface{}, orderBy string) int64 {
+ timeInt, err := strconv.ParseInt(fmt.Sprint(tmp), 10, 64)
+ if err == nil {
+ return timeInt
+ } else {
+ log.Info("convert " + orderBy + " error type=" + fmt.Sprint(tmp))
+ }
+ return -1
+}
+
+func makePrivateRepo(repos models.RepositoryList, res *SearchRes, keyword string, language string) {
+
+ for _, repo := range repos {
+ record := make(map[string]interface{})
+ record["id"] = repo.ID
+ record["name"] = makeHighLight(keyword, repo.Name)
+ record["real_name"] = repo.Name
+ record["owner_name"] = repo.OwnerName
+ record["description"] = truncLongText(makeHighLight(keyword, repo.Description), true)
+
+ hightTopics := make([]string, 0)
+ if len(repo.Topics) > 0 {
+ for _, t := range repo.Topics {
+ hightTopics = append(hightTopics, makeHighLight(keyword, t))
+ }
+ }
+ record["hightTopics"] = hightTopics
+
+ record["num_watches"] = repo.NumWatches
+ record["num_stars"] = repo.NumStars
+ record["num_forks"] = repo.NumForks
+ record["alias"] = truncLongText(makeHighLight(keyword, repo.Alias), true)
+ record["lower_alias"] = repo.LowerAlias
+ record["topics"] = repo.Topics
+ record["avatar"] = repo.RelAvatarLink()
+ if len(repo.RelAvatarLink()) == 0 {
+ record["avatar"] = setting.RepositoryAvatarFallbackImage
+ }
+ record["updated_unix"] = repo.UpdatedUnix
+ record["updated_html"] = timeutil.TimeSinceUnix(repo.UpdatedUnix, language)
+ lang, err := repo.GetTopLanguageStats(1)
+ if err == nil && len(lang) > 0 {
+ record["lang"] = lang[0].Language
+ } else {
+ record["lang"] = ""
+ }
+ record["is_private"] = true
+ res.Result = append(res.Result, record)
+ }
+}
+
+func makeHighLight(keyword string, dest string) string {
+
+ dest = replaceIngoreUpperOrLower(dest, strings.ToLower(dest), strings.ToLower(keyword))
+
+ return dest
+}
+
+func replaceIngoreUpperOrLower(dest string, destLower string, keywordLower string) string {
+ re := ""
+ last := 0
+ lenDestLower := len(destLower)
+ lenkeywordLower := len(keywordLower)
+ for i := 0; i < lenDestLower; i++ {
+ if destLower[i] == keywordLower[0] {
+ isFind := true
+ for j := 1; j < lenkeywordLower; j++ {
+ if (i+j) < lenDestLower && keywordLower[j] != destLower[i+j] {
+ isFind = false
+ break
+ }
+ }
+ if isFind && (i+lenkeywordLower) <= lenDestLower {
+ re += dest[last:i] + "\u003cfont color='red'\u003e" + dest[i:(i+lenkeywordLower)] + "\u003c/font\u003e"
+ i = i + lenkeywordLower
+ last = i
+ }
+ }
+ }
+ if last < lenDestLower {
+ re += dest[last:lenDestLower]
+ }
+ return re
+}
+
+func makeRepoResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool, language string) *SearchRes {
+ total := sRes.Hits.TotalHits.Value
+ result := make([]map[string]interface{}, 0)
+ if !OnlyReturnNum {
+ for i, hit := range sRes.Hits.Hits {
+ log.Info("this is repo query " + fmt.Sprint(i) + " result.")
+ recordSource := make(map[string]interface{})
+ source, err := hit.Source.MarshalJSON()
+
+ if err == nil {
+ err = json.Unmarshal(source, &recordSource)
+ if err == nil {
+ record := make(map[string]interface{})
+ record["id"] = hit.Id
+ record["alias"] = getLabelValue("alias", recordSource, hit.Highlight)
+ record["real_name"] = recordSource["name"]
+ record["owner_name"] = recordSource["owner_name"]
+ if recordSource["description"] != nil {
+ desc := getLabelValue("description", recordSource, hit.Highlight)
+ record["description"] = dealLongText(desc, Key, hit.MatchedQueries)
+ } else {
+ record["description"] = ""
+ }
+
+ record["hightTopics"] = jsonStrToArray(getLabelValue("topics", recordSource, hit.Highlight))
+ record["num_watches"] = recordSource["num_watches"]
+ record["num_stars"] = recordSource["num_stars"]
+ record["num_forks"] = recordSource["num_forks"]
+ record["lower_alias"] = recordSource["lower_alias"]
+ if recordSource["topics"] != nil {
+ topicsStr := recordSource["topics"].(string)
+ log.Info("topicsStr=" + topicsStr)
+ if topicsStr != "null" {
+ record["topics"] = jsonStrToArray(topicsStr)
+ }
+ }
+ if recordSource["avatar"] != nil {
+ avatarstr := recordSource["avatar"].(string)
+ if len(avatarstr) == 0 {
+ record["avatar"] = setting.RepositoryAvatarFallbackImage
+ } else {
+ record["avatar"] = setting.AppSubURL + "/repo-avatars/" + avatarstr
+ }
+ }
+ record["updated_unix"] = recordSource["updated_unix"]
+ setUpdateHtml(record, recordSource["updated_unix"].(string), language)
+
+ record["lang"] = recordSource["lang"]
+ record["is_private"] = false
+ result = append(result, record)
+ } else {
+ log.Info("deal repo source error," + err.Error())
+ }
+ } else {
+ log.Info("deal repo source error," + err.Error())
+ }
+ }
+ }
+ returnObj := &SearchRes{
+ Total: total,
+ Result: result,
+ }
+
+ return returnObj
+}
+
+func setUpdateHtml(record map[string]interface{}, updated_unix string, language string) {
+ timeInt, err := strconv.ParseInt(updated_unix, 10, 64)
+ if err == nil {
+ record["updated_html"] = timeutil.TimeSinceUnix(timeutil.TimeStamp(timeInt), language)
+ }
+}
+
+func jsonStrToArray(str string) []string {
+ b := []byte(str)
+ strs := make([]string, 0)
+ err := json.Unmarshal(b, &strs)
+ if err != nil {
+ log.Info("convert str arrar error, str=" + str)
+ }
+ return strs
+}
+
+func dealLongText(text string, Key string, MatchedQueries []string) string {
+ var isNeedToDealText bool
+ isNeedToDealText = false
+ if len(MatchedQueries) > 0 && Key != "" {
+ if MatchedQueries[0] == "f_second" || MatchedQueries[0] == "f_third" {
+ isNeedToDealText = true
+ }
+ }
+ return truncLongText(text, isNeedToDealText)
+}
+
+func truncLongText(text string, isNeedToDealText bool) string {
+ startStr := "color="
+ textRune := []rune(text)
+ stringlen := len(textRune)
+ if isNeedToDealText && stringlen > 200 {
+ index := findFont(textRune, []rune(startStr))
+ if index > 0 {
+ start := index - 50
+ if start < 0 {
+ start = 0
+ }
+ end := index + 150
+ if end >= stringlen {
+ end = stringlen
+ }
+ return trimFontHtml(textRune[start:end]) + "..."
+ } else {
+ return trimFontHtml(textRune[0:200]) + "..."
+ }
+ } else {
+ if stringlen > 200 {
+ return trimFontHtml(textRune[0:200]) + "..."
+ } else {
+ return text
+ }
+ }
+}
+
+func trimFontHtml(text []rune) string {
+ startRune := rune('<')
+ endRune := rune('>')
+ count := 0
+ for i := 0; i < len(text); i++ {
+ if text[i] == startRune { //start <
+ re := false
+ j := i + 1
+ for ; j < len(text); j++ {
+ if text[j] == endRune {
+ re = true
+ break
+ }
+ }
+ if re { //found >
+ i = j
+ count++
+ } else {
+ if count%2 == 1 {
+ return string(text[0:i]) + ""
+ } else {
+ return string(text[0:i])
+ }
+
+ }
+ }
+ }
+ return string(text)
+}
+
+func trimHrefHtml(result string) string {
+ result = strings.Replace(result, "", "", -1)
+ result = strings.Replace(result, "\n", "", -1)
+ var index int
+ for {
+ index = findSubstr(result, 0, "")
+ if sIndex != -1 {
+ result = result[0:index] + result[sIndex+1:]
+ } else {
+ result = result[0:index] + result[index+2:]
+ }
+ } else {
+ break
+ }
+ }
+ return result
+}
+
+func findFont(text []rune, childText []rune) int {
+ for i := 0; i < len(text); i++ {
+ if text[i] == childText[0] {
+ re := true
+ for j, k := range childText {
+ if k != text[i+j] {
+ re = false
+ break
+ }
+ }
+ if re {
+ return i
+ }
+ }
+ }
+ return -1
+}
+
+func findSubstr(text string, startindex int, childText string) int {
+ for i := startindex; i < len(text); i++ {
+ if text[i] == childText[0] {
+ re := true
+ for k := range childText {
+ if childText[k] != text[i+k] {
+ re = false
+ break
+ }
+ }
+ if re {
+ return i
+ }
+ }
+ }
+ return -1
+}
+
+func searchUserOrOrg(ctx *context.Context, TableName string, Key string, Page int, PageSize int, IsQueryUser bool, OnlyReturnNum bool) {
+ /*
+ 用户或者组织 ES名称: user-es-index
+ 搜索:
+ name , 名称
+ full_name 全名
+ description 描述或者简介
+ 排序:
+ created_unix
+ 名称字母序
+ */
+ SortBy := ctx.Query("SortBy")
+ ascending := ctx.QueryBool("Ascending")
+ boolQ := elastic.NewBoolQuery()
+
+ typeValue := 1
+ if IsQueryUser {
+ typeValue = 0
+ }
+ UserOrOrgQuery := elastic.NewTermQuery("type", typeValue)
+ if Key != "" {
+ boolKeyQ := elastic.NewBoolQuery()
+ log.Info("user or org Key=" + Key)
+ nameQuery := elastic.NewMatchQuery("name", Key).Boost(2).QueryName("f_first")
+ full_nameQuery := elastic.NewMatchQuery("full_name", Key).Boost(1.5).QueryName("f_second")
+ descriptionQuery := elastic.NewMatchQuery("description", Key).Boost(1).QueryName("f_third")
+ boolKeyQ.Should(nameQuery, full_nameQuery, descriptionQuery)
+ boolQ.Must(UserOrOrgQuery, boolKeyQ)
+ } else {
+ boolQ.Must(UserOrOrgQuery)
+ }
+
+ res, err := client.Search(TableName).Query(boolQ).SortBy(getSort(SortBy, ascending)).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("name", "full_name", "description")).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ result := makeUserOrOrgResult(res, Key, ctx, OnlyReturnNum)
+ ctx.JSON(200, result)
+ } else {
+ log.Info("query es error," + err.Error())
+ ctx.JSON(200, "")
+ }
+}
+
+func getLabelValue(key string, recordSource map[string]interface{}, searchHighliht elastic.SearchHitHighlight) string {
+ if value, ok := searchHighliht[key]; !ok {
+ if recordSource[key] != nil {
+ return recordSource[key].(string)
+ } else {
+ return ""
+ }
+ } else {
+ return value[0]
+ }
+}
+
+func makeUserOrOrgResult(sRes *elastic.SearchResult, Key string, ctx *context.Context, OnlyReturnNum bool) *SearchRes {
+ total := sRes.Hits.TotalHits.Value
+ result := make([]map[string]interface{}, 0)
+ if !OnlyReturnNum {
+ for i, hit := range sRes.Hits.Hits {
+ log.Info("this is user query " + fmt.Sprint(i) + " result.")
+ recordSource := make(map[string]interface{})
+ source, err := hit.Source.MarshalJSON()
+
+ if err == nil {
+ err = json.Unmarshal(source, &recordSource)
+ if err == nil {
+ record := make(map[string]interface{})
+ record["id"] = hit.Id
+ record["name"] = getLabelValue("name", recordSource, hit.Highlight)
+ record["real_name"] = recordSource["name"]
+ record["full_name"] = getLabelValue("full_name", recordSource, hit.Highlight)
+ if recordSource["description"] != nil {
+ desc := getLabelValue("description", recordSource, hit.Highlight)
+ record["description"] = dealLongText(desc, Key, hit.MatchedQueries)
+ } else {
+ record["description"] = ""
+ }
+ if ctx.User != nil {
+ record["email"] = recordSource["email"]
+ } else {
+ record["email"] = ""
+ }
+
+ record["location"] = recordSource["location"]
+ record["website"] = recordSource["website"]
+ record["num_repos"] = recordSource["num_repos"]
+ record["num_teams"] = recordSource["num_teams"]
+ record["num_members"] = recordSource["num_members"]
+
+ record["avatar"] = strings.TrimRight(setting.AppSubURL, "/") + "/user/avatar/" + recordSource["name"].(string) + "/" + strconv.Itoa(-1)
+ record["updated_unix"] = recordSource["updated_unix"]
+ record["created_unix"] = recordSource["created_unix"]
+ record["add_time"] = getAddTime(recordSource["created_unix"].(string))
+ result = append(result, record)
+ } else {
+ log.Info("deal user source error," + err.Error())
+ }
+ } else {
+ log.Info("deal user source error," + err.Error())
+ }
+ }
+ }
+ returnObj := &SearchRes{
+ Total: total,
+ Result: result,
+ }
+ return returnObj
+}
+
+func getAddTime(time string) string {
+ timeInt, err := strconv.ParseInt(time, 10, 64)
+ if err == nil {
+ t := timeutil.TimeStamp(timeInt)
+ return t.FormatShort()
+ }
+ return ""
+}
+
+func searchDataSet(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool) {
+ /*
+ 数据集,ES名称:dataset-es-index
+ 搜索:
+ title , 名称
+ description 描述
+ category 标签
+ file_name 数据集文件名称
+ 排序:
+ download_times
+
+ */
+ log.Info("query searchdataset start")
+ SortBy := ctx.Query("SortBy")
+ ascending := ctx.QueryBool("Ascending")
+ PrivateTotal := ctx.QueryInt("PrivateTotal")
+ WebTotal := ctx.QueryInt("WebTotal")
+ language := ctx.Query("language")
+ if language == "" {
+ language = "zh-CN"
+ }
+ from := (Page - 1) * PageSize
+ if from == 0 {
+ WebTotal = 0
+ }
+ resultObj := &SearchRes{}
+ log.Info("WebTotal=" + fmt.Sprint(WebTotal))
+ log.Info("PrivateTotal=" + fmt.Sprint(PrivateTotal))
+ resultObj.Result = make([]map[string]interface{}, 0)
+
+ if ctx.User != nil && (from < PrivateTotal || from == 0) {
+
+ log.Info("actor is null?:" + fmt.Sprint(ctx.User == nil))
+ datasets, count, err := models.SearchDatasetBySQL(Page, PageSize, Key, ctx.User.ID)
+ if err != nil {
+ ctx.JSON(200, "")
+ return
+ }
+ resultObj.PrivateTotal = count
+ datasetSize := len(datasets)
+ if datasetSize > 0 {
+ log.Info("Query private dataset number is:" + fmt.Sprint(datasetSize) + " count=" + fmt.Sprint(count))
+ makePrivateDataSet(datasets, resultObj, Key, language)
+ } else {
+ log.Info("not found private dataset, keyword=" + Key)
+ }
+ if datasetSize >= PageSize {
+ if WebTotal > 0 { //next page, not first query.
+ resultObj.Total = int64(WebTotal)
+ ctx.JSON(200, resultObj)
+ return
+ }
+ }
+ } else {
+ resultObj.PrivateTotal = int64(PrivateTotal)
+ }
+
+ from = from - PrivateTotal
+ if from < 0 {
+ from = 0
+ }
+ Size := PageSize - len(resultObj.Result)
+
+ boolQ := elastic.NewBoolQuery()
+ if Key != "" {
+ nameQuery := elastic.NewMatchQuery("title", Key).Boost(2).QueryName("f_first")
+ descQuery := elastic.NewMatchQuery("description", Key).Boost(1.5).QueryName("f_second")
+ fileNameQuery := elastic.NewMatchQuery("file_name", Key).Boost(1).QueryName("f_third")
+ categoryQuery := elastic.NewMatchQuery("category", Key).Boost(1).QueryName("f_fourth")
+ boolQ.Should(nameQuery, descQuery, categoryQuery, fileNameQuery)
+ res, err := client.Search(TableName).Query(boolQ).SortBy(getSort(SortBy, ascending)).From(from).Size(Size).Highlight(queryHighlight("title", "description", "file_name", "category")).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ esresult := makeDatasetResult(res, Key, OnlyReturnNum, language)
+ resultObj.Total = resultObj.PrivateTotal + esresult.Total
+ log.Info("query dataset es count=" + fmt.Sprint(esresult.Total) + " total=" + fmt.Sprint(resultObj.Total))
+ resultObj.Result = append(resultObj.Result, esresult.Result...)
+ ctx.JSON(200, resultObj)
+ } else {
+ log.Info("query es error," + err.Error())
+ }
+ } else {
+ log.Info("query all datasets.")
+ //搜索的属性要指定{"timestamp":{"unmapped_type":"date"}}
+ res, err := client.Search(TableName).SortBy(getSort(SortBy, ascending)).From(from).Size(Size).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ esresult := makeDatasetResult(res, "", OnlyReturnNum, language)
+ resultObj.Total = resultObj.PrivateTotal + esresult.Total
+ log.Info("query dataset es count=" + fmt.Sprint(esresult.Total) + " total=" + fmt.Sprint(resultObj.Total))
+ resultObj.Result = append(resultObj.Result, esresult.Result...)
+ ctx.JSON(200, resultObj)
+ } else {
+ log.Info("query es error," + err.Error())
+ ctx.JSON(200, "")
+ }
+ }
+
+}
+
+func makePrivateDataSet(datasets []*models.Dataset, res *SearchRes, Key string, language string) {
+ for _, dataset := range datasets {
+ record := make(map[string]interface{})
+
+ record["id"] = dataset.ID
+ userId := dataset.UserID
+
+ user, errUser := models.GetUserByID(userId)
+ if errUser == nil {
+ record["owerName"] = user.GetDisplayName()
+ record["avatar"] = user.RelAvatarLink()
+ }
+
+ repo, errRepo := models.GetRepositoryByID(dataset.RepoID)
+ if errRepo == nil {
+ log.Info("repo_url=" + repo.FullName())
+ record["repoUrl"] = repo.FullName()
+ record["avatar"] = repo.RelAvatarLink()
+ } else {
+ log.Info("repo err=" + errRepo.Error())
+ }
+
+ record["title"] = makeHighLight(Key, dataset.Title)
+ record["description"] = truncLongText(makeHighLight(Key, dataset.Description), true)
+
+ record["category"] = dataset.Category
+ record["task"] = dataset.Task
+ record["download_times"] = dataset.DownloadTimes
+ record["created_unix"] = dataset.CreatedUnix
+ record["updated_unix"] = repo.UpdatedUnix
+ record["updated_html"] = timeutil.TimeSinceUnix(repo.UpdatedUnix, language)
+
+ res.Result = append(res.Result, record)
+ }
+}
+
+func makeDatasetResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool, language string) *SearchRes {
+ total := sRes.Hits.TotalHits.Value
+ result := make([]map[string]interface{}, 0)
+ if !OnlyReturnNum {
+ for i, hit := range sRes.Hits.Hits {
+ log.Info("this is dataset query " + fmt.Sprint(i) + " result.")
+ recordSource := make(map[string]interface{})
+ source, err := hit.Source.MarshalJSON()
+
+ if err == nil {
+ err = json.Unmarshal(source, &recordSource)
+ if err == nil {
+ record := make(map[string]interface{})
+ record["id"] = hit.Id
+ userIdStr := recordSource["user_id"].(string)
+ userId, cerr := strconv.ParseInt(userIdStr, 10, 64)
+ if cerr == nil {
+ user, errUser := models.GetUserByID(userId)
+ if errUser == nil {
+ record["owerName"] = user.GetDisplayName()
+ record["avatar"] = user.RelAvatarLink()
+ }
+ }
+ setRepoInfo(recordSource, record)
+ record["title"] = getLabelValue("title", recordSource, hit.Highlight)
+ record["category"] = getLabelValue("category", recordSource, hit.Highlight)
+ if recordSource["description"] != nil {
+ desc := getLabelValue("description", recordSource, hit.Highlight)
+ record["description"] = dealLongText(desc, Key, hit.MatchedQueries)
+ } else {
+ record["description"] = ""
+ }
+ record["file_name"] = getDatasetFileName(getLabelValue("file_name", recordSource, hit.Highlight))
+ record["task"] = recordSource["task"]
+ record["download_times"] = recordSource["download_times"]
+ record["created_unix"] = recordSource["created_unix"]
+ setUpdateHtml(record, recordSource["updated_unix"].(string), language)
+ result = append(result, record)
+ } else {
+ log.Info("deal dataset source error," + err.Error())
+ }
+ } else {
+ log.Info("deal dataset source error," + err.Error())
+ }
+ }
+ }
+ returnObj := &SearchRes{
+ Total: total,
+ Result: result,
+ }
+
+ return returnObj
+}
+
+func getDatasetFileName(fileName string) string {
+ slices := strings.Split(fileName, "-#,#-")
+ fileName = strings.Join(slices, ", ")
+ return fileName
+}
+
+func searchIssueOrPr(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool, issueOrPr string) {
+
+ /*
+ 任务,合并请求 ES名称:issue-es-index
+ 搜索:
+ name character varying(255) , 标题
+ content text, 内容
+ comment text, 评论
+ 排序:
+ updated_unix
+ */
+ SortBy := ctx.Query("SortBy")
+ ascending := ctx.QueryBool("Ascending")
+ PrivateTotal := ctx.QueryInt("PrivateTotal")
+ WebTotal := ctx.QueryInt("WebTotal")
+ language := ctx.Query("language")
+ if language == "" {
+ language = "zh-CN"
+ }
+ from := (Page - 1) * PageSize
+ if from == 0 {
+ WebTotal = 0
+ }
+ resultObj := &SearchRes{}
+ log.Info("WebTotal=" + fmt.Sprint(WebTotal))
+ log.Info("PrivateTotal=" + fmt.Sprint(PrivateTotal))
+ resultObj.Result = make([]map[string]interface{}, 0)
+ isPull := false
+ if issueOrPr == "t" {
+ isPull = true
+ }
+
+ if ctx.User != nil && (from < PrivateTotal || from == 0) {
+
+ log.Info("actor is null?:" + fmt.Sprint(ctx.User == nil))
+ issues, count, err := models.SearchPrivateIssueOrPr(Page, PageSize, Key, isPull, ctx.User.ID)
+ if err != nil {
+ ctx.JSON(200, "")
+ return
+ }
+ resultObj.PrivateTotal = count
+ issuesSize := len(issues)
+ if issuesSize > 0 {
+ log.Info("Query private repo issue number is:" + fmt.Sprint(issuesSize) + " count=" + fmt.Sprint(count))
+ makePrivateIssueOrPr(issues, resultObj, Key, language)
+ } else {
+ log.Info("not found private repo issue,keyword=" + Key)
+ }
+ if issuesSize >= PageSize {
+ if WebTotal > 0 { //next page, not first query.
+ resultObj.Total = int64(WebTotal)
+ ctx.JSON(200, resultObj)
+ return
+ }
+ }
+ } else {
+ resultObj.PrivateTotal = int64(PrivateTotal)
+ }
+
+ from = from - PrivateTotal
+ if from < 0 {
+ from = 0
+ }
+ Size := PageSize - len(resultObj.Result)
+
+ boolQ := elastic.NewBoolQuery()
+ isIssueQuery := elastic.NewTermQuery("is_pull", issueOrPr)
+
+ if Key != "" {
+ boolKeyQ := elastic.NewBoolQuery()
+ log.Info("issue Key=" + Key)
+ nameQuery := elastic.NewMatchQuery("name", Key).Boost(2).QueryName("f_first")
+ contentQuery := elastic.NewMatchQuery("content", Key).Boost(1.5).QueryName("f_second")
+ commentQuery := elastic.NewMatchQuery("comment", Key).Boost(1).QueryName("f_third")
+ boolKeyQ.Should(nameQuery, contentQuery, commentQuery)
+ boolQ.Must(isIssueQuery, boolKeyQ)
+ } else {
+ boolQ.Must(isIssueQuery)
+ }
+
+ res, err := client.Search(TableName).Query(boolQ).SortBy(getSort(SortBy, ascending)).From(from).Size(Size).Highlight(queryHighlight("name", "content", "comment")).Do(ctx.Req.Context())
+ if err == nil {
+ searchJson, _ := json.Marshal(res)
+ log.Info("searchJson=" + string(searchJson))
+ esresult := makeIssueResult(res, Key, OnlyReturnNum, language)
+
+ resultObj.Total = resultObj.PrivateTotal + esresult.Total
+ log.Info("query issue es count=" + fmt.Sprint(esresult.Total) + " total=" + fmt.Sprint(resultObj.Total))
+ resultObj.Result = append(resultObj.Result, esresult.Result...)
+ ctx.JSON(200, resultObj)
+ } else {
+ log.Info("query es error," + err.Error())
+ }
+}
+
+func queryHighlight(names ...string) *elastic.Highlight {
+ re := elastic.NewHighlight()
+ for i := 0; i < len(names); i++ {
+ field := &elastic.HighlighterField{
+ Name: names[i],
+ }
+ re.Fields(field)
+ }
+ re.PreTags("")
+ re.PostTags("")
+ return re
+}
+
+func setRepoInfo(recordSource map[string]interface{}, record map[string]interface{}) {
+ repoIdstr := recordSource["repo_id"].(string)
+ repoId, cerr := strconv.ParseInt(repoIdstr, 10, 64)
+ if cerr == nil {
+ repo, errRepo := models.GetRepositoryByID(repoId)
+ if errRepo == nil {
+ log.Info("repo_url=" + repo.FullName())
+ record["repoUrl"] = repo.FullName()
+ record["avatar"] = repo.RelAvatarLink()
+ } else {
+ log.Info("repo err=" + errRepo.Error())
+ }
+ } else {
+ log.Info("parse int err=" + cerr.Error())
+ }
+}
+
+func makePrivateIssueOrPr(issues []*models.Issue, res *SearchRes, Key string, language string) {
+ for _, issue := range issues {
+ record := make(map[string]interface{})
+ record["id"] = issue.ID
+ record["repo_id"] = issue.RepoID
+
+ repo, errRepo := models.GetRepositoryByID(issue.RepoID)
+ if errRepo == nil {
+ log.Info("repo_url=" + repo.FullName())
+ record["repoUrl"] = repo.FullName()
+ record["avatar"] = repo.RelAvatarLink()
+ } else {
+ log.Info("repo err=" + errRepo.Error())
+ }
+ record["name"] = makeHighLight(Key, issue.Title)
+ record["content"] = truncLongText(makeHighLight(Key, issue.Content), true)
+
+ if issue.IsPull {
+ pr, err1 := issue.GetPullRequest()
+ if err1 == nil && pr != nil {
+ record["pr_id"] = pr.ID
+ }
+ }
+ record["index"] = issue.Index
+ record["num_comments"] = issue.NumComments
+ record["is_closed"] = issue.IsClosed
+ record["updated_unix"] = issue.UpdatedUnix
+ record["updated_html"] = timeutil.TimeSinceUnix(repo.UpdatedUnix, language)
+ res.Result = append(res.Result, record)
+ }
+}
+
+func makeIssueResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool, language string) *SearchRes {
+ total := sRes.Hits.TotalHits.Value
+ result := make([]map[string]interface{}, 0)
+ if !OnlyReturnNum {
+ for i, hit := range sRes.Hits.Hits {
+ log.Info("this is issue query " + fmt.Sprint(i) + " result.")
+ recordSource := make(map[string]interface{})
+ source, err := hit.Source.MarshalJSON()
+
+ if err == nil {
+ err = json.Unmarshal(source, &recordSource)
+ if err == nil {
+ record := make(map[string]interface{})
+ record["id"] = hit.Id
+ record["repo_id"] = recordSource["repo_id"]
+ log.Info("recordSource[\"repo_id\"]=" + fmt.Sprint(recordSource["repo_id"]))
+ setRepoInfo(recordSource, record)
+ record["name"] = getLabelValue("name", recordSource, hit.Highlight)
+ if recordSource["content"] != nil {
+ desc := getLabelValue("content", recordSource, hit.Highlight)
+ record["content"] = dealLongText(desc, Key, hit.MatchedQueries)
+ if _, ok := hit.Highlight["content"]; !ok {
+ if _, ok_comment := hit.Highlight["comment"]; ok_comment {
+ desc := getLabelValue("comment", recordSource, hit.Highlight)
+ record["content"] = trimHrefHtml(dealLongText(desc, Key, hit.MatchedQueries))
+ }
+ }
+ } else {
+ if recordSource["comment"] != nil {
+ desc := getLabelValue("comment", recordSource, hit.Highlight)
+ record["content"] = dealLongText(desc, Key, hit.MatchedQueries)
+ }
+ }
+ if recordSource["pr_id"] != nil {
+ record["pr_id"] = recordSource["pr_id"]
+ }
+ log.Info("index=" + recordSource["index"].(string))
+ record["index"] = recordSource["index"]
+ record["num_comments"] = recordSource["num_comments"]
+ record["is_closed"] = recordSource["is_closed"]
+ record["updated_unix"] = recordSource["updated_unix"]
+ setUpdateHtml(record, recordSource["updated_unix"].(string), language)
+ result = append(result, record)
+ } else {
+ log.Info("deal issue source error," + err.Error())
+ }
+ } else {
+ log.Info("deal issue source error," + err.Error())
+ }
+ }
+ }
+ returnObj := &SearchRes{
+ Total: total,
+ Result: result,
+ }
+
+ return returnObj
+}
diff --git a/templates/base/head_navbar.tmpl b/templates/base/head_navbar.tmpl
index 0ce3f2fcf..18cf3ce0e 100755
--- a/templates/base/head_navbar.tmpl
+++ b/templates/base/head_navbar.tmpl
@@ -95,9 +95,9 @@
{{if .IsSigned}}